build-system: Merge of changes for 0.07.01rc1
Based-on: 2d28043ac9a19d7d93fa91841f99e3234ac9f9d5
diff --git a/.default-version b/.default-version
new file mode 100644
index 0000000..db5f78c
--- /dev/null
+++ b/.default-version
@@ -0,0 +1 @@
+0.07.01rc1
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..11b2946
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,58 @@
+.git
+.DS_Store
+*.swp
+*.o
+*.lo
+.deps
+Makefile.in
+/Makefile
+/doc/Makefile
+/src/Makefile
+/src/connman-plugin/Makefile
+/src/ipc-dbus/Makefile
+/src/ncp-spinel/Makefile
+/src/ncp-dummy/Makefile
+/src/util/Makefile
+/src/wpanctl/Makefile
+/src/wpantund/Makefile
+/third_party/Makefile
+*.gcda
+*.gcno
+*~
+*~.c
+*.xcuserdatad
+*.orig
+xcuserdata
+.gdb_history
+*.a
+*.la
+.gdbinit
+/build
+/build-*
+/DerivedData
+/autom4te.cache
+/aclocal.m4
+/config.h.in
+/config.log
+/config.status
+/configure
+/libtool
+/src/config.h
+/m4
+/wpantund-*/
+/wpantund-*.tar.*
+src/stamp-h1
+src/config.h.in
+doxygen.cfg
+*.gz
+src/wpantund/wpantund
+src/wpanctl/wpanctl
+.dirstamp
+src/wpanctl/version.c
+wpantund.xcodeproj/project.xcworkspace/xcshareddata/wpan-tunnel-driver.xccheckout
+wpantund.xcodeproj/project.xcworkspace/xcshareddata/wpantund.xccheckout
+.cproject
+.project
+src/wpantund/.libs/wpantund
+Android.mk
+/etc/android
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..59d1081
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,45 @@
+language: cpp
+
+addons:
+ apt:
+ packages:
+ - bsdtar
+ - libdbus-1-dev
+ - autoconf-archive
+ - libglib2.0-dev
+ - libboost-dev
+ - libboost-signals-dev
+ - libreadline-dev
+ - libtool
+ - autoconf-archive
+
+sudo: required
+
+os:
+ - linux
+ - osx
+
+compiler:
+ - gcc
+ - clang
+
+before_install:
+ - .travis/before_install.sh
+
+script:
+ - .travis/script.sh
+
+after_success:
+ - ssh-agent .travis/after_success.sh
+
+env:
+ - BUILD_MAKEPATH=build BUILD_MAKEARGS="distcheck" TAR=bsdtar
+ - BUILD_MAKEPATH=build BUILD_MAKEARGS="distcheck" TAR=bsdtar BUILD_CONFIGFLAGS=--with-boost=internal
+
+matrix:
+ allow_failures:
+ - os: linux # This seems to be some sort of weird failure to
+ compiler: clang # find boost-signals. Needs further investigation.
+ exclude:
+ - os: osx
+ compiler: gcc
diff --git a/.travis/after_success.sh b/.travis/after_success.sh
new file mode 100755
index 0000000..8283316
--- /dev/null
+++ b/.travis/after_success.sh
@@ -0,0 +1,75 @@
+#!/bin/sh
+#
+# Copyright (c) 2016 Nest Labs, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+PREV_PATH="`pwd`"
+
+die() {
+ echo " *** ERROR: " $*
+ exit 1
+}
+
+set -x
+
+prep_ssh_key() {
+ openssl aes-256-cbc -K "${encrypted_8f78c13496e8_key}" -iv "${encrypted_8f78c13496e8_iv}" -in .travis/deploy.prv.enc -out .travis/deploy.prv -d &&
+ chmod 600 .travis/deploy.prv &&
+ ssh-add .travis/deploy.prv &&
+ git config --global user.name "Travis CI" &&
+ git config --global user.email "noreply@travis-ci.com"
+}
+
+AUTOCONF_BRANCH="autoconf/$TRAVIS_BRANCH"
+
+
+if [ $TRAVIS_REPO_SLUG = "openthread/wpantund" ] \
+&& [ $TRAVIS_BRANCH = "master" ] \
+&& [ $TRAVIS_OS_NAME = "linux" ] \
+&& [ $TRAVIS_PULL_REQUEST = "false" ] \
+&& [ $BUILD_MAKEPATH = "build" ] \
+&& [ $BUILD_MAKEARGS = "distcheck" ] \
+&& prep_ssh_key #
+then
+ git fetch --unshallow origin || git fetch origin || die
+
+ git fetch origin scripts:scripts ${AUTOCONF_BRANCH}:${AUTOCONF_BRANCH} ${TRAVIS_BRANCH}:${TRAVIS_BRANCH} || die
+
+ PREVREV="`git rev-parse ${AUTOCONF_BRANCH}`"
+
+ echo "Checking for update to '${AUTOCONF_BRANCH}'..."
+
+ git checkout scripts || die
+
+ NO_PUSH=1 ./update-autoconf-master ${TRAVIS_BRANCH} || die
+
+ CHANGED_LINES=`git diff "${PREVREV}".."${AUTOCONF_BRANCH}" | grep '^[-+]' | grep -v '^[-+]SOURCE_VERSION=' | wc -l`
+
+ if [ "$CHANGED_LINES" -gt "2" ]
+ then
+ echo "Branch '${AUTOCONF_BRANCH}' is OUT OF DATE."
+
+ git checkout "${TRAVIS_BRANCH}" || die
+
+ git push git@github.com:${TRAVIS_REPO_SLUG}.git ${AUTOCONF_BRANCH}:${AUTOCONF_BRANCH} || die
+ else
+ echo "Branch '${AUTOCONF_BRANCH}' is still up-to-date."
+ fi
+else
+ echo "Skipping update of '${AUTOCONF_BRANCH}'."
+fi
+
+exit 0
diff --git a/.travis/before_install.sh b/.travis/before_install.sh
new file mode 100755
index 0000000..0905be5
--- /dev/null
+++ b/.travis/before_install.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# Copyright (c) 2016 Nest Labs, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+die() {
+ echo " *** ERROR: " $*
+ exit 1
+}
+
+set -x
+
+[ $TRAVIS_OS_NAME != linux ] || {
+ wget https://gist.github.com/darconeous/d1d9bc39e0758e45a1d7/raw/ef9b01ac378a9b2e92031c846c4f6b5f94abab53/connman-include.tar.bz2 || die
+ sudo tar xvjf connman-include.tar.bz2 -C / || die
+}
+
+[ $TRAVIS_OS_NAME != osx ] || {
+ brew install d-bus
+ brew install autoconf-archive
+ brew install libtool
+ brew install gnu-sed
+}
diff --git a/.travis/deploy.prv.enc b/.travis/deploy.prv.enc
new file mode 100644
index 0000000..9c8bb57
--- /dev/null
+++ b/.travis/deploy.prv.enc
Binary files differ
diff --git a/.travis/deploy.pub b/.travis/deploy.pub
new file mode 100644
index 0000000..7c514a0
--- /dev/null
+++ b/.travis/deploy.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEz2HAMQ1MWCP3ukYnuqbyunjIegE5dgN+5bW/YjrOsnO0iuYvh3ZsKf0gBMYdDsGXYE+nRzn9tm4tKVNwjl67w= noreply@travis-ci.org
diff --git a/.travis/script.sh b/.travis/script.sh
new file mode 100755
index 0000000..cf03a26
--- /dev/null
+++ b/.travis/script.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+#
+# Copyright (c) 2016 Nest Labs, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+PREV_PATH="`pwd`"
+
+die() {
+ echo " *** ERROR: " $*
+ exit 1
+}
+
+set -x
+
+[ $TRAVIS_OS_NAME != linux ] || BUILD_CONFIGFLAGS="${BUILD_CONFIGFLAGS} --with-connman"
+
+[ -e configure ] || ./bootstrap.sh || die
+
+mkdir -p "${BUILD_MAKEPATH}" || die
+
+cd "${BUILD_MAKEPATH}" || die
+
+../configure ${BUILD_CONFIGFLAGS} || die
+
+make ${BUILD_MAKEARGS} || die
+
+cd ..
diff --git a/.uncrustify.cfg b/.uncrustify.cfg
new file mode 100644
index 0000000..e5f1502
--- /dev/null
+++ b/.uncrustify.cfg
@@ -0,0 +1,1578 @@
+# Uncrustify 0.60
+
+#
+# General options
+#
+
+# The type of line endings
+newlines = auto # auto/lf/crlf/cr
+
+# The original size of tabs in the input
+input_tab_size = 4 # number
+
+# The size of tabs in the output (only used if align_with_tabs=true)
+output_tab_size = 4 # number
+
+# The ASCII value of the string escape char, usually 92 (\) or 94 (^). (Pawn)
+string_escape_char = 92 # number
+
+# Alternate string escape char for Pawn. Only works right before the quote char.
+string_escape_char2 = 0 # number
+
+# Allow interpreting '>=' and '>>=' as part of a template in 'void f(list<list<B>>=val);'.
+# If true (default), 'assert(x<0 && y>=3)' will be broken.
+# Improvements to template detection may make this option obsolete.
+tok_split_gte = false # false/true
+
+# Control what to do with the UTF-8 BOM (recommend 'remove')
+utf8_bom = ignore # ignore/add/remove/force
+
+# If the file contains bytes with values between 128 and 255, but is not UTF-8, then output as UTF-8
+utf8_byte = false # false/true
+
+# Force the output encoding to UTF-8
+utf8_force = false # false/true
+
+#
+# Indenting
+#
+
+# The number of columns to indent per level.
+# Usually 2, 3, 4, or 8.
+indent_columns = 4 # number
+
+# The continuation indent. If non-zero, this overrides the indent of '(' and '=' continuation indents.
+# For FreeBSD, this is set to 4. Negative value is absolute and not increased for each ( level
+indent_continue = 0 # number
+
+# How to use tabs when indenting code
+# 0=spaces only
+# 1=indent with tabs to brace level, align with spaces
+# 2=indent and align with tabs, using spaces when not on a tabstop
+indent_with_tabs = 1 # number
+
+# Comments that are not a brace level are indented with tabs on a tabstop.
+# Requires indent_with_tabs=2. If false, will use spaces.
+indent_cmt_with_tabs = false # false/true
+
+# Whether to indent strings broken by '\' so that they line up
+indent_align_string = false # false/true
+
+# The number of spaces to indent multi-line XML strings.
+# Requires indent_align_string=True
+indent_xml_string = 0 # number
+
+# Spaces to indent '{' from level
+indent_brace = 0 # number
+
+# Whether braces are indented to the body level
+indent_braces = false # false/true
+
+# Disabled indenting function braces if indent_braces is true
+indent_braces_no_func = false # false/true
+
+# Disabled indenting class braces if indent_braces is true
+indent_braces_no_class = false # false/true
+
+# Disabled indenting struct braces if indent_braces is true
+indent_braces_no_struct = false # false/true
+
+# Indent based on the size of the brace parent, i.e. 'if' => 3 spaces, 'for' => 4 spaces, etc.
+indent_brace_parent = false # false/true
+
+# Whether the 'namespace' body is indented
+indent_namespace = false # false/true
+
+# The number of spaces to indent a namespace block
+indent_namespace_level = 0 # number
+
+# If the body of the namespace is longer than this number, it won't be indented.
+# Requires indent_namespace=true. Default=0 (no limit)
+indent_namespace_limit = 0 # number
+
+# Whether the 'extern "C"' body is indented
+indent_extern = false # false/true
+
+# Whether the 'class' body is indented
+indent_class = true # false/true
+
+# Whether to indent the stuff after a leading class colon
+indent_class_colon = false # false/true
+
+# Virtual indent from the ':' for member initializers. Default is 2
+indent_ctor_init_leading = 2 # number
+
+# Additional indenting for constructor initializer list
+indent_ctor_init = 0 # number
+
+# False=treat 'else\nif' as 'else if' for indenting purposes
+# True=indent the 'if' one level
+indent_else_if = false # false/true
+
+# Amount to indent variable declarations after a open brace. neg=relative, pos=absolute
+indent_var_def_blk = 0 # number
+
+# Indent continued variable declarations instead of aligning.
+indent_var_def_cont = false # false/true
+
+# True: force indentation of function definition to start in column 1
+# False: use the default behavior
+indent_func_def_force_col1 = false # false/true
+
+# True: indent continued function call parameters one indent level
+# False: align parameters under the open paren
+indent_func_call_param = false # false/true
+
+# Same as indent_func_call_param, but for function defs
+indent_func_def_param = false # false/true
+
+# Same as indent_func_call_param, but for function protos
+indent_func_proto_param = false # false/true
+
+# Same as indent_func_call_param, but for class declarations
+indent_func_class_param = false # false/true
+
+# Same as indent_func_call_param, but for class variable constructors
+indent_func_ctor_var_param = false # false/true
+
+# Same as indent_func_call_param, but for templates
+indent_template_param = false # false/true
+
+# Double the indent for indent_func_xxx_param options
+indent_func_param_double = false # false/true
+
+# Indentation column for standalone 'const' function decl/proto qualifier
+indent_func_const = 0 # number
+
+# Indentation column for standalone 'throw' function decl/proto qualifier
+indent_func_throw = 0 # number
+
+# The number of spaces to indent a continued '->' or '.'
+# Usually set to 0, 1, or indent_columns.
+indent_member = 0 # number
+
+# Spaces to indent single line ('//') comments on lines before code
+indent_sing_line_comments = 0 # number
+
+# If set, will indent trailing single line ('//') comments relative
+# to the code instead of trying to keep the same absolute column
+indent_relative_single_line_comments = false # false/true
+
+# Spaces to indent 'case' from 'switch'
+# Usually 0 or indent_columns.
+indent_switch_case = 0 # number
+
+# Spaces to shift the 'case' line, without affecting any other lines
+# Usually 0.
+indent_case_shift = 0 # number
+
+# Spaces to indent '{' from 'case'.
+# By default, the brace will appear under the 'c' in case.
+# Usually set to 0 or indent_columns.
+indent_case_brace = 0 # number
+
+# Whether to indent comments found in first column
+indent_col1_comment = false # false/true
+
+# How to indent goto labels
+# >0 : absolute column where 1 is the leftmost column
+# <=0 : subtract from brace indent
+indent_label = 1 # number
+
+# Same as indent_label, but for access specifiers that are followed by a colon
+indent_access_spec = 1 # number
+
+# Indent the code after an access specifier by one level.
+# If set, this option forces 'indent_access_spec=0'
+indent_access_spec_body = false # false/true
+
+# If an open paren is followed by a newline, indent the next line so that it lines up after the open paren (not recommended)
+indent_paren_nl = false # false/true
+
+# Controls the indent of a close paren after a newline.
+# 0: Indent to body level
+# 1: Align under the open paren
+# 2: Indent to the brace level
+indent_paren_close = 0 # number
+
+# Controls the indent of a comma when inside a paren.If TRUE, aligns under the open paren
+indent_comma_paren = false # false/true
+
+# Controls the indent of a BOOL operator when inside a paren.If TRUE, aligns under the open paren
+indent_bool_paren = false # false/true
+
+# If 'indent_bool_paren' is true, controls the indent of the first expression. If TRUE, aligns the first expression to the following ones
+indent_first_bool_expr = false # false/true
+
+# If an open square is followed by a newline, indent the next line so that it lines up after the open square (not recommended)
+indent_square_nl = false # false/true
+
+# Don't change the relative indent of ESQL/C 'EXEC SQL' bodies
+indent_preserve_sql = false # false/true
+
+# Align continued statements at the '='. Default=True
+# If FALSE or the '=' is followed by a newline, the next line is indent one tab.
+indent_align_assign = true # false/true
+
+# Indent OC blocks at brace level instead of usual rules.
+indent_oc_block = false # false/true
+
+# Indent OC blocks in a message relative to the parameter name.
+# 0=use indent_oc_block rules, 1+=spaces to indent
+indent_oc_block_msg = 0 # number
+
+# Minimum indent for subsequent parameters
+indent_oc_msg_colon = 0 # number
+
+#
+# Spacing options
+#
+
+# Add or remove space around arithmetic operator '+', '-', '/', '*', etc
+sp_arith = ignore # ignore/add/remove/force
+
+# Add or remove space around assignment operator '=', '+=', etc
+sp_assign = ignore # ignore/add/remove/force
+
+# Add or remove space around '=' in C++11 lambda capture specifications. Overrides sp_assign
+sp_cpp_lambda_assign = ignore # ignore/add/remove/force
+
+# Add or remove space after the capture specification in C++11 lambda.
+sp_cpp_lambda_paren = ignore # ignore/add/remove/force
+
+# Add or remove space around assignment operator '=' in a prototype
+sp_assign_default = ignore # ignore/add/remove/force
+
+# Add or remove space before assignment operator '=', '+=', etc. Overrides sp_assign.
+sp_before_assign = ignore # ignore/add/remove/force
+
+# Add or remove space after assignment operator '=', '+=', etc. Overrides sp_assign.
+sp_after_assign = ignore # ignore/add/remove/force
+
+# Add or remove space around assignment '=' in enum
+sp_enum_assign = ignore # ignore/add/remove/force
+
+# Add or remove space before assignment '=' in enum. Overrides sp_enum_assign.
+sp_enum_before_assign = ignore # ignore/add/remove/force
+
+# Add or remove space after assignment '=' in enum. Overrides sp_enum_assign.
+sp_enum_after_assign = ignore # ignore/add/remove/force
+
+# Add or remove space around preprocessor '##' concatenation operator. Default=Add
+sp_pp_concat = add # ignore/add/remove/force
+
+# Add or remove space after preprocessor '#' stringify operator. Also affects the '#@' charizing operator.
+sp_pp_stringify = ignore # ignore/add/remove/force
+
+# Add or remove space before preprocessor '#' stringify operator as in '#define x(y) L#y'.
+sp_before_pp_stringify = ignore # ignore/add/remove/force
+
+# Add or remove space around boolean operators '&&' and '||'
+sp_bool = ignore # ignore/add/remove/force
+
+# Add or remove space around compare operator '<', '>', '==', etc
+sp_compare = ignore # ignore/add/remove/force
+
+# Add or remove space inside '(' and ')'
+sp_inside_paren = ignore # ignore/add/remove/force
+
+# Add or remove space between nested parens
+sp_paren_paren = ignore # ignore/add/remove/force
+
+# Whether to balance spaces inside nested parens
+sp_balance_nested_parens = false # false/true
+
+# Add or remove space between ')' and '{'
+sp_paren_brace = ignore # ignore/add/remove/force
+
+# Add or remove space before pointer star '*'
+sp_before_ptr_star = ignore # ignore/add/remove/force
+
+# Add or remove space before pointer star '*' that isn't followed by a variable name
+# If set to 'ignore', sp_before_ptr_star is used instead.
+sp_before_unnamed_ptr_star = ignore # ignore/add/remove/force
+
+# Add or remove space between pointer stars '*'
+sp_between_ptr_star = ignore # ignore/add/remove/force
+
+# Add or remove space after pointer star '*', if followed by a word.
+sp_after_ptr_star = ignore # ignore/add/remove/force
+
+# Add or remove space after a pointer star '*', if followed by a func proto/def.
+sp_after_ptr_star_func = ignore # ignore/add/remove/force
+
+# Add or remove space after a pointer star '*', if followed by an open paren (function types).
+sp_ptr_star_paren = ignore # ignore/add/remove/force
+
+# Add or remove space before a pointer star '*', if followed by a func proto/def.
+sp_before_ptr_star_func = ignore # ignore/add/remove/force
+
+# Add or remove space before a reference sign '&'
+sp_before_byref = ignore # ignore/add/remove/force
+
+# Add or remove space before a reference sign '&' that isn't followed by a variable name
+# If set to 'ignore', sp_before_byref is used instead.
+sp_before_unnamed_byref = ignore # ignore/add/remove/force
+
+# Add or remove space after reference sign '&', if followed by a word.
+sp_after_byref = ignore # ignore/add/remove/force
+
+# Add or remove space after a reference sign '&', if followed by a func proto/def.
+sp_after_byref_func = ignore # ignore/add/remove/force
+
+# Add or remove space before a reference sign '&', if followed by a func proto/def.
+sp_before_byref_func = ignore # ignore/add/remove/force
+
+# Add or remove space between type and word. Default=Force
+sp_after_type = force # ignore/add/remove/force
+
+# Add or remove space before the paren in the D constructs 'template Foo(' and 'class Foo('.
+sp_before_template_paren = ignore # ignore/add/remove/force
+
+# Add or remove space in 'template <' vs 'template<'.
+# If set to ignore, sp_before_angle is used.
+sp_template_angle = ignore # ignore/add/remove/force
+
+# Add or remove space before '<>'
+sp_before_angle = ignore # ignore/add/remove/force
+
+# Add or remove space inside '<' and '>'
+sp_inside_angle = ignore # ignore/add/remove/force
+
+# Add or remove space after '<>'
+sp_after_angle = ignore # ignore/add/remove/force
+
+# Add or remove space between '<>' and '(' as found in 'new List<byte>();'
+sp_angle_paren = ignore # ignore/add/remove/force
+
+# Add or remove space between '<>' and a word as in 'List<byte> m;'
+sp_angle_word = ignore # ignore/add/remove/force
+
+# Add or remove space between '>' and '>' in '>>' (template stuff C++/C# only). Default=Add
+sp_angle_shift = add # ignore/add/remove/force
+
+# Permit removal of the space between '>>' in 'foo<bar<int> >' (C++11 only). Default=False
+# sp_angle_shift cannot remove the space without this option.
+sp_permit_cpp11_shift = false # false/true
+
+# Add or remove space before '(' of 'if', 'for', 'switch', and 'while'
+sp_before_sparen = ignore # ignore/add/remove/force
+
+# Add or remove space inside if-condition '(' and ')'
+sp_inside_sparen = ignore # ignore/add/remove/force
+
+# Add or remove space before if-condition ')'. Overrides sp_inside_sparen.
+sp_inside_sparen_close = ignore # ignore/add/remove/force
+
+# Add or remove space before if-condition '('. Overrides sp_inside_sparen.
+sp_inside_sparen_open = ignore # ignore/add/remove/force
+
+# Add or remove space after ')' of 'if', 'for', 'switch', and 'while'
+sp_after_sparen = ignore # ignore/add/remove/force
+
+# Add or remove space between ')' and '{' of 'if', 'for', 'switch', and 'while'
+sp_sparen_brace = ignore # ignore/add/remove/force
+
+# Add or remove space between 'invariant' and '(' in the D language.
+sp_invariant_paren = ignore # ignore/add/remove/force
+
+# Add or remove space after the ')' in 'invariant (C) c' in the D language.
+sp_after_invariant_paren = ignore # ignore/add/remove/force
+
+# Add or remove space before empty statement ';' on 'if', 'for' and 'while'
+sp_special_semi = ignore # ignore/add/remove/force
+
+# Add or remove space before ';'. Default=Remove
+sp_before_semi = remove # ignore/add/remove/force
+
+# Add or remove space before ';' in non-empty 'for' statements
+sp_before_semi_for = ignore # ignore/add/remove/force
+
+# Add or remove space before a semicolon of an empty part of a for statement.
+sp_before_semi_for_empty = ignore # ignore/add/remove/force
+
+# Add or remove space after ';', except when followed by a comment. Default=Add
+sp_after_semi = add # ignore/add/remove/force
+
+# Add or remove space after ';' in non-empty 'for' statements. Default=Force
+sp_after_semi_for = force # ignore/add/remove/force
+
+# Add or remove space after the final semicolon of an empty part of a for statement: for ( ; ; <here> ).
+sp_after_semi_for_empty = ignore # ignore/add/remove/force
+
+# Add or remove space before '[' (except '[]')
+sp_before_square = ignore # ignore/add/remove/force
+
+# Add or remove space before '[]'
+sp_before_squares = ignore # ignore/add/remove/force
+
+# Add or remove space inside a non-empty '[' and ']'
+sp_inside_square = ignore # ignore/add/remove/force
+
+# Add or remove space after ','
+sp_after_comma = ignore # ignore/add/remove/force
+
+# Add or remove space before ','
+sp_before_comma = remove # ignore/add/remove/force
+
+# Add or remove space between an open paren and comma: '(,' vs '( ,'
+sp_paren_comma = force # ignore/add/remove/force
+
+# Add or remove space before the variadic '...' when preceded by a non-punctuator
+sp_before_ellipsis = ignore # ignore/add/remove/force
+
+# Add or remove space after class ':'
+sp_after_class_colon = ignore # ignore/add/remove/force
+
+# Add or remove space before class ':'
+sp_before_class_colon = ignore # ignore/add/remove/force
+
+# Add or remove space before case ':'. Default=Remove
+sp_before_case_colon = remove # ignore/add/remove/force
+
+# Add or remove space between 'operator' and operator sign
+sp_after_operator = ignore # ignore/add/remove/force
+
+# Add or remove space between the operator symbol and the open paren, as in 'operator ++('
+sp_after_operator_sym = ignore # ignore/add/remove/force
+
+# Add or remove space after C/D cast, i.e. 'cast(int)a' vs 'cast(int) a' or '(int)a' vs '(int) a'
+sp_after_cast = ignore # ignore/add/remove/force
+
+# Add or remove spaces inside cast parens
+sp_inside_paren_cast = ignore # ignore/add/remove/force
+
+# Add or remove space between the type and open paren in a C++ cast, i.e. 'int(exp)' vs 'int (exp)'
+sp_cpp_cast_paren = ignore # ignore/add/remove/force
+
+# Add or remove space between 'sizeof' and '('
+sp_sizeof_paren = ignore # ignore/add/remove/force
+
+# Add or remove space after the tag keyword (Pawn)
+sp_after_tag = ignore # ignore/add/remove/force
+
+# Add or remove space inside enum '{' and '}'
+sp_inside_braces_enum = ignore # ignore/add/remove/force
+
+# Add or remove space inside struct/union '{' and '}'
+sp_inside_braces_struct = ignore # ignore/add/remove/force
+
+# Add or remove space inside '{' and '}'
+sp_inside_braces = ignore # ignore/add/remove/force
+
+# Add or remove space inside '{}'
+sp_inside_braces_empty = ignore # ignore/add/remove/force
+
+# Add or remove space between return type and function name
+# A minimum of 1 is forced except for pointer return types.
+sp_type_func = ignore # ignore/add/remove/force
+
+# Add or remove space between function name and '(' on function declaration
+sp_func_proto_paren = ignore # ignore/add/remove/force
+
+# Add or remove space between function name and '(' on function definition
+sp_func_def_paren = ignore # ignore/add/remove/force
+
+# Add or remove space inside empty function '()'
+sp_inside_fparens = ignore # ignore/add/remove/force
+
+# Add or remove space inside function '(' and ')'
+sp_inside_fparen = ignore # ignore/add/remove/force
+
+# Add or remove space inside the first parens in the function type: 'void (*x)(...)'
+sp_inside_tparen = ignore # ignore/add/remove/force
+
+# Add or remove between the parens in the function type: 'void (*x)(...)'
+sp_after_tparen_close = ignore # ignore/add/remove/force
+
+# Add or remove space between ']' and '(' when part of a function call.
+sp_square_fparen = ignore # ignore/add/remove/force
+
+# Add or remove space between ')' and '{' of function
+sp_fparen_brace = ignore # ignore/add/remove/force
+
+# Add or remove space between function name and '(' on function calls
+sp_func_call_paren = ignore # ignore/add/remove/force
+
+# Add or remove space between function name and '()' on function calls without parameters.
+# If set to 'ignore' (the default), sp_func_call_paren is used.
+sp_func_call_paren_empty = ignore # ignore/add/remove/force
+
+# Add or remove space between the user function name and '(' on function calls
+# You need to set a keyword to be a user function, like this: 'set func_call_user _' in the config file.
+sp_func_call_user_paren = ignore # ignore/add/remove/force
+
+# Add or remove space between a constructor/destructor and the open paren
+sp_func_class_paren = ignore # ignore/add/remove/force
+
+# Add or remove space between 'return' and '('
+sp_return_paren = ignore # ignore/add/remove/force
+
+# Add or remove space between '__attribute__' and '('
+sp_attribute_paren = ignore # ignore/add/remove/force
+
+# Add or remove space between 'defined' and '(' in '#if defined (FOO)'
+sp_defined_paren = ignore # ignore/add/remove/force
+
+# Add or remove space between 'throw' and '(' in 'throw (something)'
+sp_throw_paren = ignore # ignore/add/remove/force
+
+# Add or remove space between 'throw' and anything other than '(' as in '@throw [...];'
+sp_after_throw = ignore # ignore/add/remove/force
+
+# Add or remove space between 'catch' and '(' in 'catch (something) { }'
+# If set to ignore, sp_before_sparen is used.
+sp_catch_paren = ignore # ignore/add/remove/force
+
+# Add or remove space between 'version' and '(' in 'version (something) { }' (D language)
+# If set to ignore, sp_before_sparen is used.
+sp_version_paren = ignore # ignore/add/remove/force
+
+# Add or remove space between 'scope' and '(' in 'scope (something) { }' (D language)
+# If set to ignore, sp_before_sparen is used.
+sp_scope_paren = ignore # ignore/add/remove/force
+
+# Add or remove space between macro and value
+sp_macro = ignore # ignore/add/remove/force
+
+# Add or remove space between macro function ')' and value
+sp_macro_func = ignore # ignore/add/remove/force
+
+# Add or remove space between 'else' and '{' if on the same line
+sp_else_brace = ignore # ignore/add/remove/force
+
+# Add or remove space between '}' and 'else' if on the same line
+sp_brace_else = ignore # ignore/add/remove/force
+
+# Add or remove space between '}' and the name of a typedef on the same line
+sp_brace_typedef = ignore # ignore/add/remove/force
+
+# Add or remove space between 'catch' and '{' if on the same line
+sp_catch_brace = ignore # ignore/add/remove/force
+
+# Add or remove space between '}' and 'catch' if on the same line
+sp_brace_catch = ignore # ignore/add/remove/force
+
+# Add or remove space between 'finally' and '{' if on the same line
+sp_finally_brace = ignore # ignore/add/remove/force
+
+# Add or remove space between '}' and 'finally' if on the same line
+sp_brace_finally = ignore # ignore/add/remove/force
+
+# Add or remove space between 'try' and '{' if on the same line
+sp_try_brace = ignore # ignore/add/remove/force
+
+# Add or remove space between get/set and '{' if on the same line
+sp_getset_brace = ignore # ignore/add/remove/force
+
+# Add or remove space before the '::' operator
+sp_before_dc = ignore # ignore/add/remove/force
+
+# Add or remove space after the '::' operator
+sp_after_dc = ignore # ignore/add/remove/force
+
+# Add or remove around the D named array initializer ':' operator
+sp_d_array_colon = ignore # ignore/add/remove/force
+
+# Add or remove space after the '!' (not) operator. Default=Remove
+sp_not = remove # ignore/add/remove/force
+
+# Add or remove space after the '~' (invert) operator. Default=Remove
+sp_inv = remove # ignore/add/remove/force
+
+# Add or remove space after the '&' (address-of) operator. Default=Remove
+# This does not affect the spacing after a '&' that is part of a type.
+sp_addr = remove # ignore/add/remove/force
+
+# Add or remove space around the '.' or '->' operators. Default=Remove
+sp_member = remove # ignore/add/remove/force
+
+# Add or remove space after the '*' (dereference) operator. Default=Remove
+# This does not affect the spacing after a '*' that is part of a type.
+sp_deref = remove # ignore/add/remove/force
+
+# Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7'. Default=Remove
+sp_sign = remove # ignore/add/remove/force
+
+# Add or remove space before or after '++' and '--', as in '(--x)' or 'y++;'. Default=Remove
+sp_incdec = remove # ignore/add/remove/force
+
+# Add or remove space before a backslash-newline at the end of a line. Default=Add
+sp_before_nl_cont = add # ignore/add/remove/force
+
+# Add or remove space after the scope '+' or '-', as in '-(void) foo;' or '+(int) bar;'
+sp_after_oc_scope = ignore # ignore/add/remove/force
+
+# Add or remove space after the colon in message specs
+# '-(int) f:(int) x;' vs '-(int) f: (int) x;'
+sp_after_oc_colon = ignore # ignore/add/remove/force
+
+# Add or remove space before the colon in message specs
+# '-(int) f: (int) x;' vs '-(int) f : (int) x;'
+sp_before_oc_colon = ignore # ignore/add/remove/force
+
+# Add or remove space after the colon in immutable dictionary expression
+# 'NSDictionary *test = @{@"foo" :@"bar"};'
+sp_after_oc_dict_colon = ignore # ignore/add/remove/force
+
+# Add or remove space before the colon in immutable dictionary expression
+# 'NSDictionary *test = @{@"foo" :@"bar"};'
+sp_before_oc_dict_colon = ignore # ignore/add/remove/force
+
+# Add or remove space after the colon in message specs
+# '[object setValue:1];' vs '[object setValue: 1];'
+sp_after_send_oc_colon = ignore # ignore/add/remove/force
+
+# Add or remove space before the colon in message specs
+# '[object setValue:1];' vs '[object setValue :1];'
+sp_before_send_oc_colon = ignore # ignore/add/remove/force
+
+# Add or remove space after the (type) in message specs
+# '-(int)f: (int) x;' vs '-(int)f: (int)x;'
+sp_after_oc_type = ignore # ignore/add/remove/force
+
+# Add or remove space after the first (type) in message specs
+# '-(int) f:(int)x;' vs '-(int)f:(int)x;'
+sp_after_oc_return_type = ignore # ignore/add/remove/force
+
+# Add or remove space between '@selector' and '('
+# '@selector(msgName)' vs '@selector (msgName)'
+# Also applies to @protocol() constructs
+sp_after_oc_at_sel = ignore # ignore/add/remove/force
+
+# Add or remove space between '@selector(x)' and the following word
+# '@selector(foo) a:' vs '@selector(foo)a:'
+sp_after_oc_at_sel_parens = ignore # ignore/add/remove/force
+
+# Add or remove space inside '@selector' parens
+# '@selector(foo)' vs '@selector( foo )'
+# Also applies to @protocol() constructs
+sp_inside_oc_at_sel_parens = ignore # ignore/add/remove/force
+
+# Add or remove space before a block pointer caret
+# '^int (int arg){...}' vs. ' ^int (int arg){...}'
+sp_before_oc_block_caret = ignore # ignore/add/remove/force
+
+# Add or remove space after a block pointer caret
+# '^int (int arg){...}' vs. '^ int (int arg){...}'
+sp_after_oc_block_caret = ignore # ignore/add/remove/force
+
+# Add or remove space between the receiver and selector in a message.
+# '[receiver selector ...]'
+sp_after_oc_msg_receiver = ignore # ignore/add/remove/force
+
+# Add or remove space after @property.
+sp_after_oc_property = ignore # ignore/add/remove/force
+
+# Add or remove space around the ':' in 'b ? t : f'
+sp_cond_colon = ignore # ignore/add/remove/force
+
+# Add or remove space around the '?' in 'b ? t : f'
+sp_cond_question = ignore # ignore/add/remove/force
+
+# Fix the spacing between 'case' and the label. Only 'ignore' and 'force' make sense here.
+sp_case_label = ignore # ignore/add/remove/force
+
+# Control the space around the D '..' operator.
+sp_range = ignore # ignore/add/remove/force
+
+# Control the spacing after ':' in 'for (TYPE VAR : EXPR)' (Java)
+sp_after_for_colon = ignore # ignore/add/remove/force
+
+# Control the spacing before ':' in 'for (TYPE VAR : EXPR)' (Java)
+sp_before_for_colon = ignore # ignore/add/remove/force
+
+# Control the spacing in 'extern (C)' (D)
+sp_extern_paren = ignore # ignore/add/remove/force
+
+# Control the space after the opening of a C++ comment '// A' vs '//A'
+sp_cmt_cpp_start = ignore # ignore/add/remove/force
+
+# Controls the spaces between #else or #endif and a trailing comment
+sp_endif_cmt = ignore # ignore/add/remove/force
+
+# Controls the spaces after 'new', 'delete', and 'delete[]'
+sp_after_new = ignore # ignore/add/remove/force
+
+# Controls the spaces before a trailing or embedded comment
+sp_before_tr_emb_cmt = ignore # ignore/add/remove/force
+
+# Number of spaces before a trailing or embedded comment
+sp_num_before_tr_emb_cmt = 0 # number
+
+# Control space between a Java annotation and the open paren.
+sp_annotation_paren = ignore # ignore/add/remove/force
+
+#
+# Code alignment (not left column spaces/tabs)
+#
+
+# Whether to keep non-indenting tabs
+align_keep_tabs = false # false/true
+
+# Whether to use tabs for aligning
+align_with_tabs = false # false/true
+
+# Whether to bump out to the next tab when aligning
+align_on_tabstop = false # false/true
+
+# Whether to left-align numbers
+align_number_left = false # false/true
+
+# Align variable definitions in prototypes and functions
+align_func_params = false # false/true
+
+# Align parameters in single-line functions that have the same name.
+# The function names must already be aligned with each other.
+align_same_func_call_params = false # false/true
+
+# The span for aligning variable definitions (0=don't align)
+align_var_def_span = 0 # number
+
+# How to align the star in variable definitions.
+# 0=Part of the type 'void * foo;'
+# 1=Part of the variable 'void *foo;'
+# 2=Dangling 'void *foo;'
+align_var_def_star_style = 0 # number
+
+# How to align the '&' in variable definitions.
+# 0=Part of the type
+# 1=Part of the variable
+# 2=Dangling
+align_var_def_amp_style = 0 # number
+
+# The threshold for aligning variable definitions (0=no limit)
+align_var_def_thresh = 0 # number
+
+# The gap for aligning variable definitions
+align_var_def_gap = 0 # number
+
+# Whether to align the colon in struct bit fields
+align_var_def_colon = false # false/true
+
+# Whether to align any attribute after the variable name
+align_var_def_attribute = false # false/true
+
+# Whether to align inline struct/enum/union variable definitions
+align_var_def_inline = false # false/true
+
+# The span for aligning on '=' in assignments (0=don't align)
+align_assign_span = 0 # number
+
+# The threshold for aligning on '=' in assignments (0=no limit)
+align_assign_thresh = 0 # number
+
+# The span for aligning on '=' in enums (0=don't align)
+align_enum_equ_span = 0 # number
+
+# The threshold for aligning on '=' in enums (0=no limit)
+align_enum_equ_thresh = 0 # number
+
+# The span for aligning struct/union (0=don't align)
+align_var_struct_span = 0 # number
+
+# The threshold for aligning struct/union member definitions (0=no limit)
+align_var_struct_thresh = 0 # number
+
+# The gap for aligning struct/union member definitions
+align_var_struct_gap = 0 # number
+
+# The span for aligning struct initializer values (0=don't align)
+align_struct_init_span = 0 # number
+
+# The minimum space between the type and the synonym of a typedef
+align_typedef_gap = 0 # number
+
+# The span for aligning single-line typedefs (0=don't align)
+align_typedef_span = 0 # number
+
+# How to align typedef'd functions with other typedefs
+# 0: Don't mix them at all
+# 1: align the open paren with the types
+# 2: align the function type name with the other type names
+align_typedef_func = 0 # number
+
+# Controls the positioning of the '*' in typedefs. Just try it.
+# 0: Align on typedef type, ignore '*'
+# 1: The '*' is part of type name: typedef int *pint;
+# 2: The '*' is part of the type, but dangling: typedef int *pint;
+align_typedef_star_style = 0 # number
+
+# Controls the positioning of the '&' in typedefs. Just try it.
+# 0: Align on typedef type, ignore '&'
+# 1: The '&' is part of type name: typedef int &pint;
+# 2: The '&' is part of the type, but dangling: typedef int &pint;
+align_typedef_amp_style = 0 # number
+
+# The span for aligning comments that end lines (0=don't align)
+align_right_cmt_span = 0 # number
+
+# If aligning comments, mix with comments after '}' and #endif with less than 3 spaces before the comment
+align_right_cmt_mix = false # false/true
+
+# If a trailing comment is more than this number of columns away from the text it follows,
+# it will qualify for being aligned. This has to be > 0 to do anything.
+align_right_cmt_gap = 0 # number
+
+# Align trailing comment at or beyond column N; 'pulls in' comments as a bonus side effect (0=ignore)
+align_right_cmt_at_col = 0 # number
+
+# The span for aligning function prototypes (0=don't align)
+align_func_proto_span = 0 # number
+
+# Minimum gap between the return type and the function name.
+align_func_proto_gap = 0 # number
+
+# Align function protos on the 'operator' keyword instead of what follows
+align_on_operator = false # false/true
+
+# Whether to mix aligning prototype and variable declarations.
+# If true, align_var_def_XXX options are used instead of align_func_proto_XXX options.
+align_mix_var_proto = false # false/true
+
+# Align single-line functions with function prototypes, uses align_func_proto_span
+align_single_line_func = false # false/true
+
+# Aligning the open brace of single-line functions.
+# Requires align_single_line_func=true, uses align_func_proto_span
+align_single_line_brace = false # false/true
+
+# Gap for align_single_line_brace.
+align_single_line_brace_gap = 0 # number
+
+# The span for aligning ObjC msg spec (0=don't align)
+align_oc_msg_spec_span = 0 # number
+
+# Whether to align macros wrapped with a backslash and a newline.
+# This will not work right if the macro contains a multi-line comment.
+align_nl_cont = false # false/true
+
+# # Align macro functions and variables together
+align_pp_define_together = false # false/true
+
+# The minimum space between label and value of a preprocessor define
+align_pp_define_gap = 0 # number
+
+# The span for aligning on '#define' bodies (0=don't align)
+align_pp_define_span = 0 # number
+
+# Align lines that start with '<<' with previous '<<'. Default=true
+align_left_shift = true # false/true
+
+# Span for aligning parameters in an Obj-C message call on the ':' (0=don't align)
+align_oc_msg_colon_span = 0 # number
+
+# If true, always align with the first parameter, even if it is too short.
+align_oc_msg_colon_first = false # false/true
+
+# Aligning parameters in an Obj-C '+' or '-' declaration on the ':'
+align_oc_decl_colon = false # false/true
+
+#
+# Newline adding and removing options
+#
+
+# Whether to collapse empty blocks between '{' and '}'
+nl_collapse_empty_body = false # false/true
+
+# Don't split one-line braced assignments - 'foo_t f = { 1, 2 };'
+nl_assign_leave_one_liners = false # false/true
+
+# Don't split one-line braced statements inside a class xx { } body
+nl_class_leave_one_liners = false # false/true
+
+# Don't split one-line enums: 'enum foo { BAR = 15 };'
+nl_enum_leave_one_liners = false # false/true
+
+# Don't split one-line get or set functions
+nl_getset_leave_one_liners = false # false/true
+
+# Don't split one-line function definitions - 'int foo() { return 0; }'
+nl_func_leave_one_liners = false # false/true
+
+# Don't split one-line if/else statements - 'if(a) b++;'
+nl_if_leave_one_liners = false # false/true
+
+# Don't split one-line OC messages
+nl_oc_msg_leave_one_liner = false # false/true
+
+# Add or remove newlines at the start of the file
+nl_start_of_file = ignore # ignore/add/remove/force
+
+# The number of newlines at the start of the file (only used if nl_start_of_file is 'add' or 'force'
+nl_start_of_file_min = 0 # number
+
+# Add or remove newline at the end of the file
+nl_end_of_file = ignore # ignore/add/remove/force
+
+# The number of newlines at the end of the file (only used if nl_end_of_file is 'add' or 'force')
+nl_end_of_file_min = 0 # number
+
+# Add or remove newline between '=' and '{'
+nl_assign_brace = ignore # ignore/add/remove/force
+
+# Add or remove newline between '=' and '[' (D only)
+nl_assign_square = ignore # ignore/add/remove/force
+
+# Add or remove newline after '= [' (D only). Will also affect the newline before the ']'
+nl_after_square_assign = ignore # ignore/add/remove/force
+
+# The number of blank lines after a block of variable definitions at the top of a function body
+# 0 = No change (default)
+nl_func_var_def_blk = 0 # number
+
+# The number of newlines before a block of typedefs
+# 0 = No change (default)
+nl_typedef_blk_start = 0 # number
+
+# The number of newlines after a block of typedefs
+# 0 = No change (default)
+nl_typedef_blk_end = 0 # number
+
+# The maximum consecutive newlines within a block of typedefs
+# 0 = No change (default)
+nl_typedef_blk_in = 0 # number
+
+# The number of newlines before a block of variable definitions not at the top of a function body
+# 0 = No change (default)
+nl_var_def_blk_start = 0 # number
+
+# The number of newlines after a block of variable definitions not at the top of a function body
+# 0 = No change (default)
+nl_var_def_blk_end = 0 # number
+
+# The maximum consecutive newlines within a block of variable definitions
+# 0 = No change (default)
+nl_var_def_blk_in = 0 # number
+
+# Add or remove newline between a function call's ')' and '{', as in:
+# list_for_each(item, &list) { }
+nl_fcall_brace = ignore # ignore/add/remove/force
+
+# Add or remove newline between 'enum' and '{'
+nl_enum_brace = ignore # ignore/add/remove/force
+
+# Add or remove newline between 'struct and '{'
+nl_struct_brace = ignore # ignore/add/remove/force
+
+# Add or remove newline between 'union' and '{'
+nl_union_brace = ignore # ignore/add/remove/force
+
+# Add or remove newline between 'if' and '{'
+nl_if_brace = ignore # ignore/add/remove/force
+
+# Add or remove newline between '}' and 'else'
+nl_brace_else = ignore # ignore/add/remove/force
+
+# Add or remove newline between 'else if' and '{'
+# If set to ignore, nl_if_brace is used instead
+nl_elseif_brace = ignore # ignore/add/remove/force
+
+# Add or remove newline between 'else' and '{'
+nl_else_brace = ignore # ignore/add/remove/force
+
+# Add or remove newline between 'else' and 'if'
+nl_else_if = ignore # ignore/add/remove/force
+
+# Add or remove newline between '}' and 'finally'
+nl_brace_finally = ignore # ignore/add/remove/force
+
+# Add or remove newline between 'finally' and '{'
+nl_finally_brace = ignore # ignore/add/remove/force
+
+# Add or remove newline between 'try' and '{'
+nl_try_brace = ignore # ignore/add/remove/force
+
+# Add or remove newline between get/set and '{'
+nl_getset_brace = ignore # ignore/add/remove/force
+
+# Add or remove newline between 'for' and '{'
+nl_for_brace = ignore # ignore/add/remove/force
+
+# Add or remove newline between 'catch' and '{'
+nl_catch_brace = ignore # ignore/add/remove/force
+
+# Add or remove newline between '}' and 'catch'
+nl_brace_catch = ignore # ignore/add/remove/force
+
+# Add or remove newline between 'while' and '{'
+nl_while_brace = ignore # ignore/add/remove/force
+
+# Add or remove newline between 'scope (x)' and '{' (D)
+nl_scope_brace = ignore # ignore/add/remove/force
+
+# Add or remove newline between 'unittest' and '{' (D)
+nl_unittest_brace = ignore # ignore/add/remove/force
+
+# Add or remove newline between 'version (x)' and '{' (D)
+nl_version_brace = ignore # ignore/add/remove/force
+
+# Add or remove newline between 'using' and '{'
+nl_using_brace = ignore # ignore/add/remove/force
+
+# Add or remove newline between two open or close braces.
+# Due to general newline/brace handling, REMOVE may not work.
+nl_brace_brace = ignore # ignore/add/remove/force
+
+# Add or remove newline between 'do' and '{'
+nl_do_brace = ignore # ignore/add/remove/force
+
+# Add or remove newline between '}' and 'while' of 'do' statement
+nl_brace_while = ignore # ignore/add/remove/force
+
+# Add or remove newline between 'switch' and '{'
+nl_switch_brace = ignore # ignore/add/remove/force
+
+# Add a newline between ')' and '{' if the ')' is on a different line than the if/for/etc.
+# Overrides nl_for_brace, nl_if_brace, nl_switch_brace, nl_while_switch, and nl_catch_brace.
+nl_multi_line_cond = false # false/true
+
+# Force a newline in a define after the macro name for multi-line defines.
+nl_multi_line_define = false # false/true
+
+# Whether to put a newline before 'case' statement
+nl_before_case = false # false/true
+
+# Add or remove newline between ')' and 'throw'
+nl_before_throw = ignore # ignore/add/remove/force
+
+# Whether to put a newline after 'case' statement
+nl_after_case = false # false/true
+
+# Add or remove a newline between a case ':' and '{'. Overrides nl_after_case.
+nl_case_colon_brace = ignore # ignore/add/remove/force
+
+# Newline between namespace and {
+nl_namespace_brace = ignore # ignore/add/remove/force
+
+# Add or remove newline between 'template<>' and whatever follows.
+nl_template_class = ignore # ignore/add/remove/force
+
+# Add or remove newline between 'class' and '{'
+nl_class_brace = ignore # ignore/add/remove/force
+
+# Add or remove newline after each ',' in the constructor member initialization
+nl_class_init_args = ignore # ignore/add/remove/force
+
+# Add or remove newline between return type and function name in a function definition
+nl_func_type_name = ignore # ignore/add/remove/force
+
+# Add or remove newline between return type and function name inside a class {}
+# Uses nl_func_type_name or nl_func_proto_type_name if set to ignore.
+nl_func_type_name_class = ignore # ignore/add/remove/force
+
+# Add or remove newline between function scope and name in a definition
+# Controls the newline after '::' in 'void A::f() { }'
+nl_func_scope_name = ignore # ignore/add/remove/force
+
+# Add or remove newline between return type and function name in a prototype
+nl_func_proto_type_name = ignore # ignore/add/remove/force
+
+# Add or remove newline between a function name and the opening '('
+nl_func_paren = ignore # ignore/add/remove/force
+
+# Add or remove newline between a function name and the opening '(' in the definition
+nl_func_def_paren = ignore # ignore/add/remove/force
+
+# Add or remove newline after '(' in a function declaration
+nl_func_decl_start = ignore # ignore/add/remove/force
+
+# Add or remove newline after '(' in a function definition
+nl_func_def_start = ignore # ignore/add/remove/force
+
+# Overrides nl_func_decl_start when there is only one parameter.
+nl_func_decl_start_single = ignore # ignore/add/remove/force
+
+# Overrides nl_func_def_start when there is only one parameter.
+nl_func_def_start_single = ignore # ignore/add/remove/force
+
+# Add or remove newline after each ',' in a function declaration
+nl_func_decl_args = ignore # ignore/add/remove/force
+
+# Add or remove newline after each ',' in a function definition
+nl_func_def_args = ignore # ignore/add/remove/force
+
+# Add or remove newline before the ')' in a function declaration
+nl_func_decl_end = ignore # ignore/add/remove/force
+
+# Add or remove newline before the ')' in a function definition
+nl_func_def_end = ignore # ignore/add/remove/force
+
+# Overrides nl_func_decl_end when there is only one parameter.
+nl_func_decl_end_single = ignore # ignore/add/remove/force
+
+# Overrides nl_func_def_end when there is only one parameter.
+nl_func_def_end_single = ignore # ignore/add/remove/force
+
+# Add or remove newline between '()' in a function declaration.
+nl_func_decl_empty = ignore # ignore/add/remove/force
+
+# Add or remove newline between '()' in a function definition.
+nl_func_def_empty = ignore # ignore/add/remove/force
+
+# Whether to put each OC message parameter on a separate line
+# See nl_oc_msg_leave_one_liner
+nl_oc_msg_args = false # false/true
+
+# Add or remove newline between function signature and '{'
+nl_fdef_brace = ignore # ignore/add/remove/force
+
+# Add or remove a newline between the return keyword and return expression.
+nl_return_expr = ignore # ignore/add/remove/force
+
+# Whether to put a newline after semicolons, except in 'for' statements
+nl_after_semicolon = false # false/true
+
+# Whether to put a newline after brace open.
+# This also adds a newline before the matching brace close.
+nl_after_brace_open = false # false/true
+
+# If nl_after_brace_open and nl_after_brace_open_cmt are true, a newline is
+# placed between the open brace and a trailing single-line comment.
+nl_after_brace_open_cmt = false # false/true
+
+# Whether to put a newline after a virtual brace open with a non-empty body.
+# These occur in un-braced if/while/do/for statement bodies.
+nl_after_vbrace_open = false # false/true
+
+# Whether to put a newline after a virtual brace open with an empty body.
+# These occur in un-braced if/while/do/for statement bodies.
+nl_after_vbrace_open_empty = false # false/true
+
+# Whether to put a newline after a brace close.
+# Does not apply if followed by a necessary ';'.
+nl_after_brace_close = false # false/true
+
+# Whether to put a newline after a virtual brace close.
+# Would add a newline before return in: 'if (foo) a++; return;'
+nl_after_vbrace_close = false # false/true
+
+# Control the newline between the close brace and 'b' in: 'struct { int a; } b;'
+# Affects enums, unions, and structures. If set to ignore, uses nl_after_brace_close
+nl_brace_struct_var = ignore # ignore/add/remove/force
+
+# Whether to alter newlines in '#define' macros
+nl_define_macro = false # false/true
+
+# Whether to not put blanks after '#ifxx', '#elxx', or before '#endif'
+nl_squeeze_ifdef = false # false/true
+
+# Add or remove blank line before 'if'
+nl_before_if = ignore # ignore/add/remove/force
+
+# Add or remove blank line after 'if' statement
+nl_after_if = ignore # ignore/add/remove/force
+
+# Add or remove blank line before 'for'
+nl_before_for = ignore # ignore/add/remove/force
+
+# Add or remove blank line after 'for' statement
+nl_after_for = ignore # ignore/add/remove/force
+
+# Add or remove blank line before 'while'
+nl_before_while = ignore # ignore/add/remove/force
+
+# Add or remove blank line after 'while' statement
+nl_after_while = ignore # ignore/add/remove/force
+
+# Add or remove blank line before 'switch'
+nl_before_switch = ignore # ignore/add/remove/force
+
+# Add or remove blank line after 'switch' statement
+nl_after_switch = ignore # ignore/add/remove/force
+
+# Add or remove blank line before 'do'
+nl_before_do = ignore # ignore/add/remove/force
+
+# Add or remove blank line after 'do/while' statement
+nl_after_do = ignore # ignore/add/remove/force
+
+# Whether to double-space commented-entries in struct/enum
+nl_ds_struct_enum_cmt = false # false/true
+
+# Whether to double-space before the close brace of a struct/union/enum
+# (lower priority than 'eat_blanks_before_close_brace')
+nl_ds_struct_enum_close_brace = false # false/true
+
+# Add or remove a newline around a class colon.
+# Related to pos_class_colon, nl_class_init_args, and pos_comma.
+nl_class_colon = ignore # ignore/add/remove/force
+
+# Change simple unbraced if statements into a one-liner
+# 'if(b)\n i++;' => 'if(b) i++;'
+nl_create_if_one_liner = false # false/true
+
+# Change simple unbraced for statements into a one-liner
+# 'for (i=0;i<5;i++)\n foo(i);' => 'for (i=0;i<5;i++) foo(i);'
+nl_create_for_one_liner = false # false/true
+
+# Change simple unbraced while statements into a one-liner
+# 'while (i<5)\n foo(i++);' => 'while (i<5) foo(i++);'
+nl_create_while_one_liner = false # false/true
+
+#
+# Positioning options
+#
+
+# The position of arithmetic operators in wrapped expressions
+pos_arith = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
+
+# The position of assignment in wrapped expressions.
+# Do not affect '=' followed by '{'
+pos_assign = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
+
+# The position of boolean operators in wrapped expressions
+pos_bool = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
+
+# The position of comparison operators in wrapped expressions
+pos_compare = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
+
+# The position of conditional (b ? t : f) operators in wrapped expressions
+pos_conditional = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
+
+# The position of the comma in wrapped expressions
+pos_comma = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
+
+# The position of the comma in the constructor initialization list
+pos_class_comma = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
+
+# The position of colons between constructor and member initialization
+pos_class_colon = ignore # ignore/join/lead/lead_break/lead_force/trail/trail_break/trail_force
+
+#
+# Line Splitting options
+#
+
+# Try to limit code width to N number of columns
+code_width = 0 # number
+
+# Whether to fully split long 'for' statements at semi-colons
+ls_for_split_full = false # false/true
+
+# Whether to fully split long function protos/calls at commas
+ls_func_split_full = false # false/true
+
+# Whether to split lines as close to code_width as possible and ignore some groupings
+ls_code_width = false # false/true
+
+#
+# Blank line options
+#
+
+# The maximum consecutive newlines
+nl_max = 0 # number
+
+# The number of newlines after a function prototype, if followed by another function prototype
+nl_after_func_proto = 0 # number
+
+# The number of newlines after a function prototype, if not followed by another function prototype
+nl_after_func_proto_group = 0 # number
+
+# The number of newlines after '}' of a multi-line function body
+nl_after_func_body = 0 # number
+
+# The number of newlines after '}' of a multi-line function body in a class declaration
+nl_after_func_body_class = 0 # number
+
+# The number of newlines after '}' of a single line function body
+nl_after_func_body_one_liner = 0 # number
+
+# The minimum number of newlines before a multi-line comment.
+# Doesn't apply if after a brace open or another multi-line comment.
+nl_before_block_comment = 0 # number
+
+# The minimum number of newlines before a single-line C comment.
+# Doesn't apply if after a brace open or other single-line C comments.
+nl_before_c_comment = 0 # number
+
+# The minimum number of newlines before a CPP comment.
+# Doesn't apply if after a brace open or other CPP comments.
+nl_before_cpp_comment = 0 # number
+
+# Whether to force a newline after a multi-line comment.
+nl_after_multiline_comment = false # false/true
+
+# The number of newlines after '}' or ';' of a struct/enum/union definition
+nl_after_struct = 0 # number
+
+# The number of newlines after '}' or ';' of a class definition
+nl_after_class = 0 # number
+
+# The number of newlines before a 'private:', 'public:', 'protected:', 'signals:', or 'slots:' label.
+# Will not change the newline count if after a brace open.
+# 0 = No change.
+nl_before_access_spec = 0 # number
+
+# The number of newlines after a 'private:', 'public:', 'protected:', 'signals:', or 'slots:' label.
+# 0 = No change.
+nl_after_access_spec = 0 # number
+
+# The number of newlines between a function def and the function comment.
+# 0 = No change.
+nl_comment_func_def = 0 # number
+
+# The number of newlines after a try-catch-finally block that isn't followed by a brace close.
+# 0 = No change.
+nl_after_try_catch_finally = 0 # number
+
+# The number of newlines before and after a property, indexer or event decl.
+# 0 = No change.
+nl_around_cs_property = 0 # number
+
+# The number of newlines between the get/set/add/remove handlers in C#.
+# 0 = No change.
+nl_between_get_set = 0 # number
+
+# Add or remove newline between C# property and the '{'
+nl_property_brace = ignore # ignore/add/remove/force
+
+# Whether to remove blank lines after '{'
+eat_blanks_after_open_brace = false # false/true
+
+# Whether to remove blank lines before '}'
+eat_blanks_before_close_brace = false # false/true
+
+# How aggressively to remove extra newlines not in preproc.
+# 0: No change
+# 1: Remove most newlines not handled by other config
+# 2: Remove all newlines and reformat completely by config
+nl_remove_extra_newlines = 0 # number
+
+# Whether to put a blank line before 'return' statements, unless after an open brace.
+nl_before_return = false # false/true
+
+# Whether to put a blank line after 'return' statements, unless followed by a close brace.
+nl_after_return = false # false/true
+
+# Whether to put a newline after a Java annotation statement.
+# Only affects annotations that are after a newline.
+nl_after_annotation = ignore # ignore/add/remove/force
+
+# Controls the newline between two annotations.
+nl_between_annotation = ignore # ignore/add/remove/force
+
+#
+# Code modifying options (non-whitespace)
+#
+
+# Add or remove braces on single-line 'do' statement
+mod_full_brace_do = ignore # ignore/add/remove/force
+
+# Add or remove braces on single-line 'for' statement
+mod_full_brace_for = ignore # ignore/add/remove/force
+
+# Add or remove braces on single-line function definitions. (Pawn)
+mod_full_brace_function = ignore # ignore/add/remove/force
+
+# Add or remove braces on single-line 'if' statement. Will not remove the braces if they contain an 'else'.
+mod_full_brace_if = ignore # ignore/add/remove/force
+
+# Make all if/elseif/else statements in a chain be braced or not. Overrides mod_full_brace_if.
+# If any must be braced, they are all braced. If all can be unbraced, then the braces are removed.
+mod_full_brace_if_chain = false # false/true
+
+# Don't remove braces around statements that span N newlines
+mod_full_brace_nl = 0 # number
+
+# Add or remove braces on single-line 'while' statement
+mod_full_brace_while = ignore # ignore/add/remove/force
+
+# Add or remove braces on single-line 'using ()' statement
+mod_full_brace_using = ignore # ignore/add/remove/force
+
+# Add or remove unnecessary paren on 'return' statement
+mod_paren_on_return = ignore # ignore/add/remove/force
+
+# Whether to change optional semicolons to real semicolons
+mod_pawn_semicolon = false # false/true
+
+# Add parens on 'while' and 'if' statement around bools
+mod_full_paren_if_bool = false # false/true
+
+# Whether to remove superfluous semicolons
+mod_remove_extra_semicolon = false # false/true
+
+# If a function body exceeds the specified number of newlines and doesn't have a comment after
+# the close brace, a comment will be added.
+mod_add_long_function_closebrace_comment = 0 # number
+
+# If a switch body exceeds the specified number of newlines and doesn't have a comment after
+# the close brace, a comment will be added.
+mod_add_long_switch_closebrace_comment = 0 # number
+
+# If an #ifdef body exceeds the specified number of newlines and doesn't have a comment after
+# the #endif, a comment will be added.
+mod_add_long_ifdef_endif_comment = 0 # number
+
+# If an #ifdef or #else body exceeds the specified number of newlines and doesn't have a comment after
+# the #else, a comment will be added.
+mod_add_long_ifdef_else_comment = 0 # number
+
+# If TRUE, will sort consecutive single-line 'import' statements [Java, D]
+mod_sort_import = false # false/true
+
+# If TRUE, will sort consecutive single-line 'using' statements [C#]
+mod_sort_using = false # false/true
+
+# If TRUE, will sort consecutive single-line '#include' statements [C/C++] and '#import' statements [Obj-C]
+# This is generally a bad idea, as it may break your code.
+mod_sort_include = false # false/true
+
+# If TRUE, it will move a 'break' that appears after a fully braced 'case' before the close brace.
+mod_move_case_break = false # false/true
+
+# Will add or remove the braces around a fully braced case statement.
+# Will only remove the braces if there are no variable declarations in the block.
+mod_case_brace = ignore # ignore/add/remove/force
+
+# If TRUE, it will remove a void 'return;' that appears as the last statement in a function.
+mod_remove_empty_return = false # false/true
+
+#
+# Comment modifications
+#
+
+# Try to wrap comments at cmt_width columns
+cmt_width = 0 # number
+
+# Set the comment reflow mode (default: 0)
+# 0: no reflowing (apart from the line wrapping due to cmt_width)
+# 1: no touching at all
+# 2: full reflow
+cmt_reflow_mode = 0 # number
+
+# If false, disable all multi-line comment changes, including cmt_width. keyword substitution, and leading chars.
+# Default is true.
+cmt_indent_multi = true # false/true
+
+# Whether to group c-comments that look like they are in a block
+cmt_c_group = false # false/true
+
+# Whether to put an empty '/*' on the first line of the combined c-comment
+cmt_c_nl_start = false # false/true
+
+# Whether to put a newline before the closing '*/' of the combined c-comment
+cmt_c_nl_end = false # false/true
+
+# Whether to group cpp-comments that look like they are in a block
+cmt_cpp_group = false # false/true
+
+# Whether to put an empty '/*' on the first line of the combined cpp-comment
+cmt_cpp_nl_start = false # false/true
+
+# Whether to put a newline before the closing '*/' of the combined cpp-comment
+cmt_cpp_nl_end = false # false/true
+
+# Whether to change cpp-comments into c-comments
+cmt_cpp_to_c = false # false/true
+
+# Whether to put a star on subsequent comment lines
+cmt_star_cont = false # false/true
+
+# The number of spaces to insert at the start of subsequent comment lines
+cmt_sp_before_star_cont = 0 # number
+
+# The number of spaces to insert after the star on subsequent comment lines
+cmt_sp_after_star_cont = 0 # number
+
+# For multi-line comments with a '*' lead, remove leading spaces if the first and last lines of
+# the comment are the same length. Default=True
+cmt_multi_check_last = true # false/true
+
+# The filename that contains text to insert at the head of a file if the file doesn't start with a C/C++ comment.
+# Will substitute $(filename) with the current file's name.
+cmt_insert_file_header = "" # string
+
+# The filename that contains text to insert at the end of a file if the file doesn't end with a C/C++ comment.
+# Will substitute $(filename) with the current file's name.
+cmt_insert_file_footer = "" # string
+
+# The filename that contains text to insert before a function implementation if the function isn't preceded with a C/C++ comment.
+# Will substitute $(function) with the function name and $(javaparam) with the javadoc @param and @return stuff.
+# Will also substitute $(fclass) with the class name: void CFoo::Bar() { ... }
+cmt_insert_func_header = "" # string
+
+# The filename that contains text to insert before a class if the class isn't preceded with a C/C++ comment.
+# Will substitute $(class) with the class name.
+cmt_insert_class_header = "" # string
+
+# The filename that contains text to insert before a Obj-C message specification if the method isn't preceeded with a C/C++ comment.
+# Will substitute $(message) with the function name and $(javaparam) with the javadoc @param and @return stuff.
+cmt_insert_oc_msg_header = "" # string
+
+# If a preprocessor is encountered when stepping backwards from a function name, then
+# this option decides whether the comment should be inserted.
+# Affects cmt_insert_oc_msg_header, cmt_insert_func_header and cmt_insert_class_header.
+cmt_insert_before_preproc = false # false/true
+
+#
+# Preprocessor options
+#
+
+# Control indent of preprocessors inside #if blocks at brace level 0
+pp_indent = ignore # ignore/add/remove/force
+
+# Whether to indent #if/#else/#endif at the brace level (true) or from column 1 (false)
+pp_indent_at_level = false # false/true
+
+# If pp_indent_at_level=false, specifies the number of columns to indent per level. Default=1.
+pp_indent_count = 1 # number
+
+# Add or remove space after # based on pp_level of #if blocks
+pp_space = ignore # ignore/add/remove/force
+
+# Sets the number of spaces added with pp_space
+pp_space_count = 0 # number
+
+# The indent for #region and #endregion in C# and '#pragma region' in C/C++
+pp_indent_region = 0 # number
+
+# Whether to indent the code between #region and #endregion
+pp_region_indent_code = false # false/true
+
+# If pp_indent_at_level=true, sets the indent for #if, #else, and #endif when not at file-level
+pp_indent_if = 0 # number
+
+# Control whether to indent the code between #if, #else and #endif when not at file-level
+pp_if_indent_code = false # false/true
+
+# Whether to indent '#define' at the brace level (true) or from column 1 (false)
+pp_define_at_level = false # false/true
+
+# You can force a token to be a type with the 'type' option.
+# Example:
+# type myfoo1 myfoo2
+#
+# You can create custom macro-based indentation using macro-open,
+# macro-else and macro-close.
+# Example:
+# macro-open BEGIN_TEMPLATE_MESSAGE_MAP
+# macro-open BEGIN_MESSAGE_MAP
+# macro-close END_MESSAGE_MAP
+#
+# You can assign any keyword to any type with the set option.
+# set func_call_user _ N_
+#
+# The full syntax description of all custom definition config entries
+# is shown below:
+#
+# define custom tokens as:
+# - embed whitespace in token using '' escape character, or
+# put token in quotes
+# - these: ' " and ` are recognized as quote delimiters
+#
+# type token1 token2 token3 ...
+# ^ optionally specify multiple tokens on a single line
+# define def_token output_token
+# ^ output_token is optional, then NULL is assumed
+# macro-open token
+# macro-close token
+# macro-else token
+# set id token1 token2 ...
+# ^ optionally specify multiple tokens on a single line
+# ^ id is one of the names in token_enum.h sans the CT_ prefix,
+# e.g. PP_PRAGMA
+#
+# all tokens are separated by any mix of ',' commas, '=' equal signs
+# and whitespace (space, tab)
+#
diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644
index 0000000..b24cf43
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,3 @@
+## New in 0.07.00
+
+* Initial Open-Source Release.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..f50e5f2
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,37 @@
+Contributing to wpantund
+========================
+
+Want to contribute? Great! First, read this page (including the small
+print at the end).
+
+### Before you contribute ###
+
+Before we can use your code, you must sign the [Google Individual
+Contributor License Agreement][CLA-INDI] (CLA), which you can do
+online. The CLA is necessary mainly because you own the copyright to
+your changes, even after your contribution becomes part of our
+codebase, so we need your permission to use and distribute your code.
+We also need to be sure of various other things—for instance that
+you'll tell us if you know that your code infringes on other people's
+patents. You don't have to sign the CLA until after you've submitted
+your code for review and a member has approved it, but you must do it
+before we can put your code into our codebase. Before you start
+working on a larger contribution, you should get in touch with us
+first through the issue tracker with your idea so that we can help out
+and possibly guide you. Coordinating up front makes it much easier to
+avoid frustration later on.
+
+[CLA-INDI]: https://cla.developers.google.com/about/google-individual
+
+### Code reviews ###
+
+All submissions, including submissions by project members, require
+review. We use Github pull requests for this purpose.
+
+### The small print ###
+
+Contributions made by corporations are covered by a different
+agreement than the one above, the [Software Grant and Corporate
+Contributor License Agreement][CLA-CORP].
+
+[CLA-CORP]: https://cla.developers.google.com/about/google-corporate
diff --git a/HACKING.md b/HACKING.md
new file mode 100644
index 0000000..520977a
--- /dev/null
+++ b/HACKING.md
@@ -0,0 +1,56 @@
+Hacking wpantund
+================
+
+## Prerequisite Knowledge ##
+
+The wpantund project makes heavy use of the following:
+
+* [Protothreads](http://dunkels.com/adam/pt/)
+* [`boost::any`](http://www.boost.org/doc/libs/1_57_0/doc/html/any.html)
+* [`boost::signals2`](http://www.boost.org/doc/libs/1_51_0/doc/html/signals2.html)
+
+Understanding what these are and how they work are critical to being able to
+successfully work on WPAN Tunnel Driver.
+
+
+## General Project Structure ##
+
+There are give types of code in this project:
+
+1. Third-party code - Always contained in the `third_party`
+ directory.
+2. Separable Utilities - There are stand-alone utilities that are
+ generally useful and may be easily used by other projects. These
+ are in the `src/utils` directory.
+3. Fundamental Utilities - These are utilitity classes and functions
+ which are specific to WPAN Tunnel Driver, but used by both
+ application-specific and modem-specific classes. These can be
+ found in `src/utils` and `src/wpantund`.
+4. Application Specific - There are classes which define the basic
+ structure of the application. These are found in `src/wpantund`.
+5. Modem Specific - These are classes that are specific to individual
+ NCP implementations. These are found in specific subdirectories.
+ For example, `src/ncp-spinel`.
+
+There are three primary application-level virtual base classes in
+wpantund:
+
+ * `NCPControlInterface`
+ * `NCPInstance`
+ * `IPCServer`
+
+The `NCPControlInterface` is the interface through which all
+operations on an NCP are preformed, with the exception of sending and
+receiving packets on the network. For example, if you want to form or
+join a network, you do so via the virtual methods of this class.
+
+The `NCPInstance` class represents a NCP. The methods of this class
+are use by WPAN Tunnel Driver for low-level configuration and setup of
+the NCP. The `NCPInstance` class offers the `NCPControlInterface`
+object which is used to interact with this specific NCP. Generally,
+NCP implementations use this class for setting up the `TUN` interface,
+framing/unframing data and management packets, etc.
+
+The `IPCServer` class exposes the methods from the
+`NCPControlInterface` class via an unspecified IPC mechanism (DBus is
+currently the only sublass implemented).
diff --git a/INSTALL.md b/INSTALL.md
new file mode 100644
index 0000000..8fbe97e
--- /dev/null
+++ b/INSTALL.md
@@ -0,0 +1,247 @@
+`wpantund` Installation Guide
+=============================
+
+This document describes the process of building and installing
+`wpantund` on both Ubuntu and OS X. Installation on other platforms
+may be possible, but are left as an excercise for the reader. This
+document assumes that you are at least casually familiar with
+[Autoconf][1]. It also assumes that you have already gotten a copy of
+the wpantund sources, extracted them, and are wondering what to do
+next.
+
+[1]: http://www.gnu.org/software/autoconf/autoconf.html
+
+
+
+Installing `wpantund` on Ubuntu
+-------------------------------
+
+### 1. Install Dependencies ###
+
+Open up a terminal and perform the following commands:
+
+ sudo apt-get update
+
+ # Install runtine-dependent packages (libreadline is optional)
+ sudo apt-get install dbus libreadline
+
+ # Install build-dependent packages (libreadline-dev is optional)
+ sudo apt-get install gcc g++ libdbus-1-dev libboost-dev libreadline-dev
+
+### 2. Configure and build the project ###
+
+If the `configure` script is not already present in the root directory
+of your `wpantund` sources (which it should be if you got these
+sources from a tarball), you will need to either grab one of the `full/*`
+tags from the official git repository or run the bootstrap script.
+
+#### 2.1. Grabbing a full tag from Git ####
+
+The most likely thing you want to build is the latest stable release.
+In that case, all you need to do is checkout the tag `full/latest-release`:
+
+ git checkout full/latest-release
+
+And you should then be ready to build configure. Jump to section 2.3.
+
+#### 2.2. Running the bootstrap script ####
+
+Alternatively, you can *bootstrap* the project directly by doing the
+following:
+
+ sudo apt-get install libtool autoconf autoconf-archive
+ ./bootstrap.sh
+
+#### 2.3. Running the configure script ####
+
+If the `configure` script is present, run it and them start the make
+process:
+
+ ./configure --sysconfdir=/etc
+ make
+
+This may take a while. You can speed up the process by adding the
+argument `-j4` to the call to `make`, substituting the number `4` with
+the number of processor cores you have on your machine. This greatly
+improves the speed of builds.
+
+Also, if additional debugging information is required or helpful from
+`wpantund`, add the argument `--enable-debug` to the `./configure`
+line above.
+
+### 3. Install `wpantund` ###
+
+Once the build above is complete, execute the following command:
+
+ sudo make install
+
+This will install `wpantund` onto your computer.
+
+Installing `wpantund` on OS X
+-----------------------------
+
+Installing `wpantund` on OS X is largely similar to the process above,
+except things are complicated by the fact that we depend on D-Bus—and
+there is no native package manager for OS X. These instructions assume
+that you are using [Homebrew][2] as your package manager.
+
+[2]: http://brew.sh/
+
+What is nice about homebrew is that we have a recipe to build
+`wpantund` for you. This makes installing `wpantund` on OS X as easy
+as:
+
+ brew update
+ brew install ./etc/wpantund.rb
+
+ # Start the D-Bus daemon
+ sudo cp "$(brew --repository)"/Cellar/d-bus/*/org.freedesktop.dbus-session.plist /Library/LaunchDaemons/
+ sudo launchctl load -w /Library/LaunchDaemons/org.freedesktop.dbus-session.plist
+
+(the last two commands are for setting D-Bus up to launch properly at
+startup)
+
+PRO-TIP: Use `brew install wpantund --HEAD` if you want the latest
+bleeding-edge version of wpantund!
+
+However, **if you want to build `wpantund` manually**, the procedure
+described below allows you to manually set up the `wpantund` dependencies
+so that the build can run without a hitch.
+
+### 1. Install Xcode ###
+
+Go [here](http://itunes.apple.com/us/app/xcode/id497799835?ls=1&mt=12)
+and install [Xcode](https://developer.apple.com/xcode/) if you haven't
+already.
+
+After you have installed Xcode, you will need to install the Xcode
+command-line tools. You can do this easily from the command line with
+the following command:
+
+ xcode-select --install
+
+### 2. Install Homebrew ###
+
+[Homebrew](http://brew.sh/) is a package management system for OS X. While
+it is possible to install wpantund's dependencies manually, using
+homebrew makes this process much easier. If you don't already have it
+installed on your Mac, you can install it to your home directory using
+the following instructions:
+
+ cd ~
+ mkdir homebrew && curl -L https://github.com/mxcl/homebrew/tarball/master | tar xz --strip 1 -C homebrew
+ mkdir ~/bin
+
+Create the file `~/.bash_profile` with the following contents (tweak to
+your preference if you know what you're doing):
+
+ # Global stuff
+ export PATH=$HOME/bin:$PATH
+ export EDITOR=vi
+
+ # Homebrew stuff
+ export PATH=$HOME/homebrew/bin:$PATH
+
+Then close and reopen your terminal window.
+
+Alternatively, you can follow the instructions at <http://brew.sh/>, which
+installs to the prefix `/usr/local` instead of `~/homebrew`.
+
+### 2. Install and Setup `wpantund` dependencies ###
+
+We need a few dependencies in order to be able to build and use
+wpantund. The following commands will get us up and running:
+
+ brew install pkg-config
+ brew install autoconf-archive
+ brew install libtool
+ brew install boost
+ brew install d-bus
+
+ # Start the D-Bus daemon
+ sudo cp "$(brew --repository)"/Cellar/d-bus/*/org.freedesktop.dbus-session.plist /Library/LaunchDaemons/
+ sudo launchctl load -w /Library/LaunchDaemons/org.freedesktop.dbus-session.plist
+
+### 3. Configure and build ###
+
+At this point, you can jump over to step 2 from the section
+*Installing `wpantund` on Ubuntu*, above.
+
+
+
+
+Configuring and Using `wpantund`
+-------------------------------
+
+### 1. Configuring `wpantund` ###
+
+Now that you have `wpantund` installed, you will need to edit the
+configuration file to tell the daemon how to communicate with the NCP.
+You do this by editing the `wpantund.conf` file, which (if you
+followed the directions above) should now be at `/etc/wpantund.conf`.
+
+This file is, by default, filled only with comments—which describe
+all of the important configuration options that you might need to set
+in order to make wpantund usable. Read them over and then uncomment
+and update the appropriate configuration properties.
+
+Alternatively, you can specify any needed properties on the command
+line when invoking `wpantund`. At a minimum, at least `NCPSocketName`
+needs to be specified, which describes how `wpantund` is supposed to
+talk to the NCP.
+
+Refer to the authorative documentation in `/etc/wpantund.conf` or
+`./src/wpantund/wpantund.conf` for more information.
+
+### 2. Start wpantund ###
+
+To connect to an NCP on the serial port `/dev/ttyUSB0`, type the
+following into terminal:
+
+ sudo /usr/local/sbin/wpantund -o NCPSocketName /dev/ttyUSB0
+
+To start wpan on more than one interface, you can specify the WPAN
+interface name. For example, to set `wpan0` network interface on
+`/dev/ttyUSB0` USB interface, and `wpan1` on `/dev/ttyUSB1`, run:
+
+ sudo /usr/local/sbin/wpantund -o NCPSocketName /dev/ttyUSB0 -o WPANInterfaceName wpan0
+
+and
+
+ sudo /usr/local/sbin/wpantund -o NCPSocketName /dev/ttyUSB1 -o WPANInterfaceName wpan1
+
+Note that, unless you are running as root, you *must* use `sudo` when
+invoking `wpantund` directly.
+
+On an embedded device, you would add the appropriate scripts or
+configuration files that would cause `wpantund` to be started at boot.
+Doing so should be pretty straightforward.
+
+### 3. Using `wpanctl` ###
+
+Now that you have `wpantund` running, you can now issue commands to
+the daemon using `wpanctl` from another window: (Again, unless you are
+running as root, you *must* use `sudo`)
+
+ $ sudo /usr/local/bin/wpanctl
+ wpanctl:wpan0> leave
+ Leaving current WPAN. . .
+ wpanctl:wpan0> setprop NetworkKey --data 000102030405060708090a0b0c0d0e0f
+ wpanctl:wpan0> form "MyCoolNetwork" -c 26
+ Forming WPAN "MyCoolNetwork" as node type 2
+ Successfully formed!
+ wpanctl:wpan0> permit-join 3600 22
+ Permitting Joining on the current WPAN for 3600 seconds, commissioning traffic on TCP/UDP port 22. . .
+ wpanctl:wpan0> status
+ wpan0 => [
+ "AssociationState" => "joined"
+ "NetworkName" => "MyCoolNetwork"
+ "XPanId" => 0xD6D8A04025AB3B0C
+ "PanId" => 0xE3C3
+ "Channel" => 26
+ "AllowingJoin" => true
+ "Prefix" => [FDD6D8A040250000]
+ "NCPVersion" => "OpenThread/1.0d26-25-gb684c7f; DEBUG; May 9 2016 18:22:04"
+ "HWAddr" => [18B430000003F202]
+ ]
+ wpanctl:wpan0>
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..4b872bb
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,71 @@
+#
+# Copyright (c) 2016 Nest Labs, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+AUTOMAKE_OPTIONS = foreign
+ACLOCAL_AMFLAGS = -I m4
+DIST_TARGETS = dist-gzip dist-bzip2
+DIST_ARCHIVES = $(distdir).tar.gz $(distdir).tar.bz2
+AM_DISTCHECK_CONFIGURE_FLAGS = --enable-all-restricted-plugins
+
+SUBDIRS = \
+ src \
+ doc \
+ third_party \
+ $(NULL)
+
+DISTCLEANFILES = \
+ config.log \
+ config.status \
+ Makefile \
+ libtool \
+ make.out \
+ $(distdir).tar.* \
+ $(NULL)
+
+EXTRA_DIST = \
+ .default-version \
+ .gitignore \
+ .uncrustify.cfg \
+ bootstrap.sh \
+ README.md \
+ TODO.md \
+ HACKING.md \
+ LICENSE \
+ CHANGELOG \
+ CONTRIBUTING.md \
+ INSTALL.md \
+ doxygen.cfg.in \
+ etc/Dockerfile \
+ etc/build-in-docker.sh \
+ etc/run-in-docker.sh \
+ etc/wpantund.rb \
+ etc/autoandr/autoandr \
+ m4/nl.m4 \
+ $(NULL)
+
+
+
+HASH_VERSION = $(shell \
+ git describe --dirty --match __poison__ --always 2> /dev/null \
+)
+
+EXTRA_VERSION = $(shell \
+ git describe --all --contains 54e116add1f093663e047f88dac18b4851589483 1> /dev/null 2> /dev/null \
+ && (test "`git describe 2> /dev/null | sed 's:^full/::'`" = $(VERSION) || echo -g$(HASH_VERSION)) \
+)
+
+distdir = $(PACKAGE)-$(VERSION)$(EXTRA_VERSION)
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..84ad629
--- /dev/null
+++ b/README.md
@@ -0,0 +1,205 @@
+wpantund, Userspace WPAN Network Daemon
+=======================================
+
+`wpantund` is a user-space network interface driver/daemon that
+provides a native IPv6 network interface to a low-power wireless
+**Network Co-Processor** (or *NCP*). It was written and developed by
+Nest Labs to make supporting [Thread](http://threadgroup.org)
+connectivity on Unix-like operating systems more straightforward.
+
+`wpantund` is designed to marshall all access to the NCP, ensuring
+that it always remains in a consistent and well-defined state.
+
+This is not an official Google product.
+
+## Feature and Architecture Summary ##
+
+`wpantund` provides:
+
+ * ... a native IPv6 interface to an NCP.
+ * ... a command line interface (`wpanctl`) for managing and
+ configuring the NCP.
+ * ... a DBus API for managing and configuring the NCP.
+ * ... a way to reliably manage the power state of the NCP.
+ * ... a uniform mechanism for handling NCP firmware updates.
+
+The architecture and design of `wpantund` has been motivated by the
+following design goals (in no specific order):
+
+ * Portability across Unix-like operating systems (currently supports
+ Linux and OS X. BSD support should be fairly trivial to add)
+ * Require few runtime dependencies (DBus, with boost needed when
+ building)
+ * Single-threaded architecture, with heavy use of asynchronous I/O
+ * Power efficiency (0% CPU usage when idle)
+ * Allow management interface to be used by multiple independent
+ applications simultaneously
+ * Allow multiple instances of `wpantund` to gracefully co-exist on a
+ single machine
+ * Modular, plugin-based architecture (all details for communicating
+ with a specific NCP stack are implemented as plugins)
+
+Note that Windows is not currently supported, but patches are welcome.
+
+The following NCP plugins are provided:
+
+* `src/ncp-spinel`: Supports NCPs that communicate using the [Spinel NCP
+ Protocol][1], used by NCPs running [OpenThread][2]
+* `src/ncp-dummy`: A dummy NCP plug-in implementation meant to be the
+ starting point for implementing new NCP plug-ins
+
+[1]: ./third_party/openthread/src/ncp/PROTOCOL.md
+[2]: https://github.com/openthread/openthread/
+
+## License ##
+
+`wpantund` is open-source software released under the [Apache License,
+Version 2.0][3]. See the file [`LICENSE`][4] for more information.
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the [License][4] for the specific language governing permissions and
+limitations under the License.
+
+[3]: http://www.apache.org/licenses/LICENSE-2.0
+[4]: ./LICENSE
+
+## Conceptual Overview ##
+
+`wpantund` is conceptually similar in purpose to the point-to-point
+daemon (`pppd`, commonly used on Unix platforms to provide network
+connectivity via a dial-up modems) except that instead of communicating
+with a dial-up modem, `wpantund` is communicating with an NCP.
+
+`wpantund` communicates with the NCP via an abstraction of a
+asynchronous stream socket, which could be any of the following:
+
+ * A real serial port (UART) connected to the NCP (preferably with
+ hardware flow control)
+ * The stdin and stdout from a subprocess (for supporting SPI
+ interfaces using a translator program or debugging virtual
+ stacks)
+ * A TCP socket (for debugging, not recommended for production)
+
+Unlike a dial-up modem, NCPs often have a rich management interface
+for performing operations, such as forming a network, joining a
+network, scanning for nearby networks, etc. To perform these operations,
+`wpantund` includes a command line utility called `wpanctl`.
+Applications that need to directly configure the network interface can
+also communicate directly with `wpantund` using its DBus API.
+
+To expose a native IPv6 network interface to the host operating
+system, `wpantund` uses the `tun` driver on Linux and the `utun`
+driver on OS X. On Linux, the default name for the interface is
+`wpan0`. On OS X, the default name is `utun0`.
+
+## Usage Overview ##
+
+The behavior of `wpantund` is determined by its configuration
+parameters, which may be specified in a configuration file (typically
+`/etc/wpantund.conf`) or at the command line. A typical configuration
+file might look like that shown below. For a more thorough explanation
+of available configuration parameters, see the [included example][5].
+
+ # Try to name the network interface `wpan0`.
+ # If not possible, a different name will be used.
+ Config:TUN:InterfaceName "wpan0"
+
+ # The pathname of the socket used to communicate
+ # with the NCP.
+ Config:NCP:SocketPath "/dev/ttyUSB0"
+
+ # The name of the driver plugin to use. The chosen
+ # plugin must support the NCP you are trying to use.
+ Config:NCP:DriverName "spinel"
+
+ # Drop root privileges after opening all sockets
+ Config:Daemon:PrivDropToUser "nobody"
+
+ # Use a CCA Threshold of -70db
+ NCP:CCAThreshold "-70"
+
+When up and running, you can use `wpanctl` to check the status of the
+interface and perform various management operations. For example, to
+check the general status of an interface:
+
+ $ sudo wpanctl status
+ wpan0 => [
+ "NCP:State" => "offline"
+ "Daemon:Enabled" => true
+ "NCP:Version" => "OPENTHREAD/g1651a47; May 23 2016 17:23:24"
+ "Daemon:Version" => "0.07.00 (May 23 2016 12:58:54)"
+ "Config:NCP:DriverName" => "spinel"
+ "NCP:HardwareAddress" => [F1D92A82C8D8FE43]
+ ]
+
+Here we see that the NCP is in the `offline` state along with a few
+additional bits of information such as the version of the NCP and its
+hardware address. From here we can easily form a new network:
+
+ $ sudo wpanctl form "wpantund-testnet"
+ Forming WPAN "wpantund-testnet" as node type router
+ Successfully formed!
+ $
+
+Now if we check the status, we will see more information:
+
+ $ sudo wpanctl status
+ wpan0 => [
+ "NCP:State" => "associated"
+ "Daemon:Enabled" => true
+ "NCP:Version" => "OPENTHREAD/g1651a47; May 23 2016 17:23:24"
+ "Daemon:Version" => "0.07.00 (May 23 2016 12:58:54)"
+ "Config:NCP:DriverName" => "spinel"
+ "NCP:HardwareAddress" => [F1D92A82C8D8FE43]
+ "NCP:Channel" => 23
+ "Network:NodeType" => "leader"
+ "Network:Name" => "wpantund-testnet"
+ "Network:XPANID" => 0x09717AEF221F66FB
+ "Network:PANID" => 0xBFCD
+ "IPv6:LinkLocalAddress" => "fe80::f3d9:2a82:c8d8:fe43"
+ "IPv6:MeshLocalAddress" => "fd09:717a:ef22::9a5d:5d1e:5527:5fc8"
+ "IPv6:MeshLocalPrefix" => "fd09:717a:ef22::/64"
+ ]
+ $ ifconfig wpan0
+ wpan0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1280
+ inet6 fe80::f3d9:2a82:c8d8:fe43%wpan0 prefixlen 10 scopeid 0x15
+ inet6 fd09:717a:ef22::9a5d:5d1e:5527:5fc8 prefixlen 64
+
+If compiled with `libreadline` or `libedit`, `wpanctl` supports an
+convenient interactive console. All commands support online help: type
+`help` to get a list of supported commands, or add `-h` to a command to get
+help with that specific command.
+
+For more information, see the wiki: <https://github.com/openthread/wpantund/wiki>
+
+[5]: ./src/wpantund/wpantund.conf
+
+## Support ##
+
+Submit bugs and feature requests to [issue tracker][6]. We use the
+following mailing lists for discussion and announcements:
+
+ * [wpantund-announce](https://groups.google.com/forum/#!forum/wpantund-announce)
+ \- Official Anouncements About `wpantund`
+ * [wpantund-users](https://groups.google.com/forum/#!forum/wpantund-users)
+ \- `wpantund` User Discussion Group
+ * [wpantund-devel](https://groups.google.com/forum/#!forum/wpantund-devel)
+ \- `wpantund` Developer Discussion Group
+
+[6]: https://github.com/openthread/wpantund/issues
+
+## Authors and Contributors ##
+
+The following people have significantly contributed to the design
+and development of `wpantund`:
+
+ * Robert Quattlebaum
+ * Marcin Szczodrak
+ * Vaas Krishnamurthy
+ * Arjuna Siva
+ * Abtin Keshavarzian
+
+If you would like to contribute to this project, please read
+[CONTRIBUTING.md](CONTRIBUTING.md) first.
diff --git a/TODO.md b/TODO.md
new file mode 100644
index 0000000..8ce3b26
--- /dev/null
+++ b/TODO.md
@@ -0,0 +1,35 @@
+TODO LIST
+=========
+
+This document describes various tasks and features that are wanted or
+in-progress.
+
+General Cleanup/Refactoring Tasks
+---------------------------------
+
+### Finish DBusv1 API and move `wpanctl` to use it ###
+
+The new DBusv1 API is all but complete, but we still need to move a
+few methods in `wpanctl` over to use the new API. We also need to add
+the DBusv1 API equivalent for the `GetInterfaces` method, which is
+currently only in the V0 API.
+
+
+
+Security Tasks
+--------------
+
+Since WPAN Tunnel Driver communicates directly with the dangerous
+uncontrolled real-world, additional hardening is warranted. The
+following tasks are important for hardening `wpantund` from malicious foes:
+
+ * Investigate ways to harden the process by Limiting kernel attackable
+ surface-area by using a syscall filter like [`libseccomp`](https://github.com/seccomp/libseccomp).
+ * Full security audit of code paths which directly interpret data
+ from the NCP. Should be performed after the refactoring described
+ above.
+
+Wanted Features/Tasks
+---------------------
+
+ * Provide more behavioral logic in the `NCPInstanceBase` class.
diff --git a/bootstrap.sh b/bootstrap.sh
new file mode 100755
index 0000000..5074de6
--- /dev/null
+++ b/bootstrap.sh
@@ -0,0 +1,128 @@
+#!/bin/sh
+#
+# Copyright (c) 2016 Nest Labs, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOGFILE=`mktemp -q /tmp/bootstrap.log.XXXXXX`
+BOOTSTRAP_ANDROID=0
+BOOTSTRAP_AUTOTOOLS=1
+SOURCE_DIR=$(cd `dirname $0` && pwd)
+AUTOANDR=${AUTOANDR-${SOURCE_DIR}/etc/autoandr/autoandr}
+AUTOMAKE="automake --foreign"
+
+die() {
+ local errcode=$?
+ local prog=$1
+ shift
+
+ echo " ***************************** "
+
+ [[ $prog == "autoreconf" ]] && cat "$LOGFILE"
+
+ echo ""
+ if [[ $# -ge 1 ]]
+ then echo " *** $prog failed: \"$*\""
+ else echo " *** $prog failed with error code $errcode"
+ fi
+
+ exit 1
+}
+
+while [ "$#" -ge 1 ]
+do
+ case $1 in
+ --all)
+ BOOTSTRAP_ANDROID=1
+ BOOTSTRAP_AUTOTOOLS=1
+ ;;
+
+ --android)
+ BOOTSTRAP_ANDROID=1
+ BOOTSTRAP_AUTOTOOLS=0
+ ;;
+
+ --verbose)
+ LOGFILE=/dev/stderr
+ export V=1
+ ;;
+
+ *)
+ die bootstrap "Unknown argument: $1"
+ ;;
+ esac
+ shift
+done
+
+
+if [ "$BOOTSTRAP_AUTOTOOLS" = 1 ]
+then
+ cd "${SOURCE_DIR}"
+
+ which autoreconf 1>/dev/null 2>&1 || {
+ echo " *** error: The 'autoreconf' command was not found."
+ echo "Use the appropriate command for your platform to install the package:"
+ echo ""
+ echo "Homebrew(OS X) ....... brew install libtool autoconf autoconf-archive"
+ echo "Debian/Ubuntu ........ apt-get install libtool autoconf autoconf-archive"
+ exit 1
+ }
+
+ autoreconf --verbose --force --install 2>"$LOGFILE" || die autoreconf
+
+ grep -q AX_CHECK_ configure && {
+ echo " *** error: The 'autoconf-archive' package is not installed."
+ echo "Use the appropriate command for your platform to install the package:"
+ echo ""
+ echo "Homebrew(OS X) ....... brew install autoconf-archive"
+ echo "Debian/Ubuntu ........ apt-get install autoconf-archive"
+ exit 1
+ }
+fi
+
+if [ "$BOOTSTRAP_ANDROID" = 1 ]
+then
+ cd "${SOURCE_DIR}"
+
+ AUTOANDR_STDOUT="$LOGFILE" \
+ AUTOANDR_MODULE_TAGS=optional \
+ $AUTOANDR start \
+ --disable-option-checking \
+ --enable-static-link-ncp-plugin \
+ --disable-shared \
+ --prefix=/system \
+ --localstatedir=/data/misc \
+ --bindir=/system/bin \
+ --sbindir=/system/bin \
+ --libexecdir=/system/bin \
+ --libdir=/system/lib \
+ --includedir=/system/include \
+ --oldincludedir=/system/include \
+ --enable-debug=verbose \
+ CXXFLAGS="-fexceptions -Wno-non-virtual-dtor -frtti -Wno-c++11-narrowing" \
+ CPPFLAGS="-Wno-date-time -Wno-unused-parameter -Wno-missing-field-initializers -Wno-sign-compare" \
+ DBUS_CFLAGS="-Iexternal/dbus" \
+ DBUS_LIBS="-ldbus" \
+ TUNNEL_TUNTAP_DEVICE="/dev/tun" \
+ SOCKET_UTILS_DEFAULT_SHELL="/system/bin/sh" \
+ ac_cv_func_getdtablesize=no \
+ ac_cv_func_fgetln=no \
+ ac_cv_header_util_h=no \
+ --with-boost=internal \
+ || die autoandr
+fi
+
+echo
+echo Success. Logs in '"'$LOGFILE'"'
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..3f1f033
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,336 @@
+dnl #
+dnl # Copyright (c) 2016 Nest Labs, Inc.
+dnl # All rights reserved.
+dnl #
+dnl # Licensed under the Apache License, Version 2.0 (the "License");
+dnl # you may not use this file except in compliance with the License.
+dnl # You may obtain a copy of the License at
+dnl #
+dnl # http://www.apache.org/licenses/LICENSE-2.0
+dnl #
+dnl # Unless required by applicable law or agreed to in writing, software
+dnl # distributed under the License is distributed on an "AS IS" BASIS,
+dnl # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl # See the License for the specific language governing permissions and
+dnl # limitations under the License.
+dnl #
+
+AC_PREREQ(2.59)
+
+dnl This is the project name and release verison number.
+dnl The release version is stored in the file `.default-version`.
+dnl Update that file *after* every release to indicate the version
+dnl of the *next* anticipated release.
+AC_INIT(
+ [wpantund],
+ m4_esyscmd([printf "%s" `cat .default-version`]),
+ [wpantund-devel@googlegroups.com],
+ [wpantund],
+ [https://github.com/openthread/wpantund/]dnl
+)
+
+dnl These are the list of plugins that have usage restrictions
+dnl associated with their license. These will be automatically
+dnl disabled by default and print out a warning when enabled.
+m4_define(RESTRICTED_USE_NCP_PLUGINS, [ dnl
+])
+
+dnl This is the list of plugins which are included with wpantund.
+dnl As plugins are added, they should be appended to this list.
+m4_define(AVAILABLE_NCP_PLUGINS, [ dnl
+ RESTRICTED_USE_NCP_PLUGINS dnl
+ spinel dnl
+ dummy dnl
+])
+
+dnl These are the list of plugins are disabled by default.
+dnl This list automatically includes the plugins from
+dnl RESTRICTED_USE_NCP_PLUGINS.
+m4_define(DISABLED_NCP_PLUGINS, [RESTRICTED_USE_NCP_PLUGINS])
+
+dnl Attempt to include a reasonable git tag description.
+SOURCE_VERSION=m4_esyscmd([
+ configver="$PACKAGE_VERSION"
+ (test -d .git && gitver=`git describe --dirty --match "[0-9].*"` && printf "$gitver") ||
+ (test -d .git && gitver=`git describe --always` && printf "$configver-g$gitver") ||
+ printf "$configver"
+])
+
+AC_CONFIG_AUX_DIR([m4])
+AC_CONFIG_MACRO_DIR([m4])
+AC_CONFIG_FILES(Makefile doxygen.cfg src/Makefile doc/Makefile src/connman-plugin/Makefile src/ipc-dbus/Makefile src/wpanctl/Makefile src/wpantund/Makefile src/util/Makefile src/scripts/Makefile third_party/Makefile)
+
+# Set up AC_CONFIG_FILES for all of the available plugins.
+AC_CONFIG_FILES(m4_normalize(m4_foreach_w(THIS_PLUGIN,AVAILABLE_NCP_PLUGINS,[src/ncp-[]THIS_PLUGIN/Makefile ])))
+
+
+PLUGIN_SUBDIRS="[]m4_foreach_w(THIS_PLUGIN,AVAILABLE_NCP_PLUGINS,ncp-[]THIS_PLUGIN )"
+AC_SUBST(PLUGIN_SUBDIRS)
+
+AM_INIT_AUTOMAKE()
+
+AM_MAINTAINER_MODE
+
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+m4_ifdef([AX_CODE_COVERAGE], [AX_CODE_COVERAGE], [AC_SUBST([CODE_COVERAGE_RULES])])
+
+LT_INIT
+
+AC_LIBTOOL_DLOPEN_SELF
+
+AC_PROG_LIBTOOL
+
+AC_CONFIG_SRCDIR([src/version.h])
+AC_CONFIG_HEADERS([src/config.h])
+
+# This varable is for defining the default NCP plugin.
+# This is the default value, which can be overridden below.
+default_ncp_plugin=none
+
+dnl Add --enable/--disable configure arguments for all the available plugins.
+m4_foreach_w(THIS_PLUGIN,AVAILABLE_NCP_PLUGINS,[
+ m4_define([THIS_PLUGIN_DISABLED],m4_foreach_w(THAT_PLUGIN,DISABLED_NCP_PLUGINS,[m4_if(THIS_PLUGIN,THAT_PLUGIN,[disabled])]))
+
+ AC_ARG_ENABLE(
+ ncp-[]m4_translit(THIS_PLUGIN,[_],[-]),
+ AC_HELP_STRING(
+ [--[]m4_if(THIS_PLUGIN_DISABLED,[disabled],[enable],[disable])-ncp-[]m4_translit(THIS_PLUGIN,[_],[-])],
+ m4_do([[]m4_if(THIS_PLUGIN_DISABLED,[disabled],[enable],[disable]) the NCP plugin "],[THIS_PLUGIN],["])
+ ),
+ [
+ if test "x$enableval" = "xdefault"
+ then
+ default_ncp_plugin=[]THIS_PLUGIN
+ enable_ncp_[]THIS_PLUGIN=yes
+ fi
+ ],
+ [m4_if(THIS_PLUGIN_DISABLED,[disabled],[true],[enable_ncp_[]THIS_PLUGIN=yes])],
+ )
+])
+
+AC_ARG_ENABLE(
+ all-restricted-plugins,
+ AC_HELP_STRING(
+ [--enable-all-restricted-plugins],
+ [Enable all plugins with restrictive licenses]
+ )
+)
+
+AC_ARG_ENABLE(
+ static-link-ncp-plugin,
+ AC_HELP_STRING(
+ [--enable-static-link-ncp-plugin=[plugin]],
+ [Statically link against a single NCP plugin]
+ ),
+ [],
+ [
+ if test "x$enable_shared" == "xno"
+ then enable_static_link_ncp_plugin=yes
+ fi
+ ]
+)
+
+if test "x$enable_all_restricted_plugins" = "xyes"
+then {
+true
+m4_foreach_w(THIS_PLUGIN,RESTRICTED_USE_NCP_PLUGINS,
+[ if test "x$enable_ncp_[]m4_translit(THIS_PLUGIN,[-],[_])" = "x"
+ then enable_ncp_[]m4_translit(THIS_PLUGIN,[-],[_])="yes"
+ fi
+])}
+fi
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+test "x$pkglibexecdir" = x && pkglibexecdir='${libexecdir}/${PACKAGE_TARNAME}'
+
+AC_DEFINE_UNQUOTED([PREFIX], ["`eval echo "$prefix"`"], [Define to the install prefix])
+AC_DEFINE_UNQUOTED([SYSCONFDIR], ["`eval echo "$sysconfdir"`"], [Define to the sub-directory for system settings.])
+AC_DEFINE_UNQUOTED([PKGLIBEXECDIR], ["`eval eval eval echo "$pkglibexecdir"`"], [Define to the sub-directory for plugins.])
+
+AC_DEFINE_UNQUOTED([SOURCE_VERSION], ["`eval echo "$SOURCE_VERSION"`"], [Source version])
+
+if test "${TUNNEL_TUNTAP_DEVICE+set}" = "set"
+then AC_DEFINE_UNQUOTED([TUNNEL_TUNTAP_DEVICE], ["$TUNNEL_TUNTAP_DEVICE"], [Path to tuntap device])
+fi
+if test "${SOCKET_UTILS_DEFAULT_SHELL+set}" = "set"
+then AC_DEFINE_UNQUOTED([SOCKET_UTILS_DEFAULT_SHELL], ["$SOCKET_UTILS_DEFAULT_SHELL"], [Default path to a shell])
+fi
+
+AC_PROG_CC([],AC_MSG_ERROR(["A working C compiler is required"]))
+AC_PROG_CXX([],AC_MSG_ERROR(["A working C++ compiler is required"]))
+
+AC_HEADER_STDC
+AC_HEADER_TIME
+
+AC_CHECK_HEADERS([unistd.h errno.h stdbool.h], [], AC_MSG_ERROR(["Missing a required header."]))
+
+AC_CHECK_HEADERS([sys/un.h sys/wait.h pty.h pwd.h execinfo.h asm/sigcontext.h sys/prctl.h])
+
+AC_C_CONST
+AC_TYPE_SIZE_T
+AC_TYPE_SSIZE_T
+
+AC_C_INLINE
+AC_C_VOLATILE
+
+dnl Raspberry Pi's clock_gettime() function is in librt.
+dnl This should only pick it up if necessary.
+AC_SEARCH_LIBS([clock_gettime], [rt])
+AC_CHECK_FUNCS([clock_gettime])
+
+AC_CHECK_FUNCS([alloca fgetln memcmp memset strtol strdup strndup strlcpy strlcat stpncpy vsnprintf vsprintf snprintf getdtablesize getloadavg])
+
+NL_DEBUG
+NL_CHECK_DBUS
+NL_CHECK_BOOST_SIGNALS2([],AC_MSG_ERROR([Unable to find a usable implementation of boost::signals2 (not even our internal copy)]))
+NL_CHECK_READLINE
+NL_CHECK_PTS
+
+AC_DEFINE_UNQUOTED([__STDC_LIMIT_MACROS], [1], [Needed by C++])
+AC_DEFINE_UNQUOTED([__STDC_CONSTANT_MACROS], [1], [Needed by C++])
+
+AC_DEFINE_UNQUOTED([ASSERT_MACROS_USE_SYSLOG], 1, [Define to 1 to have assertmacros.h use syslog])
+AC_DEFINE_UNQUOTED([ASSERT_MACROS_SQUELCH], 0, [Define to 0 to explicitly prevent squelching assert printouts])
+
+NL_CHECK_CONNMAN([
+ NL_CHECK_GLIB(
+ [],
+ AC_MSG_ERROR(["Found ConnMan headers, but couldn't find GLIB"])
+ )
+])
+AM_CONDITIONAL([BUILD_CONNMAN_PLUGIN],[test "x${with_connman}" = "xyes"])
+
+
+AM_CONDITIONAL([HOST_IS_LINUX],[(case "${host_os}" in *linux*) true ;; *) false ;; esac)])
+
+building_ncp_plugins=""
+
+m4_foreach_w(THIS_PLUGIN,AVAILABLE_NCP_PLUGINS,[
+ if test "x${enable_ncp_[]m4_translit(THIS_PLUGIN,[-],[_])}" = "xyes"
+ then building_ncp_plugins=`echo ${building_ncp_plugins} []THIS_PLUGIN`
+ fi
+])
+
+if test "x$building_ncp_plugins" != "x"
+then
+ if test "x$default_ncp_plugin" = "xnone"
+ then default_ncp_plugin=$(IFS=" " ; set -- $building_ncp_plugins ; echo $1)
+ fi
+fi
+
+if test "x${enable_static_link_ncp_plugin-no}" != "xno"
+then {
+ if test "x${enable_static_link_ncp_plugin-no}" != "xyes"
+ then {
+ # TODO: Extract statically linked plugin here, make sure it is enabled.
+ default_ncp_plugin=${enable_static_link_ncp_plugin}
+ enable_static_link_ncp_plugin=yes
+ } fi
+
+ if test "x${default_ncp_plugin-none}" = "xnone"
+ then AC_MSG_ERROR(["You must enable one NCP plugin when statically linking"])
+ fi
+
+ building_ncp_plugins=${default_ncp_plugin}
+
+ m4_foreach_w(THIS_PLUGIN,AVAILABLE_NCP_PLUGINS,[
+ if test "[]THIS_PLUGIN" != "${default_ncp_plugin}"
+ then enable_ncp_[]m4_translit(THIS_PLUGIN,[-],[_])=no
+ fi
+ ])
+
+ AC_DEFINE_UNQUOTED([WPANTUND_PLUGIN_STATICLY_LINKED], [1], [Set to 1 if we are statically linking the plugin/])
+}
+else {
+ NL_CHECK_LIBDL
+ NL_EXPORT_DYNAMIC
+}
+fi
+
+AC_DEFINE_UNQUOTED([WPANTUND_DEFAULT_NCP_PLUGIN], ["${default_ncp_plugin}"], [Set to the name of the default NCP plugin])
+
+AM_CONDITIONAL(STATIC_LINK_NCP_PLUGIN,[test "x${enable_static_link_ncp_plugin}" = "xyes"])
+
+building_ncp_plugins=""
+
+
+m4_foreach_w(THIS_PLUGIN,AVAILABLE_NCP_PLUGINS,[
+ if test "x${enable_ncp_[]m4_translit(THIS_PLUGIN,[-],[_])}" = "xyes"
+ then building_ncp_plugins=`echo ${building_ncp_plugins} []THIS_PLUGIN`
+ fi
+
+ m4_ifdef([m4_do(WPANTUND_PLUGIN_NCP_[]m4_toupper(m4_translit(THIS_PLUGIN,[-],[_]))],
+ [WPANTUND_PLUGIN_NCP_[]m4_toupper(m4_translit(THIS_PLUGIN,[-],[_])]
+ )
+
+ AM_CONDITIONAL(BUILD_PLUGIN_NCP_[]m4_toupper(m4_translit(THIS_PLUGIN,[-],[_])),[test "x${enable_ncp_[]m4_translit(THIS_PLUGIN,[-],[_])}" = "xyes"])
+])
+
+m4_foreach_w(THIS_PLUGIN,RESTRICTED_USE_NCP_PLUGINS,[
+ if test "x${enable_ncp_[]m4_translit(THIS_PLUGIN,[-],[_])}" = "xyes"
+ then restricted_use_ncp_plugins=`echo ${restricted_use_ncp_plugins} []THIS_PLUGIN`
+ fi
+])
+
+AC_SUBST(default_ncp_plugin)
+
+AC_OUTPUT
+
+echo ""
+echo "= Summary ====================================================================="
+echo ""
+echo "ConnMan Plugin ................. ${with_connman-no}"
+echo "Using libreadline .............. ${with_readline-???}"
+echo "Boost .......................... ${with_boost-???}"
+echo "NCP plugins to build ........... ${building_ncp_plugins-none}"
+echo "Default NCP Plugin ............. ${default_ncp_plugin}"
+echo "Static link NCP plugin ......... ${enable_static_link_ncp_plugin-no}"
+echo ""
+
+if test "x${with_readline}" != "xyes"
+then {
+ echo "warning: libreadline was disabled or not found, interactive"
+ echo " wpanctl command line interface will not be enabled!"
+ echo ""
+}
+fi
+
+if test "x$restricted_use_ncp_plugins" != "x"
+then {
+ echo "ATTENTION: Some of the plugins you are building have proprietary licenses which"
+ echo " are more restrictive than the Apache 2.0 license that covers wpantund"
+ echo " in general. If you are reading this message, it means you have manually"
+ echo " enabled at least one plug-in that has a proprietary license. Please"
+ echo " make sure that you understand the usage restrictions before using"
+ echo " wpantund with these plugins: "
+ echo ""
+ echo " $restricted_use_ncp_plugins"
+ echo ""
+}
+fi
+
+if test "x$building_ncp_plugins" = "x"
+then {
+ echo " *** WARNING: The current configuration is NOT BUILDING ANY PLUGINS! wpantund won't"
+ echo " be very useful in this state. Note that plugins with proprietary"
+ echo " licenses are no longer built by default: you must either enable them"
+ echo ' individually (using `--enable-ncp-*` configuration options) or by using'
+ echo ' the `--enable-all-restricted-plugins` configuration option.'
+ echo " In any case, you can still make and install wpantund without plugins"
+ echo " if you really know what you are doing."
+ echo ""
+}
+fi
+
+if test "x$building_ncp_plugins" = "xdummy"
+then {
+ echo " *** WARNING: The current configuration is only building the dummy plugin! wpantund"
+ echo " won't be very useful in this state. Note that plugins with proprietary"
+ echo " licenses are no longer built by default: you must either enable them"
+ echo ' individually (using `--enable-ncp-*` configuration options) or by using'
+ echo ' the `--enable-all-restricted-plugins` configuration option.'
+ echo ""
+}
+fi
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 0000000..d8d8258
--- /dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1,29 @@
+#
+# Copyright (c) 2016 Nest Labs, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+
+man_MANS = \
+ wpantund.1 \
+ wpanctl.1 \
+ $(NULL)
+
+EXTRA_DIST = \
+ wpantund-oss-plan.md \
+ wpan-dbus-protocol.md \
+ wpantund.1 \
+ wpanctl.1 \
+ $(NULL)
diff --git a/doc/wpan-dbus-protocol.md b/doc/wpan-dbus-protocol.md
new file mode 100644
index 0000000..13bf867
--- /dev/null
+++ b/doc/wpan-dbus-protocol.md
@@ -0,0 +1,136 @@
+wpantund DBus Protocol v1
+=========================
+
+This document outlines the DBus protocol used to communicate
+with `wpantund` to manage a low-power wireless network interface.
+
+It is a work in progress.
+
+daemon id: `org.wpantund`
+
+# Interface: `org.wpantund`
+
+## Path `/org/wpantund/`
+
+### Command: `GetInterfaces`
+### Command: `GetVersion`
+### Signal: `InterfaceAdded`
+### Signal: `InterfaceRemoved`
+
+## Path `/org/wpantund/<iface-name>`
+
+### Signal: `NetScanBeacon`
+### Signal: `NetScanComplete`
+
+### Command: `NetScanStart`
+### Command: `NetScanStop`
+
+### Command: `Status`
+### Command: `Reset`
+
+### Command: `BeginLowPower`
+### Command: `HostDidWake`
+
+### Command: `Attach`
+### Command: `Join`
+### Command: `Form`
+### Command: `Leave`
+
+### Command: `ConfigGateway`
+### Command: `DataPoll`
+
+## Path `/org/wpantund/<iface-name>/Properties/<property-name>`
+
+### Signal: "Changed"
+### Command: "Set"
+### Command: "Get"
+
+# Interface: `com.nestlabs.wpantund.internal`
+
+## Path `/org/wpantund/<iface-name>`
+
+### Command: `PermitJoin`
+### Command: `BeginNetWake`
+
+
+
+-------------------------------------------------------------------------------
+
+# Configuration Properties
+
+## `Config:NCP:SocketPath`
+## `Config:NCP:SocketBaud`
+## `Config:NCP:DriverName`
+## `Config:NCP:HardResetPath`
+## `Config:NCP:PowerPath`
+## `Config:NCP:ReliabilityLayer`
+## `Config:NCP:FirmwareCheckCommand`
+## `Config:NCP:FirmwareUpgradeCommand`
+## `Config:TUN:InterfaceName`
+## `Config:Daemon:PIDFile`
+## `Config:Daemon:PrivDropToUser`
+## `Config:Daemon:Chroot`
+
+## `Daemon:Version`
+## `Daemon:Enabled`
+## `Daemon:SyslogMask`
+## `Daemon:TerminateOnFault`
+
+
+## `Daemon:ReadyForHostSleep`
+Read only. Set to `true` if `wpantund` is busy. Set to `false` if it is idle.
+Primarily used for determining if it is a good opportunity to attempt to
+put the host into a low-power state.
+
+## `Daemon:AutoAssociateAfterReset` (Was AutoResume)
+If the NCP persistently stores network association and the NCP
+comes up in the `offline:commissioned` state, this option being set
+will cause `wpantund` to automatiaclly attempt to associate.
+
+## `Daemon:AutoFirmwareUpdate`
+## `Daemon:AutoDeepSleep`
+
+## `NCP:Version`
+## `NCP:State`
+## `NCP:HardwareAddress`
+## `NCP:Channel`
+## `NCP:TXPower`
+## `NCP:TXPowerLimit`
+## `NCP:CCAThreshold`
+## `NCP:DefaultChannelMask`
+## `NCP:SleepyPollInterval`
+
+## `Network:Name`
+## `Network:XPANID`
+## `Network:PANID`
+## `Network:NodeType`
+## `Network:Key`
+## `Network:KeyIndex`
+## `Network:IsAssociated`
+
+## `IPv6:LinkLocalAddress`
+## `IPv6:MeshLocalAddress`
+## `IPv6:AllAddresses`
+
+
+
+
+
+
+
+
+
+# NCP States
+
+## "uninitialized" (same)
+## "uninitialized:fault" (same)
+## "uninitialized:upgrading" (same)
+## "offline:deep-sleep" (was "deep-sleep")
+## "offline" (was "disconnected")
+## "offline:commissioned" (was "saved")
+## "associating" (was "joining")
+## "associating:credentials-needed" (was "credentials-needed")
+## "associated" (was "joined")
+## "associated:no-parent" (was "joined-no-parent")
+## "associated:netwake-sleeping" (was "joined-lurking")
+## "associated:netwake-waking" (was "net-wake")
diff --git a/doc/wpanctl.1 b/doc/wpanctl.1
new file mode 100644
index 0000000..ac4cea2
--- /dev/null
+++ b/doc/wpanctl.1
@@ -0,0 +1,377 @@
+.TH wpanctl 1 "" "" "USER COMMANDS"
+
+.SH NAME
+wpanctl \- command line interfase for wpantund
+
+.SH SYNOPSIS
+.B wpanctl
+[\fIOPTIONS\fR] <\fICOMMANDS\fR> [args]
+
+.SH DESCRIPTION
+.B wpanctl
+is itself a command-line interface. You can specify an individual single command
+directly on the \fBwpanctl\fR command line, or run \fBwpanctl\fR without any arguments
+to enter the command-line interface shell.
+
+.SH OPTIONS
+
+.TP
+\fB\-h\fP, \fB\-\-help\fp
+Print help.
+
+.TP
+\fB\-v\fP, \fB\-\-version\fp
+Print version.
+
+.TP
+\fB\-f\fP \fIFILE
+Read commands from a file.
+
+.TP
+\fB\-I\fP, \fB\-\-interface\fp \fIINTERFACE\fR
+Set interface to use (e.g. wpan0).
+
+.TP
+\fB\-i\fP, \fB\-\-ignore-mismatch\fP
+Ignore driver version mismatch.
+
+.SH COMMANDS
+
+.TP
+\fBbegin-low-power\fR [\fBargs\fR]
+Enter low-power mode.
+
+ \fB\-h\fP, \fB\-\-help\fR
+ Print join help.
+
+ \fB\-t\fP, \fB\-\-timeout\fR [\fBTIMEOUT\fR]
+ Set timeout period.
+
+.TP
+\fBbegin-net-wake\fR [\fBargs\fR]
+Initiate a network wakeup.
+
+ \fB\-h\fP, \fB\-\-help\fR
+ Print join help.
+
+ \fB\-t\fP, \fB\-\-timeout\fR [\fBTIMEOUT\fR]
+ Set timeout period.
+
+.TP
+\fBcd\fR
+Change current interface (command mode).
+
+.TP
+\fBconfig-gateway\fR [\fBargs\fR] <\fBPREFIX\fR>
+Configure gateway.
+
+ \fB\-h\fP, \fB\-\-help\fR
+ Print join help.
+
+ \fB\-t\fP, \fB\-\-timeout\fR [\fBTIMEOUT\fR]
+ Set timeout period.
+
+ \fB\-p\fP, \fB\-\-preferred-lifetime\fR
+ Set the \fBPREFERRED_LIFETIME\fR.
+
+ \fB\-v\fP, \fB\-\-valid-lifetime\fR
+ Set the \fBVALID_LIFETIME\fR.
+
+ \fB\-d\fP, \fB\-\-default\fR
+ Indicates that we can be a default route.
+
+.TP
+\fBform\fR [\fBargs\fR] [\fBNETWORK_NAME\fR]
+Form a new WPAN.
+
+ \fB\-h\fP, \fB\-\-help\fR
+ Print join help.
+
+ \fB\-t\fP, \fB\-\-timeout\fR [\fBTIMEOUT\fR]
+ Set timeout period.
+
+ \fB\-u\fP, \fB\-\-ula-prefix\fR [\fBULA_PREFIX\fR]
+ Specify a specific ULA prefix.
+
+ \fB\-c\fP, \fB\-\-channel\fR [\fBCHANNEL\fR]
+ Specify a specific radio channel.
+
+.TP
+\fBgetprop\fR, \fBget\fR [\fBargs\fR] <\fBproperty-name\fR>
+Get a property.
+
+ \fB\-h\fP, \fB\-\-help\fR
+ Print join help.
+
+ \fB\-t\fP, \fB\-\-timeout\fR [\fBTIMEOUT\fR]
+ Set timeout period.
+
+ \fB\-a\fP, \fB\-\-all\fR
+ Print all supported properties.
+
+ \fB\-v\fP, \fB\-\-value-only\fR
+ Print only the value of the property.
+
+.TP
+\fBhelp\fR
+Display help.
+
+.TP
+\fBhost-did-wake\fR [\fBargs\fR]
+Perform any host-wakeup related tasks.
+
+ \fB\-h\fP, \fB\-\-help\fR
+ Print join help.
+
+ \fB\-t\fP, \fB\-\-timeout\fR [\fBTIMEOUT\fR]
+ Set timeout period.
+
+.TP
+\fBjoin\fR [\fBargs\fR] [\fBNETWORK_NAME\fR]
+Join a WPAN.
+
+ \fB\-h\fP, \fB\-\-help\fR
+ Print join help.
+
+ \fB\-t\fP, \fB\-\-timeout\fR [\fBTIMEOUT\fR]
+ Set timeout period.
+
+ \fB\-T\fP, \fB\-\-type\fR [\fBNODE_TYPE\fR]
+ Join as a specific node type.
+
+ \fB\-p\fP, \fB\-\-panid\fR [\fBPAN_ID\fR]
+ Specify a specific PAN ID.
+
+ \fB\-x\fP, \fB\-\-xpanid\fR [\fBExtended_PAN_ID\fR]
+ Specify a specific extended PAN ID.
+
+ \fB\-c\fP, \fB\-\-channel\fR [\fBCHANNEL\fR]
+ Specify a specific radio channel.
+
+.TP
+\fBleave\fR [\fBargs\fR]
+Abandon the currently connected WPAN.
+
+ \fB\-h\fP, \fB\-\-help\fR
+ Print join help.
+
+ \fB\-t\fP, \fB\-\-timeout\fR [\fBTIMEOUT\fR]
+ Set timeout period.
+
+.TP
+\fBlist\fR [\fBargs\fR]
+List available interfaces.
+
+ \fB\-h\fP, \fB\-\-help\fR
+ Print join help.
+
+ \fB\-t\fP, \fB\-\-timeout\fR [\fBTIMEOUT\fR]
+ Set timeout period.
+
+.TP
+\fBpermit-join\fR [\fBargs\fR] <\fBPERMIT_JOIN_DURATION\fR> [\fBCOMMISSIONING_PORT\fR]
+Permit other devices to join the current network.
+
+ \fB\-h\fP, \fB\-\-help\fR
+ Print join help.
+
+ \fB\-t\fP, \fB\-\-timeout\fR [\fBTIMEOUT\fR]
+ Set timeout period.
+
+ \fB\-n\fP, \fB\-\-network-wide\fR
+ Permit joining network-wide.
+
+ \fB\-c\fP, \fB\-\-tcp\fR
+ Permit only TCP for commissioning traffic.
+
+ \fB\-d\fP, \fB\-\-udp\fR
+ Permit only UDP for commissioning traffic.
+
+.TP
+\fBping\fR [\fBargs\fR]
+Ping the NCP.
+
+ \fB\-h\fP, \fB\-\-help\fR
+ Print join help.
+
+ \fB\-t\fP, \fB\-\-timeout\fR [\fBTIMEOUT\fR]
+ Set timeout period.
+
+.TP
+\fBpoll\fR [\fBargs\fR]
+Poll the parent immediately to see if there is IP traffic.
+
+ \fB\-h\fP, \fB\-\-help\fR
+ Print join help.
+
+ \fB\-t\fP, \fB\-\-timeout\fR [\fBTIMEOUT\fR]
+ Set timeout period.
+
+.TP
+\fBquit\fR
+Terminate command line mode.
+
+.TP
+\fBreset\fR [\fBargs\fR]
+Reset the NCP.
+
+ \fB\-h\fP, \fB\-\-help\fR
+ Print join help.
+
+ \fB\-t\fP, \fB\-\-timeout\fR [\fBTIMEOUT\fR]
+ Set timeout period.
+
+.TP
+\fBresume\fR [\fBargs\fR]
+Resume a previously connected network.
+
+ \fB\-h\fP, \fB\-\-help\fR
+ Print join help.
+
+ \fB\-t\fP, \fB\-\-timeout\fR [\fBTIMEOUT\fR]
+ Set timeout period.
+
+.TP
+\fBscan\fR [\fBargs\fR]
+Scan for nearby networks.
+
+ \fB\-h\fP, \fB\-\-help\fR
+ Print join help.
+
+ \fB\-t\fP, \fB\-\-timeout\fR [\fBTIMEOUT\fR]
+ Set timeout period.
+
+ \fB\-c\fP, \fB\-\-channel\fR [\fBCHANNEL\fR]
+ Specify a specific radio channel.
+
+.TP
+\fBsetprop\fR, \fBset\fR \fBget\fR [\fBargs\fR] <\fBproperty-name\fR> <\fBproperty-value\fR>
+Set a property.
+
+ \fB\-h\fP, \fB\-\-help\fR
+ Print join help.
+
+ \fB\-t\fP, \fB\-\-timeout\fR [\fBTIMEOUT\fR]
+ Set timeout period.
+
+ \fB\-d\fP, \fB\-\-data\fR
+ Value is binary data (in hex).
+
+ \fB\-s\fP, \fB\-\-string\fR
+ Value is a string.
+
+ \fB\-i\fP, \fB\-\-integer\fR
+ Value is an integer.
+
+ \fB\-v\fP, \fB\-\-value\fR
+ Useful when the value starts with a '-'.
+
+.TP
+\fBstatus\fR [\fBargs\fR]
+Retrieve the status of the interface.
+
+ \fB\-h\fP, \fB\-\-help\fR
+ Print join help.
+
+ \fB\-t\fP, \fB\-\-timeout\fR [\fBTIMEOUT\fR]
+ Set timeout period.
+
+
+.SH EXAMPLES
+
+.TP
+$ sudo wpanctl
+Enter wpanctl command line interface that starts with prompt \fBwpanctl:[Iinterface_name]>\fR
+
+.TP
+$ sudo wpanctl -I <interface-name>
+Enter wpanctl command line and connect to specified interface, e.g.
+\fI$ sudo wpanctl -I wpan0\fR
+results with the following wpanctl shell prompt:
+\fBwpanctl:wpan0>\fR
+
+.TP
+$ sudo wpanctl scan
+Sends \fIscan\fR command to wpantund.
+The wpantund output is printed in the shell.
+
+.TP
+$ sudo wpanctl scan -c25-26,14,18-16
+Requests wpantund to scan for networks on channels 14,16,17,18,25,26.
+
+.SH DEFINITIONS
+
+.TP
+\fBCHANNEL\fR
+Integer in range [11-26] indicating one of the IEEE 802.15.4 channels.
+
+.TP
+\fBCOMMISSIONING_PORT\fR
+???
+
+.TP
+\fBEXTENDED_PAN_ID\fR
+???
+
+.TP
+\fBNCP\fR
+Network Control Processor.
+
+.TP
+\fBNETWORK_NAME\fR
+A string identifier of a network, e.g. "HomeNetwork".
+
+.TP
+\fBNODE_TYPE\fR
+WPAN type as one of the following:
+ - 0 (unknown): will starts as 2
+ - 1 (coordinator)
+ - 2 (router)
+ - 3 (end | end-device)
+ - 4 (sleepy | sleepy-end-device)
+ - 5 (mobile | mobile-end-device)
+ - 6 (lurker)
+
+.TP
+\fBPAN_ID\fR
+???
+
+.TP
+\fBPERMIT_JOIN_DURATION\fR
+???unit??
+unit: seconds (sec)
+
+.TP
+\fBPREFERRED_LIFETIME\fR
+???
+unit: seconds (sec)
+(Default: infinite)
+
+.TP
+\fBTIMEOUT\fR
+???
+unit: milliseconds (msec)
+
+.TP
+\fBULA_PREFIX\fR
+A unique local address (ULA) in the block fc00::/7.
+
+.TP
+\fBVALID_LIFETIME\fR
+???
+(Default: infinite)
+
+\" .SH FILES
+\" .TP
+\" .I /etc/wpantund.conf
+\" The default wpantund configuration file.
+
+.SH SEE ALSO
+wpantund(1)
+.SH BUGS
+Bug tracker:
+.IP
+http://...
+.PP
+
+.\" .SH HISTORY
diff --git a/doc/wpantund-oss-plan.md b/doc/wpantund-oss-plan.md
new file mode 100644
index 0000000..e2d7003
--- /dev/null
+++ b/doc/wpantund-oss-plan.md
@@ -0,0 +1,235 @@
+# "wpantund" Open-Source Plan #
+
+This document outlines the resources, processes, and procedures for
+the launch and ongoing operation of the "wpantund" open-source
+project.
+
+## Online Resources ##
+
+ * Github: <https://github.com/openthread/wpantund/>
+ * Public Wiki: <https://github.com/openthread/wpantund/wiki>
+ * Front-end URL: <http://wpantund.org>
+ * Will initially redirect to
+ <https://github.com/openthread/wpantund/#readme>
+ * Content eventually maintained in gh-pages branch.
+ * Mailing Lists
+ * <wpantund-announce@googlegroups.com>
+ * Read-only. Announces releases, security issues, etc.
+ * <wpantund-user@googlegroups.com>
+ * Read-write. For people who are using wpantund.
+ * <wpantund-devel@googlegroups.com>
+ * Read-write. For people who are contributing to wpantund.
+
+## Continuous Integration ##
+
+"wpantund" will use [Travis](https://travis-ci.org/) for continuous
+integration testing. All pull requests MUST pass the travis build test
+before being considered for merging into the master branch.
+
+## Versoning ##
+
+"wpantund" follows the Semantic Versioning guidelines, with one
+exception: the minor and patch versions use a minimum of two digits to
+facilitate better sorting.
+
+In short, the version format is of the form `M.mm.pp`, where `M` is
+the major version, `mm` is the minor version, and `pp` is the patch
+level. Additional suffixes can be appended according to the release
+type, as described in the following section.
+
+## Releases ##
+
+A "release" denotes a specific state of the code base that has been
+officially designated a unique identifier called the version
+(Depending on context, it is sometimes called the release tag). Note
+that this section refers to a several git branches which are defined
+in later sections.
+
+Broadly, there are three types of releases:
+
+**Primary Releases** — Any release in which the release tag takes the
+form of `M.mm.pp`, without any additional annotations. These are the
+canonical releases. There are generally two categories of primary
+releases:
+
+ * **Patch Releases** — Increment only the patch version. Made
+ periodically as needed.
+ * **Major and Minor Releases** — Patch version is always `00`. Used
+ as feature milestones and are planned well in advance.
+
+**Pre-Releases** — Any release leading up to a primary release. There
+are three different types of pre-releases:
+
+ * **Alpha Releases** — which have the suffix `a#`, e.g.: `1.02.03a4`
+ * **Beta Releases** — which have the suffix `b#`, e.g.: `1.02.03b4`
+ * **Release Candidates** — which have the suffix `rc#`, e.g.:
+ `1.02.03rc4`
+
+**Special Releases** — Any release that is intended for a special
+purpose or task. Denoted by the suffix `-*`, e.g. `1.02.03-special`
+or `4.56.78a9-foobar`.
+
+### Release Process Output ###
+
+"Cutting a release" involves the creation and updating of tarballs,
+branches, and tags. The following git tags are created or updated:
+
+ * `<VERSION>` — The identifying tag of the release, pointing to
+ the commit that is being released. The contents of this tag
+ contain the information contained in the CHANGELOG which has been
+ added since the previous release this release was based on. This
+ tag is cryptographically signed with the OpenPGP signature of a
+ project maintainer. Ex: `1.02.03a4`
+ * `full/<VERSION>` - A merge commit between the release tag and the
+ corresponding commit from `autoconf/master` (See the git
+ repository plan later in this document). In other words, this tag
+ points to the actual files that are released in the official
+ tarballs. Created for each of the two above tags (contains
+ autoconf files). This tag is cryptographically signed with the
+ OpenPGP signature of a project maintainer. Ex: `full/1.02.03a4`
+ * `latest-unstable` — Updated to point to the release tag ONLY if
+ the version of this release is larger than the previous version
+ this tag points to. This is a pointer-only tag.
+ * `latest-release` — Updated to point to the release tag ONLY if
+ this release is a primary release and ONLY if version of this
+ release is larger than the previous version this tag points to.
+ This is a pointer-only tag, and MUST NOT contain a message.
+ * `full/latest-unstable` / `full/latest-release` — Created for
+ each of the two above tags (contains autoconf files).
+
+Tarballs are created by checking out the `full/<VERSION>` tag (created
+above) and performing a `./configure && make distcheck`. The resulting
+files are the official tarballs. All released tarballs are
+cryptographically signed with the OpenPGP signature of a maintainer.
+
+### Release Checklist ###
+
+The following is the checklist followed by a project maintainer to cut
+an official release from the top of the master branch:
+
+1. Clone a clean copy of the repository from the official repository
+ on GitHub. If this fails, STOP.
+2. Do a `git checkout master`. If this fails, STOP.
+3. Do a `git show`. Verify that Travis has passed the given commit.
+ If this commit has not passed, STOP.
+4. Collect the changes that have been included since the last release
+ and update the contents of the CHANGELOG accordingly.
+5. Verify that the project version in `.default-version` is set to
+ the version that is about to be released. This should already be
+ the case, but if it isn’t go ahead and update `.default-version`
+ to the version of the release.
+6. Commit the changes made to the working directory from steps 2 and
+ 3\. Use a commit message like `Updated CHANGELOG for release
+ <VERSION>` or `Updated CHANGELOG and configure.ac for release
+ <VERSION>`.
+7. If this is a prerelease, copy the section that you just added to
+ the CHANGELOG to the clipboard. If this is a primary release,
+ copy the contents of the CHANGELOG added after the last primary
+ release to the clipboard.
+8. Create a signed tag for the release named `<VERSION>`, making sure
+ pasting in the contents we copied to the clipboard as the tag
+ message. This is performed with the command `git tag -s
+ <VERSION>`. If this command fails, STOP.
+9. Check out the `origin/scripts` branch: `git checkout
+ origin/scripts`. If this command fails, STOP.
+10. If this is a primary release execute the command
+ `./primary-release-from-master-helper`; or if this is a
+ prerelease execute the command
+ `./pre-release-from-master-helper`. These commands update
+ `autoconf/master`, `full/<VERSION>`, `latest-unstable`,
+ `full/latest-unstable` and (if this is a primary release)
+ `latest-release`, `full/latest-release`. If the command fails,
+ STOP. Note that the tag `full/<VERSION>` will be signed by this
+ process, so you may be asked for your GPG keychain credentials or
+ your token PIN.
+11. Check out the `full/<VERSION>` branch: `git checkout
+ full/<VERSION>`. If this command fails, STOP.
+12. Execute the command `./configure && make distcheck`. If this
+ command fails, STOP.
+13. There should now be at least one tarball (maybe more) in the
+ current directory. If this is not the case, STOP.
+14. Use GPG to sign the tarballs. If this process fails, STOP.
+15. Type `git show master`. Review the commit to make sure it looks
+ sane. If you notice anything wrong, STOP.
+16. Type `git show <VERSION>`. Review the tag notes make they look
+ properly formatted. If you notice anything wrong, STOP.
+17. Push the branches and tags to the origin server: `git push origin
+ master autoconf/master <VERSION> full/<VERSION>`. If this command
+ fails, STOP.
+18. Update the `latest-*` tags on the origin server: `git push origin
+ latest-release latest-unstable full/latest-release
+ full/latest-unstable`
+19. Upload the tarballs and their signatures to the designated
+ location. (Currently TBD)
+20. ???
+21. Pr0fit!!1
+
+Note that the above checklist is only appropriate for cutting releases
+from the master branch! Cutting releases from non-master branches
+would follow a similar (but different) process that is not yet
+defined.
+
+## Public Git Repository Branch and Tag Plan ##
+
+### Branches ###
+
+ * `master` — Main development branch. Acceptable commits are
+ generally limited to those intended for the next major/minor
+ release. Does not contain any autoconf-generated files!
+ * `autoconf/master` — All of (and only!) the autoconf-generated
+ files associated with master. Automatically maintained by a script
+ that checks if a commit to master has invalidated any of these
+ files and commits updates.
+ * `scripts` — A collection of repository maintenance scripts.
+ * `gh-pages` — Will eventually contain the content of
+ <http://wpantund.org/>.
+ * `feature/*` — Feature-specific branches that are currently
+ under development but not yet appropriate for inclusion in master.
+ * `release/M.mm/master` — A separate branch maintained for each
+ minor version release, for tracking things like security updates
+ and back-ported changes. These branches are created when
+ master is opened to taking commits for the next major/minor
+ release.
+
+### Tags ###
+
+ * `M.mm.pp` — Each primary release is tagged with the bare
+ version number of the release.
+ * `M.mm.ppx#` — Each pre-release is tagged with the version of
+ the upcoming release with a suffix `x` denoting the type of
+ pre-release and `#` denoting the count.
+ * `M.mm.pp-x` — Each special-purpose release is tagged with the
+ version of the most recent official release (for any other type),
+ suffixed with a dash and a short descriptor of the release.
+ * `full/*` — For each release (primary, pre, or
+ special-purpose), the tag that is the name of the release prefixed
+ with `full/` points to a merge commit between the release tag and
+ the corresponding commit from `autoconf/master`. In other words,
+ this tag points to the actual files that are released in the
+ official tarballs.
+ * `latest-release` — A tag with no message that points to the tag
+ of the most recent primary release.
+ * `full/latest-release` — A tag with no message that points to
+ the tag of the most recent primary release in `full/*`.
+ * `latest-unstable` — A tag with no message that points to the
+ tag of the most recent primary release or pre-release.
+ * `full/latest-unstable` — A tag with no message that points to
+ the tag of the most recent primary release or pre-release in
+ `full/*`.
+
+### Regarding Autotools ###
+
+No generated autotools files are allowed in master, or in any branch
+that doesn’t begin with `autoconf/` or `full/`.
+
+If you are working from the top of master and don’t have a working
+copy of autotools, the following command will populate your working
+tree with all of the appropriate files and is the functional
+equivalent of typing `./bootstrap.sh` on a machine with autotools
+installed:
+
+ git archive origin/autoconf/master | tar xv
+
+Note that the `full/*` branches contain the full set of files,
+including the sources and autotools files. The `autoconf/*` branches
+contain ONLY the autoconf files.
diff --git a/doc/wpantund.1 b/doc/wpantund.1
new file mode 100644
index 0000000..28b56ea
--- /dev/null
+++ b/doc/wpantund.1
@@ -0,0 +1,97 @@
+.TH wpantund 1 "" "" "USER COMMANDS"
+
+.SH NAME
+wpantund \- interface to 6LoWPAN communication
+
+.SH SYNOPSIS
+.B wpantund
+[\fIOPTIONS\fR]
+
+.SH DESCRIPTION
+.B wpantund
+is a userspace driver which uses the Linux TUN driver (or the UTUN driver on OS X)
+to present a network interface for 6LoWPAN communication. It communicates with the
+NCP via a socket, which can be any of the following:
+.TP
+\- a TCP socket
+
+.TP
+\- a serial port
+
+.TP
+\- stdin and stdout from a subprocess
+
+.SH OPTIONS
+
+.TP
+\fB\-h\fP, \fB\-\-help\fp
+Print help.
+
+.TP
+\fB\-v\fP, \fB\-\-version\fp
+Print version.
+
+.TP
+\fB\-d\fP, \fB\-\-debug\fp \fILEVEL
+Enable debugging mode (see \fBDEBUGGING\fP below).
+
+.TP
+\fB\-c\fP, \fB\-\-config\fp \fIFILE
+Specify config file (default /etc/wpantund.conf).
+
+.TP
+\fB\-s\fP, \fB\-\-socket\fp \fIFILE
+Specify socket file; same as \fI-o NCPSocketName\fR.
+
+.TP
+\fB\-b\fP, \fB\-\-baudrate\fp \fIFILE
+Specify baudrate; same as \fI-o NCPSocketBaud\fR.
+
+.TP
+\fB\-I\fP, \fB\-\-interface\fp \fIFILE
+Specify network interface; same as \fI-o WPANInterfaceName\fR.
+
+.TP
+\fB\-o\fP, \fB\-\-option\fp \fIWPAN_OPTIONS
+Overwrites config file options.
+
+ -- NCPSocketName \fIFILE\fR
+ Specify socket location (e.g. /dev/ttyUSB0).
+
+ -- WPANInterfaceName \fIINTERFACE\fR
+ Specify the name of the created network interface (e.g. wpan0).
+
+ -- SyslogMask \fIMASK\fR
+ To add more logs, start \fBwpantund\fP with SyslogMask all.
+
+ -- PIDFile \fIFILE\fR
+ Specify location of the file with the wpan-tunnel-daemon PID.
+
+ -- NCPReliabilityLayer
+ Specify a serial reliability layer, \fBlibsoot\fP or \fBnone\fP.
+
+ -- NCPSocketBaud
+
+.SH DEBUGGING
+
+
+.SH EXAMPLES
+
+.TP
+$ sudo wpantund -o NCPSocketName /dev/ttyUSB0 -o WPANInterfaceName wpan0
+Starts wpantund on /dev/ttyUSB0 and create network intarfeca called wpan0.
+
+.SH FILES
+.TP
+.I /etc/wpantund.conf
+The default wpantund configuration file.
+
+.SH SEE ALSO
+wpanctl(1)
+.SH BUGS
+Bug tracker:
+.IP
+http://...
+.PP
+
+.\" .SH HISTORY \" Document history if command behaves in a unique manner
diff --git a/doxygen.cfg.in b/doxygen.cfg.in
new file mode 100644
index 0000000..a301174
--- /dev/null
+++ b/doxygen.cfg.in
@@ -0,0 +1,1808 @@
+# Doxyfile 1.8.2
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or sequence of words) that should
+# identify the project. Note that if you do not use Doxywizard you need
+# to put quotes around the project name if it contains spaces.
+
+PROJECT_NAME = "@PACKAGE@"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF = "Wireless Network Interface Daemon for Low-Power Wireless SoCs"
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = doc
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip. Note that you specify absolute paths here, but also
+# relative paths, which will be relative from the directory where doxygen is
+# started.
+
+STRIP_FROM_PATH = @top_srcdir@
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful if your file system
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding
+# "class=itcl::class" will allow you to use the command class in the
+# itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension,
+# and language is one of the parsers supported by doxygen: IDL, Java,
+# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C,
+# C++. For instance to make doxygen treat .inc files as Fortran files (default
+# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note
+# that for custom extensions you also need to set FILE_PATTERNS otherwise the
+# files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
+# comments according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you
+# can mix doxygen, HTML, and XML commands with Markdown formatting.
+# Disable only in case of backward compatibilities issues.
+
+MARKDOWN_SUPPORT = YES
+
+# When enabled doxygen tries to link words that correspond to documented classes,
+# or namespaces to their corresponding documentation. Such a link can be
+# prevented in individual cases by by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also makes the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter and setter methods for a property. Setting this option to YES (the default) will make doxygen replace the get and set methods by a property in the documentation. This will only work if the methods are indeed getting or setting a simple type. If this is not the case, or you want to show the methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
+# unions are shown inside the group in which they are included (e.g. using
+# @ingroup) instead of on a separate page (for HTML and Man pages) or
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
+# unions with only public data fields will be shown inline in the documentation
+# of the scope in which they are defined (i.e. file, namespace, or group
+# documentation), provided this scope is documented. If set to NO (the default),
+# structs, classes, and unions are shown on a separate page (for HTML and Man
+# pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penalty.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will roughly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+SYMBOL_CACHE_SIZE = 0
+
+# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
+# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
+# their name and scope. Since this can be an expensive process and often the
+# same symbol appear multiple times in the code, doxygen keeps a cache of
+# pre-resolved symbols. If the cache is too small doxygen will become slower.
+# If the cache is too large, memory is wasted. The cache size is given by this
+# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or macro consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and macros in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files
+# containing the references data. This must be a list of .bib files. The
+# .bib extension is automatically appended if omitted. Using this command
+# requires the bibtex tool to be installed. See also
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
+# feature you need bibtex and perl available in the search path.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = @top_srcdir@ @top_srcdir@/src/wpantund @top_srcdir@/src/wpanctl @top_srcdir@/src/ncp-spinel @top_srcdir@/src/ncp-dummy @top_srcdir@/src/ipc-dbus @top_srcdir@/src/utils
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C, C++ and Fortran comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header. Note that when using a custom header you are responsible
+# for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is advised to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If left blank doxygen will
+# generate a default style sheet. Note that it is recommended to use
+# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this
+# tag will in the future become obsolete.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional
+# user-defined cascading style sheet that is included after the standard
+# style sheets created by doxygen. Using this option one can overrule
+# certain style aspects. This is preferred over using HTML_STYLESHEET
+# since it does not replace the standard style sheet and is therefor more
+# robust against future updates. Doxygen will copy the style sheet file to
+# the output directory.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the style sheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
+# entries shown in the various tree structured indices initially; the user
+# can expand and collapse entries dynamically later on. Doxygen will expand
+# the tree to such a level that at most the specified number of entries are
+# visible (unless a fully collapsed tree already exceeds this amount).
+# So setting the number of entries 1 will produce a full collapsed tree by
+# default. 0 is a special value representing an infinite number of entries
+# and will result in a full expanded tree by default.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely
+# identify the documentation publisher. This should be a reverse domain-name
+# style string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+# will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
+# at top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it. Since the tabs have the same information as the
+# navigation tree you can set this option to NO if you already set
+# GENERATE_TREEVIEW to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+# Since the tree basically has the same information as the tab index you
+# could consider to set DISABLE_INDEX to NO when enabling this option.
+
+GENERATE_TREEVIEW = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you may also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to
+# the MathJax Content Delivery Network so you can quickly see the result without
+# installing MathJax.
+# However, it is strongly recommended to install a local
+# copy of MathJax from http://www.mathjax.org before deployment.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a PHP enabled web server instead of at the web client
+# using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server
+# based approach is that it scales better to large projects and allows
+# full text search. The disadvantages are that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load style sheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. For each
+# tag file the location of the external documentation should be added. The
+# format of a tag file without this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths
+# or URLs. Note that each tag file must have a unique name (where the name does
+# NOT include the path). If a tag file is not located in the directory in which
+# doxygen is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS = 0
+
+# By default doxygen will use the Helvetica font for all dot files that
+# doxygen generates. When you want a differently looking font you can specify
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find
+# the font, which can be done by putting it in a standard location or by setting
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the Helvetica font.
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
+# set the path where dot can find it.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside
+# the class node. If there are many fields or methods and many nodes the
+# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
+# threshold limits the number of items for each type to make the size more
+# managable. Set this to 0 for no limit. Note that the threshold may be
+# exceeded by 50% before the limit is enforced.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used. If you choose svg you need to set
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible in IE 9+ (other browsers do not have this requirement).
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+# Note that this requires a modern browser other than Internet Explorer.
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG = NO
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
diff --git a/etc/Dockerfile b/etc/Dockerfile
new file mode 100644
index 0000000..f2baee1
--- /dev/null
+++ b/etc/Dockerfile
@@ -0,0 +1,52 @@
+#
+# Copyright (c) 2016 Nest Labs, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+FROM ubuntu:trusty
+
+ENV CONNMAN_INCLUDE_ARCHIVE=https://gist.github.com/darconeous/d1d9bc39e0758e45a1d7/raw/ef9b01ac378a9b2e92031c846c4f6b5f94abab53/connman-include.tar.bz2
+
+RUN apt-get -y update \
+ && DEBIAN_FRONTEND=noninteractive \
+ apt-get install -y -q --no-install-recommends \
+ libglib2.0-dev \
+ libdbus-1-dev \
+ libdbus-1-dev \
+ libreadline-dev \
+ libtool \
+ autoconf-archive \
+ dbus \
+ xtables-addons-source \
+ net-tools \
+ usbutils \
+ vim \
+ man \
+ bsdtar \
+ gcc g++ \
+ pkg-config \
+ autoconf \
+ autoconf-archive \
+ automake
+
+ADD $CONNMAN_INCLUDE_ARCHIVE /
+
+RUN apt-get -y update \
+ && DEBIAN_FRONTEND=noninteractive \
+ apt-get install -y -q --no-install-recommends \
+ libboost-dev \
+ libboost-signals-dev
+
+RUN tar xvjf /connman-include.tar.bz2 -C / && rm /connman-include.tar.bz2
diff --git a/etc/autoandr/autoandr b/etc/autoandr/autoandr
new file mode 100755
index 0000000..c86705f
--- /dev/null
+++ b/etc/autoandr/autoandr
@@ -0,0 +1,1165 @@
+#!/bin/bash
+#
+# Copyright (c) 2016 Nest Labs, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# ---------------------------------------------------------------------------
+#
+# AUTOANDR v0.1
+# =============
+#
+# Autoandr is a tool for easily generating `Android.mk` files for
+# autotools-based projects.
+#
+
+
+# todo: add support for LOCAL_COPY_HEADERS_TO and LOCAL_COPY_HEADERS
+
+# -- CONSTANTS --------------------------------------------------------------
+
+AUTOANDR_VERSION=0.00.01
+
+AUTOANDR_CFLAGS_SUFFIX=.andr_cflags
+AUTOANDR_CXX_FEATURES_SUFFIX=.andr_cxxfeatures
+AUTOANDR_INCLUDEPATH_SUFFIX=.andr_includes
+AUTOANDR_SOURCE_SUFFIX=.andr_source
+AUTOANDR_AIDL_SUFFIX=.andr_aidl
+
+AUTOANDR_MAKE_FLAGS=
+
+if [ -t 1 ]
+then
+ export ESC_BOLD=${ESC_BOLD-`printf '\033[0;1m'`} # '
+ export ESC_NORMAL=${ESC_NORMAL-`printf '\033[0m'`} # '
+fi
+
+export AUTOANDR_DIR=${AUTOANDR_DIR-`cd "$(dirname $0)" && pwd`}
+export SOURCE_DIR=${SOURCE_DIR-`pwd`}
+export BUILD_DIR=${BUILD_DIR-${SOURCE_DIR}/etc/android}
+export DESTDIR=${DESTDIR-${BUILD_DIR}/root}
+
+export V=${V-0}
+
+# -- FUNCS AND UTILS --------------------------------------------------------
+
+die() {
+ echo " *** ${ESC_BOLD}Fatal Error${ESC_NORMAL} $*" > /dev/stderr
+ exit 1
+}
+
+show_version() {
+ echo "autoandr ${AUTOANDR_VERSION}"
+}
+
+announce_pass() {
+ echo " *** ${ESC_BOLD}${*}${ESC_NORMAL}"
+}
+
+announce_tool() {
+ local tool=$1
+ shift
+ echo " * ${ESC_BOLD}${tool}${ESC_NORMAL} $*"
+}
+
+announce_path() {
+ echo " ** ${ESC_BOLD}path${ESC_NORMAL} $*"
+}
+
+
+source_pwd() {
+ echo "${SOURCE_DIR}/$(proj_pwd)"
+}
+
+library_converter() {
+ while [[ $# -ge 1 ]]
+ do
+ case $1 in
+ dbus-1) echo dbus ;;
+ util) ;;
+ *) echo $1 ;;
+ esac
+ shift
+ done
+}
+
+proj_path() {
+ local tmp="$*"
+ tmp="${tmp#$BUILD_DIR}"
+ tmp="${tmp#$SOURCE_DIR}"
+ echo "${tmp#/}"
+}
+
+proj_pwd() {
+ proj_path `pwd`
+}
+
+full_real_path() {
+ local dir_name=`dirname $1`
+ local base_name=`basename $1`
+ if test -d $dir_name
+ then printf "%s/%s\n" "$(cd $dir_name && pwd)" "$base_name"
+ else echo $1
+ fi
+}
+
+adjust_include_path() {
+ includedir=$(full_real_path "${1}")
+ rel_includedir="$(rel_path ${includedir})"
+
+ [ -z "${rel_includedir}" ] && continue
+ if [ "${rel_includedir::1}" = "." ]
+ then rel_includedir='$(LOCAL_PATH)/'"${rel_includedir}"
+ fi
+
+ if test "${includedir#$SOURCE_DIR}" == "${includedir}"
+ then rel_includedir="${includedir#$ANDROID_BUILD_TOP/}"
+ fi
+ echo "${rel_includedir}"
+}
+
+rel_path() {
+ local target=$(cd `dirname "${1}"` 2>/dev/null && pwd || dirname "${1}" )/`basename "${1}"`
+ local common_part=`pwd`
+ local result=""
+
+ if [[ "${target:0:1}" == "/" ]]
+ then
+ while [[ "${target#$common_part}" == "${target}" ]]; do
+ # no match, means that candidate common part is not correct
+ # go up one level (reduce common part)
+ common_part="$(dirname $common_part)"
+ # and record that we went back, with correct / handling
+ if [[ -z $result ]]; then
+ result=".."
+ else
+ result="../$result"
+ fi
+ done
+
+ if [[ $common_part == "/" ]]; then
+ # special case for root (no common path)
+ result="$result/"
+ fi
+
+ # since we now have identified the common part,
+ # compute the non-common part
+ forward_part="${target#$common_part}"
+
+ # and now stick all parts together
+ if [[ -n $result ]] && [[ -n $forward_part ]]; then
+ result="$result$forward_part"
+ elif [[ -n $forward_part ]]; then
+ # extra slash removal
+ result="${forward_part:1}"
+ fi
+ else
+ result="${target}"
+ fi
+
+ echo $result
+}
+
+# This function checks the arguments that would be passed to a `cc`-like
+# program to see if the output is going to be an executable or an object
+# file. This is needed because autotools uses `cc` as a linker when making
+# executables. This function allows us to quickly determine the intent.
+is_ccld() {
+ while [[ $# -ge 1 ]]
+ do
+ case $1 in
+ -c)
+ return 1 # false
+ ;;
+ esac
+ shift
+ done
+
+ return 0 # true
+}
+
+# ---------------------------------------------------------------------------
+
+androidmake_prep() {
+ local parentdir
+
+ if ! [ -f Android.mk ]
+ then
+ (
+ echo "# File automatically generated by $(show_version)"
+ echo "# \"`proj_pwd`\""
+ echo "#"
+ echo
+ echo 'LOCAL_PATH := $(call my-dir)'
+ ) > Android.mk
+
+ localpath="$(pwd)"
+ parentdir="$(cd .. && pwd)"
+
+ if [[ "$(cd $BUILD_DIR/.. && pwd)" != "${parentdir}" ]] && [[ "${SOURCE_DIR}" != "${parentdir}" ]] && [[ "${SOURCE_DIR}" != "${localpath}" ]]
+ then
+ (cd .. && androidmake_prep)
+ grep -q all-subdir-makefiles ../Android.mk || echo 'include $(call all-subdir-makefiles)' >> ../Android.mk
+ fi
+ fi
+}
+
+# Arguments: <object-name> <source-file>
+androidmake_object_begin() {
+ ANDROIDMAKE_OBJECT_NAME=$1
+ ANDROIDMAKE_SOURCE_FILE=$2
+
+ if [ -f "${ANDROIDMAKE_SOURCE_FILE}${AUTOANDR_AIDL_SUFFIX}" ]
+ then
+ announce_tool aidl-object `basename ${ANDROIDMAKE_OBJECT_NAME}`: $(basename $2)
+ cp "${ANDROIDMAKE_SOURCE_FILE}${AUTOANDR_AIDL_SUFFIX}" "${ANDROIDMAKE_OBJECT_NAME}"${AUTOANDR_AIDL_SUFFIX}
+ cp "${ANDROIDMAKE_SOURCE_FILE}${AUTOANDR_INCLUDEPATH_SUFFIX}" "${ANDROIDMAKE_OBJECT_NAME}"${AUTOANDR_INCLUDEPATH_SUFFIX}
+ else
+ announce_tool object `basename ${ANDROIDMAKE_OBJECT_NAME}`: $(basename $2)
+ echo "$2" > "${ANDROIDMAKE_OBJECT_NAME}"${AUTOANDR_SOURCE_SUFFIX}
+ fi
+}
+
+# Arguments: <c-flags>
+androidmake_object_cflags() {
+ [ "${ANDROIDMAKE_OBJECT_NAME}" != "" ] || die "Internal error"
+ echo "$@" >> "${ANDROIDMAKE_OBJECT_NAME}"${AUTOANDR_CFLAGS_SUFFIX}
+}
+
+# Arguments: <c++-features>
+androidmake_object_cxx_features() {
+ [ "${ANDROIDMAKE_OBJECT_NAME}" != "" ] || die "Internal error"
+ echo "$@" >> "${ANDROIDMAKE_OBJECT_NAME}"${AUTOANDR_CXX_FEATURES_SUFFIX}
+}
+
+# Arguments: <header-include-paths>
+androidmake_object_include_paths() {
+ [ "${ANDROIDMAKE_OBJECT_NAME}" != "" ] || die "Internal error"
+ if ! [ -f "${ANDROIDMAKE_SOURCE_FILE}${AUTOANDR_AIDL_SUFFIX}" ]
+ then echo "$@" >> "${ANDROIDMAKE_OBJECT_NAME}"${AUTOANDR_INCLUDEPATH_SUFFIX}
+ fi
+}
+
+androidmake_object_end() {
+ [ "${ANDROIDMAKE_OBJECT_NAME}" != "" ] || die "Internal error"
+ unset ANDROIDMAKE_OBJECT_NAME
+ unset ANDROIDMAKE_SOURCE_FILE
+}
+
+
+
+# Arguments: <source-name> <aidl-file>
+androidmake_aidl_begin() {
+ ANDROIDMAKE_AIDL_OUTPUT=$1
+ ANDROIDMAKE_AIDL_INPUT=$2
+ announce_tool aidl `basename ${ANDROIDMAKE_AIDL_INPUT}`
+
+ mkdir -p `dirname ${ANDROIDMAKE_AIDL_OUTPUT}` || die "Unable to mkdir `dirname ${ANDROIDMAKE_AIDL_OUTPUT}`"
+ echo "${ANDROIDMAKE_AIDL_INPUT}" > "${ANDROIDMAKE_AIDL_OUTPUT}"${AUTOANDR_AIDL_SUFFIX}
+}
+
+# Arguments: <header-dir>
+androidmake_aidl_header_dir() {
+ [ "${ANDROIDMAKE_AIDL_OUTPUT}" != "" ] || die "Internal error"
+ [ "${ANDROIDMAKE_AIDL_INPUT}" != "" ] || die "Internal error"
+ # Nothing to do here?
+}
+
+# Arguments: <aidl-include-paths>*
+androidmake_aidl_include_paths() {
+ [ "${ANDROIDMAKE_AIDL_INPUT}" != "" ] || die "Internal error"
+ [ "${ANDROIDMAKE_AIDL_OUTPUT}" != "" ] || die "Internal error"
+ echo $* >> "${ANDROIDMAKE_AIDL_OUTPUT}"${AUTOANDR_INCLUDEPATH_SUFFIX}
+}
+
+androidmake_aidl_end() {
+ [ "${ANDROIDMAKE_AIDL_INPUT}" != "" ] || die "Internal error"
+ [ "${ANDROIDMAKE_AIDL_OUTPUT}" != "" ] || die "Internal error"
+ unset ANDROIDMAKE_AIDL_OUTPUT
+ unset ANDROIDMAKE_AIDL_INPUT
+}
+
+
+
+# Arguments: <module-name>
+androidmake_module_begin() {
+ ANDROIDMAKE_MODULE_NAME=$1
+ androidmake_prep
+ (
+ echo ''
+ echo "#### BEGIN ${ANDROIDMAKE_MODULE_NAME} ####"
+ echo 'include $(CLEAR_VARS)'
+ echo "LOCAL_MODULE := ${ANDROIDMAKE_MODULE_NAME}"
+ ) >> $ANDROIDMAKE_MODULE_NAME.Android.mk
+ rm -f $ANDROIDMAKE_MODULE_NAME.Android.mk.tmp || die
+}
+
+androidmake_module_tags() {
+ [ "${ANDROIDMAKE_MODULE_NAME}" != "" ] || die "Internal error"
+ (
+ echo 'LOCAL_MODULE_TAGS +=' "$@"
+ ) >> $ANDROIDMAKE_MODULE_NAME.Android.mk.tmp
+}
+
+androidmake_module_dependency() {
+ [ "${ANDROIDMAKE_MODULE_NAME}" != "" ] || die "Internal error"
+ (
+ echo "LOCAL_ADDITIONAL_DEPENDENCIES +=" $1
+ ) >> $ANDROIDMAKE_MODULE_NAME.Android.mk.tmp
+}
+
+androidmake_module_path_64() {
+ [ "${ANDROIDMAKE_MODULE_NAME}" != "" ] || die "Internal error"
+ (
+ echo "LOCAL_MODULE_PATH_64 := \$(PRODUCT_OUT)$1"
+ ) >> $ANDROIDMAKE_MODULE_NAME.Android.mk
+}
+
+androidmake_module_link_shared_library() {
+ [ "${ANDROIDMAKE_MODULE_NAME}" != "" ] || die "Internal error"
+ (
+ echo "LOCAL_SHARED_LIBRARIES +=" $1
+ ) >> $ANDROIDMAKE_MODULE_NAME.Android.mk.tmp
+}
+
+androidmake_module_link_static_library() {
+ [ "${ANDROIDMAKE_MODULE_NAME}" != "" ] || die "Internal error"
+ (
+ echo "LOCAL_STATIC_LIBRARIES +=" $1
+ ) >> $ANDROIDMAKE_MODULE_NAME.Android.mk.tmp
+}
+
+# Arguments: <object-name>
+androidmake_module_add_object() {
+ [ "${ANDROIDMAKE_MODULE_NAME}" != "" ] || die "Internal error"
+ object=$1
+ if [ -f ${object}${AUTOANDR_AIDL_SUFFIX} ]
+ then
+ source_file=`rel_path $(cat ${object}${AUTOANDR_AIDL_SUFFIX})`
+ (
+ echo "LOCAL_SRC_FILES +=" ${source_file}
+ for includedir in $(cat ${object}${AUTOANDR_INCLUDEPATH_SUFFIX})
+ do
+ echo "LOCAL_AIDL_INCLUDES += $(adjust_include_path "$includedir")"
+ done
+ ) >> $ANDROIDMAKE_MODULE_NAME.Android.mk.tmp
+ else
+ source_file=`rel_path $(cat ${object}${AUTOANDR_SOURCE_SUFFIX})`
+ (
+ echo "LOCAL_SRC_FILES +=" ${source_file}
+ if [ "${source_file%.cpp}" != "${source_file}" ]
+ then # C++ File
+ cat ${object}${AUTOANDR_CFLAGS_SUFFIX} | sed "s/\\\\\"/'\\\\\"'/g;" | xargs -n 1 echo "LOCAL_CPPFLAGS +="
+ else # C file
+ cat ${object}${AUTOANDR_CFLAGS_SUFFIX} | sed "s/\\\\\"/'\\\\\"'/g;" | xargs -n 1 echo "LOCAL_CFLAGS +="
+ fi
+ for includedir in $(cat ${object}${AUTOANDR_INCLUDEPATH_SUFFIX})
+ do
+ echo "LOCAL_C_INCLUDES += $(adjust_include_path "$includedir")"
+ done
+ cat ${object}${AUTOANDR_CXX_FEATURES_SUFFIX} | xargs -n 1 echo "LOCAL_CPP_FEATURES +="
+ ) >> $ANDROIDMAKE_MODULE_NAME.Android.mk.tmp
+ fi
+}
+
+androidmake_module_allow_shlib_undefined() {
+ [ "${ANDROIDMAKE_MODULE_NAME}" != "" ] || die "Internal error"
+ (
+ echo "LOCAL_ALLOW_UNDEFINED_SYMBOLS := true"
+ ) >> $ANDROIDMAKE_MODULE_NAME.Android.mk.tmp
+}
+
+androidmake_module_end_exec() {
+ [ "${ANDROIDMAKE_MODULE_NAME}" != "" ] || die "Internal error"
+ (
+ grep LOCAL_STATIC_LIBRARIES $ANDROIDMAKE_MODULE_NAME.Android.mk.tmp
+ sort -u $ANDROIDMAKE_MODULE_NAME.Android.mk.tmp | grep -v LOCAL_STATIC_LIBRARIES
+ echo 'include $(BUILD_EXECUTABLE)'
+ echo "#### END ${ANDROIDMAKE_MODULE_NAME} ####"
+ ) >> $ANDROIDMAKE_MODULE_NAME.Android.mk
+ rm -f $ANDROIDMAKE_MODULE_NAME.Android.mk.tmp
+ #lockfile -1 -r 3 Android.mk.lock || die Lock failure
+ cat $ANDROIDMAKE_MODULE_NAME.Android.mk >> Android.mk
+ #rm -fr Android.mk.lock
+ rm -f $ANDROIDMAKE_MODULE_NAME.Android.mk
+ unset ANDROIDMAKE_MODULE_NAME
+}
+
+androidmake_module_end_shared_lib() {
+ [ "${ANDROIDMAKE_MODULE_NAME}" != "" ] || die "Internal error"
+ (
+ grep LOCAL_STATIC_LIBRARIES $ANDROIDMAKE_MODULE_NAME.Android.mk.tmp
+ sort -u $ANDROIDMAKE_MODULE_NAME.Android.mk.tmp | grep -v LOCAL_STATIC_LIBRARIES
+ echo 'include $(BUILD_SHARED_LIBRARY)'
+ echo "#### END ${ANDROIDMAKE_MODULE_NAME} ####"
+ ) >> $ANDROIDMAKE_MODULE_NAME.Android.mk
+ rm -f $ANDROIDMAKE_MODULE_NAME.Android.mk.tmp
+ #lockfile -1 -r 3 Android.mk.lock || die Lock failure
+ cat $ANDROIDMAKE_MODULE_NAME.Android.mk >> Android.mk
+ #rm -fr Android.mk.lock
+ rm -f $ANDROIDMAKE_MODULE_NAME.Android.mk
+ unset ANDROIDMAKE_MODULE_NAME
+}
+
+androidmake_module_end_static_lib() {
+ [ "${ANDROIDMAKE_MODULE_NAME}" != "" ] || die "Internal error"
+ (
+ grep LOCAL_STATIC_LIBRARIES $ANDROIDMAKE_MODULE_NAME.Android.mk.tmp
+ sort -u $ANDROIDMAKE_MODULE_NAME.Android.mk.tmp | grep -v LOCAL_STATIC_LIBRARIES
+ echo 'include $(BUILD_STATIC_LIBRARY)'
+ echo "#### END ${ANDROIDMAKE_MODULE_NAME} ####"
+ ) >> $ANDROIDMAKE_MODULE_NAME.Android.mk
+ rm -f $ANDROIDMAKE_MODULE_NAME.Android.mk.tmp
+ #lockfile -1 -r 3 Android.mk.lock || die Lock failure
+ cat $ANDROIDMAKE_MODULE_NAME.Android.mk >> Android.mk
+ #rm -fr Android.mk.lock
+ rm -f $ANDROIDMAKE_MODULE_NAME.Android.mk
+ unset ANDROIDMAKE_MODULE_NAME
+}
+
+# -- ARGUMENT PARSERS ------------------------------------------------------
+
+handle_cc() {
+ if [[ ${AUTOANDR_MODE} == "make" ]]
+ then (
+
+ INCLUDE_PATHS=
+ SOURCES=
+ CFLAGS=
+ OUTPUT=
+ CXX_FEATURES=
+ DEPENDS="${AUTOANDR_DEPENDS}"
+
+ while [[ $# -ge 1 ]]
+ do
+ case $1 in
+ -include)
+ CFLAGS="${CFLAGS} $1 $2"
+ shift
+ ;;
+
+ -I*|-i*)
+ INCLUDE_PATHS="${INCLUDE_PATHS} ${1:2}"
+ ;;
+
+ --AUTOANDR-DEPENDS,*|--AUTOANDR-DEPENDS=*)
+ DEPENDS="${DEPENDS} ${1:19}"
+ ;;
+
+ -frtti|-fexceptions)
+ # For some reason, the LOCAL_CPP_FEATURES
+ # variable doesn't seem to be working, so
+ # we just pass these as normal CFLAGS.
+ #CXX_FEATURES="${CXX_FEATURES} ${1:2}"
+ CFLAGS="${CFLAGS} $(printf "%q" "$1")"
+ ;;
+
+ -Werror)
+ # Ignore -Werror, if present.
+ ;;
+
+ -f*|-W*|-D*|-U*|-pthread|-std=*|-O[0-9]|-pedantic-*)
+ CFLAGS="${CFLAGS} $(printf "%q" "$1")"
+ ;;
+
+ -o)
+ shift
+ OUTPUT="$1"
+ ;;
+
+ *.c|*.cpp)
+ SOURCES="${SOURCES} $1"
+ ;;
+
+ -g|-O[0-9]|-c)
+ # Ignore these
+ ;;
+
+ *)
+ echo " $# UNKNOWN \"$1\""
+ ;;
+ esac
+ shift
+ done
+ if [ -z "${OUTPUT}" ]
+ then return 0
+ fi
+
+ touch "${OUTPUT}"
+
+ androidmake_object_begin ${OUTPUT} ${SOURCES}
+ androidmake_object_cflags "${CFLAGS}"
+ androidmake_object_cxx_features "${CXX_FEATURES}"
+ androidmake_object_include_paths "${INCLUDE_PATHS}"
+ androidmake_object_end
+
+ ) >&3
+ elif [[ ${AUTOANDR_MODE} == "install" ]]
+ then true
+ else false
+ fi
+}
+
+handle_ccld() {
+ if [[ ${AUTOANDR_MODE} == "make" ]]
+ then (
+ OBJECTS=
+ OUTPUT=
+ LIBRARIES=
+ STATIC_LIBRARIES=
+ CFLAGS=
+ OUTPUT_SHARED_LIBRARY=0
+ ALLOW_SHLIB_UNDEFINED=1
+ DEPENDS="${AUTOANDR_DEPENDS}"
+ TAGS=${AUTOANDR_MODULE_TAGS}
+ while [[ $# -ge 1 ]]
+ do
+ case $1 in
+ -o)
+ shift
+ OUTPUT="$1"
+ ;;
+ -shared)
+ OUTPUT_SHARED_LIBRARY=1
+ ;;
+ -Wl,--allow-shlib-undefined)
+ ALLOW_SHLIB_UNDEFINED=1
+ ;;
+ -Wl*)
+ # Linker stuff. Ignore for now.
+ ;;
+ --AUTOANDR-MODULE-TAG=*)
+ TAGS="${TAGS} ${1:25}"
+ ;;
+ --AUTOANDR-DEPENDS,*|--AUTOANDR-DEPENDS=*)
+ DEPENDS="${DEPENDS} ${1:19}"
+ ;;
+ --AUTOANDR-MODULE-PATH-64=*)
+ AUTOANDR_MODULE_PATH_64="${1:26}"
+ ;;
+ --AUTOANDR,-l*)
+ LIBRARIES="${LIBRARIES} ${1:13}"
+ ;;
+ -l*)
+ LIBRARIES="${LIBRARIES} ${1:2}"
+ ;;
+ *.so|*.la)
+ lib=${1:2}
+ lib=$(basename ${lib%.so})
+ lib=$(basename ${lib%.la})
+ LIBRARIES="${LIBRARIES} $lib"
+ ;;
+ -f*|-W*|-U*|-D*|-pthread|-pedantic-*)
+ CFLAGS="${CFLAGS} ${1}"
+ ;;
+ -L*|-I*)
+ # Ignore library and header search paths
+ ;;
+ *.a)
+ STATIC_LIBRARIES="${STATIC_LIBRARIES} $1"
+ ;;
+ *.o|*.lo)
+ OBJECTS="${OBJECTS} $1"
+ ;;
+ -g|-O[0-9]|-c|-std=*)
+ # Ignore these
+ ;;
+ -V)
+ # Version query.
+ return 0
+ ;;
+ --AUTOANDR*)
+ echo " >>> Unknown autoandr argument $1"
+ ;;
+ *)
+ echo " $# UNKNOWN \"$1\""
+ ;;
+ esac
+ shift
+ done
+
+ if [ "${OUTPUT}" != "${OUTPUT%.so}" ] || [ "${OUTPUT}" != "${OUTPUT%.so.0.0.0}" ]
+ then OUTPUT_SHARED_LIBRARY=1
+ fi
+
+ OUTPUT=${OUTPUT%.so.0.0.0}
+ OUTPUT=${OUTPUT%.so}
+ OUTPUT=$(basename $OUTPUT)
+
+ announce_tool link "${OUTPUT}"
+
+ androidmake_module_begin ${OUTPUT}
+ if test "${AUTOANDR_MODULE_PATH_64}" != ""
+ then androidmake_module_path_64 "${AUTOANDR_MODULE_PATH_64}"
+ fi
+ for tag in ${TAGS}
+ do androidmake_module_tags ${tag}
+ done
+ for object in ${OBJECTS}
+ do androidmake_module_add_object ${object}
+ done
+ for depend in $(library_converter ${DEPENDS})
+ do androidmake_module_dependency ${depend}
+ done
+ for lib in $(library_converter ${LIBRARIES})
+ do androidmake_module_link_shared_library lib${lib#lib}
+ done
+ for lib in ${STATIC_LIBRARIES}
+ do androidmake_module_link_static_library $(basename ${lib%.a})
+ done
+ if [ "${OUTPUT_SHARED_LIBRARY}" = "1" ]
+ then
+ [ "${ALLOW_SHLIB_UNDEFINED}" = "1" ] && androidmake_module_allow_shlib_undefined
+ androidmake_module_end_shared_lib
+ else androidmake_module_end_exec
+ fi
+
+ ) >&3
+ elif [[ ${AUTOANDR_MODE} == "install" ]]
+ then true
+ else false
+ fi
+}
+
+handle_libtool() {
+ # We use this to extract library arguments when building static libraries.
+
+ if [[ ${AUTOANDR_MODE} == "make" ]]
+ then (
+ COMMAND="${AUTOANDR_LIBTOOL} $@"
+ export AUTOANDR_LIBTOOL_LIBS=
+ export AUTOANDR_DEPENDS=
+ export AUTOANDR_MODULE_PATH_64=
+ while [[ $# -ge 1 ]]
+ do
+ case $1 in
+ -l*)
+ AUTOANDR_LIBTOOL_LIBS="${AUTOANDR_LIBTOOL_LDFLAGS} ${1:2}"
+ COMMAND="${COMMAND} --AUTOANDR,$1"
+ ;;
+ --AUTOANDR-DEPENDS,*|--AUTOANDR-DEPENDS=*)
+ AUTOANDR_DEPENDS="${AUTOANDR_DEPENDS} ${1:19}"
+ ;;
+ --AUTOANDR-MODULE-PATH-64=*)
+ AUTOANDR_MODULE_PATH_64="${1:26}"
+ ;;
+ --AUTOANDR*)
+ echo " >>> Unknown autoandr argument $1"
+ ;;
+ *)
+ ;;
+ esac
+ shift
+ done
+
+ ${COMMAND} "$@" >&4
+
+ true
+ ) 4>&1 >&3
+ elif [[ ${AUTOANDR_MODE} == "install" ]]
+ then true
+ else false
+ fi
+}
+
+
+handle_aidl_cpp() {
+ if [[ ${AUTOANDR_MODE} == "make" ]]
+ then (
+ INPUT_FILE=
+ HEADER_DIR=
+ OUTPUT_FILE=
+ INCLUDE_PATHS=
+
+ while [[ $# -ge 1 ]]
+ do
+ case $1 in
+ -I*|-i*)
+ INCLUDE_PATHS="${INCLUDE_PATHS} ${1:2}"
+ ;;
+
+ *.cxx|*.cpp)
+ OUTPUT_FILE="$1"
+ ;;
+
+ *.aidl)
+ INPUT_FILE="$1"
+ ;;
+
+ -g|-O[0-9]|-c)
+ # Ignore these
+ ;;
+
+ *)
+ HEADER_DIR="$1"
+ ;;
+ esac
+ shift
+ done
+
+ [ -n "${OUTPUT_FILE}" ] || return 0
+ [ -n "${INPUT_FILE}" ] || return 0
+ [ -n "${HEADER_DIR}" ] || return 0
+
+ mkdir -p `dirname ${OUTPUT_FILE}` || die "Unable to mkdir `dirname ${OUTPUT_FILE}`"
+ touch "${OUTPUT_FILE}"
+
+ androidmake_aidl_begin ${OUTPUT_FILE} ${INPUT_FILE}
+ androidmake_aidl_header_dir ${HEADER_DIR}
+ androidmake_aidl_include_paths ${INCLUDE_PATHS}
+ androidmake_aidl_end
+
+ ) >&3
+ elif [[ ${AUTOANDR_MODE} == "install" ]]
+ then true
+ else false
+ fi
+}
+
+handle_ar() {
+ if [[ ${AUTOANDR_MODE} == "make" ]]
+ then (
+ OUTPUT=
+ LIBRARIES=${AUTOANDR_LIBTOOL_LIBS}
+ STATIC_LIBRARIES=
+ OBJECTS=
+
+ shift
+ OUTPUT=`basename $1`
+ shift
+ while [[ $# -ge 1 ]]
+ do
+ case $1 in
+ *.a)
+ STATIC_LIBRARIES="${STATIC_LIBRARIES} $1"
+ ;;
+ *.o|*.lo)
+ OBJECTS="${OBJECTS} $(rel_path $1)"
+ ;;
+ *)
+ echo " $# UNKNOWN \"$1\""
+ ;;
+ esac
+ shift
+ done
+ if [ -z "${OUTPUT}" ]
+ then return 0
+ fi
+
+ touch "${OUTPUT}"
+
+ OUTPUT=${OUTPUT%.a}
+ OUTPUT=$(basename $OUTPUT)
+
+ announce_tool link-lib "${OUTPUT}"
+
+ androidmake_module_begin ${OUTPUT}
+ if test "${AUTOANDR_MODULE_PATH_64}" != ""
+ then androidmake_module_path_64 "${AUTOANDR_MODULE_PATH_64}"
+ fi
+ for tag in ${AUTOANDR_MODULE_TAGS}
+ do androidmake_module_tags ${tag}
+ done
+ for object in ${OBJECTS}
+ do androidmake_module_add_object ${object}
+ done
+ for depend in $(library_converter ${AUTOANDR_DEPENDS})
+ do androidmake_module_dependency ${depend}
+ done
+ for lib in $(library_converter ${LIBRARIES})
+ do androidmake_module_link_shared_library lib${lib#lib}
+ done
+ for lib in ${STATIC_LIBRARIES}
+ do androidmake_module_link_static_library $(basename ${lib%.a})
+ done
+ androidmake_module_end_static_lib
+
+ ) >&3
+ elif [[ ${AUTOANDR_MODE} == "install" ]]
+ then true
+ else false
+ fi
+}
+
+handle_make() {
+ if [[ ${AUTOANDR_MODE} == "make" ]]
+ then
+ [[ $1 == "all" ]] && (
+ announce_path "$(proj_pwd)"
+
+ ) >&3
+ fi
+}
+
+
+# -- COMMANDS ---------------------------------------------------------
+
+autoandr_cc() {
+ [ -z ${AUTOANDR_MODE} ] && die "missing mode"
+
+ if is_ccld "$@"
+ then handle_ccld "$@" || ${AUTOANDR_CC} "$@"
+ else handle_cc "$@" || ${AUTOANDR_CC} "$@"
+ fi
+}
+
+autoandr_cxx() {
+ [ -z ${AUTOANDR_MODE} ] && die "missing mode"
+
+ if is_ccld "$@"
+ then handle_ccld "$@" || ${AUTOANDR_CXX} "$@"
+ else handle_cc "$@" || ${AUTOANDR_CXX} "$@"
+ fi
+}
+
+autoandr_libtool() {
+ [ -z ${AUTOANDR_MODE} ] && die "missing mode"
+
+ handle_libtool "$@" || ${AUTOANDR_LIBTOOL} "$@"
+}
+
+autoandr_ccld() {
+
+ [ -z ${AUTOANDR_MODE} ] && die "missing mode"
+
+ handle_ccld "$@" ||
+
+ ${AUTOANDR_CCLD} "$@"
+}
+
+autoandr_aidl_cpp() {
+
+ [ -z ${AUTOANDR_MODE} ] && die "missing mode"
+
+ handle_aidl_cpp "$@" ||
+
+ ${AUTOANDR_AIDL_CPP} "$@"
+}
+
+
+autoandr_cxxld() {
+ [ -z ${AUTOANDR_MODE} ] && die "missing mode"
+
+ handle_ccld "$@" ||
+
+ ${AUTOANDR_CXXLD} "$@"
+}
+
+autoandr_ld() {
+ [ -z ${AUTOANDR_MODE} ] && die "missing mode"
+
+ if [[ ${AUTOANDR_MODE} == "make" ]]
+ then
+ echo " **" ld "$@" >&3
+ fi
+
+ ${AUTOANDR_LD} "$@"
+}
+
+autoandr_cpp() {
+ [ -z ${AUTOANDR_MODE} ] && die "missing mode"
+
+ ${AUTOANDR_CPP} "$@"
+}
+
+autoandr_ar() {
+ [ -z ${AUTOANDR_MODE} ] && die "missing mode"
+
+ handle_ar "$@" ||
+
+ ${AUTOANDR_AR} "$@"
+}
+
+autoandr_ranlib() {
+ [ -z ${AUTOANDR_MODE} ] && die "missing mode"
+
+ if [[ ${AUTOANDR_MODE} != "make" ]]
+ then ${AUTOANDR_RANLIB} "$@"
+ fi
+
+ true
+}
+
+autoandr_make() {
+ [ -z ${AUTOANDR_MODE} ] && die "missing mode"
+
+ handle_make "$@"
+
+ ${AUTOANDR_MAKE} "$@"
+}
+
+autoandr_install() {
+ [ -z ${AUTOANDR_MODE} ] && die "missing mode"
+
+ if [[ ${AUTOANDR_MODE} == "install" ]]
+ then
+ announce_tool install "$*" >&3
+ else
+ ${AUTOANDR_INSTALL} "$@"
+ fi
+}
+
+# ---------------------------------------------------------------------------
+
+autoandr_cleanup() {
+ if [ "${AUTOANDR_SKIP_CLEANUP}" == 1 ]
+ then
+ announce_pass "SKIPPING CLEANING UP"
+ return
+ fi
+
+ announce_pass "CLEANING UP"
+
+ [ "${BUILD_DIR}" != "/" ] || die "Build directory is root"
+ [ "${DESTDIR}" != "/" ] || die "DESTDIR is root"
+
+ cd ${BUILD_DIR}
+
+ find . "(" \
+ -name Makefile \
+ -o -name Makefile.in \
+ -o -name config.status \
+ -o -name .libs \
+ -o -name '*.[oa]' \
+ -o -name '*.[sl]o' \
+ -o -name '*.la' \
+ -o -name '*.dylib' \
+ -o -name '.deps' \
+ -o -name '.dirstamp' \
+ -o -name 'stamp-h[0-9]' \
+ -o -name 'config.log' \
+ -o -name 'libtool' \
+ -o -name 'I*.cpp' \
+ -o -name '*'${AUTOANDR_CFLAGS_SUFFIX} \
+ -o -name '*'${AUTOANDR_CXX_FEATURES_SUFFIX} \
+ -o -name '*'${AUTOANDR_INCLUDEPATH_SUFFIX} \
+ -o -name '*'${AUTOANDR_SOURCE_SUFFIX} \
+ -o -name '*'${AUTOANDR_AIDL_SUFFIX} \
+ ")" -print0 \
+ | xargs -0 rm -rf || die
+
+ rm -fr ${DESTDIR}
+}
+
+first() {
+ echo $1
+}
+
+autoandr_start() {
+ # Set up our environment
+
+ # Maybe the root was specified with the NDK environment variable.
+ [ -z "${NDK_ROOT}" ] && NDK_ROOT="${NDK}"
+
+ # Maybe the NDK is in the path. If so, grab it via `which`.
+ [ -z "${NDK_ROOT}" ] && NDK_ROOT=$(dirname `which ndk-build 2>/dev/null`)
+
+ [ -z "${NDK_ROOT}" ] && die "\$NDK_ROOT environment variable not set!"
+ [ -d "${NDK_ROOT}" ] || die "NDK root doesn't seem to exist (\"$NDK_ROOT\")"
+
+ export NDK_ROOT
+ export NDK=${NDK-$NDK_ROOT}
+
+ export SYSROOT=${SYSROOT-$NDK/platforms/android-21/arch-arm}
+
+ export PKG_CONFIG_PATH=/dev/null
+ export PKG_CONFIG_LIBDIR=/dev/null
+ export PKG_CONFIG_DATADIR=/dev/null
+
+ export PATH="${NDK_ROOT}:${PATH}"
+
+ HOST=$(basename `ndk-which gcc`)
+ HOST=${HOST%-gcc}
+
+ echo NDK_ROOT=${NDK_ROOT}
+ echo HOST=${HOST}
+
+ export AUTOANDR_CC=${CC-$(ndk-which gcc) --sysroot=$SYSROOT}
+ export AUTOANDR_CCLD=${CCLD-$AUTOANDR_CC}
+ export AUTOANDR_AR=${AR-$(ndk-which ar)}
+ export AUTOANDR_LD=${LD-$(ndk-which ld)}
+ export AUTOANDR_CPP=${CPP-$(ndk-which cpp) --sysroot=$SYSROOT}
+ export AUTOANDR_CXX=${CXX-$(ndk-which c++) --sysroot=$SYSROOT}
+ export AUTOANDR_CXXLD=${CXXLD-$AUTOANDR_CXX}
+ export AUTOANDR_MAKE=${MAKE-make}
+ export AUTOANDR_INSTALL=${INSTALL-install}
+ export AUTOANDR_RANLIB=${RANLIB-$(ndk-which ranlib)}
+ export AUTOANDR_AIDL_CPP=${AIDL_CPP-$(ndk-which aidl-cpp)}
+ export AUTOANDR_LIBTOOL=${LIBTOOL-${BUILD_DIR}/libtool}
+
+ # Make sure the build directory exists
+ mkdir -p "${BUILD_DIR}" || die "Unable to create \"${BUILD_DIR}\""
+
+ # Make sure DESTDIR exists
+ mkdir -p "${DESTDIR}" || die "Unable to create \"${DESTDIR}\""
+
+ # Make sure BUILD_DIR is absolute.
+ BUILD_DIR=$(cd "${BUILD_DIR}" && pwd) || die "Unable to normalize build directory path"
+
+ # Make sure SOURCE_DIR is absolute.
+ SOURCE_DIR=$(cd "${SOURCE_DIR}" && pwd) || die "Unable to normalize source directory path"
+
+ # Make sure DESTDIR is absolute.
+ DESTDIR=$(cd "${DESTDIR}" && pwd) || die "Unable to normalize DESTDIR"
+
+ # Sanity checks
+ [ "${SOURCE_DIR::1}" == "/" ] || die "SOURCE_DIR is not an absolute path"
+ [ "${BUILD_DIR::1}" == "/" ] || die "BUILD_DIR is not an absolute path"
+ [ "${DESTDIR::1}" == "/" ] || die "DESTDIR is not an absolute path"
+ [ "${BUILD_DIR}" != "${SOURCE_DIR}" ] || die "Build directory same as source directory"
+ [ "${BUILD_DIR}" != "/" ] || die "Build directory is root"
+ [ "${DESTDIR}" != "/" ] || die "DESTDIR is root"
+
+ # Clean up our build directory
+ rm -fr "${BUILD_DIR}"
+ mkdir -p "${BUILD_DIR}"
+
+ # Make a root Android.mk file
+ cd "${SOURCE_DIR}" || die
+ rm -f Android.mk
+ androidmake_prep
+ echo 'include $(LOCAL_PATH)/'$(rel_path "${BUILD_DIR}")'/Android.mk' >> ${SOURCE_DIR}/Android.mk
+
+ cd "${BUILD_DIR}" || die
+
+ announce_pass "CONFIGURE PASS"
+ export AUTOANDR_MODE=configure
+ ( "${SOURCE_DIR}/configure" \
+ CC="${AUTOANDR_DIR}/autoandr cc" \
+ CCLD="${AUTOANDR_DIR}/autoandr ccld" \
+ LD="${AUTOANDR_DIR}/autoandr ld" \
+ CPP="${AUTOANDR_DIR}/autoandr cpp" \
+ AR="${AUTOANDR_DIR}/autoandr ar" \
+ CXX="${AUTOANDR_DIR}/autoandr cxx" \
+ CXXLD="${AUTOANDR_DIR}/autoandr cxxld" \
+ MAKE="${AUTOANDR_DIR}/autoandr make" \
+ INSTALL="${AUTOANDR_DIR}/autoandr install" \
+ RANLIB="${AUTOANDR_DIR}/autoandr ranlib" \
+ AIDL_CPP="${AUTOANDR_DIR}/autoandr aidl-cpp" \
+ --disable-dependency-tracking \
+ --with-gnu-ld \
+ --host=${HOST} \
+ ac_cv_func_getdtablesize=no \
+ ac_cv_func_fgetln=no \
+ ac_cv_header_util_h=no \
+ ${OTHER_CONFIGURE_FLAGS} \
+ "$@" \
+ ) 3>&1 1> "${AUTOANDR_STDOUT}" || die "Configure script failed"
+
+ announce_pass "MAKE PASS"
+ export AUTOANDR_MODE=make
+ ( autoandr_make all V=1 \
+ ${AUTOANDR_MAKE_FLAGS} \
+ MAKE="${AUTOANDR_DIR}/autoandr make" \
+ CCLD="${AUTOANDR_DIR}/autoandr ccld" \
+ CXXLD="${AUTOANDR_DIR}/autoandr cxxld" \
+ CXXLINK="${AUTOANDR_DIR}/autoandr cxxld" \
+ LIBTOOL="\$(SHELL) ${AUTOANDR_DIR}/autoandr libtool" \
+ AIDL_CPP="${AUTOANDR_DIR}/autoandr aidl-cpp" \
+ ) 3>&1 1> "${AUTOANDR_STDOUT}" || die
+
+ # Skipping install pass for now
+ #
+ #announce_pass "INSTALL PASS"
+ #export AUTOANDR_MODE=install
+ #( autoandr_make install V=1 \
+ # ${AUTOANDR_MAKE_FLAGS} \
+ # DESTDIR=${DESTDIR} \
+ # MAKE="${AUTOANDR_DIR}/autoandr make" \
+ # CCLD="${AUTOANDR_DIR}/autoandr ccld" \
+ # CXXLD="${AUTOANDR_DIR}/autoandr cxxld" \
+ #) 3>&1 1> "${AUTOANDR_STDOUT}" || die
+
+ autoandr_cleanup
+
+ cd ${SOURCE_DIR} || die
+
+ marker="Added by autoandr"
+ if sed -i.bak "/# $marker\$/d" Makefile.in
+ then
+ rm Makefile.in.bak
+ else
+ die "Call to 'sed' failed"
+ fi
+ echo "EXTRA_DIST += Android.mk" $(find `rel_path "${BUILD_DIR}"` -type f) "# $marker" >> Makefile.in
+}
+
+
+show_help() {
+ show_version
+ echo ""
+ echo "syntax: autoandr [general-args] <command> [command-args]"
+ echo ""
+ echo "General Arguments:"
+ echo " -v,--verbose .................... Verbose output"
+ echo " -V,--version .................... Print version"
+ echo " -?,-h,--help .................... Show help"
+ echo ""
+ echo "Commands:"
+ echo ""
+ echo " start <configure-args>"
+ echo " Starts the process of building the Android.mk files."
+ echo " Must be executed from the root of the project. Any"
+ echo " arguments that you want passed to the configure script"
+ echo " should be specified after the command."
+ echo ""
+}
+
+# ---------------------------------------------------------------------------
+
+# Parse the arguments present before the command
+while [[ $# -ge 1 ]]
+do
+ case $1 in
+ -v|--verbose)
+ AUTOANDR_STDOUT=/dev/stdout
+ ;;
+ -V|--version)
+ show_version
+ exit 0
+ ;;
+ -j*)
+ AUTOANDR_MAKE_FLAGS="${AUTOANDR_MAKE_FLAGS} $1"
+ ;;
+ -*)
+ die "Unknown argument \"$1\""
+ ;;
+ *)
+ break
+ ;;
+ esac
+ shift
+done
+
+AUTOANDR_STDOUT=${AUTOANDR_STDOUT-/dev/null}
+
+case $1 in
+ cc) shift ; autoandr_cc "$@" ;;
+ ccld) shift ; autoandr_ccld "$@" ;;
+ ar) shift ; autoandr_ar "$@" ;;
+ ld) shift ; autoandr_ld "$@" ;;
+ cxx) shift ; autoandr_cxx "$@" ;;
+ cxxld) shift ; autoandr_cxxld "$@" ;;
+ libtool) shift ; autoandr_libtool "$@" ;;
+ cpp) shift ; autoandr_cpp "$@" ;;
+ make) shift ; autoandr_make "$@" ;;
+ install) shift ; autoandr_install "$@" ;;
+ ranlib) shift ; autoandr_ranlib "$@" ;;
+ aidl-cpp) shift ; autoandr_aidl_cpp "$@" ;;
+
+ start) shift ; autoandr_start "$@" ;;
+ cleanup) shift ; autoandr_cleanup "$@" ;;
+
+ *) die "Unknown command \"$1\"" ;;
+esac
diff --git a/etc/build-in-docker.sh b/etc/build-in-docker.sh
new file mode 100755
index 0000000..c6d3083
--- /dev/null
+++ b/etc/build-in-docker.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+#
+# Copyright (c) 2016 Nest Labs, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+
+DIR="`dirname $0`"
+
+"${DIR}"/run-in-docker.sh -i 'DIR="`pwd`" &&
+mkdir -p /build &&
+cd /build && "${DIR}"/configure --enable-all-restricted-plugins --with-connman --with-readline &&
+make -j `nproc` distcheck AM_DEFAULT_VERBOSITY=1
+' || exit 1
+
+"${DIR}"/run-in-docker.sh -i 'DIR="`pwd`" &&
+mkdir -p /build &&
+cd /build && "${DIR}"/configure --enable-ncp-spinel --enable-static-link-ncp-plugin=spinel &&
+make -j `nproc` check AM_DEFAULT_VERBOSITY=1 &&
+make -j `nproc` install DESTDIR=/destdir AM_DEFAULT_VERBOSITY=1 &&
+cd /destdir &&
+find .
+' || exit 1
diff --git a/etc/run-in-docker.sh b/etc/run-in-docker.sh
new file mode 100755
index 0000000..e644754
--- /dev/null
+++ b/etc/run-in-docker.sh
@@ -0,0 +1,161 @@
+#!/bin/bash
+#
+# Copyright (c) 2016 Nest Labs, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+set -e
+
+path_to_dir ()
+{
+ f=$@;
+ if [ -d "$f" ]; then
+ base="";
+ dir="$f";
+ else
+ base="/$(basename "$f")";
+ dir=$(dirname "$f");
+ fi;
+ dir=$(cd "$dir" && /bin/pwd);
+ echo "$dir$base"
+}
+
+usage ()
+{
+ echo "usage: "
+ echo "$0 [-i] <command to exec inside docker>"
+ echo "$0 -c|--clear"
+ echo "$0 -a|--clear-all"
+ echo -n
+ echo "-c, --clear delete all docker images including the current one"
+ echo "--priv run container with privileges"
+ echo "-p, --prune delete all docker images except the current one"
+ echo "-i, --interactive run docker with -it"
+}
+
+calc_sha1 ()
+{
+ # Figure out which program to use to calculate
+ # the SHA1 hash and execute it.
+ if ( which shasum > /dev/null 2>&1 )
+ then shasum "$1"
+ elif ( which sha1sum > /dev/null 2>&1 )
+ then sha1sum "$1"
+ elif ( which openssl > /dev/null 2>&1 )
+ then openssl dgst -sha1 < "$1"
+ fi
+}
+
+SCRIPT_DIR="$(path_to_dir "$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )")"
+PROJECT_DIR="$(pwd)"
+SRC_DIR="/src"
+
+# 1. Calculate the SHA1 hash of the Dockerfile
+DOCKER_SHA=$(calc_sha1 $SCRIPT_DIR/Dockerfile)
+DOCKER_SHORT_SHA=${DOCKER_SHA:0:8}
+DOCKER_IMAGE_NAME_BASE="nestlabs/wpantund-build"
+DOCKER_IMAGE_NAME="$DOCKER_IMAGE_NAME_BASE:$DOCKER_SHORT_SHA"
+
+prune_unused_dockers ()
+{
+ docker images | grep $DOCKER_IMAGE_NAME_BASE | awk 'BEGIN{OFS = ":"}{print $1,$2}' | grep -v $DOCKER_IMAGE_NAME | xargs -I {} docker rmi {}
+ return 0
+}
+
+delete_current_docker ()
+{
+ docker rmi $DOCKER_IMAGE_NAME
+}
+
+delete_all_dockers ()
+{
+ prune_unused_dockers
+ delete_current_docker
+ rm -rf "$SCRIPT_DIR/hostinfo"
+}
+
+if [[ $# -eq 0 ]]
+then
+ echo "Give me something to do."
+ usage
+ exit 0
+fi
+
+OTHER_OPTS=""
+
+# Check to see if we have any arguments to work on.
+while [[ $# > 0 ]]
+do
+ key="$1"
+
+ case $key in
+ -h|--help)
+ usage
+ exit 0;
+ ;;
+ -c|--clear)
+ delete_all_dockers
+ exit $?
+ ;;
+ -p|--prune)
+ prune_unused_dockers
+ exit $?
+ ;;
+ --priv)
+ OTHER_OPTS="${OTHER_OPTS} --privileged"
+ ;;
+ -i|--it)
+ OTHER_OPTS="${OTHER_OPTS} -it"
+ ;;
+ *)
+ if [ ${key:0:1} == '-' ]
+ then
+ echo "Unknown option $key"
+ usage
+ exit 1
+ fi
+ break
+ ;;
+ esac
+ shift
+done
+
+# 2. Check to see if that docker image exists.
+RESULT=$(docker images | awk 'BEGIN{OFS = ":"}{print $1,$2}' |grep -c $DOCKER_IMAGE_NAME) || true
+
+if [ $RESULT -eq 1 ]; then
+ echo "Docker image $DOCKER_IMAGE_NAME already exists"
+else
+ echo "Creating new docker image: $DOCKER_IMAGE_NAME"
+ docker build -t $DOCKER_IMAGE_NAME $SCRIPT_DIR
+fi
+
+COMMAND="$@"
+TMPFILE="$(mktemp ./tmp.XXXXXXXXXX)"
+echo "$COMMAND" > "$TMPFILE"
+chmod 0755 "$TMPFILE"
+trap "rm -f '$TMPFILE'" EXIT
+echo "Executing '$COMMAND' as $USERNAME"
+
+CMD="docker run \
+ -v=$PROJECT_DIR:$SRC_DIR \
+ -w=$SRC_DIR \
+ --hostname=`hostname`\
+ --rm \
+ $OTHER_OPTS \
+ $DOCKER_IMAGE_NAME \
+ bash --login -ci '$TMPFILE'"
+
+$CMD
diff --git a/etc/wpantund.rb b/etc/wpantund.rb
new file mode 100644
index 0000000..36ff72b
--- /dev/null
+++ b/etc/wpantund.rb
@@ -0,0 +1,58 @@
+# Homebrew recipe for wpantund.
+
+#
+# Copyright (c) 2016 Nest Labs, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+require 'formula'
+
+class Wpantund < Formula
+ homepage 'https://github.com/openthread/wpantund'
+ head 'https://github.com/openthread/wpantund.git', :using => :git, :branch => 'master'
+ url 'https://github.com/openthread/wpantund.git', :using => :git, :tag => 'full/0.07.00'
+ version '0.07.00'
+
+ devel do
+ url 'https://github.com/openthread/wpantund.git', :using => :git, :tag => 'full/latest-unstable'
+ version 'latest-unstable'
+ end
+
+ depends_on 'pkg-config' => :build
+ depends_on 'd-bus'
+ depends_on 'boost'
+
+ depends_on 'autoconf' => :build
+ depends_on 'automake' => :build
+ depends_on 'libtool' => :build
+ depends_on 'autoconf-archive' => :build
+
+ def install
+ system "[ -x configure ] || PATH=\"#{HOMEBREW_PREFIX}/bin:$PATH\" ./bootstrap.sh"
+
+ system "./configure",
+ "--disable-dependency-tracking",
+ "--without-connman",
+ "--enable-all-restricted-plugins",
+ "--prefix=#{prefix}"
+
+ system "make check"
+ system "make install"
+ end
+
+ def test
+ system "wpanctl"
+ end
+end
diff --git a/m4/nl.m4 b/m4/nl.m4
new file mode 100644
index 0000000..4de5476
--- /dev/null
+++ b/m4/nl.m4
@@ -0,0 +1,345 @@
+dnl #
+dnl # Copyright (c) 2016 Nest Labs, Inc.
+dnl # All rights reserved.
+dnl #
+dnl # Licensed under the Apache License, Version 2.0 (the "License");
+dnl # you may not use this file except in compliance with the License.
+dnl # You may obtain a copy of the License at
+dnl #
+dnl # http://www.apache.org/licenses/LICENSE-2.0
+dnl #
+dnl # Unless required by applicable law or agreed to in writing, software
+dnl # distributed under the License is distributed on an "AS IS" BASIS,
+dnl # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl # See the License for the specific language governing permissions and
+dnl # limitations under the License.
+dnl #
+
+AC_DEFUN([NL_DEBUG], [
+ AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug[=verbose|symbols]],
+ [enable compiling with debugging information and symbols]),
+ [],
+ [enable_debug=no])
+
+ if test "x$enable_debug" '!=' "xno"
+ then
+ CXXFLAGS="$CXXFLAGS -g"
+ CFLAGS="$CFLAGS -g"
+
+ if test "x$enable_debug" '!=' "xsymbols"
+ then CPPFLAGS="$CPPFLAGS -DDEBUG=1 -DDEBUG_LEVEL=2"
+ fi
+
+ if test "x$enable_debug" = "xverbose"
+ then CPPFLAGS="$CPPFLAGS -DVERBOSE_DEBUG=1"
+ fi
+ fi
+
+
+ AM_CONDITIONAL([DEBUG],[test "x$enable_debug" '!=' "xno" && test "x$enable_debug" '!=' "xsymbols"])
+ AM_CONDITIONAL([VERBOSE_DEBUG],[test "x$enable_debug" = "xverbose"])
+])
+
+AC_DEFUN([NL_EXPORT_DYNAMIC], [
+ prev_LDFLAGS="${LDFLAGS}"
+ LDFLAGS="-Wl,--export-dynamic"
+ AC_LANG_PUSH(C)
+ AC_MSG_CHECKING([linker flags needed for programs to export symbols])
+ AC_LINK_IFELSE(
+ AC_LANG_PROGRAM,
+ [EXPORT_DYNAMIC_LDFLAGS="$LDFLAGS"],
+ [EXPORT_DYNAMIC_LDFLAGS=""]
+ )
+ LDFLAGS="${prev_LDFLAGS}"
+ unset prev_LDFLAGS
+ AC_MSG_RESULT([\"$EXPORT_DYNAMIC_LDFLAGS\"])
+ AC_SUBST(EXPORT_DYNAMIC_LDFLAGS)
+ AC_LANG_POP(C)
+])
+
+AC_DEFUN([NL_CHECK_BOOST_SIGNALS2], [
+ AC_LANG_PUSH([C++])
+
+ AC_ARG_VAR([BOOST_CXXFLAGS], [C compiler flags for boost])
+ AC_ARG_VAR([BOOST_LIBS], [linker flags for boost])
+
+ boost_internal_cxxflags="-I$(cd $srcdir && pwd)/third_party/boost -DBOOST_NO_CXX11_VARIADIC_TEMPLATES -DBOOST_NO_CXX11_HDR_ARRAY -DBOOST_NO_CXX11_HDR_CODECVT -DBOOST_NO_CXX11_HDR_CONDITION_VARIABLE -DBOOST_NO_CXX11_HDR_FORWARD_LIST -DBOOST_NO_CXX11_HDR_INITIALIZER_LIST -DBOOST_NO_CXX11_HDR_MUTEX -DBOOST_NO_CXX11_HDR_RANDOM -DBOOST_NO_CXX11_HDR_RATIO -DBOOST_NO_CXX11_HDR_REGEX -DBOOST_NO_CXX11_HDR_SYSTEM_ERROR -DBOOST_NO_CXX11_HDR_THREAD -DBOOST_NO_CXX11_HDR_TUPLE -DBOOST_NO_CXX11_HDR_TYPEINDEX -DBOOST_NO_CXX11_HDR_UNORDERED_MAP -DBOOST_NO_CXX11_HDR_UNORDERED_SET -DBOOST_NO_CXX11_NUMERIC_LIMITS -DBOOST_NO_CXX11_ALLOCATOR -DBOOST_NO_CXX11_SMART_PTR -DBOOST_NO_CXX11_HDR_FUNCTIONAL -DBOOST_NO_CXX11_STD_ALIGN -DBOOST_NO_CXX11_ADDRESSOF -DBOOST_NO_CXX11_DECLTYPE_N3276 -Wp,-w"
+
+ AC_ARG_WITH(
+ [boost],
+ AC_HELP_STRING([--with-boost=internal], [Use internal copy of boost])
+ )
+
+ with_boost=${with_boost-yes}
+
+ case ${with_boost} in
+ no)
+ $2
+ ;;
+ internal)
+ BOOST_CXXFLAGS="${boost_internal_cxxflags}"
+ $1
+ ;;
+ yes)
+ if test -z "${BOOST_CXXFLAGS}"
+ then
+ # If BOOST_CFLAGS was set for some reason, merge them into BOOST_CXXFLAGS.
+ test -n "${BOOST_CFLAGS}" && BOOST_CXXFLAGS="${BOOST_CXXFLAGS} ${BOOST_CFLAGS}"
+
+ # Go ahead and add the BOOST_CPPFLAGS into CFLAGS for now.
+ nl_check_boost_signals2_CXXFLAGS="${CXXFLAGS}"
+ nl_check_boost_signals2_CPPFLAGS="${CPPFLAGS}"
+ CXXFLAGS+=" ${BOOST_CXXFLAGS}"
+ CPPFLAGS+=" ${BOOST_CXXFLAGS}"
+
+ AC_CHECK_HEADERS([boost/signals2/signal.hpp], [$1],[
+
+ # Sometimes boost explicitly needs this flag to work.
+ AX_CHECK_COMPILE_FLAG([-std=c++11], [
+ CXXFLAGS="$CXXFLAGS -std=c++11"
+ CPPFLAGS="$CPPFLAGS -std=c++11"
+ BOOST_CXXFLAGS="$BOOST_CXXFLAGS -std=c++11"
+ ], [$2])
+
+ ## Clear the cache entry we that we try again
+ unset ac_cv_header_boost_signals2_signal_hpp
+
+ AC_CHECK_HEADERS([boost/signals2/signal.hpp], [$1], [
+ with_boost=internal
+ BOOST_CXXFLAGS="${boost_internal_cxxflags}"
+ CXXFLAGS="${nl_check_boost_signals2_CXXFLAGS} ${BOOST_CXXFLAGS}"
+ CPPFLAGS="${nl_check_boost_signals2_CPPFLAGS} ${BOOST_CXXFLAGS}"
+ unset ac_cv_header_boost_signals2_signal_hpp
+ AC_CHECK_HEADERS([boost/signals2/signal.hpp], [
+ $1
+ with_boost=internal
+ ], [
+ $2
+ ])
+ ])
+ ])
+
+ CXXFLAGS="${nl_check_boost_signals2_CXXFLAGS}"
+ unset nl_check_boost_signals2_CXXFLAGS
+
+ CPPFLAGS="${nl_check_boost_signals2_CPPFLAGS}"
+ unset nl_check_boost_signals2_CPPFLAGS
+ fi
+
+ ;;
+ *)
+ BOOST_CXXFLAGS="-I${with_boost}"
+ ;;
+ esac
+
+ AC_SUBST(BOOST_CXXFLAGS)
+ AC_SUBST(BOOST_LIBS)
+
+ AC_LANG_POP([C++])
+])
+
+AC_DEFUN([NL_CHECK_READLINE], [
+ AC_LANG_PUSH([C])
+
+ readline_required=no
+
+ AC_ARG_WITH(
+ [readline],
+ AC_HELP_STRING([--without-readline], [Don't use libreadline or libedit])
+ )
+
+ if test "${with_readline}" '!=' "no"
+ then
+ if test "${with_readline}" '=' "yes"
+ then unset with_readline;
+ readline_required=yes
+ fi
+
+ temp_LIBS="${LIBS}"
+ temp_CPPFLAGS="${CPPFLAGS}"
+ LIBS="${LIBREADLINE_LIBS}"
+ CPPFLAGS="${LIBREADLINE_CPPFLAGS} ${LIBREADLINE_CFLAGS}"
+
+ AC_CHECK_HEADER(
+ [readline/readline.h],
+ [
+ AC_SEARCH_LIBS(waddstr, [ncurses cursesX curses])
+ AC_SEARCH_LIBS(tgetstr, [tinfo])
+ AC_SEARCH_LIBS(
+ [readline],
+ [${with_readline-readline edit}],
+ [with_readline=yes]
+ )
+ ]
+ )
+
+ if test "x$with_readline" = "xyes"
+ then
+ LIBREADLINE_LIBS="${LIBS}"
+ LIBREADLINE_CPPFLAGS="${CPPFLAGS}"
+ AC_DEFINE([HAVE_LIBREADLINE], [1], [Define to 1 if we have libreadline or libedit])
+ fi
+
+ CPPFLAGS="${temp_CPPFLAGS}"
+ LIBS="${temp_LIBS}"
+ else
+ LIBREADLINE_LIBS=""
+ LIBREADLINE_CPPFLAGS=""
+ fi
+
+ AC_SUBST(LIBREADLINE_LIBS)
+ AC_SUBST(LIBREADLINE_CPPFLAGS)
+ AM_CONDITIONAL([HAVE_LIBREADLINE],[test "x$with_readline" = "xyes"])
+
+ if test "x$with_readline" = "xyes"
+ then true; $1
+ elif test "x$readline_required" = "xyes"
+ then false; AC_MSG_ERROR(["libreadline or libedit was explicitly requested but was unable to figure out how to use either"])
+ else false; $2
+ fi
+
+ AC_LANG_POP([C])
+])
+
+AC_DEFUN([NL_CHECK_DBUS], [
+ PKG_CHECK_MODULES(DBUS, dbus-1 >= 1.4, [$1], [$2])
+ AC_SUBST(DBUS_CFLAGS)
+ AC_SUBST(DBUS_LIBS)
+
+ AC_ARG_WITH(dbusconfdir,
+ AC_HELP_STRING([--with-dbusconfdir=PATH], [path to D-Bus config directory]),
+ [path_dbusconf=${withval}],
+ [
+ if test "$prefix" = "`$PKG_CONFIG --variable=prefix dbus-1`"
+ then path_dbusconf="`$PKG_CONFIG --variable=sysconfdir dbus-1`"
+ fi
+ ]
+ )
+ if (test -z "${path_dbusconf}"); then
+ if test "${prefix}" = "/usr/local" && test "${sysconfdir}" = '${prefix}/etc' && test -d /etc/dbus-1/system.d
+ then DBUS_CONFDIR='/etc/dbus-1/system.d'
+ else DBUS_CONFDIR='${sysconfdir}/dbus-1/system.d'
+ fi
+ else
+ [path_dbusconf="$(echo ${path_dbusconf} | sed 's:^'"${prefix}"':${prefix}:')" ; ]
+ [path_dbusconf="$(echo ${path_dbusconf} | sed 's:^'"${sysconfdir}"':${sysconfdir}:')" ; ]
+ DBUS_CONFDIR="${path_dbusconf}/dbus-1/system.d"
+ fi
+ AC_SUBST(DBUS_CONFDIR)
+
+ AC_ARG_WITH(dbusdatadir, AC_HELP_STRING([--with-dbusdatadir=PATH],
+ [path to D-Bus data directory]), [path_dbusdata=${withval}],
+ [
+ if test "$prefix" = "`$PKG_CONFIG --variable=prefix dbus-1`"
+ then path_dbusdata="`$PKG_CONFIG --variable=datadir dbus-1`"
+ fi
+ ]
+ )
+ if (test -z "${path_dbusdata}"); then
+ DBUS_DATADIR='${datadir}/dbus-1/system-services'
+ else
+ [path_dbusconf="$(echo ${path_dbusdata} | sed 's:^'"${prefix}"':${prefix}:')" ; ]
+ [path_dbusconf="$(echo ${path_dbusdata} | sed 's:^'"${datadir}"':${datadir}:')" ; ]
+ DBUS_DATADIR="${path_dbusdata}/dbus-1/system-services"
+ fi
+ AC_SUBST(DBUS_DATADIR)
+])
+
+AC_DEFUN([NL_CHECK_LIBDL], [
+ HAVE_LIBDL=false
+ AC_ARG_WITH(libdl,AC_HELP_STRING([--without-libdl], [Do not use libdl]))
+ if test "${with_libdl-yes}" '!=' 'no'; then :
+ AC_CHECK_HEADER(
+ [dlfcn.h],
+ AC_CHECK_LIB([dl], [dlsym], [
+ HAVE_LIBDL=true
+ LIBDL_LIBS="-ldl"
+ ],
+ AC_CHECK_LIB([ltdl], [dlsym], [
+ HAVE_LIBDL=true
+ LIBDL_LIBS="-lltdl"
+ ])
+ )
+ )
+ fi
+ AC_SUBST(LIBDL_LIBS)
+])
+
+
+AC_DEFUN([NL_CHECK_CONNMAN], [
+ AC_ARG_WITH(
+ [connman],
+ [AC_HELP_STRING([--without-connman], [Don't build connman plugin])],
+ [
+ if test "x${with_connman}" '=' "xyes"
+ then require_connman=yes
+ fi
+ ]
+ )
+
+ if test "x${with_connman}" '==' "xforce"
+ then
+ with_connman=yes
+ if test "x${CONNMAN_LIBS}" == "x"
+ then CONNMAN_LIBS="-module -avoid-version -export-symbols-regex connman_plugin_desc"
+ fi
+ elif test "x${with_connman}" '!=' "xno"
+ then
+ if test "x${CONNMAN_CFLAGS}" '==' "x"
+ then
+ PKG_CHECK_MODULES(
+ [CONNMAN],
+ [connman >= 1.0],
+ [with_connman=yes],
+ [with_connman=no]
+ )
+ else
+ # CONNMAN_CFLAGS was given manually.
+ prev_CPPFLAGS="${CPPFLAGS}"
+ CPPFLAGS="${CPPFLAGS} ${CONNMAN_CFLAGS}"
+ AC_CHECK_HEADERS([connman/plugin.h],[with_connman=yes],[with_connman=no])
+ CPPFLAGS="${prev_CPPFLAGS}"
+ unset prev_CPPFLAGS
+
+ if test "x${CONNMAN_LIBS}" == "x"
+ then CONNMAN_LIBS="-module -avoid-version -export-symbols-regex connman_plugin_desc"
+ fi
+ fi
+ fi
+
+ AC_SUBST(CONNMAN_CFLAGS)
+ AC_SUBST(CONNMAN_LIBS)
+
+ if test "x${with_connman}" = "xyes"
+ then {
+ $1
+ }
+ elif test "x$require_connman" = "xyes"
+ then false; AC_MSG_ERROR(["ConnMan plugin was explicitly requested, but can't find ConnMan headers"])
+ else false; $2
+ fi
+])
+
+AC_DEFUN([NL_CHECK_GLIB], [
+ if test "x${GLIB_CFLAGS}" '==' "x"
+ then
+ PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.28, [$1], [$2])
+ else {
+ true
+ $1
+ }
+ fi
+
+ GLIB_CFLAGS="${GLIB_CFLAGS} -DGLIB_VERSION_MAX_ALLOWED=138240 -DGLIB_VERSION_MIN_REQUIRED=138240"
+
+ AC_SUBST(GLIB_CFLAGS)
+ AC_SUBST(GLIB_LIBS)
+])
+
+dnl Unix Pseudoterminal Support
+AC_DEFUN([NL_CHECK_PTS], [
+ AC_CHECK_LIB([util], [forkpty])
+ AC_CHECK_HEADERS([pty.h util.h phy.h])
+ AM_CONDITIONAL([_XOPEN_SOURCE],[true])
+ AC_CHECK_FUNCS([forkpty ptsname], [$1], [$2])
+])
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..102f22a
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,47 @@
+#
+# Copyright (c) 2016 Nest Labs, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+SUBDIRS = \
+ util \
+ wpanctl \
+ ipc-dbus \
+ connman-plugin \
+ @PLUGIN_SUBDIRS@ \
+ wpantund \
+ scripts \
+ $(NULL)
+
+DISTCLEANFILES = \
+ .deps \
+ Makefile \
+ $(NULL)
+
+EXTRA_DIST = \
+ version.c.in \
+ version.h \
+ $(NULL)
+
+SOURCE_VERSION=$(shell \
+ git describe --dirty --always --match "[0-9].*" 2> /dev/null \
+)
+
+CLEANFILES = $(top_builddir)/$(subdir)/version.c
+BUILT_SOURCES = $(top_builddir)/$(subdir)/version.c
+.INTERMEDIATE: $(top_builddir)/$(subdir)/version.c
+
+$(top_builddir)/$(subdir)/version.c: version.c.in Makefile
+ sed 's/SOURCE_VERSION/"$(SOURCE_VERSION)"/' < $< > $@
diff --git a/src/connman-plugin/Makefile.am b/src/connman-plugin/Makefile.am
new file mode 100644
index 0000000..349bf98
--- /dev/null
+++ b/src/connman-plugin/Makefile.am
@@ -0,0 +1,53 @@
+#
+# Copyright (c) 2016 Nest Labs, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/src/ipc-dbus \
+ -I$(top_srcdir)/src/wpantund \
+ -I$(top_srcdir)/src/util \
+ -I$(top_srcdir)/third_party/assert-macros \
+ $(NULL)
+
+DISTCLEANFILES = .deps Makefile
+
+if BUILD_CONNMAN_PLUGIN
+
+connman_plugindir = ${libdir}/connman/plugins
+
+connman_plugin_LTLIBRARIES = wpan-tunnel-plugin.la
+
+wpan_tunnel_plugin_la_SOURCES = \
+ wpan-connman-plugin.c \
+ ../util/string-utils.c \
+ $(NULL)
+
+wpan_tunnel_plugin_la_CFLAGS = \
+ $(CONNMAN_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(DBUS_CFLAGS) \
+ $(NULL)
+
+wpan_tunnel_plugin_la_LDFLAGS = \
+ $(CONNMAN_LIBS) \
+ -shared \
+ -module \
+ -avoid-version \
+ -Wl,--allow-shlib-undefined \
+ $(NULL)
+
+endif
diff --git a/src/connman-plugin/wpan-connman-plugin.c b/src/connman-plugin/wpan-connman-plugin.c
new file mode 100644
index 0000000..9387597
--- /dev/null
+++ b/src/connman-plugin/wpan-connman-plugin.c
@@ -0,0 +1,2701 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define ASSERT_MACROS_USE_SYSLOG 1
+#include "assert-macros.h"
+#include <errno.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+
+#define _GNU_SOURCE 1
+#include <stdio.h>
+
+#ifndef IFF_LOWER_UP
+#define IFF_LOWER_UP 0x10000
+#endif
+
+#define CONNMAN_API_SUBJECT_TO_CHANGE
+#include <connman/technology.h>
+#include <connman/plugin.h>
+#include <connman/device.h>
+#include <connman/inet.h>
+#include <connman/ipaddress.h>
+#include <connman/log.h>
+#include <connman/dbus.h>
+#include <syslog.h>
+#include <dbus/dbus.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <string.h>
+#include <stdio.h>
+#include <syslog.h>
+#include "wpan-dbus-v0.h"
+#include "wpan-properties.h"
+#include "wpan-error.h"
+#include <stdbool.h>
+#include "string-utils.h"
+
+static struct connman_technology *lowpan_tech;
+static DBusConnection *connection;
+
+//#define DEBUG 1
+
+#define LOWPAN_AUTH_KEY "WiFi.Passphrase"
+#define LOWPAN_SECURITY_KEY "WiFi.Security"
+#define LOWPAN_PERMIT_JOINING_KEY "LoWPAN.PermitJoining"
+#define LOWPAN_PARENT_ADDRESS_KEY "LoWPAN.ParentAddress"
+
+#if DEBUG
+#undef DBG
+#define DBG(fmt, arg ...) \
+ connman_debug("%s:%d:%s() " fmt, \
+ "wpan-connman-plugin.c", __LINE__, __FUNCTION__, ## arg);
+#endif
+
+static GHashTable* devices;
+static GHashTable* networks;
+
+// Simplified state representation
+typedef enum {
+ NCP_STATE_UNINITIALIZED,
+ NCP_STATE_UPGRADING,
+ NCP_STATE_OFFLINE,
+ NCP_STATE_COMMISSIONED,
+ NCP_STATE_ASSOCIATING,
+ NCP_STATE_CREDENTIALS_NEEDED,
+ NCP_STATE_ASSOCIATED,
+ NCP_STATE_NET_WAKE_ASLEEP,
+} ncp_state_t;
+
+struct wpan_network_info_s {
+ char network_name[17];
+ dbus_bool_t allowing_join;
+ uint16_t pan_id;
+ int16_t channel;
+ uint64_t xpanid;
+ int8_t rssi;
+ uint8_t hwaddr[8];
+ uint8_t prefix[8];
+};
+
+struct lowpan_device_s {
+ struct wpan_network_info_s current_network_info;
+ struct connman_network* current_network;
+ uint8_t hwaddr[8];
+ ncp_state_t ncp_state;
+};
+
+struct lowpan_network_s {
+ struct wpan_network_info_s network_info;
+ int16_t node_type;
+};
+
+/* -------------------------------------------------------------------------- */
+// MARK: - Other Helpers
+
+
+static bool
+ncp_state_is_initializing(ncp_state_t ncp_state)
+{
+ switch (ncp_state) {
+ case NCP_STATE_UNINITIALIZED:
+ case NCP_STATE_UPGRADING:
+ return true;
+ break;
+
+ default:
+ break;
+ }
+ return false;
+}
+
+static bool
+ncp_state_is_not_associated(ncp_state_t ncp_state)
+{
+ switch(ncp_state) {
+ case NCP_STATE_OFFLINE:
+ case NCP_STATE_UPGRADING:
+ case NCP_STATE_UNINITIALIZED:
+ return true;
+
+ default:
+ break;
+ }
+ return false;
+}
+
+
+static bool
+ncp_state_is_has_joined(ncp_state_t ncp_state)
+{
+ switch(ncp_state) {
+ case NCP_STATE_ASSOCIATED:
+ case NCP_STATE_NET_WAKE_ASLEEP:
+ return true;
+
+ default:
+ break;
+ }
+ return false;
+}
+
+
+static ncp_state_t
+string_to_ncp_state(const char* new_state, ncp_state_t ncp_state) {
+ DBG("string_to_ncp_state: %s",new_state);
+
+ if(new_state == NULL) {
+ DBG("Bad association state");
+ } else if (0 == strcmp(new_state, kWPANTUNDStateFault)) {
+ ncp_state = NCP_STATE_UNINITIALIZED;
+
+ } else if (0 == strcmp(new_state, kWPANTUNDStateUpgrading)) {
+ ncp_state = NCP_STATE_UPGRADING;
+
+ } else if (0 == strcmp(new_state, kWPANTUNDStateCommissioned)) {
+ ncp_state = NCP_STATE_COMMISSIONED;
+
+ } else if (0 == strcmp(new_state, kWPANTUNDStateCredentialsNeeded)) {
+ ncp_state = NCP_STATE_CREDENTIALS_NEEDED;
+
+ } else if (0 == strcmp(new_state, kWPANTUNDStateNetWake_Asleep)) {
+ ncp_state = NCP_STATE_NET_WAKE_ASLEEP;
+
+ } else if (0 == strcmp(new_state, kWPANTUNDStateIsolated)) {
+ ncp_state = NCP_STATE_ASSOCIATING;
+
+ } else if (0 == strncmp(new_state, kWPANTUNDStateOffline, sizeof(kWPANTUNDStateOffline)-1)) {
+ ncp_state = NCP_STATE_OFFLINE;
+
+ } else if (0 == strncmp(new_state, kWPANTUNDStateAssociating, sizeof(kWPANTUNDStateAssociating)-1)) {
+ ncp_state = NCP_STATE_ASSOCIATING;
+
+ } else if (0 == strncmp(new_state, kWPANTUNDStateAssociated, sizeof(kWPANTUNDStateAssociated)-1)) {
+ ncp_state = NCP_STATE_ASSOCIATED;
+
+ } else if (0 == strncmp(new_state, kWPANTUNDStateUninitialized, sizeof(kWPANTUNDStateUninitialized)-1)) {
+ ncp_state = NCP_STATE_UNINITIALIZED;
+ }
+ return ncp_state;
+}
+
+static void
+parse_prefix_string(const char *prefix_cstr, uint8_t *prefix)
+{
+ uint8_t bytes[16];
+ char str[INET6_ADDRSTRLEN + 10];
+ char *p;
+
+ memset(prefix, 0, 8);
+ memset(bytes, 0, sizeof(bytes));
+
+ // Create a copy of the prefix string so we can modify it.
+ strcpy(str, prefix_cstr);
+
+ // Search for "/64" and remove it from the str.
+ p = strchr(str, '/');
+ if (p != NULL) {
+ *p = 0;
+ }
+
+ // Parse the str as an ipv6 address.
+ if (inet_pton(AF_INET6, str, bytes) > 0)
+ {
+ // If successful, copy the first 8 bytes.
+ memcpy(prefix, bytes, 8);
+ }
+}
+
+static int
+encode_data_into_b16_string(
+ const uint8_t* buffer,
+ size_t len,
+ char* c_str,
+ size_t c_str_max_len,
+ int pad_to
+ )
+{
+ int ret = 0;
+
+ while (len && (c_str_max_len > 2)) {
+ uint8_t byte = *buffer++;
+ len--;
+ pad_to--;
+ *c_str++ = int_to_hex_digit(byte >> 4);
+ *c_str++ = int_to_hex_digit(byte & 0xF);
+ c_str_max_len -= 2;
+ ret += 2;
+ }
+
+ while (pad_to > 0 && (c_str_max_len > 2)) {
+ pad_to--;
+ *c_str++ = '0';
+ *c_str++ = '0';
+ c_str_max_len -= 2;
+ ret += 2;
+ }
+
+ *c_str++ = 0;
+ return ret;
+}
+
+static int
+encode_ipv6_address_from_prefx_and_hwaddr(
+ char* c_str,
+ size_t c_str_max_len,
+ const uint8_t prefix[8],
+ const uint8_t hwaddr[8]
+ )
+{
+ return snprintf(c_str, c_str_max_len,
+ "%02X%02X:%02X%02X:%02X%02X:%02X%02X:"
+ "%02X%02X:%02X%02X:%02X%02X:%02X%02X",
+ prefix[0], prefix[1], prefix[2], prefix[3],
+ prefix[4], prefix[5], prefix[6], prefix[7],
+ hwaddr[0] ^ 0x02, hwaddr[1], hwaddr[2], hwaddr[3],
+ hwaddr[4], hwaddr[5], hwaddr[6], hwaddr[7]
+ );
+}
+
+/* -------------------------------------------------------------------------- */
+// MARK: - Static Declarations
+
+static void lowpan_device_leave(struct connman_device *device);
+static int lowpan_driver_setprop_data(struct connman_device *device, const char* key, const uint8_t* data, size_t size);
+static int lowpan_driver_getprop_data(struct connman_device *device, const char* key, void(*callback)(void* context, int error, const uint8_t* data, size_t len), void* context);
+
+static void lowpan_device_set_network(struct connman_device *device, struct connman_network *network);
+
+static int lowpan_device_update_status(struct connman_device *device);
+
+
+/* -------------------------------------------------------------------------- */
+// MARK: - DBus Helpers
+
+uint8_t
+CalculateStrengthFromRSSI(int8_t rssi)
+{
+ uint8_t ret = 0;
+
+ if (rssi > -120) {
+ ret = 120 + rssi;
+ }
+
+ if (ret > 100) {
+ ret = 100;
+ }
+ return ret;
+}
+
+static void
+dump_info_from_iter(
+ FILE* file, DBusMessageIter *iter, int indent, bool bare
+ )
+{
+ DBusMessageIter sub_iter;
+ int i;
+
+ if (!bare) for (i = 0; i < indent; i++) fprintf(file, "\t");
+
+ switch (dbus_message_iter_get_arg_type(iter)) {
+ case DBUS_TYPE_DICT_ENTRY:
+ dbus_message_iter_recurse(iter, &sub_iter);
+ dump_info_from_iter(file, &sub_iter, indent + 1, true);
+ fprintf(file, " => ");
+ dbus_message_iter_next(&sub_iter);
+ dump_info_from_iter(file, &sub_iter, indent + 1, true);
+ break;
+ case DBUS_TYPE_ARRAY:
+ dbus_message_iter_recurse(iter, &sub_iter);
+ if (dbus_message_iter_get_arg_type(&sub_iter) == DBUS_TYPE_BYTE ||
+ dbus_message_iter_get_arg_type(&sub_iter) == DBUS_TYPE_INVALID) {
+ fprintf(file, "[");
+ indent = 0;
+ } else {
+ fprintf(file, "[\n");
+ }
+
+ for (;
+ dbus_message_iter_get_arg_type(&sub_iter) != DBUS_TYPE_INVALID;
+ dbus_message_iter_next(&sub_iter)) {
+ dump_info_from_iter(file,
+ &sub_iter,
+ indent + 1,
+ dbus_message_iter_get_arg_type(&sub_iter) == DBUS_TYPE_BYTE);
+ }
+ for (i = 0; i < indent; i++) fprintf(file, "\t");
+ fprintf(file, "]");
+
+ break;
+ case DBUS_TYPE_VARIANT:
+ dbus_message_iter_recurse(iter, &sub_iter);
+ dump_info_from_iter(file, &sub_iter, indent, true);
+ break;
+ case DBUS_TYPE_STRING:
+ {
+ const char* string;
+ dbus_message_iter_get_basic(iter, &string);
+ fprintf(file, "\"%s\"", string);
+ }
+ break;
+
+ case DBUS_TYPE_BYTE:
+ {
+ uint8_t v;
+ dbus_message_iter_get_basic(iter, &v);
+ fprintf(file, "%02X", v);
+ }
+ break;
+ case DBUS_TYPE_UINT16:
+ {
+ uint16_t v;
+ dbus_message_iter_get_basic(iter, &v);
+ fprintf(file, "0x%04X", v);
+ }
+ break;
+ case DBUS_TYPE_INT16:
+ {
+ int16_t v;
+ dbus_message_iter_get_basic(iter, &v);
+ fprintf(file, "%d", v);
+ }
+ break;
+ case DBUS_TYPE_UINT32:
+ {
+ uint32_t v;
+ dbus_message_iter_get_basic(iter, &v);
+ fprintf(file, "%d", v);
+ }
+ break;
+ case DBUS_TYPE_BOOLEAN:
+ {
+ dbus_bool_t v;
+ dbus_message_iter_get_basic(iter, &v);
+ fprintf(file, "%s", v ? "true" : "false");
+ }
+ break;
+ case DBUS_TYPE_INT32:
+ {
+ int32_t v;
+ dbus_message_iter_get_basic(iter, &v);
+ fprintf(file, "%d", v);
+ }
+ break;
+ case DBUS_TYPE_UINT64:
+ {
+ uint64_t v;
+ dbus_message_iter_get_basic(iter, &v);
+ fprintf(file, "0x%016llX", (unsigned long long)v);
+ }
+ break;
+ default:
+ fprintf(file, "<%s>",
+ dbus_message_type_to_string(dbus_message_iter_get_arg_type(iter)));
+ break;
+ }
+ if (!bare)
+ fprintf(file, "\n");
+}
+
+static int
+parse_network_info_from_iter(
+ struct wpan_network_info_s *network_info, DBusMessageIter *iter
+ )
+{
+ int ret = 0;
+ DBusMessageIter outer_iter;
+ DBusMessageIter dict_iter;
+
+ if (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_ARRAY) {
+ dbus_message_iter_recurse(iter, &outer_iter);
+ iter = &outer_iter;
+ }
+
+ memset(network_info, 0, sizeof(*network_info));
+
+ for (;
+ dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID;
+ dbus_message_iter_next(iter)) {
+ DBusMessageIter value_iter;
+ char* key;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY) {
+ DBG(
+ "error: Bad type for network (%c)\n",
+ dbus_message_iter_get_arg_type(iter));
+ ret = -1;
+ goto bail;
+ }
+
+ dbus_message_iter_recurse(iter, &dict_iter);
+
+ if (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_STRING) {
+ DBG(
+ "error: Bad type for network list (%c)\n",
+ dbus_message_iter_get_arg_type(&dict_iter));
+ ret = -1;
+ goto bail;
+ }
+
+ // Get the key
+ dbus_message_iter_get_basic(&dict_iter, &key);
+ dbus_message_iter_next(&dict_iter);
+
+ if (key == NULL) {
+ ret = -EINVAL;
+ goto bail;
+
+ }
+
+ if (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_VARIANT) {
+ DBG(
+ "error: Bad type for network list (%c)\n",
+ dbus_message_iter_get_arg_type(&dict_iter));
+ ret = -1;
+ goto bail;
+ }
+
+ dbus_message_iter_recurse(&dict_iter, &value_iter);
+
+ if (strcmp(key, kWPANTUNDProperty_NetworkName) == 0 || strcmp(key, "NetworkName") == 0) {
+ char* network_name = NULL;
+ dbus_message_iter_get_basic(&value_iter, &network_name);
+ snprintf(network_info->network_name,
+ sizeof(network_info->network_name), "%s", network_name);
+ } else if ((strcmp(key, kWPANTUNDProperty_NCPChannel) == 0) || strcmp(key, "Channel") == 0) {
+ dbus_message_iter_get_basic(&value_iter, &network_info->channel);
+ } else if ((strcmp(key, kWPANTUNDProperty_NetworkPANID) == 0) || strcmp(key, "PanId") == 0) {
+ dbus_message_iter_get_basic(&value_iter, &network_info->pan_id);
+ } else if ((strcmp(key, kWPANTUNDProperty_NetworkXPANID) == 0) || strcmp(key, "XPanId") == 0) {
+ dbus_message_iter_get_basic(&value_iter, &network_info->xpanid);
+ } else if ((strcmp(key, kWPANTUNDProperty_NestLabs_NetworkAllowingJoin) == 0) || strcmp(key, "AllowingJoin") == 0) {
+ dbus_message_iter_get_basic(&value_iter,
+ &network_info->allowing_join);
+ } else if ((strcmp(key, kWPANTUNDProperty_NCPHardwareAddress) == 0) || strcmp(key, "BeaconHWAddr") == 0) {
+ DBusMessageIter array_iter;
+ dbus_message_iter_recurse(&value_iter, &array_iter);
+ const uint8_t* value = NULL;
+ int nelements = 0;
+ dbus_message_iter_get_fixed_array(&array_iter, &value, &nelements);
+ if (value != NULL && nelements == 8)
+ memcpy(network_info->hwaddr, value, 8);
+ } else if (strcmp(key, kWPANTUNDProperty_IPv6MeshLocalPrefix) == 0) {
+ int value_dbus_type = dbus_message_iter_get_arg_type(&value_iter);
+ if (value_dbus_type == DBUS_TYPE_STRING) {
+ const char *prefix_cstr = NULL;
+ dbus_message_iter_get_basic(&value_iter, &prefix_cstr);
+ parse_prefix_string(prefix_cstr, network_info->prefix);
+ } else if (value_dbus_type == DBUS_TYPE_ARRAY) {
+ DBusMessageIter array_iter;
+ dbus_message_iter_recurse(&value_iter, &array_iter);
+ const uint8_t *value = NULL;
+ int nelements = 0;
+ dbus_message_iter_get_fixed_array(&array_iter, &value, &nelements);
+ if (value != NULL && nelements == 8) {
+ memcpy(network_info->prefix, value, 8);
+ }
+ } else {
+ DBG("Unexpected dbus type %c for %s", value_dbus_type, kWPANTUNDProperty_IPv6MeshLocalPrefix);
+ memset(network_info->prefix, 0 , sizeof(network_info->prefix));
+ }
+ } else if (strcmp(key, "RSSI") == 0) {
+ int8_t rssi;
+ dbus_message_iter_get_basic(&value_iter, &rssi);
+ network_info->rssi = rssi;
+ } else {
+#if DEBUG
+ DBG(
+ "info: %s -> (%c)\n",
+ key,
+ dbus_message_iter_get_arg_type(&value_iter));
+#endif
+ }
+ }
+
+bail:
+ if (ret) DBG("Network parse failed.\n");
+ return ret;
+}
+
+/* -------------------------------------------------------------------------- */
+// MARK: - LoWPAN Network
+
+static struct connman_network*
+get_network_from_iter(
+ struct connman_device* device, DBusMessageIter *iter
+ )
+{
+ const char* new_state = NULL;
+ struct connman_network *network = NULL;
+ struct wpan_network_info_s network_info = {};
+ char network_identifier[256];
+ const char * group_identifier = network_identifier;
+ char hwaddr_str[256];
+ struct lowpan_network_s *network_data = NULL;
+
+ if (parse_network_info_from_iter(&network_info, iter) != 0) {
+ goto bail;
+ }
+
+ if (!network_info.network_name[0]) {
+ goto bail;
+ }
+
+ if (network_info.xpanid == 0) {
+ goto bail;
+ }
+
+ encode_data_into_b16_string(
+ (const uint8_t*)network_info.network_name,
+ strlen(network_info.network_name),
+ network_identifier,
+ sizeof(network_identifier),
+ 0
+ );
+
+ encode_data_into_b16_string(
+ (const uint8_t*)network_info.hwaddr,
+ 8,
+ hwaddr_str,
+ sizeof(hwaddr_str),
+ 0
+ );
+
+ snprintf(network_identifier + strlen(network_identifier),
+ sizeof(network_identifier) - strlen(
+ network_identifier), "_x%016llX", (unsigned long long)network_info.xpanid);
+
+ network = connman_device_get_network(device, network_identifier);
+
+ if (!network) {
+ network = connman_network_create(
+ network_identifier,
+ CONNMAN_NETWORK_TYPE_LOWPAN
+ );
+ network_data = (struct lowpan_network_s *)calloc(1,sizeof(struct lowpan_network_s));
+ network_data->network_info = network_info;
+ network_data->node_type = WPAN_IFACE_ROLE_ROUTER;
+ connman_network_set_data(network, network_data);
+ connman_network_set_string(network, LOWPAN_SECURITY_KEY, "psk");
+
+ connman_device_add_network(device, network);
+
+ connman_network_unref(network);
+
+ connman_network_set_strength(network,
+ CalculateStrengthFromRSSI(network_info.rssi));
+ connman_network_set_name(network, network_info.network_name);
+
+ // Set network extended ID before a service is created from network
+ // since this information is needed when service loads provision.
+ connman_network_set_lowpan_xpan_id(network, network_data->network_info.xpanid);
+
+ connman_network_set_group(network, group_identifier);
+ connman_network_set_index(network, -1);
+
+ DBG("New Network: %p ident:%s group:%s", network, network_identifier, group_identifier);
+ } else {
+ network_data = connman_network_get_data(network);
+ network_data->network_info = network_info;
+ }
+
+ connman_network_set_bool(network, LOWPAN_PERMIT_JOINING_KEY, network_data->network_info.allowing_join);
+ connman_network_set_string(network, LOWPAN_PARENT_ADDRESS_KEY, hwaddr_str);
+
+bail:
+
+ DBG("%p NetworkFromIter: %p", device, network);
+ return network;
+}
+
+
+static void
+network_unref_callback(void* user_data)
+{
+ struct connman_network *network = (struct connman_network *)user_data;
+
+ connman_network_unref(network);
+}
+
+static int
+lowpan_network_probe(struct connman_network *network)
+{
+ DBG("%p %s", network, connman_network_get_identifier(network));
+
+ return 0;
+}
+
+static void
+lowpan_network_remove(struct connman_network *network)
+{
+ DBG("%p %s", network, connman_network_get_identifier(network));
+
+ struct lowpan_network_s *network_data =
+ (struct lowpan_network_s *)connman_network_get_data(network);
+
+ if(network_data) {
+ connman_network_set_name(network, "X");
+ connman_network_set_group(network, "X");
+
+ free(network_data);
+ connman_network_set_data(network, NULL);
+ }
+
+}
+
+static void
+join_finished_callback(
+ DBusPendingCall *pending, void* user_data
+ )
+{
+ int32_t ret = 0;
+ struct connman_network *network = (struct connman_network *)user_data;
+ struct connman_device* device = NULL;
+ struct lowpan_device_s *device_info = NULL;
+ DBusMessage* reply = dbus_pending_call_steal_reply(pending);
+ DBusMessageIter iter;
+ DBusMessageIter list_iter;
+
+ // network will never be NULL in this callback.
+
+ DBG("%p %s", network, connman_network_get_identifier(network));
+
+ device = connman_network_get_device(network);
+
+ require_action(device != NULL, bail, ret = -ENODEV);
+
+ device_info = (struct lowpan_device_s *)connman_device_get_data(device);
+
+ require_action(device_info != NULL, bail, ret = -ENODEV);
+ require_action(reply != NULL, bail, ret = -EINVAL);
+
+ dbus_message_iter_init(reply, &iter);
+
+ // Get return code
+ dbus_message_iter_get_basic(&iter, &ret);
+
+bail:
+ if (reply) {
+ dbus_message_unref(reply);
+ }
+ if (pending) {
+ dbus_pending_call_unref(pending);
+ }
+
+ if ((ret != 0) && (ret != -EINPROGRESS) && (ret != kWPANTUNDStatus_InProgress)) {
+ DBG("%p Join/Resume returned failure: %d", network, ret);
+
+ if((device_info != NULL) && ncp_state_is_has_joined(device_info->ncp_state)) {
+ DBG("%p ... But we seem to have connected anyway. Ignoring the error.", network);
+ ret = 0;
+ } else {
+ connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
+ }
+ }
+
+ if (ret == 0) {
+ connman_network_set_connected(network, TRUE);
+ }
+
+ return;
+}
+
+static int
+lowpan_network_connect_using_join(struct connman_network *network)
+{
+ int ret = -EINVAL;
+ DBG("%p %s", network, connman_network_get_identifier(network));
+ struct connman_device* device = connman_network_get_device(network);
+ DBusPendingCall *pending_call = NULL;
+ DBusMessage *message = NULL;
+ char dbus_path[DBUS_MAXIMUM_NAME_LENGTH];
+ struct lowpan_network_s *network_data =
+ (struct lowpan_network_s *)connman_network_get_data(network);
+
+ require_action(device != NULL, bail, ret = -ENODEV);
+
+ require_action(network_data != NULL, bail, ret = -ENODEV);
+
+ struct lowpan_device_s *device_info =
+ (struct lowpan_device_s *)connman_device_get_data(device);
+
+ require_action(device_info != NULL, bail, ret = -ENODEV);
+
+ snprintf(dbus_path,
+ sizeof(dbus_path),
+ "%s/%s",
+ WPAN_TUNNEL_DBUS_PATH,
+ connman_device_get_ident(device));
+
+ message = dbus_message_new_method_call(
+ WPAN_TUNNEL_DBUS_NAME,
+ dbus_path,
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_IFACE_CMD_JOIN
+ );
+ const char* network_name = network_data->network_info.network_name;
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_STRING, &network_name,
+ DBUS_TYPE_INVALID
+ );
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_INT16, &network_data->node_type,
+ DBUS_TYPE_INVALID
+ );
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_UINT64, &network_data->network_info.xpanid,
+ DBUS_TYPE_INVALID
+ );
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_UINT16, &network_data->network_info.pan_id,
+ DBUS_TYPE_INVALID
+ );
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_BYTE, &network_data->network_info.channel,
+ DBUS_TYPE_INVALID
+ );
+
+
+ if (!dbus_connection_send_with_reply(
+ connection,
+ message,
+ &pending_call,
+ 45000
+ )
+ ) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ connman_network_ref(network);
+
+ if (!dbus_pending_call_set_notify(
+ pending_call,
+ &join_finished_callback,
+ (void*)network,
+ (DBusFreeFunction) & network_unref_callback
+ )
+ ) {
+ dbus_pending_call_cancel(pending_call);
+ connman_network_unref(network);
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ ret = -EINPROGRESS;
+
+
+bail:
+ if(message)
+ dbus_message_unref(message);
+ return ret;
+}
+
+static int
+lowpan_network_connect_using_resume(struct connman_network *network)
+{
+ int ret = -EINVAL;
+
+ DBG("%p %s", network, connman_network_get_identifier(network));
+ struct connman_device* device = connman_network_get_device(network);
+ DBusPendingCall *pending_call = NULL;
+ DBusMessage *message = NULL;
+ char dbus_path[DBUS_MAXIMUM_NAME_LENGTH];
+
+ require_action(device != NULL, bail, ret = -ENODEV);
+
+ struct lowpan_device_s *device_info =
+ (struct lowpan_device_s *)connman_device_get_data(device);
+
+ require_action(device_info != NULL, bail, ret = -ENODEV);
+
+ snprintf(dbus_path,
+ sizeof(dbus_path),
+ "%s/%s",
+ WPAN_TUNNEL_DBUS_PATH,
+ connman_device_get_ident(device));
+
+ message = dbus_message_new_method_call(
+ WPAN_TUNNEL_DBUS_NAME,
+ dbus_path,
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_IFACE_CMD_RESUME
+ );
+
+ if (!dbus_connection_send_with_reply(
+ connection,
+ message,
+ &pending_call,
+ 30000 // Thirty seconds
+ )) {
+ ret = -1;
+ goto bail;
+ }
+
+ connman_network_ref(network);
+
+ if (!dbus_pending_call_set_notify(
+ pending_call,
+ &join_finished_callback,
+ (void*)network,
+ (DBusFreeFunction) & network_unref_callback
+ )
+ ) {
+ dbus_pending_call_cancel(pending_call);
+ connman_network_unref(network);
+ ret = -EINVAL;
+ return -1;
+ }
+
+ DBG("Now waiting for resume to complete...");
+
+ ret = -EINPROGRESS;
+
+bail:
+ if(message)
+ dbus_message_unref(message);
+ return ret;
+}
+
+static void
+lowpan_network_update_key(struct connman_network *network, const uint8_t* data, size_t len)
+{
+ char key_cstr[16*2+1];
+
+ DBG("%p %s", network, connman_network_get_identifier(network));
+
+ if (len != 0) {
+ encode_data_into_b16_string(data, len, key_cstr, sizeof(key_cstr), 0);
+ connman_network_set_string(network, LOWPAN_AUTH_KEY, key_cstr);
+ connman_network_update(network);
+ }
+}
+
+static void
+_lowpan_network_update_key_from_ncp_callback(void* context, int error, const uint8_t* data, size_t len)
+{
+ struct connman_network *network = context;
+ DBG("%p %s", network, connman_network_get_identifier(network));
+ if (error == 0) {
+ lowpan_network_update_key(network, data, len);
+ }
+
+ struct connman_device* device = connman_network_get_device(network);
+
+ if (!device) {
+ DBG("NO DEVICE!");
+ return;
+ }
+
+ struct lowpan_device_s *device_info =
+ (struct lowpan_device_s *)connman_device_get_data(device);
+
+ if (!device_info) {
+ DBG("NO DEVICE INFO!");
+ return;
+ }
+
+ if (ncp_state_is_has_joined(device_info->ncp_state)
+ && !connman_network_get_connected(network)
+ && !connman_network_get_connecting(network)
+ && !connman_network_get_associating(network)
+ ) {
+ DBG("We got the network key, asking connman to connect...");
+ connman_service_connect(connman_service_lookup_from_network(network),
+ CONNMAN_SERVICE_CONNECT_REASON_USER);
+ }
+
+ connman_network_unref(network);
+}
+
+static int
+lowpan_network_update_key_from_ncp(struct connman_network *network)
+{
+ int ret = 0;
+ struct connman_device* device = connman_network_get_device(network);
+ if (!device) {
+ ret = -ENODEV;
+ goto bail;
+ }
+
+ DBG("%p %s", network, connman_network_get_identifier(network));
+
+ connman_network_ref(network);
+
+ ret = lowpan_driver_getprop_data(
+ device,
+ kWPANTUNDProperty_NetworkKey,
+ &_lowpan_network_update_key_from_ncp_callback,
+ network
+ );
+
+ if(ret != 0)
+ goto bail;
+
+bail:
+ return ret;
+}
+
+static int
+lowpan_network_set_key_on_ncp(struct connman_network *network)
+{
+ int ret = 0;
+ struct connman_device* device = connman_network_get_device(network);
+ DBG("%p %s", network, connman_network_get_identifier(network));
+ if (!device) {
+ ret = -ENODEV;
+ goto bail;
+ }
+ uint8_t key[16];
+ unsigned int size = sizeof(key);
+ const char* key_cstr = connman_network_get_string(network, LOWPAN_AUTH_KEY);
+
+ if (key_cstr) {
+ size = parse_string_into_data(key, size, key_cstr);
+
+ if (size > sizeof(key)) {
+ connman_warn("Key is too large: %d (max %d)", size, (int)sizeof(key));
+ ret = -EINVAL;
+ } else if (sizeof(key) != size) {
+ connman_warn("Key-size mismatch (Expecting %d, but key was %d bytes long)", (int)sizeof(key), size);
+ }
+ } else {
+#if 0
+ size = 16;
+ memset(key,0,sizeof(key));
+ size = sizeof(key);
+ connman_warn("No valid key specified for %s, using all-zeros...", connman_network_get_identifier(network));
+#else
+ ret = -ENOKEY;
+ DBG("No key to set!");
+#endif
+ }
+
+ if (ret == 0) {
+ DBG("Setting the key at %p for the service...", key);
+ ret = lowpan_driver_setprop_data(device, kWPANTUNDProperty_NetworkKey, key, size);
+ }
+
+bail:
+ return ret;
+}
+
+static int
+lowpan_network_connect(struct connman_network *network)
+{
+ int ret = -EINVAL;
+ struct connman_device* device = connman_network_get_device(network);
+
+ DBG("%p %s", network, connman_network_get_identifier(network));
+
+ if (!device) {
+ ret = -ENODEV;
+ goto bail;
+ }
+
+ struct lowpan_device_s *device_info =
+ (struct lowpan_device_s *)connman_device_get_data(device);
+
+ if (!device_info) {
+ ret = -ENODEV;
+ goto bail;
+ }
+
+ if (device_info->ncp_state == NCP_STATE_UPGRADING) {
+ // We can't connect while upgrading.
+ ret = -EBUSY;
+ goto bail;
+ } else if (ncp_state_is_not_associated(device_info->ncp_state)) {
+ lowpan_device_set_network(device, network);
+ ret = lowpan_network_connect_using_join(network);
+ } else if (device_info->ncp_state == NCP_STATE_COMMISSIONED) {
+ if (device_info->current_network == network) {
+ // Do not auto-resume, this is performed automatically by wpantund.
+ // TODO: Check if Autoresume is enabled and allow this if not.
+ // ret = lowpan_network_connect_using_resume(network);
+
+ // Since we know Autoresume is on, we return -EINPROGRESS.
+ ret = -EINPROGRESS;
+ } else {
+ ret = -EBUSY;
+ }
+ } else if (device_info->ncp_state == NCP_STATE_CREDENTIALS_NEEDED) {
+ if (device_info->current_network == network) {
+ ret = lowpan_network_set_key_on_ncp(network);
+
+ if (-ENOKEY == ret) {
+ ret = connman_network_needs_input(network);
+ if (0 != ret) {
+ DBG("connman_network_needs_input(network) failed with %d", ret);
+ }
+ }
+
+ if ((0 != ret) && (-EINPROGRESS != ret)) {
+ connman_network_set_associating(network, false);
+ lowpan_device_leave(device);
+ }
+
+ if (0 == ret) {
+ ret = -EINPROGRESS;
+ }
+ } else {
+ DBG("%p Aborting connection in progress", network);
+ lowpan_device_leave(device);
+ ret = -EAGAIN;
+ }
+ } else if (device_info->ncp_state == NCP_STATE_ASSOCIATING) {
+ if (device_info->current_network == network) {
+ DBG("%p Already connecting to THIS network!", network);
+ ret = -EINPROGRESS;
+ } else {
+ DBG("%p Already connecting to a different network!", network);
+ ret = -EINVAL;
+ }
+ } else if (ncp_state_is_has_joined(device_info->ncp_state)) {
+ if (device_info->current_network == network) {
+ DBG("%p Already connected to THIS network!", network);
+ ret = 0;
+ connman_network_set_connected(network, TRUE);
+ } else if(device_info->current_network && 0 == strcmp(connman_network_get_group(device_info->current_network),connman_network_get_group(network))) {
+ DBG("%p Already connected to THIS service!", network);
+ ret = 0;
+ connman_network_unref(device_info->current_network);
+ device_info->current_network = network;
+ connman_network_ref(device_info->current_network);
+ connman_network_set_connected(network, TRUE);
+ } else {
+ DBG("%p Already connected to an entirely different network, %s!", network, connman_network_get_identifier(device_info->current_network));
+ ret = -EINVAL;
+ }
+ }
+
+bail:
+ DBG("%p ret=%d", network, ret);
+ return ret;
+}
+
+static void
+disconnect_finished_callback(
+ DBusPendingCall *pending, void* user_data
+ )
+{
+}
+
+
+void
+lowpan_device_leave(struct connman_device *device)
+{
+ DBusMessage *message = NULL;
+ char dbus_path[DBUS_MAXIMUM_NAME_LENGTH];
+
+ snprintf(dbus_path,
+ sizeof(dbus_path),
+ "%s/%s",
+ WPAN_TUNNEL_DBUS_PATH,
+ connman_device_get_ident(device));
+
+ message = dbus_message_new_method_call(
+ WPAN_TUNNEL_DBUS_NAME,
+ dbus_path,
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_IFACE_CMD_LEAVE
+ );
+
+ dbus_connection_send(connection, message, NULL);
+
+ if(message)
+ dbus_message_unref(message);
+}
+
+static void
+lowpan_device_reset(struct connman_device *device)
+{
+ DBusMessage *message = NULL;
+ char dbus_path[DBUS_MAXIMUM_NAME_LENGTH];
+
+ snprintf(dbus_path,
+ sizeof(dbus_path),
+ "%s/%s",
+ WPAN_TUNNEL_DBUS_PATH,
+ connman_device_get_ident(device));
+
+ message = dbus_message_new_method_call(
+ WPAN_TUNNEL_DBUS_NAME,
+ dbus_path,
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_IFACE_CMD_RESET
+ );
+
+ dbus_connection_send(connection, message, NULL);
+
+ if(message)
+ dbus_message_unref(message);
+}
+
+
+static int
+lowpan_network_disconnect(struct connman_network *network, bool user_initiated)
+{
+ int ret = -EINVAL;
+ bool should_reset = false;
+ struct connman_device* device = connman_network_get_device(network);
+ struct lowpan_device_s *device_info =
+ (struct lowpan_device_s *)connman_device_get_data(device);
+
+ DBG("%p %s", network, connman_network_get_identifier(network));
+
+ if (!device) {
+ ret = -ENODEV;
+ goto bail;
+ }
+
+ if (!device_info) {
+ ret = -ENODEV;
+ goto bail;
+ }
+
+ if (device_info->current_network != network) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ connman_network_set_connected(network, FALSE);
+
+ switch(device_info->ncp_state) {
+ case NCP_STATE_ASSOCIATING:
+ case NCP_STATE_CREDENTIALS_NEEDED:
+ should_reset = true;
+ break;
+
+ case NCP_STATE_OFFLINE:
+ user_initiated = TRUE;
+ break;
+ default:
+ break;
+ }
+
+ if (user_initiated) {
+ lowpan_device_leave(device);
+ } else if (should_reset) {
+ lowpan_device_reset(device);
+ }
+
+ ret = 0;
+
+bail:
+ DBG("%p ret=%d", network, ret);
+ return ret;
+}
+
+int
+lowpan_driver_setprop_int32(struct connman_device *device, const char* key, int32_t value)
+{
+ int ret = 0;
+ DBusMessage *message = NULL;
+ char dbus_path[128];
+
+ snprintf(dbus_path,
+ sizeof(dbus_path),
+ "%s/%s",
+ WPAN_TUNNEL_DBUS_PATH,
+ connman_device_get_ident(device));
+
+ message = dbus_message_new_method_call(
+ WPAN_TUNNEL_DBUS_NAME,
+ dbus_path,
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_IFACE_CMD_SET_PROP
+ );
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_STRING, &key,
+ DBUS_TYPE_INT32, &value,
+ DBUS_TYPE_INVALID
+ );
+
+ if (!dbus_connection_send(
+ connection,
+ message,
+ NULL)) {
+ dbus_message_unref(message);
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+bail:
+ if(message)
+ dbus_message_unref(message);
+ return ret;
+}
+
+int
+lowpan_driver_setprop_data(struct connman_device *device, const char* key, const uint8_t* data, size_t size)
+{
+ int ret = 0;
+ DBusMessage *message = NULL;
+ char dbus_path[128];
+
+ snprintf(dbus_path,
+ sizeof(dbus_path),
+ "%s/%s",
+ WPAN_TUNNEL_DBUS_PATH,
+ connman_device_get_ident(device));
+
+ message = dbus_message_new_method_call(
+ WPAN_TUNNEL_DBUS_NAME,
+ dbus_path,
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_IFACE_CMD_SET_PROP
+ );
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_STRING, &key,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &data, size,
+ DBUS_TYPE_INVALID
+ );
+
+ if (!dbus_connection_send(
+ connection,
+ message,
+ NULL)) {
+ dbus_message_unref(message);
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+bail:
+ if(message)
+ dbus_message_unref(message);
+ return ret;
+}
+
+struct lowpan_driver_getprop_state_s {
+ void(*callback)(void* context, int err, const uint8_t* data, size_t len);
+ void* context;
+ struct connman_device* device;
+};
+
+static void
+_lowpan_driver_getprop_data_free(void* user_data)
+{
+ struct lowpan_driver_getprop_state_s* state = user_data;
+ DBG("%p device:%p", state, state->device);
+// DBG("%p %s", state->device, connman_device_get_ident(state->device));
+
+ if (NULL != state->callback) {
+ (*state->callback)(state->context, -1, NULL, 0);
+ state->callback = NULL;
+ }
+ if(state->device)
+ connman_device_unref(state->device);
+ free(state);
+}
+
+static void
+_lowpan_driver_getprop_data_callback(
+ DBusPendingCall *pending, void* user_data
+ )
+{
+ int32_t ret = 0;
+ struct lowpan_driver_getprop_state_s* state = user_data;
+ DBusMessage* reply = dbus_pending_call_steal_reply(pending);
+ DBusMessageIter iter;
+ const uint8_t* value = NULL;
+ int nelements = 0;
+
+ if (!state) {
+ goto bail;
+ }
+
+ DBG("%p device:%p", state, state->device);
+// DBG("%p %s", state->device, connman_device_get_ident(state->device));
+
+ if (!reply) {
+ DBG("No reply...?");
+ goto bail;
+ }
+
+ dbus_message_iter_init(reply, &iter);
+
+ // Get return code
+ dbus_message_iter_get_basic(&iter, &ret);
+ dbus_message_iter_next(&iter);
+
+ if (ret == 0) {
+ DBusMessageIter array_iter;
+ dbus_message_iter_recurse(&iter, &array_iter);
+ dbus_message_iter_get_fixed_array(&array_iter, &value, &nelements);
+ }
+
+ if (NULL != state->callback) {
+ (*state->callback)(state->context, ret, value, nelements);
+ state->callback = NULL;
+ }
+
+bail:
+ if (reply) {
+ dbus_message_unref(reply);
+ }
+ if (pending) {
+ dbus_pending_call_unref(pending);
+ }
+
+ DBG("%p ret = %d", state->device, ret);
+ return;
+}
+
+int
+lowpan_driver_getprop_data(struct connman_device *device, const char* key, void(*callback)(void* context, int err, const uint8_t* data, size_t len), void* context)
+{
+ int ret = 0;
+ DBusMessage *message = NULL;
+ DBusPendingCall *pending_call = NULL;
+ struct lowpan_driver_getprop_state_s* state = NULL;
+ char dbus_path[128];
+
+ DBG("%p %s key:%s", device, connman_device_get_ident(device),key);
+
+ snprintf(dbus_path,
+ sizeof(dbus_path),
+ "%s/%s",
+ WPAN_TUNNEL_DBUS_PATH,
+ connman_device_get_ident(device));
+
+ message = dbus_message_new_method_call(
+ WPAN_TUNNEL_DBUS_NAME,
+ dbus_path,
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_IFACE_CMD_GET_PROP
+ );
+
+ state = calloc(sizeof(*state),1);
+ if(!state) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+ state->context = context;
+ state->callback = callback;
+ state->device = device;
+ connman_device_ref(device);
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_STRING, &key,
+ DBUS_TYPE_INVALID
+ );
+
+ if (!dbus_connection_send_with_reply(
+ connection,
+ message,
+ &pending_call,
+ 10000 // Ten seconds
+ )
+ ) {
+ ret = -ENOMEM;
+ goto bail;
+ }
+
+ if (!dbus_pending_call_set_notify(
+ pending_call,
+ &_lowpan_driver_getprop_data_callback,
+ (void*)state,
+ &_lowpan_driver_getprop_data_free
+ )
+ ) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ DBG("state:%p device:%p ret = %d",state, state->device, ret);
+
+ pending_call = NULL;
+ state = NULL;
+
+bail:
+ DBG("device:%p ret = %d",device, ret);
+
+ if(state)
+ _lowpan_driver_getprop_data_free((void*)state);
+ if(message)
+ dbus_message_unref(message);
+ if(pending_call)
+ dbus_pending_call_cancel(pending_call);
+
+ return ret;
+}
+
+
+static struct connman_network_driver lowpan_network_driver = {
+ .name = "lowpan",
+ .type = CONNMAN_NETWORK_TYPE_LOWPAN,
+ .priority = CONNMAN_NETWORK_PRIORITY_LOW,
+ .probe = lowpan_network_probe,
+ .remove = lowpan_network_remove,
+ .connect = lowpan_network_connect,
+ .disconnect = lowpan_network_disconnect,
+};
+
+/* -------------------------------------------------------------------------- */
+// MARK: - LoWPAN Device
+
+void
+lowpan_device_set_network(struct connman_device *device, struct connman_network *network)
+{
+ struct lowpan_device_s *device_info =
+ (struct lowpan_device_s *)connman_device_get_data(device);
+
+ if (network != device_info->current_network) {
+ DBG("%p Request to change current network from %p (\"%s\") to %p (\"%s\").", device, device_info->current_network,device_info->current_network?connman_network_get_identifier(device_info->current_network):NULL,network,network?connman_network_get_identifier(network):NULL);
+ if(device_info->current_network
+ && network
+ && 0 == strcmp(connman_network_get_group(device_info->current_network),connman_network_get_group(network)))
+ {
+ if(connman_network_get_connected(device_info->current_network)
+ || connman_network_get_connecting(device_info->current_network)
+ || connman_network_get_associating(device_info->current_network)
+ ) {
+ DBG("%p Networks are a part of the same group and a connection is in progress. Network change aborted.", device);
+
+ return;
+ }
+ }
+
+ if (device_info->current_network != NULL) {
+ connman_network_set_index(device_info->current_network, -1);
+ connman_network_unref(device_info->current_network);
+ }
+ device_info->current_network = network;
+ if (device_info->current_network != NULL)
+ connman_network_ref(device_info->current_network);
+ DBG("%p Network change complete.", device);
+ }
+}
+
+int
+lowpan_device_handle_state_change(
+ struct connman_device* device,
+ ncp_state_t new_state,
+ struct connman_network* network
+ )
+{
+ int ret;
+ struct lowpan_device_s *device_info =
+ (struct lowpan_device_s *)connman_device_get_data(device);
+
+ if (!ncp_state_is_not_associated(new_state) && !network) {
+ network = device_info->current_network;
+ }
+
+ DBG("%s %d network %p", connman_device_get_ident(device), new_state, network);
+
+ if (network == device_info->current_network
+ && (new_state == device_info->ncp_state)
+ && (new_state != NCP_STATE_ASSOCIATED)
+ ) {
+ DBG("%s State was already %d", connman_device_get_ident(device), new_state);
+
+ // Skip when nothing has really changed.
+ return 0;
+ }
+
+ if (ncp_state_is_not_associated(new_state)) {
+ // If the previous NCP state is also 'disconnected' or 'uninitialized' ignore the new state change
+ if (ncp_state_is_not_associated(device_info->ncp_state)) {
+ // In case of connecting to a network from 'deep-sleep' we get a 'disconnected' state before change
+ // to 'joining'. In this case, we should ignore the 'disconnected' state change as to not remove the
+ // current_network we are attempting to connect to and fail to connect/join.
+ device_info->ncp_state = new_state;
+ DBG("%s State was already effectively %d", connman_device_get_ident(device), new_state);
+ return 0;
+ }
+
+ connman_device_set_disconnected(device, TRUE);
+
+ if (device_info->current_network != NULL) {
+ memset(&device_info->current_network_info,0,sizeof(device_info->current_network_info));
+ if (connman_network_get_connecting(device_info->current_network))
+ connman_network_set_error(device_info->current_network, CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
+ else if (connman_network_get_associating(device_info->current_network))
+ connman_network_set_error(device_info->current_network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
+ else
+ connman_network_set_connected(device_info->current_network, FALSE);
+ }
+ network = NULL;
+ }
+
+ lowpan_device_set_network(device, network);
+ network = device_info->current_network;
+
+ if (ncp_state_is_initializing(new_state)) {
+ return 0;
+ }
+
+ device_info->ncp_state = new_state;
+
+ if (network) {
+ if (new_state == NCP_STATE_COMMISSIONED) {
+ if (connman_network_get_connected(network)) {
+ // Do not auto-resume, this is performed automatically by wpantund.
+ // TODO: Check if Autoresume is enabled and allow this if not.
+ // lowpan_network_connect_using_resume(network);
+ } else if (connman_network_get_connecting(network)
+ || connman_network_get_associating(network)
+ ) {
+ connman_network_set_error(network, CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
+ } else {
+ connman_service_connect(connman_service_lookup_from_network(network),
+ CONNMAN_SERVICE_CONNECT_REASON_USER);
+ }
+ } else if (new_state == NCP_STATE_ASSOCIATING) {
+
+ } else if (new_state == NCP_STATE_CREDENTIALS_NEEDED) {
+ if (connman_network_get_associating(network)) {
+ int err;
+
+ connman_service_create_ip6config(connman_service_lookup_from_network(network), connman_device_get_index(device));
+ connman_network_set_index(network, connman_device_get_index(device));
+ connman_network_set_ipv4_method(network, CONNMAN_IPCONFIG_METHOD_OFF);
+ connman_network_set_ipv6_method(network, CONNMAN_IPCONFIG_METHOD_FIXED);
+
+ err = lowpan_network_set_key_on_ncp(network);
+ if (-ENOKEY == err) {
+ err = connman_network_needs_input(network);
+ if (0 != err) {
+ DBG("connman_network_needs_input(network) failed with %d", err);
+ }
+ }
+
+ if ((0 != err) && (-EINPROGRESS != err)) {
+ connman_network_set_associating(network, false);
+ lowpan_device_leave(device);
+ }
+ }
+
+
+ } else if (new_state == NCP_STATE_NET_WAKE_ASLEEP) {
+ // Don't do anything special when we are in the lurking state.
+
+ } else if (new_state == NCP_STATE_ASSOCIATED) {
+
+ connman_service_create_ip6config(connman_service_lookup_from_network(network), connman_device_get_index(device));
+ connman_network_set_index(network, connman_device_get_index(device));
+ connman_network_set_ipv4_method(network, CONNMAN_IPCONFIG_METHOD_OFF);
+ connman_network_set_ipv6_method(network, CONNMAN_IPCONFIG_METHOD_FIXED);
+
+#if 0
+ /* This part is removed as a solution for COM-1070 (Need temporary workaround for ConnMan supporting only one IPv6 address)
+ * We'd like the connman to store just the Thread ULA address (which is set by client through network manager)
+ */
+
+ if (buffer_is_nonzero(device_info->current_network_info.prefix, sizeof(device_info->current_network_info.prefix))) {
+ struct connman_ipaddress *ip_address;
+ char v6_addr_str[56];
+
+ ip_address = connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6);
+ encode_ipv6_address_from_prefx_and_hwaddr(v6_addr_str,
+ sizeof(v6_addr_str),
+ device_info->current_network_info.prefix,
+ device_info->hwaddr);
+
+ connman_ipaddress_set_ipv6(ip_address, v6_addr_str, 64, "::");
+
+ connman_network_set_ipaddress(network, ip_address);
+
+ connman_ipaddress_free(ip_address);
+ } else {
+ struct connman_ipaddress *ip_address;
+
+ // If there is no prefix, set an empty address.
+ ip_address = connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6);
+ connman_ipaddress_set_ipv6(ip_address, "::", 128, "::");
+ connman_network_set_ipaddress(network, ip_address);
+ connman_ipaddress_free(ip_address);
+ }
+
+#endif /* End of change for COM-1070 */
+
+ lowpan_network_update_key_from_ncp(network);
+
+ if (!connman_network_get_connected(network)) {
+ if (!connman_network_get_connecting(network)
+ && !connman_network_get_associating(network)
+ ) {
+ if(connman_network_get_string(network, LOWPAN_AUTH_KEY)) {
+ DBG("We need to get connman to connect...");
+ connman_service_connect(connman_service_lookup_from_network(network),
+ CONNMAN_SERVICE_CONNECT_REASON_USER);
+ } else {
+ DBG("Waiting to get network key before asking connman to connect...");
+ // This should happen in a few moments, initiated
+ // by the call to lowpan_network_update_key_from_ncp, above.
+ }
+ return 0;
+ } else {
+ DBG("Marking Network as connected.");
+ connman_network_set_connected(network, TRUE);
+ }
+ } else {
+ DBG("Service/Network already connected.");
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+DBusHandlerResult
+lowpan_device_signal_handler(
+ DBusConnection *connection,
+ DBusMessage * message,
+ void * user_data
+ )
+{
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ struct connman_device* device = user_data;
+ struct lowpan_device_s *device_info =
+ (struct lowpan_device_s *)connman_device_get_data(device);
+ const char* msg_path = dbus_message_get_path(message);
+ const char* interface_name = connman_device_get_ident(device);
+ char* path = NULL;
+
+ asprintf(&path, "%s/%s", WPAN_TUNNEL_DBUS_PATH, interface_name);
+
+
+ if (!msg_path || (0 != strcmp(path, msg_path)))
+ goto bail;
+
+ if (dbus_message_is_signal(message, WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_IFACE_SIGNAL_STATE_CHANGED)) {
+ DBusMessageIter iter;
+ const char* new_state = NULL;
+ struct connman_network *network = NULL;
+ struct wpan_network_info_s network_info;
+ bool should_change_device_power_state = false;
+ bool new_device_power_state = false;
+ char network_identifier[256];
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ dbus_message_iter_init(message, &iter);
+
+ dbus_message_iter_get_basic(&iter, &new_state);
+
+ if (new_state == NULL) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ if (ncp_state_is_initializing(device_info->ncp_state)) {
+ // Make sure that we start up in a powered state.
+ should_change_device_power_state = true;
+ new_device_power_state = true;
+ }
+
+ DBG("AssociationStateChanged: %s", new_state);
+
+ dbus_message_iter_next(&iter);
+
+ network = get_network_from_iter(device, &iter);
+ parse_network_info_from_iter(&device_info->current_network_info, &iter);
+ ncp_state_t ncp_state;
+
+ ncp_state = string_to_ncp_state(new_state, device_info->ncp_state);
+
+
+ DBusMessageIter outer_iter;
+ DBusMessageIter dict_iter;
+ if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY) {
+ dbus_message_iter_recurse(&iter, &outer_iter);
+ iter = outer_iter;
+ }
+
+ for (;
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INVALID;
+ dbus_message_iter_next(&iter)) {
+ DBusMessageIter value_iter;
+ char* key = NULL;
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
+ ret = -1;
+ goto bail;
+ }
+
+ dbus_message_iter_recurse(&iter, &dict_iter);
+
+ if (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_STRING) {
+ ret = -1;
+ goto bail;
+ }
+
+ // Get the key
+ dbus_message_iter_get_basic(&dict_iter, &key);
+ dbus_message_iter_next(&dict_iter);
+
+ if(key == NULL) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ if (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_VARIANT) {
+ ret = -1;
+ goto bail;
+ }
+
+ dbus_message_iter_recurse(&dict_iter, &value_iter);
+
+ if (strcmp(key, "Enabled") == 0) {
+ dbus_bool_t enabled = 0;
+ bool device_power_state = (should_change_device_power_state?
+ new_device_power_state : connman_device_get_powered(device) );
+
+ dbus_message_iter_get_basic(&value_iter, &enabled);
+
+ DBG("NCP IS %s",enabled?"ENABLED":"DISABLED");
+ if (enabled != device_power_state) {
+ if (ncp_state_is_initializing(device_info->ncp_state)) {
+ // If this connman_device is uninitialized/initializing, then we need to make
+ // sure that the NCP is in our current power state.
+ enabled = !enabled;
+ DBG("%sABLING NCP",enabled?"EN":"DIS");
+ lowpan_driver_setprop_int32(device, kWPANTUNDProperty_DaemonEnabled, enabled);
+ } else {
+ // If this connman_device is initialized, then we need to make
+ // sure that our power state matches the power state of the NCP.
+ should_change_device_power_state = true;
+ new_device_power_state = enabled;
+ }
+ }
+ }
+ }
+
+
+ lowpan_device_handle_state_change(device, ncp_state, network);
+
+ if (should_change_device_power_state) {
+ DBG("%sABLING CONNMAN DEVICE",new_device_power_state?"EN":"DIS");
+ connman_device_set_powered(device, new_device_power_state);
+ }
+ }
+
+bail:
+ free(path);
+ return ret;
+}
+
+
+static int
+lowpan_device_probe(struct connman_device *device)
+{
+ DBG("%p %s", device, connman_device_get_ident(device));
+
+ if (dbus_connection_add_filter(connection,
+ lowpan_device_signal_handler,
+ (void*)device,
+ NULL) == FALSE) {
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static void
+lowpan_device_remove(struct connman_device *device)
+{
+ DBG("%p %s", device, connman_device_get_ident(device));
+
+ (void)dbus_connection_remove_filter(connection, lowpan_device_signal_handler,
+ (void*)device);
+}
+
+
+static int
+lowpan_device_enable(struct connman_device *device)
+{
+ DBG("%p %s", device, connman_device_get_ident(device));
+ lowpan_driver_setprop_int32(device, kWPANTUNDProperty_DaemonEnabled, 1);
+ return 0;
+}
+
+static int
+lowpan_device_disable(struct connman_device *device)
+{
+ DBG("%p %s", device, connman_device_get_ident(device));
+
+ struct lowpan_device_s *device_info = (struct lowpan_device_s *)connman_device_get_data(device);
+ if (device_info) {
+ lowpan_device_set_network(device, NULL);
+ connman_device_set_disconnected(device, TRUE);
+ }
+
+ lowpan_driver_setprop_int32(device, kWPANTUNDProperty_DaemonEnabled, 0);
+ return 0;
+}
+
+static void
+status_finished_callback(
+ DBusPendingCall *pending, void* user_data
+ )
+{
+ int32_t ret = 0;
+ struct connman_device *device = (struct connman_device *)user_data;
+ struct lowpan_device_s *device_info =
+ (struct lowpan_device_s *)connman_device_get_data(device);
+ struct connman_network *network = NULL;
+ DBusMessage* reply = dbus_pending_call_steal_reply(pending);
+ DBusMessageIter iter;
+ ncp_state_t ncp_state;
+ bool should_change_device_power_state = false;
+ bool new_device_power_state = false;
+
+ DBG("%p %s", device, connman_device_get_ident(device));
+
+ if (!reply) {
+ DBG("%p Status callback failed", device);
+ ret = -1;
+ goto bail;
+ }
+
+ dbus_message_iter_init(reply, &iter);
+ dump_info_from_iter(stderr, &iter, 1, false);
+
+ if(dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING) {
+ char* cstr = NULL;
+ dbus_message_iter_get_basic(&iter,&cstr);
+ DBG("%p Status callback failed: %s", device, cstr);
+ ret = -1;
+ goto bail;
+ }
+
+ parse_network_info_from_iter(&device_info->current_network_info, &iter);
+ network = get_network_from_iter(device, &iter);
+
+ DBusMessageIter outer_iter;
+ DBusMessageIter dict_iter;
+ if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY) {
+ dbus_message_iter_recurse(&iter, &outer_iter);
+ iter = outer_iter;
+ }
+
+ if (ncp_state_is_initializing(device_info->ncp_state)) {
+ // Make sure that we start up in a powered state.
+ should_change_device_power_state = true;
+ new_device_power_state = true;
+ }
+
+ ncp_state = device_info->ncp_state;
+
+ for (;
+ dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INVALID;
+ dbus_message_iter_next(&iter)) {
+ DBusMessageIter value_iter;
+ char* key = NULL;
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_DICT_ENTRY) {
+ ret = -1;
+ goto bail;
+ }
+
+ dbus_message_iter_recurse(&iter, &dict_iter);
+
+ if (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_STRING) {
+ ret = -1;
+ goto bail;
+ }
+
+ // Get the key
+ dbus_message_iter_get_basic(&dict_iter, &key);
+ dbus_message_iter_next(&dict_iter);
+
+ if(key == NULL) {
+ ret = -EINVAL;
+ goto bail;
+ }
+
+ if (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_VARIANT) {
+ ret = -1;
+ goto bail;
+ }
+
+ dbus_message_iter_recurse(&dict_iter, &value_iter);
+
+ if (strcmp(key, kWPANTUNDProperty_NCPHardwareAddress) == 0) {
+ DBusMessageIter array_iter;
+ dbus_message_iter_recurse(&value_iter, &array_iter);
+ const uint8_t* value = NULL;
+ int nelements = 0;
+ dbus_message_iter_get_fixed_array(&array_iter, &value, &nelements);
+ if (nelements == 8)
+ memcpy(device_info->hwaddr, value, 8);
+ else
+ DBG("%p Bad HWAddr length: %d", device, nelements);
+
+ char hwaddr_str[64];
+ snprintf(hwaddr_str,
+ sizeof(hwaddr_str),
+ "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
+ device_info->hwaddr[0],
+ device_info->hwaddr[1],
+ device_info->hwaddr[2],
+ device_info->hwaddr[3],
+ device_info->hwaddr[4],
+ device_info->hwaddr[5],
+ device_info->hwaddr[6],
+ device_info->hwaddr[7]);
+ DBG("%p HWAddr set to %s", device, hwaddr_str);
+ connman_device_set_string(device, "Address", hwaddr_str);
+
+ struct connman_ipdevice *ipdevice = NULL;
+ ipdevice = connman_ipdevice_lookup_from_index(connman_device_get_index(device));
+
+ if (ipdevice) {
+ connman_ipdevice_set_address(ipdevice, hwaddr_str);
+ DBG("Set HWAddr on ipdevice! GOOD");
+ } else {
+ DBG("Can't set HWAddr on ipdevice because we can't find the ipdevice!");
+ }
+
+ } else if (strcmp(key, kWPANTUNDProperty_DaemonEnabled) == 0) {
+ dbus_bool_t enabled = FALSE;
+ bool device_power_state = (should_change_device_power_state?
+ new_device_power_state : connman_device_get_powered(device) );
+
+ dbus_message_iter_get_basic(&value_iter, &enabled);
+
+ DBG("NCP IS %s",enabled?"ENABLED":"DISABLED");
+ if (enabled != device_power_state) {
+ if (ncp_state_is_initializing(device_info->ncp_state)) {
+ // If this connman_device is UNinitialized, then we need to make
+ // sure that the NCP is in our current power state.
+ enabled = !enabled;
+ DBG("%sABLING NCP",enabled?"EN":"DIS");
+ lowpan_driver_setprop_int32(device, kWPANTUNDProperty_DaemonEnabled, enabled);
+ } else {
+ // If this connman_device is initialized, then we need to make
+ // sure that our power state matches the power state of the NCP.
+ should_change_device_power_state = true;
+ new_device_power_state = enabled;
+ }
+ }
+
+ } else if (strcmp(key, kWPANTUNDProperty_NetworkKey) == 0) {
+ DBusMessageIter array_iter;
+ dbus_message_iter_recurse(&value_iter, &array_iter);
+ const uint8_t* value = NULL;
+ int nelements = 0;
+ dbus_message_iter_get_fixed_array(&array_iter, &value, &nelements);
+
+ lowpan_network_update_key(network, value, nelements);
+ } else if (strcmp(key, kWPANTUNDProperty_NCPState) == 0) {
+ const char* new_state = NULL;
+ dbus_message_iter_get_basic(&value_iter, &new_state);
+
+ ncp_state = string_to_ncp_state(new_state, ncp_state);
+ } else {
+#if DEBUG
+ DBG(
+ "info: %s -> (%c)\n",
+ key,
+ dbus_message_iter_get_arg_type(&value_iter));
+#endif
+ }
+ }
+
+ lowpan_device_handle_state_change(device, ncp_state, network);
+
+ if (should_change_device_power_state) {
+ DBG("%sABLING CONNMAN DEVICE",new_device_power_state?"EN":"DIS");
+ connman_device_set_powered(device, new_device_power_state);
+ }
+
+bail:
+ if (reply) {
+ dbus_message_unref(reply);
+ }
+ if (pending) {
+ dbus_pending_call_unref(pending);
+ }
+
+ return;
+}
+
+static void
+scan_free_callback(void* user_data)
+{
+ struct connman_device *device = (struct connman_device *)user_data;
+
+ connman_device_unref(device);
+}
+
+
+static int
+lowpan_device_update_status(struct connman_device *device)
+{
+ DBusPendingCall *pending_status = NULL;
+ DBusMessage *message = NULL;
+ char dbus_path[128];
+
+ snprintf(dbus_path,
+ sizeof(dbus_path),
+ "%s/%s",
+ WPAN_TUNNEL_DBUS_PATH,
+ connman_device_get_ident(device));
+
+ message = dbus_message_new_method_call(
+ WPAN_TUNNEL_DBUS_NAME,
+ dbus_path,
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_IFACE_CMD_STATUS
+ );
+
+ if (!dbus_connection_send_with_reply(
+ connection,
+ message,
+ &pending_status,
+ 3000
+ )
+ ) {
+ dbus_message_unref(message);
+ return -1;
+ }
+
+ dbus_message_unref(message);
+
+ if (!dbus_pending_call_set_notify(
+ pending_status,
+ &status_finished_callback,
+ (void*)device,
+ (DBusFreeFunction) & scan_free_callback
+ )
+ ) {
+ dbus_pending_call_cancel(pending_status);
+ return -1;
+ }
+
+ connman_device_ref(device);
+
+ return 0;
+}
+
+static void
+scan_finished_callback(
+ DBusPendingCall *pending, void* user_data
+ )
+{
+ int32_t ret = 0;
+ struct connman_device *device = (struct connman_device *)user_data;
+ struct lowpan_device_s *device_info = (struct lowpan_device_s *)connman_device_get_data(device);
+ DBusMessage* reply = dbus_pending_call_steal_reply(pending);
+ DBusMessageIter iter;
+ DBusMessageIter list_iter;
+
+ DBG("%p SCAN CALLBACK", device);
+
+ if (!reply) {
+ DBG("%p Scan reply was empty?", device);
+ ret = -1;
+ goto bail;
+ }
+
+ dbus_message_iter_init(reply, &iter);
+ dump_info_from_iter(stderr, &iter, 1, false);
+
+ if(dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING) {
+ char* cstr = NULL;
+ dbus_message_iter_get_basic(&iter,&cstr);
+ DBG("%p Scan failed: %s", device, cstr);
+ ret = -1;
+ connman_device_reset_scanning(device);
+ goto bail;
+ }
+
+
+ // Get return code
+ dbus_message_iter_get_basic(&iter, &ret);
+
+ if (ret) {
+ DBG("%p Scan failed: %d", device, ret);
+ connman_device_reset_scanning(device);
+ goto bail;
+ }
+
+ // Move to the list of networks.
+ dbus_message_iter_next(&iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
+ ret = -1;
+ goto bail;
+ }
+
+ dbus_message_iter_recurse(&iter, &list_iter);
+
+ for (;
+ dbus_message_iter_get_arg_type(&list_iter) == DBUS_TYPE_ARRAY;
+ dbus_message_iter_next(&list_iter)) {
+ struct connman_network *network = NULL;
+ char network_name[128];
+
+ network = get_network_from_iter(device, &list_iter);
+
+ if(network == NULL)
+ continue;
+
+ connman_network_set_available(network, TRUE);
+ connman_network_update(network);
+ }
+
+
+bail:
+ if (reply) {
+ dbus_message_unref(reply);
+ }
+ if (pending) {
+ dbus_pending_call_unref(pending);
+ }
+
+ if ((device_info != NULL) && (device_info->current_network != NULL)) {
+ // Always make sure that the current network is marked as
+ // available, so that we don't end up accidentally
+ // disconnecting from it.
+ connman_network_set_available(device_info->current_network, TRUE);
+ }
+
+ connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_LOWPAN, FALSE);
+ return;
+}
+
+static int
+lowpan_device_scan(enum connman_service_type type,
+ struct connman_device *device,
+ const char *ssid, unsigned int ssid_len,
+ const char *identity, const char* passphrase,
+ const char *security, void* user_data
+ )
+{
+ int status = 0;
+ DBusPendingCall *pending_scan = NULL;
+ DBusMessage *message = NULL;
+ char *dbus_path = NULL;
+ struct lowpan_device_s *device_info =
+ (struct lowpan_device_s *)connman_device_get_data(device);
+
+ DBG("%p ssid=%s, id=%s, passphrate=%s", device, ssid, identity, passphrase);
+
+ require_action(
+ connman_device_get_scanning(device) == FALSE,
+ bail,
+ status = -EALREADY
+ );
+
+ if (device_info->current_network != NULL) {
+ require_action(
+ connman_network_get_associating(device_info->current_network) == FALSE,
+ bail,
+ status = -EBUSY
+ );
+ }
+
+ require_action(device_info->ncp_state != NCP_STATE_ASSOCIATING, bail, status = -EBUSY);
+ require_action(device_info->ncp_state != NCP_STATE_COMMISSIONED, bail, status = -EBUSY);
+ require_action(!ncp_state_is_initializing(device_info->ncp_state), bail, status = -EBUSY);
+
+ asprintf(&dbus_path,
+ "%s/%s",
+ WPAN_TUNNEL_DBUS_PATH,
+ connman_device_get_ident(device));
+
+ message = dbus_message_new_method_call(
+ WPAN_TUNNEL_DBUS_NAME,
+ dbus_path,
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_IFACE_CMD_SCAN
+ );
+
+ require_action(message != NULL, bail, status = -ENOMEM);
+
+ require_action(message != NULL, bail, status = -ENOMEM);
+
+ require_action(
+ dbus_connection_send_with_reply(
+ connection,
+ message,
+ &pending_scan,
+ 45000 // Timeout, in ms
+ ) == TRUE,
+ bail,
+ status = -EIO
+ );
+
+ require_action(
+ dbus_pending_call_set_notify(
+ pending_scan,
+ &scan_finished_callback,
+ (void*)device,
+ (DBusFreeFunction) & scan_free_callback
+ ) == TRUE,
+ bail,
+ status = -EIO
+ );
+
+ pending_scan = NULL;
+ connman_device_ref(device);
+ connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_LOWPAN, TRUE);
+
+bail:
+ free(dbus_path);
+
+ if (pending_scan != NULL) {
+ dbus_pending_call_cancel(pending_scan);
+ }
+
+ if (message != NULL) {
+ dbus_message_unref(message);
+ }
+ return status;
+}
+
+
+static int lowpan_device_set_regdom(
+ struct connman_device *device, const char *alpha2
+ )
+{
+ DBG("%p", device);
+ connman_device_regdom_notify(device, 0, alpha2);
+ return 0;
+}
+
+static struct connman_device_driver lowpan_device_driver = {
+ .name = "lowpan",
+ .type = CONNMAN_DEVICE_TYPE_LOWPAN,
+ .priority = CONNMAN_DEVICE_PRIORITY_LOW,
+ .probe = lowpan_device_probe,
+ .remove = lowpan_device_remove,
+ .enable = lowpan_device_enable,
+ .disable = lowpan_device_disable,
+ .scan = lowpan_device_scan,
+ .set_regdom = lowpan_device_set_regdom,
+};
+
+static struct connman_device*
+lowpan_device_create(const char* interface_name)
+{
+ struct connman_device *device = NULL;
+
+ device = g_hash_table_lookup(devices, interface_name);
+ if (!device) {
+ struct lowpan_device_s *device_info =
+ calloc(1, sizeof(struct lowpan_device_s));
+
+ device = connman_device_create(
+ "lowpan",
+ lowpan_device_driver.type
+ );
+
+ connman_device_set_data(device, device_info);
+
+ g_hash_table_replace(devices, g_strdup(interface_name), device);
+
+ connman_device_set_index(device, connman_inet_ifindex(interface_name));
+ connman_device_set_ident(device, interface_name);
+ connman_device_set_interface(device, interface_name);
+
+ if(connman_device_register(device)<0) {
+ g_hash_table_remove(devices, device);
+ device = NULL;
+ }
+ DBG("device created: %p", device);
+ }
+
+ if(device)
+ lowpan_device_update_status(device);
+
+ return device;
+}
+
+static void
+lowpan_device_finalize(gpointer data)
+{
+ struct connman_device *device = data;
+ struct lowpan_device_s *device_info =
+ (struct lowpan_device_s *)connman_device_get_data(device);
+
+ DBG("%p %s", device, connman_device_get_ident(device));
+ if (device_info) {
+ if (device_info->current_network) {
+ connman_network_set_connected(device_info->current_network, FALSE);
+ }
+
+ connman_device_remove_network(device, device_info->current_network);
+
+ lowpan_device_set_network(device, NULL);
+
+ free(device_info);
+ connman_device_set_data(device, NULL);
+
+ connman_device_unregister(device);
+
+ connman_device_set_ident(device, "X");
+ connman_device_set_interface(device, "X");
+
+ connman_device_unref(device);
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+// MARK: - LoWPAN Technology
+
+static int
+lowpan_tech_probe(struct connman_technology *technology)
+{
+ DBG("%s: %p", __FUNCTION__, technology);
+ lowpan_tech = technology;
+
+ return 0;
+}
+
+static void
+lowpan_tech_remove(struct connman_technology *technology)
+{
+ DBG("");
+ lowpan_tech = NULL;
+}
+
+static int
+lowpan_tech_set_regdom(
+ struct connman_technology *technology, const char *alpha2
+ )
+{
+ return 0;
+}
+
+static int
+lowpan_tech_set_tethering(
+ struct connman_technology *technology,
+ const char *identifier, const char *passphrase,
+ const char *bridge, bool enabled
+ )
+{
+ return 0;
+}
+
+static struct connman_technology_driver lowpan_tech_driver = {
+ .name = "lowpan",
+ .type = CONNMAN_SERVICE_TYPE_LOWPAN,
+ .probe = lowpan_tech_probe,
+ .remove = lowpan_tech_remove,
+ .set_regdom = lowpan_tech_set_regdom,
+};
+
+/* -------------------------------------------------------------------------- */
+// MARK: - LoWPAN DBus
+
+static void
+lowpan_dbus_init_interfaces(void)
+{
+ DBusMessage *message = NULL;
+ DBusMessage *reply = NULL;
+ DBusError error = DBUS_ERROR_INIT;
+ DBusMessageIter iter;
+ DBusMessageIter list_iter;
+
+ DBG("%s", __FUNCTION__);
+
+ message = dbus_message_new_method_call(
+ WPAN_TUNNEL_DBUS_NAME,
+ WPAN_TUNNEL_DBUS_PATH,
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_TUNNEL_CMD_GET_INTERFACES
+ );
+
+ if (!message) {
+ DBG("%s: Unable to create dbus message.", __FUNCTION__);
+ goto bail;
+ }
+
+ reply = dbus_connection_send_with_reply_and_block(
+ connection,
+ message,
+ 5000,
+ &error
+ );
+
+ if (!reply) {
+ DBG("%s: DBus call to GetInterfaces failed: %s", __FUNCTION__, error.message);
+ goto bail;
+ }
+
+ dbus_message_iter_init(reply, &iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
+ DBG("%s: Bad return type for GetInterfaces", __FUNCTION__);
+ goto bail;
+ }
+
+ dbus_message_iter_recurse(&iter, &list_iter);
+
+ for (;
+ dbus_message_iter_get_arg_type(&list_iter) != DBUS_TYPE_INVALID;
+ dbus_message_iter_next(&list_iter)) {
+ DBusMessageIter tmp_iter;
+ DBusMessageIter *this_iter = &list_iter;
+ char *interface_name = NULL;
+
+ if (dbus_message_iter_get_arg_type(this_iter) == DBUS_TYPE_ARRAY) {
+ dbus_message_iter_recurse(this_iter, &tmp_iter);
+ this_iter = &tmp_iter;
+ }
+
+ if (dbus_message_iter_get_arg_type(this_iter) == DBUS_TYPE_STRING) {
+ dbus_message_iter_get_basic(this_iter, &interface_name);
+ }
+
+ if (interface_name != NULL) {
+ DBG("%s: Interface: \"%s\"", __FUNCTION__, interface_name);
+ lowpan_device_create(interface_name);
+ } else {
+ DBG("%s: Unable to extract interface name", __FUNCTION__);
+ }
+ }
+
+bail:
+ if (message)
+ dbus_message_unref(message);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_error_free(&error);
+}
+
+DBusHandlerResult
+lowpan_signal_handler(
+ DBusConnection *connection,
+ DBusMessage * message,
+ void * user_data
+ )
+{
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ if (dbus_message_is_signal(message, WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_TUNNEL_SIGNAL_INTERFACE_ADDED)) {
+ const char* interface_name = NULL;
+ DBG("%s", dbus_message_get_path(message));
+
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_STRING, &interface_name,
+ DBUS_TYPE_INVALID
+ );
+
+ DBG("%s: InterfaceAdded: %s", __FUNCTION__, interface_name);
+ lowpan_device_create(interface_name);
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+ } else if (dbus_message_is_signal(message, WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_TUNNEL_SIGNAL_INTERFACE_REMOVED)) {
+ const char* interface_name = NULL;
+ DBG("%s", dbus_message_get_path(message));
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_STRING, &interface_name,
+ DBUS_TYPE_INVALID
+ );
+
+ DBG("%s: InterfaceRemoved: %s", __FUNCTION__, interface_name);
+
+ struct connman_device *device = g_hash_table_lookup(devices, interface_name);
+
+ g_hash_table_remove(devices, device);
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+ } else if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS,
+ "NameOwnerChanged")) {
+ const char* name = NULL;
+ const char* oldOwner = NULL;
+ const char* newOwner = NULL;
+
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_STRING, &oldOwner,
+ DBUS_TYPE_STRING, &newOwner,
+ DBUS_TYPE_INVALID
+ );
+ if (name && (0 == strcmp(name, WPAN_TUNNEL_DBUS_INTERFACE))) {
+ if(newOwner[0]!=0 && oldOwner[0]==0) {
+ DBG("%s is now ONLINE: \"%s\" (was \"%s\")",name, newOwner, oldOwner);
+ }
+ if(newOwner[0]!=0) {
+ lowpan_dbus_init_interfaces();
+ }
+ if(oldOwner[0]!=0 && newOwner[0]==0) {
+ DBG("%s is now OFFLINE: \"%s\" (was \"%s\")",name, newOwner, oldOwner);
+ g_hash_table_remove_all(devices);
+ }
+ }
+ }
+
+ return ret;
+}
+
+
+static int
+lowpan_dbus_init(void)
+{
+ int ret = 0;
+ DBG("%s", __FUNCTION__);
+
+ // TODO: Add free function!
+ if (dbus_connection_add_filter(connection, lowpan_signal_handler, NULL, NULL) == FALSE) {
+ ret = -EIO;
+ goto bail;
+ }
+
+ static const char *lowpan_dbus_rule0 = "type=signal,"
+ "path=" DBUS_PATH_DBUS ","
+ "sender=" DBUS_SERVICE_DBUS ","
+ "interface=" DBUS_INTERFACE_DBUS ","
+ "member=NameOwnerChanged,"
+ "arg0=" WPAN_TUNNEL_DBUS_NAME;
+ static const char *lowpan_dbus_rule1 = "type=signal,"
+ "interface=" WPAN_TUNNEL_DBUS_INTERFACE;
+
+ dbus_bus_add_match(connection, lowpan_dbus_rule0, NULL);
+ dbus_bus_add_match(connection, lowpan_dbus_rule1, NULL);
+
+ lowpan_dbus_init_interfaces();
+
+bail:
+ return ret;
+}
+
+/* -------------------------------------------------------------------------- */
+// MARK: - LoWPAN Plugin
+
+static int
+lowpan_tunnel_init(void)
+{
+ DBG("%s", __FUNCTION__);
+
+ int err = -1;
+
+ connection = connman_dbus_get_connection();
+ if (connection == NULL) {
+ DBG("%s: No DBUS connection...?", __FUNCTION__);
+ err = -EIO;
+
+ goto out;
+ }
+
+ devices = g_hash_table_new_full(g_str_hash,
+ g_str_equal,
+ g_free,
+ lowpan_device_finalize);
+
+ err = connman_technology_driver_register(&lowpan_tech_driver);
+ if (err < 0)
+ goto out;
+
+ err = connman_network_driver_register(&lowpan_network_driver);
+ if (err < 0) {
+ connman_technology_driver_unregister(&lowpan_tech_driver);
+ goto out;
+ }
+
+ err = connman_device_driver_register(&lowpan_device_driver);
+ if (err < 0) {
+ connman_network_driver_unregister(&lowpan_network_driver);
+ connman_technology_driver_unregister(&lowpan_tech_driver);
+ goto out;
+ }
+
+ err = lowpan_dbus_init();
+ if (err < 0) {
+ connman_device_driver_unregister(&lowpan_device_driver);
+ connman_network_driver_unregister(&lowpan_network_driver);
+ connman_technology_driver_unregister(&lowpan_tech_driver);
+ goto out;
+ }
+
+#if 0
+
+
+ err = connman_device_driver_register(ðernet_driver);
+ if (err < 0) {
+ connman_network_driver_unregister(&cable_driver);
+ goto out;
+ }
+
+ err = connman_technology_driver_register(&tech_driver);
+ if (err < 0) {
+ connman_device_driver_unregister(ðernet_driver);
+ connman_network_driver_unregister(&cable_driver);
+ goto out;
+ }
+#endif
+
+ return 0;
+out:
+
+ return err;
+}
+
+static void
+lowpan_tunnel_exit(void)
+{
+ DBG("%s", __FUNCTION__);
+
+ connman_network_driver_unregister(&lowpan_network_driver);
+
+ connman_technology_driver_unregister(&lowpan_tech_driver);
+
+ connman_device_driver_unregister(&lowpan_device_driver);
+
+#if 0
+ connman_technology_driver_unregister(&tech_driver);
+
+ connman_network_driver_unregister(&cable_driver);
+
+ connman_device_driver_unregister(ðernet_driver);
+#endif
+}
+
+CONNMAN_PLUGIN_DEFINE(
+ lowpan_tunnel,
+ "LoWPAN tunnel plugin",
+ CONNMAN_VERSION,
+ CONNMAN_PLUGIN_PRIORITY_DEFAULT,
+ lowpan_tunnel_init,
+ lowpan_tunnel_exit
+ )
diff --git a/src/ipc-dbus/DBUSIPCServer.cpp b/src/ipc-dbus/DBUSIPCServer.cpp
new file mode 100644
index 0000000..7ee595f
--- /dev/null
+++ b/src/ipc-dbus/DBUSIPCServer.cpp
@@ -0,0 +1,413 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * Implementation of the DBus IPCServer subclass.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef ASSERT_MACROS_USE_SYSLOG
+#define ASSERT_MACROS_USE_SYSLOG 1
+#endif
+
+#include <stdio.h>
+#include "DBUSIPCServer.h"
+#include <dbus/dbus.h>
+#if USING_GLIB
+#include <glib.h>
+#include <glib-object.h>
+#endif
+#include <string.h>
+#include "NCPControlInterface.h"
+#include "assert-macros.h"
+
+#include <boost/bind.hpp>
+#include "DBUSHelpers.h"
+#include <errno.h>
+#include <algorithm>
+#include "any-to.h"
+#include "wpan-dbus-v0.h"
+
+using namespace DBUSHelpers;
+using namespace nl;
+using namespace nl::wpantund;
+
+static const char gDBusObjectManagerMatchString[] =
+ "type='signal'"
+ ",interface='" WPAN_TUNNEL_DBUS_INTERFACE "'"
+ ;
+
+static DBusConnection *
+get_dbus_connection()
+{
+ static DBusConnection* connection = NULL;
+ DBusError error;
+ dbus_error_init(&error);
+
+ if (connection == NULL) {
+ syslog(LOG_DEBUG, "Getting DBus connection");
+
+ connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
+
+ if (!connection) {
+ dbus_error_free(&error);
+ dbus_error_init(&error);
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ }
+
+ require_string(connection != NULL, bail, error.message);
+
+ syslog(LOG_DEBUG, "Registering DBus connection");
+
+ dbus_bus_register(connection, &error);
+
+ require_string(error.name == NULL, bail, error.message);
+
+ syslog(LOG_DEBUG, "Requesting DBus connection name %s", WPAN_TUNNEL_DBUS_NAME);
+
+ dbus_bus_request_name(
+ connection,
+ WPAN_TUNNEL_DBUS_NAME,
+ 0,
+ &error
+ );
+
+ require_string(error.name == NULL, bail, error.message);
+ }
+
+bail:
+ if (error.message) {
+ throw std::runtime_error(error.message);
+ }
+ dbus_error_free(&error);
+
+ return connection;
+}
+
+DBUSIPCServer::DBUSIPCServer():
+ mConnection(get_dbus_connection()),
+ mAPI_v0(mConnection),
+ mAPI_v1(mConnection)
+{
+ DBusError error;
+
+ dbus_error_init(&error);
+
+ static const DBusObjectPathVTable ipc_interface_vtable = {
+ NULL,
+ &DBUSIPCServer::dbus_message_handler,
+ };
+
+ require(
+ dbus_connection_register_object_path(
+ mConnection,
+ WPAN_TUNNEL_DBUS_PATH,
+ &ipc_interface_vtable,
+ (void*)this
+ ),
+ bail
+ );
+
+ dbus_bus_add_match(
+ mConnection,
+ gDBusObjectManagerMatchString,
+ &error
+ );
+ require_string(error.name == NULL, bail, error.message);
+
+ dbus_connection_add_filter(mConnection, &DBUSIPCServer::dbus_message_handler, (void*)this, NULL);
+
+ syslog(LOG_NOTICE, "Ready. Using DBUS bus \"%s\"", dbus_bus_get_unique_name(mConnection));
+
+bail:
+ if (error.message) {
+ throw std::runtime_error(error.message);
+ }
+ dbus_error_free(&error);
+}
+
+DBUSIPCServer::~DBUSIPCServer()
+{
+ dbus_bus_remove_match(
+ mConnection,
+ gDBusObjectManagerMatchString,
+ NULL
+ );
+ dbus_connection_unref(mConnection);
+}
+
+cms_t
+DBUSIPCServer::get_ms_to_next_event()
+{
+ cms_t ret = CMS_DISTANT_FUTURE;
+
+ /* We could set up some sort of complicated mechanism
+ * using the dbus_timer objects to actually calculate this
+ * correctly, however we aren't really using any of the
+ * timer-dependent stuff in DBus. As such, the following
+ * seems to suffice. If we want wpantund to do things
+ * like handle response timeouts in a timely manner then
+ * we will need to go ahead and fully implement such a
+ * mechanism. */
+
+ if (dbus_connection_get_dispatch_status(mConnection) == DBUS_DISPATCH_DATA_REMAINS) {
+ ret = 0;
+ }
+
+ if (dbus_connection_has_messages_to_send(mConnection)) {
+ ret = 0;
+ }
+
+ return ret;
+}
+
+void
+DBUSIPCServer::process(void)
+{
+ dbus_connection_read_write_dispatch(mConnection, 0);
+}
+
+int
+DBUSIPCServer::update_fd_set(fd_set *read_fd_set, fd_set *write_fd_set, fd_set *error_fd_set, int *max_fd, cms_t *timeout)
+{
+ int ret = -1;
+ int unix_fd = -1;
+
+ require(dbus_connection_get_unix_fd(mConnection, &unix_fd), bail);
+
+ if (read_fd_set != NULL) {
+ FD_SET(unix_fd, read_fd_set);
+ }
+
+ if (error_fd_set != NULL) {
+ FD_SET(unix_fd, error_fd_set);
+ }
+
+ if ((write_fd_set != NULL) && dbus_connection_has_messages_to_send(mConnection)) {
+ FD_SET(unix_fd, write_fd_set);
+ }
+
+ if ((max_fd != NULL)) {
+ *max_fd = std::max(*max_fd, unix_fd);
+ }
+
+ if (timeout != NULL) {
+ *timeout = std::min(*timeout, get_ms_to_next_event());
+ }
+
+ ret = 0;
+bail:
+ return ret;
+}
+
+
+
+void
+DBUSIPCServer::interface_added(const std::string& interface_name)
+{
+ DBusMessage* signal;
+ const char *interface_name_cstr = interface_name.c_str();
+
+ syslog(LOG_DEBUG,
+ "DBus Sending Interface Added Signal for %s",
+ interface_name_cstr);
+ signal = dbus_message_new_signal(
+ WPAN_TUNNEL_DBUS_PATH,
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_TUNNEL_SIGNAL_INTERFACE_ADDED
+ );
+ dbus_message_append_args(
+ signal,
+ DBUS_TYPE_STRING, &interface_name_cstr,
+ DBUS_TYPE_INVALID
+ );
+
+ dbus_connection_send(mConnection, signal, NULL);
+ dbus_message_unref(signal);
+}
+
+void
+DBUSIPCServer::interface_removed(const std::string& interface_name)
+{
+ DBusMessage* signal;
+ const char *interface_name_cstr = interface_name.c_str();
+
+ syslog(LOG_DEBUG,
+ "DBus Sending Interface Added Signal for %s",
+ interface_name_cstr);
+ signal = dbus_message_new_signal(
+ WPAN_TUNNEL_DBUS_PATH,
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ "InterfaceRemoved"
+ );
+ dbus_message_append_args(
+ signal,
+ DBUS_TYPE_STRING, &interface_name_cstr,
+ DBUS_TYPE_INVALID
+ );
+ dbus_connection_send(mConnection, signal, NULL);
+ dbus_message_unref(signal);
+}
+
+int
+DBUSIPCServer::add_interface(NCPControlInterface* instance)
+{
+ std::string name = instance->get_name();
+
+ mInterfaceMap[name] = instance;
+
+ mAPI_v0.add_interface(instance);
+ mAPI_v1.add_interface(instance);
+
+ interface_added(name);
+
+ return 0;
+}
+
+DBusHandlerResult
+DBUSIPCServer::message_handler(
+ DBusConnection *connection,
+ DBusMessage *message
+ )
+{
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ if (dbus_message_is_method_call(message, WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_TUNNEL_CMD_GET_INTERFACES)) {
+ DBusMessage *reply = dbus_message_new_method_return(message);
+ DBusMessageIter iter, array_iter;
+ dbus_message_iter_init_append(reply, &iter);
+
+ dbus_message_iter_open_container(
+ &iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_TYPE_ARRAY_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING,
+ &array_iter
+ );
+ {
+ std::map<std::string, NCPControlInterface*>::const_iterator i;
+ std::map<std::string,
+ NCPControlInterface*>::const_iterator end =
+ mInterfaceMap.end();
+ for (i = mInterfaceMap.begin(); i != end; ++i) {
+ DBusMessageIter item_iter;
+ const char* name = i->first.c_str();
+ const char* bus_name = dbus_bus_get_unique_name(connection);
+ dbus_message_iter_open_container(
+ &array_iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING,
+ &item_iter
+ );
+ dbus_message_iter_append_basic(&item_iter, DBUS_TYPE_STRING,
+ &name);
+ dbus_message_iter_append_basic(&item_iter, DBUS_TYPE_STRING,
+ &bus_name);
+ dbus_message_iter_close_container(&array_iter, &item_iter);
+ }
+ }
+ {
+ std::map<std::string, std::string>::const_iterator i;
+ std::map<std::string, std::string>::const_iterator end =
+ mExternalInterfaceMap.end();
+ for (i = mExternalInterfaceMap.begin(); i != end; ++i) {
+ DBusMessageIter item_iter;
+ const char* name = i->first.c_str();
+ const char* bus_name = i->second.c_str();
+ dbus_message_iter_open_container(
+ &array_iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING,
+ &item_iter
+ );
+ dbus_message_iter_append_basic(&item_iter, DBUS_TYPE_STRING,
+ &name);
+ dbus_message_iter_append_basic(&item_iter, DBUS_TYPE_STRING,
+ &bus_name);
+ dbus_message_iter_close_container(&array_iter, &item_iter);
+ }
+ }
+
+ dbus_message_iter_close_container(&iter, &array_iter);
+
+ dbus_connection_send(connection, reply, NULL);
+ dbus_message_unref(reply);
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+ } else if (dbus_message_is_signal(message, WPAN_TUNNEL_DBUS_INTERFACE, WPAN_TUNNEL_SIGNAL_INTERFACE_ADDED)) {
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+ if (!strequal(dbus_message_get_sender(message), dbus_bus_get_unique_name(connection))) {
+ const char* interface_name = NULL;
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_STRING, &interface_name,
+ DBUS_TYPE_INVALID
+ );
+ if (NULL != interface_name && (mInterfaceMap.count(interface_name) == 0)) {
+ mExternalInterfaceMap[interface_name] = dbus_message_get_sender(message);
+ }
+ }
+ } else if (dbus_message_is_signal(message, WPAN_TUNNEL_DBUS_INTERFACE, WPAN_TUNNEL_SIGNAL_INTERFACE_REMOVED)) {
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+ if (!strequal(dbus_message_get_sender(message), dbus_bus_get_unique_name(connection))) {
+ const char* interface_name = NULL;
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_STRING, &interface_name,
+ DBUS_TYPE_INVALID
+ );
+ if ((NULL != interface_name)
+ && (mInterfaceMap.count(interface_name) == 0)
+ && (mExternalInterfaceMap.count(interface_name) == 1)
+ && (mExternalInterfaceMap[interface_name] == dbus_message_get_sender(message))
+ ) {
+ mExternalInterfaceMap.erase(interface_name);
+ }
+ }
+ } else if (dbus_message_is_method_call(message, WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_TUNNEL_CMD_GET_VERSION)) {
+ DBusMessage *reply = dbus_message_new_method_return(message);
+ uint32_t version = WPAN_TUNNEL_DBUS_VERSION;
+ dbus_message_append_args(
+ reply,
+ DBUS_TYPE_UINT32, &version,
+ DBUS_TYPE_INVALID
+ );
+
+ dbus_connection_send(connection, reply, NULL);
+ dbus_message_unref(reply);
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return ret;
+}
+
+DBusHandlerResult
+DBUSIPCServer::dbus_message_handler(
+ DBusConnection *connection,
+ DBusMessage * message,
+ void * user_data
+ )
+{
+ return ((DBUSIPCServer*)user_data)->message_handler(connection, message);
+}
diff --git a/src/ipc-dbus/DBUSIPCServer.h b/src/ipc-dbus/DBUSIPCServer.h
new file mode 100644
index 0000000..0a4ade4
--- /dev/null
+++ b/src/ipc-dbus/DBUSIPCServer.h
@@ -0,0 +1,76 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * Declaration of the DBus IPCServer subclass.
+ *
+ */
+
+#ifndef wpantund_DBUSIPCServer_h
+#define wpantund_DBUSIPCServer_h
+
+#include "IPCServer.h"
+#include <map>
+#include <dbus/dbus.h>
+#include <boost/signals2/signal.hpp>
+#include <boost/bind.hpp>
+
+#include "DBusIPCAPI_v0.h"
+#include "DBusIPCAPI_v1.h"
+
+namespace nl {
+namespace wpantund {
+
+class DBUSIPCServer : public IPCServer {
+public:
+
+ DBUSIPCServer();
+ virtual ~DBUSIPCServer();
+
+ virtual int add_interface(NCPControlInterface* instance);
+ virtual cms_t get_ms_to_next_event(void );
+ virtual void process(void);
+ virtual int update_fd_set(fd_set *read_fd_set, fd_set *write_fd_set, fd_set *error_fd_set, int *max_fd, cms_t *timeout);
+
+private:
+ DBusHandlerResult message_handler(
+ DBusConnection *connection,
+ DBusMessage * message
+ );
+
+ static DBusHandlerResult dbus_message_handler(
+ DBusConnection *connection,
+ DBusMessage * message,
+ void * user_data
+ );
+
+ void interface_added(const std::string& interface_name);
+ void interface_removed(const std::string& interface_name);
+
+private:
+ DBusConnection *mConnection;
+ std::map<std::string, NCPControlInterface*> mInterfaceMap;
+ std::map<std::string, std::string> mExternalInterfaceMap;
+ DBusIPCAPI_v0 mAPI_v0;
+ DBusIPCAPI_v1 mAPI_v1;
+};
+
+};
+};
+
+
+#endif
diff --git a/src/ipc-dbus/DBusIPCAPI_v0.cpp b/src/ipc-dbus/DBusIPCAPI_v0.cpp
new file mode 100644
index 0000000..8874712
--- /dev/null
+++ b/src/ipc-dbus/DBusIPCAPI_v0.cpp
@@ -0,0 +1,1626 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+
+#include <string.h>
+#include <errno.h>
+#include <algorithm>
+
+#include <boost/bind.hpp>
+
+#include <dbus/dbus.h>
+
+#include "DBusIPCAPI_v0.h"
+#include "wpan-dbus-v0.h"
+
+#include "NCPControlInterface.h"
+#include "NCPTypes.h"
+#include "NCPMfgInterface_v0.h"
+#include "assert-macros.h"
+
+#include "DBUSHelpers.h"
+#include "any-to.h"
+#include "wpan-error.h"
+
+using namespace DBUSHelpers;
+using namespace nl;
+using namespace nl::wpantund;
+
+DBusIPCAPI_v0::DBusIPCAPI_v0(DBusConnection *connection)
+ :mConnection(connection)
+{
+ dbus_connection_ref(mConnection);
+ init_callback_tables();
+}
+
+DBusIPCAPI_v0::~DBusIPCAPI_v0()
+{
+ dbus_connection_unref(mConnection);
+}
+
+void
+DBusIPCAPI_v0::init_callback_tables()
+{
+#define INTERFACE_CALLBACK_CONNECT(cmd_name, member_func) \
+ mInterfaceCallbackTable[(cmd_name)] = boost::bind( \
+ &DBusIPCAPI_v0::member_func, this, _1, _2)
+
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_JOIN, interface_join_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_FORM, interface_form_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_BEGIN_NET_WAKE, interface_begin_net_wake_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_PERMIT_JOIN, interface_permit_join_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_LEAVE, interface_leave_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_DATA_POLL, interface_data_poll_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_CONFIG_GATEWAY, interface_config_gateway_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_ADD_ROUTE, interface_add_route_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_REMOVE_ROUTE, interface_remove_route_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_BEGIN_LOW_POWER, interface_begin_low_power_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_PING, interface_ping_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_HOST_DID_WAKE, interface_host_did_wake_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_STOP_SCAN, interface_stop_scan_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_GET_PROP, interface_get_prop_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_SET_PROP, interface_set_prop_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_RESET, interface_reset_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_STATUS, interface_status_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_ACTIVE_SCAN, interface_active_scan_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_RESUME, interface_resume_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_MFG_BEGIN_TEST, interface_mfg_begin_test_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_MFG_END_TEST, interface_mfg_end_test_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_MFG_TX_PACKET, interface_mfg_tx_packet_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_MFG_FINISH, interface_mfg_finish_handler);
+
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_MFG_CLOCKMON, interface_mfg_clockmon_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_MFG_GPIO_SET, interface_mfg_gpio_set_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_MFG_GPIO_GET, interface_mfg_gpio_get_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_MFG_CHANNELCAL, interface_mfg_channelcal_handler);
+ INTERFACE_CALLBACK_CONNECT(WPAN_IFACE_CMD_MFG_CHANNELCAL_GET, interface_mfg_channelcal_get_handler);
+}
+
+void
+DBusIPCAPI_v0::CallbackWithStatus_Helper(
+ int ret, DBusMessage *original_message
+ )
+{
+ DBusMessage *reply = dbus_message_new_method_return(original_message);
+
+ syslog(LOG_DEBUG, "Sending DBus response for \"%s\" to \"%s\"", dbus_message_get_member(original_message), dbus_message_get_sender(original_message));
+
+ if(reply) {
+ dbus_message_append_args(
+ reply,
+ DBUS_TYPE_INT32, &ret,
+ DBUS_TYPE_INVALID
+ );
+
+ dbus_connection_send(mConnection, reply, NULL);
+ dbus_message_unref(reply);
+ }
+ dbus_message_unref(original_message);
+}
+
+static void
+ipc_append_network_properties(
+ DBusMessageIter *iter, const WPAN::NetworkInstance& network
+ )
+{
+ const char* network_name = network.name.c_str();
+
+ if (network_name[0])
+ append_dict_entry(iter,
+ "NetworkName",
+ DBUS_TYPE_STRING,
+ &network_name);
+
+ if (network.get_xpanid_as_uint64() != 0) {
+ uint64_t xpan_id = network.get_xpanid_as_uint64();
+ append_dict_entry(iter, "XPanId", DBUS_TYPE_UINT64, &xpan_id);
+ }
+
+ if (network.panid && network.panid != 0xFFFF) {
+ uint16_t pan_id = network.panid;
+ append_dict_entry(iter, "PanId", DBUS_TYPE_UINT16, &pan_id);
+ }
+
+ if (network.channel) {
+ uint16_t channel = network.channel;
+ append_dict_entry(iter, "Channel", DBUS_TYPE_INT16, &channel);
+
+ if (network.rssi != -128) {
+ int8_t rssi = network.rssi;
+ append_dict_entry(iter, "RSSI", DBUS_TYPE_BYTE, &rssi);
+ }
+
+ dbus_bool_t allowing_join = network.joinable;
+ append_dict_entry(iter,
+ "AllowingJoin",
+ DBUS_TYPE_BOOLEAN,
+ &allowing_join);
+ }
+
+ if (network.type != 0) {
+ int32_t type = network.type;
+ append_dict_entry(iter, "Type", DBUS_TYPE_INT32, &type);
+ }
+
+ if (network.get_hwaddr_as_uint64() != 0)
+ append_dict_entry(iter, "BeaconHWAddr",
+ nl::Data(network.hwaddr, 8));
+
+}
+
+static void
+ipc_append_network_dict(
+ DBusMessageIter *iter, const WPAN::NetworkInstance& network
+ )
+{
+ DBusMessageIter dict;
+
+ dbus_message_iter_open_container(
+ iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+ &dict
+ );
+ ipc_append_network_properties(&dict, network);
+
+
+ dbus_message_iter_close_container(iter, &dict);
+}
+
+static void
+ipc_append_networks(
+ DBusMessageIter *iter, const std::list<WPAN::NetworkInstance>& networks
+ )
+{
+ DBusMessageIter array;
+
+ dbus_message_iter_open_container(
+ iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_TYPE_ARRAY_AS_STRING
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+ &array
+ );
+
+ std::list<WPAN::NetworkInstance>::const_iterator i;
+ std::list<WPAN::NetworkInstance>::const_iterator end = networks.end();
+ for (i = networks.begin(); i != end; ++i) {
+ ipc_append_network_dict(&array, *i);
+ }
+
+ dbus_message_iter_close_container(iter, &array);
+}
+
+void
+DBusIPCAPI_v0::received_beacon(NCPControlInterface* interface, const WPAN::NetworkInstance& network)
+{
+ mReceivedBeacons.push_back(network);
+}
+
+void
+DBusIPCAPI_v0::scan_response_helper(
+ int ret,
+ DBusMessage * original_message
+)
+{
+ DBusMessage *reply = dbus_message_new_method_return(original_message);
+
+ if(reply) {
+ DBusMessageIter msg_iter;
+ dbus_message_append_args(
+ reply,
+ DBUS_TYPE_INT32, &ret,
+ DBUS_TYPE_INVALID
+ );
+
+ dbus_message_iter_init_append(reply, &msg_iter);
+
+ ipc_append_networks(&msg_iter, mReceivedBeacons);
+
+ dbus_connection_send(mConnection, reply, NULL);
+ dbus_message_unref(reply);
+ }
+ dbus_message_unref(original_message);
+}
+
+void
+DBusIPCAPI_v0::status_response_helper(
+ int ret, NCPControlInterface* interface, DBusMessage *message
+ )
+{
+ DBusMessage *reply = dbus_message_new_method_return(message);
+
+ if (reply) {
+ DBusMessageIter iter;
+ dbus_message_iter_init_append(reply, &iter);
+
+ DBusMessageIter dict;
+ boost::any value;
+ NCPState ncp_state = UNINITIALIZED;
+ std::string ncp_state_string;
+ const char* ncp_state_cstr = kWPANTUNDStateUninitialized;
+
+ dbus_message_iter_open_container(
+ &iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+ &dict
+ );
+
+ value = interface->get_property(kWPANTUNDProperty_NCPState);
+
+ if (!value.empty()) {
+ ncp_state_string = any_to_string(value);
+ ncp_state = string_to_ncp_state(ncp_state_string);
+ ncp_state_cstr = ncp_state_string.c_str();
+ }
+
+ append_dict_entry(&dict,
+ kWPANTUNDProperty_NCPState,
+ DBUS_TYPE_STRING,
+ &ncp_state_cstr);
+
+ if (ncp_state_is_commissioned(ncp_state))
+ {
+ value = interface->get_property(kWPANTUNDProperty_NetworkName);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_NetworkName, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_NetworkXPANID);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_NetworkXPANID, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_NetworkPANID);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_NetworkPANID, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_NCPChannel);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_NCPChannel, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_IPv6LinkLocalAddress);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_IPv6LinkLocalAddress, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_IPv6MeshLocalAddress);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_IPv6MeshLocalAddress, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_NestLabs_LegacyMeshLocalAddress);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_NestLabs_LegacyMeshLocalAddress, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_IPv6MeshLocalPrefix);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_IPv6MeshLocalPrefix, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_NestLabs_LegacyMeshLocalPrefix);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_NestLabs_LegacyMeshLocalPrefix, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_NestLabs_NetworkAllowingJoin);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_NestLabs_NetworkAllowingJoin, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_NetworkNodeType);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_NetworkNodeType, value);
+ }
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_DaemonEnabled);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_DaemonEnabled, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_NCPVersion);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_NCPVersion, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_DaemonVersion);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_DaemonVersion, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_NCPHardwareAddress);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_NCPHardwareAddress, value);
+ }
+
+ dbus_message_iter_close_container(&iter, &dict);
+
+ dbus_connection_send(mConnection, reply, NULL);
+ dbus_message_unref(reply);
+ }
+ dbus_message_unref(message);
+}
+
+void
+DBusIPCAPI_v0::CallbackWithStatusArg1_Helper(
+ int status, const boost::any& value, DBusMessage *message
+)
+{
+ DBusMessage *reply = dbus_message_new_method_return(message);
+ DBusMessageIter iter;
+
+ syslog(LOG_DEBUG, "Sending getprop response");
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ if (!status && value.empty()) {
+ status = kWPANTUNDStatus_PropertyEmpty;
+ }
+
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &status);
+
+ if (value.empty()) {
+ append_any_to_dbus_iter(&iter, std::string("<empty>"));
+ } else {
+ append_any_to_dbus_iter(&iter, value);
+ }
+
+ dbus_connection_send(mConnection, reply, NULL);
+ dbus_message_unref(message);
+ dbus_message_unref(reply);
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_join_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ const char* network_name = NULL;
+ int16_t node_type_int16 = ROUTER;
+ ValueMap options;
+ uint64_t xpanid;
+ uint16_t panid = 0xFFFF;
+ uint8_t channel = 0;
+
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_STRING, &network_name,
+ DBUS_TYPE_INT16, &node_type_int16,
+ DBUS_TYPE_UINT64, &xpanid,
+ DBUS_TYPE_UINT16, &panid,
+ DBUS_TYPE_BYTE, &channel,
+ DBUS_TYPE_INVALID
+ );
+
+ require(network_name != NULL, bail);
+
+ options[kWPANTUNDProperty_NetworkName] = std::string(network_name);
+ options[kWPANTUNDProperty_NetworkXPANID] = xpanid;
+ options[kWPANTUNDProperty_NetworkPANID] = panid;
+ options[kWPANTUNDProperty_NCPChannel] = channel;
+
+ if (node_type_int16) {
+ options[kWPANTUNDProperty_NetworkNodeType] = (int)node_type_int16;
+ }
+
+ dbus_message_ref(message);
+
+ interface->join(
+ options,
+ boost::bind(
+ &DBusIPCAPI_v0::CallbackWithStatus_Helper,
+ this,
+ _1,
+ message
+ )
+ );
+
+bail:
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_form_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ const char* network_name;
+ ValueMap options;
+ int16_t node_type_int16 = 0;
+ NCPControlInterface::ChannelMask channel_mask = 0;
+ uint8_t *ula_prefix = NULL;
+ int ula_prefix_len = 0;
+
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_STRING, &network_name,
+ DBUS_TYPE_INT16, &node_type_int16,
+ DBUS_TYPE_UINT32, &channel_mask,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &ula_prefix, &ula_prefix_len,
+ DBUS_TYPE_INVALID
+ );
+
+ if (node_type_int16) {
+ options[kWPANTUNDProperty_NetworkNodeType] = (int)node_type_int16;
+ }
+
+ if (channel_mask) {
+ options[kWPANTUNDProperty_NCPChannelMask] = channel_mask;
+ }
+
+ if (ula_prefix_len) {
+ options[kWPANTUNDProperty_NestLabs_LegacyMeshLocalPrefix] = Data(ula_prefix, ula_prefix_len);
+ }
+
+ { // The mesh local prefix can be set by setting it before forming.
+ boost::any value;
+ value = interface->get_property(kWPANTUNDProperty_IPv6MeshLocalPrefix);
+ if (!value.empty()) {
+ options[kWPANTUNDProperty_IPv6MeshLocalPrefix] = value;
+ }
+ }
+
+ options[kWPANTUNDProperty_NetworkName] = std::string(network_name);
+
+ dbus_message_ref(message);
+
+ interface->form(
+ options,
+ boost::bind(
+ &DBusIPCAPI_v0::CallbackWithStatus_Helper,
+ this,
+ _1,
+ message
+ )
+ );
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_begin_net_wake_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ uint8_t data = 0;
+ uint32_t flags = 0;
+
+ dbus_message_ref(message);
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_BYTE, &data,
+ DBUS_TYPE_UINT32, &flags,
+ DBUS_TYPE_INVALID
+ );
+
+ interface->begin_net_wake(
+ data,
+ flags,
+ boost::bind(&DBusIPCAPI_v0::CallbackWithStatus_Helper, this, _1,
+ message)
+ );
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_permit_join_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ int32_t seconds = -1;
+ dbus_bool_t network_wide = FALSE;
+ uint8_t commissioning_traffic_type = 0xFF;
+ in_port_t commissioning_traffic_port = 0;
+
+ dbus_message_ref(message);
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_INT32, &seconds,
+ DBUS_TYPE_BOOLEAN, &network_wide,
+ DBUS_TYPE_UINT16, &commissioning_traffic_port,
+ DBUS_TYPE_BYTE, &commissioning_traffic_type,
+ DBUS_TYPE_INVALID
+ );
+ commissioning_traffic_port = htons(commissioning_traffic_port);
+
+ if(seconds==-1)
+ seconds = 5*60;
+
+ interface->permit_join(
+ seconds,
+ commissioning_traffic_type,
+ commissioning_traffic_port,
+ network_wide,
+ boost::bind(&DBusIPCAPI_v0::CallbackWithStatus_Helper, this, _1,
+ message)
+ );
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_leave_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_message_ref(message);
+
+ interface->leave(boost::bind(&DBusIPCAPI_v0::CallbackWithStatus_Helper,
+ this, _1, message));
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_data_poll_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_message_ref(message);
+
+ interface->data_poll(boost::bind(&DBusIPCAPI_v0::CallbackWithStatus_Helper,
+ this, _1, message));
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_config_gateway_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_message_ref(message);
+
+ dbus_bool_t defaultRoute = FALSE;
+ uint32_t preferredLifetime = 0;
+ uint32_t validLifetime = 0;
+ uint8_t *prefix = NULL;
+ struct in6_addr addr = {};
+ int prefixLen = 0;
+
+ dbus_message_ref(message);
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_BOOLEAN, &defaultRoute,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &prefix, &prefixLen,
+ DBUS_TYPE_UINT32, &preferredLifetime,
+ DBUS_TYPE_UINT32, &validLifetime,
+ DBUS_TYPE_INVALID
+ );
+
+ if (prefixLen > 16) {
+ prefixLen = 16;
+ }
+
+ memcpy(addr.s6_addr, prefix, prefixLen);
+
+ if (validLifetime == 0) {
+ interface->remove_on_mesh_prefix(
+ &addr,
+ boost::bind(&DBusIPCAPI_v0::CallbackWithStatus_Helper,this, _1, message)
+ );
+ } else {
+ interface->add_on_mesh_prefix(
+ &addr,
+ defaultRoute,
+ boost::bind(&DBusIPCAPI_v0::CallbackWithStatus_Helper,this, _1, message)
+ );
+ }
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_add_route_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_message_ref(message);
+
+ uint8_t *prefix = NULL;
+ struct in6_addr addr = {};
+ int prefix_len = 0;
+ uint16_t domain_id = 0;
+ int16_t priority_raw;
+ NCPControlInterface::ExternalRoutePriority priority;
+
+ dbus_message_ref(message);
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &prefix, &prefix_len,
+ DBUS_TYPE_UINT16, &domain_id,
+ DBUS_TYPE_INT16, &priority_raw,
+ DBUS_TYPE_INVALID
+ );
+
+ if (prefix_len > 16) {
+ prefix_len = 16;
+ }
+
+ memcpy(addr.s6_addr, prefix, prefix_len);
+
+ priority = NCPControlInterface::ROUTE_MEDIUM_PREFERENCE;
+ if (priority_raw > 0) {
+ priority = NCPControlInterface::ROUTE_HIGH_PREFERENCE;
+ } else if (priority_raw < 0) {
+ priority = NCPControlInterface::ROUTE_LOW_PREFRENCE;
+ }
+
+ interface->add_external_route(
+ &addr,
+ IPV6_PREFIX_BYTES_TO_BITS(prefix_len),
+ domain_id,
+ priority,
+ boost::bind(&DBusIPCAPI_v0::CallbackWithStatus_Helper, this, _1, message)
+ );
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_remove_route_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_message_ref(message);
+
+ uint8_t *prefix = NULL;
+ struct in6_addr addr = {};
+ int prefix_len = 0;
+ uint16_t domain_id = 0;
+
+ dbus_message_ref(message);
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &prefix, &prefix_len,
+ DBUS_TYPE_UINT16, &domain_id,
+ DBUS_TYPE_INVALID
+ );
+
+ if (prefix_len > 16) {
+ prefix_len = 16;
+ }
+
+ memcpy(addr.s6_addr, prefix, prefix_len);
+
+ interface->remove_external_route(
+ &addr,
+ IPV6_PREFIX_BYTES_TO_BITS(prefix_len),
+ domain_id,
+ boost::bind(&DBusIPCAPI_v0::CallbackWithStatus_Helper, this, _1, message)
+ );
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_begin_low_power_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_message_ref(message);
+
+ interface->begin_low_power(boost::bind(&DBusIPCAPI_v0::CallbackWithStatus_Helper,
+ this, _1, message));
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_ping_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_message_ref(message);
+
+ interface->refresh_state(boost::bind(&DBusIPCAPI_v0::CallbackWithStatus_Helper,
+ this, _1, message));
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_host_did_wake_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_message_ref(message);
+
+ interface->host_did_wake(boost::bind(&DBusIPCAPI_v0::CallbackWithStatus_Helper,
+ this, _1, message));
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_stop_scan_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_message_ref(message);
+
+ interface->netscan_stop(boost::bind(&DBusIPCAPI_v0::CallbackWithStatus_Helper,
+ this, _1, message));
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_get_prop_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ const char* property_key_cstr = "";
+ std::string property_key;
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_STRING, &property_key_cstr,
+ DBUS_TYPE_INVALID
+ );
+
+ property_key = property_key_cstr;
+
+ if (interface->translate_deprecated_property(property_key)) {
+ syslog(LOG_WARNING, "GetProp: Property \"%s\" is deprecated. Please use \"%s\" instead.", property_key_cstr, property_key.c_str());
+ }
+
+ dbus_message_ref(message);
+ interface->get_property(property_key,
+ boost::bind(&DBusIPCAPI_v0::CallbackWithStatusArg1_Helper, this,
+ _1, _2, message));
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_set_prop_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ DBusMessageIter iter;
+ const char* property_key_cstr = "";
+ std::string property_key;
+ boost::any property_value;
+
+ dbus_message_iter_init(message, &iter);
+
+ require (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING, bail);
+
+ dbus_message_iter_get_basic(&iter, &property_key_cstr);
+ dbus_message_iter_next(&iter);
+
+ property_value = any_from_dbus_iter(&iter);
+ property_key = property_key_cstr;
+
+ if (interface->translate_deprecated_property(property_key, property_value)) {
+ syslog(LOG_WARNING, "SetProp: Property \"%s\" is deprecated. Please use \"%s\" instead.", property_key_cstr, property_key.c_str());
+ }
+
+ dbus_message_ref(message);
+ interface->set_property(
+ property_key,
+ property_value,
+ boost::bind(&DBusIPCAPI_v0::CallbackWithStatus_Helper, this, _1,
+ message)
+ );
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+bail:
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_reset_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_message_ref(message);
+
+ interface->reset(boost::bind(&DBusIPCAPI_v0::CallbackWithStatus_Helper,
+ this, _1, message));
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_status_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_message_ref(message);
+
+ NCPState ncp_state = UNINITIALIZED;
+ boost::any value(interface->get_property(kWPANTUNDProperty_NCPState));
+
+ if (!value.empty()) {
+ ncp_state = string_to_ncp_state(any_to_string(value));
+ }
+
+ if (ncp_state_is_sleeping(ncp_state)
+ || ncp_state_is_detached_from_ncp(ncp_state)
+ || (ncp_state == UNINITIALIZED)
+ ) {
+ status_response_helper(0, interface, message);
+ } else {
+ interface->refresh_state(boost::bind(&DBusIPCAPI_v0::
+ status_response_helper, this, _1, interface, message));
+ }
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_active_scan_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ int32_t period = 0;
+ ValueMap options;
+ NCPControlInterface::ChannelMask channel_mask = 0;
+
+ dbus_message_ref(message);
+
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_INT32, &period,
+ DBUS_TYPE_UINT32, &channel_mask,
+ DBUS_TYPE_INVALID
+ );
+
+ if (channel_mask) {
+ options[kWPANTUNDProperty_NCPChannelMask] = channel_mask;
+ }
+
+ if (period) {
+ // Ignoring period for now
+ }
+
+ mReceivedBeacons.clear();
+
+ interface->netscan_start(
+ options,
+ boost::bind(
+ &DBusIPCAPI_v0::scan_response_helper,
+ this,
+ _1,
+ message
+ )
+ );
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_resume_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_message_ref(message);
+
+ interface->attach(boost::bind(&DBusIPCAPI_v0::CallbackWithStatus_Helper,
+ this, _1, message));
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_mfg_finish_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ NCPMfgInterface_v0* mfg_interface(dynamic_cast<NCPMfgInterface_v0*>(interface));
+
+ if (mfg_interface) {
+ dbus_message_ref(message);
+
+ mfg_interface->mfg_finish(
+ boost::bind(
+ &DBusIPCAPI_v0::CallbackWithStatusArg1_Helper,
+ this,
+ _1,
+ _2,
+ message
+ )
+ );
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_mfg_begin_test_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ NCPMfgInterface_v0* mfg_interface(dynamic_cast<NCPMfgInterface_v0*>(interface));
+
+ if (mfg_interface) {
+ dbus_message_ref(message);
+
+ int16_t test_type = 0;
+
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_INT16, &test_type
+ );
+
+ mfg_interface->mfg_begin_test(
+ test_type,
+ boost::bind(
+ &DBusIPCAPI_v0::CallbackWithStatus_Helper,
+ this,
+ _1,
+ message
+ )
+ );
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_mfg_end_test_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ int16_t test_type = 0;
+ NCPMfgInterface_v0* mfg_interface(dynamic_cast<NCPMfgInterface_v0*>(interface));
+
+ if (mfg_interface) {
+ dbus_message_ref(message);
+
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_INT16, &test_type
+ );
+
+ mfg_interface->mfg_end_test(test_type, boost::bind(&DBusIPCAPI_v0::CallbackWithStatus_Helper,this, _1, message));
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_mfg_tx_packet_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ const uint8_t *packet_data = NULL;
+ int packet_length = 0;
+ int16_t repeat = 1;
+ NCPMfgInterface_v0* mfg_interface(dynamic_cast<NCPMfgInterface_v0*>(interface));
+
+ if (mfg_interface) {
+ dbus_message_ref(message);
+
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &packet_data, &packet_length,
+ DBUS_TYPE_INT16, &repeat,
+ DBUS_TYPE_INVALID
+ );
+
+ mfg_interface->mfg_tx_packet(
+ Data(packet_data, packet_length),
+ repeat,
+ boost::bind(&DBusIPCAPI_v0::CallbackWithStatus_Helper,this, _1, message)
+ );
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::message_handler(
+ NCPControlInterface* interface,
+ DBusConnection * connection,
+ DBusMessage * message
+ )
+{
+ if ((dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
+ && dbus_message_has_interface(message, WPAN_TUNNEL_DBUS_INTERFACE)
+ && mInterfaceCallbackTable.count(dbus_message_get_member(message))
+ ) {
+ return mInterfaceCallbackTable[dbus_message_get_member(message)](
+ interface,
+ message
+ );
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_mfg_clockmon_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ NCPMfgInterface_v0* mfg_interface(dynamic_cast<NCPMfgInterface_v0*>(interface));
+
+ if (mfg_interface) {
+ dbus_message_ref(message);
+
+ dbus_bool_t enabled;
+ uint32_t timerId;
+
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_BOOLEAN, &enabled,
+ DBUS_TYPE_UINT32, &timerId,
+ DBUS_TYPE_INVALID
+ );
+
+ mfg_interface->mfg_clockmon(
+ static_cast<bool>(enabled),
+ timerId,
+ boost::bind(
+ &DBusIPCAPI_v0::CallbackWithStatus_Helper,
+ this,
+ _1,
+ message
+ )
+ );
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_mfg_gpio_set_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ NCPMfgInterface_v0* mfg_interface(dynamic_cast<NCPMfgInterface_v0*>(interface));
+
+ if (mfg_interface) {
+ dbus_message_ref(message);
+
+ uint8_t port_pin;
+ uint8_t config;
+ uint8_t value;
+
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_BYTE, &port_pin,
+ DBUS_TYPE_BYTE, &config,
+ DBUS_TYPE_BYTE, &value,
+ DBUS_TYPE_INVALID
+ );
+
+ mfg_interface->mfg_gpio_set(
+ port_pin,
+ config,
+ value,
+ boost::bind(
+ &DBusIPCAPI_v0::CallbackWithStatus_Helper,
+ this,
+ _1,
+ message
+ )
+ );
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_mfg_gpio_get_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ NCPMfgInterface_v0* mfg_interface(dynamic_cast<NCPMfgInterface_v0*>(interface));
+
+ if (mfg_interface) {
+ dbus_message_ref(message);
+
+ uint8_t port_pin;
+
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_BYTE, &port_pin,
+ DBUS_TYPE_INVALID
+ );
+
+ mfg_interface->mfg_gpio_get(
+ port_pin,
+ boost::bind(
+ &DBusIPCAPI_v0::CallbackWithStatusArg1_Helper,
+ this,
+ _1,
+ _2,
+ message
+ )
+ );
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return ret;
+}
+
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_mfg_channelcal_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ NCPMfgInterface_v0* mfg_interface(dynamic_cast<NCPMfgInterface_v0*>(interface));
+
+ if (mfg_interface) {
+ dbus_message_ref(message);
+
+ uint8_t channel;
+ uint32_t duration;
+
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_BYTE, &channel,
+ DBUS_TYPE_UINT32, &duration,
+ DBUS_TYPE_INVALID
+ );
+
+ mfg_interface->mfg_channelcal(
+ channel,
+ duration,
+ boost::bind(
+ &DBusIPCAPI_v0::CallbackWithStatus_Helper,
+ this,
+ _1,
+ message
+ )
+ );
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v0::interface_mfg_channelcal_get_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ NCPMfgInterface_v0* mfg_interface(dynamic_cast<NCPMfgInterface_v0*>(interface));
+
+ if (mfg_interface) {
+ dbus_message_ref(message);
+
+ uint8_t channel;
+
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_BYTE, &channel,
+ DBUS_TYPE_INVALID
+ );
+
+ mfg_interface->mfg_channelcal_get(
+ channel,
+ boost::bind(
+ &DBusIPCAPI_v0::CallbackWithStatusArg1_Helper,
+ this,
+ _1,
+ _2,
+ message
+ )
+ );
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return ret;
+}
+
+void
+DBusIPCAPI_v0::ncp_state_changed(NCPControlInterface* interface)
+{
+ DBusMessage* signal;
+ boost::any value;
+ NCPState ncp_state = UNINITIALIZED;
+ std::string ncp_state_str;
+ const char* ncp_state_cstr = kWPANTUNDStateUninitialized;
+
+ value = interface->get_property(kWPANTUNDProperty_NCPState);
+
+ if (!value.empty()) {
+ ncp_state_str = any_to_string(value);
+ ncp_state = string_to_ncp_state(ncp_state_str);
+ ncp_state_cstr = ncp_state_str.c_str();
+ }
+
+ DBusMessageIter iter;
+
+ syslog(LOG_DEBUG,
+ "DBus Sending Association State Changed to %s",
+ ncp_state_cstr);
+ signal = dbus_message_new_signal(
+ (std::string(WPAN_TUNNEL_DBUS_PATH) + "/" + interface->get_name()).c_str(),
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_IFACE_SIGNAL_STATE_CHANGED
+ );
+ dbus_message_append_args(
+ signal,
+ DBUS_TYPE_STRING, &ncp_state_cstr,
+ DBUS_TYPE_INVALID
+ );
+
+ dbus_message_iter_init_append(signal, &iter);
+
+ DBusMessageIter dict;
+
+ dbus_message_iter_open_container(
+ &iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+ &dict
+ );
+
+ append_dict_entry(&dict, kWPANTUNDProperty_DaemonEnabled, interface->get_property(kWPANTUNDProperty_DaemonEnabled));
+
+ if (ncp_state_is_commissioned(ncp_state)) {
+ ipc_append_network_properties(&dict,
+ interface->get_current_network_instance());
+ boost::any prefix = interface->get_property(kWPANTUNDProperty_IPv6MeshLocalPrefix);
+ if (!prefix.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_IPv6MeshLocalPrefix, prefix);
+ }
+
+ prefix = interface->get_property(kWPANTUNDProperty_NestLabs_LegacyMeshLocalAddress);
+ if (!prefix.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_NestLabs_LegacyMeshLocalAddress, prefix);
+ }
+
+ append_dict_entry(&dict, kWPANTUNDProperty_NetworkNodeType, interface->get_property(kWPANTUNDProperty_NetworkNodeType));
+
+ if (ncp_state >= ASSOCIATED) {
+ boost::any networkKey = interface->get_property(kWPANTUNDProperty_NetworkKey);
+ if (!networkKey.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_NetworkKey, networkKey);
+ }
+ }
+ }
+
+ dbus_message_iter_close_container(&iter, &dict);
+
+ dbus_connection_send(mConnection, signal, NULL);
+ dbus_message_unref(signal);
+}
+
+
+static void
+ObjectPathUnregisterFunction_cb(DBusConnection *connection, void *user_data)
+{
+ delete (std::pair<NCPControlInterface*, DBusIPCAPI_v0*> *)user_data;
+}
+
+int
+DBusIPCAPI_v0::add_interface(NCPControlInterface* interface)
+{
+ static const DBusObjectPathVTable ipc_interface_vtable = {
+ &ObjectPathUnregisterFunction_cb,
+ &DBusIPCAPI_v0::dbus_message_handler,
+ };
+
+ std::string name = interface->get_name();
+ std::string path = std::string(WPAN_TUNNEL_DBUS_PATH) + "/" + name;
+
+ std::pair<NCPControlInterface*, DBusIPCAPI_v0*> *cb_data =
+ new std::pair<NCPControlInterface*, DBusIPCAPI_v0*>(interface, this);
+
+ NCPMfgInterface_v0* mfg_interface(dynamic_cast<NCPMfgInterface_v0*>(interface));
+
+ require(dbus_connection_register_object_path(
+ mConnection,
+ path.c_str(),
+ &ipc_interface_vtable,
+ (void*)cb_data
+ ), bail);
+
+ if (mfg_interface) {
+ mfg_interface->mOnMfgRXPacket.connect(
+ boost::bind(
+ &DBusIPCAPI_v0::mfg_rx_packet,
+ this,
+ interface,
+ _1,
+ _2,
+ _3
+ )
+ );
+ }
+
+ interface->mOnPropertyChanged.connect(
+ boost::bind(
+ &DBusIPCAPI_v0::property_changed,
+ this,
+ interface,
+ _1,
+ _2
+ )
+ );
+
+ interface->mOnNetScanBeacon.connect(
+ boost::bind(
+ &DBusIPCAPI_v0::received_beacon,
+ this,
+ interface,
+ _1
+ )
+ );
+
+bail:
+ return 0;
+}
+
+void
+DBusIPCAPI_v0::property_changed(NCPControlInterface* interface,const std::string& key, const boost::any& value)
+{
+ DBusMessage* signal;
+ DBusMessageIter iter;
+ std::string key_as_path;
+ std::string path;
+
+ // Transform the key into a DBus-compatible path
+ for (std::string::const_iterator i = key.begin();
+ i != key.end();
+ ++i
+ ) {
+ const char c = *i;
+ if (isalnum(c) || (c == '_')) {
+ key_as_path += c;
+ } else if (c == ':') {
+ key_as_path += '/';
+ } else if (c == '.') {
+ key_as_path += '_';
+ }
+ }
+
+ if (key == kWPANTUNDProperty_NestLabs_NetworkWakeRemaining) {
+ uint8_t data = static_cast<uint8_t>(any_to_int(interface->get_property(kWPANTUNDProperty_NestLabs_NetworkWakeData)));
+ net_wake_event(interface, data, any_to_int(value));
+ } else if (key == kWPANTUNDProperty_DaemonReadyForHostSleep) {
+ if (any_to_bool(value)) {
+ allow_sleep(interface);
+ } else {
+ prevent_sleep(interface);
+ }
+ } else if (key == kWPANTUNDProperty_NCPState) {
+ ncp_state_changed(interface);
+ } else if (key == kWPANTUNDProperty_NetworkNodeType) {
+ property_changed(interface, "NCPNodeType", value);
+ }
+
+ signal = dbus_message_new_signal(
+ (
+ std::string(WPAN_TUNNEL_DBUS_PATH) + "/" + interface->get_name()
+ + "/" + WPAN_TUNNEL_DBUS_PATH_PROPERTIES + "/" + key_as_path
+ ).c_str(),
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_IFACE_SIGNAL_PROPERTY_CHANGED
+ );
+
+ dbus_message_iter_init_append(signal, &iter);
+
+ append_any_to_dbus_iter(&iter, key);
+ append_any_to_dbus_iter(&iter, value);
+
+ dbus_connection_send(mConnection, signal, NULL);
+ dbus_message_unref(signal);
+}
+
+void
+DBusIPCAPI_v0::net_wake_event(NCPControlInterface* interface,uint8_t data, cms_t ms_remaining)
+{
+ DBusMessage* signal;
+
+ signal = dbus_message_new_signal(
+ (std::string(WPAN_TUNNEL_DBUS_PATH) + "/" + interface->get_name()).c_str(),
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_IFACE_SIGNAL_NET_WAKE
+ );
+ dbus_message_append_args(
+ signal,
+ DBUS_TYPE_BYTE, &data,
+ DBUS_TYPE_INT32, &ms_remaining,
+ DBUS_TYPE_INVALID
+ );
+
+ dbus_connection_send(mConnection, signal, NULL);
+ dbus_message_unref(signal);
+}
+
+void
+DBusIPCAPI_v0::mfg_rx_packet(NCPControlInterface* interface, Data packet, uint8_t lqi, int8_t rssi)
+{
+ DBusMessageIter iter;
+ DBusMessage* signal;
+
+ signal = dbus_message_new_signal(
+ (std::string(WPAN_TUNNEL_DBUS_PATH) + "/" + interface->get_name()).c_str(),
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_IFACE_SIGNAL_MFG_RX
+ );
+
+ dbus_message_iter_init_append(signal, &iter);
+
+ append_any_to_dbus_iter(&iter, packet);
+ append_any_to_dbus_iter(&iter, lqi);
+ append_any_to_dbus_iter(&iter, rssi);
+
+ dbus_connection_send(mConnection, signal, NULL);
+ dbus_message_unref(signal);
+}
+
+void
+DBusIPCAPI_v0::prevent_sleep(NCPControlInterface* interface)
+{
+ DBusMessage* signal;
+
+ signal = dbus_message_new_signal(
+ (std::string(WPAN_TUNNEL_DBUS_PATH) + "/" + interface->get_name()).c_str(),
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_IFACE_SIGNAL_PREVENT_SLEEP
+ );
+ dbus_connection_send(mConnection, signal, NULL);
+ dbus_message_unref(signal);
+}
+
+void
+DBusIPCAPI_v0::allow_sleep(NCPControlInterface* interface)
+{
+ DBusMessage* signal;
+
+ signal = dbus_message_new_signal(
+ (std::string(WPAN_TUNNEL_DBUS_PATH) + "/" + interface->get_name()).c_str(),
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_IFACE_SIGNAL_ALLOW_SLEEP
+ );
+ dbus_connection_send(mConnection, signal, NULL);
+ dbus_message_unref(signal);
+}
+
+
+DBusHandlerResult
+DBusIPCAPI_v0::dbus_message_handler(
+ DBusConnection *connection,
+ DBusMessage * message,
+ void * user_data
+ )
+{
+ if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL) {
+ syslog(LOG_INFO, "Inbound DBus message for INTERFACE \"%s\" from \"%s\"", dbus_message_get_member(message), dbus_message_get_sender(message));
+ }
+ std::pair<NCPControlInterface*,
+ DBusIPCAPI_v0*> *cb_data =
+ (std::pair<NCPControlInterface*, DBusIPCAPI_v0*> *)user_data;
+ return cb_data->second->message_handler(cb_data->first,
+ connection,
+ message);
+}
diff --git a/src/ipc-dbus/DBusIPCAPI_v0.h b/src/ipc-dbus/DBusIPCAPI_v0.h
new file mode 100644
index 0000000..390d73c
--- /dev/null
+++ b/src/ipc-dbus/DBusIPCAPI_v0.h
@@ -0,0 +1,218 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef wpantund_DBusIPCAPI_v0_h
+#define wpantund_DBusIPCAPI_v0_h
+
+#include <map>
+#include <list>
+
+#include <dbus/dbus.h>
+
+#include <boost/bind.hpp>
+#include <boost/any.hpp>
+#include <boost/function.hpp>
+
+#include "NetworkInstance.h"
+#include "Data.h"
+#include "time-utils.h"
+
+namespace nl {
+namespace wpantund {
+
+class NCPControlInterface;
+
+class DBusIPCAPI_v0 {
+public:
+ DBusIPCAPI_v0(DBusConnection *connection);
+ ~DBusIPCAPI_v0();
+
+ int add_interface(NCPControlInterface* interface);
+
+private:
+
+ DBusHandlerResult message_handler(
+ NCPControlInterface* interface,
+ DBusConnection *connection,
+ DBusMessage *message
+ );
+
+ static DBusHandlerResult dbus_message_handler(
+ DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data
+ );
+
+ void init_callback_tables(void);
+
+ // ------------------------------------------------------------------------
+
+ void CallbackWithStatus_Helper(int ret, DBusMessage *original_message);
+ void CallbackWithStatusArg1_Helper(int ret, const boost::any& value, DBusMessage *original_message);
+
+ void status_response_helper(int ret, NCPControlInterface* interface, DBusMessage *original_message);
+ void scan_response_helper(int ret, DBusMessage *original_message);
+
+ // ------------------------------------------------------------------------
+
+ void ncp_state_changed(NCPControlInterface* interface);
+ void net_wake_event(NCPControlInterface* interface,uint8_t data, cms_t ms_remaining);
+ void prevent_sleep(NCPControlInterface* interface);
+ void allow_sleep(NCPControlInterface* interface);
+ void property_changed(NCPControlInterface* interface,const std::string& key, const boost::any& value);
+ void received_beacon(NCPControlInterface* interface, const WPAN::NetworkInstance& network);
+
+ void mfg_rx_packet(NCPControlInterface* interface, nl::Data packet, uint8_t lqi, int8_t rssi);
+
+ // ------------------------------------------------------------------------
+
+ DBusHandlerResult interface_join_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+ DBusHandlerResult interface_form_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+ DBusHandlerResult interface_begin_net_wake_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+ DBusHandlerResult interface_permit_join_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+ DBusHandlerResult interface_add_route_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+ DBusHandlerResult interface_remove_route_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+ DBusHandlerResult interface_leave_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+ DBusHandlerResult interface_data_poll_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+ DBusHandlerResult interface_config_gateway_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+ DBusHandlerResult interface_begin_low_power_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+ DBusHandlerResult interface_ping_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+ DBusHandlerResult interface_host_did_wake_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+ DBusHandlerResult interface_stop_scan_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+ DBusHandlerResult interface_get_prop_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+ DBusHandlerResult interface_set_prop_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+ DBusHandlerResult interface_reset_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+ DBusHandlerResult interface_status_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+ DBusHandlerResult interface_active_scan_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+ DBusHandlerResult interface_resume_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+ DBusHandlerResult interface_mfg_begin_test_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+ DBusHandlerResult interface_mfg_end_test_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+ DBusHandlerResult interface_mfg_tx_packet_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+ DBusHandlerResult interface_mfg_finish_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+ DBusHandlerResult interface_mfg_clockmon_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+ DBusHandlerResult interface_mfg_gpio_set_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+ DBusHandlerResult interface_mfg_gpio_get_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+ DBusHandlerResult interface_mfg_channelcal_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+ DBusHandlerResult interface_mfg_channelcal_get_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+private:
+ typedef DBusHandlerResult (interface_handler_cb)(
+ NCPControlInterface*,
+ DBusMessage *
+ );
+
+ DBusConnection *mConnection;
+ std::list<WPAN::NetworkInstance> mReceivedBeacons;
+ std::map<std::string, boost::function<interface_handler_cb> > mInterfaceCallbackTable;
+
+}; // class DBusIPCAPI_v0
+
+}; // namespace nl
+}; // namespace wpantund
+
+
+#endif
diff --git a/src/ipc-dbus/DBusIPCAPI_v1.cpp b/src/ipc-dbus/DBusIPCAPI_v1.cpp
new file mode 100644
index 0000000..1ac9160
--- /dev/null
+++ b/src/ipc-dbus/DBusIPCAPI_v1.cpp
@@ -0,0 +1,1239 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include <algorithm>
+
+#include <boost/bind.hpp>
+
+#include <dbus/dbus.h>
+
+#include "wpan-dbus-v1.h"
+#include "DBusIPCAPI_v1.h"
+#include "wpan-error.h"
+
+#include "NCPControlInterface.h"
+#include "NCPMfgInterface_v1.h"
+#include "assert-macros.h"
+
+#include "DBUSHelpers.h"
+#include "any-to.h"
+
+using namespace DBUSHelpers;
+using namespace nl;
+using namespace nl::wpantund;
+
+DBusIPCAPI_v1::DBusIPCAPI_v1(DBusConnection *connection)
+ :mConnection(connection)
+{
+ dbus_connection_ref(mConnection);
+ init_callback_tables();
+}
+
+DBusIPCAPI_v1::~DBusIPCAPI_v1()
+{
+ dbus_connection_unref(mConnection);
+}
+
+void
+DBusIPCAPI_v1::init_callback_tables()
+{
+#define INTERFACE_CALLBACK_CONNECT(cmd_name, member_func) \
+ mInterfaceCallbackTable[(cmd_name)] = boost::bind( \
+ &DBusIPCAPI_v1::member_func, this, _1, _2)
+
+ INTERFACE_CALLBACK_CONNECT(WPANTUND_IF_CMD_RESET, interface_reset_handler);
+ INTERFACE_CALLBACK_CONNECT(WPANTUND_IF_CMD_STATUS, interface_status_handler);
+
+ INTERFACE_CALLBACK_CONNECT(WPANTUND_IF_CMD_JOIN, interface_join_handler);
+ INTERFACE_CALLBACK_CONNECT(WPANTUND_IF_CMD_FORM, interface_form_handler);
+ INTERFACE_CALLBACK_CONNECT(WPANTUND_IF_CMD_LEAVE, interface_leave_handler);
+ INTERFACE_CALLBACK_CONNECT(WPANTUND_IF_CMD_ATTACH, interface_attach_handler);
+
+ INTERFACE_CALLBACK_CONNECT(WPANTUND_IF_CMD_ROUTE_ADD, interface_route_add_handler);
+ INTERFACE_CALLBACK_CONNECT(WPANTUND_IF_CMD_ROUTE_REMOVE, interface_route_remove_handler);
+
+ INTERFACE_CALLBACK_CONNECT(WPANTUND_IF_CMD_DATA_POLL, interface_data_poll_handler);
+ INTERFACE_CALLBACK_CONNECT(WPANTUND_IF_CMD_CONFIG_GATEWAY, interface_config_gateway_handler);
+
+ INTERFACE_CALLBACK_CONNECT(WPANTUND_IF_CMD_BEGIN_LOW_POWER, interface_begin_low_power_handler);
+ INTERFACE_CALLBACK_CONNECT(WPANTUND_IF_CMD_HOST_DID_WAKE, interface_host_did_wake_handler);
+ INTERFACE_CALLBACK_CONNECT(WPANTUND_IF_CMD_NET_SCAN_STOP, interface_net_scan_stop_handler);
+ INTERFACE_CALLBACK_CONNECT(WPANTUND_IF_CMD_NET_SCAN_START, interface_net_scan_start_handler);
+ INTERFACE_CALLBACK_CONNECT(WPANTUND_IF_CMD_ENERGY_SCAN_STOP, interface_energy_scan_stop_handler);
+ INTERFACE_CALLBACK_CONNECT(WPANTUND_IF_CMD_ENERGY_SCAN_START, interface_energy_scan_start_handler);
+
+ INTERFACE_CALLBACK_CONNECT(WPANTUND_IF_CMD_MFG, interface_mfg_handler);
+
+ INTERFACE_CALLBACK_CONNECT(WPANTUND_IF_CMD_PROP_GET, interface_get_prop_handler);
+ INTERFACE_CALLBACK_CONNECT(WPANTUND_IF_CMD_PROP_SET, interface_set_prop_handler);
+
+ INTERFACE_CALLBACK_CONNECT(WPANTUND_IF_CMD_PCAP_TO_FD, interface_pcap_to_fd_handler);
+ INTERFACE_CALLBACK_CONNECT(WPANTUND_IF_CMD_PCAP_TERMINATE, interface_pcap_terminate_handler);
+}
+
+static void
+ObjectPathUnregisterFunction_cb(DBusConnection *connection, void *user_data)
+{
+ delete (std::pair<NCPControlInterface*, DBusIPCAPI_v1*> *)user_data;
+}
+
+std::string
+DBusIPCAPI_v1::path_for_iface(NCPControlInterface* interface)
+{
+ return std::string(WPANTUND_DBUS_PATH) + "/" + interface->get_name();
+}
+
+int
+DBusIPCAPI_v1::add_interface(NCPControlInterface* interface)
+{
+ static const DBusObjectPathVTable ipc_interface_vtable = {
+ &ObjectPathUnregisterFunction_cb,
+ &DBusIPCAPI_v1::dbus_message_handler,
+ };
+
+ std::string name = interface->get_name();
+ std::string path = std::string(WPANTUND_DBUS_PATH) + "/" + name;
+
+ std::pair<NCPControlInterface*, DBusIPCAPI_v1*> *cb_data =
+ new std::pair<NCPControlInterface*, DBusIPCAPI_v1*>(interface, this);
+
+ require(dbus_connection_register_object_path(
+ mConnection,
+ path.c_str(),
+ &ipc_interface_vtable,
+ (void*)cb_data
+ ), bail);
+
+ interface->mOnPropertyChanged.connect(
+ boost::bind(
+ &DBusIPCAPI_v1::property_changed,
+ this,
+ interface,
+ _1,
+ _2
+ )
+ );
+
+ interface->mOnNetScanBeacon.connect(
+ boost::bind(
+ &DBusIPCAPI_v1::received_beacon,
+ this,
+ interface,
+ _1
+ )
+ );
+
+ interface->mOnEnergyScanResult.connect(
+ boost::bind(
+ &DBusIPCAPI_v1::received_energy_scan_result,
+ this,
+ interface,
+ _1
+ )
+ );
+
+
+bail:
+ return 0;
+}
+
+void
+DBusIPCAPI_v1::CallbackWithStatus_Helper(int ret, DBusMessage *original_message)
+{
+ DBusMessage *reply = dbus_message_new_method_return(original_message);
+
+ syslog(LOG_DEBUG, "Sending DBus response for \"%s\" to \"%s\"", dbus_message_get_member(original_message), dbus_message_get_sender(original_message));
+
+ if(reply) {
+ dbus_message_append_args(
+ reply,
+ DBUS_TYPE_INT32, &ret,
+ DBUS_TYPE_INVALID
+ );
+
+ dbus_connection_send(mConnection, reply, NULL);
+ dbus_message_unref(reply);
+ }
+ dbus_message_unref(original_message);
+}
+
+static void
+ipc_append_network_properties(
+ DBusMessageIter *iter, const WPAN::NetworkInstance& network
+ )
+{
+ const char* network_name = network.name.c_str();
+
+ if (network_name[0]) {
+ append_dict_entry(
+ iter,
+ kWPANTUNDProperty_NetworkName,
+ DBUS_TYPE_STRING,
+ &network_name
+ );
+ }
+
+ if (network.get_xpanid_as_uint64() != 0) {
+ uint64_t xpan_id = network.get_xpanid_as_uint64();
+ append_dict_entry(
+ iter,
+ kWPANTUNDProperty_NetworkXPANID,
+ DBUS_TYPE_UINT64,
+ &xpan_id
+ );
+ }
+
+ {
+ uint16_t pan_id = network.panid;
+ append_dict_entry(
+ iter,
+ kWPANTUNDProperty_NetworkPANID,
+ DBUS_TYPE_UINT16,
+ &pan_id
+ );
+ }
+
+ if (network.type != 0) {
+ int32_t type = network.type;
+ append_dict_entry(
+ iter,
+ kWPANTUNDProperty_NetworkNodeType,
+ DBUS_TYPE_INT32,
+ &type
+ );
+ }
+
+ if (network.channel) {
+ uint16_t channel = network.channel;
+ append_dict_entry(
+ iter,
+ kWPANTUNDProperty_NCPChannel,
+ DBUS_TYPE_INT16,
+ &channel
+ );
+
+ if (network.rssi != -128) {
+ int8_t rssi = network.rssi;
+ append_dict_entry(iter, "RSSI", DBUS_TYPE_BYTE, &rssi);
+ }
+
+ dbus_bool_t allowing_join = network.joinable;
+ append_dict_entry(
+ iter,
+ kWPANTUNDProperty_NestLabs_NetworkAllowingJoin,
+ DBUS_TYPE_BOOLEAN,
+ &allowing_join
+ );
+ }
+
+ if (network.get_hwaddr_as_uint64() != 0) {
+ append_dict_entry(
+ iter,
+ kWPANTUNDProperty_NCPHardwareAddress,
+ nl::Data(network.hwaddr, 8)
+ );
+ }
+}
+
+static void
+ipc_append_network_dict(
+ DBusMessageIter *iter, const WPAN::NetworkInstance& network
+ )
+{
+ DBusMessageIter dict;
+
+ dbus_message_iter_open_container(
+ iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+ &dict
+ );
+ ipc_append_network_properties(&dict, network);
+
+ dbus_message_iter_close_container(iter, &dict);
+}
+
+void
+DBusIPCAPI_v1::received_beacon(NCPControlInterface* interface, const WPAN::NetworkInstance& network)
+{
+ DBusMessageIter iter;
+ DBusMessage* signal;
+
+ signal = dbus_message_new_signal(
+ path_for_iface(interface).c_str(),
+ WPANTUND_DBUS_APIv1_INTERFACE,
+ WPANTUND_IF_SIGNAL_NET_SCAN_BEACON
+ );
+
+ dbus_message_iter_init_append(signal, &iter);
+
+ ipc_append_network_dict(&iter, network);
+
+ dbus_connection_send(mConnection, signal, NULL);
+
+ dbus_message_unref(signal);
+}
+
+static void
+ipc_append_energy_scan_result_dict(
+ DBusMessageIter *iter, const EnergyScanResultEntry& energy_scan_result
+ )
+{
+ uint16_t channel = energy_scan_result.mChannel;
+ int16_t maxRssi = static_cast<int16_t>(energy_scan_result.mMaxRssi);
+ DBusMessageIter dict;
+
+ dbus_message_iter_open_container(
+ iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+ &dict
+ );
+
+ append_dict_entry(&dict, kWPANTUNDProperty_NCPChannel, DBUS_TYPE_INT16, &channel);
+ append_dict_entry(&dict, "RSSI", DBUS_TYPE_BYTE, &maxRssi);
+
+ dbus_message_iter_close_container(iter, &dict);
+}
+
+void
+DBusIPCAPI_v1::received_energy_scan_result(NCPControlInterface* interface,
+ const EnergyScanResultEntry& energy_scan_result)
+{
+ DBusMessageIter iter;
+ DBusMessage* signal;
+
+ signal = dbus_message_new_signal(
+ path_for_iface(interface).c_str(),
+ WPANTUND_DBUS_APIv1_INTERFACE,
+ WPANTUND_IF_SIGNAL_ENERGY_SCAN_RESULT
+ );
+
+ dbus_message_iter_init_append(signal, &iter);
+
+ ipc_append_energy_scan_result_dict(&iter, energy_scan_result);
+
+ dbus_connection_send(mConnection, signal, NULL);
+
+ dbus_message_unref(signal);
+}
+
+void
+DBusIPCAPI_v1::property_changed(NCPControlInterface* interface,const std::string& key, const boost::any& value)
+{
+ DBusMessageIter iter;
+ DBusMessage* signal;
+ std::string key_as_path;
+ std::string path;
+
+ // Transform the key into a DBus-compatible path
+ for (std::string::const_iterator i = key.begin();
+ i != key.end();
+ ++i
+ ) {
+ const char c = *i;
+ if (isalnum(c) || (c == '_')) {
+ key_as_path += c;
+ } else if (c == ':') {
+ key_as_path += '/';
+ } else if (c == '.') {
+ key_as_path += '_';
+ }
+ }
+
+ path = path_for_iface(interface) + "/Property/" + key_as_path;
+
+ syslog(LOG_DEBUG, "DBusAPIv1:PropChanged: %s - value: %s", path.c_str(), any_to_string(value).c_str());
+
+ signal = dbus_message_new_signal(
+ path.c_str(),
+ WPANTUND_DBUS_APIv1_INTERFACE,
+ WPANTUND_IF_SIGNAL_PROP_CHANGED
+ );
+
+ if (signal) {
+ dbus_message_iter_init_append(signal, &iter);
+
+ append_any_to_dbus_iter(&iter, key);
+ append_any_to_dbus_iter(&iter, value);
+
+ dbus_connection_send(mConnection, signal, NULL);
+ dbus_message_unref(signal);
+ }
+}
+
+void
+DBusIPCAPI_v1::status_response_helper(
+ int ret, NCPControlInterface* interface, DBusMessage *message
+ )
+{
+ DBusMessage *reply = dbus_message_new_method_return(message);
+
+ if (reply) {
+ DBusMessageIter iter;
+ dbus_message_iter_init_append(reply, &iter);
+
+ DBusMessageIter dict;
+ boost::any value;
+ NCPState ncp_state = UNINITIALIZED;
+ std::string ncp_state_string;
+ const char* ncp_state_cstr = kWPANTUNDStateUninitialized;
+
+ dbus_message_iter_open_container(
+ &iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+ &dict
+ );
+
+ value = interface->get_property(kWPANTUNDProperty_NCPState);
+
+ if (!value.empty()) {
+ ncp_state_string = any_to_string(value);
+ ncp_state = string_to_ncp_state(ncp_state_string);
+ ncp_state_cstr = ncp_state_string.c_str();
+ }
+
+ append_dict_entry(&dict,
+ kWPANTUNDProperty_NCPState,
+ DBUS_TYPE_STRING,
+ &ncp_state_cstr);
+
+ value = interface->get_property(kWPANTUNDProperty_DaemonEnabled);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_DaemonEnabled, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_NCPVersion);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_NCPVersion, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_DaemonVersion);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_DaemonVersion, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_ConfigNCPDriverName);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_ConfigNCPDriverName, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_NCPHardwareAddress);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_NCPHardwareAddress, value);
+ }
+
+ if (ncp_state_is_commissioned(ncp_state))
+ {
+ value = interface->get_property(kWPANTUNDProperty_NCPChannel);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_NCPChannel, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_NetworkNodeType);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_NetworkNodeType, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_NetworkName);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_NetworkName, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_NetworkXPANID);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_NetworkXPANID, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_NetworkPANID);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_NetworkPANID, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_IPv6LinkLocalAddress);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_IPv6LinkLocalAddress, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_IPv6MeshLocalAddress);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_IPv6MeshLocalAddress, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_IPv6MeshLocalPrefix);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_IPv6MeshLocalPrefix, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_NestLabs_LegacyMeshLocalAddress);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_NestLabs_LegacyMeshLocalAddress, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_NestLabs_LegacyMeshLocalPrefix);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_NestLabs_LegacyMeshLocalPrefix, value);
+ }
+
+ value = interface->get_property(kWPANTUNDProperty_NestLabs_NetworkAllowingJoin);
+ if (!value.empty()) {
+ append_dict_entry(&dict, kWPANTUNDProperty_NestLabs_NetworkAllowingJoin, value);
+ }
+ }
+
+ dbus_message_iter_close_container(&iter, &dict);
+
+ dbus_connection_send(mConnection, reply, NULL);
+ dbus_message_unref(reply);
+ }
+ dbus_message_unref(message);
+}
+
+void
+DBusIPCAPI_v1::CallbackWithStatusArg1_Helper(
+ int status, const boost::any& value, DBusMessage *message
+)
+{
+ DBusMessage *reply = dbus_message_new_method_return(message);
+ DBusMessageIter iter;
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ if (!status && value.empty()) {
+ status = kWPANTUNDStatus_PropertyEmpty;
+ }
+
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &status);
+
+ if (value.empty()) {
+ append_any_to_dbus_iter(&iter, std::string("<empty>"));
+ } else {
+ append_any_to_dbus_iter(&iter, value);
+ }
+
+ dbus_connection_send(mConnection, reply, NULL);
+ dbus_message_unref(message);
+ dbus_message_unref(reply);
+}
+
+
+DBusHandlerResult
+DBusIPCAPI_v1::interface_reset_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_message_ref(message);
+
+ interface->reset(boost::bind(&DBusIPCAPI_v1::CallbackWithStatus_Helper,
+ this, _1, message));
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v1::interface_status_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_message_ref(message);
+
+ NCPState ncp_state = UNINITIALIZED;
+ boost::any value(interface->get_property(kWPANTUNDProperty_NCPState));
+
+ if (!value.empty()) {
+ ncp_state = string_to_ncp_state(any_to_string(value));
+ }
+
+ if (ncp_state_is_sleeping(ncp_state)
+ || ncp_state_is_detached_from_ncp(ncp_state)
+ || (ncp_state == UNINITIALIZED)
+ ) {
+ status_response_helper(0, interface, message);
+ } else {
+ interface->refresh_state(boost::bind(&DBusIPCAPI_v1::
+ status_response_helper, this, _1, interface, message));
+ }
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v1::interface_join_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ ValueMap options;
+ DBusMessageIter iter;
+
+ dbus_message_iter_init(message, &iter);
+
+ options = value_map_from_dbus_iter(&iter);
+
+ dbus_message_ref(message);
+
+ interface->join(
+ options,
+ boost::bind(
+ &DBusIPCAPI_v1::CallbackWithStatus_Helper,
+ this,
+ _1,
+ message
+ )
+ );
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v1::interface_form_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ ValueMap options;
+ DBusMessageIter iter;
+
+ dbus_message_iter_init(message, &iter);
+
+ options = value_map_from_dbus_iter(&iter);
+
+ dbus_message_ref(message);
+
+ interface->form(
+ options,
+ boost::bind(
+ &DBusIPCAPI_v1::CallbackWithStatus_Helper,
+ this,
+ _1,
+ message
+ )
+ );
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v1::interface_leave_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_message_ref(message);
+
+ interface->leave(boost::bind(&DBusIPCAPI_v1::CallbackWithStatus_Helper,
+ this, _1, message));
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v1::interface_attach_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_message_ref(message);
+
+ interface->attach(boost::bind(&DBusIPCAPI_v1::CallbackWithStatus_Helper,
+ this, _1, message));
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v1::interface_begin_low_power_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_message_ref(message);
+
+ interface->begin_low_power(boost::bind(&DBusIPCAPI_v1::CallbackWithStatus_Helper,
+ this, _1, message));
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v1::interface_host_did_wake_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_message_ref(message);
+
+ interface->host_did_wake(boost::bind(&DBusIPCAPI_v1::CallbackWithStatus_Helper,
+ this, _1, message));
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v1::interface_net_scan_stop_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_message_ref(message);
+
+ interface->netscan_stop(boost::bind(&DBusIPCAPI_v1::CallbackWithStatus_Helper,
+ this, _1, message));
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v1::interface_energy_scan_stop_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_message_ref(message);
+
+ interface->energyscan_stop(boost::bind(&DBusIPCAPI_v1::CallbackWithStatus_Helper,
+ this, _1, message));
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v1::interface_mfg_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ NCPMfgInterface_v1* mfg_interface(dynamic_cast<NCPMfgInterface_v1*>(interface));
+
+ const char *mfg_command_cstr = "";
+ std::string mfg_command;
+
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_STRING, &mfg_command_cstr,
+ DBUS_TYPE_INVALID
+ );
+
+ mfg_command = mfg_command_cstr;
+
+ dbus_message_ref(message);
+
+ mfg_interface->mfg(
+ mfg_command,
+ boost::bind(
+ &DBusIPCAPI_v1::CallbackWithStatusArg1_Helper,
+ this,
+ _1,
+ _2,
+ message
+ )
+ );
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v1::interface_get_prop_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ const char* property_key_cstr = "";
+ std::string property_key;
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_STRING, &property_key_cstr,
+ DBUS_TYPE_INVALID
+ );
+
+ property_key = property_key_cstr;
+
+ if (interface->translate_deprecated_property(property_key)) {
+ syslog(LOG_WARNING, "PropGet: Property \"%s\" is deprecated. Please use \"%s\" instead.", property_key_cstr, property_key.c_str());
+ }
+
+ dbus_message_ref(message);
+
+ interface->get_property(
+ property_key,
+ boost::bind(
+ &DBusIPCAPI_v1::CallbackWithStatusArg1_Helper,
+ this,
+ _1,
+ _2,
+ message
+ )
+ );
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v1::interface_set_prop_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ DBusMessageIter iter;
+ const char* property_key_cstr = "";
+ std::string property_key;
+ boost::any property_value;
+
+ dbus_message_iter_init(message, &iter);
+
+ require (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING, bail);
+
+ dbus_message_iter_get_basic(&iter, &property_key_cstr);
+ dbus_message_iter_next(&iter);
+
+ property_value = any_from_dbus_iter(&iter);
+ property_key = property_key_cstr;
+
+ if (interface->translate_deprecated_property(property_key, property_value)) {
+ syslog(LOG_WARNING, "PropSet: Property \"%s\" is deprecated. Please use \"%s\" instead.", property_key_cstr, property_key.c_str());
+ }
+
+ dbus_message_ref(message);
+
+ interface->set_property(
+ property_key,
+ property_value,
+ boost::bind(
+ &DBusIPCAPI_v1::CallbackWithStatus_Helper,
+ this,
+ _1,
+ message
+ )
+ );
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+bail:
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v1::interface_net_scan_start_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ ValueMap options;
+ NCPControlInterface::ChannelMask channel_mask = 0;
+
+ dbus_message_ref(message);
+
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_UINT32, &channel_mask,
+ DBUS_TYPE_INVALID
+ );
+
+ if (channel_mask) {
+ options[kWPANTUNDProperty_NCPChannelMask] = channel_mask;
+ }
+
+ interface->netscan_start(
+ options,
+ boost::bind(
+ &DBusIPCAPI_v1::CallbackWithStatus_Helper,
+ this,
+ _1,
+ message
+ )
+ );
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v1::interface_energy_scan_start_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ ValueMap options;
+ NCPControlInterface::ChannelMask channel_mask = 0;
+
+ dbus_message_ref(message);
+
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_UINT32, &channel_mask,
+ DBUS_TYPE_INVALID
+ );
+
+ if (channel_mask) {
+ options[kWPANTUNDProperty_NCPChannelMask] = channel_mask;
+ }
+
+ interface->energyscan_start(
+ options,
+ boost::bind(
+ &DBusIPCAPI_v1::CallbackWithStatus_Helper,
+ this,
+ _1,
+ message
+ )
+ );
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v1::interface_pcap_to_fd_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ int fd = -1;
+
+ dbus_message_ref(message);
+
+ dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_UNIX_FD, &fd,
+ DBUS_TYPE_INVALID
+ );
+
+ interface->pcap_to_fd(
+ fd,
+ boost::bind(
+ &DBusIPCAPI_v1::CallbackWithStatus_Helper,
+ this,
+ _1,
+ message
+ )
+ );
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v1::interface_pcap_terminate_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_message_ref(message);
+
+ interface->pcap_terminate(
+ boost::bind(
+ &DBusIPCAPI_v1::CallbackWithStatus_Helper,
+ this,
+ _1,
+ message
+ )
+ );
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v1::interface_data_poll_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_message_ref(message);
+
+ interface->data_poll(boost::bind(&DBusIPCAPI_v1::CallbackWithStatus_Helper,
+ this, _1, message));
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v1::interface_config_gateway_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ dbus_bool_t default_route = FALSE;
+ uint32_t preferred_lifetime = 0;
+ uint32_t valid_lifetime = 0;
+ uint8_t *prefix(NULL);
+ int prefix_len_in_bytes(0);
+ struct in6_addr address = {};
+ bool did_succeed(false);
+
+ did_succeed = dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_BOOLEAN, &default_route,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &prefix, &prefix_len_in_bytes,
+ DBUS_TYPE_UINT32, &preferred_lifetime,
+ DBUS_TYPE_UINT32, &valid_lifetime,
+ DBUS_TYPE_INVALID
+ );
+
+ require(did_succeed, bail);
+ require(prefix_len_in_bytes <= sizeof(address), bail);
+ require(prefix_len_in_bytes >= 0, bail);
+
+ memcpy(address.s6_addr, prefix, prefix_len_in_bytes);
+
+ dbus_message_ref(message);
+
+ if (valid_lifetime == 0) {
+ interface->remove_on_mesh_prefix(
+ &address,
+ boost::bind(&DBusIPCAPI_v1::CallbackWithStatus_Helper,this, _1, message)
+ );
+ } else {
+ interface->add_on_mesh_prefix(
+ &address,
+ default_route,
+ boost::bind(&DBusIPCAPI_v1::CallbackWithStatus_Helper,this, _1, message)
+ );
+ }
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+bail:
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v1::interface_route_add_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_message_ref(message);
+
+ uint8_t *route_prefix(NULL);
+ int prefix_len_in_bytes(0);
+ uint16_t domain_id(0);
+ int16_t priority_raw(0);
+ NCPControlInterface::ExternalRoutePriority priority(NCPControlInterface::ROUTE_MEDIUM_PREFERENCE);
+ uint8_t prefix_len_in_bits(0);
+ struct in6_addr address = {};
+ bool did_succeed(false);
+
+ did_succeed = dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &route_prefix, &prefix_len_in_bytes,
+ DBUS_TYPE_UINT16, &domain_id,
+ DBUS_TYPE_INT16, &priority_raw,
+ DBUS_TYPE_BYTE, &prefix_len_in_bits,
+ DBUS_TYPE_INVALID
+ );
+
+ if (!did_succeed) {
+ // Likely using the old syntax that doesn't include the prefix length in bits
+ did_succeed = dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &route_prefix, &prefix_len_in_bytes,
+ DBUS_TYPE_UINT16, &domain_id,
+ DBUS_TYPE_INT16, &priority_raw,
+ DBUS_TYPE_INVALID
+ );
+ prefix_len_in_bits = IPV6_PREFIX_BYTES_TO_BITS(prefix_len_in_bytes);
+ }
+
+ require(did_succeed, bail);
+ require(prefix_len_in_bytes <= sizeof(address), bail);
+ require(prefix_len_in_bytes >= 0, bail);
+
+ memcpy(address.s6_addr, route_prefix, prefix_len_in_bytes);
+
+ if (priority_raw > 0) {
+ priority = NCPControlInterface::ROUTE_HIGH_PREFERENCE;
+ } else if (priority_raw < 0) {
+ priority = NCPControlInterface::ROUTE_LOW_PREFRENCE;
+ }
+
+ dbus_message_ref(message);
+
+ interface->add_external_route(
+ &address,
+ prefix_len_in_bits,
+ domain_id,
+ priority,
+ boost::bind(&DBusIPCAPI_v1::CallbackWithStatus_Helper, this, _1, message)
+ );
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+bail:
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v1::interface_route_remove_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+) {
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ uint8_t *route_prefix = NULL;
+ int prefix_len_in_bytes(0);
+ uint8_t prefix_len_in_bits(0);
+ uint16_t domain_id = 0;
+ struct in6_addr address = {};
+ bool did_succeed(false);
+
+ did_succeed = dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &route_prefix, &prefix_len_in_bytes,
+ DBUS_TYPE_UINT16, &domain_id,
+ DBUS_TYPE_BYTE, &prefix_len_in_bits,
+ DBUS_TYPE_INVALID
+ );
+
+ if (!did_succeed) {
+ // Likely using the old syntax that doesn't include the prefix length in bits
+ did_succeed = dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &route_prefix, &prefix_len_in_bytes,
+ DBUS_TYPE_UINT16, &domain_id,
+ DBUS_TYPE_INVALID
+ );
+ prefix_len_in_bits = IPV6_PREFIX_BYTES_TO_BITS(prefix_len_in_bytes);
+ }
+
+ require(did_succeed, bail);
+ require(prefix_len_in_bytes <= sizeof(address), bail);
+ require(prefix_len_in_bytes >= 0, bail);
+
+ memcpy(address.s6_addr, route_prefix, prefix_len_in_bytes);
+
+ dbus_message_ref(message);
+
+ interface->remove_external_route(
+ &address,
+ prefix_len_in_bits,
+ domain_id,
+ boost::bind(&DBusIPCAPI_v1::CallbackWithStatus_Helper, this, _1, message)
+ );
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+bail:
+
+ return ret;
+}
+
+
+DBusHandlerResult
+DBusIPCAPI_v1::message_handler(
+ NCPControlInterface* interface,
+ DBusConnection * connection,
+ DBusMessage * message
+ )
+{
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ if ((dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL)
+ && (dbus_message_has_interface(message, WPANTUND_DBUS_APIv1_INTERFACE)
+ || dbus_message_has_interface(message, WPANTUND_DBUS_NLAPIv1_INTERFACE))
+ && mInterfaceCallbackTable.count(dbus_message_get_member(message))
+ ) {
+ try {
+ ret = mInterfaceCallbackTable.at(dbus_message_get_member(message))(
+ interface,
+ message
+ );
+ } catch (std::invalid_argument x) {
+ DBusIPCAPI_v1::CallbackWithStatus_Helper(kWPANTUNDStatus_InvalidArgument,message);
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+ }
+ }
+
+ return ret;
+}
+
+DBusHandlerResult
+DBusIPCAPI_v1::dbus_message_handler(
+ DBusConnection *connection,
+ DBusMessage * message,
+ void * user_data
+) {
+ if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL) {
+ syslog(LOG_INFO, "Inbound DBus message for INTERFACE \"%s\" from \"%s\"", dbus_message_get_member(message), dbus_message_get_sender(message));
+ }
+ std::pair<NCPControlInterface*,
+ DBusIPCAPI_v1*> *cb_data =
+ (std::pair<NCPControlInterface*, DBusIPCAPI_v1*> *)user_data;
+ return cb_data->second->message_handler(cb_data->first,
+ connection,
+ message);
+}
diff --git a/src/ipc-dbus/DBusIPCAPI_v1.h b/src/ipc-dbus/DBusIPCAPI_v1.h
new file mode 100644
index 0000000..79cf3a1
--- /dev/null
+++ b/src/ipc-dbus/DBusIPCAPI_v1.h
@@ -0,0 +1,205 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef wpantund_DBusIPCAPI_v1_h
+#define wpantund_DBusIPCAPI_v1_h
+
+#include <map>
+#include <list>
+
+#include <dbus/dbus.h>
+
+#include <boost/bind.hpp>
+#include <boost/any.hpp>
+#include <boost/function.hpp>
+
+#include "NetworkInstance.h"
+#include "NCPTypes.h"
+#include "Data.h"
+#include "time-utils.h"
+
+namespace nl {
+namespace wpantund {
+
+class NCPControlInterface;
+
+class DBusIPCAPI_v1 {
+public:
+ DBusIPCAPI_v1(DBusConnection *connection);
+ ~DBusIPCAPI_v1();
+
+ int add_interface(NCPControlInterface* interface);
+
+private:
+
+ DBusHandlerResult message_handler(
+ NCPControlInterface* interface,
+ DBusConnection *connection,
+ DBusMessage *message
+ );
+
+ static DBusHandlerResult dbus_message_handler(
+ DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data
+ );
+
+ void init_callback_tables(void);
+
+ std::string path_for_iface(NCPControlInterface* interface);
+
+ // ------------------------------------------------------------------------
+
+ void CallbackWithStatus_Helper(int ret, DBusMessage *original_message);
+ void CallbackWithStatusArg1_Helper(int ret, const boost::any& value, DBusMessage *original_message);
+
+ void status_response_helper(int ret, NCPControlInterface* interface, DBusMessage *original_message);
+
+ // TODO: Remove these...
+ //void scan_response_helper(int ret, DBusMessage *original_message);
+ //void energy_scan_response_helper(int ret, DBusMessage *original_message);
+
+ // ------------------------------------------------------------------------
+
+ void property_changed(NCPControlInterface* interface,const std::string& key, const boost::any& value);
+ void received_beacon(NCPControlInterface* interface, const WPAN::NetworkInstance& network);
+ void received_energy_scan_result(NCPControlInterface* interface, const EnergyScanResultEntry& energy_scan_result);
+
+ // ------------------------------------------------------------------------
+
+ DBusHandlerResult interface_route_add_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+ DBusHandlerResult interface_route_remove_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+ DBusHandlerResult interface_reset_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+ DBusHandlerResult interface_status_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+ DBusHandlerResult interface_join_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+ DBusHandlerResult interface_form_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+ DBusHandlerResult interface_leave_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+ DBusHandlerResult interface_attach_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+ DBusHandlerResult interface_begin_low_power_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+ DBusHandlerResult interface_host_did_wake_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+ DBusHandlerResult interface_pcap_to_fd_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+ DBusHandlerResult interface_pcap_terminate_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+ DBusHandlerResult interface_get_prop_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+ DBusHandlerResult interface_set_prop_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+ DBusHandlerResult interface_net_scan_start_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+ DBusHandlerResult interface_net_scan_stop_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+ DBusHandlerResult interface_energy_scan_start_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+ DBusHandlerResult interface_energy_scan_stop_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+ DBusHandlerResult interface_data_poll_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+ DBusHandlerResult interface_config_gateway_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+ DBusHandlerResult interface_mfg_handler(
+ NCPControlInterface* interface,
+ DBusMessage * message
+ );
+
+private:
+ typedef DBusHandlerResult (interface_handler_cb)(
+ NCPControlInterface*,
+ DBusMessage *
+ );
+
+ DBusConnection *mConnection;
+ std::map<std::string, boost::function<interface_handler_cb> > mInterfaceCallbackTable;
+}; // class DBusIPCAPI_v1
+
+}; // namespace nl
+}; // namespace wpantund
+
+
+#endif
diff --git a/src/ipc-dbus/Makefile.am b/src/ipc-dbus/Makefile.am
new file mode 100644
index 0000000..80f38af
--- /dev/null
+++ b/src/ipc-dbus/Makefile.am
@@ -0,0 +1,54 @@
+#
+# Copyright (c) 2016 Nest Labs, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/src/util \
+ -I$(top_srcdir)/src/ipc-dbus \
+ -I$(top_srcdir)/src/wpantund \
+ -I$(top_srcdir)/third_party/assert-macros \
+ $(NULL)
+
+EXTRA_DIST = wpantund.conf
+
+DISTCLEANFILES = .deps Makefile
+
+AUTOMAKE_OPTIONS = subdir-objects
+
+dbusconfdir = $(DBUS_CONFDIR)
+
+dbusconf_DATA = wpantund.conf
+
+noinst_LTLIBRARIES = libwpantund-dbus.la
+
+libwpantund_dbus_la_SOURCES = \
+ DBUSIPCServer.cpp \
+ DBUSIPCServer.h \
+ DBusIPCAPI_v1.cpp \
+ DBusIPCAPI_v1.h \
+ wpan-dbus-v1.h \
+ DBusIPCAPI_v0.cpp \
+ DBusIPCAPI_v0.h \
+ wpan-dbus-v0.h \
+ ../util/DBUSHelpers.cpp \
+ $(NULL)
+
+libwpantund_dbus_la_LIBADD = $(DBUS_LIBS)
+libwpantund_dbus_la_CPPFLAGS = $(AM_CPPFLAGS) $(DBUS_CFLAGS)
+libwpantund_dbus_la_CXXFLAGS = $(BOOST_CXXFLAGS)
+
+pkginclude_HEADERS = wpan-dbus-v0.h wpan-dbus-v1.h
diff --git a/src/ipc-dbus/wpan-dbus-v0.h b/src/ipc-dbus/wpan-dbus-v0.h
new file mode 100644
index 0000000..9677316
--- /dev/null
+++ b/src/ipc-dbus/wpan-dbus-v0.h
@@ -0,0 +1,99 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef wpantund_wpan_dbus_v0_h
+#define wpantund_wpan_dbus_v0_h
+
+#include "wpan-properties.h"
+
+#if !defined(wpantund_DBusIPCAPI_v0_h) && !defined(BUILD_FEATURE_WPANTUND)
+// Disabling these warnings for now.
+// Will re-enable once more stuff has moved over.
+//#warning wpan-dbus-v0.h is deprecated. Please migrate to the API in wpan-dbus-v1.h.
+#endif
+
+#define WPAN_TUNNEL_DBUS_NAME "com.nestlabs.WPANTunnelDriver"
+#define WPAN_TUNNEL_DBUS_INTERFACE "com.nestlabs.WPANTunnelDriver"
+#define WPAN_TUNNEL_DBUS_PATH "/com/nestlabs/WPANTunnelDriver"
+#define WPAN_TUNNEL_DBUS_VERSION 2
+#define WPAN_TUNNEL_DBUS_PATH_PROPERTIES "Properties"
+
+#define WPAN_TUNNEL_CMD_GET_INTERFACES "GetInterfaces"
+#define WPAN_TUNNEL_CMD_GET_VERSION "GetVersion"
+
+#define WPAN_TUNNEL_SIGNAL_INTERFACE_ADDED "InterfaceAdded"
+#define WPAN_TUNNEL_SIGNAL_INTERFACE_REMOVED "InterfaceRemoved"
+
+#define WPAN_IFACE_SIGNAL_STATE_CHANGED "AssociationStateChanged"
+#define WPAN_IFACE_SIGNAL_PROPERTY_CHANGED "PropertyChanged"
+#define WPAN_IFACE_SIGNAL_NET_WAKE "NetWake"
+#define WPAN_IFACE_SIGNAL_PREVENT_SLEEP "PreventSleep"
+#define WPAN_IFACE_SIGNAL_ALLOW_SLEEP "AllowSleep"
+
+#define WPAN_IFACE_CMD_JOIN "Join"
+#define WPAN_IFACE_CMD_FORM "Form"
+#define WPAN_IFACE_CMD_LEAVE "Leave"
+#define WPAN_IFACE_CMD_ACTIVE_SCAN "Scan"
+#define WPAN_IFACE_CMD_RESUME "Resume"
+#define WPAN_IFACE_CMD_PERMIT_JOIN "PermitJoin"
+#define WPAN_IFACE_CMD_STOP_SCAN "StopScan"
+#define WPAN_IFACE_CMD_RESET "Reset"
+#define WPAN_IFACE_CMD_STATUS "Status"
+#define WPAN_IFACE_CMD_PING "Ping"
+#define WPAN_IFACE_CMD_SCAN "Scan"
+#define WPAN_IFACE_CMD_BEGIN_NET_WAKE "BeginNetWake"
+#define WPAN_IFACE_CMD_CONFIG_GATEWAY "ConfigGateway"
+#define WPAN_IFACE_CMD_ADD_ROUTE "AddRoute"
+#define WPAN_IFACE_CMD_REMOVE_ROUTE "RemoveRoute"
+#define WPAN_IFACE_CMD_DATA_POLL "DataPoll"
+#define WPAN_IFACE_CMD_HOST_DID_WAKE "HostDidWake"
+
+#define WPAN_IFACE_CMD_BEGIN_LOW_POWER "BeginLowPower"
+
+/* The property "MfgTestMode" must be enabled in order to use these commands */
+#define WPAN_IFACE_CMD_MFG_FINISH "MfgFinish"
+#define WPAN_IFACE_CMD_MFG_BEGIN_TEST "MfgBeginTest" // Argument is test type
+#define WPAN_IFACE_CMD_MFG_END_TEST "MfgEndTest" // Argument is test type
+#define WPAN_IFACE_CMD_MFG_TX_PACKET "MfgTXPacket" // Argument is packet
+#define WPAN_IFACE_SIGNAL_MFG_RX "MfgRXPacket" // packet, lqi, rssi
+#define WPAN_IFACE_CMD_MFG_CLOCKMON "MfgClockMon"
+#define WPAN_IFACE_CMD_MFG_GPIO_SET "MfgGPIOSet"
+#define WPAN_IFACE_CMD_MFG_GPIO_GET "MfgGPIOGet"
+#define WPAN_IFACE_CMD_MFG_CHANNELCAL "MfgChannelCal"
+#define WPAN_IFACE_CMD_MFG_CHANNELCAL_GET "MfgChannelCalGet"
+/* Also, there are the following properties that can be set when in MFG mode:
+ * "Channel", "TXPower", "SYNOffset"
+ */
+
+
+#define WPAN_IFACE_CMD_GET_PROP "GetProp"
+#define WPAN_IFACE_CMD_SET_PROP "SetProp"
+
+
+#define WPAN_IFACE_PROTOCOL_TCPUDP 0xFF
+#define WPAN_IFACE_PROTOCOL_TCP 6
+#define WPAN_IFACE_PROTOCOL_UDP 17
+
+#define WPAN_IFACE_ROLE_UNKNOWN 0
+#define WPAN_IFACE_ROLE_ROUTER 2
+#define WPAN_IFACE_ROLE_END_DEVICE 3
+#define WPAN_IFACE_ROLE_SLEEPY_END_DEVICE 4
+#define WPAN_IFACE_ROLE_LURKER 6
+
+#endif
diff --git a/src/ipc-dbus/wpan-dbus-v1.h b/src/ipc-dbus/wpan-dbus-v1.h
new file mode 100644
index 0000000..2d573d8
--- /dev/null
+++ b/src/ipc-dbus/wpan-dbus-v1.h
@@ -0,0 +1,89 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef wpantund_wpan_dbus_v1_h
+#define wpantund_wpan_dbus_v1_h
+
+#include "wpan-properties.h"
+
+#define WPANTUND_DBUS_NAME "org.wpantund"
+#define WPANTUND_DBUS_PATH "/org/wpantund"
+
+// ============================================================================
+// Base Interface
+
+#define WPANTUND_DBUS_BASE_INTERFACE "org.wpantund"
+
+#define WPANTUND_BASE_CMD_GET_INTERFACES "GetInterfaces"
+
+#define WPANTUND_BASE_SIGNAL_INTERFACE_ADDED "InterfaceAdded"
+#define WPANTUND_BASE_SIGNAL_INTERFACE_REMOVED "InterfaceRemoved"
+
+#define WPANTUND_IF_GET_VERSION "GetVersion"
+
+// ============================================================================
+// Standard API Interface
+
+// Note that this API is not yet fully baked and may change before
+// being considered frozen.
+
+#define WPANTUND_DBUS_APIv1_INTERFACE WPANTUND_DBUS_BASE_INTERFACE".v1"
+
+#define WPANTUND_IF_CMD_JOIN "Join"
+#define WPANTUND_IF_CMD_FORM "Form"
+#define WPANTUND_IF_CMD_LEAVE "Leave"
+#define WPANTUND_IF_CMD_ATTACH "Attach"
+
+#define WPANTUND_IF_CMD_RESET "Reset"
+#define WPANTUND_IF_CMD_STATUS "Status"
+
+#define WPANTUND_IF_CMD_ROUTE_ADD "RouteAdd"
+#define WPANTUND_IF_CMD_ROUTE_REMOVE "RouteRemove"
+#define WPANTUND_IF_CMD_CONFIG_GATEWAY "ConfigGateway"
+#define WPANTUND_IF_CMD_DATA_POLL "DataPoll"
+
+#define WPANTUND_IF_CMD_BEGIN_LOW_POWER "BeginLowPower"
+#define WPANTUND_IF_CMD_HOST_DID_WAKE "HostDidWake"
+
+#define WPANTUND_IF_CMD_PCAP_TO_FD "PcapToFd"
+#define WPANTUND_IF_CMD_PCAP_TERMINATE "PcapTerminate"
+
+#define WPANTUND_IF_CMD_NET_SCAN_START "NetScanStart"
+#define WPANTUND_IF_CMD_NET_SCAN_STOP "NetScanStop"
+#define WPANTUND_IF_SIGNAL_NET_SCAN_BEACON "NetScanBeacon"
+
+#define WPANTUND_IF_CMD_ENERGY_SCAN_START "EnergyScanStart"
+#define WPANTUND_IF_CMD_ENERGY_SCAN_STOP "EnergyScanStop"
+#define WPANTUND_IF_SIGNAL_ENERGY_SCAN_RESULT "EnergyScanResult"
+
+#define WPANTUND_IF_CMD_PROP_GET "PropGet"
+#define WPANTUND_IF_CMD_PROP_SET "PropSet"
+#define WPANTUND_IF_SIGNAL_PROP_CHANGED "PropChanged"
+
+// ============================================================================
+// NestLabs Internal API Interface
+
+#define WPANTUND_DBUS_NLAPIv1_INTERFACE "com.nestlabs.wpantund.v1"
+
+#define WPANTUND_IF_CMD_PERMIT_JOIN "PermitJoin"
+#define WPANTUND_IF_CMD_NETWORK_WAKE_BEGIN "NetworkWakeBegin"
+
+#define WPANTUND_IF_CMD_MFG "Mfg"
+
+#endif
diff --git a/src/ipc-dbus/wpantund.conf b/src/ipc-dbus/wpantund.conf
new file mode 100644
index 0000000..bf26bf1
--- /dev/null
+++ b/src/ipc-dbus/wpantund.conf
@@ -0,0 +1,44 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <policy user="root">
+ <allow own="org.wpantund"/>
+ <allow own="org.wpantund.wpanctl"/>
+
+ <allow send_interface="org.wpantund.Join"/>
+ <allow send_interface="org.wpantund.Form"/>
+ <allow send_interface="org.wpantund.Leave"/>
+ <allow send_interface="org.wpantund.Attach"/>
+ <allow send_interface="org.wpantund.Status"/>
+ <allow send_interface="org.wpantund.Reset"/>
+ <allow send_interface="org.wpantund.NetScanStart"/>
+ <allow send_interface="org.wpantund.NetScanStop"/>
+ <allow send_interface="org.wpantund.List"/>
+
+
+ <!-- Deprecated -->
+ <allow own="com.nestlabs.WPANTunnelDriver"/>
+ <allow own="com.nestlabs.WPANTunnelDriver.wpanctl"/>
+ <allow send_destination="com.nestlabs.WPANTunnelDriver"/>
+ <allow send_interface="com.nestlabs.WPANTunnelDriver.Join"/>
+ <allow send_interface="com.nestlabs.WPANTunnelDriver.Form"/>
+ <allow send_interface="com.nestlabs.WPANTunnelDriver.Leave"/>
+ <allow send_interface="com.nestlabs.WPANTunnelDriver.Resume"/>
+ <allow send_interface="com.nestlabs.WPANTunnelDriver.Scan"/>
+ <allow send_interface="com.nestlabs.WPANTunnelDriver.PermitJoin"/>
+ <allow send_interface="com.nestlabs.WPANTunnelDriver.Status"/>
+ <allow send_interface="com.nestlabs.WPANTunnelDriver.List"/>
+ </policy>
+ <policy at_console="true">
+ <allow send_destination="org.wpantund"/>
+
+ <!-- Deprecated -->
+ <allow send_destination="com.nestlabs.WPANTunnelDriver"/>
+ </policy>
+ <policy context="default">
+ <deny send_destination="org.wpantund"/>
+
+ <!-- Deprecated -->
+ <deny send_destination="com.nestlabs.WPANTunnelDriver"/>
+ </policy>
+</busconfig>
diff --git a/src/ncp-dummy/DummyNCPControlInterface.cpp b/src/ncp-dummy/DummyNCPControlInterface.cpp
new file mode 100644
index 0000000..518a70a
--- /dev/null
+++ b/src/ncp-dummy/DummyNCPControlInterface.cpp
@@ -0,0 +1,275 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "assert-macros.h"
+
+#include "DummyNCPControlInterface.h"
+#include "DummyNCPInstance.h"
+
+#include "wpantund.h"
+#include "config-file.h"
+#include "nlpt.h"
+#include "string-utils.h"
+#include "any-to.h"
+#include "time-utils.h"
+
+#include <cstring>
+#include <algorithm>
+#include <errno.h>
+#include <arpa/inet.h>
+#include <syslog.h>
+#include <sys/time.h>
+
+#include <boost/bind.hpp>
+
+using namespace nl;
+using namespace nl::wpantund;
+
+// ----------------------------------------------------------------------------
+// MARK: -
+
+DummyNCPControlInterface::DummyNCPControlInterface(DummyNCPInstance* instance_pointer)
+ :mNCPInstance(instance_pointer)
+{
+}
+
+// ----------------------------------------------------------------------------
+// MARK: -
+
+void
+DummyNCPControlInterface::join(
+ const ValueMap& options,
+ CallbackWithStatus cb
+) {
+ // TODO: Writeme!
+ cb(kWPANTUNDStatus_FeatureNotImplemented);
+}
+
+void
+DummyNCPControlInterface::form(
+ const ValueMap& options,
+ CallbackWithStatus cb
+) {
+
+ // TODO: Writeme!
+ cb(kWPANTUNDStatus_FeatureNotImplemented);
+}
+
+void
+DummyNCPControlInterface::leave(CallbackWithStatus cb)
+{
+ // TODO: Writeme!
+ cb(kWPANTUNDStatus_FeatureNotImplemented);
+}
+
+void
+DummyNCPControlInterface::attach(CallbackWithStatus cb)
+{
+ // TODO: Writeme!
+ cb(kWPANTUNDStatus_FeatureNotImplemented);
+}
+
+void
+DummyNCPControlInterface::reset(CallbackWithStatus cb)
+{
+ // TODO: Writeme!
+ cb(kWPANTUNDStatus_FeatureNotImplemented);
+}
+
+void
+DummyNCPControlInterface::begin_net_wake(uint8_t data, uint32_t flags, CallbackWithStatus cb)
+{
+ // TODO: Writeme!
+ cb(kWPANTUNDStatus_FeatureNotImplemented);
+}
+
+void
+DummyNCPControlInterface::host_did_wake(CallbackWithStatus cb)
+{
+ // TODO: Writeme!
+ cb(kWPANTUNDStatus_FeatureNotImplemented);
+}
+
+void
+DummyNCPControlInterface::begin_low_power(CallbackWithStatus cb)
+{
+ // TODO: Writeme!
+ cb(kWPANTUNDStatus_FeatureNotImplemented);
+}
+
+void
+DummyNCPControlInterface::refresh_state(CallbackWithStatus cb)
+{
+ // TODO: Writeme!
+ cb(kWPANTUNDStatus_FeatureNotImplemented);
+}
+
+void
+DummyNCPControlInterface::data_poll(CallbackWithStatus cb)
+{
+ cb(kWPANTUNDStatus_FeatureNotImplemented); // TODO: Send data poll command
+}
+
+void
+DummyNCPControlInterface::add_on_mesh_prefix(
+ const struct in6_addr *prefix,
+ bool defaultRoute,
+ CallbackWithStatus cb
+) {
+ cb(kWPANTUNDStatus_FeatureNotImplemented);
+}
+
+void
+DummyNCPControlInterface::remove_on_mesh_prefix(
+ const struct in6_addr *prefix,
+ CallbackWithStatus cb
+) {
+ cb(kWPANTUNDStatus_FeatureNotImplemented);
+}
+
+void
+DummyNCPControlInterface::add_external_route(
+ const struct in6_addr *prefix,
+ int prefix_len_in_bits,
+ int domain_id,
+ ExternalRoutePriority priority,
+ CallbackWithStatus cb
+) {
+ cb(kWPANTUNDStatus_FeatureNotImplemented);
+}
+
+void
+DummyNCPControlInterface::remove_external_route(
+ const struct in6_addr *prefix,
+ int prefix_len_in_bits,
+ int domain_id,
+ CallbackWithStatus cb
+) {
+ cb(kWPANTUNDStatus_FeatureNotImplemented);
+}
+
+void
+DummyNCPControlInterface::permit_join(
+ int seconds,
+ uint8_t traffic_type,
+ in_port_t traffic_port,
+ bool network_wide,
+ CallbackWithStatus cb
+ )
+{
+ // TODO: Writeme!
+ cb(kWPANTUNDStatus_FeatureNotImplemented);
+}
+
+void
+DummyNCPControlInterface::netscan_start(
+ const ValueMap& options,
+ CallbackWithStatus cb
+) {
+ cb(kWPANTUNDStatus_FeatureNotImplemented); // TODO: Start network scan
+}
+
+void
+DummyNCPControlInterface::mfg(
+ const std::string& mfg_command,
+ CallbackWithStatusArg1 cb
+) {
+ cb(kWPANTUNDStatus_FeatureNotImplemented, 0); // TODO: Start mfg run
+}
+
+void
+DummyNCPControlInterface::netscan_stop(CallbackWithStatus cb)
+{
+ cb(kWPANTUNDStatus_FeatureNotImplemented); // TODO: Start network scan
+}
+
+void
+DummyNCPControlInterface::energyscan_start(
+ const ValueMap& options,
+ CallbackWithStatus cb
+) {
+ cb(kWPANTUNDStatus_FeatureNotImplemented);
+}
+
+void
+DummyNCPControlInterface::energyscan_stop(CallbackWithStatus cb)
+{
+ cb(kWPANTUNDStatus_FeatureNotImplemented);
+}
+
+std::string
+DummyNCPControlInterface::get_name() {
+ return mNCPInstance->get_name();
+}
+
+const WPAN::NetworkInstance&
+DummyNCPControlInterface::get_current_network_instance()const
+{
+ return mNCPInstance->get_current_network_instance();
+}
+
+
+NCPInstance&
+DummyNCPControlInterface::get_ncp_instance()
+{
+ return (*mNCPInstance);
+}
+
+void
+DummyNCPControlInterface::pcap_to_fd(int fd, CallbackWithStatus cb)
+{
+ cb(kWPANTUNDStatus_FeatureNotImplemented);
+}
+
+void
+DummyNCPControlInterface::pcap_terminate(CallbackWithStatus cb)
+{
+ cb(kWPANTUNDStatus_FeatureNotImplemented);
+}
+
+
+// ----------------------------------------------------------------------------
+// MARK: -
+
+void
+DummyNCPControlInterface::get_property(
+ const std::string& in_key, CallbackWithStatusArg1 cb
+ )
+{
+ if (!mNCPInstance->is_initializing_ncp()) {
+ syslog(LOG_INFO, "get_property: key: \"%s\"", in_key.c_str());
+ }
+ mNCPInstance->get_property(in_key, cb);
+}
+
+void
+DummyNCPControlInterface::set_property(
+ const std::string& key,
+ const boost::any& value,
+ CallbackWithStatus cb
+ )
+{
+ syslog(LOG_INFO, "set_property: key: \"%s\"", key.c_str());
+ mNCPInstance->set_property(key, value, cb);
+
+}
diff --git a/src/ncp-dummy/DummyNCPControlInterface.h b/src/ncp-dummy/DummyNCPControlInterface.h
new file mode 100644
index 0000000..5bac656
--- /dev/null
+++ b/src/ncp-dummy/DummyNCPControlInterface.h
@@ -0,0 +1,134 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __WPAN_DUMMY_NCP_H__
+#define __WPAN_DUMMY_NCP_H__ 1
+
+#include "NCPInstance.h"
+#include "NCPControlInterface.h"
+#include "nlpt.h"
+#include "Callbacks.h"
+#include "EventHandler.h"
+
+#include <queue>
+#include <set>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+
+namespace nl {
+namespace wpantund {
+
+class DummyNCPInstance;
+
+class DummyNCPControlInterface : public NCPControlInterface {
+public:
+ friend class DummyNCPInstance;
+
+ DummyNCPControlInterface(DummyNCPInstance* instance_pointer);
+ virtual ~DummyNCPControlInterface() { }
+
+ virtual const WPAN::NetworkInstance& get_current_network_instance(void)const;
+
+ virtual void join(
+ const ValueMap& options,
+ CallbackWithStatus cb = NilReturn()
+ );
+
+ virtual void form(
+ const ValueMap& options,
+ CallbackWithStatus cb = NilReturn()
+ );
+
+ virtual void leave(CallbackWithStatus cb = NilReturn());
+ virtual void attach(CallbackWithStatus cb = NilReturn());
+ virtual void begin_low_power(CallbackWithStatus cb = NilReturn());
+
+ virtual void netscan_start(const ValueMap& options, CallbackWithStatus cb = NilReturn());
+ virtual void netscan_stop(CallbackWithStatus cb = NilReturn());
+
+ virtual void energyscan_start(const ValueMap& options, CallbackWithStatus cb = NilReturn());
+ virtual void energyscan_stop(CallbackWithStatus cb = NilReturn());
+
+ virtual void mfg(const std::string& mfg_command, CallbackWithStatusArg1 cb = NilReturn());
+
+ virtual void begin_net_wake(uint8_t data, uint32_t flags, CallbackWithStatus cb = NilReturn());
+ virtual void reset(CallbackWithStatus cb = NilReturn());
+ virtual void permit_join(
+ int seconds = 15 * 60,
+ uint8_t commissioning_traffic_type = 0xFF,
+ in_port_t commissioning_traffic_port = 0,
+ bool network_wide = false,
+ CallbackWithStatus cb = NilReturn());
+
+ virtual void refresh_state(CallbackWithStatus cb = NilReturn());
+
+ virtual void get_property(
+ const std::string& key, CallbackWithStatusArg1 cb);
+ virtual void set_property(
+ const std::string& key,
+ const boost::any& value,
+ CallbackWithStatus cb);
+ virtual void add_on_mesh_prefix(
+ const struct in6_addr *prefix,
+ bool defaultRoute,
+ CallbackWithStatus cb = NilReturn()
+ );
+
+ virtual void remove_on_mesh_prefix(
+ const struct in6_addr *prefix,
+ CallbackWithStatus cb = NilReturn()
+ );
+
+ virtual void add_external_route(
+ const struct in6_addr *prefix,
+ int prefix_len_in_bits,
+ int domain_id,
+ ExternalRoutePriority priority,
+ CallbackWithStatus cb = NilReturn()
+ );
+
+ virtual void remove_external_route(
+ const struct in6_addr *prefix,
+ int prefix_len_in_bits,
+ int domain_id,
+ CallbackWithStatus cb = NilReturn()
+ );
+
+ virtual void data_poll(CallbackWithStatus cb = NilReturn());
+ virtual void host_did_wake(CallbackWithStatus cb = NilReturn());
+
+ virtual std::string get_name();
+
+ virtual NCPInstance& get_ncp_instance(void);
+
+ virtual void pcap_to_fd(int fd, CallbackWithStatus cb = NilReturn());
+
+ virtual void pcap_terminate(CallbackWithStatus cb = NilReturn());
+
+private:
+
+ DummyNCPInstance* mNCPInstance;
+
+};
+
+}; // namespace wpantund
+}; // namespace nl
+
+
+#endif
diff --git a/src/ncp-dummy/DummyNCPInstance.cpp b/src/ncp-dummy/DummyNCPInstance.cpp
new file mode 100644
index 0000000..659057d
--- /dev/null
+++ b/src/ncp-dummy/DummyNCPInstance.cpp
@@ -0,0 +1,92 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "DummyNCPInstance.h"
+#include "time-utils.h"
+#include "assert-macros.h"
+#include <syslog.h>
+#include <errno.h>
+#include "socket-utils.h"
+#include <stdexcept>
+#include <sys/file.h>
+#include "SuperSocket.h"
+
+using namespace nl;
+using namespace wpantund;
+
+WPANTUND_DEFINE_NCPINSTANCE_PLUGIN(dummy, DummyNCPInstance);
+
+DummyNCPInstance::DummyNCPInstance(const Settings& settings) :
+ NCPInstanceBase(settings), mControlInterface(this)
+{
+}
+
+DummyNCPInstance::~DummyNCPInstance()
+{
+}
+
+int
+DummyNCPInstance::vprocess_event(int event, va_list args)
+{
+ EH_BEGIN();
+
+ EH_SLEEP_FOR(1);
+
+ change_ncp_state(OFFLINE);
+ signal_property_changed(kWPANTUNDProperty_NCPState, ncp_state_to_string(get_ncp_state()));
+
+ // Wait forever, this is the dummy plugin.
+ EH_WAIT_UNTIL(false);
+
+ EH_END();
+}
+
+char
+DummyNCPInstance::ncp_to_driver_pump()
+{
+ struct nlpt*const pt = &mNCPToDriverPumpPT;
+
+ NLPT_BEGIN(pt);
+ NLPT_END(pt);
+}
+
+char
+DummyNCPInstance::driver_to_ncp_pump()
+{
+ struct nlpt*const pt = &mNCPToDriverPumpPT;
+
+ NLPT_BEGIN(pt);
+ NLPT_END(pt);
+}
+
+bool
+DummyNCPInstance::setup_property_supported_by_class(const std::string& prop_name)
+{
+ return NCPInstanceBase::setup_property_supported_by_class(prop_name);
+}
+
+DummyNCPControlInterface&
+DummyNCPInstance::get_control_interface()
+{
+ return mControlInterface;
+}
diff --git a/src/ncp-dummy/DummyNCPInstance.h b/src/ncp-dummy/DummyNCPInstance.h
new file mode 100644
index 0000000..2d9d8d4
--- /dev/null
+++ b/src/ncp-dummy/DummyNCPInstance.h
@@ -0,0 +1,70 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __wpantund__DummyNCPInstance__
+#define __wpantund__DummyNCPInstance__
+
+#include "NCPInstanceBase.h"
+#include "DummyNCPControlInterface.h"
+#include "nlpt.h"
+#include "SocketWrapper.h"
+#include "SocketAsyncOp.h"
+
+#include <queue>
+#include <set>
+#include <map>
+#include <errno.h>
+
+WPANTUND_DECLARE_NCPINSTANCE_PLUGIN(dummy, DummyNCPInstance);
+
+namespace nl {
+namespace wpantund {
+
+class DummyNCPControlInterface;
+
+class DummyNCPInstance : public NCPInstanceBase {
+ friend class DummyNCPControlInterface;
+
+public:
+ DummyNCPInstance(const Settings& settings = Settings());
+
+ virtual ~DummyNCPInstance();
+
+ virtual DummyNCPControlInterface& get_control_interface();
+
+ virtual int vprocess_event(int event, va_list args);
+
+protected:
+ virtual char ncp_to_driver_pump();
+ virtual char driver_to_ncp_pump();
+
+
+public:
+ static bool setup_property_supported_by_class(const std::string& prop_name);
+
+private:
+ DummyNCPControlInterface mControlInterface;
+}; // class DummyNCPInstance
+
+extern class DummyNCPInstance* gNCPInstance;
+
+}; // namespace wpantund
+}; // namespace nl
+
+#endif /* defined(__wpantund__DummyNCPInstance__) */
diff --git a/src/ncp-dummy/Makefile.am b/src/ncp-dummy/Makefile.am
new file mode 100644
index 0000000..8fbb626
--- /dev/null
+++ b/src/ncp-dummy/Makefile.am
@@ -0,0 +1,59 @@
+#
+# Copyright (c) 2016 Nest Labs, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/src/util \
+ -I$(top_srcdir)/src/ncp-dummy \
+ -I$(top_srcdir)/src/wpantund \
+ -I$(top_srcdir)/third_party/pt \
+ -I$(top_srcdir)/third_party/assert-macros \
+ $(NULL)
+
+DISTCLEANFILES = \
+ .deps \
+ Makefile \
+ $(NULL)
+
+if BUILD_PLUGIN_NCP_DUMMY
+
+# Work-around the omnipotent automake nanny-state.
+mypkglibexecdir = $(pkglibexecdir)
+
+NCP_SOURCES = \
+ DummyNCPControlInterface.cpp \
+ DummyNCPControlInterface.h \
+ DummyNCPInstance.cpp \
+ DummyNCPInstance.h \
+ $(NULL)
+
+if STATIC_LINK_NCP_PLUGIN
+noinst_LTLIBRARIES = libncp-dummy.la
+libncp_dummy_la_SOURCES = $(NCP_SOURCES)
+libncp_dummy_la_CXXFLAGS = @BOOST_CXXFLAGS@
+else
+mypkglibexec_LTLIBRARIES = ncp-dummy.la
+ncp_dummy_la_LDFLAGS = \
+ -module \
+ -avoid-version \
+ -shared \
+ $(NULL)
+ncp_dummy_la_SOURCES = $(NCP_SOURCES)
+ncp_dummy_la_CXXFLAGS = @BOOST_CXXFLAGS@
+endif
+
+endif #BUILD_PLUGIN_NCP_dummy
diff --git a/src/ncp-spinel/Makefile.am b/src/ncp-spinel/Makefile.am
new file mode 100644
index 0000000..e66e9a4
--- /dev/null
+++ b/src/ncp-spinel/Makefile.am
@@ -0,0 +1,100 @@
+#
+# Copyright (c) 2016 Nest Labs, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/src/util \
+ -I$(top_srcdir)/src/ncp-spinel \
+ -I$(top_srcdir)/src/wpantund \
+ -I$(top_srcdir)/third_party/pt \
+ -I$(top_srcdir)/third_party/assert-macros \
+ -I$(top_srcdir)/third_party/openthread/src/ncp \
+ $(NULL)
+
+DISTCLEANFILES = \
+ .deps \
+ Makefile \
+ $(NULL)
+
+EXTRA_DIST = \
+ ../../third_party/openthread/CONTRIBUTING.md \
+ ../../third_party/openthread/LICENSE \
+ ../../third_party/openthread/NOTICE \
+ ../../third_party/openthread/README.google \
+ ../../third_party/openthread/README.md \
+ ../../third_party/openthread/src/ncp/PROTOCOL.md \
+ ../../third_party/openthread/src/ncp/spinel.c \
+ ../../third_party/openthread/src/ncp/spinel.h \
+ ../../third_party/openthread/tools/spi-hdlc-adapter/README.md \
+ ../../third_party/openthread/tools/spi-hdlc-adapter/spi-hdlc-adapter.c \
+ $(NULL)
+
+if BUILD_PLUGIN_NCP_SPINEL
+
+if HOST_IS_LINUX
+bin_PROGRAMS = spi-hdlc-adapter
+spi_hdlc_adapter_SOURCES = ../../third_party/openthread/tools/spi-hdlc-adapter/spi-hdlc-adapter.c
+endif
+
+# Work around the omnipotent automake nanny-state.
+mypkglibexecdir = $(pkglibexecdir)
+
+NCP_SOURCES = \
+ SpinelNCPControlInterface.cpp \
+ SpinelNCPControlInterface.h \
+ SpinelNCPInstance.cpp \
+ SpinelNCPInstance.h \
+ SpinelNCPInstance-DataPump.cpp \
+ SpinelNCPInstance-Protothreads.cpp \
+ SpinelNCPTask.cpp \
+ SpinelNCPTask.h \
+ SpinelNCPTaskDeepSleep.cpp \
+ SpinelNCPTaskGetNetworkTopology.h \
+ SpinelNCPTaskGetNetworkTopology.cpp \
+ SpinelNCPTaskGetMsgBufferCounters.h \
+ SpinelNCPTaskGetMsgBufferCounters.cpp \
+ SpinelNCPTaskDeepSleep.h \
+ SpinelNCPTaskForm.cpp \
+ SpinelNCPTaskForm.h \
+ SpinelNCPTaskJoin.cpp \
+ SpinelNCPTaskJoin.h \
+ SpinelNCPTaskLeave.cpp \
+ SpinelNCPTaskLeave.h \
+ SpinelNCPTaskScan.cpp \
+ SpinelNCPTaskScan.h \
+ SpinelNCPTaskSendCommand.cpp \
+ SpinelNCPTaskSendCommand.h \
+ SpinelNCPTaskWake.cpp \
+ SpinelNCPTaskWake.h \
+ $(top_srcdir)/third_party/openthread/src/ncp/spinel.c \
+ spinel-extra.c \
+ spinel-extra.h \
+ $(NULL)
+
+
+if STATIC_LINK_NCP_PLUGIN
+noinst_LTLIBRARIES = libncp-spinel.la
+libncp_spinel_la_SOURCES = $(NCP_SOURCES)
+libncp_spinel_la_CXXFLAGS = @BOOST_CXXFLAGS@
+else
+mypkglibexec_LTLIBRARIES = ncp-spinel.la
+ncp_spinel_la_LDFLAGS = -module -avoid-version -shared
+ncp_spinel_la_SOURCES = $(NCP_SOURCES)
+ncp_spinel_la_CXXFLAGS = @BOOST_CXXFLAGS@
+endif
+
+endif #BUILD_PLUGIN_NCP_SPINEL
diff --git a/src/ncp-spinel/SpinelNCPControlInterface.cpp b/src/ncp-spinel/SpinelNCPControlInterface.cpp
new file mode 100644
index 0000000..c8a5df3
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPControlInterface.cpp
@@ -0,0 +1,535 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "assert-macros.h"
+
+#include "SpinelNCPControlInterface.h"
+#include "SpinelNCPInstance.h"
+
+#include "wpantund.h"
+#include "config-file.h"
+#include "nlpt.h"
+#include "string-utils.h"
+#include "any-to.h"
+#include "time-utils.h"
+
+#include <cstring>
+#include <algorithm>
+#include <errno.h>
+#include <arpa/inet.h>
+#include <syslog.h>
+#include <sys/time.h>
+
+#include <boost/bind.hpp>
+
+#include "spinel-extra.h"
+
+#include "SpinelNCPTask.h"
+#include "SpinelNCPTaskWake.h"
+#include "SpinelNCPTaskJoin.h"
+#include "SpinelNCPTaskForm.h"
+#include "SpinelNCPTaskLeave.h"
+#include "SpinelNCPTaskScan.h"
+#include "SpinelNCPTaskSendCommand.h"
+
+using namespace nl;
+using namespace nl::wpantund;
+
+// ----------------------------------------------------------------------------
+// MARK: -
+
+SpinelNCPControlInterface::SpinelNCPControlInterface(SpinelNCPInstance* instance_pointer)
+ :mNCPInstance(instance_pointer)
+{
+}
+
+// ----------------------------------------------------------------------------
+// MARK: -
+
+void
+SpinelNCPControlInterface::join(
+ const ValueMap& options,
+ CallbackWithStatus cb
+) {
+ mNCPInstance->start_new_task(boost::shared_ptr<SpinelNCPTask>(
+ new SpinelNCPTaskJoin(
+ mNCPInstance,
+ boost::bind(cb,_1),
+ options
+ )
+ ));
+}
+
+void
+SpinelNCPControlInterface::form(
+ const ValueMap& options,
+ CallbackWithStatus cb
+) {
+ mNCPInstance->start_new_task(boost::shared_ptr<SpinelNCPTask>(
+ new SpinelNCPTaskForm(
+ mNCPInstance,
+ boost::bind(cb,_1),
+ options
+ )
+ ));
+}
+
+void
+SpinelNCPControlInterface::leave(CallbackWithStatus cb)
+{
+ mNCPInstance->start_new_task(boost::shared_ptr<SpinelNCPTask>(
+ new SpinelNCPTaskLeave(
+ mNCPInstance,
+ boost::bind(cb,_1)
+ )
+ ));
+}
+
+void
+SpinelNCPControlInterface::attach(CallbackWithStatus cb)
+{
+ mNCPInstance->start_new_task(
+ SpinelNCPTaskSendCommand::Factory(mNCPInstance)
+ .set_callback(cb)
+ .add_command(SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_BOOL_S),
+ SPINEL_PROP_NET_IF_UP,
+ true
+ ))
+ .add_command(SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_BOOL_S),
+ SPINEL_PROP_NET_STACK_UP,
+ true
+ ))
+ .finish()
+ );
+}
+
+void
+SpinelNCPControlInterface::reset(CallbackWithStatus cb)
+{
+ if (mNCPInstance->get_ncp_state() == FAULT) {
+ mNCPInstance->change_ncp_state(UNINITIALIZED);
+ }
+
+ mNCPInstance->start_new_task(SpinelNCPTaskSendCommand::Factory(mNCPInstance)
+ .set_callback(CallbackWithStatus(boost::bind(cb,kWPANTUNDStatus_Ok)))
+ .add_command(SpinelPackData(SPINEL_FRAME_PACK_CMD_RESET))
+ .finish()
+ );
+}
+
+void
+SpinelNCPControlInterface::begin_net_wake(uint8_t data, uint32_t flags, CallbackWithStatus cb)
+{
+ // TODO: Writeme!
+ cb(kWPANTUNDStatus_FeatureNotImplemented);
+}
+
+void
+SpinelNCPControlInterface::host_did_wake(CallbackWithStatus cb)
+{
+ // TODO: Writeme!
+ cb(kWPANTUNDStatus_FeatureNotImplemented);
+}
+
+void
+SpinelNCPControlInterface::begin_low_power(CallbackWithStatus cb)
+{
+ // TODO: Writeme!
+ cb(kWPANTUNDStatus_FeatureNotImplemented);
+}
+
+void
+SpinelNCPControlInterface::refresh_state(CallbackWithStatus cb)
+{
+ mNCPInstance->start_new_task(SpinelNCPTaskSendCommand::Factory(mNCPInstance)
+ .set_callback(cb)
+ .add_command(SpinelPackData(SPINEL_FRAME_PACK_CMD_NOOP))
+ .finish()
+ );
+}
+
+void
+SpinelNCPControlInterface::data_poll(CallbackWithStatus cb)
+{
+ mNCPInstance->start_new_task(SpinelNCPTaskSendCommand::Factory(mNCPInstance)
+ .set_callback(cb)
+ .add_command(SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_GET, SPINEL_PROP_STREAM_NET))
+ .finish()
+ );
+}
+
+void
+SpinelNCPControlInterface::add_on_mesh_prefix(
+ const struct in6_addr *prefix,
+ bool defaultRoute,
+ CallbackWithStatus cb
+) {
+ uint8_t flags = 0;
+ SpinelNCPTaskSendCommand::Factory factory(mNCPInstance);
+
+ require_action(prefix != NULL, bail, cb(kWPANTUNDStatus_InvalidArgument));
+ require_action(mNCPInstance->mEnabled, bail, cb(kWPANTUNDStatus_InvalidWhenDisabled));
+
+ if (defaultRoute) {
+ flags |= SPINEL_NET_FLAG_DEFAULT_ROUTE;
+ }
+
+ flags |= SPINEL_NET_FLAG_PREFERRED | SPINEL_NET_FLAG_SLAAC | SPINEL_NET_FLAG_ON_MESH;
+
+ factory.set_callback(cb);
+ factory.set_lock_property(SPINEL_PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE);
+
+ factory.add_command(SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_INSERT(
+ SPINEL_DATATYPE_IPv6ADDR_S
+ SPINEL_DATATYPE_UINT8_S
+ SPINEL_DATATYPE_BOOL_S
+ SPINEL_DATATYPE_UINT8_S
+ ),
+ SPINEL_PROP_THREAD_ON_MESH_NETS,
+ prefix,
+ IPV6_NETWORK_PREFIX_LENGTH,
+ true,
+ flags
+ ));
+
+ mNCPInstance->start_new_task(factory.finish());
+
+bail:
+ return;
+}
+
+void
+SpinelNCPControlInterface::remove_on_mesh_prefix(
+ const struct in6_addr *prefix,
+ CallbackWithStatus cb
+) {
+ uint8_t flags = 0;
+ SpinelNCPTaskSendCommand::Factory factory(mNCPInstance);
+
+ require_action(prefix != NULL, bail, cb(kWPANTUNDStatus_InvalidArgument));
+ require_action(mNCPInstance->mEnabled, bail, cb(kWPANTUNDStatus_InvalidWhenDisabled));
+
+ factory.set_callback(cb);
+ factory.set_lock_property(SPINEL_PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE);
+
+ factory.add_command(SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_REMOVE(
+ SPINEL_DATATYPE_IPv6ADDR_S
+ SPINEL_DATATYPE_UINT8_S
+ SPINEL_DATATYPE_BOOL_S
+ SPINEL_DATATYPE_UINT8_S
+ ),
+ SPINEL_PROP_THREAD_ON_MESH_NETS,
+ prefix,
+ IPV6_NETWORK_PREFIX_LENGTH,
+ true,
+ flags
+ ));
+
+ mNCPInstance->start_new_task(factory.finish());
+
+bail:
+ return;
+}
+
+void
+SpinelNCPControlInterface::add_external_route(
+ const struct in6_addr *prefix,
+ int prefix_len_in_bits,
+ int domain_id,
+ ExternalRoutePriority priority,
+ CallbackWithStatus cb
+) {
+ const static int kPreferenceOffset = 6;
+ uint8_t flags = 0;
+
+ require_action(prefix != NULL, bail, cb(kWPANTUNDStatus_InvalidArgument));
+ require_action(prefix_len_in_bits >= 0, bail, cb(kWPANTUNDStatus_InvalidArgument));
+ require_action(prefix_len_in_bits <= IPV6_MAX_PREFIX_LENGTH, bail, cb(kWPANTUNDStatus_InvalidArgument));
+ require_action(mNCPInstance->mEnabled, bail, cb(kWPANTUNDStatus_InvalidWhenDisabled));
+
+ switch (priority) {
+ case ROUTE_HIGH_PREFERENCE:
+ flags = (1 << kPreferenceOffset);
+ break;
+
+ case ROUTE_MEDIUM_PREFERENCE:
+ flags = 0;
+ break;
+
+ case ROUTE_LOW_PREFRENCE:
+ flags = (3 << kPreferenceOffset);
+ break;
+ }
+
+ mNCPInstance->start_new_task(SpinelNCPTaskSendCommand::Factory(mNCPInstance)
+ .set_callback(cb)
+ .add_command(SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_INSERT(
+ SPINEL_DATATYPE_IPv6ADDR_S
+ SPINEL_DATATYPE_UINT8_S
+ SPINEL_DATATYPE_BOOL_S
+ SPINEL_DATATYPE_UINT8_S
+ ),
+ SPINEL_PROP_THREAD_LOCAL_ROUTES,
+ prefix,
+ prefix_len_in_bits,
+ true,
+ flags
+ ))
+ .set_lock_property(SPINEL_PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE)
+ .finish()
+ );
+
+bail:
+ return;
+}
+
+void
+SpinelNCPControlInterface::remove_external_route(
+ const struct in6_addr *prefix,
+ int prefix_len_in_bits,
+ int domain_id,
+ CallbackWithStatus cb
+) {
+ require_action(prefix != NULL, bail, cb(kWPANTUNDStatus_InvalidArgument));
+ require_action(prefix_len_in_bits >= 0, bail, cb(kWPANTUNDStatus_InvalidArgument));
+ require_action(prefix_len_in_bits <= IPV6_MAX_PREFIX_LENGTH, bail, cb(kWPANTUNDStatus_InvalidArgument));
+ require_action(mNCPInstance->mEnabled, bail, cb(kWPANTUNDStatus_InvalidWhenDisabled));
+
+ mNCPInstance->start_new_task(SpinelNCPTaskSendCommand::Factory(mNCPInstance)
+ .set_callback(cb)
+ .add_command(SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_REMOVE(
+ SPINEL_DATATYPE_IPv6ADDR_S
+ SPINEL_DATATYPE_UINT8_S
+ SPINEL_DATATYPE_BOOL_S
+ SPINEL_DATATYPE_UINT8_S
+ ),
+ SPINEL_PROP_THREAD_LOCAL_ROUTES,
+ prefix,
+ prefix_len_in_bits,
+ true,
+ 0
+ ))
+ .set_lock_property(SPINEL_PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE)
+ .finish()
+ );
+
+bail:
+ return;
+}
+
+void
+SpinelNCPControlInterface::permit_join(
+ int seconds,
+ uint8_t traffic_type,
+ in_port_t traffic_port,
+ bool network_wide,
+ CallbackWithStatus cb
+ )
+{
+ SpinelNCPTaskSendCommand::Factory factory(mNCPInstance);
+ int ret = kWPANTUNDStatus_Ok;
+
+ if (!mNCPInstance->mEnabled) {
+ ret = kWPANTUNDStatus_InvalidWhenDisabled;
+ goto bail;
+ }
+
+ if (traffic_port == 0) {
+ // If no port was explicitly set, default to the discovered
+ // "Commissioner Port" (“:MC”).
+ traffic_port = htons(mNCPInstance->mCommissionerPort);
+ }
+
+ ret = mNCPInstance->set_commissioniner(seconds, traffic_type, traffic_port);
+
+ require_noerr(ret, bail);
+
+ factory.set_callback(cb);
+
+ if (seconds > 0) {
+ factory.add_command(SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT16_S),
+ SPINEL_PROP_THREAD_ASSISTING_PORTS,
+ ntohs(traffic_port)
+ ));
+ } else {
+ factory.add_command(SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_NULL_S),
+ SPINEL_PROP_THREAD_ASSISTING_PORTS
+ ));
+ }
+
+ mNCPInstance->start_new_task(factory.finish());
+
+bail:
+ if (ret) {
+ cb(ret);
+ } else {
+ syslog(LOG_NOTICE, "PermitJoin: seconds=%d type=%d port=%d", seconds, traffic_type, ntohs(traffic_port));
+ }
+}
+
+void
+SpinelNCPControlInterface::netscan_start(
+ const ValueMap& options,
+ CallbackWithStatus cb
+) {
+ ChannelMask channel_mask(mNCPInstance->get_default_channel_mask());
+
+ if (options.count(kWPANTUNDProperty_NCPChannelMask)) {
+ channel_mask = any_to_int(options.at(kWPANTUNDProperty_NCPChannelMask));
+ }
+
+ mNCPInstance->start_new_task(boost::shared_ptr<SpinelNCPTask>(
+ new SpinelNCPTaskScan(
+ mNCPInstance,
+ boost::bind(cb,_1),
+ channel_mask
+ )
+ ));
+}
+
+void
+SpinelNCPControlInterface::netscan_stop(CallbackWithStatus cb)
+{
+ cb(kWPANTUNDStatus_FeatureNotImplemented); // TODO: Start network scan
+}
+
+void
+SpinelNCPControlInterface::energyscan_start(
+ const ValueMap& options,
+ CallbackWithStatus cb
+) {
+ ChannelMask channel_mask(mNCPInstance->get_default_channel_mask());
+
+ if (options.count(kWPANTUNDProperty_NCPChannelMask)) {
+ channel_mask = any_to_int(options.at(kWPANTUNDProperty_NCPChannelMask));
+ }
+
+ mNCPInstance->start_new_task(boost::shared_ptr<SpinelNCPTask>(
+ new SpinelNCPTaskScan(
+ mNCPInstance,
+ boost::bind(cb,_1),
+ channel_mask,
+ SpinelNCPTaskScan::kDefaultScanPeriod,
+ SpinelNCPTaskScan::kScanTypeEnergy
+ )
+ ));
+}
+
+void
+SpinelNCPControlInterface::energyscan_stop(CallbackWithStatus cb)
+{
+ cb(kWPANTUNDStatus_FeatureNotImplemented);
+}
+
+std::string
+SpinelNCPControlInterface::get_name() {
+ return mNCPInstance->get_name();
+}
+
+void
+SpinelNCPControlInterface::mfg(
+ const std::string& mfg_command,
+ CallbackWithStatusArg1 cb
+) {
+ mNCPInstance->start_new_task(
+ SpinelNCPTaskSendCommand::Factory(mNCPInstance)
+ .set_callback(cb)
+ .add_command(SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UTF8_S),
+ SPINEL_PROP_NEST_STREAM_MFG,
+ mfg_command.c_str()
+ ))
+ .set_reply_format(SPINEL_DATATYPE_UTF8_S)
+ .finish()
+ );
+}
+
+const WPAN::NetworkInstance&
+SpinelNCPControlInterface::get_current_network_instance()const
+{
+ return mNCPInstance->get_current_network_instance();
+}
+
+
+NCPInstance&
+SpinelNCPControlInterface::get_ncp_instance()
+{
+ return (*mNCPInstance);
+}
+
+void
+SpinelNCPControlInterface::pcap_to_fd(int fd, CallbackWithStatus cb)
+{
+ int ret = mNCPInstance->mPcapManager.insert_fd(fd);
+
+ if (ret < 0) {
+ syslog(LOG_ERR, "pcap_to_fd: Failed: \"%s\" (%d)", strerror(errno), errno);
+
+ cb(kWPANTUNDStatus_Failure);
+
+ } else {
+ cb(kWPANTUNDStatus_Ok);
+ }
+}
+
+void
+SpinelNCPControlInterface::pcap_terminate(CallbackWithStatus cb)
+{
+ mNCPInstance->mPcapManager.close_fd_set(mNCPInstance->mPcapManager.get_fd_set());
+ cb(kWPANTUNDStatus_Ok);
+}
+
+
+
+// ----------------------------------------------------------------------------
+// MARK: -
+
+void
+SpinelNCPControlInterface::get_property(
+ const std::string& in_key, CallbackWithStatusArg1 cb
+ )
+{
+ if (!mNCPInstance->is_initializing_ncp()) {
+ syslog(LOG_INFO, "get_property: key: \"%s\"", in_key.c_str());
+ }
+ mNCPInstance->get_property(in_key, cb);
+}
+
+void
+SpinelNCPControlInterface::set_property(
+ const std::string& key,
+ const boost::any& value,
+ CallbackWithStatus cb
+ )
+{
+ syslog(LOG_INFO, "set_property: key: \"%s\"", key.c_str());
+ mNCPInstance->set_property(key, value, cb);
+}
diff --git a/src/ncp-spinel/SpinelNCPControlInterface.h b/src/ncp-spinel/SpinelNCPControlInterface.h
new file mode 100644
index 0000000..b91335a
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPControlInterface.h
@@ -0,0 +1,136 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __WPAN_DUMMY_NCP_H__
+#define __WPAN_DUMMY_NCP_H__ 1
+
+#include "NCPInstance.h"
+#include "NCPControlInterface.h"
+#include "NCPMfgInterface_v1.h"
+#include "nlpt.h"
+#include "Callbacks.h"
+#include "EventHandler.h"
+
+#include <queue>
+#include <set>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+
+namespace nl {
+namespace wpantund {
+
+class SpinelNCPInstance;
+
+class SpinelNCPControlInterface : public NCPControlInterface, public NCPMfgInterface_v1 {
+public:
+ friend class SpinelNCPInstance;
+
+ SpinelNCPControlInterface(SpinelNCPInstance* instance_pointer);
+ virtual ~SpinelNCPControlInterface() { }
+
+ virtual const WPAN::NetworkInstance& get_current_network_instance(void)const;
+
+ virtual void join(
+ const ValueMap& options,
+ CallbackWithStatus cb = NilReturn()
+ );
+
+ virtual void form(
+ const ValueMap& options,
+ CallbackWithStatus cb = NilReturn()
+ );
+
+ virtual void leave(CallbackWithStatus cb = NilReturn());
+ virtual void attach(CallbackWithStatus cb = NilReturn());
+ virtual void begin_low_power(CallbackWithStatus cb = NilReturn());
+
+ virtual void netscan_start(const ValueMap& options, CallbackWithStatus cb = NilReturn());
+ virtual void netscan_stop(CallbackWithStatus cb = NilReturn());
+
+ virtual void energyscan_start(const ValueMap& options, CallbackWithStatus cb = NilReturn());
+ virtual void energyscan_stop(CallbackWithStatus cb = NilReturn());
+
+ virtual void begin_net_wake(uint8_t data, uint32_t flags, CallbackWithStatus cb = NilReturn());
+ virtual void reset(CallbackWithStatus cb = NilReturn());
+ virtual void permit_join(
+ int seconds = 15 * 60,
+ uint8_t commissioning_traffic_type = 0xFF,
+ in_port_t commissioning_traffic_port = 0,
+ bool network_wide = false,
+ CallbackWithStatus cb = NilReturn());
+
+ virtual void refresh_state(CallbackWithStatus cb = NilReturn());
+
+ virtual void get_property(
+ const std::string& key, CallbackWithStatusArg1 cb);
+ virtual void set_property(
+ const std::string& key,
+ const boost::any& value,
+ CallbackWithStatus cb);
+ virtual void add_on_mesh_prefix(
+ const struct in6_addr *prefix,
+ bool defaultRoute,
+ CallbackWithStatus cb = NilReturn()
+ );
+
+ virtual void remove_on_mesh_prefix(
+ const struct in6_addr *prefix,
+ CallbackWithStatus cb = NilReturn()
+ );
+
+ virtual void add_external_route(
+ const struct in6_addr *prefix,
+ int prefix_len_in_bits,
+ int domain_id,
+ ExternalRoutePriority priority,
+ CallbackWithStatus cb = NilReturn()
+ );
+
+ virtual void remove_external_route(
+ const struct in6_addr *prefix,
+ int prefix_len_in_bits,
+ int domain_id,
+ CallbackWithStatus cb = NilReturn()
+ );
+
+ virtual void data_poll(CallbackWithStatus cb = NilReturn());
+ virtual void host_did_wake(CallbackWithStatus cb = NilReturn());
+
+ virtual std::string get_name();
+
+ virtual NCPInstance& get_ncp_instance(void);
+
+ virtual void pcap_to_fd(int fd, CallbackWithStatus cb = NilReturn());
+
+ virtual void pcap_terminate(CallbackWithStatus cb = NilReturn());
+
+ /******************* NCPMfgInterface_v1 ********************/
+ virtual void mfg(const std::string& mfg_command, CallbackWithStatusArg1 cb = NilReturn());
+
+private:
+
+ SpinelNCPInstance* mNCPInstance;
+
+};
+
+}; // namespace wpantund
+}; // namespace nl
+
+
+#endif
diff --git a/src/ncp-spinel/SpinelNCPInstance-DataPump.cpp b/src/ncp-spinel/SpinelNCPInstance-DataPump.cpp
new file mode 100644
index 0000000..871dc25
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPInstance-DataPump.cpp
@@ -0,0 +1,545 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "SpinelNCPInstance.h"
+#include "time-utils.h"
+#include "assert-macros.h"
+#include <syslog.h>
+#include <errno.h>
+#include "socket-utils.h"
+#include <stdexcept>
+#include <sys/file.h>
+#include "SuperSocket.h"
+
+using namespace nl;
+using namespace wpantund;
+
+#define HDLC_BYTE_FLAG 0x7E
+#define HDLC_BYTE_ESC 0x7D
+#define HDLC_BYTE_XON 0x11
+#define HDLC_BYTE_XOFF 0x13
+#define HDLC_BYTE_SPECIAL 0xF8
+#define HDLC_ESCAPE_XFORM 0x20
+
+static bool
+hdlc_byte_needs_escape(uint8_t byte)
+{
+ switch(byte) {
+ case HDLC_BYTE_SPECIAL:
+ case HDLC_BYTE_ESC:
+ case HDLC_BYTE_FLAG:
+ case HDLC_BYTE_XOFF:
+ case HDLC_BYTE_XON:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static uint16_t
+hdlc_crc16(uint16_t aFcs, uint8_t aByte)
+{
+#if 1
+ // CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-CCITT
+ // width=16 poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189 name="KERMIT"
+ // http://reveng.sourceforge.net/crc-catalogue/16.htm#crc.cat.kermit
+ static const uint16_t sFcsTable[256] =
+ {
+ 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
+ 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
+ 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
+ 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
+ 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
+ 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
+ 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
+ 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
+ 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
+ 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
+ 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
+ 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
+ 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
+ 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
+ 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
+ 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
+ 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
+ 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
+ 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
+ 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
+ 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
+ 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
+ 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
+ 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
+ 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
+ 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
+ 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
+ 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
+ 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
+ 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
+ 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
+ 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
+ };
+ return (aFcs >> 8) ^ sFcsTable[(aFcs ^ aByte) & 0xff];
+#else
+ // CRC-16/CCITT-FALSE, same CRC as 802.15.4
+ // width=16 poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1 name="CRC-16/CCITT-FALSE"
+ // http://reveng.sourceforge.net/crc-catalogue/16.htm#crc.cat.crc-16-ccitt-false
+ aFcs = (uint16_t)((aFcs >> 8) | (aFcs << 8));
+ aFcs ^= aByte;
+ aFcs ^= ((aFcs & 0xff) >> 4);
+ aFcs ^= (aFcs << 12);
+ aFcs ^= ((aFcs & 0xff) << 5);
+ return aFcs;
+#endif
+}
+
+char
+SpinelNCPInstance::ncp_to_driver_pump()
+{
+ struct nlpt*const pt = &mNCPToDriverPumpPT;
+// unsigned int prop_key = 0;
+ unsigned int command_value = 0;
+ uint8_t byte;
+
+ // Automatically detect socket resets and behave accordingly.
+ if (mSerialAdapter->did_reset()) {
+ syslog(LOG_NOTICE, "[-NCP-]: Socket Reset");
+ NLPT_INIT(&mNCPToDriverPumpPT);
+ NLPT_INIT(&mDriverToNCPPumpPT);
+
+ process_event(EVENT_NCP_CONN_RESET);
+ }
+
+ NLPT_BEGIN(pt);
+
+ // This macro abstracts the logic to read a single character into
+ // `data`, in a protothreads-friendly way.
+#define READ_CHARACTER(pt, data, on_fail) \
+ while(1) { \
+ NLPT_WAIT_UNTIL_READABLE_OR_COND(pt, mSerialAdapter->get_read_fd(), mSerialAdapter->can_read()); \
+ ssize_t retlen = mSerialAdapter->read(data, 1); \
+ if (retlen < 0) { \
+ syslog(LOG_ERR, "[-NCP-]: Socket error on read: %s %d", \
+ strerror((int)-retlen), (int)(-retlen)); \
+ signal_fatal_error(ERRORCODE_ERRNO); \
+ goto on_fail; \
+ } else if (retlen == 0) { \
+ continue; \
+ } \
+ break ; \
+ };
+
+ while (!ncp_state_is_detached_from_ncp(get_ncp_state())) {
+ mInboundHeader = 0;
+ mInboundFrameSize = 0;
+
+ // Yield until the socket is readable. We do a
+ // yield here instead of a wait because we want to
+ // only handle one packet per run through the main loop.
+ // Using `YIELD` instead of `WAIT` guarantees that we
+ // will yield control of the protothread at least once,
+ // even if the socket is already readable.
+ NLPT_YIELD_UNTIL_READABLE_OR_COND(pt, mSerialAdapter->get_read_fd(), mSerialAdapter->can_read());
+
+#if WPANTUND_SPINEL_USE_FLEN
+ do {
+ READ_CHARACTER(pt, (void*)&mInboundFrame[0], on_error);
+
+ if (HDLC_BYTE_FLAG != mInboundFrame[0]) {
+ // The dreaded extraneous character error.
+
+ // Log the error.
+ {
+ char printable = mInboundFrame[0];
+ if(iscntrl(printable) || printable<0)
+ printable = '.';
+
+ syslog(LOG_WARNING,
+ "[NCP->] Extraneous Character: 0x%02X [%c] (%d)\n",
+ (uint8_t)mInboundFrame[0],
+ printable,
+ (uint8_t)mInboundFrame[0]);
+ }
+
+ // Flush out all remaining data since this is a strong
+ // indication that something has gone horribly wrong.
+ while (mSerialAdapter->can_read()) {
+ READ_CHARACTER(pt, (void*)&mInboundFrame[0], on_error);
+ }
+
+ ncp_is_misbehaving();
+ goto on_error;
+ }
+ } while (UART_STREAM_FLAG != mInboundFrame[0]);
+
+ // Read the frame length
+ READ_CHARACTER(pt, (void*)((char*)&mInboundFrame+0), on_error);
+ READ_CHARACTER(pt, (void*)((char*)&mInboundFrame+1), on_error);
+
+ mInboundFrameSize = (mInboundFrame[0] << 8) + mInboundFrame[1];
+
+ require(mInboundFrameSize > 1, on_error);
+ require(mInboundFrameSize <= SPINEL_FRAME_MAX_SIZE, on_error);
+
+ // Read the rest of the packet.
+ NLPT_ASYNC_READ_STREAM(
+ pt,
+ mSerialAdapter.get(),
+ mInboundFrame,
+ mInboundFrameSize
+ );
+#else
+
+ mInboundFrameSize = 0;
+ mInboundFrameHDLCCRC = 0xffff;
+
+ do {
+ READ_CHARACTER(pt, &byte, on_error);
+
+ if (byte == HDLC_BYTE_FLAG) {
+ break;
+ }
+ if (byte == HDLC_BYTE_ESC) {
+ READ_CHARACTER(pt, &byte, on_error);
+ if (byte == HDLC_BYTE_FLAG) {
+ break;
+ } else {
+ byte ^= HDLC_ESCAPE_XFORM;
+ }
+ }
+
+ if (mInboundFrameSize >= 2) {
+ mInboundFrameHDLCCRC = hdlc_crc16(mInboundFrameHDLCCRC, mInboundFrame[mInboundFrameSize-2]);
+ }
+
+ require(mInboundFrameSize < sizeof(mInboundFrame), on_error);
+
+ mInboundFrame[mInboundFrameSize++] = byte;
+
+ } while(true);
+
+ if (mInboundFrameSize <= 2) {
+ continue;
+ }
+
+ mInboundFrameSize -= 2;
+ mInboundFrameHDLCCRC ^= 0xFFFF;
+ {
+ uint16_t frame_crc = (mInboundFrame[mInboundFrameSize]|(mInboundFrame[mInboundFrameSize+1]<<8));
+ if (mInboundFrameHDLCCRC != frame_crc) {
+
+ int i;
+ static const uint8_t kAsciiCR = 13;
+ static const uint8_t kAsciiBEL = 7;
+
+ syslog(LOG_ERR, "[NCP->]: Frame CRC Mismatch: Calc:0x%04X != Frame:0x%04X, Garbage on line?", mInboundFrameHDLCCRC, frame_crc);
+
+ // This frame might be an ASCII backtrace, so we check to
+ // see if all of the characters are ascii characters, and if
+ // so we dump out this packet directly to syslog.
+
+ mInboundFrameSize += 2;
+
+ for (i = 0; i < mInboundFrameSize; i++) {
+ // Acceptable control codes
+ if (mInboundFrame[i] >= kAsciiBEL && mInboundFrame[i] <= kAsciiCR) {
+ continue;
+ }
+ // NUL characters are OK.
+ if (mInboundFrame[i] == 0) {
+ continue;
+ }
+ // Acceptable characters
+ if (mInboundFrame[i] >= 32 && mInboundFrame[i] <= 127) {
+ continue;
+ }
+
+ syslog(LOG_ERR, "[NCP->]: Garbage is not ASCII ([%d]=%d)", i, mInboundFrame[i]);
+ break;
+ }
+
+ if (i == mInboundFrameSize) {
+ handle_ncp_log(mInboundFrame, mInboundFrameSize);
+ }
+
+ continue;
+ }
+ }
+
+#endif
+
+ if (pt->last_errno) {
+ syslog(LOG_ERR, "[-NCP-]: Socket error on read: %s", strerror(pt->last_errno));
+ errno = pt->last_errno;
+ signal_fatal_error(ERRORCODE_ERRNO);
+ goto on_error;
+ }
+
+ if (spinel_datatype_unpack(mInboundFrame, mInboundFrameSize, "Ci", &mInboundHeader, &command_value) > 0) {
+ if ((mInboundHeader&SPINEL_HEADER_FLAG) != SPINEL_HEADER_FLAG) {
+ // Unrecognized frame.
+ break;
+ }
+
+ if (SPINEL_HEADER_GET_IID(mInboundHeader) != 0) {
+ // We only support IID zero for now.
+ break;
+ }
+
+ handle_ncp_spinel_callback(command_value, mInboundFrame, mInboundFrameSize);
+ }
+ } // while (!ncp_state_is_detached_from_ncp(get_ncp_state()))
+
+on_error:;
+ // If we get here, we will restart the protothread at the next iteration.
+
+ NLPT_END(pt);
+}
+
+char
+SpinelNCPInstance::driver_to_ncp_pump()
+{
+ struct nlpt*const pt = &mDriverToNCPPumpPT;
+
+ NLPT_BEGIN(pt);
+
+ while (!ncp_state_is_detached_from_ncp(get_ncp_state())) {
+ // If there is an outbound callback at this
+ // point, then we assume it is stale and
+ // immediately clear it out.
+ if (!mOutboundCallback.empty()) {
+ mOutboundCallback(kWPANTUNDStatus_Canceled);
+ mOutboundCallback.clear();
+ }
+
+ // Wait for a packet to be available from interface OR management queue.
+ if (mOutboundBufferLen > 0) {
+ // If there is something in the outbound queue,
+ // we shouldn't try any of the checks below, since it
+ // will delay processing.
+
+ } else if (static_cast<bool>(mLegacyInterface) && is_legacy_interface_enabled()) {
+ NLPT_YIELD_UNTIL_READABLE2_OR_COND(
+ pt,
+ mPrimaryInterface->get_read_fd(),
+ mLegacyInterface->get_read_fd(),
+ (mOutboundBufferLen > 0)
+ || mLegacyInterface->can_read()
+ || mPrimaryInterface->can_read()
+ );
+
+ } else {
+ NLPT_YIELD_UNTIL_READABLE_OR_COND(
+ pt,
+ mPrimaryInterface->get_read_fd(),
+ mPrimaryInterface->can_read() || (mOutboundBufferLen > 0)
+ );
+ }
+
+ // Get packet or management command, and also
+ // perform any necessary filtering.
+ if (mOutboundBufferLen > 0) {
+ if (mOutboundBuffer[1] == SPINEL_CMD_PROP_VALUE_GET) {
+ spinel_prop_key_t key;
+ spinel_datatype_unpack(mOutboundBuffer, mOutboundBufferLen, "Cii", NULL, NULL, &key);
+ syslog(LOG_INFO, "[->NCP] CMD_PROP_VALUE_GET(%s) tid:%d", spinel_prop_key_to_cstr(key), SPINEL_HEADER_GET_TID(mOutboundBuffer[0]));
+ } else if (mOutboundBuffer[1] == SPINEL_CMD_PROP_VALUE_SET) {
+ spinel_prop_key_t key;
+ spinel_datatype_unpack(mOutboundBuffer, mOutboundBufferLen, "Cii", NULL, NULL, &key);
+ syslog(LOG_INFO, "[->NCP] CMD_PROP_VALUE_SET(%s) tid:%d", spinel_prop_key_to_cstr(key), SPINEL_HEADER_GET_TID(mOutboundBuffer[0]));
+ } else if (mOutboundBuffer[1] == SPINEL_CMD_PROP_VALUE_INSERT) {
+ spinel_prop_key_t key;
+ spinel_datatype_unpack(mOutboundBuffer, mOutboundBufferLen, "Cii", NULL, NULL, &key);
+ syslog(LOG_INFO, "[->NCP] CMD_PROP_VALUE_INSERT(%s) tid:%d", spinel_prop_key_to_cstr(key), SPINEL_HEADER_GET_TID(mOutboundBuffer[0]));
+ } else if (mOutboundBuffer[1] == SPINEL_CMD_PROP_VALUE_REMOVE) {
+ spinel_prop_key_t key;
+ spinel_datatype_unpack(mOutboundBuffer, mOutboundBufferLen, "Cii", NULL, NULL, &key);
+ syslog(LOG_INFO, "[->NCP] CMD_PROP_VALUE_REMOVE(%s) tid:%d", spinel_prop_key_to_cstr(key), SPINEL_HEADER_GET_TID(mOutboundBuffer[0]));
+ } else if (mOutboundBuffer[1] == SPINEL_CMD_NOOP) {
+ syslog(LOG_INFO, "[->NCP] CMD_NOOP tid:%d", SPINEL_HEADER_GET_TID(mOutboundBuffer[0]));
+ } else if (mOutboundBuffer[1] == SPINEL_CMD_RESET) {
+ syslog(LOG_INFO, "[->NCP] CMD_RESET tid:%d", SPINEL_HEADER_GET_TID(mOutboundBuffer[0]));
+ } else if (mOutboundBuffer[1] == SPINEL_CMD_NET_CLEAR) {
+ syslog(LOG_INFO, "[->NCP] CMD_NET_CLEAR tid:%d", SPINEL_HEADER_GET_TID(mOutboundBuffer[0]));
+ } else {
+ syslog(LOG_INFO, "[->NCP] Spinel command 0x%02X tid:%d", mOutboundBuffer[1], SPINEL_HEADER_GET_TID(mOutboundBuffer[0]));
+ }
+ } else {
+ // There is an IPv6 packet waiting on one of the tunnel interfaces.
+
+ if (mPrimaryInterface->can_read()) {
+ mOutboundBufferLen = (spinel_ssize_t)mPrimaryInterface->read(
+ &mOutboundBuffer[5],
+ sizeof(mOutboundBuffer)-5
+ );
+ mOutboundBufferType = FRAME_TYPE_DATA;
+ } else if (static_cast<bool>(mLegacyInterface)) {
+ mOutboundBufferLen = (spinel_ssize_t)mLegacyInterface->read(
+ &mOutboundBuffer[5],
+ sizeof(mOutboundBuffer)-5
+ );
+ mOutboundBufferType = FRAME_TYPE_LEGACY_DATA;
+ }
+
+ if (0 > mOutboundBufferLen) {
+ syslog(LOG_ERR,
+ "driver_to_ncp_pump: Socket error on read: %s",
+ strerror(errno));
+ signal_fatal_error(ERRORCODE_ERRNO);
+ break;
+ }
+
+ if (mOutboundBufferLen <= 0) {
+ // No packet...?
+ mOutboundBufferLen = 0;
+ continue;
+ }
+
+ if (!should_forward_ncpbound_frame(&mOutboundBufferType, &mOutboundBuffer[5], mOutboundBufferLen)) {
+ mOutboundBufferLen = 0;
+ continue;
+ }
+
+ if (get_ncp_state() == CREDENTIALS_NEEDED) {
+ mOutboundBufferType = FRAME_TYPE_INSECURE_DATA;
+ }
+
+ mOutboundBuffer[3] = (mOutboundBufferLen & 0xFF);
+ mOutboundBuffer[4] = ((mOutboundBufferLen >> 8) & 0xFF);
+
+ mOutboundBufferLen += 5;
+
+ mOutboundBuffer[0] = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0;
+ mOutboundBuffer[1] = SPINEL_CMD_PROP_VALUE_SET;
+
+ if (mOutboundBufferType == FRAME_TYPE_DATA) {
+ mOutboundBuffer[2] = SPINEL_PROP_STREAM_NET;
+
+ } else if (mOutboundBufferType == FRAME_TYPE_INSECURE_DATA) {
+ mOutboundBuffer[2] = SPINEL_PROP_STREAM_NET_INSECURE;
+
+ } else {
+ mOutboundBuffer[0] = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_1;
+ mOutboundBuffer[2] = SPINEL_PROP_STREAM_NET;
+ }
+ }
+
+#if VERBOSE_DEBUG || 1
+ // Very verbose debugging. Dumps out all outbound packets.
+ {
+ char readable_buffer[300];
+ encode_data_into_string(mOutboundBuffer,
+ mOutboundBufferLen,
+ readable_buffer,
+ sizeof(readable_buffer),
+ 0);
+ syslog(LOG_INFO, "\t↳ %s", (const char*)readable_buffer);
+ }
+#endif // VERBOSE_DEBUG
+
+
+#if WPANTUND_SPINEL_USE_FLEN
+ mOutboundBufferHeader[0] = HDLC_BYTE_FLAG;
+ mOutboundBufferHeader[1] = (mOutboundBufferLen >> 8);
+ mOutboundBufferHeader[2] = (mOutboundBufferLen & 0xFF);
+
+ mOutboundBufferSent = 0;
+
+ // Go ahead send
+ NLPT_ASYNC_WRITE_STREAM(
+ pt,
+ mSerialAdapter.get(),
+ mOutboundBufferHeader,
+ mOutboundBufferLen + sizeof(mOutboundBufferHeader)
+ );
+ mOutboundBufferSent += pt->byte_count;
+#else
+
+ mOutboundBufferEscapedLen = 1;
+ mOutboundBufferEscaped[0] = HDLC_BYTE_FLAG;
+ {
+ spinel_ssize_t i;
+ uint8_t byte;
+ uint16_t crc(0xFFFF);
+ for (i = 0; i < mOutboundBufferLen; i++) {
+ byte = mOutboundBuffer[i];
+ crc = hdlc_crc16(crc, byte);
+ if (hdlc_byte_needs_escape(byte)) {
+ mOutboundBufferEscaped[mOutboundBufferEscapedLen++] = HDLC_BYTE_ESC;
+ mOutboundBufferEscaped[mOutboundBufferEscapedLen++] = byte ^ HDLC_ESCAPE_XFORM;
+ } else {
+ mOutboundBufferEscaped[mOutboundBufferEscapedLen++] = byte;
+ }
+ }
+ crc ^= 0xFFFF;
+ byte = (crc & 0xFF);
+ if (hdlc_byte_needs_escape(byte)) {
+ mOutboundBufferEscaped[mOutboundBufferEscapedLen++] = HDLC_BYTE_ESC;
+ mOutboundBufferEscaped[mOutboundBufferEscapedLen++] = byte ^ HDLC_ESCAPE_XFORM;
+ } else {
+ mOutboundBufferEscaped[mOutboundBufferEscapedLen++] = byte;
+ }
+ byte = ((crc>>8) & 0xFF);
+ if (hdlc_byte_needs_escape(byte)) {
+ mOutboundBufferEscaped[mOutboundBufferEscapedLen++] = HDLC_BYTE_ESC;
+ mOutboundBufferEscaped[mOutboundBufferEscapedLen++] = byte ^ HDLC_ESCAPE_XFORM;
+ } else {
+ mOutboundBufferEscaped[mOutboundBufferEscapedLen++] = byte;
+ }
+ mOutboundBufferEscaped[mOutboundBufferEscapedLen++] = HDLC_BYTE_FLAG;
+ }
+
+ mOutboundBufferSent = 0;
+
+ // Go ahead send
+ NLPT_ASYNC_WRITE_STREAM(
+ pt,
+ mSerialAdapter.get(),
+ mOutboundBufferEscaped,
+ mOutboundBufferEscapedLen
+ );
+ mOutboundBufferSent += pt->byte_count;
+#endif
+
+ mOutboundBufferLen = 0;
+
+ require(pt->last_errno == 0, on_error);
+
+ // Go ahead and fire off the "did send" callback.
+ if (!mOutboundCallback.empty()) {
+ mOutboundCallback(kWPANTUNDStatus_Ok);
+ mOutboundCallback.clear();
+ }
+
+ } // while(true)
+
+on_error:
+ // If we get here, we will restart the protothread at the next iteration.
+
+ if (!mOutboundCallback.empty()) {
+ mOutboundCallback(kWPANTUNDStatus_Failure);
+ mOutboundCallback.clear();
+ }
+
+ NLPT_END(pt);
+}
diff --git a/src/ncp-spinel/SpinelNCPInstance-Protothreads.cpp b/src/ncp-spinel/SpinelNCPInstance-Protothreads.cpp
new file mode 100644
index 0000000..7586db1
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPInstance-Protothreads.cpp
@@ -0,0 +1,637 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "SpinelNCPInstance.h"
+#include "time-utils.h"
+#include "assert-macros.h"
+#include <syslog.h>
+#include <errno.h>
+#include "socket-utils.h"
+#include <stdexcept>
+#include <sys/file.h>
+#include "SuperSocket.h"
+#include "SpinelNCPTask.h"
+#include "spinel-extra.h"
+
+#include "SpinelNCPTaskSendCommand.h"
+#include "SpinelNCPTaskScan.h"
+#include "SpinelNCPTaskForm.h"
+#include "SpinelNCPTaskLeave.h"
+#include "SpinelNCPTaskJoin.h"
+#include "SpinelNCPTaskWake.h"
+#include "SpinelNCPTaskDeepSleep.h"
+
+using namespace nl;
+using namespace wpantund;
+
+int
+SpinelNCPInstance::vprocess_disabled(int event, va_list args)
+{
+ EH_BEGIN_SUB(&mSubPT);
+
+
+ while(!mEnabled) {
+ // If the association state is uninitialized, fail early.
+ if (get_ncp_state() == UNINITIALIZED) {
+ syslog(LOG_NOTICE, "Cannot attempt to sleep until NCP is initialized.");
+ EH_EXIT();
+ }
+
+ // Wait for any tasks or commands to complete.
+ EH_REQUIRE_WITHIN(
+ NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT,
+ mEnabled || is_busy(),
+ timeout_error
+ );
+
+ if (mEnabled) {
+ break;
+ }
+
+ if ((get_ncp_state() != DEEP_SLEEP) && (get_ncp_state() != FAULT)) {
+ start_new_task(boost::shared_ptr<SpinelNCPTask>(new SpinelNCPTaskDeepSleep(this, NilReturn())));
+
+ EH_WAIT_UNTIL_WITH_TIMEOUT(
+ NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT,
+ (get_ncp_state() == DEEP_SLEEP) || mTaskQueue.empty()
+ );
+ }
+
+ // If we didn't enter deep sleep then we need to bail early.
+ if ((get_ncp_state() != DEEP_SLEEP) && (get_ncp_state() != FAULT)) {
+ if (!ncp_state_is_initializing(get_ncp_state())) {
+ get_control_interface().reset();
+ }
+ EH_EXIT();
+ }
+
+ EH_WAIT_UNTIL(!IS_EVENT_FROM_NCP(event));
+
+ EH_REQUIRE_WITHIN(
+ NCP_DEEP_SLEEP_TICKLE_TIMEOUT,
+ (get_ncp_state() != DEEP_SLEEP)
+ || mEnabled
+ || IS_EVENT_FROM_NCP(event),
+ do_deep_sleep_tickle
+ );
+
+ continue;
+
+ // Exceptions
+
+do_deep_sleep_tickle:
+ // ...Go ahead and reset the NCP and state machine.
+ // This will make sure the NCP is in a known state
+ // and allow it to recover if the NCP is
+ // unresponsive.
+ syslog(LOG_WARNING, "DEEP-SLEEP-TICKLE: Resetting NCP . . .");
+
+ // Send a RESET.
+ CONTROL_REQUIRE_PREP_TO_SEND_COMMAND_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, timeout_error);
+ mOutboundBufferLen = spinel_datatype_pack(GetInstance(this)->mOutboundBuffer, sizeof(GetInstance(this)->mOutboundBuffer), "Ci", 0, SPINEL_CMD_RESET);
+ CONTROL_REQUIRE_OUTBOUND_BUFFER_FLUSHED_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, timeout_error);
+
+ mResetIsExpected = true;
+
+ // Wait for the response.
+ EH_REQUIRE_WITHIN(
+ NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT,
+ event == EVENT_NCP_RESET,
+ timeout_error
+ );
+
+ continue;
+
+timeout_error:
+ EH_EXIT();
+ }
+
+ set_ncp_power(true);
+
+ if (ncp_state_is_sleeping(get_ncp_state())) {
+ start_new_task(boost::shared_ptr<SpinelNCPTask>(
+ new SpinelNCPTaskWake(
+ this,
+ NilReturn()
+ )
+ ));
+ }
+
+ EH_END();
+}
+
+int
+SpinelNCPInstance::vprocess_resume(int event, va_list args)
+{
+ Data command;
+ bool is_commissioned;
+ int ret;
+
+ EH_BEGIN_SUB(&mSubPT);
+
+ // Get the `SPINEL_PROP_NET_SAVED` property to check if the NCP is commissioned.
+
+ CONTROL_REQUIRE_PREP_TO_SEND_COMMAND_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, on_error);
+
+ command = SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_GET, SPINEL_PROP_NET_SAVED);
+ require(command.size() < sizeof(mOutboundBuffer), on_error);
+ memcpy(mOutboundBuffer, command.data(), command.size());
+ mOutboundBufferLen = static_cast<spinel_ssize_t>(command.size());
+ CONTROL_REQUIRE_OUTBOUND_BUFFER_FLUSHED_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, on_error);
+ CONTROL_REQUIRE_COMMAND_RESPONSE_WITHIN(NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT, on_error);
+
+ ret = peek_ncp_callback_status(event, args);
+ require_noerr(ret, on_error);
+
+ {
+ unsigned int key = va_arg(args, unsigned int);
+ const uint8_t* data_in = va_arg(args, const uint8_t*);
+ spinel_size_t data_len = va_arg_small(args, spinel_size_t);
+ spinel_ssize_t len = 0;
+
+ require(key == SPINEL_PROP_NET_SAVED, on_error);
+
+ len = spinel_datatype_unpack(data_in, data_len, SPINEL_DATATYPE_BOOL_S, &is_commissioned);
+ require(len > 0, on_error);
+ }
+
+ if (!is_commissioned) {
+ syslog(LOG_NOTICE, "NCP is NOT commissioned. Cannot resume.");
+ EH_EXIT();
+ }
+
+ syslog(LOG_NOTICE, "NCP is commissioned. Resuming...");
+
+ // Resume by setting `NET_IF_UP` and `NET_STACK_UP` to `true`
+
+ CONTROL_REQUIRE_PREP_TO_SEND_COMMAND_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, on_error);
+
+ command = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_BOOL_S),
+ SPINEL_PROP_NET_IF_UP,
+ true
+ );
+
+ require(command.size() < sizeof(mOutboundBuffer), on_error);
+ memcpy(mOutboundBuffer, command.data(), command.size());
+ mOutboundBufferLen = static_cast<spinel_ssize_t>(command.size());
+ CONTROL_REQUIRE_OUTBOUND_BUFFER_FLUSHED_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, on_error);
+ CONTROL_REQUIRE_COMMAND_RESPONSE_WITHIN(NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT, on_error);
+ ret = peek_ncp_callback_status(event, args);
+ require_noerr(ret, on_error);
+
+ CONTROL_REQUIRE_PREP_TO_SEND_COMMAND_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, on_error);
+ command = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_BOOL_S),
+ SPINEL_PROP_NET_STACK_UP,
+ true
+ );
+ require(command.size() < sizeof(mOutboundBuffer), on_error);
+ memcpy(mOutboundBuffer, command.data(), command.size());
+ mOutboundBufferLen = static_cast<spinel_ssize_t>(command.size());
+ CONTROL_REQUIRE_OUTBOUND_BUFFER_FLUSHED_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, on_error);
+ CONTROL_REQUIRE_COMMAND_RESPONSE_WITHIN(NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT, on_error);
+ ret = peek_ncp_callback_status(event, args);
+ require_noerr(ret, on_error);
+
+ EH_EXIT();
+
+on_error:
+
+ syslog(LOG_ERR, "NCP is misbehaving or unresponsive");
+ reinitialize_ncp();
+
+ EH_END();
+}
+
+int
+SpinelNCPInstance::vprocess_associated(int event, va_list args)
+{
+ // Conditions under which this protothread should be exited gracefully.
+ const bool should_exit = !mEnabled
+ || !ncp_state_is_joining_or_joined(get_ncp_state());
+
+ EH_BEGIN_SUB(&mSubPT);
+
+ EH_WAIT_UNTIL_WITH_TIMEOUT(
+ NCP_TICKLE_TIMEOUT,
+ should_exit || !(IS_EVENT_FROM_NCP(event))
+ );
+
+ // This is not a typo. Despite the above "WAIT_UNTIL" looking
+ // very similar, it is not the same! DO NOT REMOVE!
+ EH_WAIT_UNTIL_WITH_TIMEOUT(
+ NCP_TICKLE_TIMEOUT,
+ should_exit
+ );
+
+ if (eh_did_timeout) {
+ syslog(LOG_INFO, "Tickle...");
+ CONTROL_REQUIRE_PREP_TO_SEND_COMMAND_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, on_error);
+ mOutboundBufferLen = spinel_datatype_pack(GetInstance(this)->mOutboundBuffer, sizeof(GetInstance(this)->mOutboundBuffer), "Ci", 0, SPINEL_CMD_NOOP);
+ CONTROL_REQUIRE_OUTBOUND_BUFFER_FLUSHED_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, on_error);
+
+ CONTROL_REQUIRE_COMMAND_RESPONSE_WITHIN(NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT, on_error);
+ mFailureCount = 0;
+ }
+
+ EH_EXIT();
+
+on_error:
+
+ syslog(LOG_ERR, "NCP is misbehaving or unresponsive");
+ reinitialize_ncp();
+
+ EH_END();
+}
+
+int
+SpinelNCPInstance::vprocess_offline(int event, va_list args)
+{
+ // Conditions under which this protothread should be exited gracefully.
+ const bool should_exit = ncp_state_is_interface_up(get_ncp_state())
+ || !mEnabled
+ || (mOutboundBufferLen>0);
+
+ float sleep_timeout = mAutoDeepSleepTimeout;
+
+ if (!mNetworkKey.empty() || (mNetworkKeyIndex != 0)) {
+ sleep_timeout += 60;
+ }
+
+ EH_BEGIN_SUB(&mSubPT);
+
+ // Wait for auto deep sleep to be turned on, or if there is an exit condition.
+ EH_WAIT_UNTIL(should_exit || mAutoDeepSleep);
+
+ // Wait for auto deep sleep to be turned off or for us to be not asleep, or if there is an exit condition
+ EH_WAIT_UNTIL(
+ should_exit
+ || !mAutoDeepSleep
+ || !ncp_state_is_sleeping(get_ncp_state())
+ );
+
+ // Wait within a timeout for us to enter sleep state, or for auto deep sleep to be turned off, or
+ // if we have a command to send to NCP or receive a callback/event from NCP, or if there is an exit condition
+ EH_WAIT_UNTIL_WITH_TIMEOUT(
+ sleep_timeout,
+ should_exit
+ || !mAutoDeepSleep
+ || !mTaskQueue.empty()
+ || (IS_EVENT_FROM_NCP(event))
+ || ncp_state_is_sleeping(get_ncp_state())
+ );
+
+ if (eh_did_timeout) {
+ start_new_task(boost::shared_ptr<SpinelNCPTask>(new SpinelNCPTaskDeepSleep(this, NilReturn())));
+ }
+
+ EH_END();
+}
+
+int
+SpinelNCPInstance::vprocess_init(int event, va_list args)
+{
+ int status = 0;
+
+ if (event == EVENT_NCP_RESET) {
+ if (mDriverState == INITIALIZING) {
+ syslog(LOG_ERR, "Unexpected reset durring NCP initialization.");
+ mFailureCount++;
+ PT_INIT(&mSubPT);
+ } else if (mDriverState == INITIALIZING_WAITING_FOR_RESET) {
+ mDriverState = INITIALIZING;
+ }
+ }
+
+ EH_BEGIN_SUB(&mSubPT);
+
+ if (get_ncp_state() == UPGRADING) {
+ EH_WAIT_UNTIL(get_upgrade_status() != EINPROGRESS);
+
+ status = get_upgrade_status();
+
+ if (status == 0) {
+ syslog(LOG_INFO, "Firmware Update Complete.");
+ } else {
+ syslog(LOG_ERR, "Firmware Update Failed with Error %d", status);
+ mFailureCount++;
+
+ if (mFailureCount > mFailureThreshold) {
+ change_ncp_state(FAULT);
+ }
+ }
+ }
+
+ if (get_ncp_state() == FAULT) {
+ EH_EXIT();
+ }
+
+ syslog(LOG_INFO, "Initializing NCP");
+
+ set_initializing_ncp(true);
+
+ change_ncp_state(UNINITIALIZED);
+
+ set_ncp_power(true);
+
+ clear_nonpermanent_global_addresses();
+
+ mNCPVersionString = "";
+
+ mDriverState = INITIALIZING_WAITING_FOR_RESET;
+
+ if (mResetIsExpected) {
+ EH_WAIT_UNTIL_WITH_TIMEOUT(NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT, mResetIsExpected == false);
+
+ if (eh_did_timeout) {
+ // mResetIsExpected has been set for too long and we
+ // haven't gotten a reset yet. This can prevent us from sleeping.
+ // by incrementing the failure count here we will cause
+ // another reset to occur in the code below.
+ mFailureCount++;
+ mResetIsExpected = false;
+ syslog(LOG_ERR, "Was waiting for a reset, but we never got one.");
+ }
+ } else {
+ // Backoff delay. Normaly zero. May increase if we are in a reset loop.
+ EH_SLEEP_FOR(mRunawayResetBackoffManager.delay_for_unexpected_reset());
+ }
+
+ do {
+ EH_SLEEP_FOR(0.1);
+
+ if (mFailureCount > mFailureThreshold) {
+ syslog(LOG_ALERT, "The NCP is misbehaving: Repeatedly unable to initialize NCP. Entering fault state.");
+ change_ncp_state(FAULT);
+ EH_EXIT();
+ }
+
+ if ( mAutoUpdateFirmware
+ && (mFailureCount > (mFailureThreshold - 1))
+ && can_upgrade_firmware()
+ ) {
+ syslog(LOG_ALERT, "The NCP is misbehaving: Attempting a firmware update");
+ upgrade_firmware();
+ EH_RESTART();
+ }
+
+ if ((event != EVENT_NCP_RESET) && (mFailureCount > 0)) {
+ syslog(LOG_ERR, "Resetting and trying again... (retry %d)", mFailureCount);
+
+ change_ncp_state(UNINITIALIZED);
+
+ mNetworkKey = Data();
+ mNetworkKeyIndex = 0;
+
+ reset_tasks(kWPANTUNDStatus_Canceled);
+
+ // Do a hard reset only on even attempts.
+ if ((mFailureCount & 1) == 0) {
+ hard_reset_ncp();
+ } else {
+ CONTROL_REQUIRE_PREP_TO_SEND_COMMAND_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, on_error);
+ mOutboundBufferLen = spinel_datatype_pack(GetInstance(this)->mOutboundBuffer, sizeof(GetInstance(this)->mOutboundBuffer), "Ci", 0, SPINEL_CMD_RESET);
+ CONTROL_REQUIRE_OUTBOUND_BUFFER_FLUSHED_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, on_error);
+ }
+
+ mDriverState = INITIALIZING_WAITING_FOR_RESET;
+
+ EH_REQUIRE_WITHIN(
+ NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT,
+ event == EVENT_NCP_RESET,
+ on_error
+ );
+
+ mDriverState = INITIALIZING;
+ }
+
+ // Get the protocol version
+ CONTROL_REQUIRE_PREP_TO_SEND_COMMAND_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, on_error);
+ GetInstance(this)->mOutboundBufferLen = spinel_cmd_prop_value_get(GetInstance(this)->mOutboundBuffer, sizeof(GetInstance(this)->mOutboundBuffer), SPINEL_PROP_PROTOCOL_VERSION);
+ CONTROL_REQUIRE_OUTBOUND_BUFFER_FLUSHED_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, on_error);
+
+ CONTROL_REQUIRE_COMMAND_RESPONSE_WITHIN(NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT, on_error);
+
+ status = peek_ncp_callback_status(event, args);
+ require_noerr(status, on_error);
+
+ if (get_ncp_state() == UNINITIALIZED) {
+ // Get the thread state
+ CONTROL_REQUIRE_PREP_TO_SEND_COMMAND_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, on_error);
+ GetInstance(this)->mOutboundBufferLen = spinel_cmd_prop_value_get(GetInstance(this)->mOutboundBuffer, sizeof(GetInstance(this)->mOutboundBuffer), SPINEL_PROP_NET_STACK_UP);
+ CONTROL_REQUIRE_OUTBOUND_BUFFER_FLUSHED_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, on_error);
+
+ CONTROL_REQUIRE_COMMAND_RESPONSE_WITHIN(NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT, on_error);
+
+ require(get_ncp_state() != UNINITIALIZED, on_error);
+ }
+
+ // If we are "joining" at this point, then we must start over.
+ // This will cause a reset to occur.
+ require(!ncp_state_is_joining(get_ncp_state()), on_error);
+
+ // This next line causes any resets received after this
+ // point to cause the control protothread to be restarted.
+ mDriverState = INITIALIZING;
+
+ if (mIsPcapInProgress) {
+ CONTROL_REQUIRE_PREP_TO_SEND_COMMAND_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, on_error);
+ GetInstance(this)->mOutboundBufferLen = spinel_cmd_prop_value_set_uint(GetInstance(this)->mOutboundBuffer, sizeof(GetInstance(this)->mOutboundBuffer), SPINEL_PROP_MAC_RAW_STREAM_ENABLED, 1);
+ CONTROL_REQUIRE_OUTBOUND_BUFFER_FLUSHED_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, on_error);
+
+ CONTROL_REQUIRE_COMMAND_RESPONSE_WITHIN(NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT, on_error);
+ }
+
+ if (mEnabled) {
+ // Refresh our internal copies of the following radio parameters:
+ static const spinel_prop_key_t keys_to_fetch[] = {
+ SPINEL_PROP_NCP_VERSION,
+ SPINEL_PROP_INTERFACE_TYPE,
+ SPINEL_PROP_VENDOR_ID,
+ SPINEL_PROP_CAPS,
+ SPINEL_PROP_HWADDR,
+ SPINEL_PROP_PHY_CHAN,
+ SPINEL_PROP_PHY_CHAN_SUPPORTED,
+ SPINEL_PROP_MAC_15_4_PANID,
+ SPINEL_PROP_MAC_15_4_LADDR,
+ SPINEL_PROP_NET_MASTER_KEY,
+ SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER,
+ SPINEL_PROP_NET_NETWORK_NAME,
+ SPINEL_PROP_NET_XPANID,
+ SPINEL_PROP_IPV6_LL_ADDR,
+ SPINEL_PROP_IPV6_ML_ADDR,
+ SPINEL_PROP_THREAD_ASSISTING_PORTS,
+ SPINEL_PROP_NET_IF_UP,
+ SPINEL_PROP_NET_STACK_UP,
+ SPINEL_PROP_NET_ROLE,
+ };
+
+ for (mSubPTIndex = 0; mSubPTIndex < sizeof(keys_to_fetch)/sizeof(keys_to_fetch[0]); mSubPTIndex++) {
+ CONTROL_REQUIRE_PREP_TO_SEND_COMMAND_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, on_error);
+ GetInstance(this)->mOutboundBufferLen = spinel_cmd_prop_value_get(GetInstance(this)->mOutboundBuffer, sizeof(GetInstance(this)->mOutboundBuffer), keys_to_fetch[mSubPTIndex]);
+ CONTROL_REQUIRE_OUTBOUND_BUFFER_FLUSHED_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, on_error);
+ CONTROL_REQUIRE_COMMAND_RESPONSE_WITHIN(NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT, on_error);
+
+ status = peek_ncp_callback_status(event, args);
+
+ if (status != 0) {
+ syslog(LOG_WARNING, "Unsuccessful fetching property \"%s\" from NCP: \"%s\" (%d)", spinel_prop_key_to_cstr(keys_to_fetch[mSubPTIndex]), spinel_status_to_cstr(static_cast<spinel_status_t>(status)), status);
+ }
+ }
+
+ // Restore all the saved settings
+ for (mSettingsIter = mSettings.begin(); mSettingsIter != mSettings.end(); mSettingsIter++) {
+
+ syslog(LOG_INFO, "Restoring property \"%s\" on NCP", mSettingsIter->first.c_str());
+
+ // Skip the settings if capability is not present.
+ if ((mSettingsIter->second.mCapability != 0) &&!mCapabilities.count(mSettingsIter->second.mCapability)) {
+ continue;
+ }
+
+ CONTROL_REQUIRE_PREP_TO_SEND_COMMAND_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, on_error);
+
+ if (mSettingsIter->second.mSpinelCommand.size() > sizeof(GetInstance(this)->mOutboundBuffer))
+ {
+ syslog(LOG_WARNING,
+ "Spinel command for restoring property \"%s\" does not fit in outbound buffer (require %d bytes but only %u bytes available)",
+ mSettingsIter->first.c_str(),
+ mSettingsIter->second.mSpinelCommand.size(),
+ sizeof(GetInstance(this)->mOutboundBuffer)
+ );
+
+ continue;
+ }
+
+ GetInstance(this)->mOutboundBufferLen = mSettingsIter->second.mSpinelCommand.size();
+ memcpy(GetInstance(this)->mOutboundBuffer, mSettingsIter->second.mSpinelCommand.data(), mSettingsIter->second.mSpinelCommand.size());
+
+ CONTROL_REQUIRE_OUTBOUND_BUFFER_FLUSHED_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, on_error);
+ CONTROL_REQUIRE_COMMAND_RESPONSE_WITHIN(NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT, on_error);
+
+ status = peek_ncp_callback_status(event, args);
+
+ if (status != 0) {
+ syslog(LOG_WARNING, "Unsuccessful in restoring property \"%s\" on NCP: \"%s\" (%d)", mSettingsIter->first.c_str(), spinel_status_to_cstr(static_cast<spinel_status_t>(status)), status);
+ }
+ }
+ }
+
+ break;
+
+on_error:
+ if (status) {
+ syslog(LOG_ERR, "Initialization error: %d", status);
+ }
+ EH_SLEEP_FOR(0.5);
+ mFailureCount++;
+ } while (true);
+
+ mIsPcapInProgress = false;
+ mFailureCount = 0;
+ mResetIsExpected = false;
+ set_initializing_ncp(false);
+ mDriverState = NORMAL_OPERATION;
+
+ syslog(LOG_NOTICE, "Finished initializing NCP");
+
+ EH_END();
+}
+
+int
+SpinelNCPInstance::vprocess_event(int event, va_list args)
+{
+ if (get_ncp_state() == FAULT) {
+ // We perform no processing in the fault state.
+ PT_INIT(&mControlPT);
+ return 0;
+ }
+
+ while (!mTaskQueue.empty()) {
+ va_list tmp;
+ boost::shared_ptr<SpinelNCPTask> current_task(mTaskQueue.front());
+ va_copy(tmp, args);
+ char ret = current_task->vprocess_event(event, tmp);
+ va_end(tmp);
+
+ if (ret == PT_ENDED || ret == PT_EXITED) {
+ mTaskQueue.pop_front();
+ continue;
+ }
+
+ break;
+ }
+
+ EH_BEGIN();
+
+ EH_SPAWN(&mSubPT, vprocess_init(event, args));
+
+ if (get_ncp_state() == FAULT) {
+ EH_EXIT();
+ }
+
+ EH_WAIT_UNTIL(mTaskQueue.empty());
+
+ // If we are offline and autoResume is enabled
+ if (mAutoResume && mEnabled && (get_ncp_state() == OFFLINE)) {
+ syslog(LOG_NOTICE, "AutoResume is enabled. Trying to resume.");
+ EH_SPAWN(&mSubPT, vprocess_resume(event, args));
+ }
+
+ while (1) {
+ // Yield for one loop cycle only. This prevents
+ // us from entering any endless loops.
+ EH_SLEEP_FOR(0);
+
+ if (ncp_state_is_initializing(get_ncp_state())) {
+ EH_RESTART();
+
+ } else if (!mEnabled) {
+ syslog(LOG_NOTICE, "Interface Disabled.");
+ EH_SPAWN(&mSubPT, vprocess_disabled(event, args));
+
+ } else if (ncp_state_is_joining_or_joined(get_ncp_state())) {
+ EH_SPAWN(&mSubPT, vprocess_associated(event, args));
+
+ } else if (!ncp_state_is_interface_up(get_ncp_state())) {
+ EH_SPAWN(&mSubPT, vprocess_offline(event, args));
+
+ } else {
+ syslog(
+ LOG_WARNING,
+ "Unexpected NCP state %d (%s)",
+ get_ncp_state(),
+ ncp_state_to_string(get_ncp_state()).c_str()
+ );
+
+ // Yield for one main loop cycle without
+ // specifying a timeout to avoid high CPU usage
+ // cases like this.
+ EH_YIELD();
+ }
+
+ } // while(1)
+
+ EH_END();
+}
diff --git a/src/ncp-spinel/SpinelNCPInstance.cpp b/src/ncp-spinel/SpinelNCPInstance.cpp
new file mode 100644
index 0000000..42eac92
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPInstance.cpp
@@ -0,0 +1,1784 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "SpinelNCPInstance.h"
+#include "time-utils.h"
+#include "assert-macros.h"
+#include <syslog.h>
+#include <errno.h>
+#include "socket-utils.h"
+#include <stdexcept>
+#include <sys/file.h>
+#include "SuperSocket.h"
+#include "SpinelNCPTask.h"
+#include "SpinelNCPTaskWake.h"
+#include "SpinelNCPTaskSendCommand.h"
+#include "SpinelNCPTaskJoin.h"
+#include "SpinelNCPTaskGetNetworkTopology.h"
+#include "SpinelNCPTaskGetMsgBufferCounters.h"
+#include "any-to.h"
+#include "spinel-extra.h"
+
+#define kWPANTUNDProperty_Spinel_CounterPrefix "NCP:Counter:"
+
+using namespace nl;
+using namespace wpantund;
+
+WPANTUND_DEFINE_NCPINSTANCE_PLUGIN(spinel, SpinelNCPInstance);
+
+void
+SpinelNCPInstance::handle_ncp_log(const uint8_t* data_ptr, int data_len)
+{
+ static char linebuffer[NCP_DEBUG_LINE_LENGTH_MAX + 1];
+ static int linepos = 0;
+ while (data_len--) {
+ char nextchar = *data_ptr++;
+
+ if ((nextchar == '\t') || (nextchar >= 32)) {
+ linebuffer[linepos++] = nextchar;
+ }
+
+ if ( (linepos != 0)
+ && ( (nextchar == '\n')
+ || (nextchar == '\r')
+ || (linepos >= (sizeof(linebuffer) - 1))
+ )
+ )
+ {
+ // flush.
+ linebuffer[linepos] = 0;
+ syslog(LOG_WARNING, "NCP => %s\n", linebuffer);
+ linepos = 0;
+ }
+ }
+}
+
+void
+SpinelNCPInstance::start_new_task(const boost::shared_ptr<SpinelNCPTask> &task)
+{
+ if (ncp_state_is_detached_from_ncp(get_ncp_state())) {
+ task->finish(kWPANTUNDStatus_InvalidWhenDisabled);
+ } else if (PT_SCHEDULE(task->process_event(EVENT_STARTING_TASK))) {
+
+ if (ncp_state_is_sleeping(get_ncp_state())
+ && (dynamic_cast<const SpinelNCPTaskWake*>(task.get()) == NULL)
+ ) {
+ start_new_task(boost::shared_ptr<SpinelNCPTask>(new SpinelNCPTaskWake(this, NilReturn())));
+ }
+ mTaskQueue.push_back(task);
+ }
+}
+
+int
+nl::wpantund::spinel_status_to_wpantund_status(int spinel_status)
+{
+ wpantund_status_t ret;
+ switch (spinel_status) {
+ case SPINEL_STATUS_ALREADY:
+ ret = kWPANTUNDStatus_Already;
+ break;
+ case SPINEL_STATUS_BUSY:
+ ret = kWPANTUNDStatus_Busy;
+ break;
+ case SPINEL_STATUS_IN_PROGRESS:
+ ret = kWPANTUNDStatus_InProgress;
+ break;
+ case SPINEL_STATUS_JOIN_FAILURE:
+ ret = kWPANTUNDStatus_JoinFailedUnknown;
+ break;
+ case SPINEL_STATUS_JOIN_INCOMPATIBLE:
+ ret = kWPANTUNDStatus_JoinFailedAtScan;
+ break;
+ case SPINEL_STATUS_JOIN_SECURITY:
+ ret = kWPANTUNDStatus_JoinFailedAtAuthenticate;
+ break;
+ case SPINEL_STATUS_OK:
+ ret = kWPANTUNDStatus_Ok;
+ break;
+ case SPINEL_STATUS_PROP_NOT_FOUND:
+ ret = kWPANTUNDStatus_PropertyNotFound;
+ break;
+ case SPINEL_STATUS_INVALID_ARGUMENT:
+ ret = kWPANTUNDStatus_NCP_InvalidArgument;
+ break;
+ case SPINEL_STATUS_INVALID_STATE:
+ ret = kWPANTUNDStatus_InvalidForCurrentState;
+ break;
+
+ default:
+ ret = WPANTUND_NCPERROR_TO_STATUS(spinel_status);
+ break;
+ }
+
+ return ret;
+}
+
+int
+nl::wpantund::peek_ncp_callback_status(int event, va_list args)
+{
+ int ret = 0;
+
+ if (EVENT_NCP_PROP_VALUE_IS == event) {
+ va_list tmp;
+ va_copy(tmp, args);
+ unsigned int key = va_arg(tmp, unsigned int);
+ if (SPINEL_PROP_LAST_STATUS == key) {
+ const uint8_t* spinel_data_ptr = va_arg(tmp, const uint8_t*);
+ spinel_size_t spinel_data_len = va_arg(tmp, spinel_size_t);
+
+ if (spinel_datatype_unpack(spinel_data_ptr, spinel_data_len, "i", &ret) <= 0) {
+ ret = SPINEL_STATUS_PARSE_ERROR;
+ }
+ }
+ va_end(tmp);
+ } else if (EVENT_NCP_RESET == event) {
+ va_list tmp;
+ va_copy(tmp, args);
+ ret = va_arg(tmp, int);
+ va_end(tmp);
+ }
+
+ return ret;
+}
+
+SpinelNCPInstance::SpinelNCPInstance(const Settings& settings) :
+ NCPInstanceBase(settings), mControlInterface(this)
+{
+ mOutboundBufferLen = 0;
+ mInboundHeader = 0;
+ mSupprotedChannels.clear();
+
+ mIsPcapInProgress = false;
+ mNoMemStatusCounter = 0;
+ mLastTimeNoMemStatus = 0;
+ mSettings.clear();
+
+ if (!settings.empty()) {
+ int status;
+ Settings::const_iterator iter;
+
+ for(iter = settings.begin(); iter != settings.end(); iter++) {
+ if (!NCPInstanceBase::setup_property_supported_by_class(iter->first)) {
+ status = static_cast<NCPControlInterface&>(get_control_interface())
+ .set_property(iter->first, iter->second);
+
+ if (status != 0) {
+ syslog(LOG_WARNING, "Attempt to set property \"%s\" failed with err %d", iter->first.c_str(), status);
+ }
+ }
+ }
+ }
+}
+
+SpinelNCPInstance::~SpinelNCPInstance()
+{
+}
+
+
+bool
+SpinelNCPInstance::setup_property_supported_by_class(const std::string& prop_name)
+{
+ return NCPInstanceBase::setup_property_supported_by_class(prop_name);
+}
+
+SpinelNCPControlInterface&
+SpinelNCPInstance::get_control_interface()
+{
+ return mControlInterface;
+}
+
+uint32_t
+SpinelNCPInstance::get_default_channel_mask(void)
+{
+ uint32_t channel_mask = 0;
+ uint16_t i;
+
+ for (i = 0; i < 32; i++) {
+ if (mSupprotedChannels.find(i) != mSupprotedChannels.end()) {
+ channel_mask |= (1 << i);
+ }
+ }
+
+ return channel_mask;
+}
+
+std::set<std::string>
+SpinelNCPInstance::get_supported_property_keys()const
+{
+ std::set<std::string> properties (NCPInstanceBase::get_supported_property_keys());
+
+ properties.insert(kWPANTUNDProperty_ConfigNCPDriverName);
+ properties.insert(kWPANTUNDProperty_NCPChannel);
+ properties.insert(kWPANTUNDProperty_NCPChannelMask);
+ properties.insert(kWPANTUNDProperty_NCPFrequency);
+ properties.insert(kWPANTUNDProperty_NCPRSSI);
+ properties.insert(kWPANTUNDProperty_NCPExtendedAddress);
+
+ if (mCapabilities.count(SPINEL_CAP_NET_THREAD_1_0)) {
+ properties.insert(kWPANTUNDProperty_ThreadRLOC16);
+ properties.insert(kWPANTUNDProperty_ThreadRouterID);
+ properties.insert(kWPANTUNDProperty_ThreadLeaderAddress);
+ properties.insert(kWPANTUNDProperty_ThreadLeaderRouterID);
+ properties.insert(kWPANTUNDProperty_ThreadLeaderWeight);
+ properties.insert(kWPANTUNDProperty_ThreadLeaderLocalWeight);
+ properties.insert(kWPANTUNDProperty_ThreadNetworkData);
+ properties.insert(kWPANTUNDProperty_ThreadNetworkDataVersion);
+ properties.insert(kWPANTUNDProperty_ThreadStableNetworkData);
+ properties.insert(kWPANTUNDProperty_ThreadStableNetworkDataVersion);
+ properties.insert(kWPANTUNDProperty_ThreadLeaderNetworkData);
+ properties.insert(kWPANTUNDProperty_ThreadStableLeaderNetworkData);
+ properties.insert(kWPANTUNDProperty_ThreadChildTable);
+ properties.insert(kWPANTUNDProperty_ThreadNeighborTable);
+ }
+
+ if (mCapabilities.count(SPINEL_CAP_COUNTERS)) {
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "TX_PKT_TOTAL");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "TX_PKT_UNICAST");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "TX_PKT_BROADCAST");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "TX_PKT_ACK_REQ");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "TX_PKT_ACKED");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "TX_PKT_NO_ACK_REQ");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "TX_PKT_DATA");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "TX_PKT_DATA_POLL");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "TX_PKT_BEACON");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "TX_PKT_BEACON_REQ");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "TX_PKT_OTHER");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "TX_PKT_RETRY");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "TX_ERR_CCA");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "TX_ERR_ABORT");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "RX_PKT_TOTAL");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "RX_PKT_UNICAST");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "RX_PKT_BROADCAST");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "RX_PKT_DATA");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "RX_PKT_DATA_POLL");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "RX_PKT_BEACON");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "RX_PKT_BEACON_REQ");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "RX_PKT_OTHER");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "RX_PKT_FILT_WL");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "RX_PKT_FILT_DA");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "RX_ERR_EMPTY");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "RX_ERR_UKWN_NBR");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "RX_ERR_NVLD_SADDR");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "RX_ERR_SECURITY");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "RX_ERR_BAD_FCS");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "RX_ERR_OTHER");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "TX_IP_SEC_TOTAL");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "TX_IP_INSEC_TOTAL");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "TX_IP_DROPPED");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "RX_IP_SEC_TOTAL");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "RX_IP_INSEC_TOTAL");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "RX_IP_DROPPED");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "TX_SPINEL_TOTAL");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "RX_SPINEL_TOTAL");
+ properties.insert(kWPANTUNDProperty_Spinel_CounterPrefix "RX_SPINEL_ERR");
+ }
+
+ if (mCapabilities.count(SPINEL_CAP_JAM_DETECT)) {
+ properties.insert(kWPANTUNDProperty_JamDetectionStatus);
+ properties.insert(kWPANTUNDProperty_JamDetectionEnable);
+ properties.insert(kWPANTUNDProperty_JamDetectionRssiThreshold);
+ properties.insert(kWPANTUNDProperty_JamDetectionWindow);
+ properties.insert(kWPANTUNDProperty_JamDetectionBusyPeriod);
+ properties.insert(kWPANTUNDProperty_JamDetectionDebugHistoryBitmap);
+ }
+
+ if (mCapabilities.count(SPINEL_CAP_NEST_LEGACY_INTERFACE))
+ {
+ properties.insert(kWPANTUNDProperty_NestLabs_LegacyMeshLocalPrefix);
+ }
+
+ return properties;
+}
+
+cms_t
+SpinelNCPInstance::get_ms_to_next_event(void)
+{
+ cms_t cms = NCPInstanceBase::get_ms_to_next_event();
+
+ if (ncp_state_is_detached_from_ncp(get_ncp_state())) {
+ return CMS_DISTANT_FUTURE;
+ }
+
+ // If the control protothread hasn't even started, set cms to zero.
+ if (0 == mControlPT.lc) {
+ cms = 0;
+ }
+
+ if (!mTaskQueue.empty()) {
+ int tmp_cms = mTaskQueue.front()->get_ms_to_next_event();
+ if (tmp_cms < cms) {
+ cms = tmp_cms;
+ }
+ }
+
+ if (cms < 0) {
+ cms = 0;
+ }
+
+ return cms;
+}
+
+static void convert_rloc16_to_router_id(CallbackWithStatusArg1 cb, int status, const boost::any& value)
+{
+ uint8_t router_id = 0;
+
+ if (status == kWPANTUNDStatus_Ok) {
+ uint16_t rloc16 = any_to_int(value);
+ router_id = rloc16 >> 10;
+ }
+ cb(status, router_id);
+}
+
+static int unpack_jam_detect_history_bitmap(const uint8_t *data_in, spinel_size_t data_len, boost::any& value)
+{
+ spinel_ssize_t len;
+ uint32_t lower, higher;
+ uint64_t val;
+ int ret = kWPANTUNDStatus_Failure;
+
+ len = spinel_datatype_unpack(
+ data_in,
+ data_len,
+ SPINEL_DATATYPE_UINT32_S SPINEL_DATATYPE_UINT32_S,
+ &lower,
+ &higher
+ );
+
+ if (len > 0)
+ {
+ ret = kWPANTUNDStatus_Ok;
+ value = (static_cast<uint64_t>(higher) << 32) + static_cast<uint64_t>(lower);
+ }
+
+ return ret;
+}
+
+void
+SpinelNCPInstance::get_property(
+ const std::string& key,
+ CallbackWithStatusArg1 cb
+) {
+
+#define SIMPLE_SPINEL_GET(prop__, type__) \
+ start_new_task(SpinelNCPTaskSendCommand::Factory(this) \
+ .set_callback(cb) \
+ .add_command( \
+ SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_GET, prop__) \
+ ) \
+ .set_reply_format(type__) \
+ .finish() \
+ )
+
+ if (strcaseequal(key.c_str(), kWPANTUNDProperty_ConfigNCPDriverName)) {
+ cb(0, boost::any(std::string("spinel")));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NCPChannelMask)) {
+ cb(0, boost::any(get_default_channel_mask()));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NCPCCAThreshold)) {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_PHY_CCA_THRESHOLD, SPINEL_DATATYPE_INT8_S);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NCPFrequency)) {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_PHY_FREQ, SPINEL_DATATYPE_INT32_S);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NetworkKey)) {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_NET_MASTER_KEY, SPINEL_DATATYPE_DATA_S);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NCPExtendedAddress)) {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_MAC_EXTENDED_ADDR, SPINEL_DATATYPE_EUI64_S);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NetworkKeyIndex)) {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER, SPINEL_DATATYPE_UINT32_S);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NetworkIsCommissioned)) {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_NET_SAVED, SPINEL_DATATYPE_BOOL_S);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NCPRSSI)) {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_PHY_RSSI, SPINEL_DATATYPE_INT8_S);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_ThreadRLOC16)) {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_THREAD_RLOC16, SPINEL_DATATYPE_UINT16_S);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_ThreadRouterID)) {
+ cb = boost::bind(convert_rloc16_to_router_id, cb, _1, _2);
+ SIMPLE_SPINEL_GET(SPINEL_PROP_THREAD_RLOC16, SPINEL_DATATYPE_UINT16_S);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_ThreadLeaderAddress)) {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_THREAD_LEADER_ADDR, SPINEL_DATATYPE_IPv6ADDR_S);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_ThreadLeaderRouterID)) {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_THREAD_LEADER_RID, SPINEL_DATATYPE_UINT8_S);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_ThreadLeaderWeight)) {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_THREAD_LEADER_WEIGHT, SPINEL_DATATYPE_UINT8_S);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_ThreadLeaderLocalWeight)) {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_THREAD_LOCAL_LEADER_WEIGHT, SPINEL_DATATYPE_UINT8_S);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_ThreadNetworkData)) {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_THREAD_NETWORK_DATA, SPINEL_DATATYPE_DATA_S);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_ThreadNetworkDataVersion)) {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_THREAD_NETWORK_DATA_VERSION, SPINEL_DATATYPE_UINT8_S);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_ThreadStableNetworkData)) {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_THREAD_STABLE_NETWORK_DATA, SPINEL_DATATYPE_DATA_S);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_ThreadLeaderNetworkData)) {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_THREAD_LEADER_NETWORK_DATA, SPINEL_DATATYPE_DATA_S);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_ThreadStableLeaderNetworkData)) {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_THREAD_STABLE_LEADER_NETWORK_DATA, SPINEL_DATATYPE_DATA_S);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_ThreadStableNetworkDataVersion)) {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_THREAD_STABLE_NETWORK_DATA_VERSION, SPINEL_DATATYPE_UINT8_S);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_IPv6MeshLocalPrefix) && !buffer_is_nonzero(mNCPV6Prefix, sizeof(mNCPV6Prefix))) {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_IPV6_ML_PREFIX, SPINEL_DATATYPE_IPv6ADDR_S);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_IPv6MeshLocalAddress) && !buffer_is_nonzero(mNCPV6Prefix, sizeof(mNCPV6Prefix))) {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_IPV6_ML_ADDR, SPINEL_DATATYPE_IPv6ADDR_S);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_IPv6LinkLocalAddress) && !IN6_IS_ADDR_LINKLOCAL(&mNCPLinkLocalAddress)) {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_IPV6_LL_ADDR, SPINEL_DATATYPE_IPv6ADDR_S);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_JamDetectionStatus)) {
+ if (!mCapabilities.count(SPINEL_CAP_JAM_DETECT)) {
+ cb(kWPANTUNDStatus_FeatureNotSupported, boost::any(std::string("Jam Detection Feature Not Supported")));
+ } else {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_JAM_DETECTED, SPINEL_DATATYPE_BOOL_S);
+ }
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_JamDetectionEnable)) {
+ if (!mCapabilities.count(SPINEL_CAP_JAM_DETECT)) {
+ cb(kWPANTUNDStatus_FeatureNotSupported, boost::any(std::string("Jam Detection Feature Not Supported")));
+ } else {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_JAM_DETECT_ENABLE, SPINEL_DATATYPE_BOOL_S);
+ }
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_JamDetectionRssiThreshold)) {
+ if (!mCapabilities.count(SPINEL_CAP_JAM_DETECT)) {
+ cb(kWPANTUNDStatus_FeatureNotSupported, boost::any(std::string("Jam Detection Feature Not Supported")));
+ } else {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_JAM_DETECT_RSSI_THRESHOLD, SPINEL_DATATYPE_INT8_S);
+ }
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_JamDetectionWindow)) {
+ if (!mCapabilities.count(SPINEL_CAP_JAM_DETECT)) {
+ cb(kWPANTUNDStatus_FeatureNotSupported, boost::any(std::string("Jam Detection Feature Not Supported")));
+ } else {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_JAM_DETECT_WINDOW, SPINEL_DATATYPE_UINT8_S);
+ }
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_JamDetectionBusyPeriod)) {
+ if (!mCapabilities.count(SPINEL_CAP_JAM_DETECT)) {
+ cb(kWPANTUNDStatus_FeatureNotSupported, boost::any(std::string("Jam Detection Feature Not Supported")));
+ } else {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_JAM_DETECT_BUSY, SPINEL_DATATYPE_UINT8_S);
+ }
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_JamDetectionDebugHistoryBitmap)) {
+ if (!mCapabilities.count(SPINEL_CAP_JAM_DETECT)) {
+ cb(kWPANTUNDStatus_FeatureNotSupported, boost::any(std::string("Jam Detection Feature Not Supported")));
+ } else {
+ start_new_task(SpinelNCPTaskSendCommand::Factory(this)
+ .set_callback(cb)
+ .add_command(
+ SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_GET, SPINEL_PROP_JAM_DETECT_HISTORY_BITMAP)
+ )
+ .set_reply_unpacker(unpack_jam_detect_history_bitmap)
+ .finish()
+ );
+ }
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NestLabs_LegacyMeshLocalPrefix)) {
+ if (!mCapabilities.count(SPINEL_CAP_NEST_LEGACY_INTERFACE)) {
+ cb(kWPANTUNDStatus_FeatureNotSupported, boost::any(std::string("Legacy Capability Not Supported by NCP")));
+ } else {
+ SIMPLE_SPINEL_GET(SPINEL_PROP_NEST_LEGACY_ULA_PREFIX, SPINEL_DATATYPE_DATA_S);
+ }
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_ThreadChildTable)) {
+ start_new_task(boost::shared_ptr<SpinelNCPTask>(
+ new SpinelNCPTaskGetNetworkTopology(
+ this,
+ cb,
+ SpinelNCPTaskGetNetworkTopology::kChildTable,
+ SpinelNCPTaskGetNetworkTopology::kResultFormat_StringArray
+ )
+ ));
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_ThreadChildTableAsValMap)) {
+ start_new_task(boost::shared_ptr<SpinelNCPTask>(
+ new SpinelNCPTaskGetNetworkTopology(
+ this,
+ cb,
+ SpinelNCPTaskGetNetworkTopology::kChildTable,
+ SpinelNCPTaskGetNetworkTopology::kResultFormat_ValueMapArray
+ )
+ ));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_ThreadNeighborTable)) {
+ start_new_task(boost::shared_ptr<SpinelNCPTask>(
+ new SpinelNCPTaskGetNetworkTopology(
+ this,
+ cb,
+ SpinelNCPTaskGetNetworkTopology::kNeighborTable,
+ SpinelNCPTaskGetNetworkTopology::kResultFormat_StringArray
+ )
+ ));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_ThreadNeighborTableAsValMap)) {
+ start_new_task(boost::shared_ptr<SpinelNCPTask>(
+ new SpinelNCPTaskGetNetworkTopology(
+ this,
+ cb,
+ SpinelNCPTaskGetNetworkTopology::kNeighborTable,
+ SpinelNCPTaskGetNetworkTopology::kResultFormat_ValueMapArray
+ )
+ ));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_OpenThreadMsgBufferCounters)) {
+ start_new_task(boost::shared_ptr<SpinelNCPTask>(
+ new SpinelNCPTaskGetMsgBufferCounters(
+ this,
+ cb,
+ SpinelNCPTaskGetMsgBufferCounters::kResultFormat_StringArray
+ )
+ ));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_OpenThreadMsgBufferCountersAsString)) {
+ start_new_task(boost::shared_ptr<SpinelNCPTask>(
+ new SpinelNCPTaskGetMsgBufferCounters(
+ this,
+ cb,
+ SpinelNCPTaskGetMsgBufferCounters::kResultFormat_String
+ )
+ ));
+
+ } else if (strncaseequal(key.c_str(), kWPANTUNDProperty_Spinel_CounterPrefix, sizeof(kWPANTUNDProperty_Spinel_CounterPrefix)-1)) {
+ int cntr_key = 0;
+
+#define CNTR_KEY(x) \
+ else if (strcaseequal(key.c_str()+sizeof(kWPANTUNDProperty_Spinel_CounterPrefix)-1, # x)) { \
+ cntr_key = SPINEL_PROP_CNTR_ ## x; \
+ }
+
+ // Check to see if the counter name is an integer.
+ cntr_key = (int)strtol(key.c_str()+(int)sizeof(kWPANTUNDProperty_Spinel_CounterPrefix)-1, NULL, 0);
+
+ if ( (cntr_key > 0)
+ && (cntr_key < SPINEL_PROP_CNTR__END-SPINEL_PROP_CNTR__BEGIN)
+ ) {
+ // Counter name was a valid integer. Let's use it.
+ cntr_key += SPINEL_PROP_CNTR__BEGIN;
+ }
+
+ CNTR_KEY(TX_PKT_TOTAL)
+ CNTR_KEY(TX_PKT_UNICAST)
+ CNTR_KEY(TX_PKT_BROADCAST)
+ CNTR_KEY(TX_PKT_ACK_REQ)
+ CNTR_KEY(TX_PKT_ACKED)
+ CNTR_KEY(TX_PKT_NO_ACK_REQ)
+ CNTR_KEY(TX_PKT_DATA)
+ CNTR_KEY(TX_PKT_DATA_POLL)
+ CNTR_KEY(TX_PKT_BEACON)
+ CNTR_KEY(TX_PKT_BEACON_REQ)
+ CNTR_KEY(TX_PKT_OTHER)
+ CNTR_KEY(TX_PKT_RETRY)
+ CNTR_KEY(TX_ERR_CCA)
+ CNTR_KEY(TX_ERR_ABORT)
+ CNTR_KEY(RX_PKT_TOTAL)
+ CNTR_KEY(RX_PKT_UNICAST)
+ CNTR_KEY(RX_PKT_BROADCAST)
+ CNTR_KEY(RX_PKT_DATA)
+ CNTR_KEY(RX_PKT_DATA_POLL)
+ CNTR_KEY(RX_PKT_BEACON)
+ CNTR_KEY(RX_PKT_BEACON_REQ)
+ CNTR_KEY(RX_PKT_OTHER)
+ CNTR_KEY(RX_PKT_FILT_WL)
+ CNTR_KEY(RX_PKT_FILT_DA)
+ CNTR_KEY(RX_ERR_EMPTY)
+ CNTR_KEY(RX_ERR_UKWN_NBR)
+ CNTR_KEY(RX_ERR_NVLD_SADDR)
+ CNTR_KEY(RX_ERR_SECURITY)
+ CNTR_KEY(RX_ERR_BAD_FCS)
+ CNTR_KEY(RX_ERR_OTHER)
+ CNTR_KEY(TX_IP_SEC_TOTAL)
+ CNTR_KEY(TX_IP_INSEC_TOTAL)
+ CNTR_KEY(TX_IP_DROPPED)
+ CNTR_KEY(RX_IP_SEC_TOTAL)
+ CNTR_KEY(RX_IP_INSEC_TOTAL)
+ CNTR_KEY(RX_IP_DROPPED)
+ CNTR_KEY(TX_SPINEL_TOTAL)
+ CNTR_KEY(RX_SPINEL_TOTAL)
+ CNTR_KEY(RX_SPINEL_ERR)
+
+#undef CNTR_KEY
+
+ if (cntr_key != 0) {
+ SIMPLE_SPINEL_GET(cntr_key, SPINEL_DATATYPE_UINT32_S);
+ } else {
+ NCPInstanceBase::get_property(key, cb);
+ }
+ } else {
+ NCPInstanceBase::get_property(key, cb);
+ }
+}
+
+void
+SpinelNCPInstance::set_property(
+ const std::string& key,
+ const boost::any& value,
+ CallbackWithStatus cb
+) {
+ syslog(LOG_INFO, "set_property: key: \"%s\"", key.c_str());
+
+ // If we are disabled, then the only property we
+ // are allowed to set is kWPANTUNDProperty_DaemonEnabled.
+ if (!mEnabled && !strcaseequal(key.c_str(), kWPANTUNDProperty_DaemonEnabled)) {
+ cb(kWPANTUNDStatus_InvalidWhenDisabled);
+ return;
+ }
+
+ try {
+ if (strcaseequal(key.c_str(), kWPANTUNDProperty_NCPChannel)) {
+ int channel = any_to_int(value);
+ mCurrentNetworkInstance.channel = channel;
+
+ start_new_task(SpinelNCPTaskSendCommand::Factory(this)
+ .set_callback(cb)
+ .add_command(
+ SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT8_S), SPINEL_PROP_PHY_CHAN, channel)
+ )
+ .finish()
+ );
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NCPCCAThreshold)) {
+ int cca = any_to_int(value);
+ Data command = SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_INT8_S), SPINEL_PROP_PHY_CCA_THRESHOLD, cca);
+
+ mSettings[kWPANTUNDProperty_NCPCCAThreshold] = SettingsEntry(command);
+
+ start_new_task(SpinelNCPTaskSendCommand::Factory(this)
+ .set_callback(cb)
+ .add_command(command)
+ .finish()
+ );
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NetworkPANID)) {
+ uint16_t panid = any_to_int(value);
+
+ start_new_task(SpinelNCPTaskSendCommand::Factory(this)
+ .set_callback(cb)
+ .add_command(
+ SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT16_S), SPINEL_PROP_MAC_15_4_PANID, panid)
+ )
+ .finish()
+ );
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NetworkKey)) {
+ Data network_key = any_to_data(value);
+
+ if (!ncp_state_is_joining_or_joined(get_ncp_state())) {
+ mNetworkKey = network_key;
+ if (mNetworkKeyIndex == 0) {
+ mNetworkKeyIndex = 1;
+ }
+ }
+
+ if (get_ncp_state() == CREDENTIALS_NEEDED) {
+ ValueMap options;
+ options[kWPANTUNDProperty_NetworkKey] = value;
+ start_new_task(boost::shared_ptr<SpinelNCPTask>(
+ new SpinelNCPTaskJoin(
+ this,
+ boost::bind(cb,_1),
+ options
+ )
+ ));
+ } else {
+ start_new_task(SpinelNCPTaskSendCommand::Factory(this)
+ .set_callback(cb)
+ .add_command(
+ SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_DATA_S), SPINEL_PROP_NET_MASTER_KEY, network_key.data(), network_key.size())
+ )
+ .finish()
+ );
+ }
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NCPMACAddress)) {
+ Data eui64_value = any_to_data(value);
+
+ if (eui64_value.size() == sizeof(spinel_eui64_t)) {
+ start_new_task(SpinelNCPTaskSendCommand::Factory(this)
+ .set_callback(cb)
+ .add_command(
+ SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_EUI64_S),
+ SPINEL_PROP_MAC_15_4_LADDR,
+ eui64_value.data()
+ )
+ )
+ .finish()
+ );
+
+ } else {
+ cb(kWPANTUNDStatus_InvalidArgument);
+ }
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NCPExtendedAddress)) {
+ Data eui64_value = any_to_data(value);
+
+ if (eui64_value.size() == sizeof(spinel_eui64_t)) {
+ start_new_task(SpinelNCPTaskSendCommand::Factory(this)
+ .set_callback(cb)
+ .add_command(
+ SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_EUI64_S),
+ SPINEL_PROP_MAC_EXTENDED_ADDR,
+ eui64_value.data()
+ )
+ )
+ .finish()
+ );
+
+ } else {
+ cb(kWPANTUNDStatus_InvalidArgument);
+ }
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NetworkXPANID)) {
+ Data xpanid = any_to_data(value);
+
+ start_new_task(SpinelNCPTaskSendCommand::Factory(this)
+ .set_callback(cb)
+ .add_command(
+ SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_DATA_S), SPINEL_PROP_NET_XPANID, xpanid.data(), xpanid.size())
+ )
+ .finish()
+ );
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NetworkKey)) {
+ Data network_key = any_to_data(value);
+
+ start_new_task(SpinelNCPTaskSendCommand::Factory(this)
+ .set_callback(cb)
+ .add_command(
+ SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_DATA_S), SPINEL_PROP_NET_MASTER_KEY, network_key.data(), network_key.size())
+ )
+ .finish()
+ );
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NetworkKeyIndex)) {
+ uint32_t key_index = any_to_int(value);
+
+ start_new_task(SpinelNCPTaskSendCommand::Factory(this)
+ .set_callback(cb)
+ .add_command(
+ SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT32_S), SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER, key_index)
+ )
+ .finish()
+ );
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NetworkName)) {
+ std::string str = any_to_string(value);
+
+ start_new_task(SpinelNCPTaskSendCommand::Factory(this)
+ .set_callback(cb)
+ .add_command(SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UTF8_S), SPINEL_PROP_NET_NETWORK_NAME, str.c_str()))
+ .finish()
+ );
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_ThreadPreferredRouterID)) {
+ uint8_t routerId = any_to_int(value);
+
+ start_new_task(SpinelNCPTaskSendCommand::Factory(this)
+ .set_callback(cb)
+ .add_command(
+ SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT8_S), SPINEL_PROP_THREAD_PREFERRED_ROUTER_ID, routerId)
+ )
+ .finish()
+ );
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_JamDetectionEnable)) {
+ bool isEnabled = any_to_bool(value);
+ Data command = SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_BOOL_S), SPINEL_PROP_JAM_DETECT_ENABLE, isEnabled);
+
+ mSettings[kWPANTUNDProperty_JamDetectionEnable] = SettingsEntry(command, SPINEL_CAP_JAM_DETECT);
+
+ if (!mCapabilities.count(SPINEL_CAP_JAM_DETECT))
+ {
+ cb(kWPANTUNDStatus_FeatureNotSupported);
+ } else {
+ start_new_task(SpinelNCPTaskSendCommand::Factory(this)
+ .set_callback(cb)
+ .add_command(command)
+ .finish()
+ );
+ }
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_JamDetectionRssiThreshold)) {
+ int8_t rssiThreshold = static_cast<int8_t>(any_to_int(value));
+ Data command = SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_INT8_S), SPINEL_PROP_JAM_DETECT_RSSI_THRESHOLD, rssiThreshold);
+
+ mSettings[kWPANTUNDProperty_JamDetectionRssiThreshold] = SettingsEntry(command, SPINEL_CAP_JAM_DETECT);
+
+ if (!mCapabilities.count(SPINEL_CAP_JAM_DETECT))
+ {
+ cb(kWPANTUNDStatus_FeatureNotSupported);
+ } else {
+ start_new_task(SpinelNCPTaskSendCommand::Factory(this)
+ .set_callback(cb)
+ .add_command(command)
+ .finish()
+ );
+ }
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_JamDetectionWindow)) {
+ uint8_t window = static_cast<uint8_t>(any_to_int(value));
+ Data command = SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT8_S), SPINEL_PROP_JAM_DETECT_WINDOW, window);
+
+ mSettings[kWPANTUNDProperty_JamDetectionWindow] = SettingsEntry(command, SPINEL_CAP_JAM_DETECT);
+
+ if (!mCapabilities.count(SPINEL_CAP_JAM_DETECT))
+ {
+ cb(kWPANTUNDStatus_FeatureNotSupported);
+ } else {
+ start_new_task(SpinelNCPTaskSendCommand::Factory(this)
+ .set_callback(cb)
+ .add_command(command)
+ .finish()
+ );
+ }
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_JamDetectionBusyPeriod)) {
+ uint8_t busyPeriod = static_cast<uint8_t>(any_to_int(value));
+ Data command = SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT8_S), SPINEL_PROP_JAM_DETECT_BUSY, busyPeriod);
+
+ mSettings[kWPANTUNDProperty_JamDetectionBusyPeriod] = SettingsEntry(command, SPINEL_CAP_JAM_DETECT);
+
+ if (!mCapabilities.count(SPINEL_CAP_JAM_DETECT))
+ {
+ cb(kWPANTUNDStatus_FeatureNotSupported);
+ } else {
+ start_new_task(SpinelNCPTaskSendCommand::Factory(this)
+ .set_callback(cb)
+ .add_command(command)
+ .finish()
+ );
+ }
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NestLabs_LegacyMeshLocalPrefix)) {
+ Data legacy_prefix = any_to_data(value);
+ Data command =
+ SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_DATA_S),
+ SPINEL_PROP_NEST_LEGACY_ULA_PREFIX,
+ legacy_prefix.data(),
+ legacy_prefix.size()
+ );
+
+ mSettings[kWPANTUNDProperty_NestLabs_LegacyMeshLocalPrefix] = SettingsEntry(command, SPINEL_CAP_NEST_LEGACY_INTERFACE);
+
+ if (!mCapabilities.count(SPINEL_CAP_NEST_LEGACY_INTERFACE))
+ {
+ cb(kWPANTUNDStatus_FeatureNotSupported);
+ } else {
+ start_new_task(SpinelNCPTaskSendCommand::Factory(this)
+ .set_callback(cb)
+ .add_command(command)
+ .finish()
+ );
+ }
+
+ } else {
+ NCPInstanceBase::set_property(key, value, cb);
+ }
+
+ } catch (const boost::bad_any_cast &x) {
+ // We will get a bad_any_cast exception if the property is of
+ // the wrong type.
+ syslog(LOG_ERR,"set_property: Bad type for property \"%s\" (%s)", key.c_str(), x.what());
+ cb(kWPANTUNDStatus_InvalidArgument);
+ } catch (const std::invalid_argument &x) {
+ // We will get a bad_any_cast exception if the property is of
+ // the wrong type.
+ syslog(LOG_ERR,"set_property: Invalid argument for property \"%s\" (%s)", key.c_str(), x.what());
+ cb(kWPANTUNDStatus_InvalidArgument);
+ }
+
+}
+
+void
+SpinelNCPInstance::reset_tasks(wpantund_status_t status)
+{
+ NCPInstanceBase::reset_tasks(status);
+ while(!mTaskQueue.empty()) {
+ mTaskQueue.front()->finish(status);
+ mTaskQueue.pop_front();
+ }
+}
+
+void
+SpinelNCPInstance::handle_ncp_spinel_value_is(spinel_prop_key_t key, const uint8_t* value_data_ptr, spinel_size_t value_data_len)
+{
+ const uint8_t *original_value_data_ptr = value_data_ptr;
+ spinel_size_t original_value_data_len = value_data_len;
+
+ if (key == SPINEL_PROP_LAST_STATUS) {
+ spinel_status_t status = SPINEL_STATUS_OK;
+ spinel_datatype_unpack(value_data_ptr, value_data_len, "i", &status);
+ syslog(LOG_INFO,"[-NCP-]: Last status (%s, %d)", spinel_status_to_cstr(status), status);
+ if ((status >= SPINEL_STATUS_RESET__BEGIN) && (status <= SPINEL_STATUS_RESET__END)) {
+ syslog(LOG_NOTICE, "[-NCP-]: NCP was reset (%s, %d)", spinel_status_to_cstr(status), status);
+ process_event(EVENT_NCP_RESET, status);
+ if (!mResetIsExpected && (mDriverState == NORMAL_OPERATION)) {
+ wpantund_status_t wstatus = kWPANTUNDStatus_NCP_Reset;
+ switch(status) {
+ case SPINEL_STATUS_RESET_CRASH:
+ case SPINEL_STATUS_RESET_FAULT:
+ case SPINEL_STATUS_RESET_ASSERT:
+ case SPINEL_STATUS_RESET_WATCHDOG:
+ case SPINEL_STATUS_RESET_OTHER:
+ wstatus = kWPANTUNDStatus_NCP_Crashed;
+ break;
+ default:
+ break;
+ }
+ reset_tasks(wstatus);
+ }
+
+ if (mDriverState == NORMAL_OPERATION) {
+ reinitialize_ncp();
+ }
+ mResetIsExpected = false;
+ return;
+
+ } else if (status == SPINEL_STATUS_NOMEM) {
+ cms_t now = time_ms();
+ if (now - mLastTimeNoMemStatus > kMaxTimeBetweenNoMemStatus) {
+ mNoMemStatusCounter = 0;
+ }
+ mLastTimeNoMemStatus = now;
+ mNoMemStatusCounter++;
+
+ if (mNoMemStatusCounter == kMaxNonMemCountToReset)
+ {
+ mNoMemStatusCounter = 0;
+ syslog(LOG_WARNING, "NCP is out of memory for too long...Resetting the NCP!");
+ ncp_is_misbehaving();
+ return;
+ }
+ } else if (status == SPINEL_STATUS_INVALID_COMMAND) {
+ syslog(LOG_NOTICE, "[-NCP-]: COMMAND NOT RECOGNIZED");
+ }
+ } else if (key == SPINEL_PROP_NCP_VERSION) {
+ const char* ncp_version = NULL;
+ spinel_datatype_unpack(value_data_ptr, value_data_len, "U", &ncp_version);
+
+ set_ncp_version_string(ncp_version);
+
+
+ } else if (key == SPINEL_PROP_INTERFACE_TYPE) {
+ unsigned int interface_type = 0;
+ spinel_datatype_unpack(value_data_ptr, value_data_len, "i", &interface_type);
+
+ if (interface_type != SPINEL_PROTOCOL_TYPE_THREAD) {
+ syslog(LOG_CRIT, "[-NCP-]: NCP is using unsupported protocol type (%d)", interface_type);
+ change_ncp_state(FAULT);
+ }
+
+
+ } else if (key == SPINEL_PROP_PROTOCOL_VERSION) {
+ unsigned int protocol_version_major = 0;
+ unsigned int protocol_version_minor = 0;
+ spinel_datatype_unpack(value_data_ptr, value_data_len, "ii", &protocol_version_major, &protocol_version_minor);
+
+ if (protocol_version_major != SPINEL_PROTOCOL_VERSION_THREAD_MAJOR) {
+ syslog(LOG_CRIT, "[-NCP-]: NCP is using unsupported protocol version (NCP:%d, wpantund:%d)", protocol_version_major, SPINEL_PROTOCOL_VERSION_THREAD_MAJOR);
+ change_ncp_state(FAULT);
+ }
+
+ if (protocol_version_minor != SPINEL_PROTOCOL_VERSION_THREAD_MINOR) {
+ syslog(LOG_WARNING, "[-NCP-]: NCP is using different protocol minor version (NCP:%d, wpantund:%d)", protocol_version_minor, SPINEL_PROTOCOL_VERSION_THREAD_MINOR);
+ }
+
+ } else if (key == SPINEL_PROP_CAPS) {
+ const uint8_t* data_ptr = value_data_ptr;
+ spinel_size_t data_len = value_data_len;
+ std::set<unsigned int> capabilities;
+
+ while(data_len != 0) {
+ unsigned int value = 0;
+ spinel_ssize_t parse_len = spinel_datatype_unpack(data_ptr, data_len, SPINEL_DATATYPE_UINT_PACKED_S, &value);
+ if (parse_len <= 0) {
+ syslog(LOG_WARNING, "[-NCP-]: Capability Parse failure");
+ break;
+ }
+ capabilities.insert(value);
+
+ data_ptr += parse_len;
+ data_len -= parse_len;
+ }
+
+ if (capabilities != mCapabilities) {
+ mCapabilities = capabilities;
+ }
+
+ } else if (key == SPINEL_PROP_NET_NETWORK_NAME) {
+ const char* value = NULL;
+ spinel_datatype_unpack(value_data_ptr, value_data_len, "U", &value);
+ if (value && (mCurrentNetworkInstance.name != value)) {
+ mCurrentNetworkInstance.name = value;
+ signal_property_changed(kWPANTUNDProperty_NetworkName, mCurrentNetworkInstance.name);
+ }
+
+ } else if (key == SPINEL_PROP_IPV6_LL_ADDR) {
+ struct in6_addr *addr = NULL;
+ spinel_datatype_unpack(value_data_ptr, value_data_len, "6", &addr);
+ if ( NULL != addr
+ && (0 != memcmp(mNCPLinkLocalAddress.s6_addr, addr->s6_addr, sizeof(mNCPLinkLocalAddress)))
+ ) {
+ if (IN6_IS_ADDR_LINKLOCAL(&mNCPLinkLocalAddress)) {
+ remove_address(mNCPLinkLocalAddress);
+ }
+
+ memcpy((void*)mNCPLinkLocalAddress.s6_addr, (void*)addr->s6_addr, sizeof(mNCPLinkLocalAddress));
+
+ if (IN6_IS_ADDR_LINKLOCAL(&mNCPLinkLocalAddress)) {
+ add_address(mNCPLinkLocalAddress);
+ }
+
+ signal_property_changed(kWPANTUNDProperty_IPv6LinkLocalAddress, in6_addr_to_string(*addr));
+ }
+
+ } else if (key == SPINEL_PROP_IPV6_ML_ADDR) {
+ struct in6_addr *addr = NULL;
+ spinel_datatype_unpack(value_data_ptr, value_data_len, "6", &addr);
+ if (addr
+ && buffer_is_nonzero(addr->s6_addr, 8)
+ && (0 != memcmp(mNCPMeshLocalAddress.s6_addr, addr->s6_addr, sizeof(mNCPMeshLocalAddress)))
+ ) {
+ if (buffer_is_nonzero(mNCPMeshLocalAddress.s6_addr, sizeof(mNCPMeshLocalAddress))) {
+ remove_address(mNCPMeshLocalAddress);
+ }
+ memcpy((void*)mNCPMeshLocalAddress.s6_addr, (void*)addr->s6_addr, sizeof(mNCPMeshLocalAddress));
+ signal_property_changed(kWPANTUNDProperty_IPv6MeshLocalAddress, in6_addr_to_string(*addr));
+ add_address(mNCPMeshLocalAddress);
+ }
+
+ } else if (key == SPINEL_PROP_IPV6_ML_PREFIX) {
+ struct in6_addr *addr = NULL;
+ spinel_datatype_unpack(value_data_ptr, value_data_len, "6", &addr);
+ if (addr
+ && buffer_is_nonzero(addr->s6_addr, 8)
+ && (0 != memcmp(mNCPV6Prefix, addr, sizeof(mNCPV6Prefix)))
+ ) {
+ if (buffer_is_nonzero(mNCPMeshLocalAddress.s6_addr, sizeof(mNCPMeshLocalAddress))) {
+ remove_address(mNCPMeshLocalAddress);
+ }
+ memcpy((void*)mNCPV6Prefix, (void*)addr, sizeof(mNCPV6Prefix));
+ struct in6_addr prefix_addr (mNCPMeshLocalAddress);
+ // Zero out the lower 64 bits.
+ memset(prefix_addr.s6_addr+8, 0, 8);
+ signal_property_changed(kWPANTUNDProperty_IPv6MeshLocalPrefix, in6_addr_to_string(prefix_addr) + "/64");
+ }
+
+ } else if (key == SPINEL_PROP_IPV6_ADDRESS_TABLE) {
+ std::map<struct in6_addr, GlobalAddressEntry>::const_iterator iter;
+ std::map<struct in6_addr, GlobalAddressEntry> global_addresses(mGlobalAddresses);
+
+ while (value_data_len > 0) {
+ const uint8_t *entry_ptr = NULL;
+ spinel_size_t entry_len = 0;
+ spinel_ssize_t len = 0;
+ len = spinel_datatype_unpack(value_data_ptr, value_data_len, "D.", &entry_ptr, &entry_len);
+ if (len < 1) {
+ break;
+ }
+ global_addresses.erase(*reinterpret_cast<const struct in6_addr*>(entry_ptr));
+ handle_ncp_spinel_value_inserted(key, entry_ptr, entry_len);
+
+ value_data_ptr += len;
+ value_data_len -= len;
+ }
+
+ // Since this was the whole list, we need
+ // to remove the addresses that weren't in
+ // the list.
+ for (iter = global_addresses.begin(); iter!= global_addresses.end(); ++iter) {
+ if (!iter->second.mUserAdded) {
+ remove_address(iter->first);
+ }
+ }
+
+ } else if (key == SPINEL_PROP_HWADDR) {
+ nl::Data hwaddr(value_data_ptr, value_data_len);
+ if (value_data_len == sizeof(mMACHardwareAddress)) {
+ set_mac_hardware_address(value_data_ptr);
+ }
+
+ } else if (key == SPINEL_PROP_MAC_15_4_LADDR) {
+ nl::Data hwaddr(value_data_ptr, value_data_len);
+ if (value_data_len == sizeof(mMACAddress)) {
+ set_mac_address(value_data_ptr);
+ }
+
+ } else if (key == SPINEL_PROP_MAC_15_4_PANID) {
+ uint16_t panid;
+ spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_UINT16_S, &panid);
+ if (panid != mCurrentNetworkInstance.panid) {
+ mCurrentNetworkInstance.panid = panid;
+ signal_property_changed(kWPANTUNDProperty_NetworkPANID, panid);
+ }
+
+ } else if (key == SPINEL_PROP_NET_XPANID) {
+ nl::Data xpanid(value_data_ptr, value_data_len);
+ if ((value_data_len == 8) && 0 != memcmp(xpanid.data(), mCurrentNetworkInstance.xpanid, 8)) {
+ memcpy(mCurrentNetworkInstance.xpanid, xpanid.data(), 8);
+ signal_property_changed(kWPANTUNDProperty_NetworkXPANID, xpanid);
+ }
+
+ } else if (key == SPINEL_PROP_NET_MASTER_KEY) {
+ nl::Data network_key(value_data_ptr, value_data_len);
+ if (ncp_state_is_joining_or_joined(get_ncp_state())) {
+ if (network_key != mNetworkKey) {
+ mNetworkKey = network_key;
+ signal_property_changed(kWPANTUNDProperty_NetworkKey, mNetworkKey);
+ }
+ }
+
+ } else if (key == SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER) {
+ uint32_t network_key_index;
+ spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_UINT32_S, &network_key_index);
+ if (network_key_index != mNetworkKeyIndex) {
+ mNetworkKeyIndex = network_key_index;
+ signal_property_changed(kWPANTUNDProperty_NetworkKeyIndex, mNetworkKeyIndex);
+ }
+
+ } else if (key == SPINEL_PROP_PHY_CHAN) {
+ unsigned int value;
+ spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_UINT_PACKED_S, &value);
+ if (value != mCurrentNetworkInstance.channel) {
+ mCurrentNetworkInstance.channel = value;
+ signal_property_changed(kWPANTUNDProperty_NCPChannel, mCurrentNetworkInstance.channel);
+ }
+
+ } else if (key == SPINEL_PROP_PHY_CHAN_SUPPORTED) {
+
+ uint8_t channel;
+ spinel_ssize_t len = 0;
+
+ mSupprotedChannels.clear();
+
+ while (value_data_len > 0)
+ {
+ len = spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_UINT8_S, &channel);
+ mSupprotedChannels.insert(channel);
+
+ value_data_ptr += len;
+ value_data_len -= len;
+ }
+
+ } else if (key == SPINEL_PROP_PHY_TX_POWER) {
+ int8_t value;
+ spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_INT8_S, &value);
+ if (value != mTXPower) {
+ mTXPower = value;
+ signal_property_changed(kWPANTUNDProperty_NCPTXPower, mTXPower);
+ }
+
+ } else if (key == SPINEL_PROP_STREAM_DEBUG) {
+ handle_ncp_log(value_data_ptr, value_data_len);
+
+ } else if (key == SPINEL_PROP_NET_ROLE) {
+ uint8_t value;
+ spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_UINT8_S, &value);
+ syslog(LOG_INFO,"[-NCP-]: Net Role \"%s\" (%d)", spinel_net_role_to_cstr(value), value);
+
+ if ( ncp_state_is_joining(get_ncp_state())
+ && (value != SPINEL_NET_ROLE_DETACHED)
+ ) {
+ change_ncp_state(ASSOCIATED);
+ }
+
+ if (value == SPINEL_NET_ROLE_CHILD) {
+ if (mNodeType != END_DEVICE) {
+ mNodeType = END_DEVICE;
+ signal_property_changed(kWPANTUNDProperty_NetworkNodeType, node_type_to_string(mNodeType));
+ }
+
+ } else if (value == SPINEL_NET_ROLE_ROUTER) {
+ if (mNodeType != ROUTER) {
+ mNodeType = ROUTER;
+ signal_property_changed(kWPANTUNDProperty_NetworkNodeType, node_type_to_string(mNodeType));
+ }
+
+ } else if (value == SPINEL_NET_ROLE_LEADER) {
+ if (mNodeType != LEADER) {
+ mNodeType = LEADER;
+ signal_property_changed(kWPANTUNDProperty_NetworkNodeType, node_type_to_string(mNodeType));
+ }
+
+ } else if (value == SPINEL_NET_ROLE_DETACHED) {
+ if (ncp_state_is_associated(get_ncp_state())) {
+ change_ncp_state(ISOLATED);
+ }
+ }
+
+ } else if (key == SPINEL_PROP_NET_STACK_UP) {
+ bool is_stack_up;
+ spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_BOOL_S, &is_stack_up);
+
+ if (is_stack_up) {
+ if (!ncp_state_is_joining_or_joined(get_ncp_state())) {
+ change_ncp_state(ASSOCIATING);
+ }
+ } else {
+ if (!ncp_state_is_joining(get_ncp_state())) {
+ change_ncp_state(OFFLINE);
+ }
+ }
+
+ } else if (key == SPINEL_PROP_NET_IF_UP) {
+ bool is_if_up;
+ spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_BOOL_S, &is_if_up);
+
+ if (ncp_state_is_interface_up(get_ncp_state()) && !is_if_up) {
+ change_ncp_state(OFFLINE);
+ }
+
+ } else if (key == SPINEL_PROP_THREAD_ON_MESH_NETS) {
+ while (value_data_len > 0) {
+ spinel_ssize_t len = 0;
+ struct in6_addr *addr = NULL;
+ uint8_t prefix_len = 0;
+ bool stable;
+ uint8_t flags = 0;
+
+ len = spinel_datatype_unpack(
+ value_data_ptr,
+ value_data_len,
+ "T(6CbC).",
+ &addr,
+ &prefix_len,
+ &stable,
+ &flags
+ );
+
+ if (len < 1) {
+ break;
+ }
+
+ refresh_on_mesh_prefix(addr, prefix_len, stable, flags);
+
+ value_data_ptr += len;
+ value_data_len -= len;
+ }
+
+ } else if (key == SPINEL_PROP_THREAD_ASSISTING_PORTS) {
+ bool is_assisting = (value_data_len != 0);
+ uint16_t assisting_port(0);
+
+ if (is_assisting != get_current_network_instance().joinable) {
+ mCurrentNetworkInstance.joinable = is_assisting;
+ signal_property_changed(kWPANTUNDProperty_NestLabs_NetworkAllowingJoin, is_assisting);
+ }
+
+ if (is_assisting) {
+ int i;
+ syslog(LOG_NOTICE, "Network is joinable");
+ while (value_data_len > 0) {
+ i = spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_UINT16_S, &assisting_port);
+ if (i <= 0) {
+ break;
+ }
+ syslog(LOG_NOTICE, "Assisting on port %d", assisting_port);
+ value_data_ptr += i;
+ value_data_len -= i;
+ }
+ } else {
+ syslog(LOG_NOTICE, "Network is not joinable");
+ }
+
+ } else if (key == SPINEL_PROP_JAM_DETECTED) {
+ bool jamDetected = false;
+
+ spinel_datatype_unpack(value_data_ptr, value_data_len, SPINEL_DATATYPE_BOOL_S, &jamDetected);
+ signal_property_changed(kWPANTUNDProperty_JamDetectionStatus, jamDetected);
+
+ if (jamDetected) {
+ syslog(LOG_NOTICE, "Signal jamming is detected");
+ } else {
+ syslog(LOG_NOTICE, "Signal jamming cleared");
+ }
+
+ } else if (key == SPINEL_PROP_STREAM_RAW) {
+ if (mPcapManager.is_enabled()) {
+ const uint8_t* frame_ptr(NULL);
+ unsigned int frame_len(0);
+ const uint8_t* meta_ptr(NULL);
+ unsigned int meta_len(0);
+ spinel_ssize_t ret;
+ PcapPacket packet;
+ uint16_t flags = 0;
+
+ packet.set_timestamp().set_dlt(PCAP_DLT_IEEE802_15_4);
+
+ // Unpack the packet.
+ ret = spinel_datatype_unpack(
+ value_data_ptr,
+ value_data_len,
+ SPINEL_DATATYPE_DATA_S SPINEL_DATATYPE_DATA_S,
+ &frame_ptr,
+ &frame_len,
+ &meta_ptr,
+ &meta_len
+ );
+
+ require(ret > 0, bail);
+
+ // Unpack the metadata.
+ ret = spinel_datatype_unpack(
+ meta_ptr,
+ meta_len,
+ SPINEL_DATATYPE_INT8_S // RSSI/TXPower
+ SPINEL_DATATYPE_INT8_S // Noise Floor
+ SPINEL_DATATYPE_UINT16_S, // Flags
+ NULL, // Ignore RSSI/TXPower
+ NULL, // Ignore Noise Floor
+ &flags
+ );
+
+ __ASSERT_MACROS_check(ret > 0);
+
+ if ((flags & SPINEL_MD_FLAG_TX) == SPINEL_MD_FLAG_TX)
+ {
+ // Ignore FCS for transmitted packets
+ frame_len -= 2;
+ packet.set_dlt(PCAP_DLT_IEEE802_15_4_NOFCS);
+ }
+
+ mPcapManager.push_packet(
+ packet
+ .append_ppi_field(PCAP_PPI_TYPE_SPINEL, meta_ptr, meta_len)
+ .append_payload(frame_ptr, frame_len)
+ );
+ }
+
+ } else if ((key == SPINEL_PROP_STREAM_NET) || (key == SPINEL_PROP_STREAM_NET_INSECURE)) {
+ const uint8_t* frame_ptr(NULL);
+ unsigned int frame_len(0);
+ spinel_ssize_t ret;
+ uint8_t frame_data_type = FRAME_TYPE_DATA;
+
+ if (SPINEL_PROP_STREAM_NET_INSECURE == key) {
+ frame_data_type = FRAME_TYPE_INSECURE_DATA;
+ }
+
+ ret = spinel_datatype_unpack(
+ value_data_ptr,
+ value_data_len,
+ SPINEL_DATATYPE_DATA_S SPINEL_DATATYPE_DATA_S,
+ &frame_ptr,
+ &frame_len,
+ NULL,
+ NULL
+ );
+
+ __ASSERT_MACROS_check(ret > 0);
+
+ // Analyze the packet to determine if it should be dropped.
+ if ((ret > 0) && should_forward_hostbound_frame(&frame_data_type, frame_ptr, frame_len)) {
+ if (static_cast<bool>(mLegacyInterface) && (frame_data_type == FRAME_TYPE_LEGACY_DATA)) {
+ handle_alt_ipv6_from_ncp(frame_ptr, frame_len);
+ } else {
+ handle_normal_ipv6_from_ncp(frame_ptr, frame_len);
+ }
+ }
+ } else if (key == SPINEL_PROP_THREAD_CHILD_TABLE) {
+ SpinelNCPTaskGetNetworkTopology::Table child_table;
+ SpinelNCPTaskGetNetworkTopology::Table::iterator it;
+
+ SpinelNCPTaskGetNetworkTopology::prase_child_table(value_data_ptr, value_data_len, child_table);
+
+ for (it = child_table.begin(); it != child_table.end(); it++)
+ {
+ syslog(LOG_INFO, "[-NCP-] Child: %s", it->get_as_string().c_str());
+ }
+ } else if (key == SPINEL_PROP_THREAD_LEADER_NETWORK_DATA) {
+ char net_data_cstr_buf[540];
+ encode_data_into_string(value_data_ptr, value_data_len, net_data_cstr_buf, sizeof(net_data_cstr_buf), 0);
+ syslog(LOG_INFO, "[-NCP-] Leader network data: %s", net_data_cstr_buf);
+ }
+
+bail:
+ process_event(EVENT_NCP_PROP_VALUE_IS, key, original_value_data_ptr, original_value_data_len);
+}
+
+void
+SpinelNCPInstance::refresh_on_mesh_prefix(struct in6_addr *prefix, uint8_t prefix_len, bool stable, uint8_t flags)
+{
+ if ( ((flags & (SPINEL_NET_FLAG_ON_MESH | SPINEL_NET_FLAG_SLAAC)) == (SPINEL_NET_FLAG_ON_MESH | SPINEL_NET_FLAG_SLAAC))
+ && !lookup_address_for_prefix(NULL, *prefix, prefix_len)
+ ) {
+ SpinelNCPTaskSendCommand::Factory factory(this);
+ struct in6_addr addr = make_slaac_addr_from_eui64(prefix->s6_addr, mMACAddress);
+
+ syslog(LOG_NOTICE, "Pushing a new address %s/%d to the NCP", in6_addr_to_string(addr).c_str(), prefix_len);
+
+ factory.set_lock_property(SPINEL_PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE);
+
+ factory.add_command(
+ SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_INSERT(
+ SPINEL_DATATYPE_IPv6ADDR_S // Address
+ SPINEL_DATATYPE_UINT8_S // Prefix Length
+ SPINEL_DATATYPE_UINT32_S // Valid Lifetime
+ SPINEL_DATATYPE_UINT32_S // Preferred Lifetime
+ ),
+ SPINEL_PROP_IPV6_ADDRESS_TABLE,
+ &addr,
+ prefix_len,
+ UINT32_MAX,
+ UINT32_MAX
+ )
+ );
+
+ start_new_task(factory.finish());
+ }
+}
+
+void
+SpinelNCPInstance::handle_ncp_spinel_value_inserted(spinel_prop_key_t key, const uint8_t* value_data_ptr, spinel_size_t value_data_len)
+{
+ if (key == SPINEL_PROP_IPV6_ADDRESS_TABLE) {
+ struct in6_addr *addr = NULL;
+ uint8_t prefix_len = 0;
+ uint32_t valid_lifetime = 0xFFFFFFFF;
+ uint32_t preferred_lifetime = 0xFFFFFFFF;
+
+ spinel_datatype_unpack(value_data_ptr, value_data_len, "6CLL", &addr, &prefix_len, &valid_lifetime, &preferred_lifetime);
+
+ if (addr != NULL
+ && buffer_is_nonzero(addr->s6_addr, 8)
+ && !IN6_IS_ADDR_UNSPECIFIED(addr)
+ ) {
+ static const uint8_t rloc_bytes[] = {0x00,0x00,0x00,0xFF,0xFE,0x00};
+ if (IN6_IS_ADDR_LINKLOCAL(addr)) {
+ if (0 != memcmp(rloc_bytes, addr->s6_addr+8, sizeof(rloc_bytes))) {
+ handle_ncp_spinel_value_is(SPINEL_PROP_IPV6_LL_ADDR, addr->s6_addr, sizeof(*addr));
+ }
+ } else if (0 == memcmp(mNCPV6Prefix, addr, sizeof(mNCPV6Prefix))) {
+ if (0 != memcmp(rloc_bytes, addr->s6_addr+8, sizeof(rloc_bytes))) {
+ handle_ncp_spinel_value_is(SPINEL_PROP_IPV6_ML_ADDR, addr->s6_addr, sizeof(*addr));
+ }
+ } else {
+ add_address(*addr, 64, valid_lifetime, preferred_lifetime);
+ }
+ }
+ } else if (key == SPINEL_PROP_THREAD_ON_MESH_NETS) {
+ struct in6_addr *addr = NULL;
+ uint8_t prefix_len = 0;
+ bool stable;
+ uint8_t flags = 0;
+ static const char flag_lookup[] = "ppPSDCRM";
+
+ spinel_datatype_unpack(
+ value_data_ptr,
+ value_data_len,
+ "6CbC",
+ &addr,
+ &prefix_len,
+ &stable,
+ &flags
+ );
+
+ syslog(LOG_NOTICE, "On-Mesh Network Added: %s/%d flags:%s", in6_addr_to_string(*addr).c_str(), prefix_len, flags_to_string(flags, flag_lookup).c_str());
+
+ refresh_on_mesh_prefix(addr, prefix_len, stable, flags);
+ }
+
+ process_event(EVENT_NCP_PROP_VALUE_INSERTED, key, value_data_ptr, value_data_len);
+}
+
+void
+SpinelNCPInstance::handle_ncp_state_change(NCPState new_ncp_state, NCPState old_ncp_state)
+{
+ NCPInstanceBase::handle_ncp_state_change(new_ncp_state, old_ncp_state);
+
+ if ( ncp_state_is_joining_or_joined(old_ncp_state)
+ && (new_ncp_state == OFFLINE)
+ ) {
+ // Mark this as false so that if we are actually doing
+ // a pcap right now it will force the details to be updated
+ // on the NCP at the next run through the main loop. This
+ // allows us to go back to promiscuous-mode sniffing at
+ // disconnect
+ mIsPcapInProgress = false;
+ }
+
+ if (ncp_state_is_associated(new_ncp_state)
+ && !ncp_state_is_associated(old_ncp_state)
+ ) {
+ start_new_task(SpinelNCPTaskSendCommand::Factory(this)
+ .add_command(SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_GET, SPINEL_PROP_MAC_15_4_LADDR))
+ .add_command(SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_GET, SPINEL_PROP_IPV6_ML_ADDR))
+ .add_command(SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_GET, SPINEL_PROP_NET_XPANID))
+ .add_command(SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_GET, SPINEL_PROP_MAC_15_4_PANID))
+ .add_command(SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_GET, SPINEL_PROP_PHY_CHAN))
+ .finish()
+ );
+ } else if (ncp_state_is_joining(new_ncp_state)
+ && !ncp_state_is_joining(old_ncp_state)
+ ) {
+ if (!buffer_is_nonzero(mNCPV6Prefix, 8)) {
+ start_new_task(SpinelNCPTaskSendCommand::Factory(this)
+ .add_command(SpinelPackData(SPINEL_FRAME_PACK_CMD_PROP_VALUE_GET, SPINEL_PROP_IPV6_ML_PREFIX))
+ .finish()
+ );
+ }
+ }
+}
+
+void
+SpinelNCPInstance::handle_ncp_spinel_value_removed(spinel_prop_key_t key, const uint8_t* value_data_ptr, spinel_size_t value_data_len)
+{
+ process_event(EVENT_NCP_PROP_VALUE_REMOVED, key, value_data_ptr, value_data_len);
+}
+
+void
+SpinelNCPInstance::handle_ncp_spinel_callback(unsigned int command, const uint8_t* cmd_data_ptr, spinel_size_t cmd_data_len)
+{
+ switch (command) {
+ case SPINEL_CMD_PROP_VALUE_IS:
+ {
+ spinel_prop_key_t key;
+ uint8_t* value_data_ptr = NULL;
+ spinel_size_t value_data_len = 0;
+ spinel_ssize_t ret;
+
+ ret = spinel_datatype_unpack(cmd_data_ptr, cmd_data_len, "CiiD", NULL, NULL, &key, &value_data_ptr, &value_data_len);
+
+ __ASSERT_MACROS_check(ret != -1);
+
+ if (ret == -1) {
+ return;
+ }
+
+ syslog(LOG_INFO, "[NCP->] CMD_PROP_VALUE_IS(%s) tid:%d", spinel_prop_key_to_cstr(key), SPINEL_HEADER_GET_TID(cmd_data_ptr[0]));
+
+ return handle_ncp_spinel_value_is(key, value_data_ptr, value_data_len);
+ }
+ break;
+
+ case SPINEL_CMD_PROP_VALUE_INSERTED:
+ {
+ spinel_prop_key_t key;
+ uint8_t* value_data_ptr;
+ spinel_size_t value_data_len;
+ spinel_ssize_t ret;
+
+ ret = spinel_datatype_unpack(cmd_data_ptr, cmd_data_len, "CiiD", NULL, NULL, &key, &value_data_ptr, &value_data_len);
+
+ __ASSERT_MACROS_check(ret != -1);
+
+ if (ret == -1) {
+ return;
+ }
+
+ syslog(LOG_INFO, "[NCP->] CMD_PROP_VALUE_INSERTED(%s) tid:%d", spinel_prop_key_to_cstr(key), SPINEL_HEADER_GET_TID(cmd_data_ptr[0]));
+
+ return handle_ncp_spinel_value_inserted(key, value_data_ptr, value_data_len);
+ }
+ break;
+
+ case SPINEL_CMD_PROP_VALUE_REMOVED:
+ {
+ spinel_prop_key_t key;
+ uint8_t* value_data_ptr;
+ spinel_size_t value_data_len;
+ spinel_ssize_t ret;
+
+ ret = spinel_datatype_unpack(cmd_data_ptr, cmd_data_len, "CiiD", NULL, NULL, &key, &value_data_ptr, &value_data_len);
+
+ __ASSERT_MACROS_check(ret != -1);
+
+ if (ret == -1) {
+ return;
+ }
+
+ syslog(LOG_INFO, "[NCP->] CMD_PROP_VALUE_REMOVED(%s) tid:%d", spinel_prop_key_to_cstr(key), SPINEL_HEADER_GET_TID(cmd_data_ptr[0]));
+
+ return handle_ncp_spinel_value_removed(key, value_data_ptr, value_data_len);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ process_event(EVENT_NCP(command), cmd_data_ptr[0], cmd_data_ptr, cmd_data_len);
+}
+
+void
+SpinelNCPInstance::address_was_added(const struct in6_addr& addr, int prefix_len)
+{
+ if (!is_address_known(addr) && !IN6_IS_ADDR_LINKLOCAL(&addr)) {
+ SpinelNCPTaskSendCommand::Factory factory(this);
+ uint8_t flags = SPINEL_NET_FLAG_SLAAC
+ | SPINEL_NET_FLAG_ON_MESH
+ | SPINEL_NET_FLAG_PREFERRED;
+ CallbackWithStatus callback;
+
+ NCPInstanceBase::address_was_added(addr, prefix_len);
+
+ factory.set_lock_property(SPINEL_PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE);
+
+ callback = boost::bind(&SpinelNCPInstance::check_operation_status, this, "address_was_added()", _1);
+ factory.set_callback(callback);
+
+ factory.add_command(
+ SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_INSERT(
+ SPINEL_DATATYPE_IPv6ADDR_S // Address
+ SPINEL_DATATYPE_UINT8_S // Prefix Length
+ SPINEL_DATATYPE_UINT32_S // Valid Lifetime
+ SPINEL_DATATYPE_UINT32_S // Preferred Lifetime
+ ),
+ SPINEL_PROP_IPV6_ADDRESS_TABLE,
+ &addr,
+ prefix_len,
+ UINT32_MAX,
+ UINT32_MAX
+ )
+ );
+
+ factory.add_command(
+ SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_INSERT(
+ SPINEL_DATATYPE_IPv6ADDR_S // Address
+ SPINEL_DATATYPE_UINT8_S // Prefix Length
+ SPINEL_DATATYPE_BOOL_S // Stable?
+ SPINEL_DATATYPE_UINT8_S // Flags
+ ),
+ SPINEL_PROP_THREAD_ON_MESH_NETS,
+ &addr,
+ prefix_len,
+ true,
+ flags
+ )
+ );
+
+ start_new_task(factory.finish());
+ }
+}
+
+void
+SpinelNCPInstance::address_was_removed(const struct in6_addr& addr, int prefix_len)
+{
+ if (mPrimaryInterface->is_online() && is_address_known(addr)) {
+ SpinelNCPTaskSendCommand::Factory factory(this);
+
+ factory.set_lock_property(SPINEL_PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE);
+
+ factory.add_command(
+ SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_REMOVE(
+ SPINEL_DATATYPE_IPv6ADDR_S // Address
+ SPINEL_DATATYPE_UINT8_S // Prefix
+ ),
+ SPINEL_PROP_IPV6_ADDRESS_TABLE,
+ &addr,
+ prefix_len
+ )
+ );
+
+ start_new_task(factory.finish());
+ }
+
+ NCPInstanceBase::address_was_removed(addr, prefix_len);
+}
+
+void
+SpinelNCPInstance::check_operation_status(std::string operation, int status)
+{
+ if (status == kWPANTUNDStatus_Timeout)
+ {
+ syslog(LOG_ERR, "Timed out while performing \"%s\" - Resetting NCP.", operation.c_str());
+ ncp_is_misbehaving();
+ }
+}
+
+bool
+SpinelNCPInstance::is_busy(void)
+{
+ return NCPInstanceBase::is_busy()
+ || !mTaskQueue.empty();
+}
+
+
+void
+SpinelNCPInstance::process(void)
+{
+ NCPInstanceBase::process();
+
+ if (!is_initializing_ncp() && mTaskQueue.empty()) {
+ bool x = mPcapManager.is_enabled();
+
+ if (mIsPcapInProgress != x) {
+ SpinelNCPTaskSendCommand::Factory factory(this);
+
+ mIsPcapInProgress = x;
+
+ factory.add_command(SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_BOOL_S),
+ SPINEL_PROP_MAC_RAW_STREAM_ENABLED,
+ mIsPcapInProgress
+ ));
+
+ if (mIsPcapInProgress) {
+ factory.add_command(SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_BOOL_S),
+ SPINEL_PROP_NET_IF_UP,
+ true
+ ));
+ if (!ncp_state_is_joining_or_joined(get_ncp_state())) {
+ factory.add_command(SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT8_S),
+ SPINEL_PROP_MAC_PROMISCUOUS_MODE,
+ SPINEL_MAC_PROMISCUOUS_MODE_FULL
+ ));
+ }
+ } else {
+ factory.add_command(SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT8_S),
+ SPINEL_PROP_MAC_PROMISCUOUS_MODE,
+ SPINEL_MAC_PROMISCUOUS_MODE_OFF
+ ));
+ }
+
+ start_new_task(factory.finish());
+ NCPInstanceBase::process();
+ }
+ }
+}
diff --git a/src/ncp-spinel/SpinelNCPInstance.h b/src/ncp-spinel/SpinelNCPInstance.h
new file mode 100644
index 0000000..a50f039
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPInstance.h
@@ -0,0 +1,300 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __wpantund__SpinelNCPInstance__
+#define __wpantund__SpinelNCPInstance__
+
+#include "NCPInstanceBase.h"
+#include "SpinelNCPControlInterface.h"
+#include "nlpt.h"
+#include "SocketWrapper.h"
+#include "SocketAsyncOp.h"
+
+#include <queue>
+#include <set>
+#include <map>
+#include <errno.h>
+#include "spinel.h"
+
+WPANTUND_DECLARE_NCPINSTANCE_PLUGIN(spinel, SpinelNCPInstance);
+
+#define EVENT_NCP_MARKER 0xAB000000
+#define EVENT_NCP(x) ((x)|EVENT_NCP_MARKER)
+#define IS_EVENT_FROM_NCP(x) (((x)&~0xFFFFFF) == EVENT_NCP_MARKER)
+
+
+#define EVENT_NCP_RESET (0xFF0000|EVENT_NCP_MARKER)
+#define EVENT_NCP_PROP_VALUE_IS (0xFF0001|EVENT_NCP_MARKER)
+#define EVENT_NCP_PROP_VALUE_INSERTED (0xFF0002|EVENT_NCP_MARKER)
+#define EVENT_NCP_PROP_VALUE_REMOVED (0xFF0003|EVENT_NCP_MARKER)
+
+#define NCP_FRAMING_OVERHEAD 3
+
+#define CONTROL_REQUIRE_EMPTY_OUTBOUND_BUFFER_WITHIN(seconds, error_label) do { \
+ EH_WAIT_UNTIL_WITH_TIMEOUT(seconds, (GetInstance(this)->mOutboundBufferLen <= 0) && GetInstance(this)->mOutboundCallback.empty()); \
+ require_string(!eh_did_timeout, error_label, "Timed out while waiting " # seconds " seconds for empty outbound buffer"); \
+ } while (0)
+
+#define CONTROL_REQUIRE_OUTBOUND_BUFFER_FLUSHED_WITHIN(seconds, error_label) do { \
+ static const int ___crsw_send_finished = 0xFF000000 | __LINE__; \
+ static const int ___crsw_send_failed = 0xFE000000 | __LINE__; \
+ __ASSERT_MACROS_check(GetInstance(this)->mOutboundCallback.empty()); \
+ require(GetInstance(this)->mOutboundBufferLen > 0, error_label); \
+ GetInstance(this)->mOutboundCallback = CALLBACK_FUNC_SPLIT( \
+ boost::bind(&NCPInstanceBase::process_event_helper, GetInstance(this), ___crsw_send_finished), \
+ boost::bind(&NCPInstanceBase::process_event_helper, GetInstance(this), ___crsw_send_failed) \
+ ); \
+ GetInstance(this)->mOutboundBuffer[0] = mLastHeader; \
+ EH_WAIT_UNTIL_WITH_TIMEOUT(seconds, (event == ___crsw_send_finished) || (event == ___crsw_send_failed)); \
+ require_string(!eh_did_timeout, error_label, "Timed out while trying to send command"); \
+ require_string(event == ___crsw_send_finished, error_label, "Failure while trying to send command"); \
+ } while (0)
+
+#define CONTROL_REQUIRE_PREP_TO_SEND_COMMAND_WITHIN(timeout, error_label) do { \
+ CONTROL_REQUIRE_EMPTY_OUTBOUND_BUFFER_WITHIN(timeout, error_label); \
+ GetInstance(this)->mLastTID = SPINEL_GET_NEXT_TID(GetInstance(this)->mLastTID); \
+ mLastHeader = (SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0 | (GetInstance(this)->mLastTID << SPINEL_HEADER_TID_SHIFT)); \
+ } while (false)
+
+#define CONTROL_REQUIRE_COMMAND_RESPONSE_WITHIN(timeout, error_label) do { \
+ EH_REQUIRE_WITHIN( \
+ timeout, \
+ IS_EVENT_FROM_NCP(event) && GetInstance(this)->mInboundHeader == mLastHeader, \
+ error_label \
+ ); \
+ } while (false)
+
+namespace nl {
+namespace wpantund {
+
+class SpinelNCPTask;
+class SpinelNCPControlInterface;
+
+class SpinelNCPInstance : public NCPInstanceBase {
+ friend class SpinelNCPControlInterface;
+ friend class SpinelNCPTask;
+ friend class SpinelNCPTaskDeepSleep;
+ friend class SpinelNCPTaskWake;
+ friend class SpinelNCPTaskJoin;
+ friend class SpinelNCPTaskForm;
+ friend class SpinelNCPTaskScan;
+ friend class SpinelNCPTaskLeave;
+ friend class SpinelNCPTaskSendCommand;
+ friend class SpinelNCPTaskGetNetworkTopology;
+ friend class SpinelNCPTaskGetMsgBufferCounters;
+
+public:
+
+ enum DriverState {
+ INITIALIZING,
+ INITIALIZING_WAITING_FOR_RESET,
+ NORMAL_OPERATION
+ };
+
+public:
+ SpinelNCPInstance(const Settings& settings = Settings());
+
+ virtual ~SpinelNCPInstance();
+
+ virtual SpinelNCPControlInterface& get_control_interface();
+
+ virtual int vprocess_event(int event, va_list args);
+
+
+protected:
+ virtual char ncp_to_driver_pump();
+ virtual char driver_to_ncp_pump();
+
+ void start_new_task(const boost::shared_ptr<SpinelNCPTask> &task);
+
+ virtual bool is_busy(void);
+
+protected:
+
+ int vprocess_init(int event, va_list args);
+ int vprocess_disabled(int event, va_list args);
+ int vprocess_associated(int event, va_list args);
+ int vprocess_resume(int event, va_list args);
+ int vprocess_offline(int event, va_list args);
+
+ void handle_ncp_spinel_callback(unsigned int command, const uint8_t* cmd_data_ptr, spinel_size_t cmd_data_len);
+ void handle_ncp_spinel_value_is(spinel_prop_key_t key, const uint8_t* value_data_ptr, spinel_size_t value_data_len);
+ void handle_ncp_spinel_value_inserted(spinel_prop_key_t key, const uint8_t* value_data_ptr, spinel_size_t value_data_len);
+ void handle_ncp_spinel_value_removed(spinel_prop_key_t key, const uint8_t* value_data_ptr, spinel_size_t value_data_len);
+ void handle_ncp_state_change(NCPState new_ncp_state, NCPState old_ncp_state);
+
+ virtual void address_was_added(const struct in6_addr& addr, int prefix_len);
+ virtual void address_was_removed(const struct in6_addr& addr, int prefix_len);
+
+ void check_operation_status(std::string operation, int status);
+
+ uint32_t get_default_channel_mask(void);
+
+private:
+
+ void refresh_on_mesh_prefix(struct in6_addr *addr, uint8_t prefix_len, bool stable, uint8_t flags);
+
+public:
+ static bool setup_property_supported_by_class(const std::string& prop_name);
+
+ virtual std::set<std::string> get_supported_property_keys()const;
+
+ virtual void get_property(
+ const std::string& key,
+ CallbackWithStatusArg1 cb
+ );
+
+ virtual void set_property(
+ const std::string& key,
+ const boost::any& value,
+ CallbackWithStatus cb
+ );
+
+ virtual cms_t get_ms_to_next_event(void);
+
+ virtual void reset_tasks(wpantund_status_t status = kWPANTUNDStatus_Canceled);
+
+ static void handle_ncp_log(const uint8_t* data_ptr, int data_len);
+
+ virtual void process(void);
+
+private:
+ struct SettingsEntry
+ {
+ public:
+ SettingsEntry(const Data &command = Data(), unsigned int capability = 0) :
+ mSpinelCommand(command),
+ mCapability(capability)
+ {
+ }
+
+ Data mSpinelCommand;
+ unsigned int mCapability;
+ };
+
+ /* Map from property key to setting entry
+ *
+ * The map contains all parameters/properties that are retained and
+ * restored when NCP gets initialized.
+ *
+ * `Setting entry` contains an optional capability value and an associated
+ * spinel command.
+ *
+ * If the `capability` is present in the list of NCP capabilities , then
+ * the associated spinel command is sent to NCP after initialization.
+ */
+ typedef std::map<std::string, SettingsEntry> SettingsMap;
+
+private:
+ SpinelNCPControlInterface mControlInterface;
+
+ uint8_t mLastTID;
+
+ uint8_t mLastHeader;
+
+ uint8_t mInboundFrame[SPINEL_FRAME_MAX_SIZE];
+ uint8_t mInboundHeader;
+ spinel_size_t mInboundFrameSize;
+ uint8_t mInboundFrameDataType;
+ const uint8_t* mInboundFrameDataPtr;
+ spinel_size_t mInboundFrameDataLen;
+ uint16_t mInboundFrameHDLCCRC;
+
+ uint8_t mOutboundBufferHeader[3];
+ uint8_t mOutboundBuffer[SPINEL_FRAME_MAX_SIZE];
+ uint8_t mOutboundBufferType;
+ spinel_ssize_t mOutboundBufferLen;
+ spinel_ssize_t mOutboundBufferSent;
+ uint8_t mOutboundBufferEscaped[SPINEL_FRAME_MAX_SIZE*2];
+ spinel_ssize_t mOutboundBufferEscapedLen;
+ boost::function<void(int)> mOutboundCallback;
+
+ int mTXPower;
+
+ std::set<unsigned int> mCapabilities;
+ uint32_t mDefaultChannelMask;
+
+ SettingsMap mSettings;
+ SettingsMap::iterator mSettingsIter;
+
+ DriverState mDriverState;
+
+ // Protothreads and related state
+ PT mSleepPT;
+ PT mSubPT;
+
+ int mSubPTIndex;
+
+ Data mNetworkKey;
+ uint32_t mNetworkKeyIndex;
+
+ bool mResetIsExpected;
+
+ bool mIsPcapInProgress;
+
+ // Task management
+ std::list<boost::shared_ptr<SpinelNCPTask> > mTaskQueue;
+
+ enum
+ {
+ kMaxTimeBetweenNoMemStatus = 60000, // (in ms) time between NOMEM status to consider it back-to-back.
+ kMaxNonMemCountToReset = 15, // Number of back-to-back NOMEM status to reset
+ };
+
+ cms_t mLastTimeNoMemStatus;
+ uint16_t mNoMemStatusCounter;
+
+}; // class SpinelNCPInstance
+
+extern class SpinelNCPInstance* gNCPInstance;
+
+template<class C>
+inline SpinelNCPInstance* GetInstance(C *x)
+{
+ return x->mInstance;
+}
+
+template<>
+inline SpinelNCPInstance* GetInstance<SpinelNCPInstance>(SpinelNCPInstance *x)
+{
+ return x;
+}
+
+template<class C>
+inline nl::wpantund::SpinelNCPControlInterface* GetInterface(C *x)
+{
+ return x->mInterface;
+}
+
+template<>
+inline nl::wpantund::SpinelNCPControlInterface* GetInterface<nl::wpantund::SpinelNCPControlInterface>(nl::wpantund::SpinelNCPControlInterface *x)
+{
+ return x;
+}
+
+bool ncp_event_matches_header_from_args(int event, va_list args, uint8_t last_header);
+
+int peek_ncp_callback_status(int event, va_list args);
+
+int spinel_status_to_wpantund_status(int spinel_status);
+
+}; // namespace wpantund
+}; // namespace nl
+
+#endif /* defined(__wpantund__SpinelNCPInstance__) */
diff --git a/src/ncp-spinel/SpinelNCPTask.cpp b/src/ncp-spinel/SpinelNCPTask.cpp
new file mode 100644
index 0000000..e5635d7
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPTask.cpp
@@ -0,0 +1,125 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "assert-macros.h"
+#include <syslog.h>
+#include <errno.h>
+#include "SpinelNCPTask.h"
+#include "SpinelNCPInstance.h"
+
+using namespace nl;
+using namespace nl::wpantund;
+
+SpinelNCPTask::SpinelNCPTask(SpinelNCPInstance* _instance, CallbackWithStatusArg1 cb):
+ mInstance(_instance), mCB(cb), mNextCommandTimeout(NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT)
+{
+}
+
+SpinelNCPTask::~SpinelNCPTask()
+{
+ finish(kWPANTUNDStatus_Canceled);
+}
+
+void
+SpinelNCPTask::finish(int status, const boost::any& value)
+{
+ if (!mCB.empty()) {
+ mCB(status, value);
+ mCB = CallbackWithStatusArg1();
+ }
+}
+
+static bool
+spinel_callback_is_reset(int event, va_list args)
+{
+ int status = peek_ncp_callback_status(event, args);
+ return (status >= SPINEL_STATUS_RESET__BEGIN)
+ && (status < SPINEL_STATUS_RESET__END);
+}
+
+int
+SpinelNCPTask::vprocess_send_command(int event, va_list args)
+{
+ EH_BEGIN_SUB(&mSubPT);
+
+ require(mNextCommand.size() < sizeof(GetInstance(this)->mOutboundBuffer), on_error);
+
+ CONTROL_REQUIRE_PREP_TO_SEND_COMMAND_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, on_error);
+ memcpy(GetInstance(this)->mOutboundBuffer, mNextCommand.data(), mNextCommand.size());
+ GetInstance(this)->mOutboundBufferLen = static_cast<spinel_ssize_t>(mNextCommand.size());
+ CONTROL_REQUIRE_OUTBOUND_BUFFER_FLUSHED_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, on_error);
+
+ if (mNextCommand[1] == SPINEL_CMD_RESET) {
+ mInstance->mResetIsExpected = true;
+ EH_REQUIRE_WITHIN(
+ mNextCommandTimeout,
+ IS_EVENT_FROM_NCP(event)
+ && ( (GetInstance(this)->mInboundHeader == mLastHeader)
+ || spinel_callback_is_reset(event, args)
+ ),
+ on_error
+ );
+ mNextCommandRet = kWPANTUNDStatus_Ok;
+
+ } else {
+ CONTROL_REQUIRE_COMMAND_RESPONSE_WITHIN(mNextCommandTimeout, on_error);
+ mNextCommandRet = peek_ncp_callback_status(event, args);
+ }
+
+ if (mNextCommandRet) {
+ mNextCommandRet = spinel_status_to_wpantund_status(mNextCommandRet);
+ }
+
+ EH_EXIT();
+
+on_error:
+ mNextCommandRet = kWPANTUNDStatus_Timeout;
+
+ EH_END();
+}
+
+nl::Data
+nl::wpantund::SpinelPackData(const char* pack_format, ...)
+{
+ Data ret(64);
+
+ va_list args;
+ va_start(args, pack_format);
+
+ do {
+ spinel_ssize_t packed_size = spinel_datatype_vpack(ret.data(), (spinel_size_t)ret.size(), pack_format, args);
+
+ if (packed_size < 0) {
+ ret.clear();
+ } else if (packed_size > ret.size()) {
+ ret.resize(packed_size);
+ continue;
+ } else {
+ ret.resize(packed_size);
+ }
+ break;
+ } while(true);
+
+ va_end(args);
+ return ret;
+}
diff --git a/src/ncp-spinel/SpinelNCPTask.h b/src/ncp-spinel/SpinelNCPTask.h
new file mode 100644
index 0000000..5ad5bfc
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPTask.h
@@ -0,0 +1,73 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __wpantund__SpinelNCPTask__
+#define __wpantund__SpinelNCPTask__
+
+#include "NCPInstanceBase.h"
+#include "nlpt.h"
+#include "SocketWrapper.h"
+#include "SocketAsyncOp.h"
+
+#include <boost/enable_shared_from_this.hpp>
+#include <queue>
+#include <set>
+#include <map>
+#include <errno.h>
+#include "spinel.h"
+
+namespace nl {
+namespace wpantund {
+
+class SpinelNCPInstance;
+
+class SpinelNCPTask
+ : public boost::enable_shared_from_this<SpinelNCPTask>
+ , public boost::signals2::trackable
+ , public nl::EventHandler
+{
+public:
+ SpinelNCPTask(SpinelNCPInstance* _instance, CallbackWithStatusArg1 cb);
+ virtual ~SpinelNCPTask();
+
+ virtual int vprocess_event(int event, va_list args) = 0;
+
+ virtual void finish(int status, const boost::any& value = boost::any());
+
+ bool peek_callback_is_prop_value_is(int event, va_list args, spinel_prop_key_t);
+
+ SpinelNCPInstance* mInstance;
+
+ int vprocess_send_command(int event, va_list args);
+
+protected:
+ CallbackWithStatusArg1 mCB;
+ uint8_t mLastHeader;
+ PT mSubPT;
+ Data mNextCommand;
+ int mNextCommandRet;
+ int mNextCommandTimeout;
+};
+
+nl::Data SpinelPackData(const char* pack_format, ...);
+
+}; // namespace wpantund
+}; // namespace nl
+
+#endif /* defined(__wpantund__SpinelNCPInstance__) */
diff --git a/src/ncp-spinel/SpinelNCPTaskDeepSleep.cpp b/src/ncp-spinel/SpinelNCPTaskDeepSleep.cpp
new file mode 100644
index 0000000..947fabb
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPTaskDeepSleep.cpp
@@ -0,0 +1,124 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * This file contains the code that handles transitioning the
+ * NCP into a deep-sleep state.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "assert-macros.h"
+#include <syslog.h>
+#include <errno.h>
+#include "SpinelNCPTaskDeepSleep.h"
+#include "SpinelNCPInstance.h"
+#include "spinel-extra.h"
+
+using namespace nl;
+using namespace nl::wpantund;
+
+nl::wpantund::SpinelNCPTaskDeepSleep::SpinelNCPTaskDeepSleep(
+ SpinelNCPInstance* instance,
+ CallbackWithStatusArg1 cb
+): SpinelNCPTask(instance, cb)
+{
+}
+
+void
+nl::wpantund::SpinelNCPTaskDeepSleep::finish(int status, const boost::any& value)
+{
+ mInstance->mResetIsExpected = false;
+
+ SpinelNCPTask::finish(status, value);
+}
+
+
+int
+nl::wpantund::SpinelNCPTaskDeepSleep::vprocess_event(int event, va_list args)
+{
+ int ret = kWPANTUNDStatus_Failure;
+
+ EH_BEGIN();
+
+ // The first event to a task is EVENT_STARTING_TASK. The following
+ // line makes sure that we don't start processing this task
+ // until it is properly scheduled. All tasks immediately receive
+ // the initial `EVENT_STARTING_TASK` event, but further events
+ // will only be received by that task once it is that task's turn
+ // to execute.
+ EH_WAIT_UNTIL(EVENT_STARTING_TASK != event);
+
+ // If we are still initializing, wait until we are finished.
+ EH_WAIT_UNTIL_WITH_TIMEOUT(mInstance->mDriverState == SpinelNCPInstance::NORMAL_OPERATION, NCP_DEFAULT_COMMAND_SEND_TIMEOUT);
+
+ if (mInstance->can_set_ncp_power()) {
+ mNextCommand = SpinelPackData(SPINEL_FRAME_PACK_CMD_NOOP);
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ // Wait for half a second after the last ncp-generated event before
+ // manually cutting the power, just to be conservative.
+ do {
+ EH_WAIT_UNTIL(!IS_EVENT_FROM_NCP(event));
+ EH_WAIT_UNTIL_WITH_TIMEOUT(0.5, IS_EVENT_FROM_NCP(event));
+ } while(!eh_did_timeout);
+
+ if (mInstance->set_ncp_power(false) == kWPANTUNDStatus_Ok) {
+ mInstance->change_ncp_state(DEEP_SLEEP);
+ } else {
+ syslog(LOG_ERR, "DeepSleep: set_ncp_power(false) failed.");
+
+ // Turning off the power manually didn't work for some reason.
+ // Turn it back on and we will try to do it via the API.
+ mInstance->set_ncp_power(true);
+ }
+ }
+
+ if (mInstance->get_ncp_state() != DEEP_SLEEP) {
+ syslog(LOG_NOTICE, "DeepSleep: Putting NCP to sleep.");
+
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT8_S),
+ SPINEL_PROP_POWER_STATE,
+ SPINEL_POWER_STATE_DEEP_SLEEP
+ );
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+ ret = mNextCommandRet;
+ require_noerr(ret, on_error);
+
+ mInstance->change_ncp_state(DEEP_SLEEP);
+ }
+
+on_error:
+
+ if (mInstance->get_ncp_state() == DEEP_SLEEP) {
+ syslog(LOG_NOTICE, "NCP is asleep.");
+ ret = kWPANTUNDStatus_Ok;
+ } else {
+ syslog(LOG_WARNING, "NCP DID NOT GO TO SLEEP!");
+ if (kWPANTUNDStatus_Ok == ret) {
+ ret = kWPANTUNDStatus_Failure;
+ }
+ }
+
+ finish(ret);
+
+ EH_END();
+}
diff --git a/src/ncp-spinel/SpinelNCPTaskDeepSleep.h b/src/ncp-spinel/SpinelNCPTaskDeepSleep.h
new file mode 100644
index 0000000..7c269c8
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPTaskDeepSleep.h
@@ -0,0 +1,47 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __wpantund__SpinelNCPTaskDeepSleep__
+#define __wpantund__SpinelNCPTaskDeepSleep__
+
+#include "SpinelNCPTask.h"
+#include "SpinelNCPInstance.h"
+
+using namespace nl;
+using namespace nl::wpantund;
+
+namespace nl {
+namespace wpantund {
+
+class SpinelNCPTaskDeepSleep : public SpinelNCPTask
+{
+public:
+ SpinelNCPTaskDeepSleep(
+ SpinelNCPInstance* instance,
+ CallbackWithStatusArg1 cb
+ );
+ virtual int vprocess_event(int event, va_list args);
+ virtual void finish(int status, const boost::any& value = boost::any());
+};
+
+}; // namespace wpantund
+}; // namespace nl
+
+
+#endif /* defined(__wpantund__SpinelNCPTaskDeepSleep__) */
diff --git a/src/ncp-spinel/SpinelNCPTaskForm.cpp b/src/ncp-spinel/SpinelNCPTaskForm.cpp
new file mode 100644
index 0000000..d2ddf8c
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPTaskForm.cpp
@@ -0,0 +1,413 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "assert-macros.h"
+#include <syslog.h>
+#include <errno.h>
+#include "SpinelNCPTaskForm.h"
+#include "SpinelNCPInstance.h"
+#include "SpinelNCPTaskScan.h"
+#include "any-to.h"
+#include "spinel-extra.h"
+#include "sec-random.h"
+
+using namespace nl;
+using namespace nl::wpantund;
+
+nl::wpantund::SpinelNCPTaskForm::SpinelNCPTaskForm(
+ SpinelNCPInstance* instance,
+ CallbackWithStatusArg1 cb,
+ const ValueMap& options
+): SpinelNCPTask(instance, cb), mOptions(options), mLastState(instance->get_ncp_state())
+{
+ if (!mOptions.count(kWPANTUNDProperty_NetworkPANID)) {
+ uint16_t panid;
+
+ sec_random_fill(reinterpret_cast<uint8_t*>(&panid), sizeof(panid));
+
+ mOptions[kWPANTUNDProperty_NetworkPANID] = panid;
+ }
+
+ if (!mOptions.count(kWPANTUNDProperty_NetworkXPANID)) {
+ uint64_t xpanid;
+
+ sec_random_fill(reinterpret_cast<uint8_t*>(&xpanid), sizeof(xpanid));
+
+ mOptions[kWPANTUNDProperty_NetworkXPANID] = xpanid;
+ }
+
+
+ if (!mOptions.count(kWPANTUNDProperty_IPv6MeshLocalAddress)) {
+ union {
+ uint64_t xpanid;
+ uint8_t bytes[1];
+ } x = { any_to_uint64((mOptions[kWPANTUNDProperty_NetworkXPANID])) };
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ reverse_bytes(x.bytes, sizeof(x.xpanid));
+#endif
+
+ // Default ML Prefix to be derived from XPANID.
+ struct in6_addr mesh_local_prefix = {{{
+ 0xfd, x.bytes[0], x.bytes[1], x.bytes[2], x.bytes[3], x.bytes[4], 0, 0
+ }}};
+
+ mOptions[kWPANTUNDProperty_IPv6MeshLocalAddress] = mesh_local_prefix;
+ }
+
+ if (instance->mNetworkKey.empty()) {
+ if (!mOptions.count(kWPANTUNDProperty_NetworkKey)) {
+ uint8_t net_key[NCP_NETWORK_KEY_SIZE];
+
+ sec_random_fill(net_key, sizeof(net_key));
+
+ mOptions[kWPANTUNDProperty_NetworkKey] = Data(net_key, sizeof(net_key));
+ }
+
+ if (!mOptions.count(kWPANTUNDProperty_NetworkKeyIndex)) {
+ mOptions[kWPANTUNDProperty_NetworkKeyIndex] = 1;
+ }
+ }
+}
+
+void
+nl::wpantund::SpinelNCPTaskForm::finish(int status, const boost::any& value)
+{
+ if (!ncp_state_is_associated(mInstance->get_ncp_state())) {
+ mInstance->change_ncp_state(mLastState);
+ }
+ SpinelNCPTask::finish(status, value);
+}
+
+int
+nl::wpantund::SpinelNCPTaskForm::vprocess_event(int event, va_list args)
+{
+ int ret = kWPANTUNDStatus_Failure;
+
+ EH_BEGIN();
+
+
+ if (!mInstance->mEnabled) {
+ ret = kWPANTUNDStatus_InvalidWhenDisabled;
+ finish(ret);
+ EH_EXIT();
+ }
+
+ if (mInstance->get_ncp_state() == UPGRADING) {
+ ret = kWPANTUNDStatus_InvalidForCurrentState;
+ finish(ret);
+ EH_EXIT();
+ }
+
+ // Wait for a bit to see if the NCP will enter the right state.
+ EH_REQUIRE_WITHIN(
+ NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT,
+ !ncp_state_is_initializing(mInstance->get_ncp_state()),
+ on_error
+ );
+
+ if (ncp_state_is_associated(mInstance->get_ncp_state())) {
+ ret = kWPANTUNDStatus_Already;
+ finish(ret);
+ EH_EXIT();
+ }
+
+ if (!mInstance->mCapabilities.count(SPINEL_CAP_ROLE_ROUTER)) {
+ // We can't form unless we are router-capable
+ ret = kWPANTUNDStatus_FeatureNotSupported;
+ finish(ret);
+ EH_EXIT();
+ }
+
+ // The first event to a task is EVENT_STARTING_TASK. The following
+ // line makes sure that we don't start processing this task
+ // until it is properly scheduled. All tasks immediately receive
+ // the initial `EVENT_STARTING_TASK` event, but further events
+ // will only be received by that task once it is that task's turn
+ // to execute.
+ EH_WAIT_UNTIL(EVENT_STARTING_TASK != event);
+
+ mLastState = mInstance->get_ncp_state();
+ mInstance->change_ncp_state(ASSOCIATING);
+
+ // Clear any previously saved network settings
+ mNextCommand = SpinelPackData(SPINEL_FRAME_PACK_CMD_NET_CLEAR);
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+ ret = mNextCommandRet;
+ require_noerr(ret, on_error);
+
+ // TODO: We should do a scan to make sure we pick a good channel
+ // and don't have a panid collision.
+
+ // Set the channel
+ {
+ uint8_t channel;
+
+ if (mOptions.count(kWPANTUNDProperty_NCPChannel)) {
+ channel = any_to_int(mOptions[kWPANTUNDProperty_NCPChannel]);
+
+ // Make sure the channel is the supported channel set.
+ if (mInstance->mSupprotedChannels.find(channel) == mInstance->mSupprotedChannels.end()) {
+ syslog(LOG_ERR, "Channel %d is not supported by NCP. Supported channels mask is %08x",
+ mInstance->get_default_channel_mask()
+ );
+ ret = kWPANTUNDStatus_InvalidArgument;
+ goto on_error;
+ }
+
+ } else {
+ uint32_t mask;
+ uint32_t default_mask = mInstance->get_default_channel_mask();
+
+ if (mOptions.count(kWPANTUNDProperty_NCPChannelMask)) {
+ mask = any_to_int(mOptions[kWPANTUNDProperty_NCPChannelMask]);
+ } else {
+ mask = default_mask;
+ }
+
+ if ((mask & default_mask) == 0) {
+ syslog(LOG_ERR, "Invalid channel mask 0x%08x. Supported channels mask is 0x%08x", mask, default_mask);
+ ret = kWPANTUNDStatus_InvalidArgument;
+ goto on_error;
+ }
+
+ mask &= default_mask;
+
+ // Randomly pick a channel from the given channel mask for now.
+ do {
+ sec_random_fill(&channel, 1);
+ channel = (channel % 32);
+ } while (0 == ((1 << channel) & mask));
+ }
+
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT8_S),
+ SPINEL_PROP_PHY_CHAN,
+ channel
+ );
+ }
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ require_noerr(ret, on_error);
+
+ // Turn off promiscuous mode, if it happens to be on
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT8_S),
+ SPINEL_PROP_MAC_PROMISCUOUS_MODE,
+ SPINEL_MAC_PROMISCUOUS_MODE_OFF
+ );
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+ ret = mNextCommandRet;
+ check_noerr(ret);
+
+ if (mOptions.count(kWPANTUNDProperty_NetworkPANID)) {
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT16_S),
+ SPINEL_PROP_MAC_15_4_PANID,
+ any_to_int(mOptions[kWPANTUNDProperty_NetworkPANID])
+ );
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ require_noerr(ret, on_error);
+ }
+
+ if (mOptions.count(kWPANTUNDProperty_NetworkXPANID)) {
+ {
+ uint64_t xpanid(any_to_uint64((mOptions[kWPANTUNDProperty_NetworkXPANID])));
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ reverse_bytes(reinterpret_cast<uint8_t*>(&xpanid), sizeof(xpanid));
+#endif
+
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_DATA_S),
+ SPINEL_PROP_NET_XPANID,
+ &xpanid,
+ sizeof(xpanid)
+ );
+ }
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ require_noerr(ret, on_error);
+ }
+
+ if (mOptions.count(kWPANTUNDProperty_NetworkName)) {
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UTF8_S),
+ SPINEL_PROP_NET_NETWORK_NAME,
+ any_to_string(mOptions[kWPANTUNDProperty_NetworkName]).c_str()
+ );
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ require_noerr(ret, on_error);
+ }
+
+ if (mOptions.count(kWPANTUNDProperty_NetworkKey)) {
+ {
+ nl::Data data(any_to_data(mOptions[kWPANTUNDProperty_NetworkKey]));
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_DATA_S),
+ SPINEL_PROP_NET_MASTER_KEY,
+ data.data(),
+ data.size()
+ );
+ }
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ require_noerr(ret, on_error);
+ }
+
+ if (mOptions.count(kWPANTUNDProperty_NetworkKeyIndex)) {
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT32_S),
+ SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER,
+ any_to_int(mOptions[kWPANTUNDProperty_NetworkKeyIndex])
+ );
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ require_noerr(ret, on_error);
+ }
+
+ if (mOptions.count(kWPANTUNDProperty_IPv6MeshLocalAddress)) {
+ {
+ struct in6_addr addr = any_to_ipv6(mOptions[kWPANTUNDProperty_IPv6MeshLocalAddress]);
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_IPv6ADDR_S SPINEL_DATATYPE_UINT8_S),
+ SPINEL_PROP_IPV6_ML_PREFIX,
+ &addr,
+ 64
+ );
+ }
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ require_noerr(ret, on_error);
+ } else if (mOptions.count(kWPANTUNDProperty_IPv6MeshLocalPrefix)) {
+ {
+ struct in6_addr addr = any_to_ipv6(mOptions[kWPANTUNDProperty_IPv6MeshLocalPrefix]);
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_IPv6ADDR_S SPINEL_DATATYPE_UINT8_S),
+ SPINEL_PROP_IPV6_ML_PREFIX,
+ &addr,
+ 64
+ );
+ }
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ require_noerr(ret, on_error);
+ }
+
+ if (mOptions.count(kWPANTUNDProperty_NestLabs_LegacyMeshLocalPrefix)) {
+ if (mInstance->mCapabilities.count(SPINEL_CAP_NEST_LEGACY_INTERFACE)) {
+ {
+ nl::Data data(any_to_data(mOptions[kWPANTUNDProperty_NestLabs_LegacyMeshLocalPrefix]));
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_DATA_S),
+ SPINEL_PROP_NEST_LEGACY_ULA_PREFIX,
+ data.data(),
+ data.size()
+ );
+ }
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ require_noerr(ret, on_error);
+ }
+ }
+
+ // Now bring up the network by bringing up the interface and the stack.
+
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_BOOL_S),
+ SPINEL_PROP_NET_IF_UP,
+ true
+ );
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ require(ret == kWPANTUNDStatus_Ok || ret == kWPANTUNDStatus_Already, on_error);
+
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_BOOL_S),
+ SPINEL_PROP_NET_STACK_UP,
+ true
+ );
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ require_noerr(ret, on_error);
+
+ EH_REQUIRE_WITHIN(
+ NCP_FORM_TIMEOUT,
+ ncp_state_is_associated(mInstance->get_ncp_state()),
+ on_error
+ );
+
+ ret = kWPANTUNDStatus_Ok;
+
+ finish(ret);
+
+ EH_EXIT();
+
+on_error:
+
+ if (ret == kWPANTUNDStatus_Ok) {
+ ret = kWPANTUNDStatus_Failure;
+ }
+
+ syslog(LOG_ERR, "Form failed: %d", ret);
+
+ finish(ret);
+
+ EH_END();
+}
diff --git a/src/ncp-spinel/SpinelNCPTaskForm.h b/src/ncp-spinel/SpinelNCPTaskForm.h
new file mode 100644
index 0000000..1fef8f4
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPTaskForm.h
@@ -0,0 +1,52 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __wpantund__SpinelNCPTaskForm__
+#define __wpantund__SpinelNCPTaskForm__
+
+#include "SpinelNCPTask.h"
+#include "SpinelNCPInstance.h"
+
+using namespace nl;
+using namespace nl::wpantund;
+
+namespace nl {
+namespace wpantund {
+
+class SpinelNCPTaskForm : public SpinelNCPTask
+{
+public:
+ SpinelNCPTaskForm(
+ SpinelNCPInstance* instance,
+ CallbackWithStatusArg1 cb,
+ const ValueMap& options
+ );
+ virtual int vprocess_event(int event, va_list args);
+ virtual void finish(int status, const boost::any& value = boost::any());
+
+private:
+ ValueMap mOptions;
+ NCPState mLastState;
+};
+
+}; // namespace wpantund
+}; // namespace nl
+
+
+#endif /* defined(__wpantund__SpinelNCPTaskForm__) */
diff --git a/src/ncp-spinel/SpinelNCPTaskGetMsgBufferCounters.cpp b/src/ncp-spinel/SpinelNCPTaskGetMsgBufferCounters.cpp
new file mode 100644
index 0000000..896a6e6
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPTaskGetMsgBufferCounters.cpp
@@ -0,0 +1,266 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "assert-macros.h"
+#include <syslog.h>
+#include <errno.h>
+#include "SpinelNCPTaskGetMsgBufferCounters.h"
+#include "SpinelNCPInstance.h"
+#include "spinel-extra.h"
+
+using namespace nl;
+using namespace nl::wpantund;
+
+nl::wpantund::SpinelNCPTaskGetMsgBufferCounters::SpinelNCPTaskGetMsgBufferCounters(
+ SpinelNCPInstance* instance,
+ CallbackWithStatusArg1 cb,
+ ResultFormat result_format
+): SpinelNCPTask(instance, cb), mResultFormat(result_format)
+{
+}
+
+int
+nl::wpantund::SpinelNCPTaskGetMsgBufferCounters::vprocess_event(int event, va_list args)
+{
+ int ret = kWPANTUNDStatus_Failure;
+ unsigned int prop_key;
+ const uint8_t *data_in;
+ spinel_size_t data_len;
+ spinel_ssize_t len;
+ MsgBufferCounters counters;
+
+ EH_BEGIN();
+
+ if (!mInstance->mEnabled) {
+ ret = kWPANTUNDStatus_InvalidWhenDisabled;
+ finish(ret);
+ EH_EXIT();
+ }
+
+ if (mInstance->get_ncp_state() == UPGRADING) {
+ ret = kWPANTUNDStatus_InvalidForCurrentState;
+ finish(ret);
+ EH_EXIT();
+ }
+
+ // Wait for a bit to see if the NCP will enter the right state.
+ EH_REQUIRE_WITHIN(
+ NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT,
+ !ncp_state_is_initializing(mInstance->get_ncp_state()),
+ on_error
+ );
+
+ // The first event to a task is EVENT_STARTING_TASK. The following
+ // line makes sure that we don't start processing this task
+ // until it is properly scheduled. All tasks immediately receive
+ // the initial `EVENT_STARTING_TASK` event, but further events
+ // will only be received by that task once it is that task's turn
+ // to execute.
+ EH_WAIT_UNTIL(EVENT_STARTING_TASK != event);
+
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_GET,
+ SPINEL_PROP_MSG_BUFFER_COUNTERS
+ );
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ require_noerr(ret, on_error);
+
+ require(EVENT_NCP_PROP_VALUE_IS == event, on_error);
+
+ prop_key = va_arg(args, unsigned int);
+ data_in = va_arg(args, const uint8_t*);
+ data_len = va_arg_small(args, spinel_size_t);
+
+ require(prop_key == SPINEL_PROP_MSG_BUFFER_COUNTERS, on_error);
+
+ len = spinel_datatype_unpack(
+ data_in,
+ data_len,
+ "SSSSSSSSSSSSSSSS",
+ &counters.mTotalBuffers,
+ &counters.mFreeBuffers,
+ &counters.m6loSendMessages,
+ &counters.m6loSendBuffers,
+ &counters.m6loReassemblyMessages,
+ &counters.m6loReassemblyBuffers,
+ &counters.mIp6Messages,
+ &counters.mIp6Buffers,
+ &counters.mMplMessages,
+ &counters.mMplBuffers,
+ &counters.mMleMessages,
+ &counters.mMleBuffers,
+ &counters.mArpMessages,
+ &counters.mArpBuffers,
+ &counters.mCoapClientMessages,
+ &counters.mCoapClientBuffers
+ );
+
+ require(len >=0, on_error);
+
+ ret = kWPANTUNDStatus_Ok;
+
+ if (mResultFormat == kResultFormat_StringArray)
+ {
+ finish(ret, counters.get_as_string_array());
+ }
+ else if (mResultFormat == kResultFormat_String)
+ {
+ finish(ret, counters.get_as_string());
+ }
+ else if (mResultFormat == kResultFormat_ValueMap)
+ {
+ finish(ret, counters.get_as_valuemap());
+ }
+ else
+ {
+ finish(ret);
+ }
+
+ EH_EXIT();
+
+on_error:
+
+ if (ret == kWPANTUNDStatus_Ok) {
+ ret = kWPANTUNDStatus_Failure;
+ }
+
+ syslog(LOG_ERR, "Getting msg buffer counter failed: %d", ret);
+
+ finish(ret);
+
+ EH_END();
+}
+
+std::list<std::string>
+SpinelNCPTaskGetMsgBufferCounters::MsgBufferCounters::get_as_string_array(void) const
+{
+ std::list<std::string> slist;
+ char c_string[100];
+
+ snprintf(c_string, sizeof(c_string), "mTotalBuffers = %d", mTotalBuffers);
+ slist.push_back(c_string);
+ snprintf(c_string, sizeof(c_string), "mFreeBuffers = %d", mFreeBuffers);
+ slist.push_back(c_string);
+ snprintf(c_string, sizeof(c_string), "m6loSendMessages = %d", m6loSendMessages);
+ slist.push_back(c_string);
+ snprintf(c_string, sizeof(c_string), "m6loSendBuffers = %d", m6loSendBuffers);
+ slist.push_back(c_string);
+ snprintf(c_string, sizeof(c_string), "m6loReassemblyMessages = %d", m6loReassemblyMessages);
+ slist.push_back(c_string);
+ snprintf(c_string, sizeof(c_string), "m6loReassemblyBuffers = %d", m6loReassemblyBuffers);
+ slist.push_back(c_string);
+ snprintf(c_string, sizeof(c_string), "mIp6Messages = %d", mIp6Messages);
+ slist.push_back(c_string);
+ snprintf(c_string, sizeof(c_string), "mIp6Buffers = %d", mIp6Buffers);
+ slist.push_back(c_string);
+ snprintf(c_string, sizeof(c_string), "mMplMessages = %d", mMplMessages);
+ slist.push_back(c_string);
+ snprintf(c_string, sizeof(c_string), "mMplBuffers = %d", mMplBuffers);
+ slist.push_back(c_string);
+ snprintf(c_string, sizeof(c_string), "mMleMessages = %d", mMleMessages);
+ slist.push_back(c_string);
+ snprintf(c_string, sizeof(c_string), "mMleBuffers = %d", mMleBuffers);
+ slist.push_back(c_string);
+ snprintf(c_string, sizeof(c_string), "mArpMessages = %d", mArpMessages);
+ slist.push_back(c_string);
+ snprintf(c_string, sizeof(c_string), "mArpBuffers = %d", mArpBuffers);
+ slist.push_back(c_string);
+ snprintf(c_string, sizeof(c_string), "mCoapClientMessages = %d", mCoapClientMessages);
+ slist.push_back(c_string);
+ snprintf(c_string, sizeof(c_string), "mCoapClientBuffers = %d", mCoapClientBuffers);
+ slist.push_back(c_string);
+
+ return slist;
+}
+
+std::string
+SpinelNCPTaskGetMsgBufferCounters::MsgBufferCounters::get_as_string(void) const
+{
+ char c_string[800];
+
+ snprintf(c_string, sizeof(c_string),
+ "TotalBuffers = %-3d, "
+ "FreeBuffers = %-3d, "
+ "6loSendMessages = %-3d, "
+ "6loSendBuffers = %-3d, "
+ "6loReassemblyMessages = %-3d, "
+ "6loReassemblyBuffers = %-3d, "
+ "Ip6Messages = %-3d, "
+ "Ip6Buffers = %-3d, "
+ "MplMessages = %-3d, "
+ "MplBuffers = %-3d, "
+ "MleMessages = %-3d, "
+ "MleBuffers = %-3d, "
+ "ArpMessages = %-3d, "
+ "ArpBuffers = %-3d, "
+ "CoapClientMessages = %-3d, "
+ "CoapClientBuffers = %-3d, ",
+ mTotalBuffers,
+ mFreeBuffers,
+ m6loSendMessages,
+ m6loSendBuffers,
+ m6loReassemblyMessages,
+ m6loReassemblyBuffers,
+ mIp6Messages,
+ mIp6Buffers,
+ mMplMessages,
+ mMplBuffers,
+ mMleMessages,
+ mMleBuffers,
+ mArpMessages,
+ mArpBuffers,
+ mCoapClientMessages,
+ mCoapClientBuffers
+ );
+
+ return std::string(c_string);
+}
+
+ValueMap
+SpinelNCPTaskGetMsgBufferCounters::MsgBufferCounters::get_as_valuemap(void) const
+{
+ ValueMap vm;
+
+ vm["TotalBuffers"] = mTotalBuffers;
+ vm["FreeBuffers"] = mFreeBuffers;
+ vm["6loSendMessages"] = m6loSendMessages;
+ vm["6loSendBuffers"] = m6loSendBuffers;
+ vm["6loReassemblyMessages"] = m6loReassemblyMessages;
+ vm["6loReassemblyBuffers"] = m6loReassemblyBuffers;
+ vm["Ip6Messages"] = mIp6Messages;
+ vm["Ip6Buffers"] = mIp6Buffers;
+ vm["MplMessages"] = mMplMessages;
+ vm["MplBuffers"] = mMplBuffers;
+ vm["MleMessages"] = mMleMessages;
+ vm["MleBuffers"] = mMleBuffers;
+ vm["ArpMessages"] = mArpMessages;
+ vm["ArpBuffers"] = mArpBuffers;
+ vm["CoapClientMessages"] = mCoapClientMessages;
+ vm["CoapClientBuffers"] = mCoapClientBuffers;
+
+ return vm;
+}
diff --git a/src/ncp-spinel/SpinelNCPTaskGetMsgBufferCounters.h b/src/ncp-spinel/SpinelNCPTaskGetMsgBufferCounters.h
new file mode 100644
index 0000000..addc78d
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPTaskGetMsgBufferCounters.h
@@ -0,0 +1,86 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __wpantund__SpinelNCPTaskGetMsgBufferCounters__
+#define __wpantund__SpinelNCPTaskGetMsgBufferCounters__
+
+#include <list>
+#include <string>
+#include "ValueMap.h"
+#include "SpinelNCPTask.h"
+#include "SpinelNCPInstance.h"
+
+using namespace nl;
+using namespace nl::wpantund;
+
+namespace nl {
+namespace wpantund {
+
+class SpinelNCPTaskGetMsgBufferCounters : public SpinelNCPTask
+{
+public:
+ enum ResultFormat
+ {
+ kResultFormat_String, // Returns the counter info as a std::string (long line with all counters)
+ kResultFormat_StringArray, // Returns the counter info as an array of std::string(s) (one per counter)
+ kResultFormat_ValueMap, // Returns the counter info as a ValueMap dictionary.
+ };
+
+ SpinelNCPTaskGetMsgBufferCounters(
+ SpinelNCPInstance* instance,
+ CallbackWithStatusArg1 cb,
+ ResultFormat result_format = kResultFormat_ValueMap
+ );
+ virtual int vprocess_event(int event, va_list args);
+
+private:
+
+ struct MsgBufferCounters
+ {
+ uint16_t mTotalBuffers; ///< The number of buffers in the pool.
+ uint16_t mFreeBuffers; ///< The number of free message buffers.
+ uint16_t m6loSendMessages; ///< The number of messages in the 6lo send queue.
+ uint16_t m6loSendBuffers; ///< The number of buffers in the 6lo send queue.
+ uint16_t m6loReassemblyMessages; ///< The number of messages in the 6LoWPAN reassembly queue.
+ uint16_t m6loReassemblyBuffers; ///< The number of buffers in the 6LoWPAN reassembly queue.
+ uint16_t mIp6Messages; ///< The number of messages in the IPv6 send queue.
+ uint16_t mIp6Buffers; ///< The number of buffers in the IPv6 send queue.
+ uint16_t mMplMessages; ///< The number of messages in the MPL send queue.
+ uint16_t mMplBuffers; ///< The number of buffers in the MPL send queue.
+ uint16_t mMleMessages; ///< The number of messages in the MLE send queue.
+ uint16_t mMleBuffers; ///< The number of buffers in the MLE send queue.
+ uint16_t mArpMessages; ///< The number of messages in the ARP send queue.
+ uint16_t mArpBuffers; ///< The number of buffers in the ARP send queue.
+ uint16_t mCoapClientMessages; ///< The number of messages in the CoAP client send queue.
+ uint16_t mCoapClientBuffers; ///< The number of buffers in the CoAP client send queue.
+
+ std::string get_as_string(void) const;
+ std::list<std::string> get_as_string_array(void) const;
+ ValueMap get_as_valuemap(void) const;
+ };
+
+ ResultFormat mResultFormat;
+};
+
+
+}; // namespace wpantund
+}; // namespace nl
+
+
+#endif /* defined(__wpantund__SpinelNCPTaskGetMsgBufferCounters__) */
diff --git a/src/ncp-spinel/SpinelNCPTaskGetNetworkTopology.cpp b/src/ncp-spinel/SpinelNCPTaskGetNetworkTopology.cpp
new file mode 100644
index 0000000..44c34b3
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPTaskGetNetworkTopology.cpp
@@ -0,0 +1,389 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "assert-macros.h"
+#include <syslog.h>
+#include <errno.h>
+#include "SpinelNCPTaskGetNetworkTopology.h"
+#include "SpinelNCPInstance.h"
+#include "spinel-extra.h"
+
+using namespace nl;
+using namespace nl::wpantund;
+
+nl::wpantund::SpinelNCPTaskGetNetworkTopology::SpinelNCPTaskGetNetworkTopology(
+ SpinelNCPInstance* instance,
+ CallbackWithStatusArg1 cb,
+ Type table_type,
+ ResultFormat result_format
+): SpinelNCPTask(instance, cb), mType(table_type), mTable(), mResultFormat(result_format)
+{
+}
+
+int
+nl::wpantund::SpinelNCPTaskGetNetworkTopology::prase_child_table(const uint8_t *data_in, spinel_size_t data_len,
+ Table& child_table)
+{
+ int ret = kWPANTUNDStatus_Ok;
+
+ child_table.clear();
+
+ while (data_len > 0)
+ {
+ spinel_ssize_t len = 0;
+ TableEntry child_info;
+ const spinel_eui64_t *eui64 = NULL;
+ uint8_t mode;
+
+ memset(&child_info, 0, sizeof(child_info));
+
+ child_info.mType = kChildTable;
+
+ len = spinel_datatype_unpack(
+ data_in,
+ data_len,
+ "T("
+ SPINEL_DATATYPE_EUI64_S // EUI64 Address
+ SPINEL_DATATYPE_UINT16_S // Rloc16
+ SPINEL_DATATYPE_UINT32_S // Timeout
+ SPINEL_DATATYPE_UINT32_S // Age
+ SPINEL_DATATYPE_UINT8_S // Network Data Version
+ SPINEL_DATATYPE_UINT8_S // Link Quality In
+ SPINEL_DATATYPE_INT8_S // Average RSS
+ SPINEL_DATATYPE_UINT8_S // Mode (flags)
+ ")",
+ &eui64,
+ &child_info.mRloc16,
+ &child_info.mTimeout,
+ &child_info.mAge,
+ &child_info.mNetworkDataVersion,
+ &child_info.mLinkQualityIn,
+ &child_info.mAverageRssi,
+ &mode
+ );
+
+ if (len <= 0)
+ {
+ ret = kWPANTUNDStatus_Failure;
+ break;
+ }
+
+ memcpy(child_info.mExtAddress, eui64, sizeof(child_info.mExtAddress));
+
+ child_info.mRxOnWhenIdle = ((mode & kThreadMode_RxOnWhenIdle) != 0);
+ child_info.mSecureDataRequest = ((mode & kThreadMode_SecureDataRequest) != 0);
+ child_info.mFullFunction = ((mode & kThreadMode_FullFunctionDevice) != 0);
+ child_info.mFullNetworkData = ((mode & kThreadMode_FullNetworkData) != 0);
+
+ child_table.push_back(child_info);
+
+ data_in += len;
+ data_len -= len;
+ }
+
+ return ret;
+}
+
+int
+nl::wpantund::SpinelNCPTaskGetNetworkTopology::prase_neighbor_table(const uint8_t *data_in, spinel_size_t data_len,
+ Table& neighbor_table)
+{
+ int ret = kWPANTUNDStatus_Ok;
+
+ neighbor_table.clear();
+
+ while (data_len > 0)
+ {
+ spinel_ssize_t len = 0;
+ TableEntry neighbor_info;
+ const spinel_eui64_t *eui64 = NULL;
+ uint8_t mode;
+ bool is_child = false;
+
+ memset(&neighbor_info, 0, sizeof(neighbor_info));
+
+ neighbor_info.mType = kNeighborTable;
+
+ len = spinel_datatype_unpack(
+ data_in,
+ data_len,
+ "T("
+ SPINEL_DATATYPE_EUI64_S // EUI64 Address
+ SPINEL_DATATYPE_UINT16_S // Rloc16
+ SPINEL_DATATYPE_UINT32_S // Age
+ SPINEL_DATATYPE_UINT8_S // Link Quality In
+ SPINEL_DATATYPE_INT8_S // Average RSS
+ SPINEL_DATATYPE_UINT8_S // Mode (flags)
+ SPINEL_DATATYPE_BOOL_S // Is Child
+ SPINEL_DATATYPE_UINT32_S // Link Frame Counter
+ SPINEL_DATATYPE_UINT32_S // MLE Frame Counter
+ ")",
+ &eui64,
+ &neighbor_info.mRloc16,
+ &neighbor_info.mAge,
+ &neighbor_info.mLinkQualityIn,
+ &neighbor_info.mAverageRssi,
+ &mode,
+ &is_child,
+ &neighbor_info.mLinkFrameCounter,
+ &neighbor_info.mMleFrameCounter
+ );
+
+ if (len <= 0)
+ {
+ ret = kWPANTUNDStatus_Failure;
+ break;
+ }
+
+ memcpy(neighbor_info.mExtAddress, eui64, sizeof(neighbor_info.mExtAddress));
+
+ neighbor_info.mRxOnWhenIdle = ((mode & kThreadMode_RxOnWhenIdle) != 0);
+ neighbor_info.mSecureDataRequest = ((mode & kThreadMode_SecureDataRequest) != 0);
+ neighbor_info.mFullFunction = ((mode & kThreadMode_FullFunctionDevice) != 0);
+ neighbor_info.mFullNetworkData = ((mode & kThreadMode_FullNetworkData) != 0);
+ neighbor_info.mIsChild = is_child;
+
+ neighbor_table.push_back(neighbor_info);
+
+ data_in += len;
+ data_len -= len;
+ }
+
+ return ret;
+}
+
+int
+nl::wpantund::SpinelNCPTaskGetNetworkTopology::vprocess_event(int event, va_list args)
+{
+ int ret = kWPANTUNDStatus_Failure;
+ unsigned int prop_key;
+ const uint8_t *data_in;
+ spinel_size_t data_len;
+
+ EH_BEGIN();
+
+ if (!mInstance->mEnabled) {
+ ret = kWPANTUNDStatus_InvalidWhenDisabled;
+ finish(ret);
+ EH_EXIT();
+ }
+
+ if (mInstance->get_ncp_state() == UPGRADING) {
+ ret = kWPANTUNDStatus_InvalidForCurrentState;
+ finish(ret);
+ EH_EXIT();
+ }
+
+ // Wait for a bit to see if the NCP will enter the right state.
+ EH_REQUIRE_WITHIN(
+ NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT,
+ !ncp_state_is_initializing(mInstance->get_ncp_state()),
+ on_error
+ );
+
+ // The first event to a task is EVENT_STARTING_TASK. The following
+ // line makes sure that we don't start processing this task
+ // until it is properly scheduled. All tasks immediately receive
+ // the initial `EVENT_STARTING_TASK` event, but further events
+ // will only be received by that task once it is that task's turn
+ // to execute.
+ EH_WAIT_UNTIL(EVENT_STARTING_TASK != event);
+
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_GET,
+ (mType == kChildTable) ? SPINEL_PROP_THREAD_CHILD_TABLE : SPINEL_PROP_THREAD_NEIGHBOR_TABLE
+ );
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ require_noerr(ret, on_error);
+
+ require(EVENT_NCP_PROP_VALUE_IS == event, on_error);
+
+ prop_key = va_arg(args, unsigned int);
+ data_in = va_arg(args, const uint8_t*);
+ data_len = va_arg_small(args, spinel_size_t);
+
+ if (mType == kChildTable) {
+ require(prop_key == SPINEL_PROP_THREAD_CHILD_TABLE, on_error);
+ prase_child_table(data_in, data_len, mTable);
+ } else {
+ require(prop_key == SPINEL_PROP_THREAD_NEIGHBOR_TABLE, on_error);
+ prase_neighbor_table(data_in, data_len, mTable);
+ }
+
+ ret = kWPANTUNDStatus_Ok;
+
+ if (mResultFormat == kResultFormat_StringArray)
+ {
+ std::list<std::string> result;
+ Table::iterator it;
+
+ for (it = mTable.begin(); it != mTable.end(); it++)
+ {
+ result.push_back(it->get_as_string());
+ }
+
+ finish(ret, result);
+ }
+ else if (mResultFormat == kResultFormat_ValueMapArray)
+ {
+ std::list<ValueMap> result;
+ Table::iterator it;
+
+ for (it = mTable.begin(); it != mTable.end(); it++)
+ {
+ result.push_back(it->get_as_valuemap());
+ }
+
+ finish(ret, result);
+ }
+ else
+ {
+ finish(ret);
+ }
+
+ mTable.clear();
+
+ EH_EXIT();
+
+on_error:
+
+ if (ret == kWPANTUNDStatus_Ok) {
+ ret = kWPANTUNDStatus_Failure;
+ }
+
+ syslog(LOG_ERR, "Getting child/neighbor table failed: %d", ret);
+
+ finish(ret);
+
+ mTable.clear();
+
+ EH_END();
+}
+
+std::string
+SpinelNCPTaskGetNetworkTopology::TableEntry::get_as_string(void) const
+{
+ char c_string[800];
+
+ if (mType == kChildTable) {
+ snprintf(c_string, sizeof(c_string),
+ "%02X%02X%02X%02X%02X%02X%02X%02X, "
+ kWPANTUNDValueMapKey_NetworkTopology_RLOC16 ": %04x, "
+ kWPANTUNDValueMapKey_NetworkTopology_NetworkDataVersion ": %-3d, "
+ kWPANTUNDValueMapKey_NetworkTopology_LinkQualityIn ": %-2d, "
+ kWPANTUNDValueMapKey_NetworkTopology_AverageRssi ": %-3d, "
+ kWPANTUNDValueMapKey_NetworkTopology_Timeout ": %-5u, "
+ kWPANTUNDValueMapKey_NetworkTopology_Age ": %-5u, "
+ kWPANTUNDValueMapKey_NetworkTopology_RxOnWhenIdle ": %s, "
+ kWPANTUNDValueMapKey_NetworkTopology_FullFunction ": %s, "
+ kWPANTUNDValueMapKey_NetworkTopology_SecureDataRequest ": %s, "
+ kWPANTUNDValueMapKey_NetworkTopology_FullNetworkData ": %s",
+ mExtAddress[0], mExtAddress[1], mExtAddress[2], mExtAddress[3],
+ mExtAddress[4], mExtAddress[5], mExtAddress[6], mExtAddress[7],
+ mRloc16,
+ mNetworkDataVersion,
+ mLinkQualityIn,
+ mAverageRssi,
+ mTimeout,
+ mAge,
+ mRxOnWhenIdle ? "yes" : "no",
+ mFullFunction ? "yes" : "no",
+ mSecureDataRequest ? "yes" : "no",
+ mFullNetworkData ? "yes" : "no"
+ );
+
+ } else {
+ snprintf(c_string, sizeof(c_string),
+ "%02X%02X%02X%02X%02X%02X%02X%02X, "
+ kWPANTUNDValueMapKey_NetworkTopology_RLOC16 ": %04x, "
+ kWPANTUNDValueMapKey_NetworkTopology_LinkQualityIn ": %-2d, "
+ kWPANTUNDValueMapKey_NetworkTopology_AverageRssi ": %-3d, "
+ kWPANTUNDValueMapKey_NetworkTopology_Age ": %-5u, "
+ kWPANTUNDValueMapKey_NetworkTopology_LinkFrameCounter ": %-5u, "
+ kWPANTUNDValueMapKey_NetworkTopology_MleFrameCounter ": %-5u, "
+ kWPANTUNDValueMapKey_NetworkTopology_IsChild ": %s, "
+ kWPANTUNDValueMapKey_NetworkTopology_RxOnWhenIdle ": %s, "
+ kWPANTUNDValueMapKey_NetworkTopology_FullFunction ": %s, "
+ kWPANTUNDValueMapKey_NetworkTopology_SecureDataRequest ": %s, "
+ kWPANTUNDValueMapKey_NetworkTopology_FullNetworkData ": %s",
+ mExtAddress[0], mExtAddress[1], mExtAddress[2], mExtAddress[3],
+ mExtAddress[4], mExtAddress[5], mExtAddress[6], mExtAddress[7],
+ mRloc16,
+ mLinkQualityIn,
+ mAverageRssi,
+ mAge,
+ mLinkFrameCounter,
+ mMleFrameCounter,
+ mIsChild ? "yes" : "no",
+ mRxOnWhenIdle ? "yes" : "no",
+ mFullFunction ? "yes" : "no",
+ mSecureDataRequest ? "yes" : "no",
+ mFullNetworkData ? "yes" : "no"
+ );
+ }
+
+ return std::string(c_string);
+}
+
+ValueMap
+SpinelNCPTaskGetNetworkTopology::TableEntry::get_as_valuemap(void) const
+{
+ ValueMap entryMap;
+ uint64_t addr;
+
+ addr = (uint64_t) mExtAddress[7];
+ addr |= (uint64_t) mExtAddress[6] << 8;
+ addr |= (uint64_t) mExtAddress[5] << 16;
+ addr |= (uint64_t) mExtAddress[4] << 24;
+ addr |= (uint64_t) mExtAddress[3] << 32;
+ addr |= (uint64_t) mExtAddress[2] << 40;
+ addr |= (uint64_t) mExtAddress[1] << 48;
+ addr |= (uint64_t) mExtAddress[0] << 56;
+
+#define SPINEL_TOPO_MAP_INSERT(KEY, VAL) entryMap.insert( std::pair<std::string, boost::any>( KEY, VAL ) )
+
+ SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_ExtAddress, addr );
+ SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_RLOC16, mRloc16 );
+ SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_LinkQualityIn, mLinkQualityIn );
+ SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_AverageRssi, mAverageRssi );
+ SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_Age, mAge );
+ SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_RxOnWhenIdle, mRxOnWhenIdle );
+ SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_FullFunction, mFullFunction );
+ SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_SecureDataRequest, mSecureDataRequest );
+ SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_FullNetworkData, mFullNetworkData );
+
+ if (mType == kChildTable) {
+ SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_Timeout, mTimeout );
+ SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_NetworkDataVersion, mNetworkDataVersion );
+ } else {
+ SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_LinkFrameCounter, mLinkFrameCounter );
+ SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_MleFrameCounter, mMleFrameCounter );
+ SPINEL_TOPO_MAP_INSERT( kWPANTUNDValueMapKey_NetworkTopology_IsChild, mIsChild );
+ }
+
+ return entryMap;
+}
diff --git a/src/ncp-spinel/SpinelNCPTaskGetNetworkTopology.h b/src/ncp-spinel/SpinelNCPTaskGetNetworkTopology.h
new file mode 100644
index 0000000..bdab0cd
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPTaskGetNetworkTopology.h
@@ -0,0 +1,117 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __wpantund__SpinelNCPTaskGetNetworkTopology__
+#define __wpantund__SpinelNCPTaskGetNetworkTopology__
+
+#include <list>
+#include <string>
+#include "ValueMap.h"
+#include "SpinelNCPTask.h"
+#include "SpinelNCPInstance.h"
+
+using namespace nl;
+using namespace nl::wpantund;
+
+namespace nl {
+namespace wpantund {
+
+class SpinelNCPTaskGetNetworkTopology : public SpinelNCPTask
+{
+public:
+
+ enum Type
+ {
+ kChildTable, // Get the child table
+ kNeighborTable // Get the neighbor table
+ };
+
+ enum ResultFormat
+ {
+ kResultFormat_StringArray, // Returns the child/neighbor table as an array of std::string(s) (one per child).
+ kResultFormat_ValueMapArray, // Returns the child/neighbor table as an array of ValueMap dictionary.
+ };
+
+ enum
+ {
+ kThreadMode_RxOnWhenIdle = (1 << 3),
+ kThreadMode_SecureDataRequest = (1 << 2),
+ kThreadMode_FullFunctionDevice = (1 << 1),
+ kThreadMode_FullNetworkData = (1 << 0),
+ };
+
+ // This struct defines a common table entry to store either a child info or a neighbor info
+ struct TableEntry
+ {
+ Type mType; // Indicates if this entry is for a child or a neighbor
+
+ // Common fields for both child info and neighbor info
+ uint8_t mExtAddress[8];
+ uint32_t mAge;
+ uint16_t mRloc16;
+ uint8_t mLinkQualityIn;
+ int8_t mAverageRssi;
+ bool mRxOnWhenIdle : 1;
+ bool mSecureDataRequest : 1;
+ bool mFullFunction : 1;
+ bool mFullNetworkData : 1;
+
+ // Child info only
+ uint32_t mTimeout;
+ uint8_t mNetworkDataVersion;
+
+ // Neighbor info only
+ uint32_t mLinkFrameCounter;
+ uint32_t mMleFrameCounter;
+ bool mIsChild : 1;
+
+ public:
+ std::string get_as_string(void) const;
+ ValueMap get_as_valuemap(void) const;
+ };
+
+ typedef std::list<TableEntry> Table;
+
+public:
+ SpinelNCPTaskGetNetworkTopology(
+ SpinelNCPInstance *instance,
+ CallbackWithStatusArg1 cb,
+ Type table_type = kChildTable,
+ ResultFormat result_format = kResultFormat_StringArray
+ );
+ virtual int vprocess_event(int event, va_list args);
+
+ // Parses the spinel child table property and updates the child_table
+ static int prase_child_table(const uint8_t *data_in, spinel_size_t data_len, Table& child_table);
+
+ // Parses the spinel neighbor table property and updates the neighbor_table
+ static int prase_neighbor_table(const uint8_t *data_in, spinel_size_t data_len, Table& neighbor_table);
+
+private:
+ Type mType;
+ Table mTable;
+ ResultFormat mResultFormat;
+};
+
+
+}; // namespace wpantund
+}; // namespace nl
+
+
+#endif /* defined(__wpantund__SpinelNCPTaskGetNetworkTopology__) */
diff --git a/src/ncp-spinel/SpinelNCPTaskJoin.cpp b/src/ncp-spinel/SpinelNCPTaskJoin.cpp
new file mode 100644
index 0000000..98c3902
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPTaskJoin.cpp
@@ -0,0 +1,371 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "assert-macros.h"
+#include <syslog.h>
+#include <errno.h>
+#include "SpinelNCPTaskJoin.h"
+#include "SpinelNCPInstance.h"
+#include "any-to.h"
+#include "spinel-extra.h"
+
+using namespace nl;
+using namespace nl::wpantund;
+
+nl::wpantund::SpinelNCPTaskJoin::SpinelNCPTaskJoin(
+ SpinelNCPInstance* instance,
+ CallbackWithStatusArg1 cb,
+ const ValueMap& options
+): SpinelNCPTask(instance, cb), mOptions(options), mLastState(instance->get_ncp_state())
+{
+}
+
+void
+nl::wpantund::SpinelNCPTaskJoin::finish(int status, const boost::any& value)
+{
+ SpinelNCPTask::finish(status, value);
+ if ( (status != kWPANTUNDStatus_InProgress)
+ && !ncp_state_is_associated(mInstance->get_ncp_state())
+ ) {
+ mInstance->change_ncp_state(mLastState);
+ }
+}
+
+int
+nl::wpantund::SpinelNCPTaskJoin::vprocess_event(int event, va_list args)
+{
+ int ret = kWPANTUNDStatus_Failure;
+ int last_status = peek_ncp_callback_status(event, args);
+
+ EH_BEGIN();
+
+
+ if (!mInstance->mEnabled) {
+ ret = kWPANTUNDStatus_InvalidWhenDisabled;
+ finish(ret);
+ EH_EXIT();
+ }
+
+ if (mInstance->get_ncp_state() == UPGRADING) {
+ ret = kWPANTUNDStatus_InvalidForCurrentState;
+ finish(ret);
+ EH_EXIT();
+ }
+
+ // Wait for a bit to see if the NCP will enter the right state.
+ EH_REQUIRE_WITHIN(
+ NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT,
+ !ncp_state_is_initializing(mInstance->get_ncp_state()),
+ on_error
+ );
+
+ if (ncp_state_is_associated(mInstance->get_ncp_state())) {
+ ret = kWPANTUNDStatus_Already;
+ finish(ret);
+ EH_EXIT();
+ }
+
+ // The first event to a task is EVENT_STARTING_TASK. The following
+ // line makes sure that we don't start processing this task
+ // until it is properly scheduled. All tasks immediately receive
+ // the initial `EVENT_STARTING_TASK` event, but further events
+ // will only be received by that task once it is that task's turn
+ // to execute.
+ EH_WAIT_UNTIL(EVENT_STARTING_TASK != event);
+
+ // Clear any previously saved network settings
+ mNextCommand = SpinelPackData(SPINEL_FRAME_PACK_CMD_NET_CLEAR);
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+ ret = mNextCommandRet;
+ require_noerr(ret, on_error);
+
+
+ mLastState = mInstance->get_ncp_state();
+ mInstance->change_ncp_state(ASSOCIATING);
+
+ if (mOptions.count(kWPANTUNDProperty_NetworkNodeType)) {
+ NodeType node_type;
+ bool isRouterRoleEnabled;
+
+ node_type = string_to_node_type(any_to_string(mOptions[kWPANTUNDProperty_NetworkNodeType]));
+
+ if ((node_type == ROUTER) || (node_type == LEADER)) {
+ if (!mInstance->mCapabilities.count(SPINEL_CAP_ROLE_ROUTER)) {
+ // We cannot join as a router/leader unless we are router-capable
+ ret = kWPANTUNDStatus_FeatureNotSupported;
+ goto on_error;
+ }
+ isRouterRoleEnabled = true;
+
+ } else if (node_type == END_DEVICE) {
+ isRouterRoleEnabled = false;
+
+ } else if (node_type == SLEEPY_END_DEVICE) {
+ if (!mInstance->mCapabilities.count(SPINEL_CAP_ROLE_SLEEPY)) {
+ ret = kWPANTUNDStatus_FeatureNotSupported;
+ goto on_error;
+ }
+ isRouterRoleEnabled = false;
+
+ } else if (node_type == LURKER) {
+ if (!mInstance->mCapabilities.count(SPINEL_CAP_NEST_LEGACY_INTERFACE)) {
+ ret = kWPANTUNDStatus_FeatureNotSupported;
+ goto on_error;
+ }
+ isRouterRoleEnabled = true;
+
+ } else {
+ ret = kWPANTUNDStatus_InvalidArgument;
+ goto on_error;
+ }
+
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_BOOL_S),
+ SPINEL_PROP_THREAD_ROUTER_ROLE_ENABLED,
+ isRouterRoleEnabled
+ );
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ require_noerr(ret, on_error);
+ }
+
+ // Turn off promiscuous mode, if it happens to be on
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT8_S),
+ SPINEL_PROP_MAC_PROMISCUOUS_MODE,
+ SPINEL_MAC_PROMISCUOUS_MODE_OFF
+ );
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+ ret = mNextCommandRet;
+ check_noerr(ret);
+
+ if (mOptions.count(kWPANTUNDProperty_NCPChannel)) {
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT8_S),
+ SPINEL_PROP_PHY_CHAN,
+ any_to_int(mOptions[kWPANTUNDProperty_NCPChannel])
+ );
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ require_noerr(ret, on_error);
+
+ }
+
+ if (mOptions.count(kWPANTUNDProperty_NetworkPANID)) {
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT16_S),
+ SPINEL_PROP_MAC_15_4_PANID,
+ any_to_int(mOptions[kWPANTUNDProperty_NetworkPANID])
+ );
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ require_noerr(ret, on_error);
+ }
+
+ if (mOptions.count(kWPANTUNDProperty_NetworkXPANID)) {
+ {
+ uint64_t xpanid(any_to_uint64((mOptions[kWPANTUNDProperty_NetworkXPANID])));
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ reverse_bytes(reinterpret_cast<uint8_t*>(&xpanid), sizeof(xpanid));
+#endif
+
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_DATA_S),
+ SPINEL_PROP_NET_XPANID,
+ &xpanid,
+ sizeof(xpanid)
+ );
+ }
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ require_noerr(ret, on_error);
+ }
+
+ if (mOptions.count(kWPANTUNDProperty_NetworkName)) {
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UTF8_S),
+ SPINEL_PROP_NET_NETWORK_NAME,
+ any_to_string(mOptions[kWPANTUNDProperty_NetworkName]).c_str()
+ );
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ require_noerr(ret, on_error);
+ }
+
+ if (mOptions.count(kWPANTUNDProperty_NetworkKey)) {
+ {
+ nl::Data data(any_to_data(mOptions[kWPANTUNDProperty_NetworkKey]));
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_DATA_S),
+ SPINEL_PROP_NET_MASTER_KEY,
+ data.data(),
+ data.size()
+ );
+ }
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ require_noerr(ret, on_error);
+ }
+
+ if (mOptions.count(kWPANTUNDProperty_NetworkKeyIndex)) {
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT32_S),
+ SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER,
+ any_to_int(mOptions[kWPANTUNDProperty_NetworkKeyIndex])
+ );
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ require_noerr(ret, on_error);
+ }
+
+ if (mOptions.count(kWPANTUNDProperty_IPv6MeshLocalAddress)) {
+ {
+ struct in6_addr addr = any_to_ipv6(mOptions[kWPANTUNDProperty_IPv6MeshLocalAddress]);
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_IPv6ADDR_S SPINEL_DATATYPE_UINT8_S),
+ SPINEL_PROP_IPV6_ML_PREFIX,
+ &addr,
+ 64
+ );
+ }
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ require_noerr(ret, on_error);
+ } else if (mOptions.count(kWPANTUNDProperty_IPv6MeshLocalPrefix)) {
+ {
+ struct in6_addr addr = any_to_ipv6(mOptions[kWPANTUNDProperty_IPv6MeshLocalPrefix]);
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_IPv6ADDR_S SPINEL_DATATYPE_UINT8_S),
+ SPINEL_PROP_IPV6_ML_PREFIX,
+ &addr,
+ 64
+ );
+ }
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ require_noerr(ret, on_error);
+ }
+
+
+ // Now bring up the network by bringing up the interface and the stack.
+
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_BOOL_S),
+ SPINEL_PROP_NET_IF_UP,
+ true
+ );
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ require((ret == kWPANTUNDStatus_Ok) || (ret == kWPANTUNDStatus_Already), on_error);
+
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_BOOL_S),
+ SPINEL_PROP_NET_REQUIRE_JOIN_EXISTING,
+ true
+ );
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ check_noerr(ret);
+
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_BOOL_S),
+ SPINEL_PROP_NET_STACK_UP,
+ true
+ );
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ ret = mNextCommandRet;
+
+ require_noerr(ret, on_error);
+
+ EH_REQUIRE_WITHIN(
+ NCP_JOIN_TIMEOUT,
+ ((last_status >= SPINEL_STATUS_JOIN__BEGIN) && (last_status < SPINEL_STATUS_JOIN__END))
+ || ncp_state_is_associated(mInstance->get_ncp_state()),
+ on_error
+ );
+
+ ret = last_status
+ ? WPANTUND_NCPERROR_TO_STATUS(last_status)
+ : kWPANTUNDStatus_Ok;
+
+ if ( (last_status == SPINEL_STATUS_JOIN_SECURITY)
+ || (last_status == SPINEL_STATUS_JOIN_FAILURE)
+ ) {
+ mInstance->change_ncp_state(CREDENTIALS_NEEDED);
+ ret = kWPANTUNDStatus_InProgress;
+ } else if ((last_status >= SPINEL_STATUS_JOIN__BEGIN) && (last_status < SPINEL_STATUS_JOIN__END)) {
+ ret = kWPANTUNDStatus_JoinFailedUnknown;
+ }
+
+ finish(ret);
+
+ EH_EXIT();
+
+on_error:
+
+ if (ret == kWPANTUNDStatus_Ok) {
+ ret = kWPANTUNDStatus_Failure;
+ }
+
+ syslog(LOG_ERR, "Join failed: %d", ret);
+
+ finish(ret);
+
+ EH_END();
+}
diff --git a/src/ncp-spinel/SpinelNCPTaskJoin.h b/src/ncp-spinel/SpinelNCPTaskJoin.h
new file mode 100644
index 0000000..e5534f4
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPTaskJoin.h
@@ -0,0 +1,54 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __wpantund__SpinelNCPTaskJoin__
+#define __wpantund__SpinelNCPTaskJoin__
+
+#include "SpinelNCPTask.h"
+#include "SpinelNCPInstance.h"
+#include "ValueMap.h"
+
+using namespace nl;
+using namespace nl::wpantund;
+
+namespace nl {
+namespace wpantund {
+
+class SpinelNCPTaskJoin : public SpinelNCPTask
+{
+public:
+ SpinelNCPTaskJoin(
+ SpinelNCPInstance* instance,
+ CallbackWithStatusArg1 cb,
+ const ValueMap& options
+ );
+ virtual int vprocess_event(int event, va_list args);
+ virtual void finish(int status, const boost::any& value = boost::any());
+
+
+private:
+ ValueMap mOptions;
+ NCPState mLastState;
+};
+
+}; // namespace wpantund
+}; // namespace nl
+
+
+#endif /* defined(__wpantund__SpinelNCPTaskJoin__) */
diff --git a/src/ncp-spinel/SpinelNCPTaskLeave.cpp b/src/ncp-spinel/SpinelNCPTaskLeave.cpp
new file mode 100644
index 0000000..d9ec8ad
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPTaskLeave.cpp
@@ -0,0 +1,144 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "assert-macros.h"
+#include <syslog.h>
+#include <errno.h>
+#include "SpinelNCPTaskLeave.h"
+#include "SpinelNCPInstance.h"
+#include "spinel-extra.h"
+
+using namespace nl;
+using namespace nl::wpantund;
+
+nl::wpantund::SpinelNCPTaskLeave::SpinelNCPTaskLeave(
+ SpinelNCPInstance* instance,
+ CallbackWithStatusArg1 cb
+): SpinelNCPTask(instance, cb)
+{
+}
+
+int
+nl::wpantund::SpinelNCPTaskLeave::vprocess_event(int event, va_list args)
+{
+ int ret = kWPANTUNDStatus_Failure;
+
+ EH_BEGIN();
+
+ if (!mInstance->mEnabled) {
+ ret = kWPANTUNDStatus_InvalidWhenDisabled;
+ finish(ret);
+ EH_EXIT();
+ }
+
+ if (mInstance->get_ncp_state() == UPGRADING) {
+ ret = kWPANTUNDStatus_InvalidForCurrentState;
+ finish(ret);
+ EH_EXIT();
+ }
+
+ // Wait for a bit to see if the NCP will enter the right state.
+ EH_REQUIRE_WITHIN(
+ NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT,
+ !ncp_state_is_initializing(mInstance->get_ncp_state()),
+ on_error
+ );
+
+ // The first event to a task is EVENT_STARTING_TASK. The following
+ // line makes sure that we don't start processing this task
+ // until it is properly scheduled. All tasks immediately receive
+ // the initial `EVENT_STARTING_TASK` event, but further events
+ // will only be received by that task once it is that task's turn
+ // to execute.
+ EH_WAIT_UNTIL(EVENT_STARTING_TASK != event);
+
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_BOOL_S),
+ SPINEL_PROP_NET_STACK_UP,
+ false
+ );
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+ ret = mNextCommandRet;
+ require_noerr(ret, on_error);
+
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_BOOL_S),
+ SPINEL_PROP_NET_IF_UP,
+ false
+ );
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+ ret = mNextCommandRet;
+ require_noerr(ret, on_error);
+
+ // Clear any saved network settings.
+ mNextCommand = SpinelPackData(SPINEL_FRAME_PACK_CMD_NET_CLEAR);
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+ ret = mNextCommandRet;
+ require_noerr(ret, on_error);
+
+ mInstance->mNetworkKey = Data();
+ mInstance->mNetworkKeyIndex = 0;
+
+ // Issue a Reset
+ mNextCommand = SpinelPackData(SPINEL_FRAME_PACK_CMD_RESET);
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+ ret = mNextCommandRet;
+ require_noerr(ret, on_error);
+
+ // Wait for re-initialization of NCP to start.
+ EH_REQUIRE_WITHIN(
+ NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT,
+ ncp_state_is_initializing(mInstance->get_ncp_state()),
+ on_error
+ );
+
+ // Wait for re-initialization to complete.
+ EH_REQUIRE_WITHIN(
+ NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT,
+ !ncp_state_is_initializing(mInstance->get_ncp_state()) &&
+ (mInstance->mDriverState == SpinelNCPInstance::NORMAL_OPERATION),
+ on_error
+ );
+
+ ret = kWPANTUNDStatus_Ok;
+
+ syslog(LOG_INFO, "Leave succeeded");
+
+ finish(ret);
+
+ EH_EXIT();
+
+on_error:
+
+ if (ret == kWPANTUNDStatus_Ok) {
+ ret = kWPANTUNDStatus_Failure;
+ }
+
+ syslog(LOG_ERR, "Leave failed: %d", ret);
+
+ mInstance->reinitialize_ncp();
+
+ finish(ret);
+
+ EH_END();
+}
diff --git a/src/ncp-spinel/SpinelNCPTaskLeave.h b/src/ncp-spinel/SpinelNCPTaskLeave.h
new file mode 100644
index 0000000..964b373
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPTaskLeave.h
@@ -0,0 +1,46 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __wpantund__SpinelNCPTaskLeave__
+#define __wpantund__SpinelNCPTaskLeave__
+
+#include "SpinelNCPTask.h"
+#include "SpinelNCPInstance.h"
+
+using namespace nl;
+using namespace nl::wpantund;
+
+namespace nl {
+namespace wpantund {
+
+class SpinelNCPTaskLeave : public SpinelNCPTask
+{
+public:
+ SpinelNCPTaskLeave(
+ SpinelNCPInstance* instance,
+ CallbackWithStatusArg1 cb
+ );
+ virtual int vprocess_event(int event, va_list args);
+};
+
+}; // namespace wpantund
+}; // namespace nl
+
+
+#endif /* defined(__wpantund__SpinelNCPTaskLeave__) */
diff --git a/src/ncp-spinel/SpinelNCPTaskScan.cpp b/src/ncp-spinel/SpinelNCPTaskScan.cpp
new file mode 100644
index 0000000..e726d06
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPTaskScan.cpp
@@ -0,0 +1,239 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "assert-macros.h"
+#include <syslog.h>
+#include <errno.h>
+#include "SpinelNCPTaskScan.h"
+#include "SpinelNCPInstance.h"
+#include "spinel-extra.h"
+
+using namespace nl;
+using namespace nl::wpantund;
+
+nl::wpantund::SpinelNCPTaskScan::SpinelNCPTaskScan(
+ SpinelNCPInstance* instance,
+ CallbackWithStatusArg1 cb,
+ uint32_t channel_mask,
+ uint16_t scan_period,
+ ScanType scan_type
+): SpinelNCPTask(instance, cb), mChannelMaskLen(0), mScanPeriod(scan_period), mScanType(scan_type)
+{
+ uint8_t i;
+
+ for (i = 0; i < 32; i++) {
+ if (channel_mask & (1<<i)) {
+ mChannelMaskData[mChannelMaskLen++] = i;
+ }
+ }
+}
+
+void
+nl::wpantund::SpinelNCPTaskScan::finish(int status, const boost::any& value)
+{
+ SpinelNCPTask::finish(status, value);
+}
+
+
+int
+nl::wpantund::SpinelNCPTaskScan::vprocess_event(int event, va_list args)
+{
+ int ret = 0;
+
+ EH_BEGIN();
+
+
+ if (!mInstance->mEnabled) {
+ ret = kWPANTUNDStatus_InvalidWhenDisabled;
+ finish(ret);
+ EH_EXIT();
+ }
+
+ if (mInstance->get_ncp_state() == UPGRADING) {
+ ret = kWPANTUNDStatus_InvalidForCurrentState;
+ finish(ret);
+ EH_EXIT();
+ }
+
+ // Wait for a bit to see if the NCP will enter the right state.
+ EH_REQUIRE_WITHIN(
+ NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT,
+ !ncp_state_is_initializing(mInstance->get_ncp_state())
+ && (mInstance->get_ncp_state() != ASSOCIATING)
+ && (mInstance->get_ncp_state() != CREDENTIALS_NEEDED),
+ on_error
+ );
+
+ // The first event to a task is EVENT_STARTING_TASK. The following
+ // line makes sure that we don't start processing this task
+ // until it is properly scheduled. All tasks immediately receive
+ // the initial `EVENT_STARTING_TASK` event, but further events
+ // will only be received by that task once it is that task's turn
+ // to execute.
+ EH_WAIT_UNTIL(EVENT_STARTING_TASK != event);
+
+
+ // Set channel mask
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_DATA_S),
+ SPINEL_PROP_MAC_SCAN_MASK,
+ mChannelMaskData,
+ mChannelMaskLen
+ );
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+ ret = mNextCommandRet;
+ require_noerr(ret, on_error);
+
+
+ // Set delay period
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT16_S),
+ SPINEL_PROP_MAC_SCAN_PERIOD,
+ mScanPeriod
+ );
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+ ret = mNextCommandRet;
+ require_noerr(ret, on_error);
+
+
+ // Start the scan.
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT8_S),
+ SPINEL_PROP_MAC_SCAN_STATE,
+ (mScanType == kScanTypeNet) ? SPINEL_SCAN_STATE_BEACON : SPINEL_SCAN_STATE_ENERGY
+ );
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+ ret = mNextCommandRet;
+ require_noerr(ret, on_error);
+
+ do {
+ EH_REQUIRE_WITHIN(
+ 15,
+ event == EVENT_NCP_PROP_VALUE_IS
+ || event == EVENT_NCP_PROP_VALUE_INSERTED,
+ on_error
+ );
+
+ spinel_prop_key_t prop_key = va_arg_small(args, spinel_prop_key_t);
+ const uint8_t* data_ptr = va_arg(args, const uint8_t*);
+ spinel_size_t data_len = va_arg(args, spinel_size_t);
+
+ if ((prop_key == SPINEL_PROP_MAC_SCAN_BEACON) && (mScanType == kScanTypeNet)) {
+ const spinel_eui64_t* laddr = NULL;
+ const char* networkid = "";
+ const uint8_t* xpanid = NULL;
+ unsigned int xpanid_len = 0;
+ unsigned int proto = 0;
+ uint16_t panid = 0xFFFF;
+ uint16_t saddr = 0xFFFF;
+ uint8_t chan = 0;
+ uint8_t lqi = 0x00;
+ int8_t rssi = 0x00;
+ uint8_t flags = 0x00;
+
+ syslog(LOG_DEBUG, "Got a beacon");
+
+ spinel_datatype_unpack(
+ data_ptr,
+ data_len,
+ "CcT(ESSC.)T(iCUD.).",
+ &chan,
+ &rssi,
+
+ &laddr,
+ &saddr,
+ &panid,
+ &lqi,
+
+ &proto,
+ &flags,
+ &networkid,
+ &xpanid, &xpanid_len
+ );
+
+ if ((xpanid_len != 8) && (xpanid_len != 0)) {
+ break;
+ }
+
+ WPAN::NetworkInstance network(
+ networkid,
+ xpanid,
+ panid,
+ chan,
+ (flags & SPINEL_BEACON_THREAD_FLAG_JOINABLE)
+ );
+ network.rssi = rssi;
+ network.type = proto;
+ network.lqi = lqi;
+ network.saddr = saddr;
+
+ if (laddr) {
+ memcpy(network.hwaddr, laddr, sizeof(network.hwaddr));
+ }
+
+ mInstance->get_control_interface().mOnNetScanBeacon(network);
+
+ } else if ((prop_key == SPINEL_PROP_MAC_ENERGY_SCAN_RESULT) && (mScanType == kScanTypeEnergy)) {
+ EnergyScanResultEntry result;
+
+ syslog(LOG_DEBUG, "Got an Energy Scan result");
+
+ spinel_datatype_unpack(
+ data_ptr,
+ data_len,
+ "Cc",
+ &result.mChannel,
+ &result.mMaxRssi
+ );
+
+ mInstance->get_control_interface().mOnEnergyScanResult(result);
+
+ } else if (prop_key == SPINEL_PROP_MAC_SCAN_STATE) {
+ int scan_state;
+ spinel_datatype_unpack(data_ptr, data_len, "i", &scan_state);
+
+ if (scan_state == SPINEL_SCAN_STATE_IDLE) {
+ break;
+ }
+ }
+
+ // Change the event type to 'IDLE' so that we
+ // don't try to process this event once than once.
+ event = EVENT_IDLE;
+ } while(true);
+
+ finish(ret);
+
+ EH_EXIT();
+
+on_error:
+ if (ret == kWPANTUNDStatus_Ok) {
+ ret = kWPANTUNDStatus_Failure;
+ }
+
+ syslog(LOG_ERR, "Scan failed: %d", ret);
+
+ finish(ret);
+
+ EH_END();
+}
diff --git a/src/ncp-spinel/SpinelNCPTaskScan.h b/src/ncp-spinel/SpinelNCPTaskScan.h
new file mode 100644
index 0000000..e7c35f6
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPTaskScan.h
@@ -0,0 +1,65 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __wpantund__SpinelNCPTaskScan__
+#define __wpantund__SpinelNCPTaskScan__
+
+#include "SpinelNCPTask.h"
+#include "SpinelNCPInstance.h"
+
+using namespace nl;
+using namespace nl::wpantund;
+
+namespace nl {
+namespace wpantund {
+
+class SpinelNCPTaskScan : public SpinelNCPTask
+{
+public:
+ enum ScanType {
+ kScanTypeNet = 0,
+ kScanTypeEnergy,
+ };
+
+ enum {
+ kDefaultScanPeriod = 200,
+ };
+
+ SpinelNCPTaskScan(
+ SpinelNCPInstance* instance,
+ CallbackWithStatusArg1 cb,
+ uint32_t channel_mask,
+ uint16_t channel_scan_period = kDefaultScanPeriod, // per channel in ms
+ ScanType scan_type = kScanTypeNet
+ );
+ virtual int vprocess_event(int event, va_list args);
+ virtual void finish(int status, const boost::any& value = boost::any());
+
+private:
+ uint8_t mChannelMaskData[32];
+ uint8_t mChannelMaskLen;
+ uint16_t mScanPeriod; // per channel
+ ScanType mScanType;
+};
+
+}; // namespace wpantund
+}; // namespace nl
+
+
+#endif /* defined(__wpantund__SpinelNCPTaskScan__) */
diff --git a/src/ncp-spinel/SpinelNCPTaskSendCommand.cpp b/src/ncp-spinel/SpinelNCPTaskSendCommand.cpp
new file mode 100644
index 0000000..be729bc
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPTaskSendCommand.cpp
@@ -0,0 +1,369 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "assert-macros.h"
+#include <syslog.h>
+#include <errno.h>
+#include "SpinelNCPTaskSendCommand.h"
+#include "SpinelNCPInstance.h"
+#include "spinel-extra.h"
+
+using namespace nl;
+using namespace nl::wpantund;
+
+static int simple_unpacker(const uint8_t* data_in, spinel_size_t data_len, const std::string& pack_format,
+ boost::any& result);
+
+SpinelNCPTaskSendCommand::Factory::Factory(SpinelNCPInstance* instance):
+ mInstance(instance),
+ mCb(NilReturn()),
+ mTimeout(NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT),
+ mLockProperty(0)
+{
+}
+
+SpinelNCPTaskSendCommand::Factory&
+SpinelNCPTaskSendCommand::Factory::set_callback(const CallbackWithStatusArg1 &cb)
+{
+ mCb = cb;
+ return *this;
+}
+
+SpinelNCPTaskSendCommand::Factory&
+SpinelNCPTaskSendCommand::Factory::set_callback(const CallbackWithStatus &cb)
+{
+ mCb = boost::bind(cb, _1);
+ return *this;
+}
+
+SpinelNCPTaskSendCommand::Factory&
+SpinelNCPTaskSendCommand::Factory::add_command(const Data& command)
+{
+ mCommandList.insert(mCommandList.end(), command);
+ return *this;
+}
+
+SpinelNCPTaskSendCommand::Factory&
+SpinelNCPTaskSendCommand::Factory::set_timeout(int timeout)
+{
+ mTimeout = timeout;
+ return *this;
+}
+
+SpinelNCPTaskSendCommand::Factory&
+SpinelNCPTaskSendCommand::Factory::set_reply_format(const std::string& packed_format)
+{
+ mReplyUnpacker = boost::bind(simple_unpacker, _1, _2, packed_format, _3);
+ return *this;
+}
+
+SpinelNCPTaskSendCommand::Factory&
+SpinelNCPTaskSendCommand::Factory::set_reply_unpacker(const ReplyUnpacker& reply_unpacker)
+{
+ mReplyUnpacker = reply_unpacker;
+ return *this;
+}
+
+SpinelNCPTaskSendCommand::Factory&
+SpinelNCPTaskSendCommand::Factory::set_lock_property(int lock_property)
+{
+ mLockProperty = lock_property;
+ return *this;
+}
+
+boost::shared_ptr<SpinelNCPTask>
+SpinelNCPTaskSendCommand::Factory::finish(void)
+{
+ return boost::shared_ptr<SpinelNCPTask>(new SpinelNCPTaskSendCommand(*this));
+}
+
+nl::wpantund::SpinelNCPTaskSendCommand::SpinelNCPTaskSendCommand(
+ const Factory& factory
+): SpinelNCPTask(factory.mInstance, factory.mCb),
+ mCommandList(factory.mCommandList),
+ mLockProperty(factory.mLockProperty),
+ mReplyUnpacker(factory.mReplyUnpacker),
+ mRetVal(kWPANTUNDStatus_Failure)
+{
+ mNextCommandTimeout = factory.mTimeout;
+}
+
+static boost::any
+spinel_iter_to_any(spinel_datatype_iter_t *iter)
+{
+ boost::any ret;
+ spinel_status_t status;
+
+ switch(iter->pack_format[0]) {
+ case SPINEL_DATATYPE_BOOL_C:
+ {
+ bool val(0);
+ status = spinel_datatype_iter_unpack(iter, &val);
+ require_noerr(status, bail);
+ ret = val;
+ }
+ break;
+
+ case SPINEL_DATATYPE_UINT8_C:
+ {
+ uint8_t val(0);
+ status = spinel_datatype_iter_unpack(iter, &val);
+ require_noerr(status, bail);
+ ret = val;
+ }
+ break;
+
+ case SPINEL_DATATYPE_INT8_C:
+ {
+ int8_t val(0);
+ status = spinel_datatype_iter_unpack(iter, &val);
+ require_noerr(status, bail);
+ ret = (int)val;
+ }
+ break;
+
+ case SPINEL_DATATYPE_UINT16_C:
+ {
+ uint16_t val(0);
+ status = spinel_datatype_iter_unpack(iter, &val);
+ require_noerr(status, bail);
+ ret = val;
+ }
+ break;
+
+ case SPINEL_DATATYPE_INT16_C:
+ {
+ int16_t val(0);
+ status = spinel_datatype_iter_unpack(iter, &val);
+ require_noerr(status, bail);
+ ret = val;
+ }
+ break;
+
+ case SPINEL_DATATYPE_UINT32_C:
+ {
+ uint32_t val(0);
+ status = spinel_datatype_iter_unpack(iter, &val);
+ require_noerr(status, bail);
+ ret = val;
+ }
+ break;
+
+ case SPINEL_DATATYPE_INT32_C:
+ {
+ int32_t val(0);
+ status = spinel_datatype_iter_unpack(iter, &val);
+ require_noerr(status, bail);
+ ret = val;
+ }
+ break;
+
+ case SPINEL_DATATYPE_UINT_PACKED_C:
+ {
+ unsigned int val(0);
+ status = spinel_datatype_iter_unpack(iter, &val);
+ require_noerr(status, bail);
+ ret = val;
+ }
+ break;
+
+ case SPINEL_DATATYPE_IPv6ADDR_C:
+ {
+ struct in6_addr *val = NULL;
+ status = spinel_datatype_iter_unpack(iter, &val);
+ require_noerr(status, bail);
+ ret = in6_addr_to_string(*val);
+ }
+ break;
+
+ case SPINEL_DATATYPE_EUI64_C:
+ {
+ const spinel_eui64_t *val(NULL);
+ status = spinel_datatype_iter_unpack(iter, &val);
+ require_noerr(status, bail);
+ ret = Data(val->bytes, sizeof(val->bytes));
+ }
+ break;
+
+ case SPINEL_DATATYPE_EUI48_C:
+ {
+ const spinel_eui48_t *val(NULL);
+ status = spinel_datatype_iter_unpack(iter, &val);
+ require_noerr(status, bail);
+ ret = Data(val->bytes, sizeof(val->bytes));
+ }
+ break;
+
+ case SPINEL_DATATYPE_DATA_C:
+ {
+ const uint8_t *val_ptr(NULL);
+ spinel_size_t val_len;
+ status = spinel_datatype_iter_unpack(iter, &val_ptr, &val_len);
+ require_noerr(status, bail);
+ ret = Data(val_ptr, val_len);
+ }
+ break;
+
+ case SPINEL_DATATYPE_UTF8_C:
+ {
+ const char *val(NULL);
+ status = spinel_datatype_iter_unpack(iter, &val);
+ require_noerr(status, bail);
+ ret = std::string(val);
+ }
+ break;
+
+ case SPINEL_DATATYPE_STRUCT_C:
+ goto bail;
+
+ case SPINEL_DATATYPE_ARRAY_C:
+ // TODO: Recursively parse this
+ goto bail;
+
+ default:
+ goto bail;
+
+ }
+
+bail:
+ return ret;
+}
+
+static boost::any
+spinel_packed_to_any(const uint8_t* data_in, spinel_size_t data_len, const char* pack_format)
+{
+ spinel_datatype_iter_t spinel_iter = {};
+ spinel_datatype_iter_start(&spinel_iter, data_in, data_len, pack_format);
+
+ return spinel_iter_to_any(&spinel_iter);
+}
+
+static int
+simple_unpacker(const uint8_t* data_in, spinel_size_t data_len, const std::string& pack_format, boost::any& result)
+{
+ int retval = kWPANTUNDStatus_Ok;
+
+ try {
+ result = spinel_packed_to_any(data_in, data_len, pack_format.c_str());
+
+ } catch(...) {
+ retval = kWPANTUNDStatus_Failure;
+ }
+
+ return retval;
+}
+
+int
+nl::wpantund::SpinelNCPTaskSendCommand::vprocess_event(int event, va_list args)
+{
+ EH_BEGIN();
+
+ mRetVal = kWPANTUNDStatus_Failure;
+
+ // The first event to a task is EVENT_STARTING_TASK. The following
+ // line makes sure that we don't start processing this task
+ // until it is properly scheduled. All tasks immediately receive
+ // the initial `EVENT_STARTING_TASK` event, but further events
+ // will only be received by that task once it is that task's turn
+ // to execute.
+ EH_WAIT_UNTIL(EVENT_STARTING_TASK != event);
+
+ if (mLockProperty != 0) {
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_BOOL_S),
+ mLockProperty,
+ true
+ );
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ mRetVal = mNextCommandRet;
+
+ // In case of BUSY error status (meaning the `ALLOW_LOCAL_NET_DATA_CHANGE`
+ // was already true), allow the operation to proceed.
+
+ require((mRetVal == kWPANTUNDStatus_Ok) || (mRetVal == kWPANTUNDStatus_Busy), on_error);
+ }
+
+ mRetVal = kWPANTUNDStatus_Ok;
+
+ mCommandIter = mCommandList.begin();
+
+ while ( (mRetVal == kWPANTUNDStatus_Ok)
+ && (mCommandList.end() != mCommandIter)
+ ) {
+ mNextCommand = *mCommandIter++;
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+ }
+
+ mRetVal = mNextCommandRet;
+
+ require_noerr(mRetVal, on_error);
+
+ if ( mReplyUnpacker
+ && (kWPANTUNDStatus_Ok == mRetVal)
+ && (EVENT_NCP_PROP_VALUE_IS == event)
+ ) {
+ // Handle the packed response from the last command
+
+ unsigned int key = va_arg(args, unsigned int);
+ const uint8_t* data_in = va_arg(args, const uint8_t*);
+ spinel_size_t data_len = va_arg_small(args, spinel_size_t);
+ (void) key; // Ignored
+
+ mRetVal = mReplyUnpacker(data_in, data_len, mReturnValue);
+ }
+
+on_error:
+
+ if (mRetVal != kWPANTUNDStatus_Ok) {
+ syslog(LOG_ERR, "SendCommand task encountered an error: %d (0x%08X)", mRetVal, mRetVal);
+ }
+
+ // Even in case of failure we proceed to set mLockProperty
+ // to `false`. The error status is checked after this. It is stored in
+ // a class instance variable `mRetVal` so that the value is preserved
+ // over the protothread EH_SPAWN() call.
+
+ if (mLockProperty != 0) {
+ mNextCommand = SpinelPackData(
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_BOOL_S),
+ mLockProperty,
+ false
+ );
+
+ EH_SPAWN(&mSubPT, vprocess_send_command(event, args));
+
+ if (mNextCommandRet != kWPANTUNDStatus_Ok)
+ {
+ mRetVal = mNextCommandRet;
+ }
+
+ check_noerr(mNextCommandRet);
+ }
+
+ finish(mRetVal, mReturnValue);
+
+ EH_END();
+}
diff --git a/src/ncp-spinel/SpinelNCPTaskSendCommand.h b/src/ncp-spinel/SpinelNCPTaskSendCommand.h
new file mode 100644
index 0000000..2f81c9d
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPTaskSendCommand.h
@@ -0,0 +1,90 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __wpantund__SpinelNCPTaskSendCommand__
+#define __wpantund__SpinelNCPTaskSendCommand__
+
+#include "SpinelNCPTask.h"
+#include "SpinelNCPInstance.h"
+
+using namespace nl;
+using namespace nl::wpantund;
+
+namespace nl {
+namespace wpantund {
+
+class SpinelNCPTaskSendCommand : public SpinelNCPTask
+{
+public:
+ typedef boost::function<int (const uint8_t*, spinel_size_t, boost::any&)> ReplyUnpacker;
+
+ class Factory {
+ public:
+
+ friend class SpinelNCPTaskSendCommand;
+
+ Factory(SpinelNCPInstance* instance);
+
+ Factory& set_callback(const CallbackWithStatusArg1 &cb);
+ Factory& set_callback(const CallbackWithStatus &cb);
+ Factory& add_command(const Data& command);
+ Factory& set_timeout(int timeout);
+
+ /* For simple (single type) reply formats, we can use the
+ * `set_reply_format()` and specify the spinel packing format.
+ * For more complicated reply format (e.g., multiple types, structs)
+ * a `ReplyUnpakcer` function pointer can be specified using
+ * `set_reply_unpacker()` which is then used to decode/unpack
+ * the reply spinel message into a `boost::any` output result.
+ */
+ Factory& set_reply_format(const std::string& packed_format);
+ Factory& set_reply_unpacker(const ReplyUnpacker &reply_unpacker);
+
+ Factory& set_lock_property(int lock_property = SPINEL_PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE);
+
+ boost::shared_ptr<SpinelNCPTask> finish(void);
+
+ private:
+ SpinelNCPInstance* mInstance;
+ CallbackWithStatusArg1 mCb;
+ std::list<Data> mCommandList;
+ int mTimeout;
+ ReplyUnpacker mReplyUnpacker;
+ int mLockProperty;
+ };
+
+ SpinelNCPTaskSendCommand(const Factory& factory);
+
+ virtual int vprocess_event(int event, va_list args);
+
+private:
+
+ std::list<Data> mCommandList;
+ std::list<Data>::const_iterator mCommandIter;
+ int mLockProperty;
+ ReplyUnpacker mReplyUnpacker;
+ int mRetVal;
+ boost::any mReturnValue;
+};
+
+}; // namespace wpantund
+}; // namespace nl
+
+
+#endif /* defined(__wpantund__SpinelNCPTaskSendCommand__) */
diff --git a/src/ncp-spinel/SpinelNCPTaskWake.cpp b/src/ncp-spinel/SpinelNCPTaskWake.cpp
new file mode 100644
index 0000000..8e20672
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPTaskWake.cpp
@@ -0,0 +1,97 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "assert-macros.h"
+#include <syslog.h>
+#include <errno.h>
+#include "SpinelNCPTaskWake.h"
+#include "SpinelNCPInstance.h"
+
+using namespace nl;
+using namespace nl::wpantund;
+
+nl::wpantund::SpinelNCPTaskWake::SpinelNCPTaskWake(
+ SpinelNCPInstance* instance,
+ CallbackWithStatusArg1 cb
+): SpinelNCPTask(instance, cb)
+{
+}
+
+void
+nl::wpantund::SpinelNCPTaskWake::finish(int status, const boost::any& value)
+{
+ mInstance->mResetIsExpected = false;
+
+ SpinelNCPTask::finish(status, value);
+}
+
+
+int
+nl::wpantund::SpinelNCPTaskWake::vprocess_event(int event, va_list args)
+{
+ int ret = kWPANTUNDStatus_Failure;
+
+ EH_BEGIN();
+
+ // The first event to a task is EVENT_STARTING_TASK. The following
+ // line makes sure that we don't start processing this task
+ // until it is properly scheduled. All tasks immediately receive
+ // the initial `EVENT_STARTING_TASK` event, but further events
+ // will only be received by that task once it is that task's turn
+ // to execute.
+ EH_WAIT_UNTIL(EVENT_STARTING_TASK != event);
+
+ mInstance->set_ncp_power(true);
+ mInstance->mResetIsExpected = true;
+
+ CONTROL_REQUIRE_PREP_TO_SEND_COMMAND_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, on_error);
+ GetInstance(this)->mOutboundBufferLen = spinel_datatype_pack(GetInstance(this)->mOutboundBuffer, sizeof(GetInstance(this)->mOutboundBuffer), "Ci", 0, SPINEL_CMD_NOOP);
+ CONTROL_REQUIRE_OUTBOUND_BUFFER_FLUSHED_WITHIN(NCP_DEFAULT_COMMAND_SEND_TIMEOUT, on_error);
+
+ EH_REQUIRE_WITHIN(
+ NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT,
+ !ncp_state_is_sleeping(mInstance->get_ncp_state())
+ && (!ncp_state_is_initializing(mInstance->get_ncp_state())),
+ on_error
+ );
+
+ ret = kWPANTUNDStatus_Ok;
+
+ finish(ret);
+
+ EH_EXIT();
+
+on_error:
+
+ if (ret == kWPANTUNDStatus_Ok) {
+ ret = kWPANTUNDStatus_Failure;
+ }
+
+ syslog(LOG_ERR, "Wake failed: %d", ret);
+
+ mInstance->reinitialize_ncp();
+
+ finish(ret);
+
+ EH_END();
+}
diff --git a/src/ncp-spinel/SpinelNCPTaskWake.h b/src/ncp-spinel/SpinelNCPTaskWake.h
new file mode 100644
index 0000000..52bd07f
--- /dev/null
+++ b/src/ncp-spinel/SpinelNCPTaskWake.h
@@ -0,0 +1,47 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __wpantund__SpinelNCPTaskWake__
+#define __wpantund__SpinelNCPTaskWake__
+
+#include "SpinelNCPTask.h"
+#include "SpinelNCPInstance.h"
+
+using namespace nl;
+using namespace nl::wpantund;
+
+namespace nl {
+namespace wpantund {
+
+class SpinelNCPTaskWake : public SpinelNCPTask
+{
+public:
+ SpinelNCPTaskWake(
+ SpinelNCPInstance* instance,
+ CallbackWithStatusArg1 cb
+ );
+ virtual int vprocess_event(int event, va_list args);
+ virtual void finish(int status, const boost::any& value = boost::any());
+};
+
+}; // namespace wpantund
+}; // namespace nl
+
+
+#endif /* defined(__wpantund__SpinelNCPTaskWake__) */
diff --git a/src/ncp-spinel/spinel-extra.c b/src/ncp-spinel/spinel-extra.c
new file mode 100644
index 0000000..fe586ff
--- /dev/null
+++ b/src/ncp-spinel/spinel-extra.c
@@ -0,0 +1,380 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// ----------------------------------------------------------------------------
+// MARK: -
+// MARK: Headers
+
+#include "spinel-extra.h"
+
+#include <assert.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+// ----------------------------------------------------------------------------
+// MARK: -
+
+#ifndef assert_printf
+#define assert_printf(fmt, ...) \
+fprintf(stderr, \
+ __FILE__ ":%d: " fmt "\n", \
+ __LINE__, \
+ __VA_ARGS__)
+#endif
+
+#ifndef require_action
+#define require_action(c, l, a) \
+ do { if (!(c)) { \
+ assert_printf("Requirement Failed (%s)", # c); \
+ a; \
+ goto l; \
+ } } while (0)
+#endif
+
+#ifndef require
+#define require(c, l) require_action(c, l, {})
+#endif
+
+// ----------------------------------------------------------------------------
+// MARK: -
+// MARK: Datatype Iterator
+
+spinel_status_t
+spinel_datatype_iter_start(spinel_datatype_iter_t* iter, const uint8_t* data_in, spinel_size_t data_len, const char* pack_format)
+{
+ iter->data_ptr = data_in;
+ iter->data_len = data_len;
+ iter->pack_format = pack_format;
+
+ return SPINEL_STATUS_OK;
+}
+
+spinel_status_t
+spinel_datatype_iter_next(spinel_datatype_iter_t* iter)
+{
+ spinel_status_t ret = SPINEL_STATUS_PARSE_ERROR;
+ spinel_datatype_iter_t scratchpad = *iter;
+
+ if (!iter->data_ptr || !iter->data_len || !iter->pack_format) {
+ ret = SPINEL_STATUS_EMPTY;
+ goto bail;
+ }
+
+ switch ((spinel_datatype_t)*scratchpad.pack_format) {
+ case SPINEL_DATATYPE_INT8_C:
+ case SPINEL_DATATYPE_UINT8_C:
+ require(scratchpad.data_len >= sizeof(uint8_t), bail);
+ scratchpad.data_ptr += sizeof(uint8_t);
+ scratchpad.data_len -= sizeof(uint8_t);
+ scratchpad.pack_format++;
+ break;
+
+ case SPINEL_DATATYPE_INT16_C:
+ case SPINEL_DATATYPE_UINT16_C:
+ require(scratchpad.data_len >= sizeof(uint16_t), bail);
+ scratchpad.data_ptr += sizeof(uint16_t);
+ scratchpad.data_len -= sizeof(uint16_t);
+ scratchpad.pack_format++;
+ break;
+
+ case SPINEL_DATATYPE_INT32_C:
+ case SPINEL_DATATYPE_UINT32_C:
+ require(scratchpad.data_len >= sizeof(uint32_t), bail);
+ scratchpad.data_ptr += sizeof(uint32_t);
+ scratchpad.data_len -= sizeof(uint32_t);
+ scratchpad.pack_format++;
+ break;
+
+ case SPINEL_DATATYPE_IPv6ADDR_C:
+ require(scratchpad.data_len >= sizeof(spinel_ipv6addr_t), bail);
+ scratchpad.data_ptr += sizeof(spinel_ipv6addr_t);
+ scratchpad.data_len -= sizeof(spinel_ipv6addr_t);
+ scratchpad.pack_format++;
+ break;
+
+ case SPINEL_DATATYPE_EUI64_C:
+ require(scratchpad.data_len >= sizeof(spinel_eui64_t), bail);
+ scratchpad.data_ptr += sizeof(spinel_eui64_t);
+ scratchpad.data_len -= sizeof(spinel_eui64_t);
+ scratchpad.pack_format++;
+ break;
+
+ case SPINEL_DATATYPE_EUI48_C:
+ require(scratchpad.data_len >= sizeof(spinel_eui48_t), bail);
+ scratchpad.data_ptr += sizeof(spinel_eui48_t);
+ scratchpad.data_len -= sizeof(spinel_eui48_t);
+ scratchpad.pack_format++;
+ break;
+
+ case SPINEL_DATATYPE_UINT_PACKED_C:
+ {
+ spinel_ssize_t pui_len = spinel_packed_uint_decode(scratchpad.data_ptr, scratchpad.data_len, NULL);
+ require(pui_len > 0, bail);
+ scratchpad.data_ptr += pui_len;
+ scratchpad.data_len -= pui_len;
+ scratchpad.pack_format++;
+ }
+ break;
+
+
+ case SPINEL_DATATYPE_UTF8_C:
+ break;
+
+ case SPINEL_DATATYPE_STRUCT_C:
+ case SPINEL_DATATYPE_ARRAY_C:
+ scratchpad.pack_format = spinel_next_packed_datatype(scratchpad.pack_format)-1;
+
+ case SPINEL_DATATYPE_DATA_C:
+ {
+ if ((scratchpad.pack_format[1] == ')')
+ || (scratchpad.pack_format[1] == 0)
+ ) {
+ // Special case: data is size of the rest of the buffer!
+ scratchpad.data_ptr += scratchpad.data_len;
+ scratchpad.data_len -= scratchpad.data_len;
+ } else {
+ uint32_t block_len = 0;
+ spinel_ssize_t pui_len = spinel_packed_uint_decode(scratchpad.data_ptr, scratchpad.data_len, &block_len);
+
+ require(pui_len > 0, bail);
+ require(block_len < SPINEL_FRAME_MAX_SIZE, bail);
+
+ scratchpad.data_ptr += pui_len+block_len;
+ scratchpad.data_len -= pui_len+block_len;
+
+ require(scratchpad.data_len >= block_len, bail);
+ }
+ }
+ case SPINEL_DATATYPE_VOID_C:
+ scratchpad.pack_format++;
+
+ default:
+ // Unsupported Type!
+ goto bail;
+ }
+
+ while (scratchpad.pack_format[0] == SPINEL_DATATYPE_VOID_C) {
+ scratchpad.pack_format++;
+ }
+
+ if ((*scratchpad.pack_format == ')')
+ || (*scratchpad.pack_format == 0)
+ || (scratchpad.data_len == 0)
+ ) {
+ ret = SPINEL_STATUS_EMPTY;
+ } else {
+ ret = SPINEL_STATUS_OK;
+ }
+
+ if (iter->container == SPINEL_DATATYPE_ARRAY_C) {
+ iter->data_ptr = scratchpad.data_ptr;
+ iter->data_len = scratchpad.data_len;
+ } else {
+ *iter = scratchpad;
+ }
+
+bail:
+ return ret;
+}
+
+spinel_status_t
+spinel_datatype_iter_open_container(const spinel_datatype_iter_t* iter, spinel_datatype_iter_t* subiter)
+{
+ spinel_status_t ret = SPINEL_STATUS_PARSE_ERROR;
+ int depth = 0;
+
+ require(iter->data_len > 2, bail);
+
+ switch ((spinel_datatype_t)*iter->pack_format) {
+ case SPINEL_DATATYPE_STRUCT_C:
+ case SPINEL_DATATYPE_ARRAY_C:
+ break;
+
+ default:
+ ret = SPINEL_STATUS_INVALID_ARGUMENT;
+ goto bail;
+ break;
+ }
+
+ *subiter = *iter;
+ subiter->container = iter->pack_format[0];
+
+ do {
+ switch(subiter->pack_format[1]) {
+ case '(': depth++; break;
+ case ')': depth++; break;
+ case 0: depth = 0; break;
+ }
+ } while(depth > 0);
+
+ require(subiter->pack_format[1] == ')', bail);
+ subiter->pack_format++;
+
+ if ((subiter->pack_format[1] != ')') && (subiter->pack_format[1] != 0))
+ {
+ // We aren't the special case. Extract the length.
+ uint32_t block_len = 0;
+ spinel_ssize_t pui_len = spinel_packed_uint_decode(subiter->data_ptr, subiter->data_len, &block_len);
+
+ require(pui_len > 0, bail);
+ require(block_len < SPINEL_FRAME_MAX_SIZE, bail);
+
+ subiter->data_ptr += pui_len;
+ subiter->data_len -= pui_len;
+
+ require(block_len <= subiter->data_len, bail);
+
+ subiter->data_len = block_len;
+ }
+ subiter->pack_format = iter->pack_format+2;
+
+ ret = SPINEL_STATUS_OK;
+
+bail:
+ return ret;
+}
+
+spinel_status_t
+spinel_datatype_iter_unpack(const spinel_datatype_iter_t* iter, ...)
+{
+ spinel_status_t ret = SPINEL_STATUS_PARSE_ERROR;
+ va_list args;
+ va_start(args, iter);
+ const char pack_format[2] = { iter->pack_format[0], 0 };
+
+ if (0 <= spinel_datatype_vunpack(iter->data_ptr, iter->data_len, pack_format, args)) {
+ ret = SPINEL_STATUS_OK;
+ }
+
+ va_end(args);
+ return ret;
+}
+
+spinel_status_t
+spinel_datatype_iter_vunpack(const spinel_datatype_iter_t* iter, va_list args)
+{
+ spinel_status_t ret = SPINEL_STATUS_PARSE_ERROR;
+
+ if (0 <= spinel_datatype_vunpack(iter->data_ptr, iter->data_len, iter->pack_format, args)) {
+ ret = SPINEL_STATUS_OK;
+ }
+
+ return ret;
+}
+
+spinel_datatype_t
+spinel_datatype_iter_get_type(const spinel_datatype_iter_t* iter)
+{
+ return iter->pack_format != NULL
+ ? (spinel_datatype_t)*iter->pack_format
+ : SPINEL_DATATYPE_NULL_C;
+}
+
+// ----------------------------------------------------------------------------
+// MARK: -
+// MARK: Command Generators
+
+spinel_ssize_t
+spinel_cmd_prop_value_set_uint(uint8_t* cmd_data_ptr, spinel_size_t cmd_data_len, spinel_prop_key_t prop_key, unsigned int x)
+{
+ return spinel_datatype_pack(
+ cmd_data_ptr,
+ cmd_data_len,
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT_PACKED_S),
+ prop_key,
+ x
+ );
+}
+
+spinel_ssize_t
+spinel_cmd_prop_value_set_data(uint8_t* cmd_data_ptr, spinel_size_t cmd_data_len, spinel_prop_key_t prop_key, const uint8_t* x_ptr, spinel_size_t x_len)
+{
+ return spinel_datatype_pack(
+ cmd_data_ptr,
+ cmd_data_len,
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_DATA_S),
+ prop_key,
+ x_ptr,
+ x_len
+ );
+}
+
+spinel_ssize_t
+spinel_cmd_prop_value_set_utf8(uint8_t* cmd_data_ptr, spinel_size_t cmd_data_len, spinel_prop_key_t prop_key, const char* x)
+{
+ return spinel_datatype_pack(
+ cmd_data_ptr,
+ cmd_data_len,
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_DATA_S),
+ prop_key,
+ x
+ );
+}
+
+spinel_ssize_t
+spinel_cmd_prop_value_set_uint16(uint8_t* cmd_data_ptr, spinel_size_t cmd_data_len, spinel_prop_key_t prop_key, uint16_t x)
+{
+ return spinel_datatype_pack(
+ cmd_data_ptr,
+ cmd_data_len,
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_UINT16_S),
+ prop_key,
+ x
+ );
+}
+
+spinel_ssize_t
+spinel_cmd_prop_value_set_ipv6addr(uint8_t* cmd_data_ptr, spinel_size_t cmd_data_len, spinel_prop_key_t prop_key, const spinel_ipv6addr_t* x_ptr)
+{
+ return spinel_datatype_pack(
+ cmd_data_ptr,
+ cmd_data_len,
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_IPv6ADDR_S),
+ prop_key,
+ x_ptr
+ );
+}
+
+spinel_ssize_t
+spinel_cmd_prop_value_set_eui64(uint8_t* cmd_data_ptr, spinel_size_t cmd_data_len, spinel_prop_key_t prop_key, const spinel_eui64_t* x_ptr)
+{
+ return spinel_datatype_pack(
+ cmd_data_ptr,
+ cmd_data_len,
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(SPINEL_DATATYPE_EUI64_S),
+ prop_key,
+ x_ptr
+ );
+}
+
+spinel_ssize_t
+spinel_cmd_prop_value_get(uint8_t* cmd_data_ptr, spinel_size_t cmd_data_len, spinel_prop_key_t prop_key)
+{
+ spinel_ssize_t ret;
+ ret = spinel_datatype_pack(
+ cmd_data_ptr,
+ cmd_data_len,
+ SPINEL_FRAME_PACK_CMD_PROP_VALUE_GET,
+ prop_key
+ );
+ return ret;
+}
diff --git a/src/ncp-spinel/spinel-extra.h b/src/ncp-spinel/spinel-extra.h
new file mode 100644
index 0000000..25f3e71
--- /dev/null
+++ b/src/ncp-spinel/spinel-extra.h
@@ -0,0 +1,79 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef SPINEL_EXTRA_HEADER_INCLUDED
+#define SPINEL_EXTRA_HEADER_INCLUDED 1
+
+#include "spinel.h"
+
+__BEGIN_DECLS
+
+// ----------------------------------------------------------------------------
+
+typedef struct {
+ const uint8_t* data_ptr;
+ int data_len;
+ const char* pack_format;
+ spinel_datatype_t container;
+} spinel_datatype_iter_t;
+
+SPINEL_API_EXTERN spinel_status_t spinel_datatype_iter_start(spinel_datatype_iter_t* iter, const uint8_t* data_in, spinel_size_t data_len, const char* pack_format);
+SPINEL_API_EXTERN spinel_status_t spinel_datatype_iter_next(spinel_datatype_iter_t* iter);
+SPINEL_API_EXTERN spinel_status_t spinel_datatype_iter_open_container(const spinel_datatype_iter_t* iter, spinel_datatype_iter_t* subiter);
+SPINEL_API_EXTERN spinel_status_t spinel_datatype_iter_unpack(const spinel_datatype_iter_t* iter, ...);
+SPINEL_API_EXTERN spinel_status_t spinel_datatype_iter_vunpack(const spinel_datatype_iter_t* iter, va_list args);
+SPINEL_API_EXTERN spinel_datatype_t spinel_datatype_iter_get_type(const spinel_datatype_iter_t* iter);
+
+// ----------------------------------------------------------------------------
+
+#define SPINEL_FRAME_PACK_CMD(x) "Ci" x,SPINEL_HEADER_FLAG
+#define SPINEL_FRAME_PACK_CMD_NOOP SPINEL_FRAME_PACK_CMD(SPINEL_DATATYPE_NULL_S),SPINEL_CMD_NOOP
+#define SPINEL_FRAME_PACK_CMD_RESET SPINEL_FRAME_PACK_CMD(SPINEL_DATATYPE_NULL_S),SPINEL_CMD_RESET
+#define SPINEL_FRAME_PACK_CMD_NET_CLEAR SPINEL_FRAME_PACK_CMD(SPINEL_DATATYPE_NULL_S),SPINEL_CMD_NET_CLEAR
+#define SPINEL_FRAME_PACK_CMD_PROP_VALUE_GET SPINEL_FRAME_PACK_CMD(SPINEL_DATATYPE_UINT_PACKED_S),SPINEL_CMD_PROP_VALUE_GET
+#define SPINEL_FRAME_PACK_CMD_PROP_TYPE_GET SPINEL_FRAME_PACK_CMD(SPINEL_DATATYPE_UINT_PACKED_S),SPINEL_CMD_PROP_TYPE_GET
+#define SPINEL_FRAME_PACK_CMD_PROP_VALUE_SET(x) SPINEL_FRAME_PACK_CMD(SPINEL_DATATYPE_UINT_PACKED_S x),SPINEL_CMD_PROP_VALUE_SET
+#define SPINEL_FRAME_PACK_CMD_PROP_VALUE_INSERT(x) SPINEL_FRAME_PACK_CMD(SPINEL_DATATYPE_UINT_PACKED_S x),SPINEL_CMD_PROP_VALUE_INSERT
+#define SPINEL_FRAME_PACK_CMD_PROP_VALUE_REMOVE(x) SPINEL_FRAME_PACK_CMD(SPINEL_DATATYPE_UINT_PACKED_S x),SPINEL_CMD_PROP_VALUE_REMOVE
+#define SPINEL_FRAME_PACK_CMD_PROP_VALUE_IS(x) SPINEL_FRAME_PACK_CMD(SPINEL_DATATYPE_UINT_PACKED_S x),SPINEL_CMD_PROP_VALUE_IS
+#define SPINEL_FRAME_PACK_CMD_PROP_TYPE_IS SPINEL_FRAME_PACK_CMD(SPINEL_DATATYPE_UINT_PACKED_S SPINEL_DATATYPE_UINT8_S),SPINEL_CMD_PROP_TYPE_IS
+#define SPINEL_FRAME_PACK_CMD_PROP_VALUE_INSERTED(x) SPINEL_FRAME_PACK_CMD(SPINEL_DATATYPE_UINT_PACKED_S x),SPINEL_CMD_PROP_VALUE_INSERTED
+#define SPINEL_FRAME_PACK_CMD_PROP_VALUE_REMOVED(x) SPINEL_FRAME_PACK_CMD(SPINEL_DATATYPE_UINT_PACKED_S x),SPINEL_CMD_PROP_VALUE_REMOVED
+
+SPINEL_API_EXTERN spinel_ssize_t spinel_cmd_prop_value_set_data(uint8_t* cmd_data_ptr, spinel_size_t cmd_data_len, spinel_prop_key_t prop_key, const uint8_t* x_ptr, spinel_size_t x_len);
+
+SPINEL_API_EXTERN spinel_ssize_t spinel_cmd_prop_value_set_utf8(uint8_t* cmd_data_ptr, spinel_size_t cmd_data_len, spinel_prop_key_t prop_key, const char* x);
+
+SPINEL_API_EXTERN spinel_ssize_t spinel_cmd_prop_value_set_uint(uint8_t* cmd_data_ptr, spinel_size_t cmd_data_len, spinel_prop_key_t prop_key, unsigned int x);
+
+SPINEL_API_EXTERN spinel_ssize_t spinel_cmd_prop_value_set_uint16(uint8_t* cmd_data_ptr, spinel_size_t cmd_data_len, spinel_prop_key_t prop_key, uint16_t x);
+
+SPINEL_API_EXTERN spinel_ssize_t spinel_cmd_prop_value_set_ipv6addr(uint8_t* cmd_data_ptr, spinel_size_t cmd_data_len, spinel_prop_key_t prop_key, const spinel_ipv6addr_t* x_ptr);
+
+SPINEL_API_EXTERN spinel_ssize_t spinel_cmd_prop_value_set_eui64(uint8_t* cmd_data_ptr, spinel_size_t cmd_data_len, spinel_prop_key_t prop_key, const spinel_eui64_t* x_ptr);
+
+SPINEL_API_EXTERN spinel_ssize_t spinel_cmd_prop_value_get(uint8_t* cmd_data_ptr, spinel_size_t cmd_data_len, spinel_prop_key_t prop_key);
+
+SPINEL_API_EXTERN spinel_ssize_t spinel_cmd_prop_type_get(uint8_t* cmd_data_ptr, spinel_size_t cmd_data_len, spinel_prop_key_t prop_key);
+
+SPINEL_API_EXTERN spinel_ssize_t spinel_cmd_prop_type_get(uint8_t* cmd_data_ptr, spinel_size_t cmd_data_len, spinel_prop_key_t prop_key);
+
+__END_DECLS
+
+#endif // SPINEL_EXTRA_HEADER_INCLUDED
diff --git a/src/scripts/Makefile.am b/src/scripts/Makefile.am
new file mode 100644
index 0000000..b407dc0
--- /dev/null
+++ b/src/scripts/Makefile.am
@@ -0,0 +1,29 @@
+#
+# Copyright (c) 2016 Nest Labs, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+DISTCLEANFILES = \
+ .deps \
+ Makefile \
+ $(NULL)
+
+EXTRA_DIST = \
+ wpanretain.sh \
+ $(NULL)
+
+pkgdata_DATA = \
+ wpanretain.sh \
+ $(NULL)
diff --git a/src/scripts/wpanretain.sh b/src/scripts/wpanretain.sh
new file mode 100755
index 0000000..5638d6f
--- /dev/null
+++ b/src/scripts/wpanretain.sh
@@ -0,0 +1,378 @@
+#! /bin/sh
+
+# Copyright (c) 2016 Nest Labs, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+
+display_usage ()
+{
+ echo "Thread Network Retain - Save/Recall thread network info"
+ echo ""
+ echo "Usage: $(basename $0) [primary-net-info-file] [secondary-net-info-file] [wpanctl path] [command]"
+ echo ""
+ echo " Command:"
+ echo " 'S' or 'save' : Save current network info."
+ echo " 'R' or 'recall' : Recall/Restore previously saved network info."
+ echo " 'E' or 'erase' : Erase previously saved network info."
+ echo ""
+ echo " [primary-net-info-file] and [secondary-net-info-file] give full path to files to store network info."
+ echo " [wpanctl path] gives the full path to 'wpanctl'."
+ echo ""
+}
+
+# Check the input args
+
+if [ $# -ne 4 ]; then
+ display_usage
+ exit 1
+fi
+
+primary_file_name="$1"
+secondary_file_name="$2"
+wpanctl_command="$3"
+retain_command=$4
+
+# List of all wpantund properties saved
+WPANTUND_PROP_NAME="Network:Name"
+WPANTUND_PROP_KEY="Network:Key"
+WPANTUND_PROP_PANID="Network:PANID"
+WPANTUND_PROP_XPANID="Network:XPANID"
+WPANTUND_PROP_CHANNEL="NCP:Channel"
+WPANTUND_PROP_MACADDR="NCP:MACAddress"
+WPANTUND_PROP_NODE_TYPE="Network:NodeType"
+WPANTUND_PROP_KEY_INDEX="Network:KeyIndex"
+WPANTUND_PROP_ROUTER_ID="Thread:RouterID"
+WPANTUND_PROP_PREFERRED_ROUTER_ID="Thread:PreferredRouterID"
+
+MAX_ROUTER_ID=60
+
+cur_name=
+cur_key=
+cur_panid=
+cur_xpanid=
+cur_channel=
+cur_macaddr=
+cur_type=
+cur_keyindex=
+cur_routerid=
+
+new_name=
+new_key=
+new_panid=
+new_xpanid=
+new_channel=
+new_macaddr=
+new_type=
+new_keyindex=
+new_routerid=
+
+# Populate the new network info variables by reading the values from wpanctl
+get_new_network_info_from_wpantund ()
+{
+ val=$($wpanctl_command get -v $WPANTUND_PROP_NAME)
+ val=${val#\"}
+ new_name=${val%\"}
+
+ val=$($wpanctl_command get $WPANTUND_PROP_KEY)
+ val=${val#*\[}
+ new_key=${val%\]*}
+
+ val=$($wpanctl_command get $WPANTUND_PROP_PANID)
+ new_panid=$(echo "$val" | sed -e 's/.*=[[:space:]]*//')
+
+ val=$($wpanctl_command get $WPANTUND_PROP_XPANID)
+ new_xpanid=$(echo "$val" | sed -e 's/.*=[[:space:]]*0x//')
+
+ val=$($wpanctl_command get $WPANTUND_PROP_CHANNEL)
+ new_channel=$(echo "$val" | sed -e 's/.*=[[:space:]]*//')
+
+ val=$($wpanctl_command get $WPANTUND_PROP_MACADDR)
+ val=${val#*\[}
+ new_macaddr=${val%\]*}
+
+ val=$($wpanctl_command get $WPANTUND_PROP_NODE_TYPE)
+ new_type=$(echo "$val" | sed -e 's/.*=[[:space:]]*//')
+
+ val=$($wpanctl_command get $WPANTUND_PROP_KEY_INDEX)
+ new_keyindex=$(echo "$val" | sed -e 's/.*=[[:space:]]*//')
+
+ val=$($wpanctl_command get -v $WPANTUND_PROP_ROUTER_ID)
+ new_routerid=$(printf "%d" $val)
+}
+
+restore_network_info_on_wpantund ()
+{
+ # Calculate a new router id value by adding one to it
+ # This ensures router id is different upon every reset/restore
+ router_id=$(($cur_routerid+1))
+
+ if [ "$router_id" -ge "$MAX_ROUTER_ID" ]
+ then
+ router_id=0
+ fi
+ $wpanctl_command set $WPANTUND_PROP_PREFERRED_ROUTER_ID $router_id
+
+ $wpanctl_command set $WPANTUND_PROP_MACADDR $cur_macaddr
+ $wpanctl_command set $WPANTUND_PROP_NAME $cur_name
+ $wpanctl_command set $WPANTUND_PROP_KEY -d $cur_key
+ $wpanctl_command set $WPANTUND_PROP_PANID $cur_panid
+ $wpanctl_command set $WPANTUND_PROP_XPANID -d $cur_xpanid
+ $wpanctl_command set $WPANTUND_PROP_CHANNEL $cur_channel
+ $wpanctl_command set $WPANTUND_PROP_NODE_TYPE $cur_type
+ $wpanctl_command set $WPANTUND_PROP_KEY_INDEX $cur_keyindex
+
+ $wpanctl_command attach
+}
+
+verify_cur_info ()
+{
+ if [ -z "$cur_name" ] || \
+ [ -z "$cur_key" ] || \
+ [ -z "$cur_panid" ] || \
+ [ -z "$cur_xpanid" ] || \
+ [ -z "$cur_channel" ] || \
+ [ -z "$cur_macaddr" ] || \
+ [ -z "$cur_type" ] || \
+ [ -z "$cur_keyindex" ] || \
+ [ -z "$cur_routerid" ]
+ then
+ return 1
+ fi
+
+ return 0
+}
+
+verify_new_info ()
+{
+
+ if [ -z "$new_name" ] || \
+ [ -z "$new_key" ] || \
+ [ -z "$new_panid" ] || \
+ [ -z "$new_xpanid" ] || \
+ [ -z "$new_channel" ] || \
+ [ -z "$new_macaddr" ] || \
+ [ -z "$new_type" ] || \
+ [ -z "$new_keyindex" ] || \
+ [ -z "$new_routerid" ]
+ then
+ return 1
+ fi
+
+ return 0
+}
+
+is_new_info_same_as_cur_info ()
+{
+ if [ "$cur_name" != "$new_name" ] || \
+ [ "$cur_key" != "$new_key" ] || \
+ [ "$cur_panid" != "$new_panid" ] || \
+ [ "$cur_xpanid" != "$new_xpanid" ] || \
+ [ "$cur_channel" != "$new_channel" ] || \
+ [ "$cur_macaddr" != "$new_macaddr" ] || \
+ [ "$cur_type" != "$new_type" ] || \
+ [ "$cur_keyindex" != "$new_keyindex" ] || \
+ [ "$cur_routerid" != "$new_routerid" ]
+ then
+ return 1
+ fi
+
+ return 0
+}
+
+# Reads and parses the network info from a file and populate old network info variables
+# First arg ($1) is the file name
+read_cur_network_info_from_file ()
+{
+ if [ -r $1 ]; then
+
+ while IFS="\= " read -r key value; do
+
+ case $key in
+ $WPANTUND_PROP_NAME)
+ cur_name=$value
+ ;;
+ $WPANTUND_PROP_KEY)
+ cur_key=$value
+ ;;
+ $WPANTUND_PROP_PANID)
+ cur_panid=$value
+ ;;
+ $WPANTUND_PROP_XPANID)
+ cur_xpanid=$value
+ ;;
+ $WPANTUND_PROP_CHANNEL)
+ cur_channel=$value
+ ;;
+ $WPANTUND_PROP_MACADDR)
+ cur_macaddr=$value
+ ;;
+ $WPANTUND_PROP_NODE_TYPE)
+ cur_type=$value
+ ;;
+ $WPANTUND_PROP_KEY_INDEX)
+ cur_keyindex=$value
+ ;;
+ $WPANTUND_PROP_ROUTER_ID)
+ cur_routerid=$value
+ ;;
+ esac
+
+ done < $1
+ fi
+}
+
+# Writes the new info into a given file name (first arg should be filename)
+write_new_info_to_file ()
+{
+ fname=$1
+
+ if [ -e $fname ]; then
+ rm $fname > /dev/null 2>&1
+ fi
+
+ mkdir -p $(dirname "$fname")
+
+ # Write all the contents to the file
+
+ echo "${WPANTUND_PROP_NAME} = $new_name" >> $fname
+ echo "${WPANTUND_PROP_KEY} = $new_key" >> $fname
+ echo "${WPANTUND_PROP_PANID} = $new_panid" >> $fname
+ echo "${WPANTUND_PROP_XPANID} = $new_xpanid" >> $fname
+ echo "${WPANTUND_PROP_CHANNEL} = $new_channel" >> $fname
+ echo "${WPANTUND_PROP_MACADDR} = $new_macaddr" >> $fname
+ echo "${WPANTUND_PROP_NODE_TYPE} = $new_type" >> $fname
+ echo "${WPANTUND_PROP_KEY_INDEX} = $new_keyindex" >> $fname
+ echo "${WPANTUND_PROP_ROUTER_ID} = $new_routerid" >> $fname
+
+ # Add a time stamp
+ echo "# Saved on " $(date) >> $fname
+}
+
+# For test and debugging only
+display_cur_network_info ()
+{
+ echo "cur_name is" $cur_name
+ echo "cur_key is" $cur_key
+ echo "cur_panid is" $cur_panid
+ echo "cur_xpanid is" $cur_xpanid
+ echo "cur_channel is" $cur_channel
+ echo "cur_macaddr is" $cur_macaddr
+ echo "cur_type is" $cur_type
+ echo "cur_keyindex is" $cur_keyindex
+ echo "cur_routerid is" $cur_routerid
+}
+
+# For test and debugging only
+display_new_network_info ()
+{
+ echo "new_name is" $new_name
+ echo "new_key is" $new_key
+ echo "new_panid is" $new_panid
+ echo "new_xpanid is" $new_xpanid
+ echo "new_channel is" $new_channel
+ echo "new_macaddr is" $new_macaddr
+ echo "new_type is" $new_type
+ echo "new_keyindex is" $new_keyindex
+ echo "new_routerid is" $new_routerid
+}
+
+save_network_info ()
+{
+ get_new_network_info_from_wpantund
+
+ read_cur_network_info_from_file $primary_file_name
+
+ if verify_new_info; then
+
+ if is_new_info_same_as_cur_info; then
+ echo "Saved network info in \"$primary_file_name\" is up-to-date and valid."
+ else
+
+ write_new_info_to_file $secondary_file_name
+
+ # verify the file content match what was written
+
+ read_cur_network_info_from_file $secondary_file_name
+
+ if is_new_info_same_as_cur_info; then
+
+ cp $secondary_file_name $primary_file_name
+
+ echo "Successfully saved network info in \"$primary_file_name\" and \"$secondary_file_name\""
+
+ else
+ echo "ERROR: Could not save the network data"
+ fi
+ # need to figure out if it fails what to do...
+ fi
+
+ else
+ echo "ERROR: Network info from wpantund is not valid"
+ fi
+}
+
+erase_network_info ()
+{
+ if [ -e $primary_file_name ]; then
+ rm $primary_file_name
+ fi
+
+ if [ -e $secondary_file_name ]; then
+ rm $secondary_file_name
+ fi
+
+ echo "Successfully erased network data in \"$primary_file_name\" and \"$secondary_file_name\"".
+}
+
+recall_network_info ()
+{
+ read_cur_network_info_from_file $primary_file_name
+
+ # if no valid data from the main file, try to read from the second (backup) file
+ verify_cur_info || read_cur_network_info_from_file $secondary_file_name
+
+ if verify_cur_info; then
+
+ restore_network_info_on_wpantund
+
+ echo "Successfully recalled network info from \"$primary_file_name\""
+ else
+ echo "No valid saved network info to recall."
+ fi
+}
+
+case $retain_command in
+
+R|recall)
+ recall_network_info
+ ;;
+
+S|save)
+ save_network_info
+ ;;
+
+E|erase)
+ erase_network_info
+ ;;
+
+*)
+ echo "Error: Unknown command \"$retain_command\""
+ echo " "
+ display_usage
+ ;;
+esac
+
+exit 0
diff --git a/src/util/CallbackStore.hpp b/src/util/CallbackStore.hpp
new file mode 100644
index 0000000..f0b4163
--- /dev/null
+++ b/src/util/CallbackStore.hpp
@@ -0,0 +1,115 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * Class for handling one-time callbacks. Deprecated.
+ *
+ */
+
+#ifndef wpantund_callback_store_h
+#define wpantund_callback_store_h
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <map>
+#include <boost/signals2/signal.hpp>
+#include <boost/bind.hpp>
+#include <boost/ptr_container/ptr_map.hpp>
+
+template <class Key = std::string>
+class CallbackStore {
+public:
+ typedef boost::signals2::signal<void(int, const uint8_t* data, size_t len)> signal_type;
+ typedef boost::shared_ptr<signal_type> mapped_type;
+ typedef Key key_type;
+ typedef std::map<key_type, mapped_type> map_type;
+
+private:
+ map_type _map;
+
+public:
+ CallbackStore() {
+ }
+
+ void
+ add(const Key& name, const boost::function<void(int)>& func)
+ {
+ if(!_map[name])
+ _map[name] = mapped_type(new signal_type());
+
+ _map[name]->connect(boost::bind(func, _1));
+ }
+
+ void
+ add( const Key& name, const boost::function3<void, int, const uint8_t*, size_t>& func)
+ {
+ if(!_map[name])
+ _map[name] = mapped_type(new signal_type());
+
+ _map[name]->connect(func);
+ }
+
+ void
+ set(const Key& name, const mapped_type& signal)
+ {
+ if (static_cast<bool>(signal))
+ _map[name] = signal;
+ }
+
+
+ size_t
+ count(const Key& name)const {
+ if (_map.count(name) == 0 || NULL == _map.find(name)->second.get())
+ return 0;
+ return _map.find(name)->second->num_slots();
+ }
+
+ void
+ handle(const Key& name, int val, const uint8_t* data, size_t len)
+ {
+ mapped_type signal;
+ if(_map[name]) {
+ signal.swap(_map[name]);
+ _map.erase(name);
+ (*signal)(val, data, len);
+ }
+ }
+
+ mapped_type
+ unhandle(const Key& name)
+ {
+ mapped_type signal;
+ if (_map[name]) {
+ signal.swap(_map[name]);
+ _map.erase(name);
+ }
+ return signal;
+ }
+
+ void
+ handle_all(int val)
+ {
+ map_type map(_map);
+ for (typename map_type::iterator iter=map.begin(); iter!=map.end(); iter++) {
+ handle(iter->first, val, NULL, 0);
+ }
+ }
+};
+
+#endif
diff --git a/src/util/Callbacks.h b/src/util/Callbacks.h
new file mode 100644
index 0000000..a48b9f5
--- /dev/null
+++ b/src/util/Callbacks.h
@@ -0,0 +1,74 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * Type definitions and utility functions related to callback objects.
+ *
+ */
+
+#ifndef wpantund_Callbacks_h
+#define wpantund_Callbacks_h
+
+#ifndef __STDC_CONSTANT_MACROS
+#define __STDC_CONSTANT_MACROS 1
+#endif
+
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+#include <boost/signals2/signal.hpp>
+#include <boost/bind.hpp>
+#include <boost/any.hpp>
+
+#include "NilReturn.h"
+
+namespace nl {
+
+typedef boost::function<void(void)> CallbackSimple;
+typedef boost::function<void(int)> CallbackWithStatus;
+typedef boost::function<void(int, const boost::any&)> CallbackWithStatusArg1;
+
+typedef boost::signals2::signal<void(int)> SignalWithStatus;
+
+static inline void
+split_cb_on_status(int status, CallbackSimple cb_success, CallbackWithStatus cb_error = nl::NilReturn())
+{
+ if (status == 0) {
+ cb_success();
+ } else {
+ cb_error(status);
+ }
+}
+
+#define CALLBACK_FUNC_SPLIT(success,failure) \
+ CallbackWithStatus( \
+ boost::bind( \
+ &split_cb_on_status, \
+ _1, \
+ CallbackSimple(success), \
+ CallbackWithStatus(failure) \
+ ) \
+ )
+
+}; // namespace nl
+
+#endif
diff --git a/src/util/DBUSHelpers.cpp b/src/util/DBUSHelpers.cpp
new file mode 100644
index 0000000..e394ab9
--- /dev/null
+++ b/src/util/DBUSHelpers.cpp
@@ -0,0 +1,458 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * Implementation of various helper functions related to DBus
+ * funcitonality.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "DBUSHelpers.h"
+#include "Data.h"
+#include <syslog.h>
+#include <string>
+#include <list>
+#include <map>
+#include <set>
+#include <exception>
+#include <stdexcept>
+#include "ValueMap.h"
+
+using namespace DBUSHelpers;
+
+nl::ValueMap
+DBUSHelpers::value_map_from_dbus_iter(DBusMessageIter *iter)
+{
+ nl::ValueMap ret;
+ DBusMessageIter sub_iter, dict_iter;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) {
+ throw std::invalid_argument("Wrong type for value map");
+ }
+
+ dbus_message_iter_recurse(iter, &sub_iter);
+
+ if (dbus_message_iter_get_arg_type(&sub_iter) != DBUS_TYPE_DICT_ENTRY) {
+ throw std::invalid_argument("Wrong type for value map");
+ }
+
+ do {
+ const char* key_cstr;
+ dbus_message_iter_recurse(&sub_iter, &dict_iter);
+
+ if (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_STRING) {
+ throw std::invalid_argument("Wrong type for value map");
+ }
+
+ dbus_message_iter_get_basic(&dict_iter, &key_cstr);
+ dbus_message_iter_next(&dict_iter);
+
+ ret[key_cstr] = any_from_dbus_iter(&dict_iter);
+ } while (dbus_message_iter_next(&sub_iter));
+
+ return ret;
+}
+
+boost::any
+DBUSHelpers::any_from_dbus_iter(DBusMessageIter *iter)
+{
+ boost::any ret;
+
+ switch (dbus_message_iter_get_arg_type(iter)) {
+ case DBUS_TYPE_ARRAY: {
+ DBusMessageIter sub_iter;
+ dbus_message_iter_recurse(iter, &sub_iter);
+ if (dbus_message_iter_get_arg_type(&sub_iter) == DBUS_TYPE_BYTE) {
+ const uint8_t* value = NULL;
+ int nelements = 0;
+ dbus_message_iter_get_fixed_array(&sub_iter, &value, &nelements);
+ ret = nl::Data(value, nelements);
+ } else if (dbus_message_iter_get_arg_type(&sub_iter) == DBUS_TYPE_DICT_ENTRY) {
+ ret = value_map_from_dbus_iter(iter);
+ } else {
+ syslog(LOG_NOTICE,
+ "Unsupported DBUS array type for any: %d",
+ dbus_message_iter_get_arg_type(&sub_iter));
+ }
+ } break;
+ case DBUS_TYPE_VARIANT: {
+ DBusMessageIter sub_iter;
+ dbus_message_iter_recurse(iter, &sub_iter);
+ ret = any_from_dbus_iter(&sub_iter);
+ } break;
+ case DBUS_TYPE_STRING: {
+ const char* v;
+ dbus_message_iter_get_basic(iter, &v);
+ ret = std::string(v);
+ } break;
+ case DBUS_TYPE_BOOLEAN: {
+ dbus_bool_t v;
+ dbus_message_iter_get_basic(iter, &v);
+ ret = bool(v);
+ } break;
+ case DBUS_TYPE_BYTE: {
+ uint8_t v;
+ dbus_message_iter_get_basic(iter, &v);
+ ret = v;
+ } break;
+ case DBUS_TYPE_DOUBLE: {
+ double v;
+ dbus_message_iter_get_basic(iter, &v);
+ ret = v;
+ } break;
+ case DBUS_TYPE_UINT16: {
+ uint16_t v;
+ dbus_message_iter_get_basic(iter, &v);
+ ret = v;
+ } break;
+ case DBUS_TYPE_INT16: {
+ int16_t v;
+ dbus_message_iter_get_basic(iter, &v);
+ ret = v;
+ } break;
+ case DBUS_TYPE_UINT32: {
+ uint32_t v;
+ dbus_message_iter_get_basic(iter, &v);
+ ret = v;
+ } break;
+ case DBUS_TYPE_INT32: {
+ int32_t v;
+ dbus_message_iter_get_basic(iter, &v);
+ ret = v;
+ } break;
+ case DBUS_TYPE_UINT64: {
+ uint16_t v;
+ dbus_message_iter_get_basic(iter, &v);
+ ret = v;
+ } break;
+ case DBUS_TYPE_INT64: {
+ int64_t v;
+ dbus_message_iter_get_basic(iter, &v);
+ ret = v;
+ } break;
+ }
+
+ return ret;
+}
+
+void
+DBUSHelpers::append_any_to_dbus_iter(
+ DBusMessageIter *iter, const boost::any &value
+ )
+{
+ if (value.type() == typeid(std::string)) {
+ std::string v = boost::any_cast<std::string>(value);
+ const char* cstr = v.c_str();
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &cstr);
+ } else if (value.type() == typeid(char*)) {
+ std::string v = boost::any_cast<char*>(value);
+ const char* cstr = v.c_str();
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &cstr);
+ } else if (value.type() == typeid(bool)) {
+ dbus_bool_t v = boost::any_cast<bool>(value);
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &v);
+ } else if (value.type() == typeid(uint8_t)) {
+ uint8_t v = boost::any_cast<uint8_t>(value);
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &v);
+ } else if (value.type() == typeid(int8_t)) {
+ int16_t v = boost::any_cast<int8_t>(value);
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_INT16, &v);
+ } else if (value.type() == typeid(uint16_t)) {
+ uint16_t v = boost::any_cast<uint16_t>(value);
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &v);
+ } else if (value.type() == typeid(int16_t)) {
+ int16_t v = boost::any_cast<int16_t>(value);
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_INT16, &v);
+ } else if (value.type() == typeid(uint32_t)) {
+ uint32_t v = boost::any_cast<uint32_t>(value);
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &v);
+ } else if (value.type() == typeid(int32_t)) {
+ int32_t v = boost::any_cast<int32_t>(value);
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &v);
+ } else if (value.type() == typeid(uint64_t)) {
+ uint64_t v = boost::any_cast<uint64_t>(value);
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT64, &v);
+ } else if (value.type() == typeid(int64_t)) {
+ int64_t v = boost::any_cast<int64_t>(value);
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_INT64, &v);
+ } else if (value.type() == typeid(double)) {
+ double v = boost::any_cast<double>(value);
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_DOUBLE, &v);
+ } else if (value.type() == typeid(float)) {
+ double v = boost::any_cast<float>(value);
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_DOUBLE, &v);
+ } else if (value.type() == typeid(std::list<std::string>)) {
+ DBusMessageIter array_iter;
+ const std::list<std::string>& list_of_strings =
+ boost::any_cast< std::list<std::string> >(value);
+ std::list<std::string>::const_iterator list_iter;
+ dbus_message_iter_open_container(
+ iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING,
+ &array_iter
+ );
+
+ for (list_iter = list_of_strings.begin();
+ list_iter != list_of_strings.end();
+ list_iter++) {
+ const char* cstr = list_iter->c_str();
+ dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING,
+ &cstr);
+ }
+
+ dbus_message_iter_close_container(iter, &array_iter);
+
+ } else if (value.type() == typeid(std::set<std::string>)) {
+ DBusMessageIter array_iter;
+ const std::set<std::string>& set_of_strings =
+ boost::any_cast< std::set<std::string> >(value);
+ std::set<std::string>::const_iterator set_iter;
+ dbus_message_iter_open_container(
+ iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING,
+ &array_iter
+ );
+
+ for (set_iter = set_of_strings.begin();
+ set_iter != set_of_strings.end();
+ set_iter++) {
+ const char* cstr = set_iter->c_str();
+ dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING,
+ &cstr);
+ }
+
+ dbus_message_iter_close_container(iter, &array_iter);
+ } else if (value.type() == typeid(nl::Data)) {
+ DBusMessageIter array_iter;
+ const nl::Data& vector = boost::any_cast< nl::Data >(value);
+ nl::Data::const_iterator vector_iter;
+ dbus_message_iter_open_container(
+ iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_TYPE_BYTE_AS_STRING,
+ &array_iter
+ );
+
+ for (vector_iter = vector.begin();
+ vector_iter != vector.end();
+ vector_iter++) {
+ dbus_message_iter_append_basic(&array_iter,
+ DBUS_TYPE_BYTE,
+ &*vector_iter);
+ }
+
+ dbus_message_iter_close_container(iter, &array_iter);
+ } else if (value.type() == typeid(std::vector<uint8_t>)) {
+ DBusMessageIter array_iter;
+ const std::vector<uint8_t>& vector =
+ boost::any_cast< std::vector<uint8_t> >(value);
+ std::vector<uint8_t>::const_iterator vector_iter;
+ dbus_message_iter_open_container(
+ iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_TYPE_BYTE_AS_STRING,
+ &array_iter
+ );
+
+ for (vector_iter = vector.begin();
+ vector_iter != vector.end();
+ vector_iter++) {
+ dbus_message_iter_append_basic(&array_iter,
+ DBUS_TYPE_BYTE,
+ &*vector_iter);
+ }
+
+ dbus_message_iter_close_container(iter, &array_iter);
+ } else if (value.type() == typeid(std::set<int>)) {
+ DBusMessageIter array_iter;
+ const std::set<int>& container =
+ boost::any_cast< std::set<int> >(value);
+ std::set<int>::const_iterator container_iter;
+ dbus_message_iter_open_container(
+ iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_TYPE_INT32_AS_STRING,
+ &array_iter
+ );
+
+ for (container_iter = container.begin();
+ container_iter != container.end();
+ container_iter++) {
+ dbus_message_iter_append_basic(&array_iter,
+ DBUS_TYPE_INT32,
+ &*container_iter);
+ }
+
+ dbus_message_iter_close_container(iter, &array_iter);
+ } else if (value.type() == typeid(nl::ValueMap)) {
+ DBusMessageIter array_iter;
+ const nl::ValueMap& value_map = boost::any_cast<nl::ValueMap>(value);
+ nl::ValueMap::const_iterator value_map_iter;
+
+ // Open a container as "Dictionary/Array of Strings to Variants" (dbus type "a{sv}")
+ dbus_message_iter_open_container(
+ iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+ &array_iter
+ );
+
+ for (value_map_iter = value_map.begin(); value_map_iter != value_map.end(); ++value_map_iter) {
+ append_dict_entry(&array_iter, value_map_iter->first.c_str(), value_map_iter->second);
+ }
+
+ dbus_message_iter_close_container(iter, &array_iter);
+ } else if (value.type() == typeid(std::list<nl::ValueMap>)) {
+ DBusMessageIter array_iter;
+ const std::list<nl::ValueMap>& value_map_list = boost::any_cast< std::list<nl::ValueMap> >(value);
+ std::list<nl::ValueMap>::const_iterator list_iter;
+
+ // Open a container as "Array of Dictionaries/Arrays of Strings to Variants" (dbus type "aa{sv}")
+ dbus_message_iter_open_container(
+ iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_TYPE_ARRAY_AS_STRING
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+ &array_iter
+ );
+
+ for (list_iter = value_map_list.begin(); list_iter != value_map_list.end(); ++list_iter) {
+ append_any_to_dbus_iter(&array_iter, *list_iter);
+ }
+
+ dbus_message_iter_close_container(iter, &array_iter);
+ } else {
+ throw std::invalid_argument("Unsupported type");
+ }
+}
+
+std::string
+DBUSHelpers::any_to_dbus_type_string(const boost::any &value)
+{
+ if (value.type() == typeid(std::string)) {
+ return DBUS_TYPE_STRING_AS_STRING;
+ } else if (value.type() == typeid(bool)) {
+ return DBUS_TYPE_BOOLEAN_AS_STRING;
+ } else if (value.type() == typeid(uint8_t)) {
+ return DBUS_TYPE_BYTE_AS_STRING;
+ } else if (value.type() == typeid(int8_t)) {
+ return DBUS_TYPE_INT16_AS_STRING;
+ } else if (value.type() == typeid(uint16_t)) {
+ return DBUS_TYPE_UINT16_AS_STRING;
+ } else if (value.type() == typeid(int16_t)) {
+ return DBUS_TYPE_INT16_AS_STRING;
+ } else if (value.type() == typeid(uint32_t)) {
+ return DBUS_TYPE_UINT32_AS_STRING;
+ } else if (value.type() == typeid(int32_t)) {
+ return DBUS_TYPE_INT32_AS_STRING;
+ } else if (value.type() == typeid(uint64_t)) {
+ return DBUS_TYPE_UINT64_AS_STRING;
+ } else if (value.type() == typeid(int64_t)) {
+ return DBUS_TYPE_INT64_AS_STRING;
+ } else if (value.type() == typeid(double)) {
+ return DBUS_TYPE_DOUBLE_AS_STRING;
+ } else if (value.type() == typeid(float)) {
+ return DBUS_TYPE_DOUBLE_AS_STRING;
+ } else if (value.type() == typeid(nl::Data)) {
+ return DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING;
+ } else if (value.type() == typeid(std::vector<uint8_t>)) {
+ return DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING;
+ } else if (value.type() == typeid(std::list<std::string>)) {
+ return DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING;
+ } else if (value.type() == typeid(std::set<std::string>)) {
+ return DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING;
+ } else if (value.type() == typeid(nl::ValueMap)) {
+ return std::string(DBUS_TYPE_ARRAY_AS_STRING) +
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING +
+ DBUS_TYPE_STRING_AS_STRING +
+ DBUS_TYPE_VARIANT_AS_STRING +
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING;
+ } else if (value.type() == typeid(std::list<nl::ValueMap>)) {
+ return std::string(DBUS_TYPE_ARRAY_AS_STRING) +
+ DBUS_TYPE_ARRAY_AS_STRING +
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING +
+ DBUS_TYPE_STRING_AS_STRING +
+ DBUS_TYPE_VARIANT_AS_STRING +
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING;
+ }
+
+ return "";
+}
+
+void
+DBUSHelpers::append_dict_entry(
+ DBusMessageIter *dict, const char *key, const boost::any& value
+ )
+{
+ DBusMessageIter entry;
+ DBusMessageIter value_iter;
+ std::string sig = any_to_dbus_type_string(value);
+
+ dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, NULL, &entry);
+
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+
+ dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
+ sig.c_str(), &value_iter);
+
+ append_any_to_dbus_iter(&value_iter, value);
+
+ dbus_message_iter_close_container(&entry, &value_iter);
+
+ dbus_message_iter_close_container(dict, &entry);
+}
+
+void
+DBUSHelpers::append_dict_entry(
+ DBusMessageIter *dict, const char *key, char type, void *val
+ )
+{
+ DBusMessageIter entry;
+ DBusMessageIter value_iter;
+ char sig[2] = { type, '\0' };
+
+ if (type == DBUS_TYPE_STRING) {
+ const char *str = *((const char**)val);
+ if (str == NULL)
+ return;
+ }
+
+ dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, NULL, &entry);
+
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+
+ dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, sig,
+ &value_iter);
+
+ dbus_message_iter_append_basic(&value_iter, type, val);
+
+ dbus_message_iter_close_container(&entry, &value_iter);
+
+ dbus_message_iter_close_container(dict, &entry);
+}
diff --git a/src/util/DBUSHelpers.h b/src/util/DBUSHelpers.h
new file mode 100644
index 0000000..3925319
--- /dev/null
+++ b/src/util/DBUSHelpers.h
@@ -0,0 +1,41 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * Declaration of various helper functions related to DBus
+ * funcitonality.
+ *
+ */
+
+#ifndef __wpantund__DBUSHelpers__
+#define __wpantund__DBUSHelpers__
+
+#include <boost/any.hpp>
+#include <dbus/dbus.h>
+#include <string>
+#include "ValueMap.h"
+
+namespace DBUSHelpers {
+nl::ValueMap value_map_from_dbus_iter(DBusMessageIter *iter);
+boost::any any_from_dbus_iter(DBusMessageIter *iter);
+void append_any_to_dbus_iter(DBusMessageIter *iter, const boost::any &value);
+std::string any_to_dbus_type_string(const boost::any &value);
+void append_dict_entry(DBusMessageIter *dict, const char *key, const boost::any& value);
+void append_dict_entry(DBusMessageIter *dict, const char *key, char type, void *val);
+};
+
+#endif /* defined(__wpantund__DBUSHelpers__) */
diff --git a/src/util/Data.cpp b/src/util/Data.cpp
new file mode 100644
index 0000000..e4541ae
--- /dev/null
+++ b/src/util/Data.cpp
@@ -0,0 +1,23 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * Empty.
+ *
+ */
+
+#include "Data.h"
diff --git a/src/util/Data.h b/src/util/Data.h
new file mode 100644
index 0000000..f94637f
--- /dev/null
+++ b/src/util/Data.h
@@ -0,0 +1,71 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * Class definition for binary data container.
+ *
+ */
+
+#ifndef __wpantund__Data__
+#define __wpantund__Data__
+
+#include <vector>
+#include <stdint.h>
+#include <stdlib.h>
+
+namespace nl {
+class Data : public std::vector<uint8_t> {
+public:
+ Data(const std::vector<uint8_t>& x) : std::vector<uint8_t>(x) {
+ }
+ Data(
+ const uint8_t* ptr, size_t len
+ ) : std::vector<uint8_t>(ptr, ptr + len) {
+ }
+
+ template<typename _InputIterator>
+ Data(_InputIterator __first, _InputIterator __last)
+ : std::vector<uint8_t>(__first, __last) { }
+
+ Data(size_t len = 0) : std::vector<uint8_t>(len) {
+ }
+
+ Data& append(const Data& d) {
+ insert(end(),d.begin(),d.end());
+ return *this;
+ }
+
+ Data& append(const uint8_t* ptr, size_t len) {
+ insert(end(),ptr,ptr+len);
+ return *this;
+ }
+
+ void pop_front(size_t len) {
+ erase(begin(), begin()+len);
+ }
+
+ uint8_t* data() {
+ return &*begin();
+ }
+
+ const uint8_t* data() const {
+ return &*begin();
+ }
+};
+};
+
+#endif /* defined(__wpantund__Data__) */
diff --git a/src/util/EventHandler.cpp b/src/util/EventHandler.cpp
new file mode 100644
index 0000000..3ddbe59
--- /dev/null
+++ b/src/util/EventHandler.cpp
@@ -0,0 +1,76 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "EventHandler.h"
+
+using namespace nl;
+
+EventHandler::EventHandler():
+ mControlPT(), mControlTime()
+{
+ PT_INIT(&mControlPT);
+}
+
+EventHandler::~EventHandler()
+{
+}
+
+cms_t
+EventHandler::get_ms_to_next_event()
+{
+ cms_t cms = CMS_DISTANT_FUTURE;
+
+ if (mControlTime) {
+ cms = mControlTime - time_ms();
+
+ if (cms < 0) {
+ cms = 0;
+ }
+ }
+
+ return cms;
+
+}
+
+void
+EventHandler::schedule_next_event(float seconds_until_event)
+{
+ mControlTime = time_ms() + (cms_t)(seconds_until_event * MSEC_PER_SEC);
+}
+
+void
+EventHandler::unschedule_next_event(void)
+{
+ mControlTime = 0;
+}
+
+int
+EventHandler::process_event(int event, ...)
+{
+ int ret;
+ va_list args;
+ va_start(args, event);
+ ret = vprocess_event(event, args);
+ va_end(args);
+ return ret;
+}
diff --git a/src/util/EventHandler.h b/src/util/EventHandler.h
new file mode 100644
index 0000000..af430a5
--- /dev/null
+++ b/src/util/EventHandler.h
@@ -0,0 +1,110 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __wpantund__EventHandler__
+#define __wpantund__EventHandler__
+
+#include <cstdio>
+#include <cstdarg>
+#include <boost/signals2/signal.hpp>
+
+#include "assert-macros.h"
+#include "time-utils.h"
+#include "nlpt.h"
+
+namespace nl {
+
+#define EVENT_NULL 0
+#define EVENT_IDLE 1
+#define EVENT_STARTING_TASK 2
+
+#define EH_BEGIN_SUB(pt) { bool eh_did_timeout(false); PT*const __eh_pt = (pt); (void)eh_did_timeout; PT_BEGIN(__eh_pt)
+#define EH_BEGIN() EH_BEGIN_SUB(&mControlPT)
+#define EH_END() PT_END(__eh_pt) }
+
+#define EH_SPAWN(child, proc) PT_SPAWN(__eh_pt, (child), (proc))
+
+// Explicitly terminate the protothread.
+#define EH_EXIT() PT_EXIT(__eh_pt)
+
+// Explicitly restart the protothread.
+#define EH_RESTART() PT_RESTART(__eh_pt)
+
+// Yield execution for one cycle.
+#define EH_YIELD() PT_YIELD(__eh_pt)
+
+// Suspend execution until condition `c` is satisfied.
+#define EH_WAIT_UNTIL(c) PT_WAIT_UNTIL(__eh_pt, c)
+
+// Suspend execution until condition `c` is satisfied.
+#define EH_YIELD_UNTIL(c) PT_YIELD_UNTIL(__eh_pt, c)
+
+// Unconditionally suspend execution for `s` seconds.
+#define EH_SLEEP_FOR(s) do { \
+ schedule_next_event(s); \
+ EH_YIELD_UNTIL(EventHandler::get_ms_to_next_event() == 0); \
+ unschedule_next_event(); \
+ } while (0)
+
+// Wait for condition `c` be satisfied for no more than `s` seconds.
+#define EH_WAIT_UNTIL_WITH_TIMEOUT(s, c) do { \
+ eh_did_timeout = false; \
+ schedule_next_event(s); \
+ EH_WAIT_UNTIL((c) || (eh_did_timeout=(EventHandler::get_ms_to_next_event() == 0))); \
+ unschedule_next_event(); \
+ } while (0)
+
+// Require that condition `c` be satisfied within `s` seconds. If not, goto `l`.
+#define EH_REQUIRE_WITHIN(s, c, l) do { \
+ EH_WAIT_UNTIL_WITH_TIMEOUT(s, c); \
+ require_string(!eh_did_timeout, l, # c); \
+ } while (0)
+
+
+// This class is the base class for tasks (like joining or forming).
+// They allow you to implement complex, stateful processes without being
+// too unwieldly.
+class EventHandler
+{
+public:
+ typedef struct pt PT;
+
+ EventHandler();
+
+ virtual ~EventHandler();
+
+ virtual cms_t get_ms_to_next_event();
+
+ virtual int vprocess_event(int event, va_list args) = 0;
+
+ int process_event(int event, ...);
+
+ void schedule_next_event(float seconds_until_event);
+ void unschedule_next_event(void);
+
+public:
+ PT mControlPT;
+
+private:
+ cms_t mControlTime;
+};
+
+}; // namespace nl
+
+#endif /* defined(__wpantund__EventHandler__) */
diff --git a/src/util/IPv6Helpers.cpp b/src/util/IPv6Helpers.cpp
new file mode 100644
index 0000000..21fd2d5
--- /dev/null
+++ b/src/util/IPv6Helpers.cpp
@@ -0,0 +1,64 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * This file contains helper glue code for manipulating IPv6 addresses.
+ *
+ */
+
+#include "IPv6Helpers.h"
+
+std::string
+in6_addr_to_string(const struct in6_addr &addr)
+{
+ char address_string[INET6_ADDRSTRLEN] = "::";
+ inet_ntop(AF_INET6, (const void *)&addr, address_string, sizeof(address_string));
+ return std::string(address_string);
+}
+
+struct in6_addr
+make_slaac_addr_from_eui64(const uint8_t prefix[8], const uint8_t eui64[8])
+{
+ struct in6_addr ret;
+
+ // Construct the IPv6 address from the prefix and EUI64.
+ memcpy(&ret.s6_addr[0], prefix, 8);
+ memcpy(&ret.s6_addr[8], eui64, 8);
+
+ // Flip the administratively assigned bit.
+ ret.s6_addr[8] ^= 0x02;
+
+ return ret;
+}
+
+void
+in6_addr_apply_mask(struct in6_addr &address, uint8_t mask)
+{
+ if (mask > 128) {
+ mask = 128;
+ }
+
+ memset(
+ (void*)(address.s6_addr + ((mask + 7) / 8)),
+ 0,
+ 16 - ((mask + 7) / 8)
+ );
+
+ if (mask % 8) {
+ address.s6_addr[mask / 8] &= ~(0xFF >> (mask % 8));
+ }
+}
diff --git a/src/util/IPv6Helpers.h b/src/util/IPv6Helpers.h
new file mode 100644
index 0000000..2bc3ef6
--- /dev/null
+++ b/src/util/IPv6Helpers.h
@@ -0,0 +1,72 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * This file contains helper glue code for manipulating IPv6 addresses.
+ *
+ */
+
+#ifndef wpantund_IPv6Helpers_h
+#define wpantund_IPv6Helpers_h
+
+#include <stdint.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <string>
+
+#define MINIMUM_IPV6_PACKET_SIZE 40
+
+#define IPV6_MAX_PREFIX_LENGTH 128
+#define IPV6_NETWORK_PREFIX_LENGTH 64
+
+#define IPV6_PREFIX_BITS_TO_BYTES(x) ((static_cast<uint8_t>(x)+7)/8)
+#define IPV6_PREFIX_BYTES_TO_BITS(x) (static_cast<uint8_t>(x)*8)
+
+#define IPV6_MAX_LIFETIME UINT32_MAX
+
+static inline bool
+operator==(const struct in6_addr &lhs, const struct in6_addr &rhs)
+{
+ return 0 == memcmp((const void*)&lhs, (const void*)&rhs, sizeof(rhs));
+}
+
+static inline bool
+operator!=(const struct in6_addr &lhs, const struct in6_addr &rhs)
+{
+ return !(lhs == rhs);
+}
+
+static inline bool
+operator<(const struct in6_addr &lhs, const struct in6_addr &rhs)
+{
+ return memcmp(lhs.s6_addr, rhs.s6_addr, sizeof(struct in6_addr)) < 0;
+}
+
+static inline bool
+is_valid_ipv6_packet(const uint8_t* packet, ssize_t len) {
+ return (len > MINIMUM_IPV6_PACKET_SIZE)
+ && (packet[0] & 0xF0) == 0x60; // IPv6 Version
+}
+
+std::string in6_addr_to_string(const struct in6_addr &addr);
+
+struct in6_addr make_slaac_addr_from_eui64(const uint8_t prefix[8], const uint8_t eui64[8]);
+
+void in6_addr_apply_mask(struct in6_addr &address, uint8_t mask);
+
+
+#endif
diff --git a/src/util/IPv6PacketMatcher.cpp b/src/util/IPv6PacketMatcher.cpp
new file mode 100644
index 0000000..9455ad7
--- /dev/null
+++ b/src/util/IPv6PacketMatcher.cpp
@@ -0,0 +1,550 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "IPv6PacketMatcher.h"
+#include <syslog.h>
+#include <stdio.h>
+
+#ifndef IPV6_PACKET_MATCHER_DEBUG
+#define IPV6_PACKET_MATCHER_DEBUG 0
+#endif
+
+using namespace nl;
+
+const uint8_t IPv6PacketMatcherRule::TYPE_ALL = 0xFF;
+const uint8_t IPv6PacketMatcherRule::TYPE_NONE = 0xFE;
+const uint8_t IPv6PacketMatcherRule::TYPE_UDP = 17;
+const uint8_t IPv6PacketMatcherRule::TYPE_TCP = 6;
+const uint8_t IPv6PacketMatcherRule::TYPE_ICMP = 58;
+const uint8_t IPv6PacketMatcherRule::TYPE_HOP_BY_HOP = 0;
+
+const uint8_t IPv6PacketMatcherRule::SUBTYPE_ALL = 0xFF;
+const uint8_t IPv6PacketMatcherRule::SUBTYPE_ICMP_NEIGHBOR_ADV = 136;
+const uint8_t IPv6PacketMatcherRule::SUBTYPE_ICMP_NEIGHBOR_SOL = 135;
+const uint8_t IPv6PacketMatcherRule::SUBTYPE_ICMP_ROUTER_SOL = 133;
+const uint8_t IPv6PacketMatcherRule::SUBTYPE_ICMP_ROUTER_ADV = 134;
+
+#define IPV6_HEADER_LENGTH 40
+#define IPV6_TCP_HEADER_CHECKSUM_OFFSET (IPV6_HEADER_LENGTH + 16)
+#define IPV6_UDP_HEADER_CHECKSUM_OFFSET (IPV6_HEADER_LENGTH + 6)
+
+#define PACKET_IS_IPV6(x) ((static_cast<const uint8_t*>(x)[0] & 0xF0) == 0x60)
+#define IPV6_GET_TYPE(x) (static_cast<const uint8_t*>(x)[6])
+#define IPV6_GET_SRC_PORT(x) (in_port_t)(*(const uint16_t*)((const uint8_t*)(x)+40))
+#define IPV6_GET_DEST_PORT(x) (in_port_t)(*(const uint16_t*)((const uint8_t*)(x)+42))
+#define IPV6_GET_SRC_ADDR(t,f) memcpy(&t, static_cast<const uint8_t*>(f) + 8, 16)
+#define IPV6_GET_DEST_ADDR(t,f) memcpy(&t, static_cast<const uint8_t*>(f) + 24, 16)
+#define IPV6_ICMP_GET_SUBTYPE(x) (static_cast<const uint8_t*>(x)[40])
+#define IPv6_TCP_GET_CHECKSUM(p,l) IPV6_GET_UINT16(p, l, IPV6_TCP_HEADER_CHECKSUM_OFFSET)
+#define IPv6_UDP_GET_CHECKSUM(p,l) IPV6_GET_UINT16(p, l, IPV6_UDP_HEADER_CHECKSUM_OFFSET)
+
+static inline uint16_t IPV6_GET_UINT16(const uint8_t *packet, ssize_t len, size_t offset)
+{
+ uint16_t ret;
+
+ ret = (len >= offset + sizeof(uint16_t))
+ ? (packet[offset]<<8) | (packet[offset + 1]<<0)
+ : 0;
+
+ return ret;
+}
+
+static void ipv6_add_extra_description(char *buffer, size_t buffer_size, const uint8_t *packet, ssize_t len)
+{
+ uint8_t type(IPV6_GET_TYPE(packet));
+
+ switch (type)
+ {
+ case IPv6PacketMatcherRule::TYPE_TCP:
+ snprintf(buffer, buffer_size, "(cksum 0x%04x)", IPv6_TCP_GET_CHECKSUM(packet, len));
+ break;
+
+ case IPv6PacketMatcherRule::TYPE_UDP:
+ snprintf(buffer, buffer_size, "(cksum 0x%04x)", IPv6_UDP_GET_CHECKSUM(packet, len));
+ break;
+
+ default:
+ buffer[0] = 0;
+ }
+}
+
+void
+IPv6PacketMatcherRule::clear()
+{
+ memset((void*)this, 0, sizeof(*this));
+ type = TYPE_ALL;
+ subtype = SUBTYPE_ALL;
+}
+
+IPv6PacketMatcherRule&
+IPv6PacketMatcherRule::update_from_inbound_packet(const uint8_t* packet)
+{
+ struct in6_addr address;
+
+ clear();
+
+ if (!PACKET_IS_IPV6(packet)) {
+ goto bail;
+ }
+
+ type = IPV6_GET_TYPE(packet);
+
+ subtype = IPv6PacketMatcherRule::SUBTYPE_ALL;
+
+ if (type == IPv6PacketMatcherRule::TYPE_TCP || type == IPv6PacketMatcherRule::TYPE_UDP) {
+ remote_port = IPV6_GET_SRC_PORT(packet);
+ remote_port_match = true;
+
+ local_port = IPV6_GET_DEST_PORT(packet);
+ local_port_match = true;
+ } else {
+ remote_port = 0;
+ remote_port_match = false;
+ local_port = 0;
+ local_port_match = false;
+ if (type == IPv6PacketMatcherRule::TYPE_ICMP) {
+ subtype = IPV6_ICMP_GET_SUBTYPE(packet);
+ }
+ }
+
+ IPV6_GET_DEST_ADDR(address, packet);
+ if (!IN6_IS_ADDR_MULTICAST(&address)) {
+ local_address = address;
+ local_match_mask = 128;
+ } else {
+ local_match_mask = 0;
+ }
+
+ IPV6_GET_SRC_ADDR(address, packet);
+ remote_address = address;
+ remote_match_mask = 128;
+
+bail:
+ return *this;
+}
+
+
+bool
+IPv6PacketMatcherRule::match_inbound(const uint8_t* packet) const
+{
+ if (!PACKET_IS_IPV6(packet)) {
+ return false;
+ }
+
+ if (type == TYPE_NONE) {
+ return false;
+ }
+
+ if (type != IPv6PacketMatcherRule::TYPE_ALL) {
+ if (type != IPV6_GET_TYPE(packet)) {
+ return false;
+ }
+ if (subtype != IPv6PacketMatcherRule::SUBTYPE_ALL) {
+ if (subtype != IPV6_ICMP_GET_SUBTYPE(packet)) {
+ return false;
+ }
+ }
+ }
+
+ if (local_port_match) {
+ in_port_t port(IPV6_GET_DEST_PORT(packet));
+ if (port != local_port)
+ return false;
+ }
+
+ if (remote_port_match) {
+ in_port_t port(IPV6_GET_SRC_PORT(packet));
+ if (port != remote_port)
+ return false;
+ }
+
+ if (local_match_mask) {
+ struct in6_addr address;
+ IPV6_GET_DEST_ADDR(address, packet);
+ in6_addr_apply_mask(address, local_match_mask);
+ if (address != local_address)
+ return false;
+ }
+
+ if (remote_match_mask) {
+ struct in6_addr address;
+ IPV6_GET_SRC_ADDR(address, packet);
+ in6_addr_apply_mask(address, remote_match_mask);
+ if (address != remote_address)
+ return false;
+ }
+ return true;
+}
+
+IPv6PacketMatcherRule&
+IPv6PacketMatcherRule::update_from_outbound_packet(const uint8_t* packet)
+{
+ struct in6_addr address;
+
+ clear();
+
+ if (!PACKET_IS_IPV6(packet)) {
+ goto bail;
+ }
+
+ type = IPV6_GET_TYPE(packet);
+
+ subtype = IPv6PacketMatcherRule::SUBTYPE_ALL;
+
+ if (type == IPv6PacketMatcherRule::TYPE_TCP || type == IPv6PacketMatcherRule::TYPE_UDP) {
+ remote_port = IPV6_GET_DEST_PORT(packet);
+ remote_port_match = true;
+
+ local_port = IPV6_GET_SRC_PORT(packet);
+ local_port_match = true;
+ } else {
+ remote_port = 0;
+ remote_port_match = false;
+ local_port = 0;
+ local_port_match = false;
+ if (type == IPv6PacketMatcherRule::TYPE_ICMP) {
+ subtype = IPV6_ICMP_GET_SUBTYPE(packet);
+ }
+ }
+
+ IPV6_GET_SRC_ADDR(address, packet);
+ local_address = address;
+ local_match_mask = 128;
+
+ IPV6_GET_DEST_ADDR(address, packet);
+ remote_address = address;
+ remote_match_mask = 128;
+
+bail:
+ return *this;
+}
+
+bool
+IPv6PacketMatcherRule::match_outbound(const uint8_t* packet) const
+{
+ if (!PACKET_IS_IPV6(packet)) {
+ return false;
+ }
+
+ if (type == TYPE_NONE) {
+ return false;
+ }
+
+ if (type != IPv6PacketMatcherRule::TYPE_ALL) {
+ if (type != IPV6_GET_TYPE(packet)) {
+ return false;
+ }
+ if (subtype != IPv6PacketMatcherRule::SUBTYPE_ALL) {
+ if (subtype != IPV6_ICMP_GET_SUBTYPE(packet)) {
+ return false;
+ }
+ }
+ }
+
+ if (local_port_match) {
+ in_port_t port(IPV6_GET_SRC_PORT(packet));
+ if (port != local_port) {
+ return false;
+ }
+ }
+
+ if (remote_port_match) {
+ in_port_t port(IPV6_GET_DEST_PORT(packet));
+ if (port != remote_port) {
+ return false;
+ }
+ }
+
+ if (local_match_mask) {
+ struct in6_addr address;
+ IPV6_GET_SRC_ADDR(address, packet);
+ in6_addr_apply_mask(address, local_match_mask);
+ if (address != local_address) {
+ return false;
+ }
+ }
+
+ if (remote_match_mask) {
+ struct in6_addr address;
+ IPV6_GET_DEST_ADDR(address, packet);
+ in6_addr_apply_mask(address, remote_match_mask);
+ if (address != remote_address) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool
+IPv6PacketMatcherRule::operator==(const IPv6PacketMatcherRule& lhs) const
+{
+#if IPV6_PACKET_MATCHER_DEBUG
+ syslog(LOG_DEBUG, "IPv6PacketMatcherRule operator==():\n");
+
+#define __DUMP(x,f,t) syslog(LOG_DEBUG, "\t lhs." #x "=" f "\t%s\trhs." #x "=" f "\n",(t)lhs.x,(lhs.x < x)?">":(x > lhs.x)?">":"==",(t)x);
+#define __DUMP_NTOHS(x,f) syslog(LOG_DEBUG, "\t lhs." #x "=" f "\t%s\trhs." #x "=" f "\n",ntohs(lhs.x),(ntohs(lhs.x) < ntohs(x))?">":(ntohs(x) > ntohs(lhs.x))?">":"==",ntohs(x));
+#define __DUMP_MEM(x) syslog(LOG_DEBUG, "\t lhs." #x "\t%s\trhs." #x "\n",(memcmp(&x, &lhs.x, 16) < 0)?">":(memcmp(&x, &lhs.x, 16) > 0)?">":"==");
+
+ __DUMP(type,"%d",int);
+ __DUMP(subtype,"%d",int);
+ __DUMP_NTOHS(local_port,"%d");
+ __DUMP(local_port_match,"%d",int);
+ __DUMP(local_match_mask,"%d",int);
+ __DUMP_MEM(local_address);
+
+ __DUMP_NTOHS(remote_port,"%d");
+ __DUMP(remote_port_match,"%d",int);
+ __DUMP(remote_match_mask,"%d",int);
+ __DUMP_MEM(remote_address);
+
+#undef __DUMP
+#undef __DUMP_NTOHS
+#undef __DUMP_MEM
+
+#endif // IPV6_PACKET_MATCHER_DEBUG
+
+ if (type != lhs.type) {
+ return false;
+ }
+ if (subtype != lhs.subtype) {
+ return false;
+ }
+ if (local_port != lhs.local_port) {
+ return false;
+ }
+ if (local_port_match != lhs.local_port_match) {
+ return false;
+ }
+ if (local_match_mask != lhs.local_match_mask) {
+ return false;
+ }
+ if (local_address != lhs.local_address) {
+ return false;
+ }
+ if (remote_port != lhs.remote_port) {
+ return false;
+ }
+ if (remote_port_match != lhs.remote_port_match) {
+ return false;
+ }
+ if (remote_match_mask != lhs.remote_match_mask) {
+ return false;
+ }
+ if (remote_address != lhs.remote_address) {
+ return false;
+ }
+ return true;
+
+ return 0 == memcmp(this,
+ &lhs,
+ (uint8_t*)&remote_match_mask - (uint8_t*)this + 1);
+}
+
+bool
+IPv6PacketMatcherRule::operator<(const IPv6PacketMatcherRule& lhs) const
+{
+ if (type < lhs.type) {
+ return true;
+ } else if (type > lhs.type) {
+ return false;
+ }
+
+ if (subtype < lhs.subtype) {
+ return true;
+ } else if (subtype > lhs.subtype) {
+ return false;
+ }
+
+ if (local_port < lhs.local_port) {
+ return true;
+ } else if (local_port > lhs.local_port) {
+ return false;
+ }
+
+ if (local_port_match < lhs.local_port_match) {
+ return true;
+ } else if (local_port_match > lhs.local_port_match) {
+ return false;
+ }
+
+ if (local_match_mask < lhs.local_match_mask) {
+ return true;
+ } else if (local_match_mask > lhs.local_match_mask) {
+ return false;
+ }
+
+ if (memcmp(&local_address, &lhs.local_address, 16) < 0) {
+ return true;
+ } else if (memcmp(&local_address, &lhs.local_address, 16) > 0) {
+ return false;
+ }
+
+ if (remote_port < lhs.remote_port) {
+ return true;
+ } else if (remote_port > lhs.remote_port) {
+ return false;
+ }
+
+ if (remote_port_match < lhs.remote_port_match) {
+ return true;
+ } else if (remote_port_match > lhs.remote_port_match) {
+ return false;
+ }
+
+ if (remote_match_mask < lhs.remote_match_mask) {
+ return true;
+ } else if (remote_match_mask > lhs.remote_match_mask) {
+ return false;
+ }
+
+ if (memcmp(&remote_address, &lhs.remote_address, 16) < 0) {
+ return true;
+ } else if (memcmp(&remote_address, &lhs.remote_address, 16) > 0) {
+ return false;
+ }
+
+ return false;
+}
+
+IPv6PacketMatcher::const_iterator
+IPv6PacketMatcher::match_outbound(const uint8_t* packet) const
+{
+ iterator iter;
+ for(iter = begin(); iter != end(); ++iter) {
+ if(iter->match_outbound(packet)) {
+ break;
+ }
+ }
+ return iter;
+}
+
+IPv6PacketMatcher::const_iterator
+IPv6PacketMatcher::match_inbound(const uint8_t* packet) const
+{
+ iterator iter;
+ for(iter = begin(); iter != end(); ++iter) {
+ if(iter->match_inbound(packet)) {
+ break;
+ }
+ }
+ return iter;
+}
+
+void
+nl::dump_outbound_ipv6_packet(const uint8_t* packet, ssize_t len, const char* extra, bool dropped)
+{
+ if(!(setlogmask(0)&LOG_MASK(LOG_INFO))) {
+ return;
+ }
+ char to_addr_cstr[INET6_ADDRSTRLEN] = "::";
+ char from_addr_cstr[INET6_ADDRSTRLEN] = "::";
+ uint8_t type(IPV6_GET_TYPE(packet));
+ char type_extra[32];
+ struct in6_addr addr;
+
+ ipv6_add_extra_description(type_extra, sizeof(type_extra), packet, len);
+
+ syslog(LOG_INFO,
+ "[->NCP] IPv6 len:%d type:%d%s [%s]%s",
+ (int)len,
+ type,
+ type_extra,
+ extra,
+ dropped?" [DROPPED]":""
+ );
+
+ IPV6_GET_SRC_ADDR(addr, packet);
+ inet_ntop(AF_INET6, addr.s6_addr, from_addr_cstr, sizeof(from_addr_cstr));
+
+ IPV6_GET_DEST_ADDR(addr, packet);
+ inet_ntop(AF_INET6, addr.s6_addr, to_addr_cstr, sizeof(to_addr_cstr));
+
+ if ((type == IPv6PacketMatcherRule::TYPE_TCP)
+ || (type == IPv6PacketMatcherRule::TYPE_UDP)
+ ) {
+ in_port_t to_port(IPV6_GET_DEST_PORT(packet));
+ in_port_t from_port(IPV6_GET_SRC_PORT(packet));
+
+ syslog(LOG_INFO,
+ "\tto(remote):[%s]:%d",
+ to_addr_cstr,
+ htons(to_port));
+
+ syslog(LOG_INFO,
+ "\tfrom(local):[%s]:%d",
+ from_addr_cstr,
+ htons(from_port));
+ } else {
+ syslog(LOG_INFO, "\tto(remote):[%s]", to_addr_cstr);
+ syslog(LOG_INFO, "\tfrom(local):[%s]", from_addr_cstr);
+ }
+}
+
+void
+nl::dump_inbound_ipv6_packet(const uint8_t* packet, ssize_t len, const char* extra, bool dropped)
+{
+ if(!(setlogmask(0)&LOG_MASK(LOG_INFO))) {
+ return;
+ }
+ char to_addr_cstr[INET6_ADDRSTRLEN] = "::";
+ char from_addr_cstr[INET6_ADDRSTRLEN] = "::";
+ uint8_t type(IPV6_GET_TYPE(packet));
+ char type_extra[32];
+ struct in6_addr addr;
+
+ ipv6_add_extra_description(type_extra, sizeof(type_extra), packet, len);
+
+ syslog(LOG_INFO,
+ "[NCP->] IPv6 len:%d type:%d%s [%s]%s",
+ (int)len,
+ type,
+ type_extra,
+ extra,
+ dropped?" [DROPPED]":""
+ );
+
+ IPV6_GET_SRC_ADDR(addr, packet);
+ inet_ntop(AF_INET6, addr.s6_addr, from_addr_cstr, sizeof(from_addr_cstr));
+
+ IPV6_GET_DEST_ADDR(addr, packet);
+ inet_ntop(AF_INET6, addr.s6_addr, to_addr_cstr, sizeof(to_addr_cstr));
+ if ((type == IPv6PacketMatcherRule::TYPE_TCP)
+ || (type == IPv6PacketMatcherRule::TYPE_UDP)
+ ) {
+ in_port_t to_port(IPV6_GET_DEST_PORT(packet));
+ in_port_t from_port(IPV6_GET_SRC_PORT(packet));
+
+ syslog(LOG_INFO,
+ "\tto(local):[%s]:%d",
+ to_addr_cstr,
+ htons(to_port));
+
+ syslog(LOG_INFO,
+ "\tfrom(remote):[%s]:%d",
+ from_addr_cstr,
+ htons(from_port));
+ } else {
+ syslog(LOG_INFO, "\tto(local):[%s]", to_addr_cstr);
+ syslog(LOG_INFO, "\tfrom(remote):[%s]", from_addr_cstr);
+ }
+}
diff --git a/src/util/IPv6PacketMatcher.h b/src/util/IPv6PacketMatcher.h
new file mode 100644
index 0000000..f8e218a
--- /dev/null
+++ b/src/util/IPv6PacketMatcher.h
@@ -0,0 +1,84 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __wpantund__IPv6PacketMatcherRule__
+#define __wpantund__IPv6PacketMatcherRule__
+
+#include <stdint.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <set>
+#include "IPv6Helpers.h"
+
+
+namespace nl {
+
+void dump_outbound_ipv6_packet(const uint8_t* packet, ssize_t len, const char* extra, bool dropped = false);
+void dump_inbound_ipv6_packet(const uint8_t* packet, ssize_t len, const char* extra, bool dropped = false);
+
+struct IPv6PacketMatcherRule {
+ static const uint8_t TYPE_ALL;
+ static const uint8_t TYPE_NONE;
+ static const uint8_t TYPE_UDP;
+ static const uint8_t TYPE_TCP;
+ static const uint8_t TYPE_ICMP;
+ static const uint8_t TYPE_HOP_BY_HOP;
+ static const uint8_t SUBTYPE_ALL;
+ static const uint8_t SUBTYPE_ICMP_NEIGHBOR_ADV;
+ static const uint8_t SUBTYPE_ICMP_NEIGHBOR_SOL;
+ static const uint8_t SUBTYPE_ICMP_ROUTER_ADV;
+ static const uint8_t SUBTYPE_ICMP_ROUTER_SOL;
+
+ uint8_t type;
+ uint8_t subtype;
+ in_port_t local_port;
+ bool local_port_match;
+ struct in6_addr local_address;
+ uint8_t local_match_mask;
+
+ in_port_t remote_port;
+ bool remote_port_match;
+ struct in6_addr remote_address;
+ uint8_t remote_match_mask;
+
+ void clear();
+ IPv6PacketMatcherRule& update_from_inbound_packet(const uint8_t* packet);
+ bool match_inbound(const uint8_t* packet) const;
+ IPv6PacketMatcherRule& update_from_outbound_packet(const uint8_t* packet);
+ bool match_outbound(const uint8_t* packet) const;
+ bool operator==(const IPv6PacketMatcherRule& lhs) const;
+ bool operator<(const IPv6PacketMatcherRule& lhs) const;
+
+ bool operator!=(const IPv6PacketMatcherRule& lhs) const { return !(*this == lhs); }
+ bool operator>=(const IPv6PacketMatcherRule& lhs) const { return !(*this < lhs); }
+
+ bool operator<=(const IPv6PacketMatcherRule& lhs) const { return (*this < lhs) || (*this == lhs); }
+ bool operator>(const IPv6PacketMatcherRule& lhs) const { return !(*this <= lhs); }
+};
+
+class IPv6PacketMatcher : public std::set<IPv6PacketMatcherRule> {
+public:
+
+ const_iterator match_outbound(const uint8_t* packet) const;
+ const_iterator match_inbound(const uint8_t* packet) const;
+};
+
+}; // namespace nl
+
+#endif /* defined(__wpantund__IPv6PacketMatcherRule__) */
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
new file mode 100644
index 0000000..2ae3942
--- /dev/null
+++ b/src/util/Makefile.am
@@ -0,0 +1,72 @@
+#
+# Copyright (c) 2016 Nest Labs, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+EXTRA_DIST = \
+ config-file.c \
+ nlpt-select.c \
+ socket-utils.c \
+ string-utils.c \
+ time-utils.c \
+ tunnel.c \
+ DBUSHelpers.cpp \
+ Data.cpp \
+ EventHandler.cpp \
+ IPv6PacketMatcher.cpp \
+ SocketAdapter.cpp \
+ SocketWrapper.cpp \
+ SuperSocket.cpp \
+ TunnelIPv6Interface.cpp \
+ UnixSocket.cpp \
+ any-to.cpp \
+ Callbacks.h \
+ DBUSHelpers.h \
+ Data.h \
+ EventHandler.h \
+ IPv6Helpers.h \
+ IPv6Helpers.cpp \
+ IPv6PacketMatcher.h \
+ NilReturn.h \
+ SocketAdapter.h \
+ SocketAsyncOp.h \
+ SocketWrapper.h \
+ SuperSocket.h \
+ TunnelIPv6Interface.h \
+ UnixSocket.h \
+ any-to.h \
+ args.h \
+ config-file.h \
+ nlpt-select.h \
+ nlpt.h \
+ socket-utils.h \
+ string-utils.h \
+ time-utils.h \
+ tunnel.h \
+ CallbackStore.hpp \
+ RingBuffer.h \
+ ValueMap.h \
+ ValueMap.cpp \
+ ObjectPool.h \
+ Timer.h \
+ Timer.cpp \
+ sec-random.h \
+ sec-random.c \
+ $(NULL)
+
+DISTCLEANFILES = \
+ .deps \
+ Makefile \
+ $(NULL)
diff --git a/src/util/NilReturn.h b/src/util/NilReturn.h
new file mode 100644
index 0000000..c736be8
--- /dev/null
+++ b/src/util/NilReturn.h
@@ -0,0 +1,36 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef wpantund_NilReturn_h
+#define wpantund_NilReturn_h
+
+
+namespace nl {
+class NilReturn {
+public:
+ void operator()(void) {
+ }
+ void operator()(int) {
+ }
+ template<typename ARG_X, typename ARG_Y> void operator()(ARG_X, ARG_Y) {
+ }
+};
+};
+
+#endif
diff --git a/src/util/ObjectPool.h b/src/util/ObjectPool.h
new file mode 100644
index 0000000..493b3a1
--- /dev/null
+++ b/src/util/ObjectPool.h
@@ -0,0 +1,92 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * A simple object pool implementation
+ *
+ */
+
+#ifndef wpantund_ObjectPool_h
+#define wpantund_ObjectPool_h
+
+#include <list>
+
+namespace nl {
+
+template <typename T, int I = 64>
+class ObjectPool
+{
+public:
+ typedef T element_type;
+ typedef int size_type;
+
+ static const size_type pool_size = I;
+
+public:
+ ObjectPool(): mFreeElementList()
+ {
+ free_all();
+ }
+
+ // Free all elements in the object pool
+ void free_all(void)
+ {
+ size_type count = pool_size;
+ element_type *element_ptr;
+
+ mFreeElementList.clear();
+
+ element_ptr = &mElementPool[pool_size - 1];
+ while(count--) {
+ mFreeElementList.push_back(element_ptr);
+ element_ptr--;
+ }
+ }
+
+ // Attempts to allocate a new object from pool, returns NULL if no object available.
+ element_type *alloc(void)
+ {
+ element_type *element_ptr = NULL;
+ if (!mFreeElementList.empty()) {
+ element_ptr = mFreeElementList.front();
+ mFreeElementList.pop_front();
+ }
+ return element_ptr;
+ }
+
+ // Frees a previously allocated pool object.
+ void free(element_type *element_ptr)
+ {
+ if (is_ptr_in_pool(element_ptr)) {
+ mFreeElementList.push_back(element_ptr);
+ }
+ }
+
+private:
+ element_type mElementPool[pool_size];
+ std::list<element_type *>mFreeElementList;
+
+ bool is_ptr_in_pool(const element_type *ptr) const
+ {
+ return ((ptr >= mElementPool) && (ptr < mElementPool + pool_size));
+ }
+
+};
+
+}; // namespace nl
+
+#endif // wpantund_ObjectPool_h
diff --git a/src/util/RingBuffer.h b/src/util/RingBuffer.h
new file mode 100644
index 0000000..d842e48
--- /dev/null
+++ b/src/util/RingBuffer.h
@@ -0,0 +1,396 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * Ring-buffer implementation (not thread-safe)
+ *
+ */
+
+#ifndef wpantund_RingBuffer_h
+#define wpantund_RingBuffer_h
+
+#include <stdint.h>
+#include <stdexcept>
+
+namespace nl {
+
+// NOTE: The below implementation of RingBuffer<> is NOT thread-safe.
+
+template <typename T = uint8_t, int I = 512>
+class RingBuffer
+{
+public:
+
+ typedef T value_type;
+ typedef int size_type;
+
+ static const size_type buffer_size = I;
+
+public:
+
+ RingBuffer()
+ {
+ clear();
+ }
+
+ size_type size() const
+ {
+ return mCount;
+ }
+
+ size_type space_available() const
+ {
+ return buffer_size - mCount;
+ }
+
+ bool empty() const
+ {
+ return (mCount == 0);
+ }
+
+ bool full() const
+ {
+ return (mCount == buffer_size);
+ }
+
+ size_type max_size() const
+ {
+ return buffer_size;
+ }
+
+ const value_type* data_ptr()const {
+ return &mBuffer[mReadIdx];
+ }
+
+ size_type size_of_data_ptr()const {
+ size_type ret;
+
+ if (mWriteIdx >= mReadIdx) {
+ ret = mWriteIdx - mReadIdx;
+ } else {
+ ret = buffer_size - mReadIdx;
+ }
+
+ return ret;
+ }
+
+ template <typename S> void
+ push(const value_type* values, S value_count)
+ {
+ if (space_available() < value_count) {
+ throw std::overflow_error("not enough room in ring buffer");
+ }
+
+ while(value_count--) {
+ mBuffer[mWriteIdx] = *values++;
+ mWriteIdx++;
+ mWriteIdx %= buffer_size; // Should be optimized by compiler as a mask
+ mCount++;
+ }
+ }
+
+ template <typename S> size_type
+ pop(S value_count)
+ {
+ size_type bytes_read = size();
+
+ if (bytes_read < value_count) {
+ value_count = bytes_read;
+ } else {
+ bytes_read = static_cast<size_type>(value_count);
+ }
+
+ while (value_count--) {
+ mReadIdx++;
+ mReadIdx %= buffer_size; // Should be optimized by compiler as a mask
+ mCount--;
+ }
+
+ if (mReadIdx == mWriteIdx) {
+ mReadIdx = mWriteIdx = 0;
+ }
+
+ return bytes_read;
+ }
+
+ template <typename S> size_type
+ pull(value_type* values, S value_count)
+ {
+ size_type bytes_read = size();
+
+ if (bytes_read < value_count) {
+ value_count = bytes_read;
+ } else {
+ bytes_read = static_cast<size_type>(value_count);
+ }
+
+ while (value_count--) {
+ *values++ = mBuffer[mReadIdx];
+ mReadIdx++;
+ mReadIdx %= buffer_size; // Should be optimized by compiler as a mask
+ mCount--;
+ }
+
+ return bytes_read;
+ }
+
+ // Returns a pointer to the front (head) element in ring buffer if the ring buffer
+ // is not empty, or returns NULL if buffer is empty.
+ const value_type *front() const
+ {
+ return (mCount == 0)? NULL : &mBuffer[mReadIdx];
+ }
+
+ // Returns a pointer to the back (tail) element in ring buffer if the ring buffer
+ // is not empty, or returns NULL if buffer is empty.
+ const value_type *back() const
+ {
+ if (mCount == 0) {
+ return NULL;
+ }
+
+ if (mWriteIdx == 0) {
+ return &mBuffer[buffer_size - 1];
+ }
+
+ return &mBuffer[mWriteIdx - 1];
+ }
+
+ // Attempts to write the new value in the ring buffer, if buffer is full
+ // and write fails, returns false, otherwise returns true.
+ bool write(const value_type& value)
+ {
+ if (mCount == buffer_size) {
+ return false;
+ }
+
+ mBuffer[mWriteIdx] = value;
+ mWriteIdx++;
+ mWriteIdx %= buffer_size;
+ mCount++;
+
+ return true;
+ }
+
+ // Force writes the new value in the ring buffer. May overwrite an earlier value and move
+ // the read index forward (if buffer is full).
+ void force_write(const value_type& value)
+ {
+ mBuffer[mWriteIdx] = value;
+ mWriteIdx++;
+ mWriteIdx %= buffer_size;
+
+ if (mCount == buffer_size) {
+ mReadIdx = mWriteIdx;
+ } else {
+ mCount++;
+ }
+ }
+
+ // Reads one element from the head of ring buffer and removes it. If buffer
+ // is empty returns false, otherwise returns true.
+ bool read(value_type& value)
+ {
+ value_type *f = front();
+
+ if (f) {
+ value = *f;
+ }
+
+ return remove();
+ }
+
+ // Removes the element from front of the ring buffer. If buffer is empty
+ // and the remove operation fails, returns false, otherwise returns true.
+ bool remove()
+ {
+ if (mCount == 0) {
+ return false;
+ }
+
+ mReadIdx++;
+ mReadIdx %= buffer_size;
+ mCount--;
+
+ return true;
+ }
+
+ // Clears the ring buffer.
+ void clear()
+ {
+ mReadIdx = mWriteIdx = 0;
+ mCount = 0;
+ }
+
+private:
+ class IteratorBase
+ {
+ protected:
+ IteratorBase(const value_type *ptr, const RingBuffer *ring_buffer_ptr)
+ {
+ mIterPtr = ptr;
+ mRingBufferPtr = ring_buffer_ptr;
+ }
+
+ IteratorBase(const IteratorBase &it)
+ {
+ mIterPtr = it.mIterPtr;
+ mRingBufferPtr = it.mRingBufferPtr;
+ }
+
+ public:
+ bool operator==(const IteratorBase &lhs)
+ {
+ return (mIterPtr == lhs.mIterPtr) && (mRingBufferPtr == lhs.mRingBufferPtr);
+ }
+
+ bool operator!=(const IteratorBase &lhs)
+ {
+ return !((*this) == lhs);
+ }
+
+ const value_type *get_ptr() { return mIterPtr; }
+
+ const value_type& operator* () { return *mIterPtr; }
+ const value_type* operator-> () { return mIterPtr; }
+
+ protected:
+ const value_type *mIterPtr;
+ const RingBuffer *mRingBufferPtr;
+ };
+
+public:
+ // An iterator for going through the elements in the ring buffer from front to back.
+ class Iterator : public IteratorBase
+ {
+ public:
+ Iterator() : IteratorBase(NULL, NULL) { }
+ Iterator(const Iterator &it) : IteratorBase(it) { }
+
+ Iterator& operator++() {
+ advance();
+ return *this;
+ }
+
+ Iterator operator++(int val) {
+ (void)val;
+ Iterator it(*this);
+ advance();
+ return it;
+ }
+
+ void advance(void)
+ {
+ const RingBuffer *rb = this->mRingBufferPtr;
+ if (rb)
+ {
+ this->mIterPtr++;
+ if (this->mIterPtr == &rb->mBuffer[rb->buffer_size]) {
+ this->mIterPtr = &rb->mBuffer[0];
+ }
+
+ if (this->mIterPtr == &rb->mBuffer[rb->mWriteIdx]) {
+ this->mIterPtr = NULL;
+ }
+ }
+ }
+
+ private:
+ Iterator(const value_type *ptr, const RingBuffer *ring_buffer_ptr) :
+ IteratorBase(ptr, ring_buffer_ptr) { }
+
+ friend Iterator RingBuffer::begin() const;
+ friend Iterator RingBuffer::end() const;
+ };
+
+ // A reverse iterator for going through the elements in the ring buffer from back to front.
+ class ReverseIterator : public IteratorBase
+ {
+ public:
+ ReverseIterator() : IteratorBase(NULL, NULL) { }
+ ReverseIterator(const Iterator &it) : IteratorBase(it) { }
+
+ ReverseIterator& operator++() {
+ advance();
+ return *this;
+ }
+
+ ReverseIterator operator++(int val) {
+ (void)val;
+ ReverseIterator it(*this);
+ advance();
+ return it;
+ }
+
+ void advance(void)
+ {
+ const RingBuffer *rb = this->mRingBufferPtr;
+ if (rb)
+ {
+ if (this->mIterPtr == &rb->mBuffer[rb->mReadIdx]) {
+ this->mIterPtr = NULL;
+ } else {
+ if (this->mIterPtr == &rb->mBuffer[0]) {
+ this->mIterPtr = &rb->mBuffer[rb->buffer_size - 1];
+ } else {
+ this->mIterPtr--;
+ }
+ }
+ }
+ }
+
+ private:
+ ReverseIterator(const value_type *ptr, const RingBuffer *ring_buffer_ptr) :
+ IteratorBase(ptr, ring_buffer_ptr) { }
+
+ friend ReverseIterator RingBuffer::rbegin() const;
+ friend ReverseIterator RingBuffer::rend() const;
+ };
+
+ // Returns a RingBuffer::Iterator to the beginning of the buffer
+ Iterator begin() const
+ {
+ return Iterator(front(), this);
+ }
+
+ // Returns a RingBuffer::Iterator marking the end/tail of the buffer
+ Iterator end() const
+ {
+ return Iterator(NULL, this);
+ }
+
+ // Returns a RingBuffer::ReverseIterator pointing to back/tail of the buffer.
+ ReverseIterator rbegin() const
+ {
+ return ReverseIterator(back(), this);
+ }
+
+ // Returns a RingBuffer::ReverseIterator pointing to end/head of the buffer.
+ ReverseIterator rend() const
+ {
+ return ReverseIterator(NULL, this);
+ }
+
+private:
+ size_type mReadIdx, mWriteIdx;
+ size_type mCount;
+ value_type mBuffer[buffer_size];
+};
+
+}; // namespace nl
+
+#endif
diff --git a/src/util/SocketAdapter.cpp b/src/util/SocketAdapter.cpp
new file mode 100644
index 0000000..b0b8d62
--- /dev/null
+++ b/src/util/SocketAdapter.cpp
@@ -0,0 +1,129 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * This file contains the implementation of the SocketAdapter class,
+ * which is a base class for implementing "soft" sockets that
+ * use other sockets (for things like reliability layers, etc).
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "SocketAdapter.h"
+#include <errno.h>
+
+using namespace nl;
+
+const boost::shared_ptr<SocketWrapper>&
+SocketAdapter::set_parent(boost::shared_ptr<SocketWrapper> parent)
+{
+ return mParent = parent;
+}
+
+const boost::shared_ptr<SocketWrapper>&
+SocketAdapter::get_parent()
+{
+ return mParent;
+}
+
+SocketAdapter::SocketAdapter(boost::shared_ptr<SocketWrapper> parent)
+ :mParent(parent)
+{
+}
+
+int
+SocketAdapter::hibernate(void)
+{
+ return mParent ? mParent->hibernate() : -EINVAL;
+}
+
+ssize_t
+SocketAdapter::write(const void* data, size_t len)
+{
+ return mParent ? mParent->write(data, len) : -EINVAL;
+}
+
+ssize_t
+SocketAdapter::read(void* data, size_t len)
+{
+ return mParent ? mParent->read(data, len) : -EINVAL;
+}
+
+bool
+SocketAdapter::can_read(void)const
+{
+ return mParent ? mParent->can_read() : false;
+}
+
+bool
+SocketAdapter::can_write(void)const
+{
+ return mParent ? mParent->can_write() : false;
+}
+
+int
+SocketAdapter::get_read_fd(void)const
+{
+ return mParent ? mParent->get_read_fd() : -EINVAL;
+}
+
+int
+SocketAdapter::get_write_fd(void)const
+{
+ return mParent ? mParent->get_write_fd() : -EINVAL;
+}
+
+int
+SocketAdapter::process(void)
+{
+ return mParent ? mParent->process() : 0;
+}
+
+void
+SocketAdapter::reset()
+{
+ if(mParent)
+ mParent->reset();
+}
+
+void
+SocketAdapter::send_break()
+{
+ if(mParent)
+ mParent->send_break();
+};
+
+bool
+SocketAdapter::did_reset()
+{
+ return mParent ? mParent->did_reset() : false;
+}
+
+cms_t
+SocketAdapter::get_ms_to_next_event(void)const
+{
+ return mParent ? mParent->get_ms_to_next_event() : CMS_DISTANT_FUTURE;
+}
+
+int
+SocketAdapter::update_fd_set(fd_set *read_fd_set, fd_set *write_fd_set, fd_set *error_fd_set, int *max_fd, cms_t *timeout)
+{
+ return mParent ? mParent->update_fd_set(read_fd_set, write_fd_set, error_fd_set, max_fd, timeout) : 0;
+}
diff --git a/src/util/SocketAdapter.h b/src/util/SocketAdapter.h
new file mode 100644
index 0000000..3e896af
--- /dev/null
+++ b/src/util/SocketAdapter.h
@@ -0,0 +1,61 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * This file contains the declaration of the SocketAdapter class,
+ * which is a base class for implementing "soft" sockets that
+ * use other sockets (for things like reliability layers, etc).
+ *
+ */
+
+#ifndef __wpantund__SocketAdapter__
+#define __wpantund__SocketAdapter__
+
+#include "SocketWrapper.h"
+
+namespace nl {
+class SocketAdapter : public SocketWrapper {
+public:
+ virtual ~SocketAdapter() {}
+ virtual const boost::shared_ptr<SocketWrapper>& set_parent(boost::shared_ptr<SocketWrapper> parent);
+ const boost::shared_ptr<SocketWrapper>& get_parent();
+
+ virtual ssize_t write(const void* data, size_t len);
+ virtual ssize_t read(void* data, size_t len);
+ virtual bool can_read(void)const;
+ virtual bool can_write(void)const;
+ virtual int get_read_fd(void)const;
+ virtual int get_write_fd(void)const;
+ virtual int process(void);
+ virtual cms_t get_ms_to_next_event(void)const;
+ virtual void send_break();
+
+ virtual void reset();
+ virtual bool did_reset();
+ virtual int update_fd_set(fd_set *read_fd_set, fd_set *write_fd_set, fd_set *error_fd_set, int *max_fd, cms_t *timeout);
+
+ virtual int hibernate(void);
+
+protected:
+ SocketAdapter(boost::shared_ptr<SocketWrapper> parent);
+ boost::shared_ptr<SocketWrapper> mParent;
+}; // class SocketAdapter
+
+
+}; // namespace nl
+
+#endif /* defined(__wpantund__SocketAdapter__) */
diff --git a/src/util/SocketAsyncOp.h b/src/util/SocketAsyncOp.h
new file mode 100644
index 0000000..cffbefb
--- /dev/null
+++ b/src/util/SocketAsyncOp.h
@@ -0,0 +1,167 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __wpantund__SocketAsyncOp__
+#define __wpantund__SocketAsyncOp__
+
+#include <stdint.h>
+#include "SocketWrapper.h"
+#include "nlpt.h"
+#include <errno.h>
+
+namespace nl {
+
+static inline int
+read_stream_pt(struct nlpt *pt, nl::SocketWrapper* socket, void* data, size_t len)
+{
+ const int fd = socket->get_read_fd();
+
+ PT_BEGIN(&pt->sub_pt);
+ pt->byte_count = 0;
+ pt->last_errno = 0;
+
+ while (pt->byte_count < len) {
+ ssize_t bytes_read;
+
+ // Wait for the socket to become readable...
+ _nlpt_setup_read_fd_source(pt, fd);
+ PT_WAIT_UNTIL(&pt->sub_pt, nlpt_hook_check_read_fd_source(pt, fd) || socket->can_read());
+ _nlpt_cleanup_read_fd_source(pt, fd);
+
+ // Read what is left of the packet on the socket.
+ bytes_read = socket->read(
+ static_cast<void*>(static_cast<uint8_t*>(data) + pt->byte_count),
+ len - pt->byte_count
+ );
+
+ if (0 > bytes_read) {
+ pt->last_errno = errno;
+ break;
+ }
+
+ pt->byte_count += bytes_read;
+ }
+
+ PT_END(&pt->sub_pt);
+}
+
+static inline int
+write_stream_pt(struct nlpt *pt, nl::SocketWrapper* socket, const void* data, size_t len)
+{
+ const int fd = socket->get_write_fd();
+
+ PT_BEGIN(&pt->sub_pt);
+ pt->byte_count = 0;
+ pt->last_errno = 0;
+
+ while (pt->byte_count < len) {
+ ssize_t bytes_written;
+
+ // Wait for the socket to become writable...
+ _nlpt_setup_write_fd_source(pt, fd);
+ PT_WAIT_UNTIL(&pt->sub_pt, nlpt_hook_check_write_fd_source(pt, fd) || socket->can_write());
+ _nlpt_cleanup_write_fd_source(pt, fd);
+
+ // Attempt to write out what is left of the packet to the socket.
+ bytes_written = socket->write(
+ static_cast<const void*>(static_cast<const uint8_t*>(data) + pt->byte_count),
+ len - pt->byte_count
+ );
+
+ if (0 > bytes_written) {
+ pt->last_errno = errno;
+ break;
+ }
+
+ pt->byte_count += bytes_written;
+ }
+
+ PT_END(&pt->sub_pt);
+}
+
+static inline int
+write_packet_pt(struct nlpt *pt, nl::SocketWrapper* socket, const void* data, size_t len)
+{
+ const int fd = socket->get_write_fd();
+
+ PT_BEGIN(&pt->sub_pt);
+ ssize_t bytes_written;
+ pt->byte_count = 0;
+ pt->last_errno = 0;
+
+ // Wait for the socket to become writable...
+ _nlpt_setup_write_fd_source(pt, fd);
+ PT_WAIT_UNTIL(&pt->sub_pt, nlpt_hook_check_write_fd_source(pt, fd) || socket->can_write());
+ _nlpt_cleanup_write_fd_source(pt, fd);
+
+ // Write out the packet
+ bytes_written = socket->write(
+ static_cast<const void*>(static_cast<const uint8_t*>(data) + pt->byte_count),
+ len - pt->byte_count
+ );
+
+ if (0 > bytes_written) {
+ pt->last_errno = errno;
+ } else {
+ pt->byte_count += bytes_written;
+ }
+
+ PT_END(&pt->sub_pt);
+}
+
+#define NLPT_ASYNC_READ_STREAM(pt, sock, data, len) \
+ PT_SPAWN( \
+ &(pt)->pt, \
+ &(pt)->sub_pt, \
+ ::nl::read_stream_pt( \
+ (pt), \
+ (sock), \
+ static_cast<void*>(data), \
+ (len) \
+ ) \
+ )
+
+#define NLPT_ASYNC_WRITE_STREAM(pt, sock, data, len) \
+ PT_SPAWN( \
+ &(pt)->pt, \
+ &(pt)->sub_pt, \
+ ::nl::write_stream_pt( \
+ (pt), \
+ (sock), \
+ static_cast<const void*>(data), \
+ (len) \
+ ) \
+ )
+
+#define NLPT_ASYNC_WRITE_PACKET(pt, sock, data, len) \
+ PT_SPAWN( \
+ &(pt)->pt, \
+ &(pt)->sub_pt, \
+ ::nl::write_packet_pt( \
+ (pt), \
+ (sock), \
+ static_cast<const void*>(data), \
+ (len) \
+ ) \
+ )
+
+}; // namespace nl
+
+
+#endif /* defined(__wpantund__SocketAsyncOp__) */
diff --git a/src/util/SocketWrapper.cpp b/src/util/SocketWrapper.cpp
new file mode 100644
index 0000000..ec42008
--- /dev/null
+++ b/src/util/SocketWrapper.cpp
@@ -0,0 +1,111 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * This file contains the default implementations for certain members
+ * of the SocketWrapper class, which is the virtual base class for using
+ * things like TCP sockets, serial file descriptors, or even other
+ * processes.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "SocketWrapper.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <termios.h>
+#include <poll.h>
+#include <errno.h>
+#include <syslog.h>
+#include <sys/file.h>
+
+using namespace nl;
+
+SocketWrapper::~SocketWrapper()
+{
+}
+
+bool
+SocketWrapper::can_read(void)const
+{
+ return false;
+}
+
+bool
+SocketWrapper::can_write(void)const
+{
+ return false;
+}
+
+int
+SocketWrapper::set_log_level(int log_level)
+{
+ return -ENOTSUP;
+}
+
+int
+SocketWrapper::get_read_fd(void)const
+{
+ return -1;
+}
+
+int
+SocketWrapper::get_write_fd(void)const
+{
+ return -1;
+}
+
+cms_t
+SocketWrapper::get_ms_to_next_event(void)const
+{
+ return CMS_DISTANT_FUTURE;
+}
+
+void
+SocketWrapper::send_break(void)
+{
+}
+
+void
+SocketWrapper::reset(void)
+{
+}
+
+int
+SocketWrapper::hibernate(void)
+{
+ return -1;
+}
+
+bool
+SocketWrapper::did_reset(void)
+{
+ return false;
+}
+
+int
+SocketWrapper::update_fd_set(fd_set *read_fd_set, fd_set *write_fd_set, fd_set *error_fd_set, int *max_fd, cms_t *timeout)
+{
+ if (timeout != NULL) {
+ *timeout = std::min(*timeout, get_ms_to_next_event());
+ }
+ return 0;
+}
diff --git a/src/util/SocketWrapper.h b/src/util/SocketWrapper.h
new file mode 100644
index 0000000..449f934
--- /dev/null
+++ b/src/util/SocketWrapper.h
@@ -0,0 +1,70 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * This file declares the SocketWrapper class, which is the virtual
+ * base class for using things like TCP sockets, serial file descriptors,
+ * or even other processes.
+ *
+ */
+
+#ifndef __wpantund__SocketWrapper__
+#define __wpantund__SocketWrapper__
+
+#include <stdint.h>
+#include <cstring>
+#include <boost/shared_ptr.hpp>
+#include <climits>
+#include <string>
+#include <sys/select.h>
+#include "time-utils.h"
+
+namespace nl {
+
+class SocketWrapper {
+public:
+ virtual ~SocketWrapper();
+ virtual ssize_t write(const void* data, size_t len) = 0;
+ virtual ssize_t read(void* data, size_t len) = 0;
+ virtual bool can_read(void)const;
+ virtual bool can_write(void)const;
+ virtual int process(void) = 0;
+ virtual int set_log_level(int log_level);
+
+ virtual int get_read_fd(void)const;
+ virtual int get_write_fd(void)const;
+ virtual cms_t get_ms_to_next_event(void)const;
+
+ virtual void send_break(void);
+
+ virtual void reset(void);
+ virtual bool did_reset(void);
+
+ //! Any ancilary file descriptors to update. Only really needed for adapters.
+ virtual int update_fd_set(fd_set *read_fd_set, fd_set *write_fd_set, fd_set *error_fd_set, int *max_fd, cms_t *timeout);
+
+public:
+ //! Special function which closes the file descriptors. Not supported on all sockets. Call `reset()` to undo.
+ virtual int hibernate(void);
+
+}; // class SocketWrapper
+
+
+}; // namespace nl
+
+
+#endif /* defined(__wpantund__SocketWrapper__) */
diff --git a/src/util/SuperSocket.cpp b/src/util/SuperSocket.cpp
new file mode 100644
index 0000000..d4b2f82
--- /dev/null
+++ b/src/util/SuperSocket.cpp
@@ -0,0 +1,129 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * This file defindes the SuperSocket class, which provides an
+ * easy way to create various types of sockets using a convenient
+ * path syntax.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "assert-macros.h"
+
+#include "SuperSocket.h"
+#include "socket-utils.h"
+#include "time-utils.h"
+#include <stdexcept>
+#include <syslog.h>
+#include <errno.h>
+#include <unistd.h>
+#include <termios.h>
+#include <sys/file.h>
+
+using namespace nl;
+
+SuperSocket::SuperSocket(const std::string& path)
+ :UnixSocket(-1, false), mPath(path)
+{
+ int fd = open_super_socket(path.c_str());
+
+ mFDRead = mFDWrite = fd;
+
+ if (0 > fd) {
+ syslog(LOG_ERR, "Unable to open socket with path <%s>, errno=%d (%s)", path.c_str(), errno, strerror(errno));
+ throw std::runtime_error("Unable to open socket");
+ }
+
+ // Lock the file descriptor if it is to a device. It does not make sense
+ // to allow someone else to use this file descriptor at the same time,
+ // or to use the device while someone else is using it.
+ if ( (SUPER_SOCKET_TYPE_DEVICE == get_super_socket_type_from_path(path.c_str()))
+ && (flock(fd, LOCK_EX|LOCK_NB) < 0)
+ ) {
+ // The only error we care about is EWOULDBLOCK. EINVAL is fine,
+ // it just means this file descriptor doesn't support locking.
+ if (EWOULDBLOCK == errno) {
+ syslog(LOG_ERR, "Socket \"%s\" is locked by another process", path.c_str());
+ throw std::runtime_error("Socket is locked by another process");
+ }
+ }
+}
+
+SuperSocket::~SuperSocket()
+{
+ SuperSocket::hibernate();
+}
+
+boost::shared_ptr<SocketWrapper>
+SuperSocket::create(const std::string& path)
+{
+ return boost::shared_ptr<SocketWrapper>(new SuperSocket(path));
+}
+
+int
+SuperSocket::hibernate(void)
+{
+ if (mFDRead >= 0) {
+ // Unlock the FD.
+ IGNORE_RETURN_VALUE(flock(mFDRead, LOCK_UN));
+
+ // Close the existing FD.
+ IGNORE_RETURN_VALUE(close_super_socket(mFDRead));
+ }
+
+ mFDRead = -1;
+ mFDWrite = -1;
+
+ return 0;
+}
+
+void
+SuperSocket::reset()
+{
+ syslog(LOG_DEBUG, "SuperSocket::reset()");
+
+ SuperSocket::hibernate();
+
+ // Sleep for 200ms to wait for things to settle down.
+ usleep(MSEC_PER_SEC * 200);
+
+ mFDRead = mFDWrite = open_super_socket(mPath.c_str());
+
+ if (mFDRead < 0) {
+ // Unable to reopen socket...!
+ syslog(LOG_ERR, "SuperSocket::Reset: Unable to reopen socket <%s>, errno=%d (%s)", mPath.c_str(), errno, strerror(errno));
+ throw std::runtime_error("Unable to reopen socket");
+ }
+
+ // Lock the file descriptor. It does not make sense to allow someone else
+ // to use this file descriptor at the same time, or to use the device
+ // while someone else is using it.
+ if ( (SUPER_SOCKET_TYPE_DEVICE == get_super_socket_type_from_path(mPath.c_str()))
+ && (flock(mFDRead, LOCK_EX|LOCK_NB) < 0)
+ ) {
+ // The only error we care about is EWOULDBLOCK. EINVAL is fine,
+ // it just means this file descriptor doesn't support locking.
+ if (EWOULDBLOCK == errno) {
+ syslog(LOG_ERR, "Socket is locked by another process");
+ throw std::runtime_error("Socket is locked by another process");
+ }
+ }
+}
diff --git a/src/util/SuperSocket.h b/src/util/SuperSocket.h
new file mode 100644
index 0000000..078efbf
--- /dev/null
+++ b/src/util/SuperSocket.h
@@ -0,0 +1,50 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * This file declares the SuperSocket class, which provides an
+ * easy way to create various types of sockets using a convenient
+ * path syntax.
+ *
+ */
+
+#ifndef __wpantund__SuperSocket__
+#define __wpantund__SuperSocket__
+
+#include "UnixSocket.h"
+
+namespace nl {
+class SuperSocket : public UnixSocket {
+protected:
+ SuperSocket(const std::string& path);
+
+public:
+ virtual ~SuperSocket();
+
+ static boost::shared_ptr<SocketWrapper> create(const std::string& path);
+
+ virtual void reset();
+
+ virtual int hibernate(void);
+
+protected:
+ std::string mPath;
+}; // class SuperSocket
+
+}; // namespace nl
+
+#endif /* defined(__wpantund__SuperSocket__) */
diff --git a/src/util/Timer.cpp b/src/util/Timer.cpp
new file mode 100644
index 0000000..1909967
--- /dev/null
+++ b/src/util/Timer.cpp
@@ -0,0 +1,226 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * Implementation of callback timer.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "assert-macros.h"
+#include "Timer.h"
+
+using namespace nl;
+
+const Timer::Interval Timer::kOneMilliSecond = 1;
+const Timer::Interval Timer::kOneSecond = Timer::kOneMilliSecond * 1000;
+const Timer::Interval Timer::kOneMinute = Timer::kOneSecond * 60;
+const Timer::Interval Timer::kOneHour = Timer::kOneMinute * 60;
+const Timer::Interval Timer::kOneDay = Timer::kOneHour * 24;
+
+Timer *const Timer::kListEndMarker = (Timer *)(&Timer::mListHead);
+Timer *Timer::mListHead = kListEndMarker;
+
+static void
+null_timer_callback(Timer *timer)
+{
+ return;
+}
+
+Timer::Timer() :
+ mFireTime()
+{
+ mType = kOneShot;
+ mInterval = 0;
+ mNext = NULL;
+ mCallback = &null_timer_callback;
+}
+
+Timer::~Timer()
+{
+ remove(this);
+}
+
+void
+Timer::schedule(Interval interval, const Timer::Callback& callback, Type type)
+{
+ remove(this);
+
+ require_string(interval > 0, bail, "Timer::schedule() - Input interval is invalid (is 0 or negative).");
+
+ mInterval = interval;
+ mCallback = callback;
+ mType = type;
+
+ mFireTime.set(interval + time_ms());
+ add(this);
+
+bail:
+ return;
+}
+
+void
+Timer::cancel(void)
+{
+ remove(this);
+}
+
+bool
+Timer::is_expired(void) const
+{
+ return mFireTime.is_now_or_in_past();
+}
+
+Timer::Interval
+Timer::get_interval(void) const
+{
+ return mInterval;
+}
+
+Timer::Type
+Timer::get_type(void) const
+{
+ return mType;
+}
+
+void
+Timer::add(Timer *timer)
+{
+ Timer *cur;
+
+ // If the list is empty, insert the new timer as the new head of the list.
+ if (mListHead == kListEndMarker) {
+ timer->mNext = kListEndMarker;
+ mListHead = timer;
+ return;
+ }
+
+ // If the new timer fire-time is before the head timer's fire-time, insert it as the new head.
+ if (timer->mFireTime < mListHead->mFireTime) {
+ timer->mNext = mListHead;
+ mListHead = timer;
+ return;
+ }
+
+ // Go through the list and find the proper place to insert the new timer.
+ for (cur = mListHead; cur->mNext != kListEndMarker; cur = cur->mNext) {
+ if (timer->mFireTime < cur->mNext->mFireTime) {
+ // Inset the new timer in between cur and cur->next
+ timer->mNext = cur->mNext;
+ cur->mNext = timer;
+ return;
+ }
+ }
+
+ // New timer's fire-time is after all other timers in the list, so insert it at the end.
+ timer->mNext = kListEndMarker;
+ cur->mNext = timer;
+}
+
+void
+Timer::remove(Timer *timer)
+{
+ Timer *cur;
+
+ // If timer is not on the list, there is nothing to do.
+ if (timer->mNext == NULL) {
+ goto bail;
+ }
+
+ // If timer is the head of the list, remove it and update the head.
+ if (mListHead == timer) {
+ mListHead = timer->mNext;
+ timer->mNext = NULL;
+ goto bail;
+ }
+
+ // Go through the list and find the timer.
+ for (cur = mListHead; cur != kListEndMarker; cur = cur->mNext) {
+ if (cur->mNext == timer) {
+ cur->mNext = timer->mNext;
+ timer->mNext = NULL;
+ goto bail;
+ }
+ }
+
+ // We should never get here, as the timer with a non-null mNext should be on the list
+ // If we get here, assert and bail.
+ require_string(false, bail, "Timer::remove() - Timer was not found on the list.");
+
+bail:
+ return;
+}
+
+int
+Timer::process(void)
+{
+ Timer *timer;
+
+ // Process all expired timers
+ for (timer = mListHead; (timer != kListEndMarker) && timer->is_expired(); timer = mListHead) {
+ // Remove the timer from the list and update the head.
+ mListHead = timer->mNext;
+ timer->mNext = NULL;
+
+ // Restart the timer if it is periodic.
+ if (timer->mType == kPeriodicFixedRate) {
+ // For fixed-rate, restart the timer from last fire time.
+ timer->mFireTime.set(timer->mInterval + timer->mFireTime.get());
+ add(timer);
+ } else if (timer->mType == kPeriodicFixedDelay) {
+ // For fixed-delay, restart the timer from now.
+ timer->mFireTime.set(timer->mInterval + time_ms());
+ add(timer);
+ }
+
+ // Invoke the callback.
+ timer->mCallback(timer);
+ }
+
+ return 0;
+}
+
+int
+Timer::update_timeout(cms_t *timeout)
+{
+ if (timeout != NULL) {
+ cms_t cms = get_ms_to_next_event();
+
+ if (cms < *timeout) {
+ *timeout = cms;
+ }
+ }
+
+ return 0;
+}
+
+cms_t
+Timer::get_ms_to_next_event(void)
+{
+ cms_t cms = CMS_DISTANT_FUTURE;
+
+ if (mListHead != kListEndMarker) {
+ cms = mListHead->mFireTime.get_ms_till_time();
+ if (cms < 0) {
+ cms = 0;
+ }
+ }
+ return cms;
+}
diff --git a/src/util/Timer.h b/src/util/Timer.h
new file mode 100644
index 0000000..7c33096
--- /dev/null
+++ b/src/util/Timer.h
@@ -0,0 +1,128 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * This file declares a callback timer module for use in wpantund.
+ *
+ */
+
+#ifndef __wpantund__Timer__
+#define __wpantund__Timer__
+
+#include <list>
+#include <boost/function.hpp>
+
+#include "time-utils.h"
+
+namespace nl {
+
+// A callback timer class for use in wpantund.
+class Timer {
+public:
+ // Timer interval in ms - defined as int32_t --> can go up to 24.8 days
+ typedef cms_t Interval;
+
+ // A timer callback
+ typedef boost::function<void (Timer *)> Callback;
+
+ // Timer type
+ enum Type {
+ kOneShot, // One-shot timer (runs once and expires)
+ kPeriodicFixedRate, // Restart the timer from last fire time
+ kPeriodicFixedDelay // Restart the timer after processing the timer
+ };
+
+ // Time interval constants
+ static const Interval kOneMilliSecond;
+ static const Interval kOneSecond;
+ static const Interval kOneMinute;
+ static const Interval kOneHour;
+ static const Interval kOneDay;
+
+public:
+ Timer();
+ virtual ~Timer();
+
+ // Schedules the timer with given interval/period. At fire-time the given callback is invoked.
+ // Three types of timers are supported: One-shot, fixed-rate periodic, fixed-delay periodic.
+ // Timer gets started at the time of the call to schedule(). For periodic timer, the first
+ // invocation of the callback happens after the first interval/period expires.
+ // A subsequent call to schedule() will stop an already running timer and overwrite all the
+ // timer parameters (interval, callback, and its type), basically starting a new timer.
+ void schedule(Interval interval, const Callback &callback, Type type = kOneShot);
+
+ // Cancels/Stops the timer (callback will not be invoked).
+ // If timer is already expired or stopped, calling cancel() does nothing (and is ok).
+ void cancel(void);
+
+ // Returns true if the timer is expired or not running, otherwise returns false.
+ bool is_expired(void) const;
+
+ // Returns the current interval/period of the timer
+ Interval get_interval(void) const;
+
+ // Returns the type of the timer.
+ Type get_type(void) const;
+
+
+public:
+ static int process(void);
+ static int update_timeout(cms_t *timeout);
+
+private:
+ struct ClockTime {
+ public:
+ ClockTime() { mTime = 0; }
+ ClockTime(cms_t time) { mTime = time; }
+
+ void set(cms_t time) { mTime = time; }
+ cms_t get(void) { return mTime; }
+
+ bool operator<(const ClockTime& lhs) const { return (mTime - lhs.mTime) < 0; }
+ bool operator<=(const ClockTime& lhs) const { return (mTime - lhs.mTime) <= 0; }
+ bool operator==(const ClockTime &lhs) const { return (mTime == lhs.mTime); }
+
+ bool is_now_or_in_past(void) const { return (*this) <= now(); }
+ bool is_in_future(void) const { return now() < (*this); }
+
+ cms_t get_ms_till_time(void) const { return mTime - time_ms(); }
+
+ static ClockTime now(void) { return ClockTime(time_ms()); }
+
+ private:
+ cms_t mTime;
+ };
+
+ ClockTime mFireTime;
+ cms_t mInterval;
+ Callback mCallback;
+ Type mType;
+ Timer *mNext; // for linked-list
+
+private:
+ static void remove(Timer *timer); // Removes timer from linked-list
+ static void add(Timer *timer); // Adds timer to list (list sorted based on fire-time)
+
+ static cms_t get_ms_to_next_event(void);
+
+ static Timer * mListHead; // Head of the LinkedList
+ static Timer * const kListEndMarker; // Marker for end of list
+};
+
+}; // namespace nl
+
+#endif // ifndef __wpantund__Timer__
diff --git a/src/util/TunnelIPv6Interface.cpp b/src/util/TunnelIPv6Interface.cpp
new file mode 100644
index 0000000..d74a8a3
--- /dev/null
+++ b/src/util/TunnelIPv6Interface.cpp
@@ -0,0 +1,421 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * This file contains the implementation for a C++ wrapper around the
+ * `tunnel.c`/`tunnel.h` interface.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "assert-macros.h"
+#include "TunnelIPv6Interface.h"
+#include <syslog.h>
+#include "IPv6Helpers.h"
+
+#if __linux__
+#include <asm/types.h>
+#include <linux/if_link.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <fcntl.h>
+#endif
+
+#include <sys/select.h>
+
+#ifndef O_NONBLOCK
+#define O_NONBLOCK O_NDELAY
+#endif
+
+TunnelIPv6Interface::TunnelIPv6Interface(const std::string& interface_name, int mtu):
+ UnixSocket(tunnel_open(interface_name.c_str()), true),
+ mInterfaceName(interface_name),
+ mLastError(0),
+ mNetlinkFD(-1)
+{
+ if (0 > mFDRead) {
+ throw std::invalid_argument("Unable to open tunnel interface");
+ }
+
+ {
+ char ActualInterfaceName[TUNNEL_MAX_INTERFACE_NAME_LEN] = "";
+ int ret = 0;
+ ret = tunnel_get_name(mFDRead, ActualInterfaceName, sizeof(ActualInterfaceName));
+ if (ret) {
+ syslog(LOG_WARNING,
+ "TunnelIPv6Interface: Couldn't get tunnel name! errno=%d, %s",
+ errno,
+ strerror(errno));
+ } else if (mInterfaceName != ActualInterfaceName) {
+ syslog(LOG_WARNING,
+ "TunnelIPv6Interface: Couldn't create tunnel named \"%s\", got \"%s\" instead!",
+ mInterfaceName.c_str(),
+ ActualInterfaceName);
+ mInterfaceName = ActualInterfaceName;
+ }
+ }
+
+ tunnel_set_mtu(mFDRead, mtu);
+
+ setup_signals();
+}
+
+TunnelIPv6Interface::~TunnelIPv6Interface()
+{
+ close(mNetlinkFD);
+}
+
+#if __linux__ // --------------------------------------------------------------
+
+#define LCG32(x) ((uint32_t)(x)*1664525+1013904223)
+
+void
+TunnelIPv6Interface::setup_signals()
+{
+ int status;
+ int fd;
+ struct sockaddr_nl la;
+
+ fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
+
+ require(fd != -1, bail);
+
+ memset(&la, 0, sizeof(la));
+ la.nl_family = AF_NETLINK;
+ la.nl_pad = 0;
+ la.nl_groups = RTMGRP_LINK | RTMGRP_IPV6_IFADDR;
+
+ // We calculate the PID in a pseudo-random way based on the
+ // address pointer and the actual process ID.
+ la.nl_pid = LCG32(getpid()) ^ LCG32((uint32_t)reinterpret_cast<uintptr_t>(this));
+
+ status = bind(fd, (struct sockaddr*) &la, sizeof(la));
+
+ require(status != -1, bail);
+
+ // Success!
+ IGNORE_RETURN_VALUE(fcntl(fd, F_SETFL, O_NONBLOCK));
+
+ mNetlinkFD = fd;
+ fd = -1;
+
+bail:
+
+ // Cleanup (If necessary)
+ if (fd > 0) {
+ close(fd);
+ }
+
+ return;
+}
+
+int
+TunnelIPv6Interface::process(void)
+{
+ uint8_t buffer[1024];
+ ssize_t buffer_len(-1);
+
+ if (mNetlinkFD >= 0) {
+ buffer_len = recv(mNetlinkFD, buffer, sizeof(buffer), 0);
+ }
+
+ if (buffer_len > 0) {
+ struct nlmsghdr *nlp;
+ struct rtmsg *rtp;
+ int rta_len;
+ struct rtattr *rta;
+
+ nlp = (struct nlmsghdr *)buffer;
+ for (;NLMSG_OK(nlp, buffer_len); nlp=NLMSG_NEXT(nlp, buffer_len))
+ {
+ if (nlp->nlmsg_type == RTM_NEWADDR || nlp->nlmsg_type == RTM_DELADDR) {
+ struct ifaddrmsg *ifaddr = (struct ifaddrmsg *)NLMSG_DATA(nlp);
+ char ifnamebuf[IF_NAMESIZE];
+ const char *ifname = if_indextoname(ifaddr->ifa_index, ifnamebuf);
+ struct in6_addr addr;
+
+ if ((ifname == NULL) || (get_interface_name() != ifname)) {
+ continue;
+ }
+
+ // get RTNETLINK message header
+ // get start of attributes
+ rta = (struct rtattr *) IFA_RTA(ifaddr);
+
+ // get length of attributes
+ rta_len = IFA_PAYLOAD(nlp);
+
+ for(;RTA_OK(rta, rta_len); rta = RTA_NEXT(rta, rta_len)) {
+ switch(rta->rta_type) {
+ case IFA_ADDRESS:
+ case IFA_LOCAL:
+ case IFA_BROADCAST:
+ case IFA_ANYCAST:
+ memcpy(addr.s6_addr, RTA_DATA(rta), sizeof(addr));
+
+ if (nlp->nlmsg_type == RTM_NEWADDR) {
+ mAddressWasAdded(addr, ifaddr->ifa_prefixlen);
+ } else if (nlp->nlmsg_type == RTM_DELADDR) {
+ mAddressWasRemoved(addr, ifaddr->ifa_prefixlen);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return nl::UnixSocket::process();
+}
+
+#else // ----------------------------------------------------------------------
+
+void
+TunnelIPv6Interface::setup_signals()
+{
+ // Unknown platform.
+}
+
+int
+TunnelIPv6Interface::process(void)
+{
+ return nl::UnixSocket::process();
+}
+
+#endif // ---------------------------------------------------------------------
+
+int
+TunnelIPv6Interface::update_fd_set(fd_set *read_fd_set, fd_set *write_fd_set, fd_set *error_fd_set, int *max_fd, cms_t *timeout)
+{
+ if (read_fd_set && (mNetlinkFD >= 0)) {
+ FD_SET(mNetlinkFD, read_fd_set);
+
+ if ((max_fd != NULL)) {
+ *max_fd = std::max(*max_fd, mNetlinkFD);
+ }
+ }
+
+ return nl::UnixSocket::update_fd_set(read_fd_set, write_fd_set, error_fd_set, max_fd, timeout);
+}
+
+const std::string&
+TunnelIPv6Interface::get_interface_name(void)
+{
+ return mInterfaceName;
+}
+
+int
+TunnelIPv6Interface::get_last_error(void)
+{
+ return mLastError;
+}
+
+bool
+TunnelIPv6Interface::is_online(void)
+{
+ return tunnel_is_online(mFDRead);
+}
+
+int
+TunnelIPv6Interface::set_online(bool online)
+{
+ int ret = 0;
+
+ if (online) {
+ syslog(LOG_INFO, "Bringing interface %s online. . .", mInterfaceName.c_str());
+
+ require_action((ret = tunnel_bring_online(mFDRead)) == 0, bail, mLastError = errno);
+ require_action(tunnel_is_online(mFDRead), bail, mLastError = errno);
+
+ require_action_string(tunnel_is_online(mFDRead), bail, mLastError = errno, "Tunnel went offline unexpectedly!");
+
+ std::set<struct in6_addr>::const_iterator iter;
+ for (iter = mAddresses.begin(); iter != mAddresses.end(); ++iter) {
+ (void)tunnel_add_address(mFDRead, iter->s6_addr, 64);
+ }
+ } else {
+ syslog(LOG_INFO, "Taking interface %s offline. . .", mInterfaceName.c_str());
+
+ require_action((ret = tunnel_bring_offline(mFDRead)) == 0, bail, mLastError = errno);
+ }
+
+bail:
+ return ret;
+}
+
+void
+TunnelIPv6Interface::reset(void)
+{
+ syslog(LOG_INFO, "Resetting interface %s. . .", mInterfaceName.c_str());
+
+ while (!mAddresses.empty()) {
+ const struct in6_addr addr(*mAddresses.begin());
+ remove_address(&addr);
+ }
+
+ set_online(false);
+}
+
+
+bool
+TunnelIPv6Interface::add_address(const struct in6_addr *addr, int prefixlen)
+{
+ bool ret = false;
+
+ require_action(!IN6_IS_ADDR_UNSPECIFIED(addr), bail, mLastError = EINVAL);
+
+ if (!mAddresses.count(*addr)) {
+ syslog(
+ LOG_INFO,
+ "TunnelIPv6Interface: Adding address \"%s\" to interface \"%s\".",
+ in6_addr_to_string(*addr).c_str(),
+ mInterfaceName.c_str()
+ );
+
+ mAddresses.insert(*addr);
+
+ if (is_online()) {
+ require_noerr_action(tunnel_add_address(mFDRead, addr->s6_addr, prefixlen), bail, mLastError = errno);
+ }
+ }
+
+
+ ret = true;
+
+bail:
+ return ret;
+
+}
+
+
+bool
+TunnelIPv6Interface::remove_address(const struct in6_addr *addr, int prefixlen)
+{
+ bool ret = false;
+
+ require_action(!IN6_IS_ADDR_UNSPECIFIED(addr), bail, mLastError = EINVAL);
+
+ syslog(
+ LOG_INFO,
+ "TunnelIPv6Interface: Removing address \"%s\" from interface \"%s\".",
+ in6_addr_to_string(*addr).c_str(),
+ mInterfaceName.c_str()
+ );
+
+ mAddresses.erase(*addr);
+
+ if (tunnel_remove_address(mFDRead, addr->s6_addr) != 0) {
+ mLastError = errno;
+ goto bail;
+ }
+
+ ret = true;
+
+bail:
+ return ret;
+
+}
+
+bool
+TunnelIPv6Interface::add_route(const struct in6_addr *route, int prefixlen)
+{
+ bool ret = false;
+
+ syslog(
+ LOG_INFO,
+ "TunnelIPv6Interface: Adding route prefix \"%s/%d\" -> \"%s\".",
+ in6_addr_to_string(*route).c_str(),
+ prefixlen,
+ mInterfaceName.c_str()
+ );
+
+ if (is_online()) {
+ require_noerr_action(tunnel_add_route(mFDRead, route->s6_addr, prefixlen), bail, mLastError = errno);
+ }
+
+ ret = true;
+
+bail:
+ return ret;
+}
+
+bool
+TunnelIPv6Interface::remove_route(const struct in6_addr *route, int prefixlen)
+{
+ bool ret = false;
+
+ syslog(
+ LOG_INFO,
+ "TunnelIPv6Interface: Removing route prefix \"%s/%d\" -> \"%s\".",
+ in6_addr_to_string(*route).c_str(),
+ prefixlen,
+ mInterfaceName.c_str()
+ );
+
+ if (is_online()) {
+ require_noerr_action(tunnel_remove_route(mFDRead, route->s6_addr, prefixlen), bail, mLastError = errno);
+ }
+
+ ret = true;
+
+bail:
+ return ret;
+}
+
+ssize_t
+TunnelIPv6Interface::read(void* data, size_t len)
+{
+ ssize_t ret = nl::UnixSocket::read(data, len);
+ uint8_t *data_bytes = static_cast<uint8_t*>(data);
+
+ // Remove any subheader, if present.
+ if ((ret >= 4) && (data_bytes[0] == 0) && (data_bytes[1] == 0)) {
+ ret -= 4;
+ memmove(data, static_cast<const void*>(data_bytes + 4), ret);
+ }
+
+ return ret;
+}
+
+ssize_t
+TunnelIPv6Interface::write(const void* data, size_t len)
+{
+#ifdef __APPLE__
+ const uint8_t* const data_bytes = static_cast<const uint8_t*>(data);
+
+ if ((data_bytes[0] != 0) || (data_bytes[0] != 0)) {
+ // The utun interface on OS X needs this header.
+ // Linux seems to be able to infer the type of the packet
+ // with no problems.
+ uint8_t packet[len + 4];
+ packet[0] = 0;
+ packet[1] = 0;
+ packet[2] = (PF_INET6 << 8) & 0xFF;
+ packet[3] = (PF_INET6 << 0) & 0xFF;
+ memcpy(static_cast<void*>(packet + 4), data, len);
+ ssize_t ret = nl::UnixSocket::write(packet, len + 4);
+ return (ret >= 4)?(ret - 4):(-1);
+ }
+#endif
+ return nl::UnixSocket::write(data, len);
+}
diff --git a/src/util/TunnelIPv6Interface.h b/src/util/TunnelIPv6Interface.h
new file mode 100644
index 0000000..5b87715
--- /dev/null
+++ b/src/util/TunnelIPv6Interface.h
@@ -0,0 +1,86 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * This file contains the interface for a C++ wrapper around the
+ * `tunnel.c`/`tunnel.h` interface.
+ *
+ */
+
+#ifndef __wpantund__TunnelInterface__
+#define __wpantund__TunnelInterface__
+
+#include "tunnel.h"
+#include <cstdio>
+#include <string>
+#include <errno.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include "UnixSocket.h"
+#include <set>
+#include "IPv6Helpers.h"
+#include <boost/signals2/signal.hpp>
+
+class TunnelIPv6Interface : public nl::UnixSocket
+{
+
+public:
+ TunnelIPv6Interface(const std::string& interface_name = "", int mtu = 1280);
+
+ virtual ~TunnelIPv6Interface();
+
+ const std::string& get_interface_name(void);
+
+ int get_last_error(void);
+
+ bool is_online(void);
+ int set_online(bool isOnline);
+
+
+
+ const struct in6_addr& get_realm_local_address()const;
+
+ bool add_address(const struct in6_addr *addr, int prefixlen = 64);
+ bool remove_address(const struct in6_addr *addr, int prefixlen = 64);
+
+ bool add_route(const struct in6_addr *route, int prefixlen = 64);
+ bool remove_route(const struct in6_addr *route, int prefixlen = 64);
+
+ virtual void reset();
+ virtual ssize_t write(const void* data, size_t len);
+ virtual ssize_t read(void* data, size_t len);
+
+ virtual int process(void);
+ virtual int update_fd_set(fd_set *read_fd_set, fd_set *write_fd_set, fd_set *error_fd_set, int *max_fd, cms_t *timeout);
+
+public: // Signals
+
+ boost::signals2::signal<void(const struct in6_addr&, int)> mAddressWasAdded;
+ boost::signals2::signal<void(const struct in6_addr&, int)> mAddressWasRemoved;
+
+private:
+ void setup_signals();
+
+private:
+ std::string mInterfaceName;
+ int mLastError;
+
+ int mNetlinkFD;
+
+ std::set<struct in6_addr> mAddresses;
+};
+#endif /* defined(__wpantund__TunnelInterface__) */
diff --git a/src/util/UnixSocket.cpp b/src/util/UnixSocket.cpp
new file mode 100644
index 0000000..bfd27ea
--- /dev/null
+++ b/src/util/UnixSocket.cpp
@@ -0,0 +1,187 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "UnixSocket.h"
+#include <errno.h>
+#include "socket-utils.h"
+#include <termios.h>
+#include <sys/file.h>
+#include <syslog.h>
+#include <poll.h>
+
+using namespace nl;
+
+#define SOCKET_DEBUG_BYTES_PER_LINE 16
+
+UnixSocket::UnixSocket(int rfd, int wfd, bool should_close)
+ :mShouldClose(should_close), mFDRead(rfd), mFDWrite(wfd), mLogLevel(-1)
+{
+}
+
+UnixSocket::UnixSocket(int fd, bool should_close)
+ :mShouldClose(should_close), mFDRead(fd), mFDWrite(fd), mLogLevel(-1)
+{
+}
+
+UnixSocket::~UnixSocket()
+{
+ if (mShouldClose) {
+ close(mFDRead);
+
+ if(mFDWrite != mFDRead) {
+ close(mFDWrite);
+ }
+ }
+}
+
+boost::shared_ptr<SocketWrapper>
+UnixSocket::create(int rfd, int wfd, bool should_close)
+{
+ return boost::shared_ptr<SocketWrapper>(new UnixSocket(rfd,wfd,should_close));
+}
+
+boost::shared_ptr<SocketWrapper>
+UnixSocket::create(int fd, bool should_close)
+{
+ return UnixSocket::create(fd, fd, should_close);
+}
+
+ssize_t
+UnixSocket::write(const void* data, size_t len)
+{
+ ssize_t ret = ::write(mFDWrite, data, len);
+ if(ret<0) {
+ ret = -errno;
+ } else if(ret == 0) {
+ ret = fd_has_error(mFDWrite);
+#if DEBUG
+ } else if (mLogLevel != -1) {
+ const uint8_t* byte = (uint8_t*)data;
+ ssize_t i = 0;
+
+ while(i<ret) {
+ ssize_t j = 0;
+ char dump_string[SOCKET_DEBUG_BYTES_PER_LINE*3+1];
+
+ for (j = 0;i<ret && j<SOCKET_DEBUG_BYTES_PER_LINE;i++,j++) {
+ sprintf(dump_string+j*3, "%02X ", byte[i]);
+ }
+
+ syslog(mLogLevel, "UnixSocket: %3d Byte(s) sent to FD%d: %s%s", (int)j, mFDWrite, dump_string, (i<ret)?" ...":"");
+ }
+#endif
+ }
+ return ret;
+}
+
+ssize_t
+UnixSocket::read(void* data, size_t len)
+{
+ ssize_t ret = ::read(mFDRead, data, len);
+ if(ret<0) {
+ if(EAGAIN == errno) {
+ ret = 0;
+ } else {
+ ret = -errno;
+ }
+#if DEBUG
+ } else if ((ret > 0) && (mLogLevel != -1)) {
+ const uint8_t* byte = (uint8_t*)data;
+ ssize_t i = 0;
+
+ while(i<ret) {
+ ssize_t j = 0;
+ char dump_string[SOCKET_DEBUG_BYTES_PER_LINE*3+1];
+
+ for (j = 0;i<ret && j<SOCKET_DEBUG_BYTES_PER_LINE;i++,j++) {
+ sprintf(dump_string+j*3, "%02X ", byte[i]);
+ }
+
+ syslog(mLogLevel, "UnixSocket: %3d Byte(s) read from FD%d: %s%s", (int)j, mFDWrite, dump_string, (i<ret)?" ...":"");
+ }
+#endif
+ }
+
+ if(ret==0) {
+ ret = fd_has_error(mFDRead);
+ }
+
+ return ret;
+}
+
+bool
+UnixSocket::can_read(void)const
+{
+ bool ret = false;
+ const int flags = POLLRDNORM|POLLERR|POLLNVAL|POLLHUP;
+ struct pollfd pollfd = { mFDRead, flags, 0 };
+ int count = poll(&pollfd, 1, 0);
+ ret = (count>0) && ((pollfd.revents & flags) != 0);
+ return ret;
+}
+
+bool
+UnixSocket::can_write(void)const
+{
+ const int flags = POLLOUT|POLLERR|POLLNVAL|POLLHUP;
+ struct pollfd pollfd = { mFDWrite, flags, 0 };
+
+ return (poll(&pollfd, 1, 0)>0) && ((pollfd.revents & flags) != 0);
+}
+
+void
+UnixSocket::send_break()
+{
+ if (isatty(mFDWrite)) {
+#if DEBUG
+ syslog(mLogLevel, "UnixSocket: Sending BREAK");
+#endif
+ tcsendbreak(mFDWrite, 0);
+ }
+};
+
+int
+UnixSocket::get_read_fd(void)const
+{
+ return mFDRead;
+}
+
+int
+UnixSocket::get_write_fd(void)const
+{
+ return mFDWrite;
+}
+
+int
+UnixSocket::process(void)
+{
+ return 0;
+}
+
+int
+UnixSocket::set_log_level(int log_level)
+{
+ mLogLevel = log_level;
+
+ return 0;
+}
diff --git a/src/util/UnixSocket.h b/src/util/UnixSocket.h
new file mode 100644
index 0000000..9ab990e
--- /dev/null
+++ b/src/util/UnixSocket.h
@@ -0,0 +1,56 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __wpantund__UnixSocket__
+#define __wpantund__UnixSocket__
+
+#include "SocketWrapper.h"
+#include <stdio.h>
+#include <unistd.h>
+
+namespace nl {
+class UnixSocket : public SocketWrapper {
+protected:
+ UnixSocket(int rfd, int wfd, bool should_close);
+ UnixSocket(int fd, bool should_close);
+
+public:
+ static boost::shared_ptr<SocketWrapper> create(int fd, bool should_close = false);
+ static boost::shared_ptr<SocketWrapper> create(int rfd, int wfd, bool should_close = false);
+ virtual ~UnixSocket();
+ virtual ssize_t write(const void* data, size_t len);
+ virtual ssize_t read(void* data, size_t len);
+ virtual bool can_read(void)const;
+ virtual bool can_write(void)const;
+ virtual int get_read_fd(void)const;
+ virtual int get_write_fd(void)const;
+ virtual int process(void);
+ virtual void send_break();
+ virtual int set_log_level(int log_level);
+
+protected:
+ bool mShouldClose;
+ int mFDRead;
+ int mFDWrite;
+ int mLogLevel;
+}; // class UnixSocket
+
+}; // namespace nl
+
+#endif /* defined(__wpantund__UnixSocket__) */
diff --git a/src/util/ValueMap.cpp b/src/util/ValueMap.cpp
new file mode 100644
index 0000000..923ffe9
--- /dev/null
+++ b/src/util/ValueMap.cpp
@@ -0,0 +1,42 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * ValueMap is a dictionary-like key-value store
+ *
+ */
+
+#include "ValueMap.h"
+
+nl::ValueMap
+nl::ValueMapWithKeysAndValues(const char* key, ...)
+{
+ ValueMap ret;
+ va_list args;
+ va_start(args, key);
+ while (key != NULL) {
+ boost::any* value = va_arg(args, boost::any*);
+ if (value == NULL) {
+ ret[key] = boost::any();
+ } else {
+ ret[key] = *value;
+ }
+ key = va_arg(args, const char*);
+ }
+ va_end(args);
+ return ret;
+}
diff --git a/src/util/ValueMap.h b/src/util/ValueMap.h
new file mode 100644
index 0000000..135ede5
--- /dev/null
+++ b/src/util/ValueMap.h
@@ -0,0 +1,39 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * ValueMap is a dictionary-like key-value store
+ *
+ */
+
+#ifndef wpantund_ValueMap_h
+#define wpantund_ValueMap_h
+
+#include <boost/any.hpp>
+#include <cstdarg>
+#include <map>
+#include <string>
+
+namespace nl {
+
+typedef std::map<std::string, boost::any> ValueMap;
+
+extern ValueMap ValueMapWithKeysAndValues(const char* key, ...);
+
+}; // namespace nl
+
+#endif
diff --git a/src/util/any-to.cpp b/src/util/any-to.cpp
new file mode 100644
index 0000000..6e6e77d
--- /dev/null
+++ b/src/util/any-to.cpp
@@ -0,0 +1,322 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * Implementation of utility functions related to boost::any.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdint.h>
+#include "any-to.h"
+#include <exception>
+#include <stdexcept>
+#include <ctype.h>
+#include <list>
+#include "string-utils.h"
+
+using namespace nl;
+
+nl::Data any_to_data(const boost::any& value)
+{
+ nl::Data ret;
+
+ if (value.type() == typeid(std::string)) {
+ std::string key_string = boost::any_cast<std::string>(value);
+ uint8_t data[key_string.size()/2];
+
+ int length = parse_string_into_data(data,
+ key_string.size()/2,
+ key_string.c_str());
+
+ ret = nl::Data(data, length);
+ } else if (value.type() == typeid(nl::Data)) {
+ ret = boost::any_cast<nl::Data>(value);
+ } else if (value.type() == typeid(uint64_t)) {
+ union {
+ uint64_t val;
+ uint8_t data[sizeof(uint64_t)];
+ } x;
+
+ x.val = boost::any_cast<uint64_t>(value);
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ reverse_bytes(x.data, sizeof(uint64_t));
+#endif
+
+ ret.append(x.data,sizeof(uint64_t));
+ } else {
+ ret = nl::Data(boost::any_cast<std::vector<uint8_t> >(value));
+ }
+ return ret;
+}
+
+int any_to_int(const boost::any& value)
+{
+ int32_t ret = 0;
+
+ if (value.type() == typeid(std::string)) {
+ std::string key_string = boost::any_cast<std::string>(value);
+ ret = (int)strtol(key_string.c_str(), NULL, 0);
+ } else if (value.type() == typeid(uint8_t)) {
+ ret = boost::any_cast<uint8_t>(value);
+ } else if (value.type() == typeid(int8_t)) {
+ ret = boost::any_cast<int8_t>(value);
+ } else if (value.type() == typeid(uint16_t)) {
+ ret = boost::any_cast<uint16_t>(value);
+ } else if (value.type() == typeid(int16_t)) {
+ ret = boost::any_cast<int16_t>(value);
+ } else if (value.type() == typeid(uint32_t)) {
+ ret = boost::any_cast<uint32_t>(value);
+ } else if (value.type() == typeid(int32_t)) {
+ ret = boost::any_cast<int32_t>(value);
+ } else if (value.type() == typeid(bool)) {
+ ret = boost::any_cast<bool>(value);
+ } else if (value.type() == typeid(unsigned int)) {
+ ret = boost::any_cast<unsigned int>(value);
+ } else {
+ ret = boost::any_cast<int>(value);
+ }
+ return ret;
+}
+
+struct in6_addr
+any_to_ipv6(const boost::any& value)
+{
+ struct in6_addr ret = {};
+
+ if (value.type() == typeid(std::string)) {
+ std::string str(boost::any_cast<std::string>(value));
+ size_t lastchar(str.find_first_not_of("0123456789abcdefABCDEF:."));
+ int bytes;
+
+ if (lastchar != std::string::npos) {
+ str.erase(str.begin() + lastchar, str.end());
+ }
+
+ bytes = inet_pton(
+ AF_INET6,
+ str.c_str(),
+ ret.s6_addr
+ );
+ if (bytes <= 0) {
+ throw std::invalid_argument("String not IPv6 address");
+ }
+ } else if (value.type() == typeid(nl::Data)) {
+ nl::Data data(boost::any_cast<nl::Data>(value));
+ if (data.size() <= sizeof(ret)) {
+ memcpy(ret.s6_addr, data.data(), data.size());
+ }
+ } else {
+ ret = boost::any_cast<struct in6_addr>(value);
+ }
+
+ return ret;
+}
+
+uint64_t
+any_to_uint64(const boost::any& value)
+{
+ uint64_t ret(0);
+
+ if (value.type() == typeid(std::string)) {
+ const std::string& key_string = boost::any_cast<std::string>(value);
+
+ if (key_string.size() != 16) {
+ throw std::invalid_argument("String not 16 characters long");
+ }
+
+ ret = static_cast<uint64_t>(strtoull(key_string.c_str(), NULL, 16));
+
+ } else if (value.type() == typeid(nl::Data)) {
+ const nl::Data& data = boost::any_cast<nl::Data>(value);
+ union {
+ uint64_t val;
+ uint8_t data[sizeof(uint64_t)];
+ } x;
+
+ if (data.size() != sizeof(uint64_t)) {
+ throw std::invalid_argument("Data not 8 bytes long");
+ }
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ memcpyrev(x.data, data.data(), sizeof(uint64_t));
+#else
+ memcpy(x.data, data.data(), sizeof(uint64_t));
+#endif
+
+ ret = x.val;
+
+ } else {
+ ret = boost::any_cast<uint64_t>(value);
+ }
+
+
+ return ret;
+}
+
+bool any_to_bool(const boost::any& value)
+{
+ bool ret = 0;
+
+ if (value.type() == typeid(std::string)) {
+ std::string key_string = boost::any_cast<std::string>(value);
+ if (key_string=="true" || key_string=="yes" || key_string=="1" || key_string == "TRUE" || key_string == "YES")
+ ret = true;
+ else if (key_string=="false" || key_string=="no" || key_string=="0" || key_string == "FALSE" || key_string == "NO")
+ ret = false;
+ else
+ ret = (bool)strtol(key_string.c_str(), NULL, 0);
+ } else if (value.type() == typeid(bool)) {
+ ret = boost::any_cast<bool>(value);
+ } else {
+ ret = any_to_int(value) != 0;
+ }
+ return ret;
+}
+
+std::string any_to_string(const boost::any& value)
+{
+ std::string ret;
+
+ if (value.type() == typeid(std::string)) {
+ ret = boost::any_cast<std::string>(value);
+ } else if (value.type() == typeid(uint8_t)) {
+ char tmp[10];
+ snprintf(tmp, sizeof(tmp), "%u", boost::any_cast<uint8_t>(value));
+ ret = tmp;
+ } else if (value.type() == typeid(int8_t)) {
+ char tmp[10];
+ snprintf(tmp, sizeof(tmp), "%d", boost::any_cast<int8_t>(value));
+ ret = tmp;
+ } else if (value.type() == typeid(uint16_t)) {
+ char tmp[10];
+ snprintf(tmp, sizeof(tmp), "%u", boost::any_cast<uint16_t>(value));
+ ret = tmp;
+ } else if (value.type() == typeid(int16_t)) {
+ char tmp[10];
+ snprintf(tmp, sizeof(tmp), "%d", boost::any_cast<int16_t>(value));
+ ret = tmp;
+ } else if (value.type() == typeid(uint32_t)) {
+ char tmp[10];
+ snprintf(tmp, sizeof(tmp), "%u", (unsigned int)boost::any_cast<uint32_t>(value));
+ ret = tmp;
+ } else if (value.type() == typeid(int32_t)) {
+ char tmp[10];
+ snprintf(tmp, sizeof(tmp), "%d", (int)boost::any_cast<int32_t>(value));
+ ret = tmp;
+ } else if (value.type() == typeid(uint64_t)) {
+ char tmp[20];
+ uint64_t u64_val = boost::any_cast<uint64_t>(value);
+ snprintf(tmp,
+ sizeof(tmp),
+ "%08x%08x",
+ static_cast<uint32_t>(u64_val >> 32),
+ static_cast<uint32_t>(u64_val & 0xFFFFFFFF));
+ ret = tmp;
+ } else if (value.type() == typeid(unsigned int)) {
+ char tmp[10];
+ snprintf(tmp, sizeof(tmp), "%u", boost::any_cast<unsigned int>(value));
+ ret = tmp;
+ } else if (value.type() == typeid(int)) {
+ char tmp[10];
+ snprintf(tmp, sizeof(tmp), "%d", boost::any_cast<int>(value));
+ ret = tmp;
+ } else if (value.type() == typeid(bool)) {
+ ret = (boost::any_cast<bool>(value))? "true" : "false";
+ } else if (value.type() == typeid(nl::Data)) {
+ nl::Data data = boost::any_cast<nl::Data>(value);
+ ret = std::string(data.size()*2,0);
+
+ // Reserve the zero termination
+ ret.reserve(data.size()*2+1);
+
+ encode_data_into_string(data.data(),
+ data.size(),
+ &ret[0],
+ ret.capacity(),
+ 0);
+ } else if (value.type() == typeid(std::list<std::string>)) {
+ std::list<std::string> l = boost::any_cast<std::list<std::string> >(value);
+ if (!l.empty()) {
+ std::list<std::string>::const_iterator iter;
+ ret = "{\n";
+ for (iter = l.begin(); iter != l.end(); ++iter) {
+ ret += "\t\"" + *iter + "\"\n";
+ }
+ ret += "}";
+ } else {
+ ret = "{ }";
+ }
+ } else {
+ ret += "<";
+ ret += value.type().name();
+ ret += ">";
+ }
+ return ret;
+}
+
+std::set<int>
+any_to_int_set(const boost::any& value)
+{
+ std::set<int> ret;
+
+ if (value.type() == typeid(std::string)) {
+ std::string key_string = boost::any_cast<std::string>(value);
+ if (key_string.empty()) {
+ // Empty set. Do nothing.
+ } else if (key_string.find(',') != std::string::npos) {
+ // List of values. Not yet supported.
+ throw std::invalid_argument("integer mask string format not yet implemented");
+ } else if (isdigit(key_string[0])) {
+ // Special case, only one value.
+ ret.insert((int)strtol(key_string.c_str(), NULL, 0));
+ } else {
+ throw std::invalid_argument(key_string);
+ }
+ } else if (value.type() == typeid(uint8_t)) {
+ ret.insert(boost::any_cast<uint8_t>(value));
+ } else if (value.type() == typeid(int8_t)) {
+ ret.insert(boost::any_cast<int8_t>(value));
+ } else if (value.type() == typeid(uint16_t)) {
+ ret.insert(boost::any_cast<uint16_t>(value));
+ } else if (value.type() == typeid(int16_t)) {
+ ret.insert(boost::any_cast<int16_t>(value));
+ } else if (value.type() == typeid(uint32_t)) {
+ ret.insert(boost::any_cast<uint32_t>(value));
+ } else if (value.type() == typeid(int32_t)) {
+ ret.insert(boost::any_cast<int32_t>(value));
+ } else if (value.type() == typeid(bool)) {
+ ret.insert(boost::any_cast<bool>(value));
+ } else if (value.type() == typeid(std::list<int>)) {
+ std::list<int> number_list(boost::any_cast< std::list<int> >(value));
+ ret.insert(number_list.begin(), number_list.end());
+ } else if (value.type() == typeid(std::list<boost::any>)) {
+ std::list<boost::any> any_list(boost::any_cast< std::list<boost::any> >(value));
+ std::list<boost::any>::const_iterator iter;
+ for(iter = any_list.begin(); iter != any_list.end(); ++iter) {
+ ret.insert(any_to_int(*iter));
+ }
+ } else {
+ ret = boost::any_cast< std::set<int> >(value);
+ }
+ return ret;
+}
diff --git a/src/util/any-to.h b/src/util/any-to.h
new file mode 100644
index 0000000..19e7936
--- /dev/null
+++ b/src/util/any-to.h
@@ -0,0 +1,39 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * Declaration of utility functions related to boost::any.
+ *
+ */
+
+#ifndef wpantund_any_to_h
+#define wpantund_any_to_h
+
+#include <string>
+#include <boost/any.hpp>
+#include "Data.h"
+#include <set>
+#include <arpa/inet.h>
+
+extern nl::Data any_to_data(const boost::any& value);
+extern int any_to_int(const boost::any& value);
+extern uint64_t any_to_uint64(const boost::any& value);
+extern struct in6_addr any_to_ipv6(const boost::any& value);
+extern bool any_to_bool(const boost::any& value);
+extern std::string any_to_string(const boost::any& value);
+extern std::set<int> any_to_int_set(const boost::any& value);
+#endif
diff --git a/src/util/args.h b/src/util/args.h
new file mode 100644
index 0000000..e606f5b
--- /dev/null
+++ b/src/util/args.h
@@ -0,0 +1,74 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef UTIL_ARGS_HEADER_INCLUDED
+#define UTIL_ARGS_HEADER_INCLUDED 1
+
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+
+typedef struct {
+ char shortarg;
+ const char* longarg;
+ const char* param;
+ const char* desc;
+} arg_list_item_t;
+
+static inline void
+print_arg_list_help(
+ const arg_list_item_t arg_list[],
+ const char* command_name,
+ const char* syntax
+ )
+{
+ int i;
+
+ printf("Syntax:\n");
+ printf(" %s %s\n", command_name, syntax);
+ printf("Options:\n");
+ for (i = 0; arg_list[i].desc; ++i) {
+ if (arg_list[i].shortarg)
+ printf(" -%c", arg_list[i].shortarg);
+ else
+ printf(" ");
+
+ if (arg_list[i].longarg) {
+ if (arg_list[i].shortarg)
+ printf("/");
+ else
+ printf(" ");
+
+ printf("--%s%s",
+ arg_list[i].longarg,
+ &" "[strlen(arg_list[i].longarg)]);
+ } else {
+ printf(" ");
+ }
+
+ if (arg_list[i].param != NULL) {
+ printf(" %s [%s]\n", arg_list[i].desc, arg_list[i].param);
+ } else {
+ printf(" %s\n", arg_list[i].desc);
+ }
+
+ }
+}
+
+#endif // UTIL_ARGS_HEADER_INCLUDED
diff --git a/src/util/config-file.c b/src/util/config-file.c
new file mode 100644
index 0000000..7dc24e2
--- /dev/null
+++ b/src/util/config-file.c
@@ -0,0 +1,142 @@
+/*
+ *
+ * Copyright (c) 2010-2012 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * This document is the property of Nest. It is considered
+ * confidential and proprietary information.
+ *
+ * This document may not be reproduced or transmitted in any form,
+ * in whole or in part, without the express written permission of
+ * Nest.
+ *
+ * Description:
+ * This file implements a configuration file parser.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef ASSERT_MACROS_USE_SYSLOG
+#define ASSERT_MACROS_USE_SYSLOG 1
+#endif
+
+#include "assert-macros.h"
+
+#include "config-file.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <ctype.h>
+#include <poll.h>
+#include <sys/select.h>
+#include <libgen.h>
+#include <syslog.h>
+
+#include "fgetln.h"
+#include "string-utils.h"
+
+#define strcaseequal(x, y) (strcasecmp(x, y) == 0)
+
+char*
+get_next_arg(char *buf, char **rest)
+{
+ char* ret = NULL;
+ char quote_type = 0;
+ char* write_iter = NULL;
+
+ // Trim whitespace
+ while (isspace(*buf)) {
+ buf++;
+ };
+
+ // Skip if we are empty or the start of a comment.
+ if ((*buf == 0) || (*buf == '#')) {
+ goto bail;
+ }
+
+ write_iter = ret = buf;
+
+ while (*buf != 0) {
+ if (quote_type != 0) {
+ // We are in the middle of a quote, so we are
+ // looking for matching end of the quote.
+ if (*buf == quote_type) {
+ quote_type = 0;
+ buf++;
+ continue;
+ }
+ } else {
+ if (*buf == '"' || *buf == '\'') {
+ quote_type = *buf++;
+ continue;
+ }
+
+ // Stop parsing arguments if we hit unquoted whitespace.
+ if (isspace(*buf)) {
+ buf++;
+ break;
+ }
+ }
+
+ // Allow for slash-escaping
+ if ((buf[0] == '\\') && (buf[1] != 0)) {
+ buf++;
+ }
+
+ *write_iter++ = *buf++;
+ }
+
+ *write_iter = 0;
+
+bail:
+ if (rest) {
+ *rest = buf;
+ }
+ return ret;
+}
+
+int
+read_config(
+ const char* filename,
+ config_param_set_func setter,
+ void* context
+) {
+ int ret = 0;
+
+ FILE* file = fopen(filename, "r");
+ char* line = NULL;
+ size_t line_len = 0;
+ int line_number = 0;
+
+ if (file == NULL) {
+ ret = -1;
+ goto bail;
+ }
+
+ syslog(LOG_INFO, "Reading configuration from \"%s\" . . .", filename);
+
+ while (!feof(file) && (line = fgetln(file, &line_len)) && !ret) {
+ char *key = get_next_arg(line, &line);
+ char *value = get_next_arg(line, &line);
+ line_number++;
+ if (!key) {
+ continue;
+ }
+ ret = setter(context, key, value);
+ }
+
+bail:
+ if (file) {
+ fclose(file);
+ }
+ return ret;
+}
diff --git a/src/util/config-file.h b/src/util/config-file.h
new file mode 100644
index 0000000..aac5f65
--- /dev/null
+++ b/src/util/config-file.h
@@ -0,0 +1,29 @@
+/*
+ *
+ * Copyright (c) 2010-2012 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * This document is the property of Nest. It is considered
+ * confidential and proprietary information.
+ *
+ * This document may not be reproduced or transmitted in any form,
+ * in whole or in part, without the express written permission of
+ * Nest.
+ *
+ * Description:
+ * This is the header for the configuration file parser.
+ *
+ */
+
+#ifndef __WPAN_CONFIG_FILE_H__
+#define __WPAN_CONFIG_FILE_H__ 1
+
+__BEGIN_DECLS
+extern char* get_next_arg(char *buf, char **rest);
+
+typedef int (*config_param_set_func)(void* context, const char* key, const char* value);
+
+extern int read_config(const char* filename, config_param_set_func setter, void* context);
+__END_DECLS
+
+#endif // __WPAN_CONFIG_FILE_H__
diff --git a/src/util/nlpt-select.c b/src/util/nlpt-select.c
new file mode 100644
index 0000000..f53281d
--- /dev/null
+++ b/src/util/nlpt-select.c
@@ -0,0 +1,141 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * Flavor of protothreads for handling asynchronous I/O, via select()
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _XOPEN_SOURCE 1 // For the "fds_bits" member of "fd_set"
+
+#include <stdio.h>
+#include <stdint.h>
+#include "nlpt.h"
+#include "nlpt-select.h"
+#include "assert-macros.h"
+
+static void
+fd_set_merge(const fd_set *src, fd_set *dest, int fd_count)
+{
+ int i;
+ const int32_t* src_data = (const int32_t*)src->fds_bits;
+ int32_t* dest_data = (int32_t*)dest->fds_bits;
+
+ for (i = (fd_count+31)/32; i > 0 ; --i) {
+ *dest_data++ |= *src_data++;
+ }
+}
+
+void
+nlpt_select_update_fd_set(
+ const struct nlpt* nlpt,
+ fd_set *read_fd_set,
+ fd_set *write_fd_set,
+ fd_set *error_fd_set,
+ int *max_fd
+) {
+ if ((max_fd != NULL) && (*max_fd < nlpt->max_fd)) {
+ *max_fd = nlpt->max_fd;
+ }
+
+ if (read_fd_set != NULL) {
+ fd_set_merge(&nlpt->read_fds, read_fd_set, nlpt->max_fd + 1);
+ }
+
+ if (write_fd_set != NULL) {
+ fd_set_merge(&nlpt->write_fds, write_fd_set, nlpt->max_fd + 1);
+ }
+
+ if (error_fd_set != NULL) {
+ fd_set_merge(&nlpt->error_fds, error_fd_set, nlpt->max_fd + 1);
+ }
+}
+
+bool
+_nlpt_checkpoll(int fd, short poll_flags)
+{
+ bool ret = false;
+
+ if (fd >= 0) {
+ struct pollfd pollfd = { fd, poll_flags, 0 };
+ IGNORE_RETURN_VALUE( poll(&pollfd, 1, 0) );
+ ret = ((pollfd.revents & poll_flags) != 0);
+ }
+
+ return ret;
+}
+
+void
+_nlpt_cleanup_all(struct nlpt* nlpt)
+{
+ nlpt->max_fd = -1;
+ FD_ZERO(&nlpt->read_fds);
+ FD_ZERO(&nlpt->write_fds);
+ FD_ZERO(&nlpt->error_fds);
+}
+
+void
+_nlpt_cleanup_read_fd_source(struct nlpt* nlpt, int fd)
+{
+ if (fd >= 0) {
+ FD_CLR(fd, &nlpt->read_fds);
+ FD_CLR(fd, &nlpt->error_fds);
+ }
+}
+
+void
+_nlpt_cleanup_write_fd_source(struct nlpt* nlpt, int fd)
+{
+ if (fd >= 0) {
+ FD_CLR(fd, &nlpt->write_fds);
+ FD_CLR(fd, &nlpt->error_fds);
+ }
+}
+
+void
+_nlpt_setup_read_fd_source(struct nlpt* nlpt, int fd)
+{
+ if (fd >= 0) {
+ if (fd > nlpt->max_fd) {
+ nlpt->max_fd = fd;
+ }
+ FD_SET(fd, &nlpt->read_fds);
+ FD_SET(fd, &nlpt->error_fds);
+ }
+}
+
+void
+_nlpt_setup_write_fd_source(struct nlpt* nlpt, int fd)
+{
+ if (fd >= 0) {
+ if (fd > nlpt->max_fd) {
+ nlpt->max_fd = fd;
+ }
+ FD_SET(fd, &nlpt->write_fds);
+ FD_SET(fd, &nlpt->error_fds);
+ }
+}
+
+void
+_nlpt_init(struct nlpt* nlpt)
+{
+ _nlpt_cleanup_all(nlpt);
+}
diff --git a/src/util/nlpt-select.h b/src/util/nlpt-select.h
new file mode 100644
index 0000000..0508f2e
--- /dev/null
+++ b/src/util/nlpt-select.h
@@ -0,0 +1,75 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * Flavor of protothreads for handling asynchronous I/O, via select()
+ *
+ */
+
+#ifndef wpantund_nlpt_select_h
+#define wpantund_nlpt_select_h
+
+#include <stdbool.h>
+#include <poll.h>
+#include <sys/select.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+struct nlpt {
+ struct pt pt;
+ struct pt sub_pt;
+ size_t byte_count;
+ int last_errno;
+
+ fd_set read_fds;
+ fd_set write_fds;
+ fd_set error_fds;
+ int max_fd;
+};
+
+/* ========================================================================= */
+/* Private, Back-end-specific functions */
+
+extern void _nlpt_init(struct nlpt* nlpt);
+extern void _nlpt_cleanup_all(struct nlpt* nlpt);
+extern void _nlpt_cleanup_read_fd_source(struct nlpt* nlpt, int fd);
+extern void _nlpt_cleanup_write_fd_source(struct nlpt* nlpt, int fd);
+extern void _nlpt_setup_read_fd_source(struct nlpt* nlpt, int fd);
+extern void _nlpt_setup_write_fd_source(struct nlpt* nlpt, int fd);
+
+/* ========================================================================= */
+/* Protected, Back-end-specific hooks (for async I/O) */
+
+extern bool nlpt_hook_check_read_fd_source(struct nlpt* nlpt, int fd);
+extern bool nlpt_hook_check_write_fd_source(struct nlpt* nlpt, int fd);
+
+/* ========================================================================= */
+/* Public, Back-end-specific functions (for async I/O) */
+
+extern void nlpt_select_update_fd_set(
+ const struct nlpt* nlpt,
+ fd_set *read_fd_set,
+ fd_set *write_fd_set,
+ fd_set *error_fd_set,
+ int *max_fd
+);
+extern bool _nlpt_checkpoll(int fd, short poll_flags);
+
+__END_DECLS
+
+#endif
diff --git a/src/util/nlpt.h b/src/util/nlpt.h
new file mode 100644
index 0000000..2b438a6
--- /dev/null
+++ b/src/util/nlpt.h
@@ -0,0 +1,129 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * Flavor of protothreads for handling asynchronous I/O.
+ *
+ */
+
+#ifndef wpantund_nlpt_h
+#define wpantund_nlpt_h
+
+#include "pt.h"
+
+#if USING_GLIB
+#include "nlpt-glib.h"
+#else
+#include "nlpt-select.h"
+#endif
+
+#define NLPT_INIT(nlpt) do { memset(nlpt, 0, sizeof(*nlpt)); PT_INIT(&(nlpt)->pt); _nlpt_init(nlpt); } while (0)
+
+#define NLPT_THREAD(name_args) PT_THREAD(name_args)
+#define NLPT_BEGIN(nlpt) PT_BEGIN(&(nlpt)->pt)
+#define NLPT_END(nlpt) PT_END(&(nlpt)->pt)
+#define NLPT_SPAWN(nlpt, child, thread) PT_SPAWN(&(nlpt)->pt, &(child)->pt, thread)
+#define NLPT_WAIT_UNTIL(nlpt, cond) PT_WAIT_UNTIL(&(nlpt)->pt, cond)
+#define NLPT_WAIT_WHILE(nlpt, cond) PT_WAIT_WHILE(&(nlpt)->pt, cond)
+#define NLPT_RESTART(nlpt) PT_RESTART(&(nlpt)->pt)
+#define NLPT_EXIT(nlpt) PT_EXIT(&(nlpt)->pt)
+#define NLPT_YIELD(nlpt) PT_YIELD(&(nlpt)->pt)
+#define NLPT_YIELD_UNTIL(nlpt, cond) PT_YIELD_UNTIL(&(nlpt)->pt, cond)
+
+//! Waits until one of the two given file descriptors are readable or the condition is satisfied.
+#define NLPT_WAIT_UNTIL_READABLE2_OR_COND(nlpt, fd_, fd2_, c) \
+ do { \
+ _nlpt_setup_read_fd_source(nlpt, fd_); \
+ _nlpt_setup_read_fd_source(nlpt, fd2_); \
+ NLPT_WAIT_UNTIL(nlpt, \
+ nlpt_hook_check_read_fd_source(nlpt, fd_) \
+ || nlpt_hook_check_read_fd_source(nlpt, fd2_) \
+ || (c)); \
+ _nlpt_cleanup_read_fd_source(nlpt, fd2_); \
+ _nlpt_cleanup_read_fd_source(nlpt, fd_); \
+ } while (0)
+
+#define NLPT_WAIT_UNTIL_READABLE_OR_COND(nlpt, fd_, c) \
+ do { \
+ _nlpt_setup_read_fd_source(nlpt, fd_); \
+ NLPT_WAIT_UNTIL(nlpt, \
+ nlpt_hook_check_read_fd_source(nlpt, fd_) || (c)); \
+ _nlpt_cleanup_read_fd_source(nlpt, fd_); \
+ } while (0)
+
+#define NLPT_WAIT_UNTIL_WRITABLE_OR_COND(nlpt, fd_, c) \
+ do { \
+ _nlpt_setup_write_fd_source(nlpt, fd_); \
+ NLPT_WAIT_UNTIL(nlpt, \
+ nlpt_hook_check_write_fd_source(nlpt, fd_) || (c)); \
+ _nlpt_cleanup_write_fd_source(nlpt, fd_); \
+ } while (0)
+
+#define NLPT_YIELD_UNTIL_READABLE2_OR_COND(nlpt, fd_, fd2_, c) \
+ do { \
+ _nlpt_setup_read_fd_source(nlpt, fd_); \
+ _nlpt_setup_read_fd_source(nlpt, fd2_); \
+ NLPT_YIELD_UNTIL(nlpt, \
+ nlpt_hook_check_read_fd_source(nlpt, fd_) \
+ || nlpt_hook_check_read_fd_source(nlpt, fd2_) \
+ || (c)); \
+ _nlpt_cleanup_read_fd_source(nlpt, fd2_); \
+ _nlpt_cleanup_read_fd_source(nlpt, fd_); \
+ } while (0)
+
+#define NLPT_YIELD_UNTIL_READABLE_OR_COND(nlpt, fd_, c) \
+ do { \
+ _nlpt_setup_read_fd_source(nlpt, fd_); \
+ NLPT_YIELD_UNTIL(nlpt, \
+ nlpt_hook_check_read_fd_source(nlpt, fd_) || (c)); \
+ _nlpt_cleanup_read_fd_source(nlpt, fd_); \
+ } while (0)
+
+#define NLPT_YIELD_UNTIL_WRITABLE_OR_COND(nlpt, fd_, c) \
+ do { \
+ _nlpt_setup_write_fd_source(nlpt, fd_); \
+ NLPT_YIELD_UNTIL(nlpt, \
+ nlpt_hook_check_write_fd_source(nlpt, fd_) || (c)); \
+ _nlpt_cleanup_write_fd_source(nlpt, fd_); \
+ } while (0)
+
+#define NLPT_WAIT_UNTIL_READABLE(nlpt, fd) \
+ NLPT_WAIT_UNTIL_READABLE_OR_COND( \
+ nlpt, \
+ fd, \
+ 0)
+
+#define NLPT_WAIT_UNTIL_WRITABLE(nlpt, fd) \
+ NLPT_WAIT_UNTIL_WRITABLE_OR_COND( \
+ nlpt, \
+ fd, \
+ 0)
+
+#define NLPT_YIELD_UNTIL_READABLE(nlpt, fd) \
+ NLPT_YIELD_UNTIL_READABLE_OR_COND( \
+ nlpt, \
+ fd, \
+ 0)
+
+#define NLPT_YIELD_UNTIL_WRITABLE(nlpt, fd) \
+ NLPT_YIELD_UNTIL_WRITABLE_OR_COND( \
+ nlpt, \
+ fd, \
+ 0)
+
+
+#endif
diff --git a/src/util/sec-random.c b/src/util/sec-random.c
new file mode 100644
index 0000000..7e73f51
--- /dev/null
+++ b/src/util/sec-random.c
@@ -0,0 +1,60 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "sec-random.h"
+
+static FILE* gSecRandomFile;
+
+int
+sec_random_init(void)
+{
+ if (gSecRandomFile == NULL) {
+ const char* random_source_filename = getenv("SEC_RANDOM_SOURCE_FILE");
+
+ if (!random_source_filename) {
+ random_source_filename = "/dev/urandom";
+ }
+
+ gSecRandomFile = fopen(random_source_filename, "r");
+
+ if (gSecRandomFile == NULL) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int
+sec_random_fill(uint8_t* buffer, int length)
+{
+ int ret = sec_random_init();
+
+ if (ret >= 0) {
+ ret = (int)fread(buffer, length, 1, gSecRandomFile);
+ }
+
+ return ret;
+}
diff --git a/src/util/sec-random.h b/src/util/sec-random.h
new file mode 100644
index 0000000..6d89c33
--- /dev/null
+++ b/src/util/sec-random.h
@@ -0,0 +1,33 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef SEC_RANDOM_HEADER_INCLUDED
+#define SEC_RANDOM_HEADER_INCLUDED 1
+
+#include <sys/cdefs.h>
+#include <stdint.h>
+
+__BEGIN_DECLS
+
+int sec_random_init(void);
+int sec_random_fill(uint8_t* buffer, int length);
+
+__END_DECLS
+
+#endif // SEC_RANDOM_HEADER_INCLUDED
diff --git a/src/util/socket-utils.c b/src/util/socket-utils.c
new file mode 100644
index 0000000..c829aef
--- /dev/null
+++ b/src/util/socket-utils.c
@@ -0,0 +1,949 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE 1
+
+#include "assert-macros.h"
+
+#include <stdio.h>
+#include "socket-utils.h"
+#include <ctype.h>
+#include <syslog.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/ioctl.h>
+#include <ctype.h>
+#include <signal.h>
+
+#if HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+
+#if HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+#if HAVE_PTY_H
+#include <pty.h>
+#endif
+
+#if HAVE_UTIL_H
+#include <util.h>
+#endif
+
+#if HAVE_SYS_PRCTL_H
+#include <sys/prctl.h>
+#endif
+
+
+#if !defined(HAVE_PTSNAME) && __APPLE__
+#define HAVE_PTSNAME 1
+#endif
+
+#if !HAVE_GETDTABLESIZE
+#define getdtablesize() (int)sysconf(_SC_OPEN_MAX)
+#endif
+
+#ifndef O_NONBLOCK
+#define O_NONBLOCK O_NDELAY
+#endif
+
+#include <poll.h>
+
+static struct {
+ int fd;
+ pid_t pid;
+} gSystemSocketTable[5];
+
+static void
+system_socket_table_close_alarm_(int sig)
+{
+ static const char message[] = "\nclose_super_socket: Unable to terminate child in a timely manner, watchdog fired\n";
+
+ // Can't use syslog here, write to stderr instead.
+ (void)write(STDERR_FILENO, message, sizeof(message) - 1);
+
+ _exit(EXIT_FAILURE);
+}
+
+static void
+system_socket_table_atexit_(void)
+{
+ int i;
+
+ for (i = 0; i < sizeof(gSystemSocketTable)/sizeof(gSystemSocketTable[0]); i++) {
+ if (gSystemSocketTable[i].pid != 0) {
+ kill(gSystemSocketTable[i].pid, SIGTERM);
+ }
+ }
+}
+
+static void
+system_socket_table_add_(int fd, pid_t pid)
+{
+ static bool did_init = false;
+ int i;
+
+ if (!did_init) {
+ atexit(&system_socket_table_atexit_);
+ did_init = true;
+ }
+
+ for (i = 0; i < sizeof(gSystemSocketTable)/sizeof(gSystemSocketTable[0]); i++) {
+ if (gSystemSocketTable[i].pid == 0) {
+ break;
+ }
+ }
+
+ // If we have more than 5 of these types of sockets
+ // open, then there is likely a serious problem going
+ // on that we should immediately deal with.
+ assert(i < sizeof(gSystemSocketTable)/sizeof(gSystemSocketTable[0]));
+
+ if (i < sizeof(gSystemSocketTable)/sizeof(gSystemSocketTable[0])) {
+ gSystemSocketTable[i].fd = fd;
+ gSystemSocketTable[i].pid = pid;
+ }
+}
+
+int
+close_super_socket(int fd)
+{
+ int i;
+ int ret;
+ for (i = 0; i < sizeof(gSystemSocketTable)/sizeof(gSystemSocketTable[0]); i++) {
+ if ( gSystemSocketTable[i].fd == fd
+ && gSystemSocketTable[i].pid != 0
+ ) {
+ break;
+ }
+ }
+
+ ret = close(fd);
+
+ if (i < sizeof(gSystemSocketTable)/sizeof(gSystemSocketTable[0])) {
+ pid_t pid = gSystemSocketTable[i].pid;
+ int x = 0, j = 0;
+
+ kill(gSystemSocketTable[i].pid, SIGHUP);
+
+ for (j = 0; j < 100; ++j) {
+ pid = waitpid(gSystemSocketTable[i].pid, &x, WNOHANG);
+ if (pid > 0) {
+ break;
+ }
+ usleep(100000);
+ }
+
+ if (pid <= 0) {
+ // Five second watchdog.
+ void (*prev_alarm_handler)(int) = signal(SIGALRM, &system_socket_table_close_alarm_);
+ unsigned int prev_alarm_remaining = alarm(5);
+
+ syslog(LOG_WARNING, "close_super_socket: PID %d didn't respond to SIGHUP, trying SIGTERM", gSystemSocketTable[i].pid);
+
+ kill(gSystemSocketTable[i].pid, SIGTERM);
+
+ do {
+ errno = 0;
+ pid = waitpid(gSystemSocketTable[i].pid, &x, 0);
+ } while ((pid == -1) && (errno == EINTR));
+
+ // Disarm watchdog.
+ alarm(prev_alarm_remaining);
+ signal(SIGALRM, prev_alarm_handler);
+ }
+
+ if (pid == -1) {
+ perror(strerror(errno));
+ }
+
+
+ gSystemSocketTable[i].pid = 0;
+ gSystemSocketTable[i].fd = -1;
+ }
+
+ return ret;
+}
+
+int
+fd_has_error(int fd)
+{
+ const int flags = (POLLPRI|POLLRDBAND|POLLERR|POLLHUP|POLLNVAL);
+ struct pollfd pollfd = { fd, flags, 0 };
+ int count = poll(&pollfd, 1, 0);
+
+ if (count<0) {
+ return -errno;
+ } else if (count > 0) {
+ if (pollfd.revents&POLLHUP) {
+ return -EPIPE;
+ }
+
+ if (pollfd.revents&(POLLRDBAND|POLLPRI)) {
+ return -EPIPE;
+ }
+
+ if (pollfd.revents&POLLNVAL) {
+ return -EINVAL;
+ }
+
+ if (pollfd.revents&POLLERR) {
+ return -EIO;
+ }
+ }
+ return 0;
+}
+
+int gSocketWrapperBaud = 115200;
+
+static bool
+socket_name_is_system_command(const char* socket_name)
+{
+ return strncmp(socket_name,SOCKET_SYSTEM_COMMAND_PREFIX,strlen(SOCKET_SYSTEM_COMMAND_PREFIX)) == 0
+ || strncmp(socket_name,SOCKET_SYSTEM_FORKPTY_COMMAND_PREFIX,strlen(SOCKET_SYSTEM_FORKPTY_COMMAND_PREFIX)) == 0
+ || strncmp(socket_name,SOCKET_SYSTEM_SOCKETPAIR_COMMAND_PREFIX,strlen(SOCKET_SYSTEM_SOCKETPAIR_COMMAND_PREFIX)) == 0
+ ;
+}
+
+static bool
+socket_name_is_port(const char* socket_name)
+{
+ // It's a port if the string is just a number.
+ while (*socket_name) {
+ if (!isdigit(*socket_name++)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool
+socket_name_is_inet(const char* socket_name)
+{
+ // It's an inet address if it Contains no slashes or starts with a '['.
+ if (*socket_name == '[') {
+ return true;
+ }
+ do {
+ if (*socket_name == '/') {
+ return false;
+ }
+ } while (*++socket_name);
+ return !socket_name_is_port(socket_name) && !socket_name_is_system_command(socket_name);
+}
+
+bool
+socket_name_is_device(const char* socket_name)
+{
+ return !socket_name_is_system_command(socket_name) && !socket_name_is_inet(socket_name);
+}
+
+int
+lookup_sockaddr_from_host_and_port(
+ struct sockaddr_in6* outaddr, const char* host, const char* port
+ )
+{
+ int ret = 0;
+ struct addrinfo hint = {
+ };
+
+ hint.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED | AI_ALL;
+ hint.ai_family = AF_INET6;
+
+ struct addrinfo *results = NULL;
+ struct addrinfo *iter = NULL;
+
+ if (!port) {
+ port = "4951";
+ }
+
+ if (!host) {
+ host = "::1";
+ }
+
+ syslog(LOG_INFO, "Looking up [%s]:%s", host, port);
+
+ if (isdigit(port[0]) && strcmp(host, "::1") == 0) {
+ // Special case to avoid calling getaddrinfo() when
+ // we really don't need to.
+ memset(outaddr, 0, sizeof(struct sockaddr_in6));
+ outaddr->sin6_family = AF_INET6;
+ outaddr->sin6_addr.s6_addr[15] = 1;
+ outaddr->sin6_port = htons(atoi(port));
+ } else if (isdigit(port[0]) && inet_addr(host) != 0) {
+ in_addr_t v4addr = inet_addr(host);
+ memset(outaddr, 0, sizeof(struct sockaddr_in6));
+ outaddr->sin6_family = AF_INET6;
+ outaddr->sin6_addr.s6_addr[10] = 0xFF;
+ outaddr->sin6_addr.s6_addr[11] = 0xFF;
+ outaddr->sin6_port = htons(atoi(port));
+ memcpy(outaddr->sin6_addr.s6_addr + 12, &v4addr, sizeof(v4addr));
+ outaddr->sin6_port = htons(atoi(port));
+ } else {
+ int error = getaddrinfo(host, port, &hint, &results);
+
+ require_action_string(
+ !error,
+ bail,
+ ret = -1,
+ gai_strerror(error)
+ );
+
+ for (iter = results;
+ iter && (iter->ai_family != AF_INET6);
+ iter = iter->ai_next) ;
+
+ require_action(NULL != iter, bail, ret = -1);
+
+ memcpy(outaddr, iter->ai_addr, iter->ai_addrlen);
+ }
+
+bail:
+ if (results)
+ freeaddrinfo(results);
+
+ return ret;
+}
+
+#if HAVE_FORKPTY
+static int
+diagnose_forkpty_problem()
+{
+ int ret = -1;
+ // COM-S-7530: Do some more diagnostics on the situation, because
+ // sort of failure is weird. We step through some of the same sorts of
+ // things that forkpty would do so that we can see where we are failing.
+ int pty_master_fd = -1;
+ int pty_slave_fd = -1;
+ do {
+ if( access( "/dev/ptmx", F_OK ) < 0 ) {
+ syslog(LOG_WARNING, "Call to access(\"/dev/ptmx\",F_OK) failed: %s (%d)", strerror(errno), errno);
+ perror("access(\"/dev/ptmx\",F_OK)");
+ }
+
+ if( access( "/dev/ptmx", R_OK|W_OK ) < 0 ) {
+ syslog(LOG_WARNING, "Call to access(\"/dev/ptmx\",R_OK|W_OK) failed: %s (%d)", strerror(errno), errno);
+ perror("access(\"/dev/ptmx\",R_OK|W_OK)");
+ }
+
+ pty_master_fd = posix_openpt(O_NOCTTY | O_RDWR);
+
+ if (pty_master_fd < 0) {
+ syslog(LOG_CRIT, "Call to posix_openpt() failed: %s (%d)", strerror(errno), errno);
+ perror("posix_openpt(O_NOCTTY | O_RDWR)");
+ break;
+ }
+
+ if (grantpt(pty_master_fd) < 0) {
+ syslog(LOG_CRIT, "Call to grantpt() failed: %s (%d)", strerror(errno), errno);
+ perror("grantpt");
+ }
+
+ if (unlockpt(pty_master_fd) < 0) {
+ syslog(LOG_CRIT, "Call to unlockpt() failed: %s (%d)", strerror(errno), errno);
+ perror("unlockpt");
+ }
+
+#if HAVE_PTSNAME
+ if (NULL == ptsname(pty_master_fd)) {
+ syslog(LOG_CRIT, "Call to ptsname() failed: %s (%d)", strerror(errno), errno);
+ perror("ptsname");
+ break;
+ }
+
+ pty_slave_fd = open(ptsname(pty_master_fd), O_RDWR | O_NOCTTY);
+
+ if (pty_slave_fd < 0) {
+ syslog(LOG_CRIT, "Call to open(\"%s\",O_RDWR|O_NOCTTY) failed: %s (%d)", ptsname(pty_master_fd), strerror(errno), errno);
+ perror("open(ptsname(pty_master_fd),O_RDWR|O_NOCTTY)");
+ break;
+ }
+#endif
+
+ ret = 0;
+ } while(0);
+ close(pty_master_fd);
+ close(pty_slave_fd);
+ return ret;
+}
+
+static int
+open_system_socket_forkpty(const char* command)
+{
+ int ret_fd = -1;
+ int stderr_copy_fd;
+ pid_t pid;
+ struct termios tios = { .c_cflag = CS8|HUPCL|CREAD|CLOCAL };
+
+ cfmakeraw(&tios);
+
+ // Duplicate stderr so that we can hook it back up in the forked process.
+ stderr_copy_fd = dup(STDERR_FILENO);
+ if (stderr_copy_fd < 0) {
+ syslog(LOG_ERR, "Call to dup() failed: %s (%d)", strerror(errno), errno);
+ goto cleanup_and_fail;
+ }
+
+ pid = forkpty(&ret_fd, NULL, &tios, NULL);
+ if (pid < 0) {
+ syslog(LOG_ERR, "Call to forkpty() failed: %s (%d)", strerror(errno), errno);
+
+ if (0 == diagnose_forkpty_problem()) {
+ syslog(LOG_CRIT, "FORKPTY() FAILED BUT NOTHING WAS OBVIOUSLY WRONG!!!");
+ }
+
+ goto cleanup_and_fail;
+ }
+
+ // Check to see if we are the forked process or not.
+ if (0 == pid) {
+ // We are the forked process.
+ const int dtablesize = getdtablesize();
+ int i;
+
+#if defined(_LINUX_PRCTL_H)
+ prctl(PR_SET_PDEATHSIG, SIGHUP);
+#endif
+
+ // Re-instate our original stderr.
+ dup2(stderr_copy_fd, STDERR_FILENO);
+
+ syslog(LOG_DEBUG, "Forked!");
+
+ // Re-instate our original stderr (clobbered by login_tty)
+ dup2(stderr_copy_fd, STDERR_FILENO);
+
+ // Set the shell environment variable if it isn't set already.
+ setenv("SHELL", SOCKET_UTILS_DEFAULT_SHELL, 0);
+
+ // Close all file descriptors larger than STDERR_FILENO.
+ for (i = (STDERR_FILENO + 1); i < dtablesize; i++) {
+ close(i);
+ }
+
+ syslog(LOG_NOTICE,"About to exec \"%s\"",command);
+
+ execl(getenv("SHELL"),getenv("SHELL"),"-c",command,NULL);
+
+ syslog(LOG_ERR,"Failed for fork and exec of \"%s\": %s (%d)", command, strerror(errno), errno);
+
+ _exit(errno);
+ }
+
+ // Clean up our copy of stderr
+ close(stderr_copy_fd);
+
+#if HAVE_PTSNAME
+ // See http://stackoverflow.com/questions/3486491/
+ close(open(ptsname(ret_fd), O_RDWR | O_NOCTTY));
+#endif
+
+ system_socket_table_add_(ret_fd, pid);
+
+ return ret_fd;
+
+cleanup_and_fail:
+ {
+ int prevErrno = errno;
+
+ close(ret_fd);
+ close(stderr_copy_fd);
+
+ errno = prevErrno;
+ }
+ return -1;
+}
+#endif // HAVE_FORKPTY
+
+#ifdef PF_UNIX
+
+int
+fork_unixdomain_socket(int* fd_pointer)
+{
+ int fd[2] = { -1, -1 };
+ int i;
+ pid_t pid = -1;
+
+ if (socketpair(PF_UNIX, SOCK_STREAM, 0, fd) < 0) {
+ syslog(LOG_ERR, "Call to socketpair() failed: %s (%d)", strerror(errno), errno);
+ goto bail;
+ }
+
+ pid = fork();
+ if (pid < 0) {
+ syslog(LOG_ERR, "Call to fork() failed: %s (%d)", strerror(errno), errno);
+ goto bail;
+ }
+
+ // Check to see if we are the forked process or not.
+ if (0 == pid) {
+ const int dtablesize = getdtablesize();
+ // We are the forked process.
+
+#if defined(_LINUX_PRCTL_H)
+ prctl(PR_SET_PDEATHSIG, SIGHUP);
+#endif
+
+ close(fd[0]);
+
+ dup2(fd[1], STDIN_FILENO);
+ dup2(fd[1], STDOUT_FILENO);
+
+ syslog(LOG_DEBUG, "Forked!");
+
+ // Close all file descriptors larger than STDERR_FILENO.
+ for (i = (STDERR_FILENO + 1); i < dtablesize; i++) {
+ close(i);
+ }
+
+ *fd_pointer = STDIN_FILENO;
+ } else {
+ close(fd[1]);
+ *fd_pointer = fd[0];
+ }
+
+ fd[0] = -1;
+ fd[1] = -1;
+
+bail:
+
+ {
+ int prevErrno = errno;
+ if (fd[0] >= 0) {
+ close(fd[0]);
+ }
+ if (fd[1] >= 0) {
+ close(fd[1]);
+ }
+ errno = prevErrno;
+ }
+
+ return pid;
+}
+
+static int
+open_system_socket_unix_domain(const char* command)
+{
+ int fd = -1;
+ pid_t pid = -1;
+
+ pid = fork_unixdomain_socket(&fd);
+
+ if (pid < 0) {
+ syslog(LOG_ERR, "Call to fork() failed: %s (%d)", strerror(errno), errno);
+ goto cleanup_and_fail;
+ }
+
+ // Check to see if we are the forked process or not.
+ if (0 == pid) {
+ // Set the shell environment variable if it isn't set already.
+ setenv("SHELL","/bin/sh",0);
+
+ syslog(LOG_NOTICE, "About to exec \"%s\"", command);
+
+ execl(getenv("SHELL"), getenv("SHELL"),"-c", command, NULL);
+
+ syslog(LOG_ERR, "Failed for fork and exec of \"%s\": %s (%d)", command, strerror(errno), errno);
+
+ _exit(EXIT_FAILURE);
+ }
+
+ system_socket_table_add_(fd, pid);
+
+ return fd;
+
+cleanup_and_fail:
+
+ if (fd >= 0) {
+ int prevErrno = errno;
+
+ close(fd);
+
+ errno = prevErrno;
+ }
+
+ return -1;
+}
+#endif // PF_UNIX
+
+static int
+open_system_socket(const char* command)
+{
+ int ret_fd = -1;
+
+#if HAVE_FORKPTY
+ ret_fd = open_system_socket_forkpty(command);
+#endif
+
+#if defined(PF_UNIX)
+ // Fall back to unix-domain socket-based mechanism:
+ if (ret_fd < 0) {
+ ret_fd = open_system_socket_unix_domain(command);
+ }
+#endif
+
+#if !HAVE_FORKPTY && !defined(PF_UNIX)
+ assert_printf("%s","Process pipe sockets are not supported in current configuration");
+ errno = ENOTSUP;
+#endif
+
+ return ret_fd;
+}
+
+int
+get_super_socket_type_from_path(const char* socket_name)
+{
+ int socket_type = SUPER_SOCKET_TYPE_UNKNOWN;
+
+ if (strncasecmp(socket_name, SOCKET_SYSTEM_COMMAND_PREFIX, sizeof(SOCKET_SYSTEM_COMMAND_PREFIX)-1) == 0) {
+ socket_type = SUPER_SOCKET_TYPE_SYSTEM;
+ } else if (strncasecmp(socket_name, SOCKET_SYSTEM_FORKPTY_COMMAND_PREFIX, sizeof(SOCKET_SYSTEM_FORKPTY_COMMAND_PREFIX)-1) == 0) {
+ socket_type = SUPER_SOCKET_TYPE_SYSTEM_FORKPTY;
+ } else if (strncasecmp(socket_name, SOCKET_SYSTEM_SOCKETPAIR_COMMAND_PREFIX, sizeof(SOCKET_SYSTEM_SOCKETPAIR_COMMAND_PREFIX)-1) == 0) {
+ socket_type = SUPER_SOCKET_TYPE_SYSTEM_SOCKETPAIR;
+ } else if (strncasecmp(socket_name, SOCKET_FD_COMMAND_PREFIX, sizeof(SOCKET_FD_COMMAND_PREFIX)-1) == 0) {
+ socket_type = SUPER_SOCKET_TYPE_FD;
+ } else if (strncasecmp(socket_name, SOCKET_FILE_COMMAND_PREFIX, sizeof(SOCKET_FILE_COMMAND_PREFIX)-1) == 0) {
+ socket_type = SUPER_SOCKET_TYPE_DEVICE;
+ } else if (strncasecmp(socket_name, SOCKET_SERIAL_COMMAND_PREFIX, sizeof(SOCKET_SERIAL_COMMAND_PREFIX)-1) == 0) {
+ socket_type = SUPER_SOCKET_TYPE_DEVICE;
+ } else if (strncasecmp(socket_name, SOCKET_TCP_COMMAND_PREFIX, sizeof(SOCKET_TCP_COMMAND_PREFIX)-1) == 0) {
+ socket_type = SUPER_SOCKET_TYPE_TCP;
+ } else if (socket_name_is_inet(socket_name) || socket_name_is_port(socket_name)) {
+ socket_type = SUPER_SOCKET_TYPE_TCP;
+ } else if (socket_name_is_device(socket_name)) {
+ socket_type = SUPER_SOCKET_TYPE_DEVICE;
+ }
+ return socket_type;
+}
+
+int
+baud_rate_to_termios_constant(int baud)
+{
+ int ret;
+ // Standard "TERMIOS" uses constants to get and set
+ // the baud rate, but we use the actual baud rate.
+ // This function converts from the actual baud rate
+ // to the constant supported by this platform. It
+ // returns zero if the baud rate is unsupported.
+ switch(baud) {
+ case 9600:
+ ret = B9600;
+ break;
+ case 19200:
+ ret = B19200;
+ break;
+ case 38400:
+ ret = B38400;
+ break;
+ case 57600:
+ ret = B57600;
+ break;
+ case 115200:
+ ret = B115200;
+ break;
+#ifdef B230400
+ case 230400:
+ ret = B230400;
+ break;
+#endif
+ default:
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
+int
+open_super_socket(const char* socket_name)
+{
+ int fd = -1;
+ char* host = NULL; // Needs to be freed if set
+ const char* port = NULL;
+ char* options = strchr(socket_name, ',');
+ char* filename = strchr(socket_name, ':');
+ bool socket_name_is_well_formed = true; // True if socket has type name and options
+ int socket_type = get_super_socket_type_from_path(socket_name);
+
+ // Move past the colon, if there was one.
+ if (NULL != filename && socket_name[0] != '[') {
+ filename++;
+ } else {
+ filename = "";
+ }
+
+ if (socket_type == SUPER_SOCKET_TYPE_DEVICE) {
+ socket_name_is_well_formed =
+ (strncasecmp(socket_name, SOCKET_SERIAL_COMMAND_PREFIX, sizeof(SOCKET_SERIAL_COMMAND_PREFIX)-1) == 0)
+ || (strncasecmp(socket_name, SOCKET_FILE_COMMAND_PREFIX, sizeof(SOCKET_FILE_COMMAND_PREFIX)-1) == 0);
+ }
+
+ if (socket_type == SUPER_SOCKET_TYPE_TCP) {
+ socket_name_is_well_formed =
+ (strncasecmp(socket_name, SOCKET_TCP_COMMAND_PREFIX, sizeof(SOCKET_TCP_COMMAND_PREFIX)-1) == 0);
+ if (!socket_name_is_well_formed) {
+ filename = (char*)socket_name;
+ }
+ }
+
+ if (!socket_name_is_well_formed) {
+ filename = (char*)socket_name;
+ if (socket_type == SUPER_SOCKET_TYPE_DEVICE) {
+ options = ",default";
+ } else {
+ options = NULL;
+ }
+ }
+
+ filename = strdup(filename);
+
+ if (NULL == filename) {
+ perror("strdup");
+ syslog(LOG_ERR, "strdup failed. \"%s\" (%d)", strerror(errno), errno);
+ goto bail;
+ }
+
+ // Make sure we zero terminate the file name before
+ // any options. (this is why we needed to strdup)
+ if (socket_name_is_well_formed && (NULL != options)) {
+ const char* ptr = strchr(socket_name, ':');
+ if (NULL == ptr) {
+ ptr = socket_name;
+ } else {
+ ptr++;
+ }
+ filename[options-ptr] = 0;
+ }
+
+ if (SUPER_SOCKET_TYPE_SYSTEM == socket_type) {
+ fd = open_system_socket(filename);
+#if HAVE_FORKPTY
+ } else if (SUPER_SOCKET_TYPE_SYSTEM_FORKPTY == socket_type) {
+ fd = open_system_socket_forkpty(filename);
+#endif
+ } else if (SUPER_SOCKET_TYPE_SYSTEM_SOCKETPAIR == socket_type) {
+ fd = open_system_socket_unix_domain(filename);
+ } else if (SUPER_SOCKET_TYPE_FD == socket_type) {
+ fd = dup((int)strtol(filename, NULL, 0));
+ } else if (SUPER_SOCKET_TYPE_DEVICE == socket_type) {
+ fd = open(filename, O_RDWR | O_NOCTTY | O_NONBLOCK);
+
+ if (fd >= 0) {
+ fcntl(fd, F_SETFL, O_NONBLOCK);
+ tcflush(fd, TCIOFLUSH);
+ }
+ } else if (SUPER_SOCKET_TYPE_TCP == socket_type) {
+ struct sockaddr_in6 addr;
+
+ if (socket_name_is_port(socket_name)) {
+ port = socket_name;
+ } else {
+ ssize_t i;
+ if (filename[0] == '[') {
+ host = strdup(filename + 1);
+ } else {
+ host = strdup(filename);
+ }
+ for (i = strlen(host) - 1; i >= 0; --i) {
+ if (host[i] == ':' && port == NULL) {
+ host[i] = 0;
+ port = host + i + 1;
+ continue;
+ }
+ if (host[i] == ']') {
+ host[i] = 0;
+ break;
+ }
+ if (!isdigit(host[i]))
+ break;
+ }
+ }
+
+ if (0 != lookup_sockaddr_from_host_and_port(&addr, host, port)) {
+ syslog(LOG_ERR, "Unable to lookup \"%s\"", socket_name);
+ goto bail;
+ }
+
+ fd = socket(AF_INET6, SOCK_STREAM, 0);
+
+ if (fd < 0) {
+ syslog(LOG_ERR, "Unable to open socket. \"%s\" (%d)", strerror(errno), errno);
+ goto bail;
+ }
+
+ if (0 != connect(fd, (struct sockaddr*)&addr, sizeof(addr))) {
+ syslog(LOG_ERR, "Call to connect() failed. \"%s\" (%d)", strerror(errno), errno);
+ close(fd);
+ fd = -1;
+ goto bail;
+ }
+ } else {
+ syslog(LOG_ERR, "I don't know how to open \"%s\" (socket type %d)", socket_name, (int)socket_type);
+ }
+
+ if (fd < 0) {
+ syslog(LOG_ERR, "Unable to open socket. \"%s\" (%d) (filename = %s, type = %d)", strerror(errno), errno, filename, (int)socket_type);
+ goto bail;
+ }
+
+ // Configure the socket.
+ {
+ int flags = fcntl(fd, F_GETFL);
+ int i;
+ struct termios tios;
+ fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+
+#ifdef SO_NOSIGPIPE
+ int set = 0;
+ setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
+#endif
+
+#define FETCH_TERMIOS() do { if(0 != tcgetattr(fd, &tios)) { \
+ syslog(LOG_DEBUG, "tcgetattr() failed. \"%s\" (%d)", strerror(errno), errno); \
+ } } while(0)
+
+#define COMMIT_TERMIOS() do { if(0 != tcsetattr(fd, TCSANOW, &tios)) { \
+ syslog(LOG_DEBUG, "tcsetattr() failed. \"%s\" (%d)", strerror(errno), errno); \
+ } } while(0)
+
+ // Parse the options, if any
+ for (; NULL != options; options = strchr(options+1, ',')) {
+ if (strncasecmp(options, ",b", 2) == 0 && isdigit(options[2])) {
+ // Change Baud rate
+ int baud = baud_rate_to_termios_constant((int)strtol(options+2,NULL,10));
+ FETCH_TERMIOS();
+ cfsetspeed(&tios, baud);
+ COMMIT_TERMIOS();
+ } else if (strncasecmp(options, ",default", strlen(",default")) == 0) {
+ FETCH_TERMIOS();
+ for (i=0; i < NCCS; i++) {
+ tios.c_cc[i] = _POSIX_VDISABLE;
+ }
+
+ tios.c_cflag = (CS8|HUPCL|CREAD|CLOCAL);
+ tios.c_iflag = 0;
+ tios.c_oflag = 0;
+ tios.c_lflag = 0;
+
+ cfmakeraw(&tios);
+ cfsetspeed(&tios, baud_rate_to_termios_constant(gSocketWrapperBaud));
+ COMMIT_TERMIOS();
+ } else if (strncasecmp(options, ",raw", 4) == 0) {
+ // Raw mode
+ FETCH_TERMIOS();
+ cfmakeraw(&tios);
+ COMMIT_TERMIOS();
+ } else if (strncasecmp(options, ",clocal=", 8) == 0) {
+ FETCH_TERMIOS();
+ options = strchr(options,'=');
+ if (options[1] == '1') {
+ tios.c_cflag |= CLOCAL;
+ } else if (options[1] == '0') {
+ tios.c_cflag &= ~CLOCAL;
+ }
+ COMMIT_TERMIOS();
+ } else if (strncasecmp(options, ",ixoff=", 6) == 0) {
+ FETCH_TERMIOS();
+ options = strchr(options,'=');
+ if (options[1] == '1') {
+ tios.c_iflag |= IXOFF;
+ } else if (options[1] == '0') {
+ tios.c_iflag &= ~IXOFF;
+ }
+ COMMIT_TERMIOS();
+ } else if (strncasecmp(options, ",ixon=", 6) == 0) {
+ FETCH_TERMIOS();
+ options = strchr(options,'=');
+ if (options[1] == '1') {
+ tios.c_iflag |= IXON;
+ } else if (options[1] == '0') {
+ tios.c_iflag &= ~IXON;
+ }
+ COMMIT_TERMIOS();
+ } else if (strncasecmp(options, ",ixany=", 6) == 0) {
+ FETCH_TERMIOS();
+ options = strchr(options,'=');
+ if (options[1] == '1') {
+ tios.c_iflag |= IXANY;
+ } else if (options[1] == '0') {
+ tios.c_iflag &= ~IXANY;
+ }
+ COMMIT_TERMIOS();
+ } else if (strncasecmp(options, ",crtscts=", 9) == 0) {
+ FETCH_TERMIOS();
+ options = strchr(options,'=');
+ // Hardware flow control
+ if (options[1] == '1') {
+ syslog(LOG_DEBUG, "Using hardware flow control for serial socket.");
+ tios.c_cflag |= CRTSCTS;
+ } else if (options[1] == '0') {
+ tios.c_cflag &= ~CRTSCTS;
+ }
+ COMMIT_TERMIOS();
+
+#ifdef CCTS_OFLOW
+ } else if (strncasecmp(options, ",ccts_oflow=", 12) == 0) {
+ FETCH_TERMIOS();
+ options = strchr(options,'=');
+ // Hardware output flow control
+ if (options[1] == '1') {
+ syslog(LOG_DEBUG, "Using hardware output flow control for serial socket.");
+ tios.c_cflag |= CCTS_OFLOW;
+ } else if (options[1] == '0') {
+ tios.c_cflag &= ~CCTS_OFLOW;
+ }
+ COMMIT_TERMIOS();
+#endif
+#ifdef CRTS_IFLOW
+ } else if (strncasecmp(options, ",crts_iflow=", 12) == 0) {
+ FETCH_TERMIOS();
+ options = strchr(options,'=');
+ // Hardware input flow control
+ if (options[1] == '1') {
+ syslog(LOG_DEBUG, "Using hardware input flow control for serial socket.");
+ tios.c_cflag |= CRTS_IFLOW;
+ } else if (options[1] == '0') {
+ tios.c_cflag &= ~CRTS_IFLOW;
+ }
+ COMMIT_TERMIOS();
+#endif
+ } else {
+ syslog(LOG_ERR, "Unknown option (%s)", options);
+ }
+ }
+ }
+bail:
+ free(filename);
+ free(host);
+ return fd;
+}
diff --git a/src/util/socket-utils.h b/src/util/socket-utils.h
new file mode 100644
index 0000000..3a9a825
--- /dev/null
+++ b/src/util/socket-utils.h
@@ -0,0 +1,66 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef wpantund_socket_utils_h
+#define wpantund_socket_utils_h
+
+#include <stdbool.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+
+#define SOCKET_SYSTEM_COMMAND_PREFIX "system:"
+#define SOCKET_FD_COMMAND_PREFIX "fd:"
+#define SOCKET_FILE_COMMAND_PREFIX "file:"
+#define SOCKET_SERIAL_COMMAND_PREFIX "serial:"
+#define SOCKET_TCP_COMMAND_PREFIX "tcp:"
+#define SOCKET_SYSTEM_FORKPTY_COMMAND_PREFIX "system-forkpty:"
+#define SOCKET_SYSTEM_SOCKETPAIR_COMMAND_PREFIX "system-socketpair:"
+
+#ifndef SOCKET_UTILS_DEFAULT_SHELL
+#define SOCKET_UTILS_DEFAULT_SHELL "/bin/sh"
+#endif
+
+__BEGIN_DECLS
+extern int gSocketWrapperBaud;
+bool socket_name_is_device(const char* socket_name);
+int lookup_sockaddr_from_host_and_port( struct sockaddr_in6* outaddr, const char* host, const char* port);
+int open_super_socket(const char* socket_name);
+int close_super_socket(int fd);
+int fd_has_error(int fd);
+
+enum {
+ SUPER_SOCKET_TYPE_UNKNOWN,
+ SUPER_SOCKET_TYPE_SYSTEM,
+ SUPER_SOCKET_TYPE_SYSTEM_FORKPTY,
+ SUPER_SOCKET_TYPE_SYSTEM_SOCKETPAIR,
+ SUPER_SOCKET_TYPE_FD,
+ SUPER_SOCKET_TYPE_TCP,
+ SUPER_SOCKET_TYPE_DEVICE
+};
+
+int get_super_socket_type_from_path(const char* path);
+
+int fork_unixdomain_socket(int* fd_pointer);
+
+__END_DECLS
+
+
+#endif
diff --git a/src/util/string-utils.c b/src/util/string-utils.c
new file mode 100644
index 0000000..d3f13c3
--- /dev/null
+++ b/src/util/string-utils.c
@@ -0,0 +1,299 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * This file defines utility functions for manipulating and comparing
+ * C-strings or other buffers.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include "string-utils.h"
+#include <ctype.h>
+#include <inttypes.h>
+#include <stdlib.h>
+
+#define __USE_GNU // Needed for `strcasestr`
+#include <string.h>
+
+void
+memcpyrev(void *dest_, const void *src_, size_t len)
+{
+ uint8_t* const dest = dest_;
+ const uint8_t* const src = src_;
+ int i;
+
+ for (i = 0; i < len; i++) {
+ dest[i] = src[len - 1 - i];
+ }
+}
+
+int
+memcmprev(const void *dest_, const void *src_, size_t len)
+{
+ const uint8_t* const dest = dest_;
+ const uint8_t* const src = src_;
+ int ret = 0;
+ int i;
+
+ for (i = 0; i < len && !ret; i++) {
+ ret = dest[i] - src[len - 1 - i];
+ }
+ return ret;
+}
+
+void
+reverse_bytes(uint8_t *bytes, size_t count)
+{
+ int i;
+
+ for (i = 0; i < count / 2; i++) {
+ uint8_t x = bytes[i];
+ bytes[i] = bytes[count - i - 1];
+ bytes[count - i - 1] = x;
+ }
+}
+
+int
+parse_string_into_data(uint8_t* buffer, size_t len, const char* c_str)
+{
+ int ret = 0;
+
+ if (NULL == buffer) {
+ len = 0;
+ }
+
+ while (*c_str != 0) {
+ char c = tolower(*c_str++);
+ if (!(isdigit(c) || (c >= 'a' && c <= 'f'))) {
+ continue;
+ }
+ c = isdigit(c) ? (c - '0') : (c - 'a' + 10);
+ if (len > 0) {
+ *buffer = (c << 4);
+ len--;
+ }
+ ret++;
+ if (!*c_str) {
+ break;
+ }
+ c = tolower(*c_str++);
+ if (!(isdigit(c) || (c >= 'a' && c <= 'f'))) {
+ continue;
+ }
+ c = isdigit(c) ? (c - '0') : (c - 'a' + 10);
+ *buffer++ |= c;
+ }
+
+ return ret;
+}
+
+int
+encode_data_into_string(
+ const uint8_t* buffer,
+ size_t len,
+ char* c_str,
+ size_t c_str_max_len,
+ int pad_to
+ ) {
+ int ret = 0;
+
+ c_str_max_len--;
+ while (len && (c_str_max_len > 4)) {
+ uint8_t byte = *buffer++;
+ len--;
+ pad_to--;
+ *c_str++ = int_to_hex_digit(byte >> 4);
+ *c_str++ = int_to_hex_digit(byte & 0xF);
+ c_str_max_len -= 2;
+ ret += 2;
+ }
+
+ while (pad_to > 0 && (c_str_max_len > 4)) {
+ pad_to--;
+ *c_str++ = '0';
+ *c_str++ = '0';
+ c_str_max_len -= 2;
+ ret += 2;
+ }
+
+ c_str_max_len--;
+ *c_str++ = 0;
+ return ret;
+}
+
+bool
+strtobool(const char* string)
+{
+ bool ret = false;
+ switch(string[0]) {
+ case 'y':
+ case 'Y':
+ case 't':
+ case 'T':
+ ret = true;
+ break;
+
+ case 'n':
+ case 'N':
+ case 'f':
+ case 'F':
+ ret = false;
+ break;
+
+ default:
+ ret = (strtol(string, NULL, 0) != 0);
+ break;
+ }
+ return ret;
+}
+
+uint32_t
+strtomask_uint32(const char* in_string)
+{
+ char *tmp_string = strdup(in_string);
+ char *chan_ranges; // points to a channel num or a range of channels
+ char *dash_location; // points to location of the dash in a range of channels
+ uint8_t channel_start = 0;
+ uint8_t channel_stop = 0;
+ uint32_t mask = 0;
+
+ chan_ranges = strtok(tmp_string, ",");
+ while(chan_ranges != NULL) {
+ // loop to parse channels by comma (,)
+ // each fragment may include a range (-) of channels
+
+ dash_location = strchr(chan_ranges, '-');
+ if (dash_location != NULL) {
+ // process a range of channels
+ *dash_location = '\0';
+ dash_location++;
+ if (atoi(chan_ranges) < atoi(dash_location)) {
+ channel_start = atoi(chan_ranges);
+ channel_stop = atoi(dash_location);
+ } else {
+ channel_stop = atoi(chan_ranges);
+ channel_start = atoi(dash_location);
+ }
+
+ while (channel_start <= channel_stop) {
+ mask |= (1 << channel_start);
+ channel_start++;
+ }
+ } else {
+ // no range, just add channel to the scan mask
+
+ mask |= (1 << strtol(chan_ranges, NULL, 0));
+ }
+ chan_ranges = strtok(NULL, ",");
+ }
+ free(tmp_string);
+ return mask;
+}
+
+#include <syslog.h>
+
+int
+strtologmask(const char* value, int prev_mask)
+{
+ int mask = (int)strtol(value, NULL, 0);
+
+ if (mask == 0) {
+ mask = prev_mask;
+
+ if(strcasestr(value, "all") != NULL) {
+ if (strcasestr(value, "-all") != NULL) {
+ mask &= 0;
+ } else {
+ mask |= ~0;
+ }
+ }
+ if (strcasestr(value, "emerg") != NULL) {
+ if (strcasestr(value, "-emerg") != NULL) {
+ mask &= ~LOG_MASK(LOG_EMERG);
+ } else {
+ mask |= LOG_MASK(LOG_EMERG);
+ }
+ }
+ if (strcasestr(value, "alert") != NULL) {
+ if (strcasestr(value, "-alert") != NULL) {
+ mask &= ~LOG_MASK(LOG_ALERT);
+ } else {
+ mask |= LOG_MASK(LOG_ALERT);
+ }
+ }
+ if (strcasestr(value, "crit") != NULL) {
+ if (strcasestr(value, "-crit") != NULL) {
+ mask &= ~LOG_MASK(LOG_CRIT);
+ } else {
+ mask |= LOG_MASK(LOG_CRIT);
+ }
+ }
+ if (strcasestr(value, "err") != NULL) {
+ if (strcasestr(value, "-err") != NULL) {
+ mask &= ~LOG_MASK(LOG_ERR);
+ } else {
+ mask |= LOG_MASK(LOG_ERR);
+ }
+ }
+ if (strcasestr(value, "warn") != NULL) {
+ if (strcasestr(value, "-warn") != NULL) {
+ mask &= ~LOG_MASK(LOG_WARNING);
+ } else {
+ mask |= LOG_MASK(LOG_WARNING);
+ }
+ }
+ if (strcasestr(value, "notice") != NULL) {
+ if (strcasestr(value, "-notice") != NULL) {
+ mask &= ~LOG_MASK(LOG_NOTICE);
+ } else {
+ mask |= LOG_MASK(LOG_NOTICE);
+ }
+ }
+ if (strcasestr(value, "info") != NULL) {
+ if (strcasestr(value, "-info") != NULL) {
+ mask &= ~LOG_MASK(LOG_INFO);
+ } else {
+ mask |= LOG_MASK(LOG_INFO);
+ }
+ }
+ if (strcasestr(value, "debug") != NULL) {
+ if (strcasestr(value, "-debug") != NULL) {
+ mask &= ~LOG_MASK(LOG_DEBUG);
+ } else {
+ mask |= LOG_MASK(LOG_DEBUG);
+ }
+ }
+ }
+
+ return mask;
+}
+
+bool
+buffer_is_nonzero(const uint8_t* buffer, size_t len)
+{
+ while (len--) {
+ if (*buffer++ != 0) {
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/src/util/string-utils.h b/src/util/string-utils.h
new file mode 100644
index 0000000..528fbd2
--- /dev/null
+++ b/src/util/string-utils.h
@@ -0,0 +1,58 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * This file declares utility functions for manipulating and comparing
+ * C-strings or other buffers.
+ *
+ */
+
+#ifndef wpantund_string_utils_h
+#define wpantund_string_utils_h
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <sys/cdefs.h>
+
+#define strcaseequal(x, y) (strcasecmp(x, y) == 0)
+#define strncaseequal(x, y, n) (strncasecmp(x, y, n) == 0)
+#define strequal(x, y) (strcmp(x, y) == 0)
+#define strnequal(x, y, n) (strncmp(x, y, n) == 0)
+
+__BEGIN_DECLS
+extern void memcpyrev(void* dest, const void *src, size_t len);
+extern int memcmprev(const void* dest, const void *src, size_t len);
+extern void reverse_bytes(uint8_t *bytes, size_t count);
+extern int parse_string_into_data(uint8_t* buffer, size_t len, const char* c_str);
+extern int encode_data_into_string(const uint8_t* buffer, size_t len, char* c_str, size_t c_str_max_len, int pad_to);
+extern int strtologmask(const char* value, int prev_mask);
+extern bool buffer_is_nonzero(const uint8_t* buffer, size_t len);
+
+static inline char
+int_to_hex_digit(uint8_t x)
+{
+ return "0123456789ABCDEF"[x & 0xF];
+}
+
+uint32_t strtomask_uint32(const char* in_string);
+
+extern bool strtobool(const char* string);
+
+__END_DECLS
+
+#endif
diff --git a/src/util/time-utils.c b/src/util/time-utils.c
new file mode 100644
index 0000000..40c4bd7
--- /dev/null
+++ b/src/util/time-utils.c
@@ -0,0 +1,70 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "time-utils.h"
+#include <sys/time.h>
+
+cms_t
+time_ms(void)
+{
+#if HAVE_CLOCK_GETTIME
+ struct timespec tv = { 0 };
+ int ret;
+
+ ret = clock_gettime(CLOCK_MONOTONIC, &tv);
+
+ return (cms_t)(tv.tv_sec * MSEC_PER_SEC) + (cms_t)(tv.tv_nsec / NSEC_PER_MSEC);
+#else
+ struct timeval tv = { 0 };
+ gettimeofday(&tv, NULL);
+ return (cms_t)(tv.tv_sec * MSEC_PER_SEC) + (cms_t)(tv.tv_usec / USEC_PER_MSEC);
+#endif
+}
+
+time_t
+time_get_monotonic(void)
+{
+#if HAVE_CLOCK_GETTIME
+ struct timespec ts;
+ int ret;
+
+ ret = clock_gettime(CLOCK_MONOTONIC, &ts);
+
+ return ret == 0 ? ts.tv_sec : 0;
+#else
+ return time(NULL);
+#endif // !__linux__
+}
+
+cms_t
+cms_until_time(time_t time)
+{
+ time -= time_get_monotonic();
+
+ if (time > (TIME_DISTANT_FUTURE / MSEC_PER_SEC)) {
+ // Overflow.
+ return CMS_DISTANT_FUTURE;
+ }
+
+ return (cms_t)(time * MSEC_PER_SEC);
+}
diff --git a/src/util/time-utils.h b/src/util/time-utils.h
new file mode 100644
index 0000000..0dcae86
--- /dev/null
+++ b/src/util/time-utils.h
@@ -0,0 +1,66 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef wpantund_timeutils_h
+#define wpantund_timeutils_h
+
+#ifndef __STDC_CONSTANT_MACROS
+#define __STDC_CONSTANT_MACROS 1
+#endif
+
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <sys/cdefs.h>
+#include <time.h>
+
+#ifndef MSEC_PER_SEC
+#define MSEC_PER_SEC 1000
+#endif
+
+#ifndef USEC_PER_MSEC
+#define USEC_PER_MSEC 1000
+#endif
+
+#ifndef NSEC_PER_MSEC
+#define NSEC_PER_MSEC 1000000
+#endif
+
+#ifndef CMS_DISTANT_FUTURE
+#define CMS_DISTANT_FUTURE INT32_MAX
+#endif
+
+#ifndef TIME_DISTANT_FUTURE
+#define TIME_DISTANT_FUTURE INTPTR_MAX
+#endif
+
+#define CMS_SINCE(x) (time_ms() - (x))
+
+__BEGIN_DECLS
+typedef int32_t cms_t;
+
+extern cms_t time_ms(void);
+extern time_t time_get_monotonic(void);
+extern cms_t cms_until_time(time_t time);
+__END_DECLS
+
+#endif
diff --git a/src/util/tunnel.c b/src/util/tunnel.c
new file mode 100644
index 0000000..e503981
--- /dev/null
+++ b/src/util/tunnel.c
@@ -0,0 +1,644 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * This file implements the code which managed the TUN interface.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef ASSERT_MACROS_USE_SYSLOG
+#define ASSERT_MACROS_USE_SYSLOG 1
+#endif
+
+#include "assert-macros.h"
+#include "pt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "tunnel.h"
+#include <syslog.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#ifndef __APPLE__
+#include <linux/if_tun.h>
+#endif
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <net/route.h> // AF_ROUTE things
+
+#ifdef __APPLE__
+#include <netinet6/in6_var.h>
+#include <netinet6/nd6.h> // ND6_INFINITE_LIFETIME
+#include <net/if_dl.h> // struct sockaddr_dl
+#include <net/if_utun.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/kern_control.h>
+#include <sys/ioctl.h>
+#include <sys/sys_domain.h>
+#include <sys/kern_event.h>
+#define IFEF_NOAUTOIPV6LL 0x2000 /* Interface IPv6 LinkLocal address not provided by kernel */
+#endif
+
+#ifndef TUNNEL_TUNTAP_DEVICE
+#define TUNNEL_TUNTAP_DEVICE "/dev/net/tun"
+#endif
+
+int
+tunnel_open(const char* tun_name)
+{
+ int fd = -1;
+ char *device = NULL;
+
+ if ((tun_name == NULL) || (tun_name[0] == 0)) {
+ tun_name = TUNNEL_DEFAULT_INTERFACE_NAME;
+ }
+
+ syslog(LOG_INFO, "Opening tun interface socket with name \"%s\"", tun_name);
+
+#if defined(UTUN_CONTROL_NAME)
+ int error = 0;
+ fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
+ struct sockaddr_ctl addr;
+
+ /* get/set the id */
+ struct ctl_info info;
+ memset(&info, 0, sizeof(info));
+ strncpy(info.ctl_name, UTUN_CONTROL_NAME, strlen(UTUN_CONTROL_NAME));
+ error = ioctl(fd, CTLIOCGINFO, &info);
+
+ if (error) {
+ syslog(LOG_ERR, "Failed to open utun interface: %s", strerror(errno));
+ close(fd);
+ fd = -1;
+ goto bail;
+ }
+
+ addr.sc_id = info.ctl_id;
+ addr.sc_len = sizeof(addr);
+ addr.sc_family = AF_SYSTEM;
+ addr.ss_sysaddr = AF_SYS_CONTROL;
+ addr.sc_unit = 0; /* allocate dynamically */
+
+ if (strncmp(tun_name, "utun", 4) == 0)
+ addr.sc_unit = (int)strtol(tun_name + 4, NULL, 10) + 1;
+
+ error = connect(fd, (struct sockaddr*)&addr, sizeof(addr));
+
+ if (error && errno == EBUSY) {
+ addr.sc_unit = 0; /* allocate dynamically */
+ error = connect(fd, (struct sockaddr*)&addr, sizeof(addr));
+ }
+
+ if (error) {
+ syslog(LOG_ERR, "Failed to open tun interface: %s", strerror(errno));
+ close(fd);
+ fd = -1;
+ goto bail;
+ }
+
+ tunnel_bring_offline(fd);
+
+ goto bail;
+
+#else
+
+#ifdef __APPLE__
+ if (strncmp(tun_name, "utun", 4) == 0)
+ tun_name = "tun0";
+ asprintf(&device, "/dev/%s", tun_name);
+#else
+ device = strdup(TUNNEL_TUNTAP_DEVICE);
+#endif
+
+ require(NULL != device, bail);
+
+ fd = open(device, O_RDWR | O_NONBLOCK);
+
+ if (0 > fd) {
+ syslog(LOG_ERR, "Failed to open tun interface: %s", strerror(errno));
+ perror("open-tun");
+ goto bail;
+ }
+#endif
+
+#ifdef TUNSETIFF
+ struct ifreq ifr = { .ifr_flags = IFF_TUN | IFF_NO_PI };
+ strncpy(ifr.ifr_name, tun_name, IFNAMSIZ);
+
+ require(0 == ioctl(fd, TUNSETIFF, (void*)&ifr), bail);
+
+ // Verify that the name was set. If it wasn't
+ // we need to fail.
+ char name[20] = "";
+
+ if (tunnel_get_name(fd, name, sizeof(name)) != 0) {
+ syslog(LOG_ERR, "Unable to set name on tun interface: %s", strerror(errno));
+ perror("open-tun");
+ close(fd);
+ fd = -1;
+ goto bail;
+ }
+
+ if (name[0] == 0) {
+ syslog(LOG_ERR, "Unable to set name on tun interface");
+ close(fd);
+ fd = -1;
+ goto bail;
+ }
+
+#endif
+
+bail:
+ free(device);
+ return fd;
+}
+
+void
+tunnel_close(int fd)
+{
+ close(fd);
+}
+
+int
+tunnel_get_name(
+ int fd, char* name, int maxlen
+ )
+{
+ int ret = -1;
+
+ if (maxlen && name) name[0] = 0;
+#if defined(UTUN_CONTROL_NAME)
+ socklen_t len = maxlen;
+ if (0 == getsockopt(fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, name, &len)) {
+ ret = 0;
+ goto bail;
+ }
+#elif defined(TUNGETIFF)
+ struct ifreq ifr = { };
+ require(0 == ioctl(fd, TUNGETIFF, (void*)&ifr), bail);
+ strncpy(name, ifr.ifr_name, maxlen);
+#else
+ struct stat st;
+ ret = fstat(fd, &st);
+ if (ret) {
+ perror("tunnel_get_name: fstat failed.");
+ goto bail;
+ }
+ devname_r(st.st_rdev, S_IFCHR, name, (int)maxlen);
+#endif
+ ret = 0;
+bail:
+ return ret;
+}
+
+static int
+_tunnel_get_iff(
+ int fd, struct ifreq *ifr
+ )
+{
+ int ret = -1;
+
+ ret = tunnel_get_name(fd, ifr->ifr_name, sizeof(ifr->ifr_name));
+
+ return ret;
+}
+
+
+bool
+tunnel_is_online(int fd)
+{
+ bool ret = false;
+ int status = -1;
+ int reqfd = -1;
+ struct ifreq ifr = { };
+
+ /* get interface name */
+ _tunnel_get_iff(fd, &ifr);
+
+ reqfd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
+
+ status = ioctl(reqfd, SIOCGIFFLAGS, &ifr);
+ require_string(status == 0, bail, strerror(errno));
+
+ ret = ((ifr.ifr_flags & IFF_UP) == IFF_UP);
+
+bail:
+ close(reqfd);
+ return ret;
+}
+
+int
+tunnel_bring_online(int fd)
+{
+ int ret = -1;
+ int reqfd = -1;
+ struct ifreq ifr = { };
+
+ /* get interface name */
+ _tunnel_get_iff(fd, &ifr);
+
+ reqfd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
+
+ ret = ioctl(reqfd, SIOCGIFFLAGS, &ifr);
+ require_string(ret == 0, bail, strerror(errno));
+
+ ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
+ ret = ioctl(reqfd, SIOCSIFFLAGS, &ifr);
+ require_string(ret == 0, bail, strerror(errno));
+
+bail:
+ close(reqfd);
+ return ret;
+}
+
+int
+tunnel_bring_offline(int fd)
+{
+ int ret = -1;
+ int reqfd = -1;
+ struct ifreq ifr = { };
+
+ /* get interface name */
+ _tunnel_get_iff(fd, &ifr);
+
+ reqfd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
+
+ ret = ioctl(reqfd, SIOCGIFFLAGS, &ifr);
+ require_string(ret == 0, bail, strerror(errno));
+
+ ifr.ifr_flags &= ~(IFF_UP);
+ ret = ioctl(reqfd, SIOCSIFFLAGS, &ifr);
+ require_string(ret == 0, bail, strerror(errno));
+
+bail:
+ close(reqfd);
+ return ret;
+}
+
+int
+tunnel_set_mtu(
+ int fd, uint16_t mtu
+ )
+{
+ int ret = -1;
+ int reqfd = -1;
+ struct ifreq ifr = { };
+
+ /* get interface name */
+ _tunnel_get_iff(fd, &ifr);
+
+ reqfd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
+
+ ifr.ifr_mtu = mtu;
+
+ ret = ioctl(reqfd, SIOCSIFMTU, &ifr);
+
+ if (ret)
+ perror("tapdev: Uable to set MTU, call to ioctl failed.");
+
+ close(reqfd);
+ return ret;
+}
+#ifndef SIOCSIFLLADDR
+#define SIOCSIFLLADDR SIOCSIFHWADDR
+#endif
+
+
+static inline void
+apply_mask(
+ struct in6_addr *address, uint8_t mask
+ )
+{
+ // Coverty might complain in this function, but don't believe it.
+ // This code has been reviewed carefully and should not misbehave.
+
+ if (mask > 128) {
+ mask = 128;
+ }
+
+ memset(
+ (void*)(address->s6_addr + ((mask + 7) / 8)),
+ 0,
+ 16 - ((mask + 7) / 8)
+ );
+
+ if (mask % 8) {
+ address->s6_addr[mask / 8] &= ~(0xFF >> (mask % 8));
+ }
+}
+
+int
+tunnel_add_address(
+ int fd, const uint8_t addr[16], int prefixlen
+ )
+{
+ int ret = -1;
+ int reqfd = -1;
+
+ reqfd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
+
+#ifdef __APPLE__
+
+ /************* Add address *************/
+
+ struct in6_aliasreq addreq6 = { };
+
+ ret = tunnel_get_name(fd, addreq6.ifra_name, sizeof(addreq6.ifra_name));
+
+ if (ret) {
+ perror("tunnel_add_address: Uable to get interface name.");
+ goto bail;
+ }
+
+ addreq6.ifra_addr.sin6_family = AF_INET6;
+ addreq6.ifra_addr.sin6_len = sizeof(addreq6.ifra_addr);
+ memcpy((void*)&addreq6.ifra_addr.sin6_addr, addr, 16);
+
+ addreq6.ifra_prefixmask.sin6_family = AF_INET6;
+ addreq6.ifra_prefixmask.sin6_len = sizeof(addreq6.ifra_prefixmask);
+ memset((void*)&addreq6.ifra_prefixmask.sin6_addr, 0xFF, 16);
+ apply_mask(&addreq6.ifra_prefixmask.sin6_addr, prefixlen);
+
+ addreq6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
+ addreq6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
+ addreq6.ifra_lifetime.ia6t_expire = ND6_INFINITE_LIFETIME;
+ addreq6.ifra_lifetime.ia6t_preferred = ND6_INFINITE_LIFETIME;
+
+ addreq6.ifra_flags |= IN6_IFF_NODAD;
+
+ ret = ioctl(reqfd, SIOCAIFADDR_IN6, &addreq6);
+ if (ret && errno != EALREADY)
+ goto bail;
+
+#else
+
+ /* Linux */
+
+ // In linux, we need to remove the address first.
+ tunnel_remove_address(fd, addr);
+
+#define ifreq_offsetof(x) offsetof(struct ifreq, x)
+
+ struct in6_ifreq {
+ struct in6_addr ifr6_addr;
+ __u32 ifr6_prefixlen;
+ unsigned int ifr6_ifindex;
+ };
+
+ struct ifreq ifr = { };
+ struct sockaddr_in6 sai;
+ int sockfd;
+ struct in6_ifreq ifr6;
+
+ /* get interface name */
+ _tunnel_get_iff(fd, &ifr);
+
+ memset(&sai, 0, sizeof(struct sockaddr));
+ sai.sin6_family = AF_INET6;
+ sai.sin6_port = 0;
+
+ memcpy((void*)&sai.sin6_addr, addr, 16);
+
+ memcpy((char*)&ifr6.ifr6_addr, (char*)&sai.sin6_addr,
+ sizeof(struct in6_addr));
+
+ if (ioctl(reqfd, SIOGIFINDEX, &ifr) < 0)
+ perror("SIOGIFINDEX");
+ ifr6.ifr6_ifindex = ifr.ifr_ifindex;
+ ifr6.ifr6_prefixlen = 64;
+ ret = ioctl(reqfd, SIOCSIFADDR, &ifr6);
+ if (ret && errno != EALREADY)
+ goto bail;
+ ret = 0;
+
+#endif
+ ret = 0;
+bail:
+ if (ret) {
+ syslog(LOG_INFO, "tunnel_add_address: errno=%d (%s)", errno, strerror(errno));
+ }
+ if (reqfd >= 0)
+ close(reqfd);
+
+ return ret;
+}
+
+int
+tunnel_remove_address(
+ int fd, const uint8_t addr[16]
+ )
+{
+ int ret = -1;
+
+ int reqfd = -1;
+
+ reqfd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
+
+ struct sockaddr_in6 sai = { };
+
+ memset(&sai, 0, sizeof(struct sockaddr));
+ sai.sin6_family = AF_INET6;
+ sai.sin6_port = 0;
+ memcpy((void*)&sai.sin6_addr, addr, 16);
+
+ /************* Remove address *************/
+
+#ifdef __APPLE__
+ sai.sin6_len = sizeof(sai);
+
+
+ struct in6_ifreq ifreq6 = { };
+ ret = tunnel_get_name(fd, ifreq6.ifr_name, sizeof(ifreq6.ifr_name));
+
+ if (ret)
+ goto bail;
+
+ ifreq6.ifr_addr = sai;
+
+ if (-1 == ioctl(reqfd, SIOCDIFADDR_IN6, &ifreq6)) {
+ ret = -errno;
+ goto bail;
+ }
+
+#else
+ int ifindex = 0;
+ {
+ struct ifreq ifr = { };
+
+ /* get interface name */
+ _tunnel_get_iff(fd, &ifr);
+
+ if (ioctl(reqfd, SIOGIFINDEX, &ifr) < 0)
+ perror("SIOGIFINDEX");
+
+ ifindex = ifr.ifr_ifindex;
+ }
+
+ struct in6_ifreq {
+ struct in6_addr ifr6_addr;
+ __u32 ifr6_prefixlen;
+ unsigned int ifr6_ifindex;
+ };
+
+ struct in6_ifreq ifr6;
+
+ ifr6.ifr6_addr = sai.sin6_addr;
+ ifr6.ifr6_ifindex = ifindex;
+ ifr6.ifr6_prefixlen = 64;
+
+ if (ioctl(reqfd, SIOCDIFADDR, &ifr6) < 0) {
+ ret = -errno;
+ goto bail;
+ }
+#endif
+ ret = 0;
+
+bail:
+ if (reqfd >= 0)
+ close(reqfd);
+
+ return ret;
+}
+
+
+int
+tunnel_add_route(
+ int fd, const uint8_t route[16], int prefixlen
+ )
+{
+ int ret = -1;
+ int reqfd = -1;
+
+ reqfd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
+
+#ifdef __APPLE__
+
+ /************* Add ROUTE TODO *************/
+
+#else
+ /* Linux */
+
+ struct ifreq ifr;
+ struct in6_rtmsg rt;
+
+ memset(&ifr, 0, sizeof(struct ifreq));
+
+ /* get interface name */
+ _tunnel_get_iff(fd, &ifr);
+
+ memset(&rt, 0, sizeof(struct in6_rtmsg));
+ memcpy(rt.rtmsg_dst.s6_addr, route, sizeof(struct in6_addr));
+ rt.rtmsg_dst_len = prefixlen;
+ rt.rtmsg_flags = RTF_UP;
+ if (prefixlen == 128) {
+ rt.rtmsg_flags |= RTF_HOST;
+ }
+ rt.rtmsg_metric = 512;
+
+ if (ioctl(reqfd, SIOGIFINDEX, &ifr) < 0)
+ perror("SIOGIFINDEX");
+
+ rt.rtmsg_ifindex = ifr.ifr_ifindex;
+
+ ret = ioctl(reqfd, SIOCADDRT, &rt);
+ if (ret && errno != EALREADY && errno != EEXIST)
+ goto bail;
+
+#endif
+
+ ret = 0;
+bail:
+ if (ret) {
+ syslog(LOG_INFO, "tunnel_add_route: errno=%d (%s)", errno, strerror(errno));
+ }
+ if (reqfd >= 0)
+ close(reqfd);
+
+ return ret;
+}
+
+int
+tunnel_remove_route(
+ int fd, const uint8_t route[16], int prefixlen
+ )
+{
+ int ret = -1;
+ int reqfd = -1;
+
+ reqfd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP);
+
+#ifdef __APPLE__
+
+ /************* Remove ROUTE TODO *************/
+
+#else
+ /* Linux */
+
+ struct ifreq ifr;
+ struct in6_rtmsg rt;
+
+ memset(&ifr, 0, sizeof(struct ifreq));
+
+ /* get interface name */
+ _tunnel_get_iff(fd, &ifr);
+
+ memset(&rt, 0, sizeof(struct in6_rtmsg));
+ memcpy(rt.rtmsg_dst.s6_addr, route, sizeof(struct in6_addr));
+ rt.rtmsg_dst_len = prefixlen;
+ rt.rtmsg_flags = RTF_UP;
+ if (prefixlen == 128) {
+ rt.rtmsg_flags |= RTF_HOST;
+ }
+ rt.rtmsg_metric = 512;
+
+ if (ioctl(reqfd, SIOGIFINDEX, &ifr) < 0)
+ perror("SIOGIFINDEX");
+
+ rt.rtmsg_ifindex = ifr.ifr_ifindex;
+
+ ret = ioctl(reqfd, SIOCDELRT, &rt);
+ if (ret && errno != EALREADY && errno != EEXIST)
+ goto bail;
+
+#endif
+
+ ret = 0;
+bail:
+ if (ret) {
+ syslog(LOG_INFO, "tunnel_remove_route: errno=%d (%s)", errno, strerror(errno));
+ }
+ if (reqfd >= 0)
+ close(reqfd);
+
+ return ret;
+}
diff --git a/src/util/tunnel.h b/src/util/tunnel.h
new file mode 100644
index 0000000..64ecd57
--- /dev/null
+++ b/src/util/tunnel.h
@@ -0,0 +1,59 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * This file implements the code which managed the TUN interface.
+ *
+ */
+
+
+#ifndef wpantund_tunnel_h
+#define wpantund_tunnel_h
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __APPLE__
+#define TUNNEL_DEFAULT_INTERFACE_NAME "utun2"
+#else
+#define TUNNEL_DEFAULT_INTERFACE_NAME "wpan0"
+#endif
+
+#define TUNNEL_MAX_INTERFACE_NAME_LEN 60
+
+__BEGIN_DECLS
+extern int tunnel_open(const char* tun_name);
+extern int tunnel_get_name(
+ int fd, char* name, int maxlen);
+extern int tunnel_set_mtu(
+ int fd, uint16_t mtu);
+extern int tunnel_add_address(
+ int fd, const uint8_t addr[16], int prefixlen);
+extern int tunnel_remove_address(
+ int fd, const uint8_t addr[16]);
+extern void tunnel_close(int fd);
+extern int tunnel_bring_online(int fd);
+extern int tunnel_bring_offline(int fd);
+extern bool tunnel_is_online(int fd);
+extern int tunnel_add_route(
+ int fd, const uint8_t route[16], int prefixlen);
+extern int tunnel_remove_route(
+ int fd, const uint8_t route[16], int prefixlen);
+__END_DECLS
+
+
+#endif
diff --git a/src/version.c.in b/src/version.c.in
new file mode 100644
index 0000000..dcefa39
--- /dev/null
+++ b/src/version.c.in
@@ -0,0 +1,26 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "version.h"
+
+const char *internal_build_source_version = SOURCE_VERSION;
+const char *internal_build_date = __DATE__ " " __TIME__;
diff --git a/src/version.h b/src/version.h
new file mode 100644
index 0000000..be8524c
--- /dev/null
+++ b/src/version.h
@@ -0,0 +1,29 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef INTERNAL_VERSION_H__
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+extern const char *internal_build_source_version;
+extern const char *internal_build_date;
+__END_DECLS
+
+#endif // INTERNAL_VERSION_H__
diff --git a/src/wpanctl/Makefile.am b/src/wpanctl/Makefile.am
new file mode 100644
index 0000000..95c1972
--- /dev/null
+++ b/src/wpanctl/Makefile.am
@@ -0,0 +1,100 @@
+#
+# Copyright (c) 2016 Nest Labs, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/src/ipc-dbus \
+ -I$(top_srcdir)/src/util \
+ -I$(top_srcdir)/src/wpantund \
+ -I$(top_srcdir)/third_party/fgetln \
+ -I$(top_srcdir)/third_party/assert-macros \
+ $(NULL)
+
+DISTCLEANFILES = .deps Makefile
+
+bin_PROGRAMS = wpanctl
+
+wpanctl_SOURCES = \
+ wpanctl.c \
+ wpanctl-cmds.h \
+ ../util/config-file.c \
+ ../util/string-utils.c \
+ wpanctl-utils.c \
+ tool-cmd-scan.c \
+ tool-cmd-join.c \
+ tool-cmd-form.c \
+ tool-cmd-mfg.c \
+ tool-cmd-leave.c \
+ tool-cmd-permit-join.c \
+ tool-cmd-list.c \
+ tool-cmd-status.c \
+ tool-cmd-resume.c \
+ tool-cmd-reset.c \
+ tool-cmd-getprop.c \
+ tool-cmd-setprop.c \
+ tool-cmd-begin-low-power.c \
+ tool-cmd-begin-net-wake.c \
+ tool-cmd-cd.c \
+ tool-cmd-poll.c \
+ tool-cmd-config-gateway.c \
+ tool-cmd-host-did-wake.c \
+ tool-cmd-add-route.c \
+ tool-cmd-remove-route.c \
+ wpanctl-utils.h \
+ tool-cmd-scan.h \
+ tool-cmd-join.h \
+ tool-cmd-form.h \
+ tool-cmd-leave.h \
+ tool-cmd-mfg.h \
+ tool-cmd-permit-join.h \
+ tool-cmd-list.h \
+ tool-cmd-status.h \
+ tool-cmd-resume.h \
+ tool-cmd-reset.h \
+ tool-cmd-getprop.h \
+ tool-cmd-setprop.h \
+ tool-cmd-begin-low-power.h \
+ tool-cmd-begin-net-wake.h \
+ tool-cmd-cd.h \
+ tool-cmd-poll.h \
+ tool-cmd-config-gateway.h \
+ tool-cmd-host-did-wake.h \
+ tool-cmd-add-route.h \
+ tool-cmd-remove-route.h \
+ tool-cmd-pcap.h \
+ tool-cmd-pcap.c \
+ $(NULL)
+
+wpanctl_LDADD = \
+ $(DBUS_LIBS) \
+ $(LIBREADLINE_LIBS) \
+ $(NULL)
+
+wpanctl_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ $(DBUS_CFLAGS) \
+ $(LIBREADLINE_CPPFLAGS) \
+ $(NULL)
+
+
+SOURCE_VERSION=$(shell git describe --dirty --always --match "[0-9].*" 2> /dev/null)
+BUILT_SOURCES = $(top_builddir)/$(subdir)/version.c
+CLEANFILES = $(top_builddir)/$(subdir)/version.c
+.INTERMEDIATE: wpanctl-version.$(OBJEXT)
+$(top_builddir)/$(subdir)/version.c: ../version.c.in Makefile
+ sed 's/SOURCE_VERSION/"$(SOURCE_VERSION)"/' < $< > $@
+wpanctl_SOURCES += $(top_builddir)/$(subdir)/version.c
diff --git a/src/wpanctl/tool-cmd-add-route.c b/src/wpanctl/tool-cmd-add-route.c
new file mode 100644
index 0000000..c615c2f
--- /dev/null
+++ b/src/wpanctl/tool-cmd-add-route.c
@@ -0,0 +1,258 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * This file implements "add-route" command in wpanctl.
+ *
+ */
+
+#include <getopt.h>
+#include "wpanctl-utils.h"
+#include "tool-cmd-add-route.h"
+#include "assert-macros.h"
+#include "args.h"
+#include "assert-macros.h"
+#include "wpan-dbus-v1.h"
+#include "string-utils.h"
+
+#include <arpa/inet.h>
+#include <errno.h>
+
+const char add_route_cmd_syntax[] = "[args] <prefix>";
+
+static const arg_list_item_t add_route_option_list[] = {
+ {'h', "help", NULL, "Print Help"},
+ {'p', "priority", "(>0 for high, 0 for medium, <0 for low)", "Assign route priority"},
+ {'l', "length", "in bytes", "Specifies the route prefix length (default is 8)"},
+ {'d', "domain", NULL, "Domain id for the route (default is zero)"},
+ {0}
+};
+
+int tool_cmd_add_route(int argc, char* argv[])
+{
+ int ret = 0;
+ int c;
+ int timeout = DEFAULT_TIMEOUT_IN_SECONDS * 1000;
+
+ DBusConnection* connection = NULL;
+ DBusMessage *message = NULL;
+ DBusMessage *reply = NULL;
+ DBusError error;
+
+ const char *route_prefix = NULL;
+ int prefix_len = 8;
+ int16_t priority = 0;
+ uint16_t domain_id = 0;
+
+ dbus_error_init(&error);
+
+ while (1) {
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"priority", required_argument, 0, 'p'},
+ {"length", required_argument, 0, 'l'},
+ {"domain", required_argument, 0, 'd'},
+ {0, 0, 0, 0}
+ };
+
+ int option_index = 0;
+ c = getopt_long(argc, argv, "hp:l:d:", long_options,
+ &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_arg_list_help(add_route_option_list, argv[0],
+ add_route_cmd_syntax);
+ ret = ERRORCODE_HELP;
+ goto bail;
+
+ case 'p':
+ priority = (int16_t) strtol(optarg, NULL, 0);
+ break;
+
+ case 'l' :
+ prefix_len = (int) strtol(optarg, NULL, 0);
+ break;
+
+ case 'd':
+ domain_id = (uint16_t) strtol(optarg, NULL, 0);
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ route_prefix = argv[optind];
+ optind++;
+ }
+
+ if (optind < argc) {
+ fprintf(stderr,
+ "%s: error: Unexpected extra argument: \"%s\"\n",
+ argv[0], argv[optind]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ if (gInterfaceName[0] == 0) {
+ fprintf(stderr,
+ "%s: error: No WPAN interface set (use the `cd` command, or the `-I` argument for `wpanctl`).\n",
+ argv[0]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
+
+ if (!connection) {
+ dbus_error_free(&error);
+ dbus_error_init(&error);
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ }
+
+ require_string(connection != NULL, bail, error.message);
+
+ {
+ DBusMessageIter iter;
+ DBusMessageIter list_iter;
+ char path[DBUS_MAXIMUM_NAME_LENGTH+1];
+ char interface_dbus_name[DBUS_MAXIMUM_NAME_LENGTH+1];
+ ret = lookup_dbus_name_from_interface(interface_dbus_name, gInterfaceName);
+ if (ret != 0) {
+ goto bail;
+ }
+ snprintf(path,
+ sizeof(path),
+ "%s/%s",
+ WPANTUND_DBUS_PATH,
+ gInterfaceName);
+
+ message = dbus_message_new_method_call(
+ interface_dbus_name,
+ path,
+ WPANTUND_DBUS_APIv1_INTERFACE,
+ WPANTUND_IF_CMD_ROUTE_ADD
+ );
+
+ if ((route_prefix != NULL) && (0 <= prefix_len) && (prefix_len <= 16)) {
+ uint8_t prefix_bytes[16];
+
+ memset(prefix_bytes, 0, sizeof(prefix_bytes));
+
+ // So the prefix could either be
+ // specified like an IPv6 address, or
+ // specified as a bunch of hex numbers.
+ // We use the presence of a colon (':')
+ // to differentiate.
+ if (strstr(route_prefix, ":")) {
+
+ // Address-style
+ int bits = inet_pton(AF_INET6, route_prefix, prefix_bytes);
+ if (bits < 0) {
+ fprintf(stderr,
+ "Bad prefix \"%s\", errno=%d (%s)\n",
+ route_prefix,
+ errno,
+ strerror(errno));
+ goto bail;
+ } else if (bits == 0) {
+ fprintf(stderr, "Bad prefix \"%s\"\n", route_prefix);
+ goto bail;
+ }
+ } else {
+ // DATA-style
+ int length = parse_string_into_data(prefix_bytes,
+ 16,
+ route_prefix);
+ if(length<=0) {
+ fprintf(stderr, "Bad prefix \"%s\"\n", route_prefix);
+ goto bail;
+ }
+ }
+
+ fprintf(stderr, "Adding route prefix \"%s\" with len %d, priority \"%s\", domain-id %d.\n",
+ route_prefix, prefix_len,
+ (priority > 0)? "high" : ((priority < 0)? "low" : "medium"),
+ domain_id
+ );
+
+ uint8_t *addr = prefix_bytes;
+ uint8_t len = (uint8_t)prefix_len;
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &addr, len,
+ DBUS_TYPE_INVALID
+ );
+ } else {
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, "", 0,
+ DBUS_TYPE_INVALID
+ );
+ }
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_UINT16, &domain_id,
+ DBUS_TYPE_INT16, &priority,
+ DBUS_TYPE_INVALID
+ );
+
+ reply = dbus_connection_send_with_reply_and_block(
+ connection,
+ message,
+ timeout,
+ &error
+ );
+
+ if (!reply) {
+ fprintf(stderr, "%s: error: %s\n", argv[0], error.message);
+ ret = ERRORCODE_TIMEOUT;
+ goto bail;
+ }
+
+ dbus_message_get_args(reply, &error,
+ DBUS_TYPE_INT32, &ret,
+ DBUS_TYPE_INVALID
+ );
+
+ if (!ret) {
+ fprintf(stderr, "Route prefix added.\n");
+ } else {
+ fprintf(stderr, "%s failed with error %d. %s\n", argv[0], ret, wpantund_status_to_cstr(ret));
+ print_error_diagnosis(ret);
+ }
+ }
+
+bail:
+
+ if (connection)
+ dbus_connection_unref(connection);
+
+ if (message)
+ dbus_message_unref(message);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_error_free(&error);
+
+ return ret;
+}
diff --git a/src/wpanctl/tool-cmd-add-route.h b/src/wpanctl/tool-cmd-add-route.h
new file mode 100644
index 0000000..be200ec
--- /dev/null
+++ b/src/wpanctl/tool-cmd-add-route.h
@@ -0,0 +1,31 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * This file declares function related to "add-route" command
+ * in wpanctl.
+ *
+ */
+
+#ifndef WPANCTL_TOOL_CMD_ADD_ROUTE_H
+#define WPANCTL_TOOL_CMD_ADD_ROUTE_H
+
+#include "wpanctl-utils.h"
+
+int tool_cmd_add_route(int argc, char* argv[]);
+
+#endif
diff --git a/src/wpanctl/tool-cmd-begin-low-power.c b/src/wpanctl/tool-cmd-begin-low-power.c
new file mode 100644
index 0000000..7dc3250
--- /dev/null
+++ b/src/wpanctl/tool-cmd-begin-low-power.c
@@ -0,0 +1,168 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <getopt.h>
+#include "wpanctl-utils.h"
+#include "tool-cmd-begin-low-power.h"
+#include "assert-macros.h"
+#include "args.h"
+#include "assert-macros.h"
+#include "wpan-dbus-v1.h"
+
+const char begin_low_power_cmd_syntax[] = "[args]";
+
+static const arg_list_item_t begin_low_power_option_list[] = {
+ {'h', "help", NULL, "Print Help"},
+ {'t', "timeout", "ms", "Set timeout period"},
+ {0}
+};
+
+int tool_cmd_begin_low_power(int argc, char* argv[])
+{
+ int ret = 0;
+ int c;
+ int timeout = 30 * 1000;
+ DBusConnection* connection = NULL;
+ DBusMessage *message = NULL;
+ DBusMessage *reply = NULL;
+ DBusError error;
+
+ dbus_error_init(&error);
+
+ while (1) {
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"timeout", required_argument, 0, 't'},
+ {0, 0, 0, 0}
+ };
+
+ int option_index = 0;
+ c = getopt_long(argc, argv, "ht:", long_options, &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_arg_list_help(begin_low_power_option_list, argv[0],
+ begin_low_power_cmd_syntax);
+ ret = ERRORCODE_HELP;
+ goto bail;
+
+ case 't':
+ timeout = strtol(optarg, NULL, 0);
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ fprintf(stderr,
+ "%s: error: Unexpected extra argument: \"%s\"\n",
+ argv[0], argv[optind]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ if (gInterfaceName[0] == 0) {
+ fprintf(stderr,
+ "%s: error: No WPAN interface set (use the `cd` command, or the `-I` argument for `wpanctl`).\n",
+ argv[0]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
+
+ if (!connection) {
+ dbus_error_free(&error);
+ dbus_error_init(&error);
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ }
+
+ require_string(connection != NULL, bail, error.message);
+
+ {
+ DBusMessageIter iter;
+ DBusMessageIter list_iter;
+ char path[DBUS_MAXIMUM_NAME_LENGTH+1];
+ char interface_dbus_name[DBUS_MAXIMUM_NAME_LENGTH+1];
+ ret = lookup_dbus_name_from_interface(interface_dbus_name, gInterfaceName);
+ if (ret != 0) {
+ goto bail;
+ }
+ snprintf(path,
+ sizeof(path),
+ "%s/%s",
+ WPANTUND_DBUS_PATH,
+ gInterfaceName);
+
+ message = dbus_message_new_method_call(
+ interface_dbus_name,
+ path,
+ WPANTUND_DBUS_APIv1_INTERFACE,
+ WPANTUND_IF_CMD_BEGIN_LOW_POWER
+ );
+
+ fprintf(stderr, "Sending %s command. . .\n", WPANTUND_IF_CMD_BEGIN_LOW_POWER);
+
+ reply = dbus_connection_send_with_reply_and_block(
+ connection,
+ message,
+ timeout,
+ &error
+ );
+
+ if (!reply) {
+ fprintf(stderr, "%s: error: %s\n", argv[0], error.message);
+ ret = ERRORCODE_TIMEOUT;
+ goto bail;
+ }
+
+ dbus_message_get_args(reply, &error,
+ DBUS_TYPE_INT32, &ret,
+ DBUS_TYPE_INVALID
+ );
+ if (ret == 6)
+ ret = 0;
+
+ if (ret) {
+ fprintf(stderr, "%s failed with error %d. %s\n", argv[0], ret, wpantund_status_to_cstr(ret));
+ print_error_diagnosis(ret);
+ }
+ }
+
+bail:
+
+ if (connection)
+ dbus_connection_unref(connection);
+
+ if (message)
+ dbus_message_unref(message);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_error_free(&error);
+
+ return ret;
+}
diff --git a/src/wpanctl/tool-cmd-begin-low-power.h b/src/wpanctl/tool-cmd-begin-low-power.h
new file mode 100644
index 0000000..79bdc3f
--- /dev/null
+++ b/src/wpanctl/tool-cmd-begin-low-power.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef WPANCTL_TOOL_CMD_LURK_H
+#define WPANCTL_TOOL_CMD_LURK_H
+
+#include "wpanctl-utils.h"
+
+int tool_cmd_begin_low_power(int argc, char* argv[]);
+
+#endif
diff --git a/src/wpanctl/tool-cmd-begin-net-wake.c b/src/wpanctl/tool-cmd-begin-net-wake.c
new file mode 100644
index 0000000..405f11c
--- /dev/null
+++ b/src/wpanctl/tool-cmd-begin-net-wake.c
@@ -0,0 +1,186 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * This file...
+ *
+ */
+
+#include <getopt.h>
+#include "wpanctl-utils.h"
+#include "tool-cmd-begin-net-wake.h"
+#include "assert-macros.h"
+#include "args.h"
+#include "assert-macros.h"
+#include "wpan-dbus-v0.h"
+
+const char begin_net_wake_cmd_syntax[] = "[args] <data>";
+
+static const arg_list_item_t begin_net_wake_option_list[] = {
+ {'h', "help", NULL, "Print Help"},
+ {'t', "timeout", "ms", "Set timeout period"},
+ {0}
+};
+
+int tool_cmd_begin_net_wake(int argc, char *argv[])
+{
+ int ret = 0;
+ int c;
+ int timeout = DEFAULT_TIMEOUT_IN_SECONDS * 1000;
+ DBusConnection* connection = NULL;
+ DBusMessage *message = NULL;
+ DBusMessage *reply = NULL;
+ DBusError error;
+
+ bool has_net_wake_data = false;
+ uint8_t net_wake_data = 0;
+ uint32_t net_wake_flags = -1;
+
+ dbus_error_init(&error);
+
+ while (1) {
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"timeout", required_argument, 0, 't'},
+ {0, 0, 0, 0}
+ };
+
+ int option_index = 0;
+ c = getopt_long(argc, argv, "ht:", long_options, &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_arg_list_help(begin_net_wake_option_list,
+ argv[0], begin_net_wake_cmd_syntax);
+ ret = ERRORCODE_HELP;
+ goto bail;
+
+ case 't':
+ timeout = strtol(optarg, NULL, 0);
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ if (!has_net_wake_data) {
+ net_wake_data = strtol(argv[optind], NULL, 0);
+ has_net_wake_data = true;
+ optind++;
+ }
+ }
+
+ if (optind < argc) {
+ fprintf(stderr,
+ "%s: error: Unexpected extra argument: \"%s\"\n",
+ argv[0], argv[optind]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ if (gInterfaceName[0] == 0) {
+ fprintf(stderr,
+ "%s: error: No WPAN interface set (use the `cd` command, or the `-I` argument for `wpanctl`).\n",
+ argv[0]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
+
+ if (!connection) {
+ dbus_error_free(&error);
+ dbus_error_init(&error);
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ }
+
+ require_string(connection != NULL, bail, error.message);
+
+ {
+ DBusMessageIter iter;
+ DBusMessageIter list_iter;
+ char path[DBUS_MAXIMUM_NAME_LENGTH+1];
+ char interface_dbus_name[DBUS_MAXIMUM_NAME_LENGTH+1];
+ ret = lookup_dbus_name_from_interface(interface_dbus_name, gInterfaceName);
+ if (ret != 0) {
+ goto bail;
+ }
+ snprintf(path,
+ sizeof(path),
+ "%s/%s",
+ WPAN_TUNNEL_DBUS_PATH,
+ gInterfaceName);
+
+ message = dbus_message_new_method_call(
+ interface_dbus_name,
+ path,
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_IFACE_CMD_BEGIN_NET_WAKE
+ );
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_BYTE, &net_wake_data,
+ DBUS_TYPE_UINT32, &net_wake_flags,
+ DBUS_TYPE_INVALID
+ );
+
+ fprintf(stderr,
+ "Begin Net Wake, data = 0x%02X\n",
+ net_wake_data);
+
+ reply = dbus_connection_send_with_reply_and_block(
+ connection,
+ message,
+ timeout,
+ &error
+ );
+
+ if (!reply) {
+ fprintf(stderr, "%s: error: %s\n", argv[0], error.message);
+ ret = ERRORCODE_TIMEOUT;
+ goto bail;
+ }
+
+ dbus_message_get_args(reply, &error,
+ DBUS_TYPE_INT32, &ret,
+ DBUS_TYPE_INVALID
+ );
+
+ if (ret) {
+ fprintf(stderr, "%s failed with error %d. %s\n", argv[0], ret, (ret<0)?strerror(-ret):"");
+ print_error_diagnosis(ret);
+ }
+ }
+
+bail:
+
+ if (connection)
+ dbus_connection_unref(connection);
+
+ if (message)
+ dbus_message_unref(message);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_error_free(&error);
+
+ return ret;
+}
diff --git a/src/wpanctl/tool-cmd-begin-net-wake.h b/src/wpanctl/tool-cmd-begin-net-wake.h
new file mode 100644
index 0000000..0c09648
--- /dev/null
+++ b/src/wpanctl/tool-cmd-begin-net-wake.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef WPANCTL_TOOL_CMD_BEGIN_NET_WAKE_H
+#define WPANCTL_TOOL_CMD_BEGIN_NET_WAKE_H
+
+#include "wpanctl-utils.h"
+
+int tool_cmd_begin_net_wake(int argc, char* argv[]);
+
+#endif
diff --git a/src/wpanctl/tool-cmd-cd.c b/src/wpanctl/tool-cmd-cd.c
new file mode 100644
index 0000000..9c7d7b0
--- /dev/null
+++ b/src/wpanctl/tool-cmd-cd.c
@@ -0,0 +1,48 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "wpanctl-utils.h"
+#include "tool-cmd-cd.h"
+#include <string.h>
+
+int tool_cmd_cd(int argc, char* argv[])
+{
+ int ret = 0;
+
+ if ((2 == argc) && (0 == strcmp(argv[1], "--help"))) {
+ fprintf(stderr,
+ "%s: Help not yet implemented for this command.\n",
+ argv[0]);
+ ret = ERRORCODE_HELP;
+ }
+
+ if (argc == 1) {
+ printf("%s\n", gInterfaceName);
+ ret = ERRORCODE_HELP;
+ } else if (argc == 2) {
+ strncpy(gInterfaceName, argv[1], sizeof(gInterfaceName) - 1);
+ }
+
+bail:
+ return ret;
+}
diff --git a/src/wpanctl/tool-cmd-cd.h b/src/wpanctl/tool-cmd-cd.h
new file mode 100644
index 0000000..82959c2
--- /dev/null
+++ b/src/wpanctl/tool-cmd-cd.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef WPANCTL_TOOL_CMD_CD_H
+#define WPANCTL_TOOL_CMD_CD_H
+
+#include "wpanctl-utils.h"
+
+int tool_cmd_cd(int argc, char* argv[]);
+
+#endif
diff --git a/src/wpanctl/tool-cmd-config-gateway.c b/src/wpanctl/tool-cmd-config-gateway.c
new file mode 100644
index 0000000..2258cf2
--- /dev/null
+++ b/src/wpanctl/tool-cmd-config-gateway.c
@@ -0,0 +1,264 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <getopt.h>
+#include "wpanctl-utils.h"
+#include "tool-cmd-config-gateway.h"
+#include "assert-macros.h"
+#include "args.h"
+#include "assert-macros.h"
+#include "wpan-dbus-v1.h"
+#include "string-utils.h"
+
+#include <arpa/inet.h>
+#include <errno.h>
+
+const char config_gateway_cmd_syntax[] = "[args] <prefix>";
+
+static const arg_list_item_t config_gateway_option_list[] = {
+ {'h', "help", NULL, "Print Help"},
+ {'t', "timeout", "ms", "Set timeout period"},
+
+ {'p', "preferred-lifetime", "seconds",
+ "Set the preferred lifetime (Default: infinite)"},
+ {'v', "valid-lifetime", "seconds",
+ "Set the valid lifetime (Default: infinite)"},
+ {'d', "default", NULL, "Indicates that we can be a default route"},
+ {0}
+};
+
+int tool_cmd_config_gateway(int argc, char* argv[])
+{
+ int ret = 0;
+ int c;
+ int timeout = DEFAULT_TIMEOUT_IN_SECONDS * 1000;
+ DBusConnection* connection = NULL;
+ DBusMessage *message = NULL;
+ DBusMessage *reply = NULL;
+ DBusError error;
+ dbus_bool_t defaultRoute = FALSE;
+ uint32_t preferredLifetime = 0xFFFFFFFF;
+ uint32_t validLifetime = 0xFFFFFFFF;
+ const char* prefix = NULL;
+ uint8_t prefix_length = 64;
+ char address_string[INET6_ADDRSTRLEN] = "::";
+ uint8_t prefix_bytes[16] = {};
+ uint8_t *addr = prefix_bytes;
+
+ dbus_error_init(&error);
+
+ while (1) {
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"timeout", required_argument, 0, 't'},
+ {"preferred-lifetime", required_argument, 0, 'p'},
+ {"valid-lifetime", required_argument, 0, 'v'},
+ {"default", no_argument, 0, 'd'},
+ {0, 0, 0, 0}
+ };
+
+ int option_index = 0;
+ c = getopt_long(argc, argv, "ht:p:v:d", long_options,
+ &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_arg_list_help(config_gateway_option_list, argv[0],
+ config_gateway_cmd_syntax);
+ ret = ERRORCODE_HELP;
+ goto bail;
+
+ case 'd':
+ defaultRoute = TRUE;
+ break;
+
+ case 't':
+ timeout = strtol(optarg, NULL, 0);
+ break;
+
+ case 'p':
+ preferredLifetime = (uint32_t) strtol(optarg, NULL, 0);
+ break;
+
+ case 'v':
+ validLifetime = (uint32_t) strtol(optarg, NULL, 0);
+ break;
+
+ }
+ }
+
+ if (optind < argc) {
+ if (!prefix) {
+ prefix = argv[optind];
+ optind++;
+ }
+ }
+
+ if (optind < argc) {
+ fprintf(stderr,
+ "%s: error: Unexpected extra argument: \"%s\"\n",
+ argv[0], argv[optind]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ if (gInterfaceName[0] == 0) {
+ fprintf(stderr,
+ "%s: error: No WPAN interface set (use the `cd` command, or the `-I` argument for `wpanctl`).\n",
+ argv[0]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
+
+ if (!connection) {
+ dbus_error_free(&error);
+ dbus_error_init(&error);
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ }
+
+ require_string(connection != NULL, bail, error.message);
+
+ {
+ DBusMessageIter iter;
+ DBusMessageIter list_iter;
+ char path[DBUS_MAXIMUM_NAME_LENGTH+1];
+ char interface_dbus_name[DBUS_MAXIMUM_NAME_LENGTH+1];
+ ret = lookup_dbus_name_from_interface(interface_dbus_name, gInterfaceName);
+ if (ret != 0) {
+ goto bail;
+ }
+ snprintf(path,
+ sizeof(path),
+ "%s/%s",
+ WPANTUND_DBUS_PATH,
+ gInterfaceName);
+
+ message = dbus_message_new_method_call(
+ interface_dbus_name,
+ path,
+ WPANTUND_DBUS_APIv1_INTERFACE,
+ WPANTUND_IF_CMD_CONFIG_GATEWAY
+ );
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_BOOLEAN, &defaultRoute,
+ DBUS_TYPE_INVALID
+ );
+
+ if(prefix) {
+
+ // So the prefix could either be
+ // specified like an IPv6 address, or
+ // specified as a bunch of hex numbers.
+ // We use the presence of a colon (':')
+ // to differentiate.
+ if(strstr(prefix,":")) {
+
+ // Address-style
+ int bits = inet_pton(AF_INET6,prefix,prefix_bytes);
+ if(bits<0) {
+ fprintf(stderr,
+ "Bad Prefix \"%s\", errno=%d (%s)\n",
+ prefix,
+ errno,
+ strerror(errno));
+ goto bail;
+ } else if(!bits) {
+ fprintf(stderr, "Bad prefix \"%s\"\n", prefix);
+ goto bail;
+ }
+ } else {
+ // DATA-style
+ int length = parse_string_into_data(prefix_bytes,
+ 8,
+ prefix);
+ if(length<=0) {
+ fprintf(stderr, "Bad prefix \"%s\"\n", prefix);
+ goto bail;
+ }
+ }
+
+ inet_ntop(AF_INET6, (const void *)&prefix_bytes, address_string, sizeof(address_string));
+
+ fprintf(stderr, "Using prefix \"%s\"\n", address_string);
+
+ }
+
+ addr = prefix_bytes;
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &addr, 16,
+ DBUS_TYPE_UINT32, &preferredLifetime,
+ DBUS_TYPE_UINT32, &validLifetime,
+ DBUS_TYPE_INVALID
+ );
+
+
+ reply = dbus_connection_send_with_reply_and_block(
+ connection,
+ message,
+ timeout,
+ &error
+ );
+
+ if (!reply) {
+ fprintf(stderr, "%s: error: %s\n", argv[0], error.message);
+ ret = ERRORCODE_TIMEOUT;
+ goto bail;
+ }
+
+ dbus_message_get_args(reply, &error,
+ DBUS_TYPE_INT32, &ret,
+ DBUS_TYPE_INVALID
+ );
+
+ if (!ret) {
+ fprintf(stderr, "Gateway configured.\n");
+ } else {
+ fprintf(stderr, "%s failed with error %d. %s\n", argv[0], ret, wpantund_status_to_cstr(ret));
+ print_error_diagnosis(ret);
+ }
+ }
+
+bail:
+
+ if (connection)
+ dbus_connection_unref(connection);
+
+ if (message)
+ dbus_message_unref(message);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_error_free(&error);
+
+ return ret;
+}
diff --git a/src/wpanctl/tool-cmd-config-gateway.h b/src/wpanctl/tool-cmd-config-gateway.h
new file mode 100644
index 0000000..748232a
--- /dev/null
+++ b/src/wpanctl/tool-cmd-config-gateway.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef WPANCTL_TOOL_CMD_CONFIG_GATEWAY_H
+#define WPANCTL_TOOL_CMD_CONFIG_GATEWAY_H
+
+#include "wpanctl-utils.h"
+
+int tool_cmd_config_gateway(int argc, char* argv[]);
+
+#endif
diff --git a/src/wpanctl/tool-cmd-form.c b/src/wpanctl/tool-cmd-form.c
new file mode 100644
index 0000000..a3bed76
--- /dev/null
+++ b/src/wpanctl/tool-cmd-form.c
@@ -0,0 +1,277 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <getopt.h>
+#include "wpanctl-utils.h"
+#include "tool-cmd-form.h"
+#include "assert-macros.h"
+#include "wpan-dbus-v0.h"
+#include "args.h"
+#include "string-utils.h"
+
+#include <arpa/inet.h>
+#include <errno.h>
+
+const char form_cmd_syntax[] = "[args] [network-name]";
+
+static const arg_list_item_t form_option_list[] = {
+ {'h', "help", NULL, "Print Help"},
+ {'t', "timeout", "ms", "Set timeout period"},
+ {'c', "channel", "channel", "Set the desired channel"},
+ {'T', "type", "node-type: router(r,2), end-device(end,e,3), sleepy-end-device(sleepy,sed,4), nl-lurker(lurker,l,6)",
+ "Join as a specific node type" },
+// {'u', "ula-prefix", "ULA Prefix", "Specify a specific *LEGACY* ULA prefix"},
+ {'M', "mesh-local-prefix", "Mesh-Local IPv6 Prefix", "Specify a non-default mesh-local IPv6 prefix"},
+ {'L', "legacy-prefix", "Legacy IPv6 Prefix", "Specify a specific *LEGACY* IPv6 prefix"},
+ {0}
+};
+
+int tool_cmd_form(int argc, char* argv[])
+{
+ int ret = 0;
+ int c;
+ int timeout = DEFAULT_TIMEOUT_IN_SECONDS * 1000;
+ DBusConnection* connection = NULL;
+ DBusMessage *message = NULL;
+ DBusMessage *reply = NULL;
+ DBusError error;
+ const char* network_name = NULL;
+ const char* ula_prefix = NULL;
+ uint16_t node_type = WPAN_IFACE_ROLE_ROUTER; // Default to router for form
+ uint32_t channel_mask = 0;
+
+ dbus_error_init(&error);
+
+ while (1) {
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"timeout", required_argument, 0, 't'},
+ {"channel", required_argument, 0, 'c'},
+ {"ula-prefix", required_argument, 0, 'u'},
+ {"mesh-local-prefix", required_argument, 0, 'M'},
+ {"legacy-prefix", required_argument, 0, 'L'},
+ {"type", required_argument, 0, 'T'},
+ {0, 0, 0, 0}
+ };
+
+ int option_index = 0;
+ c = getopt_long(argc, argv, "hc:t:T:u:", long_options,
+ &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_arg_list_help(form_option_list, argv[0],
+ form_cmd_syntax);
+ ret = ERRORCODE_HELP;
+ goto bail;
+
+ case 't':
+ timeout = strtol(optarg, NULL, 0);
+ break;
+
+ case 'c':
+ channel_mask = (1 << strtol(optarg, NULL, 0));
+ break;
+
+ case 'M':
+ fprintf(stderr,
+ "%s: error: Setting the mesh local address at the command line isn't yet implemented. Set it as a property instead.\n",
+ argv[0]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ break;
+
+ case 'L':
+ case 'u':
+ ula_prefix = optarg;
+ break;
+
+ case 'T':
+ node_type = node_type_str2int(optarg);
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ if (!network_name) {
+ network_name = argv[optind];
+ optind++;
+ }
+ }
+
+ if (optind < argc) {
+ fprintf(stderr,
+ "%s: error: Unexpected extra argument: \"%s\"\n",
+ argv[0], argv[optind]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ if (!network_name) {
+ fprintf(stderr, "%s: error: Missing network name.\n", argv[0]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ if (gInterfaceName[0] == 0) {
+ fprintf(stderr,
+ "%s: error: No WPAN interface set (use the `cd` command, or the `-I` argument for `wpanctl`).\n",
+ argv[0]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
+
+ if (!connection) {
+ dbus_error_free(&error);
+ dbus_error_init(&error);
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ }
+
+ require_string(connection != NULL, bail, error.message);
+
+ {
+ DBusMessageIter iter;
+ DBusMessageIter list_iter;
+ char path[DBUS_MAXIMUM_NAME_LENGTH+1];
+ char interface_dbus_name[DBUS_MAXIMUM_NAME_LENGTH+1];
+ ret = lookup_dbus_name_from_interface(interface_dbus_name, gInterfaceName);
+ if (ret != 0) {
+ goto bail;
+ }
+ snprintf(path,
+ sizeof(path),
+ "%s/%s",
+ WPAN_TUNNEL_DBUS_PATH,
+ gInterfaceName);
+
+ message = dbus_message_new_method_call(
+ interface_dbus_name,
+ path,
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_IFACE_CMD_FORM
+ );
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_STRING, &network_name,
+ DBUS_TYPE_INT16, &node_type,
+ DBUS_TYPE_UINT32, &channel_mask,
+ DBUS_TYPE_INVALID
+ );
+
+ if(ula_prefix) {
+ uint8_t ula_bytes[16] = {};
+
+ // So the ULA prefix could either be
+ // specified like an IPv6 address, or
+ // specified as a bunch of hex numbers.
+ // We use the presence of a colon (':')
+ // to differentiate.
+ if(strstr(ula_prefix,":")) {
+
+ // Address-style
+ int bits = inet_pton(AF_INET6,ula_prefix,ula_bytes);
+ if(bits<0) {
+ fprintf(stderr,
+ "Bad ULA \"%s\", errno=%d (%s)\n",
+ ula_prefix,
+ errno,
+ strerror(errno));
+ goto bail;
+ } else if(!bits) {
+ fprintf(stderr, "Bad ULA \"%s\"\n", ula_prefix);
+ goto bail;
+ }
+ } else {
+ // DATA-style
+ int length = parse_string_into_data(ula_bytes,
+ 8,
+ ula_prefix);
+ if(length<=0) {
+ fprintf(stderr, "Bad ULA \"%s\"\n", ula_prefix);
+ goto bail;
+ }
+ }
+
+ fprintf(stderr, "Using ULA prefix \"%s\"\n", ula_prefix);
+
+ uint8_t *addr = ula_bytes;
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &addr, 8,
+ DBUS_TYPE_INVALID
+ );
+ }
+
+ fprintf(stderr,
+ "Forming WPAN \"%s\" as node type \"%s\"\n",
+ network_name,
+ node_type_int2str(node_type));
+
+
+ reply = dbus_connection_send_with_reply_and_block(
+ connection,
+ message,
+ timeout,
+ &error
+ );
+
+ if (!reply) {
+ fprintf(stderr, "%s: error: %s\n", argv[0], error.message);
+ ret = ERRORCODE_TIMEOUT;
+ goto bail;
+ }
+
+ dbus_message_get_args(reply, &error,
+ DBUS_TYPE_INT32, &ret,
+ DBUS_TYPE_INVALID
+ );
+
+ if (!ret) {
+ fprintf(stderr, "Successfully formed!\n");
+ } else {
+ fprintf(stderr, "%s failed with error %d. %s\n", argv[0], ret, wpantund_status_to_cstr(ret));
+ print_error_diagnosis(ret);
+ }
+ }
+
+bail:
+
+ if (connection)
+ dbus_connection_unref(connection);
+
+ if (message)
+ dbus_message_unref(message);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_error_free(&error);
+
+ return ret;
+}
diff --git a/src/wpanctl/tool-cmd-form.h b/src/wpanctl/tool-cmd-form.h
new file mode 100644
index 0000000..781f77f
--- /dev/null
+++ b/src/wpanctl/tool-cmd-form.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef WPANCTL_TOOL_CMD_FORM_H
+#define WPANCTL_TOOL_CMD_FORM_H
+
+#include "wpanctl-utils.h"
+
+int tool_cmd_form(int argc, char* argv[]);
+
+#endif
diff --git a/src/wpanctl/tool-cmd-getprop.c b/src/wpanctl/tool-cmd-getprop.c
new file mode 100644
index 0000000..7cb59df
--- /dev/null
+++ b/src/wpanctl/tool-cmd-getprop.c
@@ -0,0 +1,240 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <getopt.h>
+#include "wpanctl-utils.h"
+#include "tool-cmd-getprop.h"
+#include "assert-macros.h"
+#include "args.h"
+#include "assert-macros.h"
+#include "wpan-dbus-v1.h"
+
+const char getprop_cmd_syntax[] = "[args] <property-name>";
+
+static const arg_list_item_t getprop_option_list[] = {
+ {'h', "help", NULL, "Print Help"},
+ {'t', "timeout", "ms", "Set timeout period"},
+ {'a', "all", NULL, "Print all supported properties"},
+ {'v', "value-only", NULL, "Print only the value of the property"},
+ {0}
+};
+
+int tool_cmd_getprop(int argc, char *argv[])
+{
+ int ret = 0;
+ int c;
+ int timeout = 10 * 1000;
+ DBusConnection *connection = NULL;
+ DBusMessage *message = NULL;
+ DBusMessage *reply = NULL;
+ DBusError error;
+ const char *property_name = NULL;
+ bool get_all = false;
+ bool value_only = false;
+
+ dbus_error_init(&error);
+
+ optind = 0;
+
+ while (1) {
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"timeout", required_argument, 0, 't'},
+ {"all", no_argument, 0, 'a'},
+ {"value-only", no_argument, 0, 'v'},
+ {0, 0, 0, 0}
+ };
+
+ int option_index = 0;
+ c = getopt_long(argc, argv, "ht:av", long_options,
+ &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_arg_list_help(getprop_option_list, argv[0],
+ getprop_cmd_syntax);
+ ret = ERRORCODE_HELP;
+ goto bail;
+
+ case 't':
+ timeout = strtol(optarg, NULL, 0);
+ break;
+
+ case 'a':
+ get_all = true;
+ break;
+
+ case 'v':
+ value_only = true;
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ property_name = argv[optind];
+ }
+
+ if (optind == argc) {
+ property_name = "";
+ get_all = true;
+ }
+
+ if ((optind < argc) && get_all) {
+ fprintf(stderr,
+ "%s: error: Can't specify a specific property and request all properties at the same time.\n",
+ argv[0]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ if (gInterfaceName[0] == 0) {
+ fprintf(stderr,
+ "%s: error: No WPAN interface set (use the `cd` command, or the `-I` argument for `wpanctl`).\n",
+ argv[0]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ if (optind + 1 < argc) {
+ int cmd_and_flags = optind;
+ int j;
+ for (j = optind; j < argc; j++) {
+ optind = 0;
+ argv[cmd_and_flags] = argv[j];
+ ret = tool_cmd_getprop(cmd_and_flags + 1, argv);
+ }
+ goto bail;
+ }
+
+
+ connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
+
+ if (!connection) {
+ dbus_error_free(&error);
+ dbus_error_init(&error);
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ }
+
+ require_string(connection != NULL, bail, error.message);
+
+ {
+ DBusMessageIter iter;
+ DBusMessageIter list_iter;
+ char path[DBUS_MAXIMUM_NAME_LENGTH+1];
+ char interface_dbus_name[DBUS_MAXIMUM_NAME_LENGTH+1];
+ ret = lookup_dbus_name_from_interface(interface_dbus_name, gInterfaceName);
+ if (ret != 0) {
+ goto bail;
+ }
+ snprintf(path,
+ sizeof(path),
+ "%s/%s",
+ WPANTUND_DBUS_PATH,
+ gInterfaceName);
+
+ message = dbus_message_new_method_call(
+ interface_dbus_name,
+ path,
+ WPANTUND_DBUS_APIv1_INTERFACE,
+ WPANTUND_IF_CMD_PROP_GET
+ );
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_STRING, &property_name,
+ DBUS_TYPE_INVALID
+ );
+
+ reply = dbus_connection_send_with_reply_and_block(
+ connection,
+ message,
+ timeout,
+ &error
+ );
+
+ if (!reply) {
+ fprintf(stderr, "%s: error: %s\n", argv[0], error.message);
+ ret = ERRORCODE_TIMEOUT;
+ goto bail;
+ }
+
+ dbus_message_iter_init(reply, &iter);
+
+ // Get return code
+ dbus_message_iter_get_basic(&iter, &ret);
+
+ if (ret) {
+ const char* error_cstr = NULL;
+
+ // Try to see if there is an error explanation we can extract
+ dbus_message_iter_next(&iter);
+ if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING) {
+ dbus_message_iter_get_basic(&iter, &error_cstr);
+ }
+
+ if(!error_cstr || error_cstr[0] == 0) {
+ error_cstr = (ret<0)?strerror(-ret):"Get failed";
+ }
+
+ fprintf(stderr, "%s: %s (%d)\n", property_name, error_cstr, ret);
+ goto bail;
+ }
+
+ // Move to the property
+ dbus_message_iter_next(&iter);
+
+ if (get_all) {
+ dbus_message_iter_recurse(&iter, &list_iter);
+
+ for (;
+ dbus_message_iter_get_arg_type(&list_iter) == DBUS_TYPE_STRING;
+ dbus_message_iter_next(&list_iter)) {
+ char* args[3] = { argv[0] };
+ dbus_message_iter_get_basic(&list_iter, &args[1]);
+ ret = tool_cmd_getprop(2, args);
+ }
+ } else {
+ if(!value_only && property_name[0])
+ fprintf(stdout, "%s = ", property_name);
+ dump_info_from_iter(stdout, &iter, 0, false, false);
+ }
+ }
+
+bail:
+
+ if (connection)
+ dbus_connection_unref(connection);
+
+ if (message)
+ dbus_message_unref(message);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_error_free(&error);
+
+ return ret;
+}
diff --git a/src/wpanctl/tool-cmd-getprop.h b/src/wpanctl/tool-cmd-getprop.h
new file mode 100644
index 0000000..bb94223
--- /dev/null
+++ b/src/wpanctl/tool-cmd-getprop.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef WPANCTL_TOOL_CMD_GETPROP_H
+#define WPANCTL_TOOL_CMD_GETPROP_H
+
+#include "wpanctl-utils.h"
+
+int tool_cmd_getprop(int argc, char* argv[]);
+
+#endif
diff --git a/src/wpanctl/tool-cmd-host-did-wake.c b/src/wpanctl/tool-cmd-host-did-wake.c
new file mode 100644
index 0000000..27ea87b
--- /dev/null
+++ b/src/wpanctl/tool-cmd-host-did-wake.c
@@ -0,0 +1,166 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <getopt.h>
+#include "wpanctl-utils.h"
+#include "tool-cmd-host-did-wake.h"
+#include "assert-macros.h"
+#include "args.h"
+#include "assert-macros.h"
+#include "wpan-dbus-v1.h"
+
+const char host_did_wake_cmd_syntax[] = "[args]";
+
+static const arg_list_item_t host_did_wake_option_list[] = {
+ {'h', "help", NULL, "Print Help"},
+ {'t', "timeout", "ms", "Set timeout period"},
+ {0}
+};
+
+int tool_cmd_host_did_wake(int argc, char* argv[])
+{
+ int ret = 0;
+ int c;
+ int timeout = 10 * 1000;
+ DBusConnection* connection = NULL;
+ DBusMessage *message = NULL;
+ DBusMessage *reply = NULL;
+ DBusError error;
+
+ dbus_error_init(&error);
+
+ while (1) {
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"timeout", required_argument, 0, 't'},
+ {0, 0, 0, 0}
+ };
+
+ int option_index = 0;
+ c = getopt_long(argc, argv, "ht:", long_options, &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_arg_list_help(host_did_wake_option_list, argv[0],
+ host_did_wake_cmd_syntax);
+ ret = ERRORCODE_HELP;
+ goto bail;
+
+ case 't':
+ timeout = strtol(optarg, NULL, 0);
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ fprintf(stderr,
+ "%s: error: Unexpected extra argument: \"%s\"\n",
+ argv[0], argv[optind]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ if (gInterfaceName[0] == 0) {
+ fprintf(stderr,
+ "%s: error: No WPAN interface set (use the `cd` command, or the `-I` argument for `wpanctl`).\n",
+ argv[0]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
+
+ if (!connection) {
+ dbus_error_free(&error);
+ dbus_error_init(&error);
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ }
+
+ require_string(connection != NULL, bail, error.message);
+
+ {
+ DBusMessageIter iter;
+ DBusMessageIter list_iter;
+ char path[DBUS_MAXIMUM_NAME_LENGTH+1];
+ char interface_dbus_name[DBUS_MAXIMUM_NAME_LENGTH+1];
+ ret = lookup_dbus_name_from_interface(interface_dbus_name, gInterfaceName);
+ if (ret != 0) {
+ goto bail;
+ }
+ snprintf(path,
+ sizeof(path),
+ "%s/%s",
+ WPANTUND_DBUS_PATH,
+ gInterfaceName);
+
+ message = dbus_message_new_method_call(
+ interface_dbus_name,
+ path,
+ WPANTUND_DBUS_APIv1_INTERFACE,
+ WPANTUND_IF_CMD_HOST_DID_WAKE
+ );
+
+ reply = dbus_connection_send_with_reply_and_block(
+ connection,
+ message,
+ timeout,
+ &error
+ );
+
+ if (!reply) {
+ fprintf(stderr, "%s: error: %s\n", argv[0], error.message);
+ ret = ERRORCODE_TIMEOUT;
+ goto bail;
+ }
+
+ dbus_message_get_args(reply, &error,
+ DBUS_TYPE_INT32, &ret,
+ DBUS_TYPE_INVALID
+ );
+ if (ret == 6)
+ ret = 0;
+
+ if (ret) {
+ fprintf(stderr, "%s failed with error %d. %s\n", argv[0], ret, wpantund_status_to_cstr(ret));
+ print_error_diagnosis(ret);
+ }
+ }
+
+bail:
+
+ if (connection)
+ dbus_connection_unref(connection);
+
+ if (message)
+ dbus_message_unref(message);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_error_free(&error);
+
+ return ret;
+}
diff --git a/src/wpanctl/tool-cmd-host-did-wake.h b/src/wpanctl/tool-cmd-host-did-wake.h
new file mode 100644
index 0000000..f11e848
--- /dev/null
+++ b/src/wpanctl/tool-cmd-host-did-wake.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef WPANCTL_TOOL_CMD_HOST_DID_WAKE_H
+#define WPANCTL_TOOL_CMD_HOST_DID_WAKE_H
+
+#include "wpanctl-utils.h"
+
+int tool_cmd_host_did_wake(int argc, char* argv[]);
+
+#endif
diff --git a/src/wpanctl/tool-cmd-join.c b/src/wpanctl/tool-cmd-join.c
new file mode 100644
index 0000000..a5d6d42
--- /dev/null
+++ b/src/wpanctl/tool-cmd-join.c
@@ -0,0 +1,269 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <getopt.h>
+#include "wpanctl-utils.h"
+#include "tool-cmd-join.h"
+#include "tool-cmd-scan.h"
+#include "assert-macros.h"
+#include "args.h"
+#include "assert-macros.h"
+#include "wpan-dbus-v0.h"
+
+#include <errno.h>
+
+const char join_cmd_syntax[] = "[args] [network-name]";
+
+static const arg_list_item_t join_option_list[] = {
+ {'h', "help", NULL, "Print Help"},
+ {'t', "timeout", "ms", "Set timeout period"},
+ {'T', "type", "node-type: router(r,2), end-device(end,e,3), sleepy-end-device(sleepy,sed,4), nl-lurker(lurker,l,6)",
+ "Join as a specific node type"},
+ {'p', "panid", "panid", "Specify a specific PAN ID"},
+ {'x', "xpanid", "xpanid", "Specify a specific Extended PAN ID"},
+ {'c', "channel", "channel", "Specify a specific channel"},
+ {0}
+};
+
+int tool_cmd_join(int argc, char* argv[])
+{
+ int ret = 0;
+ int c;
+ int timeout = DEFAULT_TIMEOUT_IN_SECONDS * 1000;
+ DBusConnection* connection = NULL;
+ DBusMessage *message = NULL;
+ DBusMessage *reply = NULL;
+ DBusError error;
+ uint16_t node_type = WPAN_IFACE_ROLE_END_DEVICE;
+ struct wpan_network_info_s target_network = {};
+
+ dbus_error_init(&error);
+
+ while (1) {
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"timeout", required_argument, 0, 't'},
+ {"type", required_argument, 0, 'T'},
+ {"panid", required_argument, 0, 'p'},
+ {"xpanid", required_argument, 0, 'x'},
+ {"channel", required_argument, 0, 'c'},
+ {0, 0, 0, 0}
+ };
+
+ int option_index = 0;
+ c = getopt_long(argc, argv, "hc:t:T:x:p:", long_options,
+ &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_arg_list_help(join_option_list, argv[0],
+ join_cmd_syntax);
+ ret = ERRORCODE_HELP;
+ goto bail;
+
+ case 't':
+ timeout = strtol(optarg, NULL, 0);
+ break;
+
+ case 'p':
+ target_network.pan_id = strtol(optarg, NULL, 16);
+ break;
+
+ case 'c':
+ target_network.channel = strtol(optarg, NULL, 0);
+ break;
+
+ case 'x':
+ target_network.xpanid = strtoull(optarg, NULL, 16);
+ break;
+
+ case 'T':
+ node_type = node_type_str2int(optarg);
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ if (!target_network.network_name[0]) {
+ int index;
+ if (1 == sscanf(argv[optind], "%d",
+ &index) && index
+ && (index <= gScannedNetworkCount)) {
+ target_network = gScannedNetworks[index - 1];
+ } else {
+ strncpy(target_network.network_name,
+ argv[optind], 16);
+ target_network.network_name[16] = 0;
+ }
+ optind++;
+ }
+ }
+
+ if (optind < argc) {
+ if (!target_network.xpanid) {
+ target_network.xpanid = strtoull(argv[optind], NULL, 16);
+ optind++;
+ }
+ }
+
+ if (optind < argc) {
+ fprintf(stderr,
+ "%s: error: Unexpected extra argument: \"%s\"\n",
+ argv[0], argv[optind]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ if (!target_network.network_name[0]) {
+ fprintf(stderr, "%s: error: Missing network name.\n", argv[0]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ if (gInterfaceName[0] == 0) {
+ fprintf(stderr,
+ "%s: error: No WPAN interface set (use the `cd` command, or the `-I` argument for `wpanctl`).\n",
+ argv[0]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
+
+ if (!connection) {
+ dbus_error_free(&error);
+ dbus_error_init(&error);
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ }
+
+ require_string(connection != NULL, bail, error.message);
+
+ {
+ DBusMessageIter iter;
+ DBusMessageIter list_iter;
+ char path[DBUS_MAXIMUM_NAME_LENGTH+1];
+ char interface_dbus_name[DBUS_MAXIMUM_NAME_LENGTH+1];
+ ret = lookup_dbus_name_from_interface(interface_dbus_name, gInterfaceName);
+ if (ret != 0) {
+ goto bail;
+ }
+ snprintf(path,
+ sizeof(path),
+ "%s/%s",
+ WPAN_TUNNEL_DBUS_PATH,
+ gInterfaceName);
+ char* network_name = target_network.network_name;
+
+ message = dbus_message_new_method_call(
+ interface_dbus_name,
+ path,
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_IFACE_CMD_JOIN
+ );
+
+ fprintf(stderr,
+ "Joining \"%s\" %016llX as node type \"%s\"\n",
+ target_network.network_name,
+ (unsigned long long)target_network.xpanid,
+ node_type_int2str(node_type));
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_STRING, &network_name,
+ DBUS_TYPE_INVALID
+ );
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_INT16, &node_type,
+ DBUS_TYPE_INVALID
+ );
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_UINT64, &target_network.xpanid,
+ DBUS_TYPE_INVALID
+ );
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_UINT16, &target_network.pan_id,
+ DBUS_TYPE_INVALID
+ );
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_BYTE, &target_network.channel,
+ DBUS_TYPE_INVALID
+ );
+
+ reply = dbus_connection_send_with_reply_and_block(
+ connection,
+ message,
+ timeout,
+ &error
+ );
+
+ if (!reply) {
+ fprintf(stderr, "%s: error: %s\n", argv[0], error.message);
+ ret = ERRORCODE_TIMEOUT;
+ goto bail;
+ }
+
+ dbus_message_get_args(reply, &error,
+ DBUS_TYPE_INT32, &ret,
+ DBUS_TYPE_INVALID
+ );
+
+ if (!ret) {
+ fprintf(stderr, "Successfully Joined!\n");
+ } else if ((ret == -EINPROGRESS) || (ret == kWPANTUNDStatus_InProgress)) {
+ fprintf(stderr,
+ "Partial (insecure) join. Credentials needed. Update key to continue.\n");
+ ret = 0;
+ } else {
+ fprintf(stderr, "%s failed with error %d. %s\n", argv[0], ret, wpantund_status_to_cstr(ret));
+
+ print_error_diagnosis(ret);
+ }
+ }
+
+bail:
+
+ if (connection)
+ dbus_connection_unref(connection);
+
+ if (message)
+ dbus_message_unref(message);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_error_free(&error);
+
+ return ret;
+}
diff --git a/src/wpanctl/tool-cmd-join.h b/src/wpanctl/tool-cmd-join.h
new file mode 100644
index 0000000..4cbff53
--- /dev/null
+++ b/src/wpanctl/tool-cmd-join.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef WPANCTL_TOOL_CMD_JOIN_H
+#define WPANCTL_TOOL_CMD_JOIN_H
+
+#include "wpanctl-utils.h"
+
+int tool_cmd_join(int argc, char* argv[]);
+
+#endif
diff --git a/src/wpanctl/tool-cmd-leave.c b/src/wpanctl/tool-cmd-leave.c
new file mode 100644
index 0000000..fa1be89
--- /dev/null
+++ b/src/wpanctl/tool-cmd-leave.c
@@ -0,0 +1,165 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <getopt.h>
+#include "wpanctl-utils.h"
+#include "tool-cmd-leave.h"
+#include "assert-macros.h"
+#include "wpan-dbus-v1.h"
+#include "args.h"
+
+const char leave_cmd_syntax[] = "[args]";
+
+static const arg_list_item_t leave_option_list[] = {
+ {'h', "help", NULL, "Print Help"},
+ {'t', "timeout", "ms", "Set timeout period"},
+ {0}
+};
+
+int tool_cmd_leave(int argc, char* argv[])
+{
+ int ret = 0;
+ int c;
+ int timeout = 10 * 1000;
+ DBusConnection* connection = NULL;
+ DBusMessage *message = NULL;
+ DBusMessage *reply = NULL;
+ DBusError error;
+
+ dbus_error_init(&error);
+
+ while (1) {
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"timeout", required_argument, 0, 't'},
+ {0, 0, 0, 0}
+ };
+
+ int option_index = 0;
+ c = getopt_long(argc, argv, "ht:", long_options, &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_arg_list_help(leave_option_list, argv[0],
+ leave_cmd_syntax);
+ ret = ERRORCODE_HELP;
+ goto bail;
+
+ case 't':
+ timeout = strtol(optarg, NULL, 0);
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ fprintf(stderr,
+ "%s: error: Unexpected extra argument: \"%s\"\n",
+ argv[0], argv[optind]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ if (gInterfaceName[0] == 0) {
+ fprintf(stderr,
+ "%s: error: No WPAN interface set (use the `cd` command, or the `-I` argument for `wpanctl`).\n",
+ argv[0]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
+
+ if (!connection) {
+ dbus_error_free(&error);
+ dbus_error_init(&error);
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ }
+
+ require_string(connection != NULL, bail, error.message);
+
+ {
+ DBusMessageIter iter;
+ DBusMessageIter list_iter;
+ char path[DBUS_MAXIMUM_NAME_LENGTH+1];
+ char interface_dbus_name[DBUS_MAXIMUM_NAME_LENGTH+1];
+ ret = lookup_dbus_name_from_interface(interface_dbus_name, gInterfaceName);
+ if (ret != 0) {
+ goto bail;
+ }
+ snprintf(path,
+ sizeof(path),
+ "%s/%s",
+ WPANTUND_DBUS_PATH,
+ gInterfaceName);
+
+ message = dbus_message_new_method_call(
+ interface_dbus_name,
+ path,
+ WPANTUND_DBUS_APIv1_INTERFACE,
+ WPANTUND_IF_CMD_LEAVE
+ );
+
+ fprintf(stderr, "Leaving current WPAN. . .\n");
+
+ reply = dbus_connection_send_with_reply_and_block(
+ connection,
+ message,
+ timeout,
+ &error
+ );
+
+ if (!reply) {
+ fprintf(stderr, "%s: error: %s\n", argv[0], error.message);
+ ret = ERRORCODE_TIMEOUT;
+ goto bail;
+ }
+
+ dbus_message_get_args(reply, &error,
+ DBUS_TYPE_INT32, &ret,
+ DBUS_TYPE_INVALID
+ );
+
+ if (ret) {
+ fprintf(stderr, "%s failed with error %d. %s\n", argv[0], ret, wpantund_status_to_cstr(ret));
+ print_error_diagnosis(ret);
+ }
+ }
+
+bail:
+
+ if (connection)
+ dbus_connection_unref(connection);
+
+ if (message)
+ dbus_message_unref(message);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_error_free(&error);
+
+ return ret;
+}
diff --git a/src/wpanctl/tool-cmd-leave.h b/src/wpanctl/tool-cmd-leave.h
new file mode 100644
index 0000000..d113169
--- /dev/null
+++ b/src/wpanctl/tool-cmd-leave.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef WPANCTL_TOOL_CMD_LEAVE_H
+#define WPANCTL_TOOL_CMD_LEAVE_H
+
+#include "wpanctl-utils.h"
+
+int tool_cmd_leave(int argc, char* argv[]);
+
+#endif
diff --git a/src/wpanctl/tool-cmd-list.c b/src/wpanctl/tool-cmd-list.c
new file mode 100644
index 0000000..7f6a0e0
--- /dev/null
+++ b/src/wpanctl/tool-cmd-list.c
@@ -0,0 +1,164 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <getopt.h>
+#include "wpanctl-utils.h"
+#include "tool-cmd-list.h"
+#include "assert-macros.h"
+#include "wpan-dbus-v0.h"
+#include "args.h"
+
+const char list_cmd_syntax[] = "[args] <duration>]";
+
+static const arg_list_item_t list_option_list[] = {
+ {'h', "help", NULL, "Print Help"},
+ {'t', "timeout", "ms", "Set timeout period"},
+ {0}
+};
+
+int tool_cmd_list(int argc, char* argv[])
+{
+ int ret = 0;
+ int c;
+ int timeout = DEFAULT_TIMEOUT_IN_SECONDS * 1000;
+ DBusConnection* connection = NULL;
+ DBusMessage *message = NULL;
+ DBusMessage *reply = NULL;
+ DBusError error;
+
+ dbus_error_init(&error);
+
+ while (1) {
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"timeout", required_argument, 0, 't'},
+ {0, 0, 0, 0}
+ };
+
+ int option_index = 0;
+ c = getopt_long(argc, argv, "ht:", long_options, &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_arg_list_help(list_option_list, argv[0],
+ list_cmd_syntax);
+ ret = ERRORCODE_HELP;
+ goto bail;
+
+ case 't':
+ timeout = strtol(optarg, NULL, 0);
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ fprintf(stderr,
+ "%s: error: Unexpected extra argument: \"%s\"\n",
+ argv[0], argv[optind]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
+
+ if (!connection) {
+ dbus_error_free(&error);
+ dbus_error_init(&error);
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ }
+
+ require_string(connection != NULL, bail, error.message);
+
+ {
+ DBusMessageIter iter;
+ DBusMessageIter list_iter;
+
+ message = dbus_message_new_method_call(
+ WPAN_TUNNEL_DBUS_NAME,
+ WPAN_TUNNEL_DBUS_PATH,
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_TUNNEL_CMD_GET_INTERFACES
+ );
+
+ reply = dbus_connection_send_with_reply_and_block(
+ connection,
+ message,
+ timeout,
+ &error
+ );
+
+ if (!reply) {
+ fprintf(stderr, "%s: error: %s\n", argv[0], error.message);
+ ret = ERRORCODE_TIMEOUT;
+ goto bail;
+ }
+
+ dbus_message_iter_init(reply, &iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
+ fprintf(stderr,
+ "%s: error: Bad type for interface list (%c)\n",
+ argv[0],
+ dbus_message_iter_get_element_type(&iter));
+ ret = ERRORCODE_UNKNOWN;
+ goto bail;
+ }
+
+ dbus_message_iter_recurse(&iter, &list_iter);
+
+ for (;
+ dbus_message_iter_get_arg_type(&list_iter) == DBUS_TYPE_ARRAY;
+ dbus_message_iter_next(&list_iter)
+ ) {
+ DBusMessageIter item_iter;
+ char *interface_name;
+ char *dbus_name;
+
+ dbus_message_iter_recurse(&list_iter, &item_iter);
+
+ dbus_message_iter_get_basic(&item_iter, &interface_name);
+ dbus_message_iter_next(&item_iter);
+ dbus_message_iter_get_basic(&item_iter, &dbus_name);
+
+ printf("%s (%s)\n", interface_name, dbus_name);
+ }
+ }
+
+bail:
+
+ if (connection)
+ dbus_connection_unref(connection);
+
+ if (message)
+ dbus_message_unref(message);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_error_free(&error);
+
+ return ret;
+}
diff --git a/src/wpanctl/tool-cmd-list.h b/src/wpanctl/tool-cmd-list.h
new file mode 100644
index 0000000..9e414c5
--- /dev/null
+++ b/src/wpanctl/tool-cmd-list.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef WPANCTL_TOOL_CMD_LIST_H
+#define WPANCTL_TOOL_CMD_LIST_H
+
+#include "wpanctl-utils.h"
+
+int tool_cmd_list(int argc, char* argv[]);
+
+#endif
diff --git a/src/wpanctl/tool-cmd-mfg.c b/src/wpanctl/tool-cmd-mfg.c
new file mode 100644
index 0000000..c0cc04c
--- /dev/null
+++ b/src/wpanctl/tool-cmd-mfg.c
@@ -0,0 +1,133 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <getopt.h>
+#include "wpanctl-utils.h"
+#include "tool-cmd-status.h"
+#include "assert-macros.h"
+#include "wpan-dbus-v1.h"
+#include "args.h"
+
+int tool_cmd_mfg(int argc, char *argv[])
+{
+ int ret = 0;
+ int c;
+ int timeout = 10 * 1000;
+ char output[100];
+ DBusConnection *connection = NULL;
+ DBusMessage *message = NULL;
+ DBusMessage *reply = NULL;
+ const char* result_cstr = NULL;
+ DBusError error;
+
+ dbus_error_init(&error);
+
+ connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
+
+ if (!connection) {
+ dbus_error_free(&error);
+ dbus_error_init(&error);
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ }
+
+ require_string(error.name == NULL, bail, error.message);
+
+ {
+ DBusMessageIter iter;
+ DBusMessageIter list_iter;
+ char path[DBUS_MAXIMUM_NAME_LENGTH+1];
+ char interface_dbus_name[DBUS_MAXIMUM_NAME_LENGTH+1];
+ ret = lookup_dbus_name_from_interface(interface_dbus_name, gInterfaceName);
+ if (ret != 0) {
+ goto bail;
+ }
+ snprintf(path,
+ sizeof(path),
+ "%s/%s",
+ WPANTUND_DBUS_PATH,
+ gInterfaceName);
+
+ message = dbus_message_new_method_call(
+ interface_dbus_name,
+ path,
+ WPANTUND_DBUS_NLAPIv1_INTERFACE,
+ WPANTUND_IF_CMD_MFG
+ );
+
+ char string[100];
+ if (argc == 1)
+ sprintf(string, "%s", argv[0]);
+ if (argc == 2)
+ sprintf(string, "%s %s", argv[0], argv[1]);
+ if (argc == 3)
+ sprintf(string, "%s %s %s", argv[0], argv[1], argv[2]);
+ if (argc == 4)
+ sprintf(string, "%s %s %s %s", argv[0], argv[1], argv[2], argv[3]);
+ char *cmd = string;
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_STRING, &cmd,
+ DBUS_TYPE_INVALID
+ );
+ reply = dbus_connection_send_with_reply_and_block(
+ connection,
+ message,
+ timeout,
+ &error
+ );
+
+ if (!reply) {
+ fprintf(stderr, "%s: error: %s\n", argv[0], error.message);
+ ret = ERRORCODE_TIMEOUT;
+ goto bail;
+ }
+
+ dbus_message_iter_init(reply, &iter);
+
+ dbus_message_iter_get_basic(&iter, &ret);
+
+ dbus_message_iter_next(&iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING) {
+ dbus_message_iter_get_basic(&iter, &result_cstr);
+ printf("%s", result_cstr);
+ } else {
+ dump_info_from_iter(stdout, &iter, 0, false, false);
+ }
+ }
+
+bail:
+
+ if (connection)
+ dbus_connection_unref(connection);
+
+ if (message)
+ dbus_message_unref(message);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_error_free(&error);
+
+ return ret;
+}
diff --git a/src/wpanctl/tool-cmd-mfg.h b/src/wpanctl/tool-cmd-mfg.h
new file mode 100644
index 0000000..8eb6b8a
--- /dev/null
+++ b/src/wpanctl/tool-cmd-mfg.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef WPANCTL_TOOL_CMD_MFG_H
+#define WPANCTL_TOOL_CMD_MFG_H
+
+#include "wpanctl-utils.h"
+
+int tool_cmd_mfg(int argc, char* argv[]);
+
+#endif
diff --git a/src/wpanctl/tool-cmd-pcap.c b/src/wpanctl/tool-cmd-pcap.c
new file mode 100644
index 0000000..da1bdbf
--- /dev/null
+++ b/src/wpanctl/tool-cmd-pcap.c
@@ -0,0 +1,337 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <getopt.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "wpanctl-utils.h"
+#include "tool-cmd-pcap.h"
+#include "assert-macros.h"
+#include "args.h"
+#include "assert-macros.h"
+#include "wpan-dbus-v1.h"
+
+const char pcap_cmd_syntax[] = "[args] <capture-file>";
+
+static const arg_list_item_t pcap_option_list[] = {
+ {'h', "help", NULL, "Print Help"},
+ {'t', "timeout", "ms", "Set timeout period"},
+ {'f', NULL, NULL, "Allow packet capture to controlling TTY"},
+ {0}
+};
+
+
+static int
+do_pcap_to_fd(int fd, int timeout, DBusError *error)
+{
+ int ret = ERRORCODE_UNKNOWN;
+ DBusConnection *connection = NULL;
+ DBusMessage *message = NULL;
+ DBusMessage *reply = NULL;
+ char path[DBUS_MAXIMUM_NAME_LENGTH+1];
+ char interface_dbus_name[DBUS_MAXIMUM_NAME_LENGTH+1];
+
+ connection = dbus_bus_get(DBUS_BUS_STARTER, error);
+
+ if (connection == NULL) {
+ if (error != NULL) {
+ dbus_error_free(error);
+ dbus_error_init(error);
+ }
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, error);
+ }
+
+ require(connection != NULL, bail);
+
+ ret = lookup_dbus_name_from_interface(interface_dbus_name, gInterfaceName);
+
+ require_noerr(ret, bail);
+
+ snprintf(
+ path,
+ sizeof(path),
+ "%s/%s",
+ WPANTUND_DBUS_PATH,
+ gInterfaceName
+ );
+
+ message = dbus_message_new_method_call(
+ interface_dbus_name,
+ path,
+ WPANTUND_DBUS_APIv1_INTERFACE,
+ WPANTUND_IF_CMD_PCAP_TO_FD
+ );
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_UNIX_FD, &fd,
+ DBUS_TYPE_INVALID
+ );
+
+ ret = ERRORCODE_TIMEOUT;
+
+ reply = dbus_connection_send_with_reply_and_block(
+ connection,
+ message,
+ timeout,
+ error
+ );
+
+ require(reply != NULL, bail);
+
+ dbus_message_get_args(
+ reply,
+ error,
+ DBUS_TYPE_INT32, &ret,
+ DBUS_TYPE_INVALID
+ );
+
+bail:
+
+ if (connection) {
+ dbus_connection_unref(connection);
+ }
+
+ if (message) {
+ dbus_message_unref(message);
+ }
+
+ if (reply) {
+ dbus_message_unref(reply);
+ }
+
+ return ret;
+}
+
+//! Checks to see if the given FD is the controlling TTY.
+bool
+is_descriptor_ctty(int fd)
+{
+ bool ret = false;
+
+ if (isatty(fd)) {
+ char tty_name_copy[L_ctermid] = "";
+ const char *tty_name = ttyname(fd);
+
+ if (tty_name == NULL) {
+ goto bail;
+ }
+
+ // Just use snprintf as a safe string copy.
+ // It is more portable than strlcpy and we don't care about
+ // performance in this context.
+ snprintf(tty_name_copy, sizeof(tty_name_copy), "%s", tty_name);
+
+ if (NULL == (tty_name = ttyname(STDIN_FILENO))) {
+ goto bail;
+ }
+
+ ret = (0 == strcmp(tty_name_copy, tty_name));
+ }
+
+bail:
+ return ret;
+}
+
+int
+tool_cmd_pcap(int argc, char *argv[])
+{
+ static const int set = 1;
+ int ret = 0;
+ int timeout = 10 * 1000;
+
+ int fd_out = -1;
+ int fd_pair[2] = { -1, -1 };
+ bool force_ctty = false;
+ bool stdout_was_closed = false;
+
+ DBusError error;
+
+ dbus_error_init(&error);
+
+ while (1) {
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"timeout", required_argument, 0, 't'},
+ {0, 0, 0, 0}
+ };
+
+ int option_index = 0;
+ int c;
+
+ c = getopt_long(argc, argv, "fht:", long_options, &option_index);
+
+ if (c == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 'h':
+ print_arg_list_help(pcap_option_list, argv[0],
+ pcap_cmd_syntax);
+ ret = ERRORCODE_HELP;
+ goto bail;
+
+ case 'f':
+ force_ctty = true;
+ break;
+
+ case 't':
+ timeout = strtol(optarg, NULL, 0);
+ break;
+ }
+ }
+
+ // We use a socket pair for the socket we hand to wpantund,
+ // so that the termination of this process will stop packet
+ // capture.
+ if (socketpair(PF_UNIX, SOCK_DGRAM, 0, fd_pair) < 0) {
+ perror("socketpair");
+ ret = ERRORCODE_UNKNOWN;
+ goto bail;
+ }
+
+ if (optind < argc) {
+ // Capture packets to a file path
+
+ fd_out = open(argv[optind], O_WRONLY|O_CREAT|O_TRUNC, 0666);
+
+ optind++;
+
+ } else {
+ // Capture packets to stdout
+
+ if (!force_ctty && is_descriptor_ctty(STDOUT_FILENO)) {
+ fprintf(stderr, "%s: error: Cowardly refusing write binary data to controlling tty, use -f to override\n", argv[0]);
+ ret = ERRORCODE_REFUSED;
+ goto bail;
+ }
+
+ // Update fd_out, close the original stdout.
+ fd_out = dup(STDOUT_FILENO);
+ close(STDOUT_FILENO);
+ stdout_was_closed = true;
+ }
+
+ if (optind < argc) {
+ fprintf(
+ stderr,
+ "%s: error: Unexpected extra argument: \"%s\"\n",
+ argv[0],
+ argv[optind]
+ );
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ if (fd_out < 0) {
+ fprintf(
+ stderr,
+ "%s: error: Unable to open file for pcap: \"%s\"\n",
+ argv[0],
+ strerror(errno)
+ );
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ if (gInterfaceName[0] == 0) {
+ fprintf(
+ stderr,
+ "%s: error: No WPAN interface set (use the `cd` command, or the `-I` argument for `wpanctl`).\n",
+ argv[0]
+ );
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ // Have wpantund start writing PCAP data to one end of our socket pair.
+ ret = do_pcap_to_fd(fd_pair[1], timeout, &error);
+
+ if (ret) {
+ if (error.message != NULL) {
+ fprintf(stderr, "%s: error: %s\n", argv[0], error.message);
+ }
+ goto bail;
+ }
+
+ // Close this side of the socket pair so that we can
+ // detect if wpantund closed the socket.
+ close(fd_pair[1]);
+
+#ifdef SO_NOSIGPIPE
+ // Turn off sigpipe so we can gracefully exit.
+ setsockopt(fd_pair[0], SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
+ setsockopt(fd_out, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
+#endif
+
+ fprintf(stderr, "%s: Capture started\n", argv[0]);
+
+ // Data pump
+ while (true) {
+ char buffer[2048];
+ ssize_t buffer_len;
+
+ // Read in from datagram socket
+ buffer_len = read(fd_pair[0], buffer, sizeof(buffer));
+
+ if (buffer_len <= 0) {
+ break;
+ }
+
+ // Write out the buffer to our file descriptor
+ buffer_len = write(fd_out, buffer, buffer_len);
+ if (buffer_len <= 0) {
+ break;
+ }
+ }
+
+ fprintf(stderr, "%s: Capture terminated\n", argv[0]);
+
+bail:
+
+ if (ret) {
+ fprintf(stderr, "pcap: failed with error %d. %s\n", ret, wpantund_status_to_cstr(ret));
+ print_error_diagnosis(ret);
+ }
+
+ // Clean up.
+
+ close(fd_out);
+
+ close(fd_pair[0]);
+
+ close(fd_pair[1]);
+
+ dbus_error_free(&error);
+
+ if (stdout_was_closed) {
+ exit (ret);
+ }
+
+ return ret;
+}
diff --git a/src/wpanctl/tool-cmd-pcap.h b/src/wpanctl/tool-cmd-pcap.h
new file mode 100644
index 0000000..5c26df6
--- /dev/null
+++ b/src/wpanctl/tool-cmd-pcap.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef WPANCTL_TOOL_CMD_PCAP_H
+#define WPANCTL_TOOL_CMD_PCAP_H
+
+#include "wpanctl-utils.h"
+
+int tool_cmd_pcap(int argc, char* argv[]);
+
+#endif
diff --git a/src/wpanctl/tool-cmd-permit-join.c b/src/wpanctl/tool-cmd-permit-join.c
new file mode 100644
index 0000000..d7dcbb3
--- /dev/null
+++ b/src/wpanctl/tool-cmd-permit-join.c
@@ -0,0 +1,225 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <getopt.h>
+#include "wpanctl-utils.h"
+#include "tool-cmd-permit-join.h"
+#include "assert-macros.h"
+#include "wpan-dbus-v0.h"
+#include "args.h"
+
+const char permit_join_cmd_syntax[] = "[args] <duration> [commissioning-port]";
+
+static const arg_list_item_t permit_join_option_list[] = {
+ {'h', "help", NULL, "Print Help"},
+ {'t', "timeout", "ms", "Set timeout period"},
+ {'n', "network-wide", NULL, "Permit joining network-wide"},
+ {'c', "tcp", NULL, "Permit only TCP for commissioning traffic"},
+ {'d', "udp", NULL, "Permit only UDP for commissioning traffic"},
+ {0}
+};
+
+int tool_cmd_permit_join(int argc, char* argv[])
+{
+ int ret = 0;
+ int c;
+ int timeout = DEFAULT_TIMEOUT_IN_SECONDS * 1000;
+ DBusConnection* connection = NULL;
+ DBusMessage *message = NULL;
+ DBusMessage *reply = NULL;
+ DBusError error;
+ int32_t period = -1;
+ dbus_bool_t network_wide = FALSE;
+ uint16_t commissioning_traffic_port = 0;
+ uint8_t commissioning_traffic_type = 0xFF;
+
+ dbus_error_init(&error);
+
+ while (1) {
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"timeout", required_argument, 0, 't'},
+ {"network-wide", no_argument, 0, 'n'},
+ {"tcp", no_argument, 0, 'c'},
+ {"udp", no_argument, 0, 'd'},
+ {0, 0, 0, 0}
+ };
+
+ int option_index = 0;
+ c = getopt_long(argc, argv, "ht:ncd", long_options,
+ &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_arg_list_help(permit_join_option_list,
+ argv[0], permit_join_cmd_syntax);
+ ret = ERRORCODE_HELP;
+ goto bail;
+
+ case 't':
+ timeout = strtol(optarg, NULL, 0);
+ break;
+
+ case 'n':
+ network_wide = TRUE;
+ break;
+
+ case 'c':
+ commissioning_traffic_type = 6;
+ break;
+
+ case 'd':
+ commissioning_traffic_type = 17;
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ if (period == -1) {
+ period = strtol(argv[optind], NULL, 0);
+ optind++;
+ }
+ }
+
+ if (optind < argc) {
+ if (!commissioning_traffic_port) {
+ commissioning_traffic_port =
+ strtol(argv[optind], NULL, 0);
+ optind++;
+ }
+ }
+
+ if (optind < argc) {
+ fprintf(stderr,
+ "%s: error: Unexpected extra argument: \"%s\"\n",
+ argv[0], argv[optind]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ if (period == -1)
+ period = 240;
+
+ if (gInterfaceName[0] == 0) {
+ fprintf(stderr,
+ "%s: error: No WPAN interface set (use the `cd` command, or the `-I` argument for `wpanctl`).\n",
+ argv[0]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
+
+ if (!connection) {
+ dbus_error_free(&error);
+ dbus_error_init(&error);
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ }
+
+ require_string(connection != NULL, bail, error.message);
+
+ {
+ DBusMessageIter iter;
+ DBusMessageIter list_iter;
+ char path[DBUS_MAXIMUM_NAME_LENGTH+1];
+ char interface_dbus_name[DBUS_MAXIMUM_NAME_LENGTH+1];
+ ret = lookup_dbus_name_from_interface(interface_dbus_name, gInterfaceName);
+ if (ret != 0) {
+ goto bail;
+ }
+ snprintf(path,
+ sizeof(path),
+ "%s/%s",
+ WPAN_TUNNEL_DBUS_PATH,
+ gInterfaceName);
+
+ message = dbus_message_new_method_call(
+ interface_dbus_name,
+ path,
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_IFACE_CMD_PERMIT_JOIN
+ );
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_INT32, &period,
+ DBUS_TYPE_BOOLEAN, &network_wide,
+ DBUS_TYPE_UINT16, &commissioning_traffic_port,
+ DBUS_TYPE_BYTE, &commissioning_traffic_type,
+ DBUS_TYPE_INVALID
+ );
+
+ if (commissioning_traffic_port)
+ fprintf(stderr,
+ "Permitting Joining on the current WPAN for %d seconds, commissioning traffic on %s port %d. . .\n",
+ period,
+ (commissioning_traffic_type ==
+ 6) ? "TCP" : (commissioning_traffic_type == 17) ? "UDP" : "TCP/UDP",
+ commissioning_traffic_port);
+ else
+ fprintf(stderr,
+ "Permitting Joining on the current WPAN for %d seconds. . .\n",
+ period);
+
+ reply = dbus_connection_send_with_reply_and_block(
+ connection,
+ message,
+ timeout,
+ &error
+ );
+
+ if (!reply) {
+ fprintf(stderr, "%s: error: %s\n", argv[0], error.message);
+ ret = ERRORCODE_TIMEOUT;
+ goto bail;
+ }
+
+ dbus_message_get_args(reply, &error,
+ DBUS_TYPE_INT32, &ret,
+ DBUS_TYPE_INVALID
+ );
+
+ if (ret) {
+ fprintf(stderr, "%s failed with error %d. %s\n", argv[0], ret, wpantund_status_to_cstr(ret));
+ print_error_diagnosis(ret);
+ }
+ }
+
+bail:
+
+ if (connection)
+ dbus_connection_unref(connection);
+
+ if (message)
+ dbus_message_unref(message);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_error_free(&error);
+
+ return ret;
+}
diff --git a/src/wpanctl/tool-cmd-permit-join.h b/src/wpanctl/tool-cmd-permit-join.h
new file mode 100644
index 0000000..a95f7b2
--- /dev/null
+++ b/src/wpanctl/tool-cmd-permit-join.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef WPANCTL_TOOL_CMD_PERMIT_JOIN_H
+#define WPANCTL_TOOL_CMD_PERMIT_JOIN_H
+
+#include "wpanctl-utils.h"
+
+int tool_cmd_permit_join(int argc, char* argv[]);
+
+#endif
diff --git a/src/wpanctl/tool-cmd-poll.c b/src/wpanctl/tool-cmd-poll.c
new file mode 100644
index 0000000..389ff04
--- /dev/null
+++ b/src/wpanctl/tool-cmd-poll.c
@@ -0,0 +1,168 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <getopt.h>
+#include "wpanctl-utils.h"
+#include "tool-cmd-poll.h"
+#include "assert-macros.h"
+#include "args.h"
+#include "assert-macros.h"
+#include "wpan-dbus-v1.h"
+
+const char poll_cmd_syntax[] = "[args]";
+
+static const arg_list_item_t poll_option_list[] = {
+ {'h', "help", NULL, "Print Help"},
+ {'t', "timeout", "ms", "Set timeout period"},
+ {0}
+};
+
+int tool_cmd_poll(int argc, char *argv[])
+{
+ int ret = 0;
+ int c;
+ int timeout = 10 * 1000;
+ DBusConnection *connection = NULL;
+ DBusMessage *message = NULL;
+ DBusMessage *reply = NULL;
+ DBusError error;
+
+ dbus_error_init(&error);
+
+ while (1) {
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"timeout", required_argument, 0, 't'},
+ {0, 0, 0, 0}
+ };
+
+ int option_index = 0;
+ c = getopt_long(argc, argv, "ht:", long_options, &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_arg_list_help(poll_option_list, argv[0],
+ poll_cmd_syntax);
+ ret = ERRORCODE_HELP;
+ goto bail;
+
+ case 't':
+ timeout = strtol(optarg, NULL, 0);
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ fprintf(stderr,
+ "%s: error: Unexpected extra argument: \"%s\"\n",
+ argv[0], argv[optind]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ if (gInterfaceName[0] == 0) {
+ fprintf(stderr,
+ "%s: error: No WPAN interface set (use the `cd` command, or the `-I` argument for `wpanctl`).\n",
+ argv[0]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
+
+ if (!connection) {
+ dbus_error_free(&error);
+ dbus_error_init(&error);
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ }
+
+ require_string(connection != NULL, bail, error.message);
+
+ {
+ DBusMessageIter iter;
+ DBusMessageIter list_iter;
+ char path[DBUS_MAXIMUM_NAME_LENGTH+1];
+ char interface_dbus_name[DBUS_MAXIMUM_NAME_LENGTH+1];
+ ret = lookup_dbus_name_from_interface(interface_dbus_name, gInterfaceName);
+ if (ret != 0) {
+ goto bail;
+ }
+ snprintf(path,
+ sizeof(path),
+ "%s/%s",
+ WPANTUND_DBUS_PATH,
+ gInterfaceName);
+
+ message = dbus_message_new_method_call(
+ interface_dbus_name,
+ path,
+ WPANTUND_DBUS_APIv1_INTERFACE,
+ WPANTUND_IF_CMD_DATA_POLL
+ );
+
+ fprintf(stderr, "Polling parent node for IP traffic. . .\n");
+
+ reply = dbus_connection_send_with_reply_and_block(
+ connection,
+ message,
+ timeout,
+ &error
+ );
+
+ if (!reply) {
+ fprintf(stderr, "%s: error: %s\n", argv[0], error.message);
+ ret = ERRORCODE_TIMEOUT;
+ goto bail;
+ }
+
+ dbus_message_get_args(reply, &error,
+ DBUS_TYPE_INT32, &ret,
+ DBUS_TYPE_INVALID
+ );
+ if (ret == 6)
+ ret = 0;
+
+ if (ret) {
+ fprintf(stderr, "%s failed with error %d. %s\n", argv[0], ret, wpantund_status_to_cstr(ret));
+ print_error_diagnosis(ret);
+ }
+ }
+
+bail:
+
+ if (connection)
+ dbus_connection_unref(connection);
+
+ if (message)
+ dbus_message_unref(message);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_error_free(&error);
+
+ return ret;
+}
diff --git a/src/wpanctl/tool-cmd-poll.h b/src/wpanctl/tool-cmd-poll.h
new file mode 100644
index 0000000..681f585
--- /dev/null
+++ b/src/wpanctl/tool-cmd-poll.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef WPANCTL_TOOL_CMD_POLL_H
+#define WPANCTL_TOOL_CMD_POLL_H
+
+#include "wpanctl-utils.h"
+
+int tool_cmd_poll(int argc, char* argv[]);
+
+#endif
diff --git a/src/wpanctl/tool-cmd-remove-route.c b/src/wpanctl/tool-cmd-remove-route.c
new file mode 100644
index 0000000..aac30a8
--- /dev/null
+++ b/src/wpanctl/tool-cmd-remove-route.c
@@ -0,0 +1,248 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * This file implements the "remove-route" command in wpanctl
+ *
+ */
+
+#include <getopt.h>
+#include "wpanctl-utils.h"
+#include "tool-cmd-remove-route.h"
+#include "assert-macros.h"
+#include "args.h"
+#include "assert-macros.h"
+#include "wpan-dbus-v1.h"
+#include "string-utils.h"
+
+#include <arpa/inet.h>
+#include <errno.h>
+
+const char remove_route_cmd_syntax[] = "[args] <prefix>";
+
+static const arg_list_item_t remove_route_option_list[] = {
+ {'h', "help", NULL, "Print Help"},
+ {'l', "length", "in bytes", "Specifies the route prefix length (default is 8)"},
+ {'d', "domain", NULL, "Domain id for the route (default is zero)"},
+ {0}
+};
+
+int tool_cmd_remove_route(int argc, char* argv[])
+{
+ int ret = 0;
+ int c;
+ int timeout = DEFAULT_TIMEOUT_IN_SECONDS * 1000;
+
+ DBusConnection* connection = NULL;
+ DBusMessage *message = NULL;
+ DBusMessage *reply = NULL;
+ DBusError error;
+
+ const char *route_prefix = NULL;
+ int prefix_len = 8;
+ uint16_t domain_id = 0;
+
+ dbus_error_init(&error);
+
+ while (1) {
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"length", required_argument, 0, 'l'},
+ {"domain", required_argument, 0, 'd'},
+ {0, 0, 0, 0}
+ };
+
+ int option_index = 0;
+ c = getopt_long(argc, argv, "hl:d:", long_options,
+ &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_arg_list_help(remove_route_option_list, argv[0],
+ remove_route_cmd_syntax);
+ ret = ERRORCODE_HELP;
+ goto bail;
+
+ case 'l' :
+ prefix_len = (int) strtol(optarg, NULL, 0);
+ break;
+
+ case 'd':
+ domain_id = (uint16_t) strtol(optarg, NULL, 0);
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ route_prefix = argv[optind];
+ optind++;
+ }
+
+ if (optind < argc) {
+ fprintf(stderr,
+ "%s: error: Unexpected extra argument: \"%s\"\n",
+ argv[0], argv[optind]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ if (gInterfaceName[0] == 0) {
+ fprintf(stderr,
+ "%s: error: No WPAN interface set (use the `cd` command, or the `-I` argument for `wpanctl`).\n",
+ argv[0]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
+
+ if (!connection) {
+ dbus_error_free(&error);
+ dbus_error_init(&error);
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ }
+
+ require_string(connection != NULL, bail, error.message);
+
+ {
+ DBusMessageIter iter;
+ DBusMessageIter list_iter;
+ char path[DBUS_MAXIMUM_NAME_LENGTH+1];
+ char interface_dbus_name[DBUS_MAXIMUM_NAME_LENGTH+1];
+ ret = lookup_dbus_name_from_interface(interface_dbus_name, gInterfaceName);
+ if (ret != 0) {
+ goto bail;
+ }
+ snprintf(path,
+ sizeof(path),
+ "%s/%s",
+ WPANTUND_DBUS_PATH,
+ gInterfaceName);
+
+ message = dbus_message_new_method_call(
+ interface_dbus_name,
+ path,
+ WPANTUND_DBUS_APIv1_INTERFACE,
+ WPANTUND_IF_CMD_ROUTE_REMOVE
+ );
+
+ if ((route_prefix != NULL) && (0 <= prefix_len) && (prefix_len <= 16)) {
+ uint8_t prefix_bytes[16];
+
+ memset(prefix_bytes, 0, sizeof(prefix_bytes));
+
+ // So the prefix could either be
+ // specified like an IPv6 address, or
+ // specified as a bunch of hex numbers.
+ // We use the presence of a colon (':')
+ // to differentiate.
+ if (strstr(route_prefix, ":")) {
+
+ // Address-style
+ int bits = inet_pton(AF_INET6, route_prefix, prefix_bytes);
+ if (bits < 0) {
+ fprintf(stderr,
+ "Bad prefix \"%s\", errno=%d (%s)\n",
+ route_prefix,
+ errno,
+ strerror(errno));
+ goto bail;
+ } else if (bits == 0) {
+ fprintf(stderr, "Bad prefix \"%s\"\n", route_prefix);
+ goto bail;
+ }
+ } else {
+ // DATA-style
+ int length = parse_string_into_data(prefix_bytes,
+ 16,
+ route_prefix);
+ if(length<=0) {
+ fprintf(stderr, "Bad prefix \"%s\"\n", route_prefix);
+ goto bail;
+ }
+ }
+
+ fprintf(stderr, "Removing route prefix \"%s\" with len %d, domain-id %d.\n",
+ route_prefix, prefix_len, domain_id
+ );
+
+ uint8_t *addr = prefix_bytes;
+ uint8_t len = (uint8_t)prefix_len;
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &addr, len,
+ DBUS_TYPE_INVALID
+ );
+ } else {
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, "", 0,
+ DBUS_TYPE_INVALID
+ );
+ }
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_UINT16, &domain_id,
+ DBUS_TYPE_INVALID
+ );
+
+ reply = dbus_connection_send_with_reply_and_block(
+ connection,
+ message,
+ timeout,
+ &error
+ );
+
+ if (!reply) {
+ fprintf(stderr, "%s: error: %s\n", argv[0], error.message);
+ ret = ERRORCODE_TIMEOUT;
+ goto bail;
+ }
+
+ dbus_message_get_args(reply, &error,
+ DBUS_TYPE_INT32, &ret,
+ DBUS_TYPE_INVALID
+ );
+
+ if (!ret) {
+ fprintf(stderr, "Route prefix removed.\n");
+ } else {
+ fprintf(stderr, "%s failed with error %d. %s\n", argv[0], ret, wpantund_status_to_cstr(ret));
+ print_error_diagnosis(ret);
+ }
+ }
+
+bail:
+
+ if (connection)
+ dbus_connection_unref(connection);
+
+ if (message)
+ dbus_message_unref(message);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_error_free(&error);
+
+ return ret;
+}
diff --git a/src/wpanctl/tool-cmd-remove-route.h b/src/wpanctl/tool-cmd-remove-route.h
new file mode 100644
index 0000000..ec10115
--- /dev/null
+++ b/src/wpanctl/tool-cmd-remove-route.h
@@ -0,0 +1,31 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * This file declares the methods for "remove-route" command
+ * in wpanctl.
+ *
+ */
+
+#ifndef WPANCTL_TOOL_CMD_REMOVE_ROUTE_H
+#define WPANCTL_TOOL_CMD_REMOVE_ROUTE_H
+
+#include "wpanctl-utils.h"
+
+int tool_cmd_remove_route(int argc, char* argv[]);
+
+#endif
diff --git a/src/wpanctl/tool-cmd-reset.c b/src/wpanctl/tool-cmd-reset.c
new file mode 100644
index 0000000..8406b00
--- /dev/null
+++ b/src/wpanctl/tool-cmd-reset.c
@@ -0,0 +1,164 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <getopt.h>
+#include "wpanctl-utils.h"
+#include "tool-cmd-scan.h"
+#include "assert-macros.h"
+#include "wpan-dbus-v1.h"
+#include "args.h"
+
+const char reset_cmd_syntax[] = "[args]";
+
+static const arg_list_item_t reset_option_list[] = {
+ {'h', "help", NULL, "Print Help"},
+ {'t', "timeout", "ms", "Set timeout period"},
+ {0}
+};
+
+int tool_cmd_reset(int argc, char *argv[])
+{
+ int ret = 0;
+ int c;
+ int timeout = 10 * 1000;
+ DBusConnection* connection = NULL;
+ DBusMessage *message = NULL;
+ DBusMessage *reply = NULL;
+ DBusError error;
+
+ dbus_error_init(&error);
+
+ while (1) {
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"timeout", required_argument, 0, 't'},
+ {0, 0, 0, 0}
+ };
+
+ int option_index = 0;
+ c = getopt_long(argc, argv, "ht:", long_options, &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_arg_list_help(reset_option_list, argv[0],
+ reset_cmd_syntax);
+ ret = ERRORCODE_HELP;
+ goto bail;
+
+ case 't':
+ timeout = strtol(optarg, NULL, 0);
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ fprintf(stderr,
+ "%s: error: Unexpected extra argument: \"%s\"\n",
+ argv[0], argv[optind]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ if (gInterfaceName[0] == 0) {
+ fprintf(stderr,
+ "%s: error: No WPAN interface set (use the `cd` command, or the `-I` argument for `wpanctl`).\n",
+ argv[0]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
+
+ if (!connection) {
+ dbus_error_free(&error);
+ dbus_error_init(&error);
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ }
+
+ require_string(connection != NULL, bail, error.message);
+
+ {
+ DBusMessageIter iter;
+ DBusMessageIter list_iter;
+ char path[DBUS_MAXIMUM_NAME_LENGTH+1];
+ char interface_dbus_name[DBUS_MAXIMUM_NAME_LENGTH+1];
+ ret = lookup_dbus_name_from_interface(interface_dbus_name, gInterfaceName);
+ if (ret != 0) {
+ print_error_diagnosis(ret);
+ goto bail;
+ }
+ snprintf(path,
+ sizeof(path),
+ "%s/%s",
+ WPANTUND_DBUS_PATH,
+ gInterfaceName);
+
+ message = dbus_message_new_method_call(
+ interface_dbus_name,
+ path,
+ WPANTUND_DBUS_APIv1_INTERFACE,
+ WPANTUND_IF_CMD_RESET
+ );
+
+ fprintf(stderr, "Resetting NCP. . .\n");
+
+ reply = dbus_connection_send_with_reply_and_block(
+ connection,
+ message,
+ timeout,
+ &error
+ );
+
+ if (!reply) {
+ fprintf(stderr, "%s: error: %s\n", argv[0], error.message);
+ ret = ERRORCODE_TIMEOUT;
+ goto bail;
+ }
+
+ dbus_message_get_args(reply, &error,
+ DBUS_TYPE_INT32, &ret,
+ DBUS_TYPE_INVALID
+ );
+
+ if (ret == 6)
+ ret = 0;
+ }
+
+bail:
+
+ if (connection)
+ dbus_connection_unref(connection);
+
+ if (message)
+ dbus_message_unref(message);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_error_free(&error);
+
+ return ret;
+}
diff --git a/src/wpanctl/tool-cmd-reset.h b/src/wpanctl/tool-cmd-reset.h
new file mode 100644
index 0000000..7283b28
--- /dev/null
+++ b/src/wpanctl/tool-cmd-reset.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef WPANCTL_TOOL_CMD_RESET_H
+#define WPANCTL_TOOL_CMD_RESET_H
+
+#include "wpanctl-utils.h"
+
+int tool_cmd_reset(int argc, char* argv[]);
+
+#endif
diff --git a/src/wpanctl/tool-cmd-resume.c b/src/wpanctl/tool-cmd-resume.c
new file mode 100644
index 0000000..db4972b
--- /dev/null
+++ b/src/wpanctl/tool-cmd-resume.c
@@ -0,0 +1,165 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <getopt.h>
+#include "wpanctl-utils.h"
+#include "tool-cmd-resume.h"
+#include "assert-macros.h"
+#include "wpan-dbus-v1.h"
+#include "args.h"
+
+const char resume_cmd_syntax[] = "[args]";
+
+static const arg_list_item_t resume_option_list[] = {
+ {'h', "help", NULL, "Print Help"},
+ {'t', "timeout", "ms", "Set timeout period"},
+ {0}
+};
+
+int tool_cmd_resume(int argc, char *argv[])
+{
+ int ret = 0;
+ int c;
+ int timeout = 10 * 1000;
+ DBusConnection *connection = NULL;
+ DBusMessage *message = NULL;
+ DBusMessage *reply = NULL;
+ DBusError error;
+
+ dbus_error_init(&error);
+
+ while (1) {
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"timeout", required_argument, 0, 't'},
+ {0, 0, 0, 0}
+ };
+
+ int option_index = 0;
+ c = getopt_long(argc, argv, "ht:", long_options, &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_arg_list_help(resume_option_list, argv[0],
+ resume_cmd_syntax);
+ ret = ERRORCODE_HELP;
+ goto bail;
+
+ case 't':
+ timeout = strtol(optarg, NULL, 0);
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ fprintf(stderr,
+ "%s: error: Unexpected extra argument: \"%s\"\n",
+ argv[0], argv[optind]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ if (gInterfaceName[0] == 0) {
+ fprintf(stderr,
+ "%s: error: No WPAN interface set (use the `cd` command, or the `-I` argument for `wpanctl`).\n",
+ argv[0]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
+
+ if (!connection) {
+ dbus_error_free(&error);
+ dbus_error_init(&error);
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ }
+
+ require_string(connection != NULL, bail, error.message);
+
+ {
+ DBusMessageIter iter;
+ DBusMessageIter list_iter;
+ char path[DBUS_MAXIMUM_NAME_LENGTH+1];
+ char interface_dbus_name[DBUS_MAXIMUM_NAME_LENGTH+1];
+ ret = lookup_dbus_name_from_interface(interface_dbus_name, gInterfaceName);
+ if (ret != 0) {
+ print_error_diagnosis(ret);
+ goto bail;
+ }
+ snprintf(path,
+ sizeof(path),
+ "%s/%s",
+ WPANTUND_DBUS_PATH,
+ gInterfaceName);
+
+ message = dbus_message_new_method_call(
+ interface_dbus_name,
+ path,
+ WPANTUND_DBUS_APIv1_INTERFACE,
+ WPANTUND_IF_CMD_ATTACH
+ );
+
+ fprintf(stderr, "Resuming saved WPAN. . .\n");
+
+ reply = dbus_connection_send_with_reply_and_block(
+ connection,
+ message,
+ timeout,
+ &error
+ );
+
+ if (!reply) {
+ fprintf(stderr, "%s: error: %s\n", argv[0], error.message);
+ ret = ERRORCODE_TIMEOUT;
+ goto bail;
+ }
+
+ dbus_message_get_args(reply, &error,
+ DBUS_TYPE_INT32, &ret,
+ DBUS_TYPE_INVALID
+ );
+ if (ret) {
+ fprintf(stderr, "%s failed with error %d. %s\n", argv[0], ret, wpantund_status_to_cstr(ret));
+ print_error_diagnosis(ret);
+ }
+ }
+
+bail:
+
+ if (connection)
+ dbus_connection_unref(connection);
+
+ if (message)
+ dbus_message_unref(message);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_error_free(&error);
+
+ return ret;
+}
diff --git a/src/wpanctl/tool-cmd-resume.h b/src/wpanctl/tool-cmd-resume.h
new file mode 100644
index 0000000..991d277
--- /dev/null
+++ b/src/wpanctl/tool-cmd-resume.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef WPANCTL_TOOL_CMD_RESUME_H
+#define WPANCTL_TOOL_CMD_RESUME_H
+
+#include "wpanctl-utils.h"
+
+int tool_cmd_resume(int argc, char* argv[]);
+
+#endif
diff --git a/src/wpanctl/tool-cmd-scan.c b/src/wpanctl/tool-cmd-scan.c
new file mode 100644
index 0000000..962b0e8
--- /dev/null
+++ b/src/wpanctl/tool-cmd-scan.c
@@ -0,0 +1,367 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <getopt.h>
+#include "wpanctl-utils.h"
+#include "tool-cmd-scan.h"
+#include "assert-macros.h"
+#include "wpan-dbus-v1.h"
+#include "string-utils.h"
+#include "args.h"
+
+const char scan_cmd_syntax[] = "[args] [seconds-to-scan]";
+
+static const arg_list_item_t scan_option_list[] = {
+ {'h', "help", NULL, "Print Help"},
+ {'t', "timeout", "ms", "Set timeout period"},
+ {'c', "channel", "channel", "Set the desired channel"},
+ {'e', "energy", NULL, "Perform an energy scan"},
+ {0}
+};
+
+int gScannedNetworkCount = 0;
+struct wpan_network_info_s gScannedNetworks[SCANNED_NET_BUFFER_SIZE];
+
+static bool sEnergyScan;
+
+static void
+print_scan_header(void)
+{
+ if (sEnergyScan) {
+ printf(" Ch | RSSI\n");
+ printf(" ----+-------\n");
+
+ return;
+ }
+
+ printf(
+ " | Joinable | NetworkName | PAN ID | Ch | XPanID | HWAddr | RSSI\n");
+ printf(
+ "---+----------+--------------------+--------+----+------------------+------------------+------\n");
+
+}
+
+static DBusHandlerResult
+dbus_beacon_handler(
+ DBusConnection *connection,
+ DBusMessage * message,
+ void * user_data
+) {
+ DBusMessageIter iter;
+ int ret;
+ struct wpan_network_info_s network_info;
+
+ if (!dbus_message_is_signal(message, WPANTUND_DBUS_APIv1_INTERFACE, WPANTUND_IF_SIGNAL_NET_SCAN_BEACON)) {
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ dbus_message_iter_init(message, &iter);
+
+ ret = parse_network_info_from_iter(&network_info, &iter);
+
+ require_noerr(ret, bail);
+
+ if (network_info.network_name[0]) {
+ if (gScannedNetworkCount < SCANNED_NET_BUFFER_SIZE) {
+ gScannedNetworks[gScannedNetworkCount++] = network_info;
+ printf("%2d", gScannedNetworkCount);
+ } else {
+ printf("--"); //This means that we cannot act on the PAN as we do not save the info
+ }
+ } else {
+ printf(" ");
+ }
+
+ printf(" | %s", network_info.allowing_join ? " YES" : " NO");
+
+ if (network_info.network_name[0]) {
+ printf(" | \"%s\"%s",
+ network_info.network_name,
+ &" "[strlen(network_info.network_name)]);
+ } else {
+ printf(" | ------ NONE ------");
+ }
+
+ printf(" | 0x%04X", network_info.pan_id);
+ printf(" | %2d", network_info.channel);
+ printf(" | %016llX", (unsigned long long)network_info.xpanid);
+ printf(" | %02X%02X%02X%02X%02X%02X%02X%02X",
+ network_info.hwaddr[0],
+ network_info.hwaddr[1],
+ network_info.hwaddr[2],
+ network_info.hwaddr[3],
+ network_info.hwaddr[4],
+ network_info.hwaddr[5],
+ network_info.hwaddr[6],
+ network_info.hwaddr[7]);
+ printf(" | %4d", network_info.rssi);
+ printf("\n");
+
+bail:
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+dbus_energy_scan_handler(
+ DBusConnection *connection,
+ DBusMessage * message,
+ void * user_data
+) {
+ DBusMessageIter iter;
+ int ret;
+ int16_t channel;
+ int8_t maxRssi;
+
+ if (!dbus_message_is_signal(message, WPANTUND_DBUS_APIv1_INTERFACE, WPANTUND_IF_SIGNAL_ENERGY_SCAN_RESULT)) {
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ dbus_message_iter_init(message, &iter);
+
+ ret = parse_energy_scan_result_from_iter(&channel, &maxRssi, &iter);
+
+ require_noerr(ret, bail);
+
+ printf(" %4d | %4d\n", channel, maxRssi);
+
+bail:
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+dbus_signal_handler(
+ DBusConnection *connection,
+ DBusMessage * message,
+ void * user_data
+) {
+ if (sEnergyScan) {
+ return dbus_energy_scan_handler(connection, message, user_data);
+ }
+
+ return dbus_beacon_handler(connection, message, user_data);
+}
+
+static const char gDBusObjectManagerMatchString[] =
+ "type='signal'"
+// ",interface='" WPANTUND_DBUS_APIv1_INTERFACE "'"
+ ;
+
+
+int tool_cmd_scan(int argc, char *argv[])
+{
+ int ret = 0;
+ int c;
+ int timeout = DEFAULT_TIMEOUT_IN_SECONDS * 1000;
+ DBusConnection* connection = NULL;
+ DBusMessage *message = NULL;
+ DBusMessage *reply = NULL;
+ DBusPendingCall *pending = NULL;
+ DBusError error;
+ int32_t scan_period = 0;
+ uint32_t channel_mask = 0;
+
+ dbus_error_init(&error);
+
+ sEnergyScan = false;
+
+ while (1) {
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"timeout", required_argument, 0, 't'},
+ {"channel", required_argument, 0, 'c'},
+ {"energy", no_argument, 0, 'e'},
+ {0, 0, 0, 0}
+ };
+
+ int option_index = 0;
+ c = getopt_long(argc, argv, "hc:t:e", long_options,
+ &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_arg_list_help(scan_option_list, argv[0],
+ scan_cmd_syntax);
+ ret = ERRORCODE_HELP;
+ goto bail;
+
+ case 't':
+ timeout = strtol(optarg, NULL, 0);
+ break;
+
+ case 'c':
+ channel_mask = strtomask_uint32(optarg);
+ break;
+
+ case 'e':
+ sEnergyScan = true;
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ if (scan_period == 0) {
+ scan_period = strtol(argv[optind], NULL, 0);
+ optind++;
+ }
+ }
+
+ if (optind < argc) {
+ fprintf(stderr,
+ "%s: error: Unexpected extra argument: \"%s\"\n",
+ argv[0], argv[optind]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ if (gInterfaceName[0] == 0) {
+ fprintf(stderr,
+ "%s: error: No WPAN interface set (use the `cd` command, or the `-I` argument for `wpanctl`).\n",
+ argv[0]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
+
+ if (!connection) {
+ dbus_error_free(&error);
+ dbus_error_init(&error);
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ }
+
+ require_string(connection != NULL, bail, error.message);
+
+ dbus_bus_add_match(connection, gDBusObjectManagerMatchString, &error);
+
+ require_string(error.name == NULL, bail, error.message);
+
+ dbus_connection_add_filter(connection, &dbus_signal_handler, NULL, NULL);
+
+ {
+ char path[DBUS_MAXIMUM_NAME_LENGTH+1];
+ char interface_dbus_name[DBUS_MAXIMUM_NAME_LENGTH+1];
+ DBusMessageIter iter;
+ ret = lookup_dbus_name_from_interface(interface_dbus_name, gInterfaceName);
+
+ if (ret != 0) {
+ print_error_diagnosis(ret);
+ goto bail;
+ }
+
+ snprintf(
+ path,
+ sizeof(path),
+ "%s/%s",
+ WPANTUND_DBUS_PATH,
+ gInterfaceName
+ );
+
+ message = dbus_message_new_method_call(
+ interface_dbus_name,
+ path,
+ WPANTUND_DBUS_APIv1_INTERFACE,
+ sEnergyScan? WPANTUND_IF_CMD_ENERGY_SCAN_START : WPANTUND_IF_CMD_NET_SCAN_START
+ );
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_UINT32, &channel_mask,
+ DBUS_TYPE_INVALID
+ );
+
+ print_scan_header();
+
+ if (!sEnergyScan) {
+ gScannedNetworkCount = 0;
+ }
+
+ if(!dbus_connection_send_with_reply(
+ connection,
+ message,
+ &pending,
+ timeout
+ )) {
+ fprintf(stderr, "%s: error: IPC failure\n", argv[0]);
+ ret = ERRORCODE_UNKNOWN;
+ goto bail;
+ }
+
+ while ((dbus_connection_get_dispatch_status(connection) == DBUS_DISPATCH_DATA_REMAINS)
+ || dbus_connection_has_messages_to_send(connection)
+ || !dbus_pending_call_get_completed(pending)
+ ) {
+ dbus_connection_read_write_dispatch(connection, 5000 /*ms*/);
+ }
+
+ reply = dbus_pending_call_steal_reply(pending);
+
+ require(reply!=NULL, bail);
+
+
+ dbus_message_iter_init(reply, &iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32) {
+ fprintf(stderr, "%s: error: Server returned a bad response ('%c')\n",
+ argv[0], dbus_message_iter_get_arg_type(&iter));
+ ret = ERRORCODE_UNKNOWN;
+ goto bail;
+ }
+
+ // Get return code
+ dbus_message_iter_get_basic(&iter, &ret);
+
+ if (ret) {
+ fprintf(stderr, "%s failed with error %d. %s\n", argv[0], ret, wpantund_status_to_cstr(ret));
+ print_error_diagnosis(ret);
+ goto bail;
+ }
+ }
+
+
+bail:
+
+ if (reply) {
+ dbus_message_unref(reply);
+ }
+
+ if (pending != NULL) {
+ dbus_pending_call_unref(pending);
+ }
+
+ if (message) {
+ dbus_message_unref(message);
+ }
+
+ if (connection) {
+ dbus_bus_remove_match(connection, gDBusObjectManagerMatchString, NULL);
+ dbus_connection_remove_filter(connection,&dbus_signal_handler,NULL);
+ dbus_connection_unref(connection);
+ }
+
+ dbus_error_free(&error);
+
+ return ret;
+}
diff --git a/src/wpanctl/tool-cmd-scan.h b/src/wpanctl/tool-cmd-scan.h
new file mode 100644
index 0000000..0029a66
--- /dev/null
+++ b/src/wpanctl/tool-cmd-scan.h
@@ -0,0 +1,32 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef WPANCTL_TOOL_CMD_SCAN_H
+#define WPANCTL_TOOL_CMD_SCAN_H
+
+#define SCANNED_NET_BUFFER_SIZE 250
+
+#include "wpanctl-utils.h"
+
+int tool_cmd_scan(int argc, char* argv[]);
+
+extern int gScannedNetworkCount;
+extern struct wpan_network_info_s gScannedNetworks[];
+
+#endif
diff --git a/src/wpanctl/tool-cmd-setprop.c b/src/wpanctl/tool-cmd-setprop.c
new file mode 100644
index 0000000..b366fa1
--- /dev/null
+++ b/src/wpanctl/tool-cmd-setprop.c
@@ -0,0 +1,242 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <getopt.h>
+#include "wpanctl-utils.h"
+#include "tool-cmd-setprop.h"
+#include "assert-macros.h"
+#include "args.h"
+#include "assert-macros.h"
+#include "wpan-dbus-v1.h"
+#include "string-utils.h"
+
+const char setprop_cmd_syntax[] = "[args] <property-name> <property-value>";
+
+static const arg_list_item_t setprop_option_list[] = {
+ {'h', "help", NULL, "Print Help"},
+ {'t', "timeout", "ms", "Set timeout period"},
+ {'d', "data", NULL, "Value is binary data (in hex)"},
+ {'s', "string", NULL, "Value is a string"},
+ {'v', "value", "property-value", "Useful when the value starts with a '-'"},
+ {0}
+};
+
+int tool_cmd_setprop(int argc, char* argv[])
+{
+ int ret = 0;
+ int c;
+ int timeout = 30 * 1000;
+ DBusConnection* connection = NULL;
+ DBusMessage *message = NULL;
+ DBusMessage *reply = NULL;
+ DBusError error;
+ const char* property_name = NULL;
+ char* property_value = NULL;
+
+ enum {
+ kPropertyType_String,
+ kPropertyType_Data,
+ } property_type = kPropertyType_String;
+
+ dbus_error_init(&error);
+
+ while (1) {
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"timeout", required_argument, 0, 't'},
+ {"data", no_argument, 0, 'd'},
+ {"string", no_argument, 0, 's'},
+ {"value", required_argument, 0, 'v'},
+ {0, 0, 0, 0}
+ };
+
+ int option_index = 0;
+ c = getopt_long(argc, argv, "ht:dsv:", long_options,
+ &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_arg_list_help(setprop_option_list,
+ argv[0], setprop_cmd_syntax);
+ ret = ERRORCODE_HELP;
+ goto bail;
+
+ case 't':
+ timeout = strtol(optarg, NULL, 0);
+ break;
+
+ case 'd':
+ property_type = kPropertyType_Data;
+ break;
+
+ case 's':
+ property_type = kPropertyType_String;
+ break;
+
+ case 'v':
+ property_value = optarg;
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ if (!property_name) {
+ property_name = argv[optind];
+ optind++;
+ }
+ }
+
+ if (optind < argc) {
+ if (!property_value) {
+ property_value = argv[optind];
+ optind++;
+ }
+ }
+
+ if (optind < argc) {
+ fprintf(stderr,
+ "%s: error: Unexpected extra argument: \"%s\"\n",
+ argv[0], argv[optind]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ if (!property_name) {
+ fprintf(stderr, "%s: error: Missing property name.\n", argv[0]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ if (!property_value) {
+ fprintf(stderr, "%s: error: Missing property value.\n", argv[0]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ if (gInterfaceName[0] == 0) {
+ fprintf(stderr,
+ "%s: error: No WPAN interface set (use the `cd` command, or the `-I` argument for `wpanctl`).\n",
+ argv[0]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
+
+ if (!connection) {
+ dbus_error_free(&error);
+ dbus_error_init(&error);
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ }
+
+ require_string(connection != NULL, bail, error.message);
+
+ {
+ DBusMessageIter iter;
+ DBusMessageIter list_iter;
+ char path[DBUS_MAXIMUM_NAME_LENGTH+1];
+ char interface_dbus_name[DBUS_MAXIMUM_NAME_LENGTH+1];
+ ret = lookup_dbus_name_from_interface(interface_dbus_name, gInterfaceName);
+ if (ret != 0) {
+ print_error_diagnosis(ret);
+ goto bail;
+ }
+ snprintf(path,
+ sizeof(path),
+ "%s/%s",
+ WPANTUND_DBUS_PATH,
+ gInterfaceName);
+
+ message = dbus_message_new_method_call(
+ interface_dbus_name,
+ path,
+ WPANTUND_DBUS_APIv1_INTERFACE,
+ WPANTUND_IF_CMD_PROP_SET
+ );
+
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_STRING, &property_name,
+ DBUS_TYPE_INVALID
+ );
+
+ if (property_type == kPropertyType_String) {
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_STRING, &property_value,
+ DBUS_TYPE_INVALID
+ );
+ } else if (property_type == kPropertyType_Data) {
+ int length = parse_string_into_data((uint8_t*)property_value,
+ strlen(property_value),
+ property_value);
+ dbus_message_append_args(
+ message,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &property_value, length,
+ DBUS_TYPE_INVALID
+ );
+ } else {
+ fprintf(stderr, "%s: error: Bad property type\n", argv[0]);
+ ret = ERRORCODE_UNKNOWN;
+ goto bail;
+ }
+
+ reply = dbus_connection_send_with_reply_and_block(
+ connection,
+ message,
+ timeout,
+ &error
+ );
+
+ if (!reply) {
+ fprintf(stderr, "%s: error: %s\n", argv[0], error.message);
+ ret = ERRORCODE_TIMEOUT;
+ goto bail;
+ }
+
+ dbus_message_get_args(reply, &error,
+ DBUS_TYPE_INT32, &ret,
+ DBUS_TYPE_INVALID
+ );
+ if (ret)
+ fprintf(stderr, "%s failed with error %d. %s\n", argv[0], ret, wpantund_status_to_cstr(ret));
+ }
+
+bail:
+
+ if (connection)
+ dbus_connection_unref(connection);
+
+ if (message)
+ dbus_message_unref(message);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_error_free(&error);
+
+ return ret;
+}
diff --git a/src/wpanctl/tool-cmd-setprop.h b/src/wpanctl/tool-cmd-setprop.h
new file mode 100644
index 0000000..e20322d
--- /dev/null
+++ b/src/wpanctl/tool-cmd-setprop.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef WPANCTL_TOOL_CMD_SETPROP_H
+#define WPANCTL_TOOL_CMD_SETPROP_H
+
+#include "wpanctl-utils.h"
+
+int tool_cmd_setprop(int argc, char* argv[]);
+
+#endif
diff --git a/src/wpanctl/tool-cmd-status.c b/src/wpanctl/tool-cmd-status.c
new file mode 100644
index 0000000..0a57d4e
--- /dev/null
+++ b/src/wpanctl/tool-cmd-status.c
@@ -0,0 +1,159 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <getopt.h>
+#include "wpanctl-utils.h"
+#include "tool-cmd-status.h"
+#include "assert-macros.h"
+#include "wpan-dbus-v1.h"
+#include "args.h"
+
+const char status_cmd_syntax[] = "[args]";
+
+static const arg_list_item_t status_option_list[] = {
+ {'h', "help", NULL, "Print Help"},
+ {'t', "timeout", "ms", "Set timeout period"},
+ {0}
+};
+
+int tool_cmd_status(int argc, char *argv[])
+{
+ int ret = 0;
+ int c;
+ int timeout = 10 * 1000;
+ DBusConnection *connection = NULL;
+ DBusMessage *message = NULL;
+ DBusMessage *reply = NULL;
+ DBusError error;
+
+ dbus_error_init(&error);
+
+ while (1) {
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"timeout", required_argument, 0, 't'},
+ {0, 0, 0, 0}
+ };
+
+ int option_index = 0;
+ c = getopt_long(argc, argv, "ht:", long_options, &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_arg_list_help(status_option_list, argv[0],
+ status_cmd_syntax);
+ ret = ERRORCODE_HELP;
+ goto bail;
+
+ case 't':
+ timeout = strtol(optarg, NULL, 0);
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ fprintf(stderr,
+ "%s: error: Unexpected extra argument: \"%s\"\n",
+ argv[0], argv[optind]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ if (gInterfaceName[0] == 0) {
+ fprintf(stderr,
+ "%s: error: No WPAN interface set (use the `cd` command, or the `-I` argument for `wpanctl`).\n",
+ argv[0]);
+ ret = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
+
+ if (!connection) {
+ dbus_error_free(&error);
+ dbus_error_init(&error);
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ }
+
+ require_string(connection != NULL, bail, error.message);
+
+ {
+ DBusMessageIter iter;
+ DBusMessageIter list_iter;
+ char path[DBUS_MAXIMUM_NAME_LENGTH+1];
+ char interface_dbus_name[DBUS_MAXIMUM_NAME_LENGTH+1];
+ ret = lookup_dbus_name_from_interface(interface_dbus_name, gInterfaceName);
+ if (ret != 0) {
+ print_error_diagnosis(ret);
+ goto bail;
+ }
+ snprintf(path,
+ sizeof(path),
+ "%s/%s",
+ WPANTUND_DBUS_PATH,
+ gInterfaceName);
+
+ message = dbus_message_new_method_call(
+ interface_dbus_name,
+ path,
+ WPANTUND_DBUS_APIv1_INTERFACE,
+ WPANTUND_IF_CMD_STATUS
+ );
+
+ reply = dbus_connection_send_with_reply_and_block(
+ connection,
+ message,
+ timeout,
+ &error
+ );
+
+ if (!reply) {
+ fprintf(stderr, "%s: error: %s\n", argv[0], error.message);
+ ret = ERRORCODE_TIMEOUT;
+ goto bail;
+ }
+
+ dbus_message_iter_init(reply, &iter);
+
+ fprintf(stdout, "%s => ", gInterfaceName);
+ dump_info_from_iter(stdout, &iter, 0, false, false);
+ }
+
+bail:
+
+ if (connection)
+ dbus_connection_unref(connection);
+
+ if (message)
+ dbus_message_unref(message);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_error_free(&error);
+
+ return ret;
+}
diff --git a/src/wpanctl/tool-cmd-status.h b/src/wpanctl/tool-cmd-status.h
new file mode 100644
index 0000000..8b69576
--- /dev/null
+++ b/src/wpanctl/tool-cmd-status.h
@@ -0,0 +1,27 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef WPANCTL_TOOL_CMD_STATUS_H
+#define WPANCTL_TOOL_CMD_STATUS_H
+
+#include "wpanctl-utils.h"
+
+int tool_cmd_status(int argc, char* argv[]);
+
+#endif
diff --git a/src/wpanctl/wpanctl-cmds.h b/src/wpanctl/wpanctl-cmds.h
new file mode 100644
index 0000000..d738cda
--- /dev/null
+++ b/src/wpanctl/wpanctl-cmds.h
@@ -0,0 +1,161 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef wpantund_wpanctl_cmds_h
+#define wpantund_wpanctl_cmds_h
+
+#include "tool-cmd-scan.h"
+#include "tool-cmd-join.h"
+#include "tool-cmd-form.h"
+#include "tool-cmd-leave.h"
+#include "tool-cmd-permit-join.h"
+#include "tool-cmd-list.h"
+#include "tool-cmd-status.h"
+#include "tool-cmd-mfg.h"
+#include "tool-cmd-resume.h"
+#include "tool-cmd-reset.h"
+#include "tool-cmd-begin-low-power.h"
+#include "tool-cmd-begin-net-wake.h"
+#include "tool-cmd-host-did-wake.h"
+#include "tool-cmd-getprop.h"
+#include "tool-cmd-setprop.h"
+#include "tool-cmd-cd.h"
+#include "tool-cmd-poll.h"
+#include "tool-cmd-config-gateway.h"
+#include "tool-cmd-add-route.h"
+#include "tool-cmd-remove-route.h"
+#include "tool-cmd-pcap.h"
+
+#include "wpanctl-utils.h"
+
+#define WPANCTL_CLI_COMMANDS \
+ { \
+ "join", \
+ "Join a WPAN.", \
+ &tool_cmd_join \
+ }, \
+ { "connect", "", &tool_cmd_join, 1 }, \
+ { \
+ "form", \
+ "Form a new WPAN.", \
+ &tool_cmd_form \
+ }, \
+ { \
+ "attach", \
+ "Attach/resume a previously commissioned network", \
+ &tool_cmd_resume \
+ }, \
+ { "resume", "", &tool_cmd_resume, 1 }, \
+ { \
+ "reset", \
+ "Reset the NCP", \
+ &tool_cmd_reset \
+ }, \
+ { \
+ "begin-low-power", \
+ "Enter low-power mode", \
+ &tool_cmd_begin_low_power \
+ }, \
+ { "lurk", "", &tool_cmd_begin_low_power, 1 }, \
+ { "wake", "", &tool_cmd_status, 1 }, \
+ { \
+ "leave", \
+ "Abandon the currently connected WPAN.", \
+ &tool_cmd_leave \
+ }, \
+ { "disconnect", "", &tool_cmd_leave, 1 }, \
+ { \
+ "poll", \
+ "Poll the parent immediately to see if there is IP traffic", \
+ &tool_cmd_poll \
+ }, \
+ { \
+ "config-gateway", \
+ "Configure gateway", \
+ &tool_cmd_config_gateway \
+ }, \
+ { \
+ "add-route", \
+ "Add external route prefix", \
+ &tool_cmd_add_route \
+ }, \
+ { \
+ "remove-route", \
+ "Remove external route prefix", \
+ &tool_cmd_remove_route \
+ }, \
+ { \
+ "list", \
+ "List available interfaces.", \
+ &tool_cmd_list \
+ }, \
+ { "ls", "", &tool_cmd_list, 1 }, \
+ { \
+ "status", \
+ "Retrieve the status of the interface.", \
+ &tool_cmd_status \
+ }, \
+ { \
+ "permit-join", \
+ "Permit other devices to join the current network.", \
+ &tool_cmd_permit_join \
+ }, \
+ { "pj", "", &tool_cmd_permit_join, 1 }, \
+ { "permit", "", &tool_cmd_permit_join, 1 }, \
+ { \
+ "scan", \
+ "Scan for nearby networks.", \
+ &tool_cmd_scan \
+ }, \
+ { \
+ "mfg", \
+ "Execute manufacturing command.", \
+ &tool_cmd_mfg \
+ }, \
+ { \
+ "getprop", \
+ "Get a property.", \
+ &tool_cmd_getprop \
+ }, \
+ { "get", "", &tool_cmd_getprop, 1 }, \
+ { \
+ "setprop", \
+ "Set a property.", \
+ &tool_cmd_setprop \
+ }, \
+ { "set", "", &tool_cmd_setprop, 1 }, \
+ { \
+ "begin-net-wake", \
+ "Initiate a network wakeup", \
+ &tool_cmd_begin_net_wake \
+ }, \
+ { \
+ "host-did-wake", \
+ "Perform any host-wakeup related tasks", \
+ &tool_cmd_host_did_wake \
+ }, \
+ { \
+ "pcap", \
+ "Start a packet capture", \
+ &tool_cmd_pcap \
+ }, \
+ { "cd", "Change current interface (command mode)", \
+ &tool_cmd_cd }
+
+#endif
diff --git a/src/wpanctl/wpanctl-utils.c b/src/wpanctl/wpanctl-utils.c
new file mode 100644
index 0000000..4ef2c8a
--- /dev/null
+++ b/src/wpanctl/wpanctl-utils.c
@@ -0,0 +1,615 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "assert-macros.h"
+#include "string-utils.h"
+#include "wpanctl-utils.h"
+#include "wpan-dbus-v0.h"
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#ifdef __APPLE__
+char gInterfaceName[32] = "utun2";
+#else
+char gInterfaceName[32] = "wpan0";
+#endif
+int gRet = 0;
+
+void dump_info_from_iter(FILE* file, DBusMessageIter *iter, int indent, bool bare, bool indentFirstLine)
+{
+ DBusMessageIter sub_iter;
+ int i;
+
+ if (!bare && indentFirstLine) for (i = 0; i < indent; i++) fprintf(file, "\t");
+
+ switch (dbus_message_iter_get_arg_type(iter)) {
+ case DBUS_TYPE_DICT_ENTRY:
+ dbus_message_iter_recurse(iter, &sub_iter);
+ dump_info_from_iter(file, &sub_iter, indent + 1, true, false);
+ fprintf(file, " => ");
+ dbus_message_iter_next(&sub_iter);
+ dump_info_from_iter(file, &sub_iter, indent + 1, bare, false);
+ bare = true;
+ break;
+ case DBUS_TYPE_ARRAY:
+ dbus_message_iter_recurse(iter, &sub_iter);
+ if (dbus_message_iter_get_arg_type(&sub_iter) == DBUS_TYPE_BYTE ||
+ dbus_message_iter_get_arg_type(&sub_iter) == DBUS_TYPE_INVALID) {
+ fprintf(file, "[");
+ indent = 0;
+ } else {
+ fprintf(file, "[\n");
+ }
+
+ for (;
+ dbus_message_iter_get_arg_type(&sub_iter) != DBUS_TYPE_INVALID;
+ dbus_message_iter_next(&sub_iter)
+ ) {
+ dump_info_from_iter(file,
+ &sub_iter,
+ indent + 1,
+ dbus_message_iter_get_arg_type(&sub_iter) == DBUS_TYPE_BYTE,
+ true);
+ }
+ for (i = 0; i < indent; i++) fprintf(file, "\t");
+ fprintf(file, "]");
+
+ break;
+ case DBUS_TYPE_VARIANT:
+ dbus_message_iter_recurse(iter, &sub_iter);
+ dump_info_from_iter(file, &sub_iter, indent, bare, false);
+ bare = true;
+ break;
+ case DBUS_TYPE_STRING:
+ {
+ const char* string;
+ dbus_message_iter_get_basic(iter, &string);
+ fprintf(file, "\"%s\"", string);
+ }
+ break;
+
+ case DBUS_TYPE_BYTE:
+ {
+ uint8_t v;
+ dbus_message_iter_get_basic(iter, &v);
+ if (!bare) {
+ fprintf(file, "0x%02X", v);
+ } else {
+ fprintf(file, "%02X", v);
+ }
+ }
+ break;
+ case DBUS_TYPE_UINT16:
+ {
+ uint16_t v;
+ dbus_message_iter_get_basic(iter, &v);
+ fprintf(file, "0x%04X", v);
+ }
+ break;
+ case DBUS_TYPE_INT16:
+ {
+ int16_t v;
+ dbus_message_iter_get_basic(iter, &v);
+ fprintf(file, "%d", v);
+ }
+ break;
+ case DBUS_TYPE_UINT32:
+ {
+ uint32_t v;
+ dbus_message_iter_get_basic(iter, &v);
+ fprintf(file, "%d", v);
+ }
+ break;
+ case DBUS_TYPE_BOOLEAN:
+ {
+ dbus_bool_t v;
+ dbus_message_iter_get_basic(iter, &v);
+ fprintf(file, "%s", v ? "true" : "false");
+ }
+ break;
+ case DBUS_TYPE_INT32:
+ {
+ int32_t v;
+ dbus_message_iter_get_basic(iter, &v);
+ fprintf(file, "%d", v);
+ }
+ break;
+ case DBUS_TYPE_UINT64:
+ {
+ uint64_t v;
+ dbus_message_iter_get_basic(iter, &v);
+ fprintf(file, "0x%016llX", (unsigned long long)v);
+ }
+ break;
+ default:
+ fprintf(file, "<%s>",
+ dbus_message_type_to_string(dbus_message_iter_get_arg_type(iter)));
+ break;
+ }
+ if (!bare)
+ fprintf(file, "\n");
+}
+
+int parse_network_info_from_iter(struct wpan_network_info_s *network_info, DBusMessageIter *iter)
+{
+ int ret = 0;
+ DBusMessageIter outer_iter;
+ DBusMessageIter dict_iter;
+
+ if (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_ARRAY) {
+ dbus_message_iter_recurse(iter, &outer_iter);
+ iter = &outer_iter;
+ }
+
+ memset(network_info, 0, sizeof(*network_info));
+
+ for (;
+ dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID;
+ dbus_message_iter_next(iter)) {
+ DBusMessageIter value_iter;
+ char* key;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY) {
+ fprintf(stderr,
+ "error: Bad type for network (%c)\n",
+ dbus_message_iter_get_arg_type(iter));
+ ret = ERRORCODE_UNKNOWN;
+ goto bail;
+ }
+
+ dbus_message_iter_recurse(iter, &dict_iter);
+
+ if (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_STRING) {
+ fprintf(stderr,
+ "error: Bad type for network list (%c)\n",
+ dbus_message_iter_get_arg_type(&dict_iter));
+ ret = ERRORCODE_UNKNOWN;
+ goto bail;
+ }
+
+ // Get the key
+ dbus_message_iter_get_basic(&dict_iter, &key);
+ dbus_message_iter_next(&dict_iter);
+
+ if (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_VARIANT) {
+ fprintf(stderr,
+ "error: Bad type for network list (%c)\n",
+ dbus_message_iter_get_arg_type(&dict_iter));
+ ret = ERRORCODE_UNKNOWN;
+ goto bail;
+ }
+
+ dbus_message_iter_recurse(&dict_iter, &value_iter);
+
+ if (strcmp(key, kWPANTUNDProperty_NetworkName) == 0) {
+ char* network_name = NULL;
+ dbus_message_iter_get_basic(&value_iter, &network_name);
+ snprintf(network_info->network_name,
+ sizeof(network_info->network_name), "%s", network_name);
+ } else if (strcmp(key, kWPANTUNDProperty_NCPChannel) == 0) {
+ dbus_message_iter_get_basic(&value_iter, &network_info->channel);
+ } else if (strcmp(key, kWPANTUNDProperty_NetworkPANID) == 0) {
+ dbus_message_iter_get_basic(&value_iter, &network_info->pan_id);
+ } else if (strcmp(key, kWPANTUNDProperty_NestLabs_NetworkAllowingJoin) == 0) {
+ dbus_message_iter_get_basic(&value_iter,
+ &network_info->allowing_join);
+ } else if (strcmp(key, "RSSI") == 0) {
+ dbus_message_iter_get_basic(&value_iter, &network_info->rssi);
+ } else if (strcmp(key, kWPANTUNDProperty_NetworkXPANID) == 0) {
+ dbus_message_iter_get_basic(&value_iter, &network_info->xpanid);
+ } else if (strcmp(key, kWPANTUNDProperty_NetworkNodeType) == 0) {
+ dbus_message_iter_get_basic(&value_iter, &network_info->type);
+ } else if (strcmp(key, kWPANTUNDProperty_NCPHardwareAddress) == 0) {
+ DBusMessageIter sub_iter;
+ dbus_message_iter_recurse(&value_iter, &sub_iter);
+ if (dbus_message_iter_get_arg_type(&sub_iter) == DBUS_TYPE_BYTE) {
+ const uint8_t* value = NULL;
+ int nelements = 0;
+ dbus_message_iter_get_fixed_array(&sub_iter, &value,
+ &nelements);
+ if (nelements == 8)
+ memcpy(network_info->hwaddr, value, nelements);
+ }
+ } else {
+#if DEBUG
+ fprintf(stderr,
+ "info: %s -> (%c)\n",
+ key,
+ dbus_message_iter_get_arg_type(&value_iter));
+#endif
+ }
+ }
+
+bail:
+ if (ret) fprintf(stderr, "Network parse failed.\n");
+ return ret;
+}
+
+int parse_energy_scan_result_from_iter(int16_t *channel, int8_t *maxRssi, DBusMessageIter *iter)
+{
+ int ret = 0;
+ DBusMessageIter outer_iter;
+ DBusMessageIter dict_iter;
+
+ if (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_ARRAY) {
+ dbus_message_iter_recurse(iter, &outer_iter);
+ iter = &outer_iter;
+ }
+
+ *channel = 0;
+ *maxRssi = 0;
+
+ for (;
+ dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID;
+ dbus_message_iter_next(iter)) {
+ DBusMessageIter value_iter;
+ char* key;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_DICT_ENTRY) {
+ fprintf(stderr,
+ "error: Bad type for energy scan result (%c)\n",
+ dbus_message_iter_get_arg_type(iter));
+ ret = ERRORCODE_UNKNOWN;
+ goto bail;
+ }
+
+ dbus_message_iter_recurse(iter, &dict_iter);
+
+ if (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_STRING) {
+ fprintf(stderr,
+ "error: Bad type for energy scan result (%c)\n",
+ dbus_message_iter_get_arg_type(&dict_iter));
+ ret = ERRORCODE_UNKNOWN;
+ goto bail;
+ }
+
+ // Get the key
+ dbus_message_iter_get_basic(&dict_iter, &key);
+ dbus_message_iter_next(&dict_iter);
+
+ if (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_VARIANT) {
+ fprintf(stderr,
+ "error: Bad type for energy scan result (%c)\n",
+ dbus_message_iter_get_arg_type(&dict_iter));
+ ret = ERRORCODE_UNKNOWN;
+ goto bail;
+ }
+
+ dbus_message_iter_recurse(&dict_iter, &value_iter);
+
+ if (strcmp(key, kWPANTUNDProperty_NCPChannel) == 0) {
+ dbus_message_iter_get_basic(&value_iter, channel);
+ } else if (strcmp(key, "RSSI") == 0) {
+ dbus_message_iter_get_basic(&value_iter, maxRssi);
+ } else {
+#if DEBUG
+ fprintf(stderr,
+ "info: %s -> (%c)\n",
+ key,
+ dbus_message_iter_get_arg_type(&value_iter));
+#endif
+ }
+ }
+
+bail:
+ if (ret) fprintf(stderr, "Energy scan result parse failed.\n");
+ return ret;
+}
+
+int
+lookup_dbus_name_from_interface(char* dbus_bus_name, const char* interface_name)
+{
+ int ret = kWPANTUNDStatus_InterfaceNotFound;
+ int i;
+ int timeout = DEFAULT_TIMEOUT_IN_SECONDS * 1000;
+ DBusConnection* connection = NULL;
+ DBusMessage *message = NULL;
+ DBusMessage *reply = NULL;
+ DBusError error;
+
+ dbus_error_init(&error);
+
+ memset(dbus_bus_name, 0, DBUS_MAXIMUM_NAME_LENGTH+1);
+
+ connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
+
+ if (!connection) {
+ dbus_error_free(&error);
+ dbus_error_init(&error);
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ }
+
+ require_string(connection != NULL, bail, error.message);
+
+ {
+ DBusMessageIter iter;
+ DBusMessageIter list_iter;
+
+ message = dbus_message_new_method_call(
+ WPAN_TUNNEL_DBUS_NAME,
+ WPAN_TUNNEL_DBUS_PATH,
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_TUNNEL_CMD_GET_INTERFACES
+ );
+
+ reply = dbus_connection_send_with_reply_and_block(
+ connection,
+ message,
+ timeout,
+ &error
+ );
+
+ if (!reply) {
+ fprintf(stderr, "%s: error: %s\n", "lookup_dbus_name_from_interface", error.message);
+ ret = ERRORCODE_TIMEOUT;
+ goto bail;
+ }
+
+ dbus_message_iter_init(reply, &iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
+ fprintf(stderr,
+ "%s: error: Bad type for interface list (%c)\n",
+ "lookup_dbus_name_from_interface",
+ dbus_message_iter_get_element_type(&iter));
+ ret = ERRORCODE_UNKNOWN;
+ goto bail;
+ }
+
+ dbus_message_iter_recurse(&iter, &list_iter);
+
+ for (;
+ dbus_message_iter_get_arg_type(&list_iter) == DBUS_TYPE_ARRAY;
+ dbus_message_iter_next(&list_iter)
+ ) {
+ DBusMessageIter item_iter;
+ char *item_interface_name = NULL;
+ char *item_dbus_name = NULL;
+
+ dbus_message_iter_recurse(&list_iter, &item_iter);
+
+ dbus_message_iter_get_basic(&item_iter, &item_interface_name);
+ dbus_message_iter_next(&item_iter);
+ dbus_message_iter_get_basic(&item_iter, &item_dbus_name);
+ if ((NULL != item_interface_name)
+ && (NULL != item_dbus_name)
+ && (strcmp(item_interface_name, interface_name) == 0)
+ ) {
+ strncpy(dbus_bus_name, item_dbus_name, DBUS_MAXIMUM_NAME_LENGTH);
+ ret = 0;
+ break;
+ }
+ }
+ }
+
+bail:
+
+ if (connection)
+ dbus_connection_unref(connection);
+
+ if (message)
+ dbus_message_unref(message);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_error_free(&error);
+
+ return ret;
+}
+
+const char*
+wpantund_status_to_cstr(int status)
+{
+ if (status<0) {
+ return strerror(status);
+ }
+ if (WPANTUND_STATUS_IS_NCPERROR(status)) {
+ return "NCP-Specific Errorcode";
+ }
+ switch(status) {
+ case kWPANTUNDStatus_Ok: return "Ok";
+ case kWPANTUNDStatus_Failure: return "Failure";
+ case kWPANTUNDStatus_Timeout: return "Timeout";
+ case kWPANTUNDStatus_SocketReset: return "SocketReset";
+ case kWPANTUNDStatus_InvalidArgument: return "InvalidArgument";
+ case kWPANTUNDStatus_Busy: return "Busy";
+ case kWPANTUNDStatus_InvalidWhenDisabled: return "InvalidWhenDisabled";
+ case kWPANTUNDStatus_InvalidForCurrentState: return "InvalidForCurrentState";
+ case kWPANTUNDStatus_PropertyEmpty: return "PropertyEmpty";
+ case kWPANTUNDStatus_InvalidType: return "InvalidType";
+ case kWPANTUNDStatus_FeatureNotSupported: return "FeatureNotSupported";
+ case kWPANTUNDStatus_FeatureNotImplemented: return "FeatureNotImplemented";
+ case kWPANTUNDStatus_PropertyNotFound: return "PropertyNotFound";
+ case kWPANTUNDStatus_Canceled: return "Canceled";
+ case kWPANTUNDStatus_InProgress: return "InProgress";
+ case kWPANTUNDStatus_NCP_Crashed: return "NCPCrashed";
+ case kWPANTUNDStatus_JoinFailedAtScan: return "JoinFailedAtScan";
+ case kWPANTUNDStatus_JoinFailedAtAuthenticate: return "JoinFailedAtAuthenticate";
+ case kWPANTUNDStatus_Already: return "Already";
+ case kWPANTUNDStatus_TryAgainLater: return "TryAgainLater";
+ case kWPANTUNDStatus_InvalidRange: return "InvalidRange";
+ case kWPANTUNDStatus_MissingXPANID: return "MissingXPANID";
+ case kWPANTUNDStatus_InterfaceNotFound: return "InterfaceNotFound";
+ default: break;
+ }
+ return "";
+}
+
+void print_error_diagnosis(int error)
+{
+ switch(error) {
+ case kWPANTUNDStatus_InterfaceNotFound:
+ fprintf(stderr, "\nDIAGNOSIS: The requested operation can't be completed because the given\n"
+ "network interface doesn't exist or it isn't managed by wpantund. If you are\n"
+ "using wpanctl in interactive mode, you can use the `ls` command to get a list\n"
+ "of valid interfaces and use the `cd` command to select a valid interface.\n"
+ "Otherwise, use the `-I` argument to wpanctl to select a valid interface.\n"
+ "\n"
+ );
+ break;
+
+ case kWPANTUNDStatus_Busy:
+ case -EBUSY:
+ fprintf(stderr, "\nDIAGNOSIS: The requested operation can't be completed because the NCP\n"
+ "is busy doing something else, like scanning or joining. If you are persistently\n"
+ "getting this error, try resetting the NCP via the \"reset\" command. You can\n"
+ "help diagnose why this is occuring using the \"state\" command.\n"
+ "\n"
+ );
+ break;
+
+
+ case kWPANTUNDStatus_Canceled:
+ case -ECONNABORTED:
+ fprintf(stderr, "\nDIAGNOSIS: This action was aborted due to a change in the NCP's state.\n"
+ "This can occur if the interface is disabled while you were trying to join,\n"
+ "or if AutoDeepSleep kicked in for some reason.\n"
+ "\n"
+ );
+ break;
+
+ case kWPANTUNDStatus_NCP_Crashed:
+ case -ECONNRESET:
+ fprintf(stderr, "\nDIAGNOSIS: The NCP has unexpectedly crashed and rebooted. Please see the\n"
+ "wpantund logs for more information and try again.\n"
+ "\n"
+ );
+ break;
+
+ case kWPANTUNDStatus_InvalidArgument:
+ case -EINVAL:
+ fprintf(stderr, "\nDIAGNOSIS: This error indicates that either the device in a state where your\n"
+ "request makes no sense or the parameters of your request were invalid. Check your\n"
+ "arguments and verify that you are allowed to perform the given operation when the\n"
+ "NCP is in its current state.\n"
+ "\n"
+ );
+ break;
+
+ case kWPANTUNDStatus_InvalidWhenDisabled:
+ fprintf(stderr, "\nDIAGNOSIS: This error indicates that this operation is not valid when the interface\n"
+ "is disabled. Enable the interface first and try again. You can enable the interface\n"
+ "with the command `setprop enabled true`.\n"
+ "\n"
+ );
+ break;
+
+ case kWPANTUNDStatus_InvalidForCurrentState:
+ case kWPANTUNDStatus_InProgress:
+ case -EALREADY:
+ fprintf(stderr, "\nDIAGNOSIS: This error indicates that the device is not in a state where\n"
+ "it can complete your request, typically because a request is already in progress or\n"
+ "the NCP is already in the requested state.\n"
+ "If you are getting this error persistently, you should try reseting the network\n"
+ "settings on the NCP (via the \"leave\" command). The \"status\" command can be\n"
+ "helpful to further diagnose the issue.\n"
+ "\n"
+ );
+ break;
+
+ case kWPANTUNDStatus_JoinFailedAtScan:
+ fprintf(stderr, "\nDIAGNOSIS: This error indicates that the NCP could not find a device in\n"
+ "range that would allow it to join the given network. This can occur if\n"
+ "the closest device on the network you are trying to join is out of range,\n"
+ "the devices on the network you are trying to join are running an\n"
+ "incompatible network stack, or if there are no devices on the target\n"
+ "network which are permitting joining.\n"
+ "\n"
+ );
+ break;
+
+ case kWPANTUNDStatus_JoinFailedAtAuthenticate:
+ fprintf(stderr, "\nDIAGNOSIS: Join failed while authenticating. This is typically due to using the wrong\n"
+ "key or because this NCP's network stack is not compatible with this network.\n"
+ "\n"
+ );
+ break;
+ }
+
+ if (WPANTUND_STATUS_IS_NCPERROR(error)) {
+ fprintf(stderr, "\nDIAGNOSIS: This error is specific to this specific type of NCP. The error\n"
+ "code is %d (0x%02X). Consult the NCP documentation for an explantion of this\n"
+ "error code.\n"
+ "\n", WPANTUND_STATUS_TO_NCPERROR(error), WPANTUND_STATUS_TO_NCPERROR(error)
+ );
+ }
+}
+
+uint16_t
+node_type_str2int(const char *node_type)
+{
+ uint16_t type;
+
+ if (strcasecmp(node_type, "router") == 0) {
+ return WPAN_IFACE_ROLE_ROUTER;
+ } else if (strcasecmp(node_type, "r") == 0) {
+ return WPAN_IFACE_ROLE_ROUTER;
+
+ } else if (strcasecmp(node_type, "end-device") == 0) {
+ return WPAN_IFACE_ROLE_END_DEVICE;
+ } else if (strcasecmp(node_type, "end") == 0) {
+ return WPAN_IFACE_ROLE_END_DEVICE;
+ } else if (strcasecmp(node_type, "e") == 0) {
+ return WPAN_IFACE_ROLE_END_DEVICE;
+
+ } else if (strcasecmp(node_type, "sleepy-end-device") == 0) {
+ return WPAN_IFACE_ROLE_SLEEPY_END_DEVICE;
+ } else if (strcasecmp(node_type, "sleepy") == 0) {
+ return WPAN_IFACE_ROLE_SLEEPY_END_DEVICE;
+ } else if (strcasecmp(node_type, "sed") == 0) {
+ return WPAN_IFACE_ROLE_SLEEPY_END_DEVICE;
+ } else if (strcasecmp(node_type, "s") == 0) {
+ return WPAN_IFACE_ROLE_SLEEPY_END_DEVICE;
+
+ } else if (strcasecmp(node_type, "lurker") == 0) {
+ return WPAN_IFACE_ROLE_LURKER;
+ } else if (strcasecmp(node_type, "nl-lurker") == 0) {
+ return WPAN_IFACE_ROLE_LURKER;
+ } else if (strcasecmp(node_type, "l") == 0) {
+ return WPAN_IFACE_ROLE_LURKER;
+
+ } else {
+ // At this moment it should be a number
+ return strtol(node_type, NULL, 0);
+ }
+}
+
+const char *
+node_type_int2str(uint16_t node_type)
+{
+ switch (node_type)
+ {
+ case WPAN_IFACE_ROLE_ROUTER: return "router";
+ case WPAN_IFACE_ROLE_END_DEVICE: return "end-device";
+ case WPAN_IFACE_ROLE_SLEEPY_END_DEVICE: return "sleepy-end-device";
+ case WPAN_IFACE_ROLE_LURKER: return "nl-lurker";
+ default: break;
+ }
+
+ return "unknown";
+}
diff --git a/src/wpanctl/wpanctl-utils.h b/src/wpanctl/wpanctl-utils.h
new file mode 100644
index 0000000..f107d5c
--- /dev/null
+++ b/src/wpanctl/wpanctl-utils.h
@@ -0,0 +1,84 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef WPANCTL_UTILS_H
+#define WPANCTL_UTILS_H
+
+#include <dbus/dbus.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "wpan-error.h"
+
+#define ERRORCODE_OK (0)
+#define ERRORCODE_HELP (1)
+#define ERRORCODE_BADARG (2)
+#define ERRORCODE_NOCOMMAND (3)
+#define ERRORCODE_UNKNOWN (4)
+#define ERRORCODE_BADCOMMAND (5)
+#define ERRORCODE_NOREADLINE (6)
+#define ERRORCODE_QUIT (7)
+#define ERRORCODE_BADCONFIG (8)
+#define ERRORCODE_ERRNO (9)
+#define ERRORCODE_NOT_IMPLEMENTED (10)
+#define ERRORCODE_TIMEOUT (11)
+#define ERRORCODE_BADVERSION (12)
+#define ERRORCODE_ALLOC (13)
+#define ERRORCODE_NOTFOUND (14)
+#define ERRORCODE_REFUSED (15)
+
+#define ERRORCODE_INTERRUPT (128 + SIGINT)
+#define ERRORCODE_SIGHUP (128 + SIGHUP)
+
+#define DEFAULT_TIMEOUT_IN_SECONDS 60
+
+struct command_info_s {
+ const char* name;
+ const char* desc;
+ int (*entrypoint)(
+ int argc, char* argv[]);
+ int isHidden;
+};
+
+struct wpan_network_info_s {
+ char network_name[17];
+ dbus_bool_t allowing_join;
+ uint16_t pan_id;
+ int16_t channel;
+ uint64_t xpanid;
+ int8_t rssi;
+ uint8_t type;
+ uint8_t hwaddr[8];
+};
+
+const char* wpantund_status_to_cstr(int status);
+void print_error_diagnosis(int error);
+int parse_network_info_from_iter(struct wpan_network_info_s *network_info, DBusMessageIter *iter);
+int parse_energy_scan_result_from_iter(int16_t *channel, int8_t *maxRssi, DBusMessageIter *iter);
+int lookup_dbus_name_from_interface(char* dbus_bus_name, const char* interface_name);
+void dump_info_from_iter(FILE* file, DBusMessageIter *iter, int indent, bool bare, bool indentFirstLine);
+uint16_t node_type_str2int(const char *node_type);
+const char *node_type_int2str(uint16_t node_type);
+
+extern char gInterfaceName[32];
+extern int gRet;
+
+#endif
diff --git a/src/wpanctl/wpanctl.c b/src/wpanctl/wpanctl.c
new file mode 100644
index 0000000..a1a97ab
--- /dev/null
+++ b/src/wpanctl/wpanctl.c
@@ -0,0 +1,684 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * This file implements the main program entry point for the
+ * WPAN control utility, `wpanctl`.
+ *
+ */
+
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#undef ASSERT_MACROS_USE_SYSLOG
+#define ASSERT_MACROS_USE_SYSLOG 0
+
+#include <getopt.h>
+#include "assert-macros.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <ctype.h>
+#include <libgen.h>
+#include <time.h>
+
+#include <dbus/dbus.h>
+
+#if HAVE_LIBREADLINE
+#include <readline/readline.h>
+#include <readline/history.h>
+#endif // HAVE_LIBREADLINE
+
+#include <poll.h>
+#include "args.h"
+#include "config-file.h"
+#include "wpanctl-cmds.h"
+#include "version.h"
+#include "string-utils.h"
+#include "wpanctl-utils.h"
+
+#include "wpan-dbus-v0.h"
+
+static bool istty = true;
+int gDebugMode = 0;
+
+static arg_list_item_t option_list[] = {
+ { 'h', "help", NULL,
+ "Print Help" },
+ { 'v', "version", NULL,
+ "Print Version Information" },
+ { 'f', NULL, "filename",
+ "Read commands from file" },
+ { 'I', "interface", "iface",
+ "Set interface to use" },
+ { 0, "ignore-mismatch", NULL, "Ignore driver version mismatch" },
+ { 0 }
+};
+
+void print_commands();
+int exec_command(
+ int argc, char * argv[]);
+
+static int
+tool_cmd_help(
+ int argc, char* argv[]
+ )
+{
+ if ((2 == argc) && (0 == strcmp(argv[1], "--help"))) {
+ printf("Help not yet implemented for this command.\n");
+ return ERRORCODE_HELP;
+ }
+
+ if ((argc == 2) && argv[1][0] != '-') {
+ const char *argv2[2] = {
+ argv[1],
+ "--help"
+ };
+ return exec_command(2, (char**)argv2);
+ } else {
+ print_commands();
+ }
+ return ERRORCODE_HELP;
+}
+
+static int tool_cmd_clear(int argc, char *argv[])
+{
+ if (system("clear") == -1) {
+ printf("\n\n\n\n\n\n\n\n");
+ }
+ return 0;
+}
+
+struct command_info_s commandList[] = {
+ WPANCTL_CLI_COMMANDS,
+ {"quit", "Terminate command line mode.", NULL},
+ {"help", "Display this help.", &tool_cmd_help},
+ {"clear", "Clear shell.", &tool_cmd_clear},
+ {"?", NULL, &tool_cmd_help, 1},
+ {NULL}
+};
+
+void
+print_commands()
+{
+ int i;
+
+ printf("Commands:\n");
+ for (i = 0; commandList[i].name; ++i) {
+ if (commandList[i].isHidden)
+ continue;
+ printf(
+ " %s %s%s\n",
+ commandList[i].name,
+ &" "[strlen(commandList[i].name)],
+ commandList[i].desc
+ );
+ }
+}
+
+struct command_info_s * find_cmd(char *cmd_name)
+{
+ int idx;
+ for (idx = 0; commandList[idx].name; idx++) {
+ if (strcmp(cmd_name, commandList[idx].name) == 0) {
+ return commandList + idx;
+ }
+ }
+ return NULL;
+}
+
+int exec_command(int argc, char * argv[])
+{
+ int ret = 0;
+ struct command_info_s *cmd_entry;
+
+ require(argc, bail);
+
+ if ((strcmp(argv[0], "quit") == 0) || (strcmp(argv[0], "exit") == 0) ||
+ (strcmp(argv[0], "q") == 0)) {
+ ret = ERRORCODE_QUIT;
+ goto bail;
+ }
+
+ if ((cmd_entry = find_cmd(argv[0])) == NULL) {
+ fprintf(stderr, "The command \"%s\" is not recognised.\n",
+ argv[0]);
+ ret = ERRORCODE_BADCOMMAND;
+ goto bail;
+ }
+
+ if (cmd_entry->entrypoint == NULL) {
+ fprintf(stderr,
+ "The command \"%s\" is not yet implemented.\n",
+ cmd_entry->name);
+ ret = ERRORCODE_NOCOMMAND;
+ goto bail;
+ }
+
+ ret = cmd_entry->entrypoint(argc, argv);
+bail:
+ return ret;
+}
+
+#if HAVE_LIBREADLINE
+static bool history_disabled;
+char* wpanctl_generator(const char* text, int state)
+{
+ static int idx, len;
+ const char *name;
+
+ if (!state) {
+ idx = 0;
+ len = strlen(text);
+ }
+
+ while ((name = commandList[idx].name)) {
+ idx++;
+
+ if (commandList[idx - 1].isHidden)
+ continue;
+
+ if (strncmp(name, text, len) == 0)
+ return strdup(name);
+ }
+
+ return NULL;
+}
+
+static char** wpanctl_completion(const char *text, int start, int end)
+{
+ if (start != 0)
+ return NULL;
+
+ return rl_completion_matches(text, wpanctl_generator);
+}
+#endif // HAVE_LIBREADLINE
+
+void
+process_input_line(char *l)
+{
+ char *inputstring;
+ char *argv2[100];
+ char **ap = argv2;
+ int argc2 = 0;
+
+ if (!l[0]) {
+ l = NULL;
+ goto bail;
+ }
+ l = strdup(l);
+#if HAVE_LIBREADLINE
+ if (!history_disabled) {
+ add_history(l);
+ }
+#endif // HAVE_LIBREADLINE
+
+ inputstring = l;
+
+ while ((*ap = get_next_arg(inputstring, &inputstring))) {
+ if (**ap != '\0') {
+ ap++;
+ argc2++;
+ }
+ }
+ if (argc2 > 0) {
+ gRet = exec_command(argc2, argv2);
+ if (gRet == ERRORCODE_QUIT)
+ goto bail;
+ else if (gRet == ERRORCODE_ERRNO)
+ fprintf(stderr, "errno=%d %s\n", errno, strerror(errno));
+ else if (gRet < 0 && (gRet != ERRORCODE_HELP))
+ fprintf(stderr, "Error %d %s\n", gRet, strerror(-gRet));
+ else if (gRet && (gRet != ERRORCODE_HELP))
+ fprintf(stderr, "Error %d (0x%02X)\n", gRet, gRet);
+
+#if HAVE_LIBREADLINE
+ if (!history_disabled)
+ write_history(getenv("WPANCTL_HISTORY_FILE"));
+#endif // HAVE_LIBREADLINE
+ }
+
+bail:
+ free(l);
+ return;
+}
+
+#if HAVE_LIBREADLINE
+static char*
+get_current_prompt()
+{
+ static char prompt[64] = {};
+
+ if (!gInterfaceName[0]) {
+ snprintf(prompt,
+ sizeof(prompt),
+ "wpanctl> "
+ );
+ } else {
+ snprintf(prompt,
+ sizeof(prompt),
+ "wpanctl:%s> ",
+ gInterfaceName
+ );
+ }
+ return prompt;
+}
+
+void
+process_input_readline(char *l)
+{
+ process_input_line(l);
+ if (istty) {
+#if HAVE_RL_SET_PROMPT
+ if (gRet == ERRORCODE_QUIT)
+ rl_set_prompt("");
+ else
+#endif
+ rl_callback_handler_install(
+ get_current_prompt(), &process_input_readline);
+ }
+}
+#endif // HAVE_LIBREADLINE
+
+#pragma mark -
+
+#if HAVE_LIBREADLINE
+
+static int
+initialize_readline()
+{
+ int ret = 0;
+
+ require_action(NULL != readline, bail, ret = ERRORCODE_NOREADLINE);
+ rl_initialize();
+
+ rl_readline_name = "wpanctl";
+ //rl_completer_word_break_characters = " \t\n\"\\'`@$><|&{("; // Removed '=' ';'
+
+ using_history();
+ read_history(getenv("WPANCTL_HISTORY_FILE"));
+ rl_instream = stdin;
+
+ rl_callback_handler_install(get_current_prompt(), &process_input_readline);
+
+ rl_attempted_completion_function = wpanctl_completion;
+
+bail:
+ return ret;
+}
+#endif
+
+static void
+print_version()
+{
+ printf("wpanctl " PACKAGE_VERSION );
+ if ((internal_build_source_version[0] == 0) || strequal(SOURCE_VERSION, internal_build_source_version)) {
+ if (strequal(PACKAGE_VERSION, SOURCE_VERSION)) {
+ printf(" (%s)\n", internal_build_date);
+ } else {
+ printf(" (" SOURCE_VERSION "; %s)\n", internal_build_date);
+ }
+ } else {
+ if (strequal(SOURCE_VERSION, PACKAGE_VERSION) || strequal(PACKAGE_VERSION, internal_build_source_version)) {
+ printf(" (%s; %s)\n", internal_build_source_version, internal_build_date);
+ } else {
+ printf(" (" SOURCE_VERSION "/%s; %s)\n", internal_build_source_version, internal_build_date);
+ }
+ }
+}
+
+static int
+wpan_dbus_version_check(DBusConnection* connection)
+{
+ int timeout = 5 * 1000; // Five second timeout
+ int ret = ERRORCODE_BADVERSION;
+ DBusMessage *message = NULL;
+ DBusMessage *reply = NULL;
+ uint32_t version = 0;
+ DBusError error;
+
+ dbus_error_init(&error);
+
+ message = dbus_message_new_method_call(
+ getenv("WPANCTL_DBUS_NAME"),
+ WPAN_TUNNEL_DBUS_PATH,
+ WPAN_TUNNEL_DBUS_INTERFACE,
+ WPAN_TUNNEL_CMD_GET_VERSION
+ );
+
+ if (!message) {
+ fprintf(stderr, "error: Unable to allocate dbus message\n");
+ ret = ERRORCODE_ALLOC;
+ goto bail;
+ }
+
+ reply = dbus_connection_send_with_reply_and_block(
+ connection,
+ message,
+ timeout,
+ &error
+ );
+
+ if (!reply) {
+ fprintf(stderr, "error: %s\n", error.message);
+ ret = ERRORCODE_TIMEOUT;
+ goto bail;
+ }
+
+ dbus_message_get_args(
+ reply, NULL,
+ DBUS_TYPE_UINT32, &version,
+ DBUS_TYPE_INVALID
+ );
+
+ if (gDebugMode >= 1) {
+ fprintf(stderr, "DEBUG: Version check, wpanctl=%d, wpantund=%d\n", WPAN_TUNNEL_DBUS_VERSION, version);
+ }
+
+ if(version != WPAN_TUNNEL_DBUS_VERSION) {
+ fprintf(stderr, "error: `wpantund` version (%d) doesn't match `wpanctl` version (%d).\n", version, WPAN_TUNNEL_DBUS_VERSION);
+ goto bail;
+ }
+
+ ret = 0;
+
+bail:
+ if (message)
+ dbus_message_unref(message);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_error_free(&error);
+
+ return ret;
+}
+
+#pragma mark -
+
+
+int main(int argc, char * argv[])
+{
+ int c;
+ bool ignore_driver_version_mismatch = false;
+ DBusError error;
+ DBusConnection* connection;
+
+ dbus_error_init(&error);
+
+ srandom(time(NULL));
+
+ while (1) {
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'v'},
+ {"ignore-mismatch", no_argument, 0, 'i'},
+ {"debug", no_argument, 0, 'd'},
+ {"interface", required_argument, 0, 'I'},
+ {"file", required_argument, 0, 'f'},
+ {0, 0, 0, 0}
+ };
+
+ int option_index = 0;
+
+ if ((optind < argc) && (find_cmd(argv[optind]) != NULL)) {
+ // This is where the wpanctl command starts; skip
+ // parsing the flags since they may belong to the command
+ break;
+ }
+
+ c = getopt_long(argc, argv, "hvidI:f:", long_options,
+ &option_index);
+
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_version();
+ print_arg_list_help(option_list,
+ argv[0],
+ "[options] <sub-command> [args]");
+ print_commands();
+ gRet = ERRORCODE_HELP;
+ goto bail;
+
+ case 'v':
+ print_version();
+ gRet = 0;
+ goto bail;
+
+ case 'd':
+ gDebugMode++;
+ break;
+
+ case 'I':
+ snprintf(gInterfaceName, sizeof(gInterfaceName),
+ "%s", optarg);
+ break;
+
+ case 'i':
+ ignore_driver_version_mismatch = true;
+ break;
+
+ case 'f':
+#if HAVE_LIBREADLINE
+ if (NULL == freopen(optarg, "r", stdin))
+ {
+ fprintf(stderr,
+ "%s: error: Unable to open file \"%s\".\n",
+ argv[0], optarg);
+ return ERRORCODE_BADARG;
+ }
+#else
+ fprintf(stderr,
+ "%s: Cannot read from file \"%s\" : Missing readline library.\n",
+ argv[0], optarg);
+ return ERRORCODE_BADARG;
+#endif
+ default:
+ break;
+ }
+ }
+
+ istty = isatty(fileno(stdin));
+
+ if (gDebugMode >= 1) {
+ fprintf(stderr, "DEBUG: isatty(fileno(stdin)) = %d\n", istty);
+ }
+
+ if (gDebugMode >= 1) {
+ fprintf(stderr, "DEBUG: Will use interface '%s'.\n", gInterfaceName);
+ }
+
+ if (getenv("WPANCTL_DBUS_NAME") && gDebugMode>=1)
+ fprintf(stderr, "DEBUG: Using dbus \"%s\"\n", getenv("WPANCTL_DBUS_NAME"));
+
+ setenv("WPANCTL_DBUS_NAME", WPAN_TUNNEL_DBUS_NAME, 0);
+
+ if (gDebugMode >= 1) {
+ fprintf(stderr, "DEBUG: Getting DBusConnection via dbus_bus_get(DBUS_BUS_STARTER). . .\n");
+ }
+
+ connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
+
+ if (!connection) {
+ if (gDebugMode >= 1) {
+ fprintf(stderr, "DEBUG: dbus_bus_get(DBUS_BUS_STARTER) didn't work, trying dbus_bus_get(DBUS_BUS_SYSTEM). . .\n");
+ }
+ dbus_error_free(&error);
+ dbus_error_init(&error);
+ connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ }
+
+ require_string(connection != NULL, bail, error.message);
+
+ if (gDebugMode >= 1) {
+ fprintf(stderr, "DEBUG: DBusConnection: %p\n", connection);
+ }
+
+ if (gDebugMode >= 1) {
+ fprintf(stderr, "DEBUG: Registering DBusConnection. . .\n");
+ }
+
+ dbus_bus_register(connection, &error);
+ require_string(error.name == NULL, bail, error.message);
+
+ if (gDebugMode >= 1) {
+ fprintf(stderr, "DEBUG: DBusConnection registered.\n");
+ }
+
+ if (gDebugMode >= 1) {
+ fprintf(stderr, "DEBUG: Requesting DBus name \"%s\". . .\n",WPAN_TUNNEL_DBUS_NAME ".wpanctl");
+ }
+
+ dbus_bus_request_name(connection,
+ WPAN_TUNNEL_DBUS_NAME ".wpanctl",
+ 0,
+ &error);
+
+ if (gDebugMode >= 1) {
+ if (error.name != NULL) {
+ fprintf(stderr, "DEBUG: Requesting DBus name \"%s\" failed (no biggie): %s\n",WPAN_TUNNEL_DBUS_NAME ".wpanctl", error.name);
+ } else {
+ fprintf(stderr, "DEBUG: Requesting DBus name \"%s\" succeded.\n",WPAN_TUNNEL_DBUS_NAME ".wpanctl");
+ }
+ }
+
+ // Don't fail if we can't get the name. It isn't a big deal.
+ //require_string(error.name == NULL, bail, error.message);
+
+ if (gDebugMode >= 1) {
+ fprintf(stderr, "DEBUG: Performing wpantund version check. . .\n");
+ }
+
+ // Make sure that we are compatible with the copy of wpantund
+ // that is currently running.
+ gRet = wpan_dbus_version_check(connection);
+
+ if (gRet != 0) {
+ fprintf(stderr,
+ "%s: error: `wpantund` is either not running, locked up, or incompatible with this version of `wpanctl`.\n",
+ argv[0]
+ );
+ if (!ignore_driver_version_mismatch)
+ goto bail;
+ } else {
+ if (gDebugMode >= 1) {
+ fprintf(stderr,
+ "DEBUG: wpantund version check succeded.\n");
+ }
+ }
+
+ if (optind < argc) {
+ if (gDebugMode >= 1) {
+ fprintf(stderr, "DEBUG: Executing command '%s'. . .\n",
+ argv[optind]);
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ optind = 0;
+ gRet = exec_command(argc, argv);
+ goto bail;
+ }
+
+ if (istty) {
+#if !HAVE_LIBREADLINE
+ fprintf(stderr,
+ "%s: error: Interactive mode disabled: Compiled without libeditline or libreadline support.\n",
+ argv[0]
+ );
+ print_arg_list_help(option_list,
+ argv[0],
+ "[options] <sub-command> [args]");
+ print_commands();
+ gRet = ERRORCODE_NOCOMMAND;
+ goto bail;
+#else // HAVE_LIBREADLINE
+ setenv("WPANCTL_HISTORY_FILE", tilde_expand("~/.wpanctl_history"), 0);
+
+ gRet = initialize_readline();
+ if(gRet) {
+ fprintf(stderr,
+ "%s: error: Failed to initialize readline: %d\n",
+ argv[0], gRet
+ );
+ goto bail;
+ }
+#endif // HAVE_LIBREADLINE
+ }
+
+ // Command mode.
+ while ((gRet != ERRORCODE_QUIT) && !feof(stdin)) {
+ optind = 0;
+#if HAVE_LIBREADLINE
+ if (istty) {
+ int dbus_fd = -1;
+
+ dbus_connection_get_unix_fd(connection, &dbus_fd);
+
+ struct pollfd polltable[2] = {
+ { fileno(stdin), POLLIN | POLLHUP, 0 },
+ { dbus_fd, POLLIN | POLLHUP, 0 },
+ };
+
+ if (poll(
+ polltable,
+ (dbus_fd >= 0) ? 2 : 1,
+ 1000
+ ) < 0
+ ) {
+ if (errno == EINTR) {
+ // We just caught a signal.
+ // Do nothing.
+ } else {
+ break;
+ }
+ }
+
+ if (polltable[0].revents)
+ rl_callback_read_char();
+ } else
+#endif // HAVE_LIBREADLINE
+ {
+ char linebuffer[200];
+ process_input_line(fgets(linebuffer, sizeof(linebuffer), stdin));
+ }
+
+ dbus_connection_read_write_dispatch(connection, 0);
+ }
+ printf("\n");
+
+bail:
+#if HAVE_LIBREADLINE
+ rl_callback_handler_remove();
+#endif // HAVE_LIBREADLINE
+ if (gRet == ERRORCODE_QUIT)
+ gRet = 0;
+
+ return gRet;
+}
diff --git a/src/wpantund/FirmwareUpgrade.cpp b/src/wpantund/FirmwareUpgrade.cpp
new file mode 100644
index 0000000..9937edb
--- /dev/null
+++ b/src/wpantund/FirmwareUpgrade.cpp
@@ -0,0 +1,433 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * Firmware Upgrade Manager
+ *
+ */
+
+/*
+
+This class does what may, at first, appear to be somewhat
+reminiscent of a "Rube Goldberg" contraption: When we
+set the check and upgrade commands, we end up forking and
+spinning off entirely new processes which we communicate
+with via a socket/pipe. Why on earth would I do this?
+
+The answer is security. While wpantund doesn't drop
+privileges yet, it will have that capability one day.
+This setup allows the upgrade and check scripts to run
+in a privileged fashion while the rest of wpantund runs
+with lower privileges. The idea is that wpantund would be
+run initially in a privileged context and then, after
+setting up this object, drop privileges.
+
+There are other places where we will likely want to have
+this sort of behavior (meaning that this doesn't yield any
+immediate increase in security), but this is a good start
+in that direction.
+
+-- RQ 2015-10-23
+
+*/
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "assert-macros.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "FirmwareUpgrade.h"
+#include "socket-utils.h"
+#include <errno.h>
+#include <syslog.h>
+#include "fgetln.h"
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+
+#if HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+using namespace nl::wpantund;
+
+FirmwareUpgrade::FirmwareUpgrade(): mUpgradeStatus(0), mFirmwareCheckFD(-1), mFirmwareUpgradeFD(-1)
+{
+}
+
+FirmwareUpgrade::~FirmwareUpgrade()
+{
+ close_check_fd();
+ close_upgrade_fd();
+}
+
+void
+FirmwareUpgrade::close_check_fd(void)
+{
+ if (mFirmwareCheckFD >= 0) {
+ IGNORE_RETURN_VALUE(write(mFirmwareCheckFD, "X\n", 1));
+ close(mFirmwareCheckFD);
+ mFirmwareCheckFD = -1;
+ }
+}
+
+void
+FirmwareUpgrade::close_upgrade_fd(void)
+{
+ if (mFirmwareUpgradeFD >= 0) {
+ IGNORE_RETURN_VALUE(write(mFirmwareUpgradeFD, "X", 1));
+ close(mFirmwareUpgradeFD);
+ mFirmwareUpgradeFD = -1;
+ }
+}
+
+bool
+FirmwareUpgrade::is_firmware_upgrade_required(const std::string& version)
+{
+ bool ret = false;
+ uint8_t c = 1;
+
+ require(!version.empty(), bail);
+
+ require_quiet(mFirmwareCheckFD >= 0, bail);
+
+ require_string(write(mFirmwareCheckFD, version.c_str(), version.size()) >= 0, bail, strerror(errno));
+
+ require_string(write(mFirmwareCheckFD, "\n", 1) == 1, bail, strerror(errno));
+
+ require_string(read(mFirmwareCheckFD, &c, 1) == 1, bail, strerror(errno));
+
+ ret = (c == 0);
+
+bail:
+
+ // If this check determined that a firmware upgrade was not required,
+ // go ahead and close out our check process so that we don't
+ // waste resources.
+ if (ret == false) {
+ close_check_fd();
+ close_upgrade_fd();
+ }
+
+ return ret;
+}
+
+void
+FirmwareUpgrade::upgrade_firmware(void)
+{
+ require(mUpgradeStatus != EINPROGRESS, bail);
+
+ mUpgradeStatus = EINVAL;
+
+ require(mFirmwareUpgradeFD >= 0, bail);
+
+ require_string(write(mFirmwareUpgradeFD, "1", 1) == 1, bail, strerror(errno));
+
+ mUpgradeStatus = EINPROGRESS;
+
+bail:
+ return;
+}
+
+void
+FirmwareUpgrade::set_firmware_upgrade_command(const std::string& command)
+{
+ int status = -1;
+ pid_t pid = -1;
+
+ if (mFirmwareUpgradeFD >= 0) {
+ close(mFirmwareUpgradeFD);
+ mFirmwareUpgradeFD = -1;
+ }
+
+ pid = fork_unixdomain_socket(&mFirmwareUpgradeFD);
+
+ if (pid < 0) {
+ return;
+ }
+
+ if (pid == 0) {
+ int stdout_fd_copy = dup(STDOUT_FILENO);
+ int stdin_fd_copy = dup(STDIN_FILENO);
+ FILE* stdin_copy = NULL;
+ FILE* stdout_copy = NULL;
+
+ dup2(STDERR_FILENO,STDOUT_FILENO);
+ close(STDIN_FILENO);
+
+ if (stdin_fd_copy >= 0) {
+ stdin_copy = fdopen(stdin_fd_copy, "r");
+ }
+
+ if (stdout_fd_copy >= 0) {
+ stdout_copy = fdopen(stdout_fd_copy, "w");
+ }
+
+ // Double fork to avoid leaking zombie processes.
+ pid = fork();
+ if (pid < 0) {
+ syslog(LOG_ERR, "Call to fork() failed: %s (%d)", strerror(errno), errno);
+
+ _exit(errno);
+ }
+
+ if (0 == pid)
+ {
+ // Set the shell environment variable if it isn't set already.
+ setenv("SHELL",SOCKET_UTILS_DEFAULT_SHELL,0);
+
+ while ((ferror(stdin_copy) == 0) && (feof(stdin_copy) == 0)) {
+ int c;
+ int ret;
+
+ c = fgetc(stdin_copy);
+
+ switch (c) {
+ case '1':
+ // Go ahead and leave the parent's process group
+ setsid();
+
+ // Execute the requested command.
+ ret = system(command.c_str());
+
+ // Inform our parent process of the return value for the command.
+ fputc(WEXITSTATUS(ret), stdout_copy);
+ fflush(stdout_copy);
+ break;
+
+ case 'X':
+ fputc(0, stdout_copy);
+ fflush(stdout_copy);
+ _exit(EXIT_SUCCESS);
+ break;
+
+ default:
+ fputc(1, stdout_copy);
+ fflush(stdout_copy);
+ _exit(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ _exit(EXIT_FAILURE);
+ }
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ // Wait for the first fork to return, and place the return value in errno
+ if (waitpid(pid, &status, 0) < 0) {
+ syslog(LOG_ERR, "Call to waitpid() failed: %s (%d)", strerror(errno), errno);
+ }
+
+ if (0 != WEXITSTATUS(status)) {
+ // If this has happened then the double fork failed. Clean up
+ // and pass this status along to the caller as errno.
+
+ syslog(LOG_ERR, "Child process failed: %s (%d)", strerror(WEXITSTATUS(status)), WEXITSTATUS(status));
+
+ close(mFirmwareUpgradeFD);
+ mFirmwareUpgradeFD = -1;
+
+ errno = WEXITSTATUS(status);
+
+ } else {
+ int saved_flags = fcntl(mFirmwareUpgradeFD, F_GETFL, 0);
+ fcntl(mFirmwareUpgradeFD, F_SETFL, saved_flags | O_NONBLOCK);
+ }
+}
+
+void
+FirmwareUpgrade::set_firmware_check_command(const std::string& command)
+{
+ int status = -1;
+ pid_t pid = -1;
+
+ if (mFirmwareCheckFD >= 0) {
+ close(mFirmwareCheckFD);
+ mFirmwareCheckFD = -1;
+ }
+
+ pid = fork_unixdomain_socket(&mFirmwareCheckFD);
+
+ if (pid < 0) {
+ return;
+ }
+
+ if (pid == 0) {
+ int stdout_fd_copy = dup(STDOUT_FILENO);
+ int stdin_fd_copy = dup(STDIN_FILENO);
+ FILE* stdin_copy = NULL;
+ FILE* stdout_copy = NULL;
+
+ dup2(STDERR_FILENO,STDOUT_FILENO);
+
+ if (stdin_fd_copy >= 0) {
+ close(STDIN_FILENO);
+ stdin_copy = fdopen(stdin_fd_copy, "r");
+ }
+
+ if (stdout_fd_copy >= 0) {
+ stdout_copy = fdopen(stdout_fd_copy, "w");
+ }
+
+ // Double fork to avoid leaking zombie processes.
+ pid = fork();
+ if (pid < 0) {
+ syslog(LOG_ERR, "Call to fork() failed: %s (%d)", strerror(errno), errno);
+
+ _exit(errno);
+ }
+
+ if (0 == pid)
+ {
+ // Set the shell environment variable if it isn't set already.
+ setenv("SHELL",SOCKET_UTILS_DEFAULT_SHELL,0);
+
+ while ((ferror(stdin_copy) == 0) && (feof(stdin_copy) == 0)) {
+ int ret;
+ const char* line = NULL;
+ size_t line_len = 0;
+ std::string escaped_line;
+
+ line = fgetln(stdin_copy, &line_len);
+
+ if (!line || (line_len == 0)) {
+ continue;
+ }
+
+ if ((line[0] == 'X') && (line[1] == 0)) {
+ fputc(0, stdout_copy);
+ fflush(stdout_copy);
+ _exit(EXIT_SUCCESS);
+ }
+
+ // Open quotation
+ escaped_line = " '";
+
+ // Sanitize and escape the string
+ for(;line_len != 0;line_len--, line++) {
+ char c = *line;
+ if ((c < 32) && (c != '\t') && (c != '\n') && (c != '\r')) {
+ // Control characters aren't allowed.
+ syslog(LOG_ERR, "FirmwareCheck: Prohibited character (%d) in version string", c);
+ fputc('E', stdout_copy);
+ fflush(stdout_copy);
+ _exit(EXIT_FAILURE);
+ }
+ switch (c) {
+ case '\'':
+ escaped_line += "'\''";
+ break;
+ case '\n':
+ case '\r':
+ break;
+ default:
+ escaped_line += c;
+ break;
+ }
+ }
+
+ // Close quotation
+ escaped_line += "'";
+
+ ret = system((command + escaped_line).c_str());
+
+ fputc(WEXITSTATUS(ret), stdout_copy);
+ fflush(stdout_copy);
+ }
+
+ _exit(EXIT_FAILURE);
+ }
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ // Wait for the first fork to return, and place the return value in errno
+ if (waitpid(pid, &status, 0) < 0) {
+ syslog(LOG_ERR, "Call to waitpid() failed: %s (%d)", strerror(errno), errno);
+ }
+
+ if (0 != WEXITSTATUS(status)) {
+ // If this has happened then the double fork failed. Clean up
+ // and pass this status along to the caller as errno.
+
+ syslog(LOG_ERR, "Child process failed: %s (%d)", strerror(WEXITSTATUS(status)), WEXITSTATUS(status));
+
+ close(mFirmwareCheckFD);
+ mFirmwareCheckFD = -1;
+
+ errno = WEXITSTATUS(status);
+ }
+}
+
+bool
+FirmwareUpgrade::can_upgrade_firmware(void)
+{
+ return (mFirmwareUpgradeFD >= 0);
+}
+
+int
+FirmwareUpgrade::get_upgrade_status(void)
+{
+ return mUpgradeStatus;
+}
+
+int
+FirmwareUpgrade::update_fd_set(fd_set *read_fd_set, fd_set *write_fd_set, fd_set *error_fd_set, int *max_fd, cms_t *timeout)
+{
+ if ((mUpgradeStatus == EINPROGRESS) && (mFirmwareUpgradeFD >= 0)) {
+ if (read_fd_set != NULL) {
+ FD_SET(mFirmwareUpgradeFD, read_fd_set);
+ }
+ if (error_fd_set != NULL) {
+ FD_SET(mFirmwareUpgradeFD, error_fd_set);
+ }
+ if (max_fd != NULL) {
+ *max_fd = std::max(*max_fd, mFirmwareUpgradeFD);
+ }
+ }
+
+ return 0;
+}
+
+void
+FirmwareUpgrade::process(void)
+{
+ if (mUpgradeStatus == EINPROGRESS) {
+ ssize_t bytes_read;
+ uint8_t value;
+
+ bytes_read = read(mFirmwareUpgradeFD, &value, 1);
+
+ if ((bytes_read < 0) && (errno != EWOULDBLOCK)) {
+ mUpgradeStatus = errno;
+ } else if (bytes_read == 1) {
+ mUpgradeStatus = value;
+
+ // If the upgrade status was successful, go ahead and close
+ // down both checks so that we don't waste resources. This
+ // also has the added benefit of preventing upgrade loops.
+ if (mUpgradeStatus == 0) {
+ close_check_fd();
+ close_upgrade_fd();
+ }
+ }
+ }
+}
diff --git a/src/wpantund/FirmwareUpgrade.h b/src/wpantund/FirmwareUpgrade.h
new file mode 100644
index 0000000..33d1e83
--- /dev/null
+++ b/src/wpantund/FirmwareUpgrade.h
@@ -0,0 +1,69 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * Firmware Upgrade Manager
+ *
+ */
+
+#ifndef __wpantund__FirmwareUpgrade__
+#define __wpantund__FirmwareUpgrade__
+
+#include <stdio.h>
+#include <sys/select.h>
+#include <string>
+#include "time-utils.h"
+
+namespace nl {
+namespace wpantund {
+
+class FirmwareUpgrade {
+public:
+ FirmwareUpgrade();
+ ~FirmwareUpgrade();
+
+ bool is_firmware_upgrade_required(const std::string& version);
+ void upgrade_firmware(void);
+
+ void set_firmware_upgrade_command(const std::string& command);
+ void set_firmware_check_command(const std::string& command);
+
+ // May return:
+ // * `0`: An upgrade was not started or the upgrade completed successfully.
+ // * `EINPROGRESS`: An upgrade is currently in process.
+ // * Any Other Value: An error occured when attempting to upgrade.
+ int get_upgrade_status(void);
+
+ int update_fd_set(fd_set *read_fd_set, fd_set *write_fd_set, fd_set *error_fd_set, int *max_fd, cms_t *timeout);
+ void process(void);
+
+ bool can_upgrade_firmware(void);
+
+private:
+ void close_check_fd(void);
+ void close_upgrade_fd(void);
+
+private:
+ int mUpgradeStatus;
+ int mFirmwareCheckFD;
+ int mFirmwareUpgradeFD;
+};
+
+}; // namespace wpantund
+}; // namespace nl
+
+#endif /* defined(__wpantund__FirmwareUpgrade__) */
diff --git a/src/wpantund/IPCServer.h b/src/wpantund/IPCServer.h
new file mode 100644
index 0000000..895234a
--- /dev/null
+++ b/src/wpantund/IPCServer.h
@@ -0,0 +1,46 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef wpantund_ipc_server_h
+#define wpantund_ipc_server_h
+
+#include <sys/select.h>
+#include <unistd.h>
+#include "time-utils.h"
+
+namespace nl {
+namespace wpantund {
+
+class NCPControlInterface;
+
+class IPCServer {
+public:
+ virtual ~IPCServer() {}
+ virtual cms_t get_ms_to_next_event(void) = 0;
+ virtual void process(void) = 0;
+
+ virtual int update_fd_set(fd_set *read_fd_set, fd_set *write_fd_set, fd_set *error_fd_set, int *max_fd, cms_t *timeout) = 0;
+
+ virtual int add_interface(NCPControlInterface* instance) = 0;
+};
+
+};
+};
+
+#endif
diff --git a/src/wpantund/Makefile.am b/src/wpantund/Makefile.am
new file mode 100644
index 0000000..12c2858
--- /dev/null
+++ b/src/wpantund/Makefile.am
@@ -0,0 +1,120 @@
+#
+# Copyright (c) 2016 Nest Labs, Inc.
+# All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/src/util \
+ -I$(top_srcdir)/src/ipc-dbus \
+ -I$(top_srcdir)/third_party/fgetln \
+ -I$(top_srcdir)/third_party/pt \
+ -I$(top_srcdir)/third_party/assert-macros \
+ $(NULL)
+
+DISTCLEANFILES = \
+ .deps \
+ Makefile \
+ $(NULL)
+
+EXTRA_DIST = \
+ wpantund.conf \
+ $(NULL)
+
+pkginclude_HEADERS = \
+ wpan-properties.h \
+ wpan-error.h \
+ $(NULL)
+
+sysconf_DATA = wpantund.conf
+
+sbin_PROGRAMS = wpantund
+
+wpantund_SOURCES = \
+ wpantund.cpp \
+ wpantund.h \
+ IPCServer.h \
+ NCPConstants.h \
+ NCPControlInterface.cpp \
+ NCPControlInterface.h \
+ NCPInstance.cpp \
+ NCPInstance.h \
+ NCPInstanceBase.cpp \
+ NCPInstanceBase.h \
+ NCPMfgInterface_v0.h \
+ NCPMfgInterface_v1.h \
+ NetworkInstance.h \
+ NCPConstants.h \
+ FirmwareUpgrade.h \
+ FirmwareUpgrade.cpp \
+ StatCollector.h \
+ StatCollector.cpp \
+ RunawayResetBackoffManager.cpp \
+ RunawayResetBackoffManager.h \
+ NCPInstanceBase-NetInterface.cpp \
+ NCPInstanceBase-Addresses.cpp \
+ NCPInstanceBase-AsyncIO.cpp \
+ NCPTypes.h \
+ NCPTypes.cpp \
+ NetworkRetain.h \
+ NetworkRetain.cpp \
+ Pcap.h \
+ Pcap.cpp \
+ ../util/IPv6PacketMatcher.cpp \
+ ../util/IPv6Helpers.cpp \
+ ../util/tunnel.c \
+ ../util/config-file.c \
+ ../util/socket-utils.c \
+ ../util/any-to.cpp \
+ ../util/string-utils.c \
+ ../util/time-utils.c \
+ ../util/nlpt-select.c \
+ ../util/Data.cpp \
+ ../util/SocketWrapper.cpp \
+ ../util/SocketAdapter.cpp \
+ ../util/UnixSocket.cpp \
+ ../util/SuperSocket.cpp \
+ ../util/EventHandler.cpp \
+ ../util/TunnelIPv6Interface.cpp \
+ ../util/ValueMap.cpp \
+ ../util/Timer.cpp \
+ ../util/sec-random.c \
+ $(NULL)
+
+wpantund_LDADD = $(DBUS_LIBS)
+wpantund_LDADD += ../ipc-dbus/libwpantund-dbus.la
+
+if STATIC_LINK_NCP_PLUGIN
+wpantund_LDADD += ../ncp-@default_ncp_plugin@/libncp-@default_ncp_plugin@.la
+else
+wpantund_LDADD += $(LIBDL_LIBS)
+wpantund_LDFLAGS = @EXPORT_DYNAMIC_LDFLAGS@
+endif
+
+wpantund_CPPFLAGS = $(AM_CPPFLAGS) $(DBUS_CFLAGS)
+wpantund_CXXFLAGS = $(BOOST_CXXFLAGS)
+
+SOURCE_VERSION=$(shell \
+ git describe --dirty --always --match "[0-9].*" 2> /dev/null \
+)
+
+BUILT_SOURCES = $(top_builddir)/$(subdir)/version.c
+CLEANFILES = $(top_builddir)/$(subdir)/version.c
+.INTERMEDIATE: wpantund-version.$(OBJEXT)
+
+$(top_builddir)/$(subdir)/version.c: ../version.c.in Makefile
+ sed 's/SOURCE_VERSION/"$(SOURCE_VERSION)"/' < $< > $@
+
+wpantund_SOURCES += $(top_builddir)/$(subdir)/version.c
diff --git a/src/wpantund/NCPConstants.h b/src/wpantund/NCPConstants.h
new file mode 100644
index 0000000..311b199
--- /dev/null
+++ b/src/wpantund/NCPConstants.h
@@ -0,0 +1,37 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef wpantund_NCPConstants_h
+#define wpantund_NCPConstants_h
+
+#define NCP_DEFAULT_COMMAND_RESPONSE_TIMEOUT 5 // seconds
+#define NCP_DEFAULT_COMMAND_SEND_TIMEOUT 5 // seconds
+#define NCP_TICKLE_TIMEOUT 60 // seconds
+#define NCP_DEEP_SLEEP_TICKLE_TIMEOUT (60*70) // Seventy minutes
+#define NCP_FORM_TIMEOUT 60 // seconds
+#define NCP_JOIN_TIMEOUT 30 // seconds
+
+#define NCP_NETWORK_KEY_SIZE 16
+
+#define BUSY_DEBOUNCE_TIME_IN_MS 200
+#define MAX_INSOMNIA_TIME_IN_MS (MSEC_PER_SEC * 60 * 3)
+
+#define NCP_DEBUG_LINE_LENGTH_MAX 400
+
+#endif
diff --git a/src/wpantund/NCPControlInterface.cpp b/src/wpantund/NCPControlInterface.cpp
new file mode 100644
index 0000000..19176be
--- /dev/null
+++ b/src/wpantund/NCPControlInterface.cpp
@@ -0,0 +1,409 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * Abstract base class for NCP implementations.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include "NCPControlInterface.h"
+#include "NCPInstance.h"
+#include "tunnel.h"
+#include <syslog.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <boost/bind.hpp>
+#include "version.h"
+#include "any-to.h"
+#include "wpan-error.h"
+
+#ifndef SOURCE_VERSION
+#define SOURCE_VERSION PACKAGE_VERSION
+#endif
+
+using namespace nl;
+using namespace wpantund;
+
+std::string
+NCPControlInterface::external_route_priority_to_string(ExternalRoutePriority route_priority)
+{
+ switch(route_priority) {
+ case ROUTE_LOW_PREFRENCE:
+ return std::string("low preference");
+
+ case ROUTE_MEDIUM_PREFERENCE:
+ return std::string("Medium (normal) preference");
+
+ case ROUTE_HIGH_PREFERENCE:
+ return std::string("High preference");
+ }
+ return std::string("Unknown route preference");
+}
+
+NCPControlInterface::~NCPControlInterface() {
+}
+
+struct GetPropertyHelper {
+ boost::any *dest;
+ bool * didFire;
+
+ void operator()(
+ int status, const boost::any& value
+ ) const
+ {
+ if (dest) {
+ if (status == 0)
+ *dest = value;
+ *didFire = true;
+ }
+ delete this;
+ }
+};
+
+boost::any
+NCPControlInterface::get_property(const std::string& key)
+{
+ // In this function, we want to immediately return the value
+ // for the given key. Since the actual get_property() function
+ // returns the value as a callback, we may not actually
+ // be able to do this. What we do here is give a callback
+ // object that contains a pointer to our return value.
+ // After we call get_property(), we then zero out that
+ // pointer. For properties which get updated immediately, our
+ // return value will be updated automatically. For properties
+ // which can't be fetched immediately, we return an empty value.
+ // The "GetPropertyHelper" class makes sure that when the
+ // callback eventually does fire that it doesn't break anything.
+
+ boost::any ret;
+ bool didFire = false;
+ struct GetPropertyHelper *helper = new GetPropertyHelper;
+
+ helper->dest = &ret;
+ helper->didFire = &didFire;
+ get_property(key, boost::bind(&GetPropertyHelper::operator(),
+ helper,
+ _1,
+ _2));
+ if (!didFire) {
+ helper->dest = 0;
+ helper->didFire = 0;
+ }
+ return ret;
+}
+
+std::string
+NCPControlInterface::get_name() {
+ return boost::any_cast<std::string>(get_property(kWPANTUNDProperty_ConfigTUNInterfaceName));
+}
+
+
+struct SetPropertyHelper {
+ int* dest;
+ bool* didFire;
+
+ void operator()(int status) const
+ {
+ if (dest) {
+ *dest = status;
+ *didFire = true;
+ }
+ delete this;
+ }
+};
+
+#define kWPANTUNDPropertyNCPSocketName "NCPSocketName"
+#define kWPANTUNDPropertyNCPSocketBaud "NCPSocketBaud"
+#define kWPANTUNDPropertyNCPDriverName "NCPDriverName"
+#define kWPANTUNDPropertyNCPHardResetPath "NCPHardResetPath"
+#define kWPANTUNDPropertyNCPPowerPath "NCPPowerPath"
+#define kWPANTUNDPropertyWPANInterfaceName "WPANInterfaceName"
+#define kWPANTUNDPropertyPIDFile "PIDFile"
+#define kWPANTUNDPropertyFirmwareCheckCommand "FirmwareCheckCommand"
+#define kWPANTUNDPropertyFirmwareUpgradeCommand "FirmwareUpgradeCommand"
+#define kWPANTUNDPropertyTerminateOnFault "TerminateOnFault"
+#define kWPANTUNDPropertyPrivDropToUser "PrivDropToUser"
+#define kWPANTUNDPropertyChroot "Chroot"
+#define kWPANTUNDPropertyNCPReliabilityLayer "NCPReliabilityLayer"
+
+// Version Properties
+#define kWPANTUNDPropertyNCPVersion "NCPVersion"
+#define kWPANTUNDPropertyDriverVersion "DriverVersion"
+
+// Driver State Properties
+#define kWPANTUNDPropertyAssociationState "AssociationState" // [RO]
+#define kWPANTUNDPropertyEnabled "Enabled" // [RW]
+#define kWPANTUNDPropertyAutoresume "AutoResume" // [RW]
+#define kWPANTUNDPropertyAutoUpdateFirmware "AutoUpdateFirmware" // [RW]
+
+// PHY-layer parameters
+#define kWPANTUNDPropertyHWAddr "HWAddr"
+#define kWPANTUNDPropertyChannel "Channel"
+#define kWPANTUNDPropertyTXPower "TXPower"
+#define kWPANTUNDPropertyNCPTXPowerLimit "NCPTXPowerLimit"
+#define kWPANTUNDPropertyCCAThreshold "CCAThreshold"
+#define kWPANTUNDPropertyDefaultChannelMask "DefaultChannelMask"
+
+// MAC-layer (and higher) parameters
+#define kWPANTUNDPropertyNetworkName "NetworkName" // [RO]
+#define kWPANTUNDPropertyXPANID "XPANID" // [RO]
+#define kWPANTUNDPropertyPANID "PANID" // [RO]
+#define kWPANTUNDPropertyNodeType "NodeType" // [RW]
+#define kWPANTUNDPropertyNetworkKey "NetworkKey" // [RW]
+#define kWPANTUNDPropertyNetworkKeyIndex "NetworkKeyIndex" // [RW]
+#define kWPANTUNDPropertyMeshLocalPrefix "MeshLocalPrefix" // [RO]
+#define kWPANTUNDPropertyAllowingJoin "AllowingJoin" // [RO]
+#define kWPANTUNDPropertyIsAssociated "IsAssociated" // [RO]
+
+// Power Management Properties
+#define kWPANTUNDPropertyIsOKToSleep "IsOKToSleep"
+#define kWPANTUNDPropertyUseDeepSleepOnLowPower "UseDeepSleepOnLowPower"
+#define kWPANTUNDPropertyAlwaysResetToWake "AlwaysResetToWake"
+#define kWPANTUNDPropertyAutoDeepSleep "AutoDeepSleep"
+#define kWPANTUNDPropertySleepPollInterval "SleepPollInterval"
+
+// Debugging and logging
+#define kWPANTUNDPropertySyslogMask "SyslogMask"
+#define kWPANTUNDPropertyNCPDebug "NCPDebug"
+
+// Properties related to manufacturing test commands
+#define kWPANTUNDPropertyMfgTestMode "MfgTestMode"
+#define kWPANTUNDPropertyMfgSYNOffset "MfgSYNOffset"
+#define kWPANTUNDPropertyMfgRepeatRandomTXInterval "MfgRepeatRandomTXInterval"
+#define kWPANTUNDPropertyMfgRepeatRandomTXLen "MfgRepeatRandomTXLen"
+#define kWPANTUNDPropertyMfgFirstPacketRSSI "MfgFirstPacketRSSI"
+#define kWPANTUNDPropertyMfgFirstPacketLQI "MfgFirstPacketLQI"
+
+
+// Nest-Specific Properties
+#define kWPANTUNDPropertyPassthruPort "PassthruPort"
+#define kWPANTUNDPropertyTransmitHookActive "TransmitHookActive"
+#define kWPANTUNDPropertyUseLegacyChannel "UseLegacyChannel"
+#define kWPANTUNDPropertyLegacyPrefix "LegacyPrefix"
+#define kWPANTUNDPropertyNetWakeData "NetWakeData"
+#define kWPANTUNDPropertyNetWakeRemaining "NetWakeRemaining"
+#define kWPANTUNDPropertyActiveWakeupBlacklist "ActiveWakeupBlacklist"
+#define kWPANTUNDPropertyLegacyInterfaceEnabled "LegacyInterfaceEnabled"
+#define kWPANTUNDPropertyPrefix "Prefix"
+
+#define kWPANTUNDPropertyGlobalIPAddresses "GlobalIPAddresses"
+#define kWPANTUNDPropertyGlobalIPAddressList "GlobalIPAddressList"
+
+int
+NCPControlInterface::set_property(const std::string& key, const boost::any& value)
+{
+ // In this function, we want to immediately return the status
+ // of the set operation. Since the actual set_property() function
+ // returns the status as a callback, we may not actually
+ // be able to do this. What we do here is give a callback
+ // object that contains a pointer to our return value.
+ // After we call set_property(), we then zero out that
+ // pointer. For properties which get updated immediately, our
+ // return value will be updated automatically. For properties
+ // which can't be fetched immediately, we return -EINPROGRESS.
+ // The "SetPropertyHelper" class makes sure that when the
+ // callback eventually does fire that it doesn't break anything.
+
+ int ret = kWPANTUNDStatus_InProgress;
+ bool didFire = false;
+ struct SetPropertyHelper *helper = new SetPropertyHelper;
+
+ helper->dest = &ret;
+ helper->didFire = &didFire;
+ set_property(key, value, boost::bind(&SetPropertyHelper::operator(),
+ helper,
+ _1));
+ if (!didFire) {
+ helper->dest = 0;
+ helper->didFire = 0;
+ }
+ return ret;
+}
+
+
+bool
+NCPControlInterface::translate_deprecated_property(std::string& key, boost::any& value)
+{
+ bool ret = false;
+ if (strcaseequal(key.c_str(), kWPANTUNDPropertyPrefix)) {
+ key = kWPANTUNDProperty_IPv6MeshLocalPrefix;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyNCPSocketName )) {
+ key = kWPANTUNDProperty_ConfigNCPSocketPath ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyNCPSocketBaud )) {
+ key = kWPANTUNDProperty_ConfigNCPSocketBaud ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyNCPDriverName )) {
+ key = kWPANTUNDProperty_ConfigNCPDriverName ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyNCPHardResetPath )) {
+ key = kWPANTUNDProperty_ConfigNCPHardResetPath ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyNCPPowerPath )) {
+ key = kWPANTUNDProperty_ConfigNCPPowerPath ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyWPANInterfaceName )) {
+ key = kWPANTUNDProperty_ConfigTUNInterfaceName ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyPIDFile )) {
+ key = kWPANTUNDProperty_ConfigDaemonPIDFile ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyFirmwareCheckCommand )) {
+ key = kWPANTUNDProperty_ConfigNCPFirmwareCheckCommand ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyFirmwareUpgradeCommand )) {
+ key = kWPANTUNDProperty_ConfigNCPFirmwareUpgradeCommand ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyTerminateOnFault )) {
+ key = kWPANTUNDProperty_DaemonTerminateOnFault ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyPrivDropToUser )) {
+ key = kWPANTUNDProperty_ConfigDaemonPrivDropToUser ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyChroot )) {
+ key = kWPANTUNDProperty_ConfigDaemonChroot ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyNCPReliabilityLayer )) {
+ key = kWPANTUNDProperty_ConfigNCPReliabilityLayer ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyNCPVersion )) {
+ key = kWPANTUNDProperty_NCPVersion ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyDriverVersion )) {
+ key = kWPANTUNDProperty_DaemonVersion ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyAssociationState )) {
+ key = kWPANTUNDProperty_NCPState ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyEnabled )) {
+ key = kWPANTUNDProperty_DaemonEnabled ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyAutoresume )) {
+ key = kWPANTUNDProperty_DaemonAutoAssociateAfterReset ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyAutoUpdateFirmware )) {
+ key = kWPANTUNDProperty_DaemonAutoFirmwareUpdate ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyHWAddr )) {
+ key = kWPANTUNDProperty_NCPHardwareAddress ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyChannel )) {
+ key = kWPANTUNDProperty_NCPChannel ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyTXPower )) {
+ key = kWPANTUNDProperty_NCPTXPower ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyNCPTXPowerLimit )) {
+ key = kWPANTUNDProperty_NCPTXPowerLimit ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyCCAThreshold )) {
+ key = kWPANTUNDProperty_NCPCCAThreshold ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyDefaultChannelMask )) {
+ key = kWPANTUNDProperty_NCPChannelMask ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyNetworkName )) {
+ key = kWPANTUNDProperty_NetworkName ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyXPANID )) {
+ key = kWPANTUNDProperty_NetworkXPANID ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyPANID )) {
+ key = kWPANTUNDProperty_NetworkPANID ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyNodeType )) {
+ key = kWPANTUNDProperty_NetworkNodeType ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyNetworkKey )) {
+ key = kWPANTUNDProperty_NetworkKey ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyNetworkKeyIndex )) {
+ key = kWPANTUNDProperty_NetworkKeyIndex ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyMeshLocalPrefix )) {
+ key = kWPANTUNDProperty_IPv6MeshLocalPrefix ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyAllowingJoin )) {
+ key = kWPANTUNDProperty_NestLabs_NetworkAllowingJoin ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyIsAssociated )) {
+ key = kWPANTUNDProperty_NetworkIsCommissioned ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyIsOKToSleep )) {
+ key = kWPANTUNDProperty_DaemonReadyForHostSleep ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyUseDeepSleepOnLowPower )) {
+ key = kWPANTUNDProperty_NestLabs_HackUseDeepSleepOnLowPower ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyAlwaysResetToWake )) {
+ key = kWPANTUNDProperty_NestLabs_HackAlwaysResetToWake ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyAutoDeepSleep )) {
+ key = kWPANTUNDProperty_DaemonAutoDeepSleep ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertySleepPollInterval )) {
+ key = kWPANTUNDProperty_NCPSleepyPollInterval ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertySyslogMask )) {
+ key = kWPANTUNDProperty_DaemonSyslogMask ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyPassthruPort )) {
+ key = kWPANTUNDProperty_NestLabs_NetworkPassthruPort ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyTransmitHookActive )) {
+ key = kWPANTUNDProperty_NestLabs_NCPTransmitHookActive ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyLegacyPrefix )) {
+ key = kWPANTUNDProperty_NestLabs_LegacyMeshLocalPrefix ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyNetWakeData )) {
+ key = kWPANTUNDProperty_NestLabs_NetworkWakeData ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyNetWakeRemaining )) {
+ key = kWPANTUNDProperty_NestLabs_NetworkWakeRemaining ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyActiveWakeupBlacklist ) || strcaseequal(key.c_str(), "ActiveWakeupMask")) {
+ key = kWPANTUNDProperty_NestLabs_NetworkWakeBlacklist ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyLegacyInterfaceEnabled )) {
+ key = kWPANTUNDProperty_NestLabs_LegacyEnabled ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyUseLegacyChannel )) {
+ key = kWPANTUNDProperty_NestLabs_LegacyPreferInterface ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyGlobalIPAddresses )) {
+ key = kWPANTUNDProperty_IPv6AllAddresses ;
+ ret = true;
+ } else if (strcaseequal(key.c_str(), kWPANTUNDPropertyGlobalIPAddressList )) {
+ key = kWPANTUNDProperty_DebugIPv6GlobalIPAddressList ;
+ ret = true;
+ }
+ return ret;
+}
+
+bool
+NCPControlInterface::translate_deprecated_property(std::string& key)
+{
+ boost::any unused;
+ return translate_deprecated_property(key, unused);
+}
diff --git a/src/wpantund/NCPControlInterface.h b/src/wpantund/NCPControlInterface.h
new file mode 100644
index 0000000..5e65490
--- /dev/null
+++ b/src/wpantund/NCPControlInterface.h
@@ -0,0 +1,254 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef wpantund_WPAN_NCPControlInterface_h
+#define wpantund_WPAN_NCPControlInterface_h
+
+#ifndef __STDC_CONSTANT_MACROS
+#define __STDC_CONSTANT_MACROS 1
+#endif
+
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+#include <boost/signals2/signal.hpp>
+#include <boost/any.hpp>
+#include <list>
+#include <arpa/inet.h>
+#include "time-utils.h"
+
+#include <pthread.h>
+
+#include "NetworkInstance.h"
+#include "NCPTypes.h"
+#include <cstring>
+#include "IPv6PacketMatcher.h"
+#include "Data.h"
+#include "NilReturn.h"
+#include "NCPConstants.h"
+#include "Callbacks.h"
+#include "wpan-properties.h"
+#include "ValueMap.h"
+
+namespace nl {
+namespace wpantund {
+
+#define USE_DEFAULT_TX_POWER INT32_MIN
+#define USE_DEFAULT_CCA_THRESHOLD INT32_MIN
+#define USE_DEFAULT_TX_POWER_MODE INT32_MIN
+#define USE_DEFAULT_TRANSMIT_HOOK_ACTIVE INT32_MIN
+
+typedef std::set<int> IntegerSet;
+
+class NCPInstance;
+
+class NCPControlInterface {
+public:
+
+ typedef uint32_t ChannelMask;
+
+ enum ExternalRoutePriority {
+ ROUTE_LOW_PREFRENCE = -1,
+ ROUTE_MEDIUM_PREFERENCE = 0,
+ ROUTE_HIGH_PREFERENCE = 1,
+ };
+
+public:
+ // ========================================================================
+ // Static Functions
+
+
+ static std::string external_route_priority_to_string(ExternalRoutePriority route_priority);
+
+public:
+ // ========================================================================
+ // Public Virtual Member Functions
+
+ //! Returns the network instance currently associated with the NCP.
+ virtual const WPAN::NetworkInstance& get_current_network_instance(void)const = 0;
+
+public:
+ // ========================================================================
+ // NCP Command Virtual Member Functions
+
+ virtual void join(
+ const ValueMap& options,
+ CallbackWithStatus cb = NilReturn()
+ ) = 0;
+
+ virtual void form(
+ const ValueMap& options,
+ CallbackWithStatus cb = NilReturn()
+ ) = 0;
+
+ virtual void leave(CallbackWithStatus cb = NilReturn()) = 0;
+
+ virtual void attach(CallbackWithStatus cb = NilReturn()) = 0;
+
+ virtual void reset(CallbackWithStatus cb = NilReturn()) = 0;
+
+ virtual void refresh_state(CallbackWithStatus cb = NilReturn()) = 0;
+
+ virtual void get_property(
+ const std::string& key,
+ CallbackWithStatusArg1 cb
+ ) = 0;
+
+ virtual void set_property(
+ const std::string& key,
+ const boost::any& value,
+ CallbackWithStatus cb
+ ) = 0;
+
+ virtual void add_on_mesh_prefix(
+ const struct in6_addr *prefix,
+ bool defaultRoute,
+ CallbackWithStatus cb = NilReturn()
+ ) = 0;
+
+ virtual void remove_on_mesh_prefix(
+ const struct in6_addr *prefix,
+ CallbackWithStatus cb = NilReturn()
+ ) = 0;
+
+ virtual void add_external_route(
+ const struct in6_addr *prefix,
+ int prefix_len_in_bits,
+ int domain_id,
+ ExternalRoutePriority priority,
+ CallbackWithStatus cb = NilReturn()
+ ) = 0;
+
+ virtual void remove_external_route(
+ const struct in6_addr *prefix,
+ int prefix_len_in_bits,
+ int domain_id,
+ CallbackWithStatus cb = NilReturn()
+ ) = 0;
+
+ virtual void pcap_to_fd(
+ int fd,
+ CallbackWithStatus cb = NilReturn()
+ ) = 0;
+
+ virtual void pcap_terminate(
+ CallbackWithStatus cb = NilReturn()
+ ) = 0;
+
+public:
+ // ========================================================================
+ // Scan-related Member Functions
+
+ virtual void netscan_start(const ValueMap& options, CallbackWithStatus cb = NilReturn()) = 0;
+
+ virtual void netscan_stop(CallbackWithStatus cb = NilReturn()) = 0;
+
+ boost::signals2::signal<void(const WPAN::NetworkInstance&)> mOnNetScanBeacon;
+
+public:
+ // ========================================================================
+ // EnergyScan-related Member Functions
+
+ virtual void energyscan_start(const ValueMap& options, CallbackWithStatus cb = NilReturn()) = 0;
+
+ virtual void energyscan_stop(CallbackWithStatus cb = NilReturn()) = 0;
+
+ boost::signals2::signal<void(const EnergyScanResultEntry&)> mOnEnergyScanResult;
+
+public:
+ // ========================================================================
+ // Power-related Member Functions
+
+ virtual void begin_low_power(CallbackWithStatus cb = NilReturn()) = 0;
+
+ virtual void host_did_wake(CallbackWithStatus cb = NilReturn()) = 0;
+
+ virtual void data_poll(CallbackWithStatus cb = NilReturn()) = 0;
+
+
+public:
+ // ========================================================================
+ // Nest-Specific Member Functions
+
+ virtual void begin_net_wake(
+ uint8_t data = 0,
+ uint32_t flags = 0,
+ CallbackWithStatus cb = NilReturn()
+ ) = 0;
+
+ virtual void permit_join(
+ int seconds = 15 * 60,
+ uint8_t commissioning_traffic_type = 0xFF,
+ in_port_t commissioning_traffic_port = 0,
+ bool network_wide = false,
+ CallbackWithStatus cb = NilReturn()
+ ) = 0;
+
+
+public:
+ // ========================================================================
+ // Convenience methods
+
+ boost::any get_property(const std::string& key);
+
+ int set_property(const std::string& key, const boost::any& value);
+
+ virtual std::string get_name();
+
+public:
+ // ========================================================================
+ // Other
+
+ static bool translate_deprecated_property(std::string& key, boost::any& value);
+
+ static bool translate_deprecated_property(std::string& key);
+
+
+public:
+ // ========================================================================
+ // Signals
+
+ //! Fires whenever value of certain properties changed (e.g. NodeType).
+ boost::signals2::signal<void(const std::string& key, const boost::any& value)> mOnPropertyChanged;
+
+public:
+ // ========================================================================
+ // Nest-Specific Signals
+
+ //! Fires when the network wake state has changed or been updated.
+ boost::signals2::signal<void(uint8_t data, cms_t ms_remaining)> mOnNetWake;
+
+protected:
+ // ========================================================================
+ // Protected Virtual Member Functions
+
+ virtual ~NCPControlInterface();
+
+ //! Returns the associated NCP instance.
+ virtual NCPInstance& get_ncp_instance(void) = 0;
+};
+
+}; // namespace wpantund
+}; // namespace nl
+
+#endif
diff --git a/src/wpantund/NCPInstance.cpp b/src/wpantund/NCPInstance.cpp
new file mode 100644
index 0000000..1b198cc
--- /dev/null
+++ b/src/wpantund/NCPInstance.cpp
@@ -0,0 +1,149 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "assert-macros.h"
+#include "NCPInstance.h"
+#include "tunnel.h"
+#include <syslog.h>
+#include <errno.h>
+
+#ifndef HAVE_DLFCN_H
+#define HAVE_DLFCN_H defined(__APPLE__)
+#endif
+
+#ifndef PKGLIBEXECDIR
+#define PKGLIBEXECDIR "/usr/local/libexec/wpantund"
+#endif
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#ifndef RTLD_DEFAULT
+#define RTLD_DEFAULT ((void*)0)
+#endif
+#ifndef RTLD_NEXT
+#define RTLD_NEXT ((void*)-1l)
+#endif
+#endif
+
+#if WPANTUND_PLUGIN_STATICLY_LINKED
+#undef HAVE_DLFCN_H
+#endif
+
+#ifndef WPANTUND_DEFAULT_NCP_PLUGIN
+#if WPANTUND_PLUGIN_STATICLY_LINKED
+#define WPANTUND_DEFAULT_NCP_PLUGIN "default"
+#else
+#define WPANTUND_DEFAULT_NCP_PLUGIN "spinel"
+#endif
+#endif
+
+using namespace nl;
+using namespace wpantund;
+
+typedef nl::wpantund::NCPInstance* (*NCPInstanceAllocatorType)(const nl::wpantund::NCPInstance::Settings& settings);
+
+NCPInstance*
+NCPInstance::alloc(const Settings& settings)
+{
+ NCPInstance* ret = NULL;
+ std::string ncp_driver_name = WPANTUND_DEFAULT_NCP_PLUGIN;
+ std::string symbol_name = "wpantund_ncpinstance_default_alloc";
+ NCPInstanceAllocatorType allocator = NULL;
+
+ if (settings.count(kWPANTUNDProperty_ConfigNCPDriverName)) {
+ ncp_driver_name = settings.find(kWPANTUNDProperty_ConfigNCPDriverName)->second;
+ }
+
+ if (ncp_driver_name == "default") {
+ ncp_driver_name = WPANTUND_DEFAULT_NCP_PLUGIN;
+ }
+
+#if WPANTUND_PLUGIN_STATICLY_LINKED
+ // Statically-linked plugin
+ if ((allocator == NULL) && (ncp_driver_name == WPANTUND_DEFAULT_NCP_PLUGIN)) {
+ allocator = &wpantund_ncpinstance_default_alloc;
+ }
+#else
+ // Dynamically-loaded plugin
+ std::string plugin_path;
+
+ if ((ncp_driver_name.find('/') != std::string::npos)
+ || (ncp_driver_name.find('.') != std::string::npos)
+ ) {
+ plugin_path = ncp_driver_name;
+ } else {
+ plugin_path = std::string("ncp-") + ncp_driver_name + ".so";
+ symbol_name = std::string("wpantund_ncpinstance_") +ncp_driver_name + "_alloc";
+
+ if( access( (std::string(PKGLIBEXECDIR "/") + plugin_path).c_str(), X_OK ) != -1 ) {
+ plugin_path = std::string(PKGLIBEXECDIR "/") + plugin_path;
+ }
+
+ allocator = (NCPInstanceAllocatorType)dlsym(RTLD_DEFAULT, symbol_name.c_str());
+ }
+
+ if (allocator == NULL) {
+ // We failed to immediately look up the allocator function,
+ // so lets see if we can find a plug-in that we can open,
+ // and then try again.
+
+ void* dl_handle = NULL;
+
+ dl_handle = dlopen(plugin_path.c_str(), RTLD_NOW|RTLD_LOCAL);
+
+ if (dl_handle == NULL) {
+ syslog(LOG_ERR, "Couldn't open plugin \"%s\", %s", plugin_path.c_str(), dlerror());
+ } else {
+ allocator = (NCPInstanceAllocatorType)dlsym(dl_handle, symbol_name.c_str());
+ }
+ }
+
+#endif
+
+ require_string(allocator != NULL, bail, "Unknown NCP Driver");
+
+ ret = (*allocator)(settings);
+
+bail:
+ if (ret == NULL) {
+ syslog(LOG_ERR, "Unable to load NCP driver \"%s\".", ncp_driver_name.c_str());
+ }
+
+ return ret;
+}
+
+NCPInstance::~NCPInstance()
+{
+}
+
+void
+NCPInstance::signal_fatal_error(int err)
+{
+ if (err == ERRORCODE_ERRNO) {
+ syslog(LOG_CRIT, "NCPInstance: errno %d \"%s\"\n", errno, strerror(
+ errno));
+ } else {
+ syslog(LOG_CRIT, "NCPInstance: error %d\n", err);
+ }
+ mOnFatalError(err);
+}
diff --git a/src/wpantund/NCPInstance.h b/src/wpantund/NCPInstance.h
new file mode 100644
index 0000000..62a363b
--- /dev/null
+++ b/src/wpantund/NCPInstance.h
@@ -0,0 +1,122 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __wpantund__NCPInstance__
+#define __wpantund__NCPInstance__
+
+#define BOOST_SIGNALS_NO_DEPRECATION_WARNING 1
+
+#ifndef __STDC_CONSTANT_MACROS
+#define __STDC_CONSTANT_MACROS 1
+#endif
+
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+#include <boost/signals2/signal.hpp>
+#include <boost/any.hpp>
+#include <list>
+#include <arpa/inet.h>
+
+#include "NetworkInstance.h"
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <cstring>
+#include "IPv6PacketMatcher.h"
+#include "Data.h"
+#include "NilReturn.h"
+#include "NCPControlInterface.h"
+#include "tunnel.h"
+#include "SocketAdapter.h"
+#include "TunnelIPv6Interface.h"
+#include "NCPConstants.h"
+#include "wpan-error.h"
+#include "StatCollector.h"
+
+#define ERRORCODE_OK (0)
+#define ERRORCODE_HELP (1)
+#define ERRORCODE_BADARG (2)
+#define ERRORCODE_NOCOMMAND (3)
+#define ERRORCODE_UNKNOWN (4)
+#define ERRORCODE_BADCOMMAND (5)
+#define ERRORCODE_NOREADLINE (6)
+#define ERRORCODE_QUIT (7)
+#define ERRORCODE_BADCONFIG (8)
+#define ERRORCODE_ERRNO (9)
+
+#define ERRORCODE_INTERRUPT (128 + SIGINT)
+#define ERRORCODE_SIGHUP (128 + SIGHUP)
+
+#define WTD_WEAK __attribute__((weak))
+
+#define WPANTUND_DECLARE_NCPINSTANCE_PLUGIN(short_name, class_name) \
+ extern "C" nl::wpantund::NCPInstance* wpantund_ncpinstance_ ## short_name ## _alloc(const nl::wpantund::NCPInstance::Settings& settings)
+
+#define WPANTUND_DEFINE_NCPINSTANCE_PLUGIN(short_name, class_name) \
+ nl::wpantund::NCPInstance* \
+ wpantund_ncpinstance_ ## short_name ## _alloc(const nl::wpantund::NCPInstance::Settings& settings) { \
+ return new class_name(settings); \
+ } \
+ nl::wpantund::NCPInstance* \
+ wpantund_ncpinstance_default_alloc(const nl::wpantund::NCPInstance::Settings& settings) { \
+ return new class_name(settings); \
+ }
+
+namespace nl {
+
+namespace wpantund {
+class NCPControlInterface;
+
+class NCPInstance {
+public:
+ typedef std::map<std::string, std::string> Settings;
+
+public:
+ static NCPInstance* alloc(
+ const Settings& settings = Settings()
+ );
+
+ virtual ~NCPInstance();
+
+ virtual const std::string &get_name(void) = 0;
+ virtual NCPControlInterface& get_control_interface(void) = 0;
+ virtual StatCollector& get_stat_collector(void) = 0;
+
+ virtual void set_socket_adapter(const boost::shared_ptr<SocketAdapter> &adapter) = 0;
+
+ virtual cms_t get_ms_to_next_event(void) = 0;
+ virtual void process(void) = 0;
+ virtual int update_fd_set(fd_set *read_fd_set, fd_set *write_fd_set, fd_set *error_fd_set, int *max_fd, cms_t *timeout) = 0;
+
+public:
+ void signal_fatal_error(int err);
+ SignalWithStatus mOnFatalError;
+}; // class NCPInstance
+
+}; // namespace wpantund
+}; // namespace nl
+
+extern "C" nl::wpantund::NCPInstance* wpantund_ncpinstance_default_alloc(const nl::wpantund::NCPInstance::Settings& settings);
+
+#endif /* defined(__wpantund__NCPInstance__) */
diff --git a/src/wpantund/NCPInstanceBase-Addresses.cpp b/src/wpantund/NCPInstanceBase-Addresses.cpp
new file mode 100644
index 0000000..d79a520
--- /dev/null
+++ b/src/wpantund/NCPInstanceBase-Addresses.cpp
@@ -0,0 +1,205 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "assert-macros.h"
+#include "NCPInstanceBase.h"
+#include "tunnel.h"
+#include <syslog.h>
+#include <errno.h>
+#include "nlpt.h"
+#include <algorithm>
+#include "socket-utils.h"
+#include "SuperSocket.h"
+
+using namespace nl;
+using namespace wpantund;
+
+
+
+void
+NCPInstanceBase::refresh_global_addresses()
+{
+ // Here is where we would do any periodic global address bookkeeping,
+ // which doesn't appear to be necessary yet but may become necessary
+ // in the future.
+}
+
+void
+NCPInstanceBase::clear_nonpermanent_global_addresses()
+{
+ std::map<struct in6_addr, GlobalAddressEntry>::iterator iter;
+
+ // We want to remove all of the addresses that were
+ // not user-added.
+ //
+ // This loop looks a little weird because we are mutating
+ // the container as we are iterating through it. Whenever
+ // we mutate the container we have to start over.
+ do {
+ for (iter = mGlobalAddresses.begin(); iter != mGlobalAddresses.end(); ++iter) {
+ // Skip the removal of user-added addresses.
+ if (iter->second.mUserAdded) {
+ continue;
+ }
+
+ mPrimaryInterface->remove_address(&iter->first);
+ mGlobalAddresses.erase(iter);
+
+ // The following assignment is needed to avoid
+ // an invalid iterator comparison in the outer loop.
+ iter = mGlobalAddresses.begin();
+
+ // Break out of the inner loop so that we start over.
+ break;
+ }
+ } while(iter != mGlobalAddresses.end());
+}
+
+void
+NCPInstanceBase::restore_global_addresses()
+{
+ std::map<struct in6_addr, GlobalAddressEntry>::const_iterator iter;
+ std::map<struct in6_addr, GlobalAddressEntry> global_addresses(mGlobalAddresses);
+
+ mGlobalAddresses.clear();
+
+ for (iter = global_addresses.begin(); iter!= global_addresses.end(); ++iter) {
+ if (iter->second.mUserAdded) {
+ address_was_added(iter->first, 64);
+ }
+ mGlobalAddresses.insert(*iter);
+
+ mPrimaryInterface->add_address(&iter->first);
+ }
+}
+
+void
+NCPInstanceBase::add_address(const struct in6_addr &address, uint8_t prefix, uint32_t valid_lifetime, uint32_t preferred_lifetime)
+{
+ GlobalAddressEntry entry = GlobalAddressEntry();
+
+ if (mGlobalAddresses.count(address)) {
+ syslog(LOG_INFO, "Updating IPv6 Address...");
+ entry = mGlobalAddresses[address];
+ } else {
+ syslog(LOG_INFO, "Adding IPv6 Address...");
+ mPrimaryInterface->add_address(&address);
+ }
+
+ entry.mValidLifetime = valid_lifetime;
+ entry.mPreferredLifetime = preferred_lifetime;
+ entry.mValidLifetimeExpiration = ((valid_lifetime == UINT32_MAX)
+ ? TIME_DISTANT_FUTURE
+ : time_get_monotonic() + valid_lifetime
+ );
+ entry.mPreferredLifetimeExpiration = ((valid_lifetime == UINT32_MAX)
+ ? TIME_DISTANT_FUTURE
+ : time_get_monotonic() + preferred_lifetime
+ );
+
+ mGlobalAddresses[address] = entry;
+}
+
+void
+NCPInstanceBase::remove_address(const struct in6_addr &address)
+{
+ mGlobalAddresses.erase(address);
+ mPrimaryInterface->remove_address(&address);
+}
+
+bool
+NCPInstanceBase::is_address_known(const struct in6_addr &address)
+{
+ bool ret(mGlobalAddresses.count(address) != 0);
+
+ return ret;
+}
+
+bool
+NCPInstanceBase::lookup_address_for_prefix(struct in6_addr *address, const struct in6_addr &prefix, int prefix_len_in_bits)
+{
+ struct in6_addr masked_prefix(prefix);
+
+ in6_addr_apply_mask(masked_prefix, prefix_len_in_bits);
+
+ std::map<struct in6_addr, GlobalAddressEntry>::const_iterator iter;
+ for (iter = mGlobalAddresses.begin(); iter != mGlobalAddresses.end(); ++iter) {
+ struct in6_addr iter_prefix(iter->first);
+ in6_addr_apply_mask(iter_prefix, prefix_len_in_bits);
+
+ if (iter_prefix == masked_prefix) {
+ if (address != NULL) {
+ *address = iter->first;
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+NCPInstanceBase::address_was_added(const struct in6_addr& addr, int prefix_len)
+{
+ char addr_cstr[INET6_ADDRSTRLEN] = "::";
+ inet_ntop(
+ AF_INET6,
+ &addr,
+ addr_cstr,
+ sizeof(addr_cstr)
+ );
+
+ syslog(LOG_NOTICE, "\"%s\" was added to \"%s\"", addr_cstr, mPrimaryInterface->get_interface_name().c_str());
+
+ if (mGlobalAddresses.count(addr) == 0) {
+ const GlobalAddressEntry entry = {
+ UINT32_MAX, // .mValidLifetime
+ TIME_DISTANT_FUTURE, // .mValidLifetimeExpiration
+ UINT32_MAX, // .mPreferredLifetime
+ TIME_DISTANT_FUTURE, // .mPreferredLifetimeExpiration
+ 0, // .mFlags
+ 1, // .mUserAdded
+ };
+
+ mGlobalAddresses[addr] = entry;
+ }
+}
+
+void
+NCPInstanceBase::address_was_removed(const struct in6_addr& addr, int prefix_len)
+{
+ char addr_cstr[INET6_ADDRSTRLEN] = "::";
+ inet_ntop(
+ AF_INET6,
+ &addr,
+ addr_cstr,
+ sizeof(addr_cstr)
+ );
+
+ if ((mGlobalAddresses.count(addr) != 0)
+ && (mPrimaryInterface->is_online() || !mGlobalAddresses[addr].mUserAdded)
+ ) {
+ mGlobalAddresses.erase(addr);
+ }
+
+ syslog(LOG_NOTICE, "\"%s\" was removed from \"%s\"", addr_cstr, mPrimaryInterface->get_interface_name().c_str());
+}
diff --git a/src/wpantund/NCPInstanceBase-AsyncIO.cpp b/src/wpantund/NCPInstanceBase-AsyncIO.cpp
new file mode 100644
index 0000000..5d1955a
--- /dev/null
+++ b/src/wpantund/NCPInstanceBase-AsyncIO.cpp
@@ -0,0 +1,238 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "assert-macros.h"
+#include "NCPInstanceBase.h"
+#include "tunnel.h"
+#include <syslog.h>
+#include <errno.h>
+#include "nlpt.h"
+#include <algorithm>
+#include "socket-utils.h"
+#include "SuperSocket.h"
+
+using namespace nl;
+using namespace wpantund;
+
+bool
+NCPInstanceBase::can_set_ncp_power(void)
+{
+ return mPowerFD >= 0;
+}
+
+int
+NCPInstanceBase::set_ncp_power(bool power)
+{
+ ssize_t ret = -1;
+
+ if (mPowerFD >= 0) {
+ // Since controlling the power such a low-level
+ // operation, we break with our usual "no blocking calls"
+ // rule here for code clarity and to avoid
+ // unnecessary complexity.
+
+ IGNORE_RETURN_VALUE( lseek(mPowerFD, 0, SEEK_SET));
+
+ if (power) {
+ ret = write(mPowerFD, static_cast<const void*>(&mPowerFD_PowerOn), 1);
+ } else {
+ ret = write(mPowerFD, static_cast<const void*>(&mPowerFD_PowerOff), 1);
+ }
+
+ require_string(ret >= 0, bail, strerror(errno));
+
+ // We assign the return value of `write()` here
+ // to `ret` because we don't care if writing the `\n`
+ // fails. This happens when writing directly to GPIO
+ // files. We write the "\n" anyway to make it easier
+ // for non-GPIO sockets to parse.
+ IGNORE_RETURN_VALUE( write(mPowerFD, static_cast<const void*>("\n"), 1) );
+ }
+
+ if (ret > 0) {
+ ret = 0;
+ }
+
+bail:
+
+ return static_cast<int>(ret);
+}
+
+void
+NCPInstanceBase::hard_reset_ncp(void)
+{
+ NLPT_INIT(&mDriverToNCPPumpPT);
+ NLPT_INIT(&mNCPToDriverPumpPT);
+
+ if (mResetFD >= 0) {
+ // Since hardware resets are such a low-level
+ // operation, we break with our usual "no blocking calls"
+ // rule here for code clarity and to avoid
+ // unnecessary complexity.
+
+ ssize_t wret = -1;
+
+ IGNORE_RETURN_VALUE( lseek(mResetFD, 0, SEEK_SET) );
+
+ wret = write(mResetFD, static_cast<const void*>(&mResetFD_BeginReset), 1);
+
+ check_string(wret != -1, strerror(errno));
+
+ // We don't assign the return value of `write()` here
+ // to `ret` because we don't care if writing the `\n`
+ // fails. This happens when writing directly to GPIO
+ // files. We write the "\n" anyway to make it easier
+ // for non-GPIO sockets to parse.
+ IGNORE_RETURN_VALUE( write(mResetFD, static_cast<const void*>("\n"), 1) );
+
+ usleep(20 * USEC_PER_MSEC);
+
+ IGNORE_RETURN_VALUE( lseek(mResetFD, 0, SEEK_SET) );
+
+ wret = write(mResetFD, static_cast<const void*>(&mResetFD_EndReset), 1);
+
+ check_string(wret != -1, strerror(errno));
+
+ IGNORE_RETURN_VALUE( write(mResetFD, static_cast<const void*>("\n"), 1) );
+ } else {
+ mSerialAdapter->reset();
+ }
+}
+
+void
+NCPInstanceBase::set_socket_adapter(const boost::shared_ptr<SocketAdapter> &adapter)
+{
+ if(adapter) {
+ adapter->set_parent(mRawSerialAdapter);
+ mSerialAdapter = adapter;
+ } else {
+ mSerialAdapter = mRawSerialAdapter;
+ }
+}
+
+// ----------------------------------------------------------------------------
+// MARK: -
+
+cms_t
+NCPInstanceBase::get_ms_to_next_event(void)
+{
+ cms_t ret(EventHandler::get_ms_to_next_event());
+
+ mSerialAdapter->update_fd_set(NULL, NULL, NULL, NULL, &ret);
+ mPrimaryInterface->update_fd_set(NULL, NULL, NULL, NULL, &ret);
+ mFirmwareUpgrade.update_fd_set(NULL, NULL, NULL, NULL, &ret);
+
+ if (mWasBusy && (mLastChangedBusy != 0)) {
+ cms_t temp_cms(MAX_INSOMNIA_TIME_IN_MS - (time_ms() - mLastChangedBusy));
+ if (temp_cms < ret) {
+ ret = temp_cms;
+ }
+
+ if (ret > BUSY_DEBOUNCE_TIME_IN_MS && !is_busy()) {
+ ret = BUSY_DEBOUNCE_TIME_IN_MS;
+ }
+ }
+
+ if (ret < 0) {
+ ret = 0;
+ }
+
+ return ret;
+}
+
+int
+NCPInstanceBase::update_fd_set(fd_set *read_fd_set, fd_set *write_fd_set, fd_set *error_fd_set, int *max_fd, cms_t *timeout)
+{
+ int ret = -1;
+
+ if (timeout != NULL) {
+ *timeout = std::min(*timeout, get_ms_to_next_event());
+ }
+
+ ret = mFirmwareUpgrade.update_fd_set(read_fd_set, write_fd_set, error_fd_set, max_fd, timeout);
+
+ require_noerr(ret, bail);
+
+ ret = mPcapManager.update_fd_set(read_fd_set, write_fd_set, error_fd_set, max_fd, timeout);
+
+ require_noerr(ret, bail);
+
+ if (!ncp_state_is_detached_from_ncp(get_ncp_state())) {
+ nlpt_select_update_fd_set(&mDriverToNCPPumpPT, read_fd_set, write_fd_set, error_fd_set, max_fd);
+ nlpt_select_update_fd_set(&mNCPToDriverPumpPT, read_fd_set, write_fd_set, error_fd_set, max_fd);
+
+ ret = mPrimaryInterface->update_fd_set(read_fd_set, write_fd_set, error_fd_set, max_fd, timeout);
+ require_noerr(ret, bail);
+
+ if (is_legacy_interface_enabled()) {
+ ret = mLegacyInterface->update_fd_set(read_fd_set, write_fd_set, error_fd_set, max_fd, timeout);
+ require_noerr(ret, bail);
+ }
+
+ ret = mSerialAdapter->update_fd_set(read_fd_set, write_fd_set, error_fd_set, max_fd, timeout);
+ require_noerr(ret, bail);
+ }
+
+bail:
+ return ret;
+}
+
+void
+NCPInstanceBase::process(void)
+{
+ int ret = 0;
+
+ mRunawayResetBackoffManager.update();
+
+ mFirmwareUpgrade.process();
+
+ mPcapManager.process();
+
+ if (get_upgrade_status() != EINPROGRESS) {
+ refresh_global_addresses();
+
+ require_noerr(ret = mPrimaryInterface->process(), socket_failure);
+
+ if (is_legacy_interface_enabled()) {
+ mLegacyInterface->process();
+ }
+
+ require_noerr(ret = mSerialAdapter->process(), socket_failure);
+
+ ncp_to_driver_pump();
+ }
+
+ EventHandler::process_event(EVENT_IDLE);
+
+ if (get_upgrade_status() != EINPROGRESS) {
+ driver_to_ncp_pump();
+ }
+
+ update_busy_indication();
+
+ return;
+
+socket_failure:
+ signal_fatal_error(ret);
+ return;
+}
diff --git a/src/wpantund/NCPInstanceBase-NetInterface.cpp b/src/wpantund/NCPInstanceBase-NetInterface.cpp
new file mode 100644
index 0000000..b6ee944
--- /dev/null
+++ b/src/wpantund/NCPInstanceBase-NetInterface.cpp
@@ -0,0 +1,478 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "assert-macros.h"
+#include "NCPInstanceBase.h"
+#include "tunnel.h"
+#include <syslog.h>
+#include <errno.h>
+#include "nlpt.h"
+#include <algorithm>
+#include "socket-utils.h"
+#include "SuperSocket.h"
+
+using namespace nl;
+using namespace wpantund;
+
+
+int
+NCPInstanceBase::set_online(bool x)
+{
+ int ret;
+
+ ret = mPrimaryInterface->set_online(x);
+
+ restore_global_addresses();
+
+ if (IN6_IS_ADDR_LINKLOCAL(&mNCPLinkLocalAddress)) {
+ add_address(mNCPLinkLocalAddress);
+ }
+
+ if (buffer_is_nonzero(mNCPMeshLocalAddress.s6_addr, sizeof(mNCPMeshLocalAddress))) {
+ add_address(mNCPMeshLocalAddress);
+ }
+
+ if ((ret == 0) && static_cast<bool>(mLegacyInterface)) {
+ if (x && mNodeTypeSupportsLegacy) {
+ ret = mLegacyInterface->set_online(true);
+
+ if (IN6_IS_ADDR_LINKLOCAL(&mNCPLinkLocalAddress)) {
+ mLegacyInterface->add_address(&mNCPLinkLocalAddress);
+ }
+ } else {
+ ret = mLegacyInterface->set_online(false);
+ }
+ }
+
+ return ret;
+}
+
+void
+NCPInstanceBase::set_mac_address(const uint8_t x[8])
+{
+ if (0 != memcmp(x, mMACAddress, sizeof(mMACAddress))) {
+ memcpy(mMACAddress, x, sizeof(mMACAddress));
+
+ syslog(
+ LOG_INFO,
+ "NCP Status: MACAddr: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
+ mMACAddress[0],mMACAddress[1],mMACAddress[2],mMACAddress[3],
+ mMACAddress[4],mMACAddress[5],mMACAddress[6],mMACAddress[7]
+ );
+
+ if ((x[0] & 1) == 1) {
+ syslog(LOG_WARNING,"MAC ADDRESS IS INVALID, MULTICAST BIT IS SET!");
+ }
+
+ signal_property_changed(kWPANTUNDProperty_NCPMACAddress, Data(mMACAddress, sizeof(mMACAddress)));
+
+ }
+
+ if (!buffer_is_nonzero(mMACHardwareAddress, sizeof(mMACHardwareAddress))) {
+ set_mac_hardware_address(x);
+ }
+}
+
+void
+NCPInstanceBase::set_mac_hardware_address(const uint8_t x[8])
+{
+ if (0 != memcmp(x, mMACHardwareAddress, sizeof(mMACHardwareAddress))) {
+ memcpy(mMACHardwareAddress, x, sizeof(mMACHardwareAddress));
+
+ syslog(
+ LOG_INFO,
+ "NCP Status: MACHardwareAddr: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
+ mMACHardwareAddress[0],mMACHardwareAddress[1],mMACHardwareAddress[2],mMACHardwareAddress[3],
+ mMACHardwareAddress[4],mMACHardwareAddress[5],mMACHardwareAddress[6],mMACHardwareAddress[7]
+ );
+
+ if ((x[0] & 1) == 1) {
+ syslog(LOG_WARNING,"HARDWARE ADDRESS IS INVALID, MULTICAST BIT IS SET!");
+ }
+
+ signal_property_changed(kWPANTUNDProperty_NCPHardwareAddress, Data(mMACHardwareAddress, sizeof(mMACHardwareAddress)));
+
+ }
+}
+
+void
+NCPInstanceBase::reset_interface(void)
+{
+ syslog(LOG_NOTICE, "Resetting interface(s). . .");
+
+ mCurrentNetworkInstance.joinable = false;
+
+ set_commissioniner(0, 0, 0);
+
+ mPrimaryInterface->reset();
+
+ // The global address table must be cleared upon reset.
+ mGlobalAddresses.clear();
+
+ if (static_cast<bool>(mLegacyInterface)) {
+ mLegacyInterface->reset();
+ }
+}
+
+void
+NCPInstanceBase::enable_legacy_interface(void)
+{
+ if (!static_cast<bool>(mLegacyInterface)) {
+ mLegacyInterface = boost::shared_ptr<TunnelIPv6Interface>(new TunnelIPv6Interface(mPrimaryInterface->get_interface_name()+"-L"));
+ }
+}
+
+bool
+NCPInstanceBase::is_legacy_interface_enabled(void)
+{
+ if (mNodeTypeSupportsLegacy) {
+ return static_cast<bool>(mLegacyInterface);
+ }
+ return false;
+}
+
+
+
+int
+NCPInstanceBase::join_multicast_group(const std::string &group_name)
+{
+ int ret = -1;
+ struct ipv6_mreq imreq;
+ unsigned int value = 1;
+ struct hostent *tmp = gethostbyname2(group_name.c_str(), AF_INET6);
+ memset(&imreq, 0, sizeof(imreq));
+
+ if (mMCFD < 0) {
+ mMCFD = socket(AF_INET6, SOCK_DGRAM, 0);
+ }
+
+ require(mMCFD >= 0, skip_mcast);
+
+ require(!h_errno && tmp, skip_mcast);
+ require(tmp->h_length > 1, skip_mcast);
+
+ memcpy(&imreq.ipv6mr_multiaddr.s6_addr, tmp->h_addr_list[0], 16);
+
+ value = 1;
+ ret = setsockopt(
+ mMCFD,
+ IPPROTO_IPV6,
+ IPV6_MULTICAST_LOOP,
+ &value,
+ sizeof(value)
+ );
+ require_noerr(ret, skip_mcast);
+
+ imreq.ipv6mr_interface = if_nametoindex(mPrimaryInterface->get_interface_name().c_str());
+
+ ret = setsockopt(
+ mMCFD,
+ IPPROTO_IPV6,
+ IPV6_JOIN_GROUP,
+ &imreq,
+ sizeof(imreq)
+ );
+ require_noerr(ret, skip_mcast);
+
+skip_mcast:
+
+ if (ret) {
+ syslog(LOG_WARNING, "Failed to join multicast group \"%s\"", group_name.c_str());
+ }
+
+ return ret;
+}
+
+
+int
+NCPInstanceBase::set_commissioniner(
+ int seconds, uint8_t traffic_type, in_port_t traffic_port
+ )
+{
+ int ret = kWPANTUNDStatus_Ok;
+
+ mCommissioningRule.clear();
+
+ if ((seconds > 0) && (traffic_port == 0)) {
+ ret = kWPANTUNDStatus_InvalidArgument;
+ goto bail;
+ }
+
+ if (seconds > 0 && traffic_port) {
+ mCommissioningExpiration = time_get_monotonic() + seconds;
+
+ mCommissioningRule.type = traffic_type;
+ mCommissioningRule.local_port = traffic_port;
+ mCommissioningRule.local_port_match = true;
+ mCommissioningRule.local_address.s6_addr[0] = 0xFE;
+ mCommissioningRule.local_address.s6_addr[1] = 0x80;
+ mCommissioningRule.local_match_mask = 10;
+ } else {
+ mCommissioningExpiration = 0;
+ mInsecureFirewall.clear();
+ }
+
+bail:
+ return ret;
+}
+
+
+
+void
+NCPInstanceBase::handle_normal_ipv6_from_ncp(const uint8_t* ip_packet, size_t packet_length)
+{
+ ssize_t ret = mPrimaryInterface->write(ip_packet, packet_length);
+
+ if (ret != packet_length) {
+ syslog(LOG_INFO, "[NCP->] IPv6 packet refused by host stack! (ret = %ld)", (long)ret);
+ }
+}
+
+void
+NCPInstanceBase::handle_alt_ipv6_from_ncp(const uint8_t* ip_packet, size_t packet_length)
+{
+ ssize_t ret = mLegacyInterface->write(ip_packet, packet_length);
+
+ if (ret != packet_length) {
+ syslog(LOG_INFO, "[NCP->] IPv6 packet refused by host stack! (ret = %ld)", (long)ret);
+ }
+}
+
+#define FRAME_TYPE_TO_CSTR(x) \
+ (((x) == FRAME_TYPE_INSECURE_DATA) \
+ ? "INSECURE" \
+ : ((x) == FRAME_TYPE_LEGACY_DATA) \
+ ? "LEGACY" \
+ : "SECURE")
+
+// This function does a little more than it's name might imply.
+// It will also mutate the NCP frame to reflect the appropriate
+// interface if the firewall rules indicate that it should be
+// handled differently (i.e., a insecure packet that matches
+// the appropriate firewall rules will be re-tagged as a normal
+// packet, etc.)
+bool
+NCPInstanceBase::should_forward_hostbound_frame(uint8_t* type, const uint8_t* ip_packet, size_t packet_length)
+{
+ bool packet_should_be_dropped = false;
+ IPv6PacketMatcherRule rule;
+
+ rule.update_from_inbound_packet(ip_packet);
+
+ // Handle special considerations for packets received
+ // from the insecure data channel.
+ if (*type == FRAME_TYPE_INSECURE_DATA) {
+ // If the packet is from the insecure channel, we
+ // mark the packed as "to be dropped" by default.
+ // We perform some additional checks below which
+ // may switch this back to `false`.
+ packet_should_be_dropped = true;
+
+ if (ncp_state_is_joining(get_ncp_state())) {
+ // Don't drop data from insecure channel if we
+ // aren't joined yet.
+ packet_should_be_dropped = false;
+
+ } else if (mCommissioningExpiration != 0) {
+ if (mCommissioningExpiration > time_get_monotonic()) {
+ // We are in the middle of commissioning and we
+ // haven't expired yet.
+
+ if (mInsecureFirewall.count(rule)) {
+ syslog(LOG_INFO,
+ "[NCP->] Routing insecure commissioning traffic.");
+ packet_should_be_dropped = false;
+ } else if (mCommissioningRule.match_inbound(ip_packet)) {
+ rule.subtype = IPv6PacketMatcherRule::SUBTYPE_ALL;
+ mInsecureFirewall.insert(rule);
+ packet_should_be_dropped = false;
+ syslog(LOG_INFO,
+ "[NCP->] Tracking *NEW* insecure commissioning connection.");
+ } else if (rule.type == IPv6PacketMatcherRule::TYPE_ICMP) {
+ mInsecureFirewall.insert(rule);
+ packet_should_be_dropped = false;
+ syslog(LOG_INFO,
+ "[NCP->] Tracking *NEW* ICMP ping during commissioning.");
+ } else {
+ syslog(LOG_INFO,
+ "[NCP->] Non-matching insecure traffic while joinable, ignoring");
+ }
+ } else {
+ // Commissioning has ended. Clean up.
+ syslog(LOG_NOTICE, "Commissioning period has ended");
+ mCommissioningExpiration = 0;
+ mInsecureFirewall.clear();
+ }
+ }
+ } else if (
+ ( (*type == FRAME_TYPE_DATA)
+ || (*type == FRAME_TYPE_LEGACY_DATA)
+ )
+ && (mInsecureFirewall.size()>0)
+ ) {
+ // In this case we want to make sure that if we receive
+ // a packet on a secure channel that we were previously
+ // routing over the insecure channel that we remove the
+ // matching entry so that we don't route those packets
+ // over the insecure channel any more.
+
+ if (mInsecureFirewall.count(rule)) {
+ syslog(LOG_NOTICE, "Secure packet matched rule on insecure firewall, removing rule.");
+ mInsecureFirewall.erase(rule);
+
+ if (*type == FRAME_TYPE_LEGACY_DATA) {
+ // The first packet to match the rule on the insecure firewall
+ // was from the legacy interface. To ensure the continuity
+ // of the connection, we need to ensure that the packets
+ // for this session continue to come out of the non-legacy
+ // interface. We do that by adding them to this packet matcher.
+ mLegacyCommissioningMatcher.insert(rule);
+ }
+ }
+ }
+
+ // If our legacy interface isn't enabled, drop all legacy traffic.
+ if (*type == FRAME_TYPE_LEGACY_DATA) {
+ packet_should_be_dropped |= !is_legacy_interface_enabled();
+ }
+
+ // Debug logging.
+ dump_inbound_ipv6_packet(
+ ip_packet,
+ packet_length,
+ FRAME_TYPE_TO_CSTR(*type),
+ packet_should_be_dropped
+ );
+
+ // Make sure the interface is up.
+ if (!ncp_state_is_interface_up(get_ncp_state())) {
+ // The interface is down, so we don't send the packet.
+ packet_should_be_dropped = true;
+
+ // Check to see if the NCP is supposed to be asleep:
+ if (ncp_state_is_sleeping(get_ncp_state())) {
+ syslog(LOG_ERR, "Got IPv6 traffic when we should be asleep! (%s)",ncp_state_to_string(get_ncp_state()).c_str());
+ ncp_is_misbehaving();
+ } else {
+ syslog(LOG_WARNING, "Ignoring IPv6 traffic while in %s state.", ncp_state_to_string(get_ncp_state()).c_str());
+ }
+ }
+
+ if ((*type == FRAME_TYPE_LEGACY_DATA) && mLegacyCommissioningMatcher.count(rule)) {
+ // This is for ensuring that the commissioning TCP connection survives
+ // the transition to joining the network. In order for this to occur,
+ // we need to ensure that the packets for this particular connection
+ // continue to flow to and from the normal IPv6 data interface.
+ *type = FRAME_TYPE_DATA;
+ }
+
+ if (!packet_should_be_dropped) {
+ // Inform the statistic collector about the inbound IP packet
+ get_stat_collector().record_inbound_packet(ip_packet);
+ } else {
+ syslog(LOG_DEBUG, "Dropping host-bound IPv6 packet.");
+ }
+
+ return !packet_should_be_dropped;
+}
+
+bool
+NCPInstanceBase::should_forward_ncpbound_frame(uint8_t* type, const uint8_t* ip_packet, size_t packet_length)
+{
+ bool should_forward = true;
+ IPv6PacketMatcherRule rule;
+
+ if (!ncp_state_is_interface_up(get_ncp_state())) {
+ syslog(LOG_DEBUG, "Dropping IPv6 packet, NCP not ready yet!");
+ should_forward = false;
+ goto bail;
+ }
+
+ // Skip non-IPv6 packets
+ if (!is_valid_ipv6_packet(ip_packet, packet_length)) {
+ syslog(LOG_DEBUG,
+ "Dropping non-IPv6 outbound packet (first byte was 0x%02X)",
+ ip_packet[0]);
+ should_forward = false;
+ goto bail;
+ }
+
+ rule.update_from_outbound_packet(ip_packet);
+
+ if (mDropFirewall.match_outbound(ip_packet) != mDropFirewall.end()) {
+ syslog(LOG_INFO, "[->NCP] Dropping matched packet.");
+ should_forward = false;
+ goto bail;
+ }
+
+ if (mLegacyCommissioningMatcher.count(rule)) {
+ if (*type == FRAME_TYPE_LEGACY_DATA) {
+ // This is for ensuring that the commissioning TCP connection survives
+ // the transition to joining the network. In order for this to occur,
+ // we need to ensure that the packets for this particular connection
+ // continue to flow to and from the normal IPv6 data interface.
+ *type = FRAME_TYPE_DATA;
+ } else {
+ mLegacyCommissioningMatcher.erase(rule);
+ }
+ }
+
+ rule.subtype = IPv6PacketMatcherRule::SUBTYPE_ALL;
+
+ if (mInsecureFirewall.count(rule)) {
+ // We use `count` instead of `match_outbound` in the
+ // check above because exact matches are faster.
+ syslog(LOG_INFO, "[->NCP] Routing insecure commissioning traffic.");
+ *type = FRAME_TYPE_INSECURE_DATA;
+ }
+
+ if (ncp_state_is_joining(get_ncp_state())) {
+ // When we are joining, all outbound traffic is insecure.
+ *type = FRAME_TYPE_INSECURE_DATA;
+
+ } else if ((mCommissioningExpiration != 0)
+ && (mCommissioningExpiration < time_get_monotonic())
+ ) {
+ syslog(LOG_NOTICE, "Commissioning period has ended");
+ mCommissioningExpiration = 0;
+ mInsecureFirewall.clear();
+ }
+
+ // Inform the statistics collector about the outbound IPv6 packet
+ if (should_forward) {
+ get_stat_collector().record_outbound_packet(ip_packet);
+ } else {
+ syslog(LOG_DEBUG, "Dropping NCP-bound IPv6 packet.");
+ }
+
+ // Debug logging
+ dump_outbound_ipv6_packet(
+ ip_packet,
+ packet_length,
+ FRAME_TYPE_TO_CSTR(*type)
+ );
+
+bail:
+
+ return should_forward;
+}
diff --git a/src/wpantund/NCPInstanceBase.cpp b/src/wpantund/NCPInstanceBase.cpp
new file mode 100644
index 0000000..0e20131
--- /dev/null
+++ b/src/wpantund/NCPInstanceBase.cpp
@@ -0,0 +1,940 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "assert-macros.h"
+#include "NCPInstanceBase.h"
+#include "tunnel.h"
+#include <syslog.h>
+#include <errno.h>
+#include "nlpt.h"
+#include <algorithm>
+#include "socket-utils.h"
+#include "SuperSocket.h"
+#include "wpantund.h"
+#include "any-to.h"
+
+using namespace nl;
+using namespace wpantund;
+
+
+
+// ----------------------------------------------------------------------------
+// MARK: -
+// MARK: Constructors/Destructors
+
+NCPInstanceBase::NCPInstanceBase(const Settings& settings):
+ mCommissioningRule(),
+ mCommissioningExpiration(0)
+{
+ std::string wpan_interface_name = "wpan0";
+
+ mResetFD = -1;
+ mResetFD_BeginReset = '0';
+ mResetFD_EndReset = '1';
+
+ mPowerFD = -1;
+ mPowerFD_PowerOff = '0';
+ mPowerFD_PowerOn = '1';
+
+ mMCFD = -1;
+
+ NLPT_INIT(&mNCPToDriverPumpPT);
+ NLPT_INIT(&mDriverToNCPPumpPT);
+
+ mCommissioningExpiration = 0;
+ mEnabled = true;
+ mTerminateOnFault = false;
+ mAutoUpdateFirmware = false;
+ mAutoResume = true;
+ mAutoDeepSleep = false;
+ mIsInitializingNCP = false;
+ mNCPState = UNINITIALIZED;
+ mNodeType = UNKNOWN;
+ mFailureCount = 0;
+ mFailureThreshold = 3;
+ mAutoDeepSleepTimeout = 10;
+ mCommissionerPort = 5684;
+
+ memset(mNCPMeshLocalAddress.s6_addr, 0, sizeof(mNCPMeshLocalAddress));
+ memset(mNCPLinkLocalAddress.s6_addr, 0, sizeof(mNCPLinkLocalAddress));
+ memset(mNCPV6LegacyPrefix, 0, sizeof(mNCPV6LegacyPrefix));
+ memset(mMACAddress, 0, sizeof(mMACAddress));
+ memset(mMACHardwareAddress, 0, sizeof(mMACHardwareAddress));
+
+ if (!settings.empty()) {
+ Settings::const_iterator iter;
+
+ for(iter = settings.begin(); iter != settings.end(); iter++) {
+ if (strcaseequal(iter->first.c_str(), kWPANTUNDProperty_ConfigNCPHardResetPath)) {
+ mResetFD = open_super_socket(iter->second.c_str());
+
+ } else if (strcaseequal(iter->first.c_str(), kWPANTUNDProperty_ConfigNCPPowerPath)) {
+ mPowerFD = open_super_socket(iter->second.c_str());
+
+ } else if (strcaseequal(iter->first.c_str(), kWPANTUNDProperty_ConfigNCPSocketPath)) {
+ mRawSerialAdapter = SuperSocket::create(iter->second);
+
+ } else if (strcaseequal(iter->first.c_str(), kWPANTUNDProperty_ConfigTUNInterfaceName)) {
+ wpan_interface_name = iter->second;
+
+ } else if (strcaseequal(iter->first.c_str(), kWPANTUNDProperty_ConfigNCPFirmwareCheckCommand)) {
+ mFirmwareUpgrade.set_firmware_check_command(iter->second);
+
+ } else if (strcaseequal(iter->first.c_str(), kWPANTUNDProperty_ConfigNCPFirmwareUpgradeCommand)) {
+ mFirmwareUpgrade.set_firmware_upgrade_command(iter->second);
+
+ } else if (strcaseequal(iter->first.c_str(), kWPANTUNDProperty_DaemonAutoFirmwareUpdate)) {
+ mAutoUpdateFirmware = any_to_bool(boost::any(iter->second));
+
+ } else if (strcaseequal(iter->first.c_str(), kWPANTUNDProperty_ConfigDaemonNetworkRetainCommand)) {
+ mNetworkRetain.set_network_retain_command(iter->second);
+ }
+ }
+ }
+
+ if (!mRawSerialAdapter) {
+ syslog(LOG_WARNING, kWPANTUNDProperty_ConfigNCPSocketPath" was not specified. Using \"/dev/null\" instead.");
+ mRawSerialAdapter = SuperSocket::create("/dev/null");
+ }
+
+ if (mRawSerialAdapter) {
+ mRawSerialAdapter->set_log_level(LOG_DEBUG);
+ }
+
+ mSerialAdapter = mRawSerialAdapter;
+
+ mPrimaryInterface = boost::shared_ptr<TunnelIPv6Interface>(new TunnelIPv6Interface(wpan_interface_name));
+ mPrimaryInterface->mAddressWasAdded.connect(boost::bind(&NCPInstanceBase::address_was_added, this, _1, _2));
+ mPrimaryInterface->mAddressWasRemoved.connect(boost::bind(&NCPInstanceBase::address_was_removed, this, _1, _2));
+
+ set_ncp_power(true);
+
+ // Go ahead and start listening on ff03::1
+ join_multicast_group("ff03::1");
+
+
+ {
+ IPv6PacketMatcherRule rule;
+
+ // --------------------------------------------------------------------
+ // Packet Drop rules
+
+ rule.clear();
+ // OS X seems to generate these packets when bringing up the interface.
+ // Honey badger don't care.
+ rule.type = IPv6PacketMatcherRule::TYPE_HOP_BY_HOP;
+ rule.remote_address.s6_addr[0x0] = 0xFF;
+ rule.remote_address.s6_addr[0x1] = 0x02;
+ rule.remote_address.s6_addr[0xF] = 0x16;
+ rule.remote_match_mask = 128;
+ mDropFirewall.insert(rule);
+
+ rule.clear();
+ // Don't forward router advertisement or router solicitation
+ // traffic.
+ rule.type = IPv6PacketMatcherRule::TYPE_ICMP;
+ rule.remote_address.s6_addr[0x0] = 0xFF;
+ rule.remote_address.s6_addr[0x1] = 0x02;
+ rule.remote_address.s6_addr[0xF] = 0x02;
+ rule.remote_match_mask = 128;
+ rule.subtype = IPv6PacketMatcherRule::SUBTYPE_ICMP_ROUTER_ADV;
+ mDropFirewall.insert(rule);
+ rule.subtype = IPv6PacketMatcherRule::SUBTYPE_ICMP_ROUTER_SOL;
+ mDropFirewall.insert(rule);
+
+ rule.clear();
+ // Don't forward neighbor advertisement or neighbor solicitation
+ // traffic.
+ rule.type = IPv6PacketMatcherRule::TYPE_ICMP;
+ rule.subtype = IPv6PacketMatcherRule::SUBTYPE_ICMP_NEIGHBOR_ADV;
+ mDropFirewall.insert(rule);
+ rule.subtype = IPv6PacketMatcherRule::SUBTYPE_ICMP_NEIGHBOR_SOL;
+ mDropFirewall.insert(rule);
+ }
+}
+
+bool
+NCPInstanceBase::setup_property_supported_by_class(const std::string& prop_name)
+{
+ return strcaseequal(prop_name.c_str(), kWPANTUNDProperty_ConfigNCPHardResetPath)
+ || strcaseequal(prop_name.c_str(), kWPANTUNDProperty_ConfigNCPPowerPath)
+ || strcaseequal(prop_name.c_str(), kWPANTUNDProperty_ConfigNCPSocketPath)
+ || strcaseequal(prop_name.c_str(), kWPANTUNDProperty_ConfigTUNInterfaceName)
+ || strcaseequal(prop_name.c_str(), kWPANTUNDProperty_ConfigNCPDriverName)
+ || strcaseequal(prop_name.c_str(), kWPANTUNDProperty_ConfigNCPFirmwareCheckCommand)
+ || strcaseequal(prop_name.c_str(), kWPANTUNDProperty_DaemonAutoFirmwareUpdate)
+ || strcaseequal(prop_name.c_str(), kWPANTUNDProperty_ConfigNCPFirmwareUpgradeCommand)
+ || strcaseequal(prop_name.c_str(), kWPANTUNDProperty_ConfigDaemonNetworkRetainCommand);
+}
+
+NCPInstanceBase::~NCPInstanceBase()
+{
+ close(mMCFD);
+ close(mPowerFD);
+ close(mResetFD);
+}
+
+
+
+const std::string &
+NCPInstanceBase::get_name()
+{
+ return mPrimaryInterface->get_interface_name();
+}
+
+const WPAN::NetworkInstance&
+NCPInstanceBase::get_current_network_instance(void)const
+{
+ return mCurrentNetworkInstance;
+}
+
+// Helpful for use with callbacks.
+int
+NCPInstanceBase::process_event_helper(int event)
+{
+ return EventHandler::process_event(event);
+}
+
+// ----------------------------------------------------------------------------
+// MARK: -
+
+wpantund_status_t
+NCPInstanceBase::set_ncp_version_string(const std::string& version_string)
+{
+ wpantund_status_t status = kWPANTUNDStatus_Ok;
+
+ if (version_string != mNCPVersionString) {
+ if (!mNCPVersionString.empty()) {
+ // The previous version string isn't empty!
+ syslog(LOG_ERR, "Illegal NCP version change! (Previously \"%s\")", mNCPVersionString.c_str());
+ ncp_is_misbehaving();
+ status = kWPANTUNDStatus_InvalidArgument;
+ } else {
+ mNCPVersionString = version_string;
+
+ syslog(LOG_NOTICE, "NCP is running \"%s\"", mNCPVersionString.c_str());
+ syslog(LOG_NOTICE, "Driver is running \"%s\"", nl::wpantund::get_wpantund_version_string().c_str());
+
+ if (mAutoUpdateFirmware && is_firmware_upgrade_required(version_string)) {
+ syslog(LOG_NOTICE, "NCP FIRMWARE UPGRADE IS REQUIRED");
+ upgrade_firmware();
+ }
+ }
+ }
+ return status;
+}
+
+std::set<std::string>
+NCPInstanceBase::get_supported_property_keys() const
+{
+ std::set<std::string> properties;
+
+ properties.insert(kWPANTUNDProperty_NetworkName);
+ properties.insert(kWPANTUNDProperty_NetworkPANID);
+ properties.insert(kWPANTUNDProperty_NetworkXPANID);
+ properties.insert(kWPANTUNDProperty_NetworkKey);
+ properties.insert(kWPANTUNDProperty_NetworkKeyIndex);
+ properties.insert(kWPANTUNDProperty_NetworkNodeType);
+
+ properties.insert(kWPANTUNDProperty_NCPState);
+
+ properties.insert(kWPANTUNDProperty_IPv6MeshLocalPrefix);
+ properties.insert(kWPANTUNDProperty_IPv6MeshLocalAddress);
+ properties.insert(kWPANTUNDProperty_IPv6LinkLocalAddress);
+ properties.insert(kWPANTUNDProperty_IPv6AllAddresses);
+
+ properties.insert(kWPANTUNDProperty_DaemonAutoAssociateAfterReset);
+ properties.insert(kWPANTUNDProperty_DaemonAutoDeepSleep);
+ properties.insert(kWPANTUNDProperty_DaemonEnabled);
+ properties.insert(kWPANTUNDProperty_DaemonReadyForHostSleep);
+ properties.insert(kWPANTUNDProperty_DaemonTerminateOnFault);
+
+ properties.insert(kWPANTUNDProperty_NestLabs_NetworkAllowingJoin);
+
+ properties.insert(kWPANTUNDProperty_DaemonVersion);
+ properties.insert(kWPANTUNDProperty_DaemonTerminateOnFault);
+
+ properties.insert(kWPANTUNDProperty_NCPChannel);
+ properties.insert(kWPANTUNDProperty_NCPVersion);
+ properties.insert(kWPANTUNDProperty_NCPHardwareAddress);
+ properties.insert(kWPANTUNDProperty_NCPCCAThreshold);
+ properties.insert(kWPANTUNDProperty_NCPTXPower);
+
+ properties.insert(kWPANTUNDProperty_NCPMACAddress);
+
+ properties.insert(kWPANTUNDProperty_NetworkIsCommissioned);
+
+ properties.insert(kWPANTUNDProperty_ConfigTUNInterfaceName);
+
+ if (mLegacyInterfaceEnabled || mNodeTypeSupportsLegacy || buffer_is_nonzero(mNCPV6LegacyPrefix, sizeof(mNCPV6LegacyPrefix))) {
+ properties.insert(kWPANTUNDProperty_NestLabs_LegacyMeshLocalAddress);
+ properties.insert(kWPANTUNDProperty_NestLabs_LegacyMeshLocalPrefix);
+ }
+
+ properties.insert(kWPANTUNDProperty_NestLabs_NetworkPassthruPort);
+
+ return properties;
+}
+
+void
+NCPInstanceBase::get_property(
+ const std::string& in_key,
+ CallbackWithStatusArg1 cb
+) {
+ std::string key = in_key;
+
+
+ if (key.empty()) {
+ /* This key is used to get the list of available properties */
+ cb(0, get_supported_property_keys());
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_ConfigTUNInterfaceName)) {
+ cb(0, get_name());
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_DaemonEnabled)) {
+ cb(0, boost::any(mEnabled));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_DaemonReadyForHostSleep)) {
+ cb(0, boost::any(!is_busy()));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_ConfigTUNInterfaceName)) {
+ cb(0, get_name());
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NCPVersion)) {
+ cb(0, boost::any(mNCPVersionString));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NetworkName)) {
+ cb(0, boost::any(get_current_network_instance().name));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NetworkIsCommissioned)) {
+ NCPState ncp_state = get_ncp_state();
+ if (ncp_state_is_commissioned(ncp_state)) {
+ cb(0, boost::any(true));
+ } else if (ncp_state == OFFLINE || ncp_state == DEEP_SLEEP) {
+ cb(0, boost::any(false));
+ } else {
+ cb(kWPANTUNDStatus_TryAgainLater, boost::any(std::string("Unable to determine association state at this time")));
+ }
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NestLabs_LegacyEnabled)) {
+ cb(0, boost::any(mLegacyInterfaceEnabled));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NestLabs_NetworkAllowingJoin)) {
+ cb(0, boost::any(get_current_network_instance().joinable));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NetworkPANID)) {
+ cb(0, boost::any(get_current_network_instance().panid));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NetworkXPANID)) {
+ cb(0, boost::any(get_current_network_instance().get_xpanid_as_uint64()));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NCPChannel)) {
+ cb(0, boost::any((int)get_current_network_instance().channel));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_DaemonVersion)) {
+ cb(0, boost::any(nl::wpantund::get_wpantund_version_string()));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_DaemonAutoAssociateAfterReset)) {
+ cb(0, boost::any(static_cast<bool>(mAutoResume)));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_DaemonAutoDeepSleep)) {
+ cb(0, boost::any(mAutoDeepSleep));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_DaemonAutoFirmwareUpdate)) {
+ cb(0, boost::any(mAutoUpdateFirmware));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_DaemonTerminateOnFault)) {
+ cb(0, boost::any(mTerminateOnFault));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NestLabs_NetworkPassthruPort)) {
+ cb(0, boost::any(mCommissionerPort));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NCPMACAddress)) {
+ cb(0, boost::any(nl::Data(mMACAddress, sizeof(mMACAddress))));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NCPHardwareAddress)) {
+ cb(0, boost::any(nl::Data(mMACHardwareAddress, sizeof(mMACHardwareAddress))));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_IPv6MeshLocalPrefix)) {
+ if (buffer_is_nonzero(mNCPV6Prefix, sizeof(mNCPV6Prefix))) {
+ struct in6_addr addr (mNCPMeshLocalAddress);
+ // Zero out the lower 64 bits.
+ memset(addr.s6_addr+8, 0, 8);
+ cb(0, boost::any(in6_addr_to_string(addr)+"/64"));
+ } else {
+ cb(kWPANTUNDStatus_FeatureNotSupported, std::string("Property is unavailable"));
+ }
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_IPv6MeshLocalAddress)) {
+ if (buffer_is_nonzero(mNCPMeshLocalAddress.s6_addr, sizeof(mNCPMeshLocalAddress))) {
+ cb(0, boost::any(in6_addr_to_string(mNCPMeshLocalAddress)));
+ } else {
+ cb(kWPANTUNDStatus_FeatureNotSupported, std::string("Property is unavailable"));
+ }
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_IPv6LinkLocalAddress)) {
+ if (buffer_is_nonzero(mNCPLinkLocalAddress.s6_addr, sizeof(mNCPLinkLocalAddress))) {
+ cb(0, boost::any(in6_addr_to_string(mNCPLinkLocalAddress)));
+ } else {
+ cb(kWPANTUNDStatus_FeatureNotSupported, std::string("Property is unavailable"));
+ }
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NestLabs_LegacyMeshLocalPrefix)) {
+ if (mLegacyInterfaceEnabled || mNodeTypeSupportsLegacy || buffer_is_nonzero(mNCPV6LegacyPrefix, sizeof(mNCPV6LegacyPrefix))) {
+ cb(0, boost::any(nl::Data(mNCPV6LegacyPrefix, sizeof(mNCPV6LegacyPrefix))));
+ } else {
+ cb(kWPANTUNDStatus_FeatureNotSupported, std::string("Property is unavailable"));
+ }
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NestLabs_LegacyMeshLocalAddress)) {
+ struct in6_addr legacy_addr;
+
+ if ( (mLegacyInterfaceEnabled || mNodeTypeSupportsLegacy)
+ && buffer_is_nonzero(mNCPV6LegacyPrefix, sizeof(mNCPV6LegacyPrefix))
+ ) {
+ legacy_addr = make_slaac_addr_from_eui64(mNCPV6LegacyPrefix, mMACAddress);
+ cb(0, boost::any(in6_addr_to_string(legacy_addr)));
+ } else {
+ cb(kWPANTUNDStatus_FeatureNotSupported, std::string("Property is unavailable"));
+ }
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NCPState)) {
+ if ( is_initializing_ncp()
+ && !ncp_state_is_detached_from_ncp(get_ncp_state())
+ ) {
+ cb(0, boost::any(std::string(kWPANTUNDStateUninitialized)));
+ } else {
+ cb(0, boost::any(ncp_state_to_string(get_ncp_state())));
+ }
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NetworkNodeType)) {
+ cb(0, boost::any(node_type_to_string(mNodeType)));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_IPv6AllAddresses) || strcaseequal(key.c_str(), kWPANTUNDProperty_DebugIPv6GlobalIPAddressList)) {
+ std::list<std::string> result;
+ std::map<struct in6_addr, GlobalAddressEntry>::const_iterator it;
+ char address_string[INET6_ADDRSTRLEN];
+ for ( it = mGlobalAddresses.begin();
+ it != mGlobalAddresses.end();
+ it++ ) {
+ inet_ntop(AF_INET6, &it->first, address_string, sizeof(address_string));
+ result.push_back(std::string(address_string)+ " " + it->second.get_description());
+ }
+ cb(0, boost::any(result));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_DaemonSyslogMask)) {
+ std::string mask_string;
+ int logmask;
+
+ setlogmask(logmask = setlogmask(0));
+
+ if (LOG_FAC(logmask) == LOG_DAEMON) {
+ mask_string += "daemon ";
+ }
+ if (LOG_FAC(logmask) == LOG_USER) {
+ mask_string += "user ";
+ }
+ if (logmask & LOG_MASK(LOG_EMERG)) {
+ mask_string += "emerg ";
+ }
+ if (logmask & LOG_MASK(LOG_ALERT)) {
+ mask_string += "alert ";
+ }
+ if (logmask & LOG_MASK(LOG_CRIT)) {
+ mask_string += "crit ";
+ }
+ if (logmask & LOG_MASK(LOG_ERR)) {
+ mask_string += "err ";
+ }
+ if (logmask & LOG_MASK(LOG_WARNING)) {
+ mask_string += "warning ";
+ }
+ if (logmask & LOG_MASK(LOG_NOTICE)) {
+ mask_string += "notice ";
+ }
+ if (logmask & LOG_MASK(LOG_INFO)) {
+ mask_string += "info ";
+ }
+ if (logmask & LOG_MASK(LOG_DEBUG)) {
+ mask_string += "debug ";
+ }
+
+ cb(0, mask_string);
+
+ } else if (StatCollector::is_a_stat_property(key)) {
+ get_stat_collector().get_property(key, cb);
+
+ } else {
+ cb(kWPANTUNDStatus_PropertyNotFound, boost::any(std::string("Property Not Found")));
+ }
+}
+
+void
+NCPInstanceBase::set_property(
+ const std::string& key,
+ const boost::any& value,
+ CallbackWithStatus cb
+) {
+ // If we are disabled, then the only property we
+ // are allowed to set is kWPANTUNDProperty_DaemonEnabled.
+ if (!mEnabled && !strcaseequal(key.c_str(), kWPANTUNDProperty_DaemonEnabled)) {
+ cb(kWPANTUNDStatus_InvalidWhenDisabled);
+ return;
+ }
+
+ try {
+ if (strcaseequal(key.c_str(), kWPANTUNDProperty_DaemonEnabled)) {
+ mEnabled = any_to_bool(value);
+ cb(0);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_DaemonAutoAssociateAfterReset)) {
+ mAutoResume = any_to_bool(value);
+ cb(0);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_NestLabs_NetworkPassthruPort)) {
+ mCommissionerPort = static_cast<uint16_t>(any_to_int(value));
+ cb(0);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_DaemonAutoFirmwareUpdate)) {
+ bool value_bool = any_to_bool(value);
+
+ if (value_bool && !mAutoUpdateFirmware) {
+ if (get_ncp_state() == FAULT) {
+ syslog(LOG_ALERT, "The NCP is misbehaving: Attempting a firmware update");
+ upgrade_firmware();
+ } else if (get_ncp_state() != UNINITIALIZED) {
+ if (is_firmware_upgrade_required(mNCPVersionString)) {
+ syslog(LOG_NOTICE, "NCP FIRMWARE UPGRADE IS REQUIRED");
+ upgrade_firmware();
+ }
+ }
+ }
+
+ mAutoUpdateFirmware = value_bool;
+
+ cb(0);
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_DaemonTerminateOnFault)) {
+ mTerminateOnFault = any_to_bool(value);
+ cb(0);
+ if (mTerminateOnFault && (get_ncp_state() == FAULT)) {
+ reinitialize_ncp();
+ }
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_IPv6MeshLocalPrefix) || strcaseequal(key.c_str(), kWPANTUNDProperty_IPv6MeshLocalAddress)) {
+ if (get_ncp_state() <= OFFLINE) {
+ nl::Data prefix;
+
+ if (value.type() == typeid(std::string)) {
+ uint8_t ula_bytes[16] = {};
+ const std::string ip_string(any_to_string(value));
+
+ // Address-style
+ int bits = inet_pton(AF_INET6,ip_string.c_str(),ula_bytes);
+ if (bits <= 0) {
+ // Prefix is the wrong length.
+ cb(kWPANTUNDStatus_InvalidArgument);
+ return;
+ }
+
+ prefix = nl::Data(ula_bytes, 8);
+ } else {
+ prefix = any_to_data(value);
+ }
+
+ if (prefix.size() < sizeof(mNCPV6Prefix)) {
+ // Prefix is the wrong length.
+ cb(kWPANTUNDStatus_InvalidArgument);
+ }
+ memcpy(mNCPV6Prefix, prefix.data(), sizeof(mNCPV6Prefix));
+ cb(0);
+ } else {
+ cb(kWPANTUNDStatus_InvalidForCurrentState);
+ }
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_DaemonAutoDeepSleep)) {
+ mAutoDeepSleep = any_to_bool(value);
+
+ if (mAutoDeepSleep == false
+ && mNCPState == DEEP_SLEEP
+ && mEnabled
+ ) {
+ // Wake us up if we are asleep and deep sleep was turned off.
+ get_control_interface().refresh_state(boost::bind(cb,0));
+ } else {
+ cb(0);
+ }
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_DaemonSyslogMask)) {
+ setlogmask(strtologmask(any_to_string(value).c_str(), setlogmask(0)));
+ cb(0);
+
+ } else if (StatCollector::is_a_stat_property(key)) {
+ get_stat_collector().set_property(key, value, cb);
+
+ } else {
+ syslog(LOG_ERR,"set_property: Unsupported property \"%s\"", key.c_str());
+ cb(kWPANTUNDStatus_PropertyNotFound);
+ }
+
+ } catch (const boost::bad_any_cast &x) {
+ // We will get a bad_any_cast exception if the property is of
+ // the wrong type.
+ syslog(LOG_ERR,"set_property: Bad type for property \"%s\" (%s)", key.c_str(), x.what());
+ cb(kWPANTUNDStatus_InvalidArgument);
+
+ } catch (const std::invalid_argument &x) {
+ // We will get a bad_any_cast exception if the property is of
+ // the wrong type.
+ syslog(LOG_ERR,"set_property: Invalid argument for property \"%s\" (%s)", key.c_str(), x.what());
+ cb(kWPANTUNDStatus_InvalidArgument);
+ }
+}
+
+void
+NCPInstanceBase::signal_property_changed(
+ const std::string& key,
+ const boost::any& value
+) {
+ get_control_interface().mOnPropertyChanged(key, value);
+}
+
+// ----------------------------------------------------------------------------
+// MARK: -
+
+void
+NCPInstanceBase::set_initializing_ncp(bool x)
+{
+ if (mIsInitializingNCP != x) {
+ mIsInitializingNCP = x;
+
+ if (mIsInitializingNCP) {
+ change_ncp_state(UNINITIALIZED);
+ set_ncp_power(true);
+ } else if ( (get_ncp_state() != UNINITIALIZED)
+ && (get_ncp_state() != FAULT)
+ && (get_ncp_state() != UPGRADING)
+ ) {
+ handle_ncp_state_change(get_ncp_state(), UNINITIALIZED);
+ }
+ }
+}
+
+bool
+NCPInstanceBase::is_initializing_ncp() const
+{
+ return mIsInitializingNCP;
+}
+
+NCPState
+NCPInstanceBase::get_ncp_state()const
+{
+ return mNCPState;
+}
+
+bool
+NCPInstanceBase::is_state_change_valid(NCPState new_ncp_state)const
+{
+ // Add any invalid state transitions here so that
+ // bugs can be more quickly identified and corrected.
+
+ if (ncp_state_is_detached_from_ncp(get_ncp_state())) {
+ return new_ncp_state == UNINITIALIZED;
+ }
+
+ return true;
+}
+
+void
+NCPInstanceBase::change_ncp_state(NCPState new_ncp_state)
+{
+ NCPState old_ncp_state = mNCPState;
+
+ if (old_ncp_state != new_ncp_state) {
+ if (!is_state_change_valid(new_ncp_state)) {
+ syslog(
+ LOG_WARNING,
+ "BUG: Invalid state change: \"%s\" -> \"%s\"",
+ ncp_state_to_string(old_ncp_state).c_str(),
+ ncp_state_to_string(new_ncp_state).c_str()
+ );
+
+ if (ncp_state_is_detached_from_ncp(get_ncp_state())) {
+ // If the state was detached, do not allow the
+ // state change to continue.
+ return;
+ }
+ } else {
+ syslog(
+ LOG_NOTICE,
+ "State change: \"%s\" -> \"%s\"",
+ ncp_state_to_string(old_ncp_state).c_str(),
+ ncp_state_to_string(new_ncp_state).c_str()
+ );
+ }
+
+ mNCPState = new_ncp_state;
+
+ if ( !mIsInitializingNCP
+ || (new_ncp_state == UNINITIALIZED)
+ || (new_ncp_state == FAULT)
+ || (new_ncp_state == UPGRADING)
+ ) {
+ handle_ncp_state_change(new_ncp_state, old_ncp_state);
+ }
+ }
+}
+
+void
+NCPInstanceBase::handle_ncp_state_change(NCPState new_ncp_state, NCPState old_ncp_state)
+{
+ // Detached NCP -> Online NCP
+ if (ncp_state_is_detached_from_ncp(old_ncp_state)
+ && !ncp_state_is_detached_from_ncp(new_ncp_state)
+ ) {
+ __ASSERT_MACROS_check(new_ncp_state == UNINITIALIZED);
+
+ // We are transitioning out of a state where we are disconnected
+ // from the NCP. This requires a hard reset.
+ set_ncp_power(true);
+
+ if (mResetFD >= 0) {
+ // If we have a way to hard reset the NCP,
+ // then do it. We do the check above to make
+ // sure that we don't end up calling mSerialAdapter->reset()
+ // twice.
+ hard_reset_ncp();
+ }
+
+ mSerialAdapter->reset();
+
+ PT_INIT(&mControlPT);
+ }
+
+ // Online NCP -> Detached NCP
+ else if (!ncp_state_is_detached_from_ncp(old_ncp_state)
+ && ncp_state_is_detached_from_ncp(new_ncp_state)
+ ) {
+ // We are transitioning into a state where we need to be disconnected
+ // from the NCP. For this we use the hibernate command.
+ mSerialAdapter->hibernate();
+ PT_INIT(&mControlPT);
+ NLPT_INIT(&mDriverToNCPPumpPT);
+ NLPT_INIT(&mNCPToDriverPumpPT);
+ mFailureCount = 0;
+
+ if (new_ncp_state == FAULT) {
+ // When we enter the fault state, attempt to
+ // ensure that we are using as little power as
+ // possible by physically turning off the NCP
+ // (if a method of doing so has been specified
+ // in our configuration)
+ set_ncp_power(false);
+
+ if (mTerminateOnFault) {
+ signal_fatal_error(kWPANTUNDStatus_Failure);
+ }
+ }
+ return;
+ }
+
+ // Interface Down -> Interface Up
+ if (!ncp_state_is_interface_up(old_ncp_state)
+ && ncp_state_is_interface_up(new_ncp_state)
+ ) {
+ set_online(true);
+
+
+ // InterfaceUp -> COMMISSIONED
+ // (Special case of InterfaceUp -> InterfaceDown)
+ } else if (ncp_state_is_interface_up(old_ncp_state)
+ && (new_ncp_state == COMMISSIONED)
+ && mAutoResume
+ ) {
+ // We don't bother going further if autoresume is on.
+ return;
+
+
+ // Commissioned -> InterfaceDown
+ // (Special case of InterfaceUp -> InterfaceDown)
+ } else if (ncp_state_is_commissioned(old_ncp_state)
+ && !ncp_state_is_commissioned(new_ncp_state)
+ && !ncp_state_is_sleeping(new_ncp_state)
+ && (new_ncp_state != UNINITIALIZED)
+ ) {
+ reset_interface();
+
+
+ // Uninitialized -> Offline
+ // If we are transitioning from uninitialized to offline,
+ // and we have global addresses, then need to clear them out.
+ } else if (old_ncp_state == UNINITIALIZED
+ && new_ncp_state == OFFLINE
+ && !mGlobalAddresses.empty()
+ ) {
+ reset_interface();
+
+
+ // InterfaceUp -> InterfaceDown (General Case)
+ } else if (ncp_state_is_interface_up(old_ncp_state)
+ && !ncp_state_is_interface_up(new_ncp_state)
+ && new_ncp_state != NET_WAKE_WAKING
+ ) {
+ // Take the interface offline.
+ syslog(LOG_NOTICE, "Taking interface(s) down. . .");
+
+ mCurrentNetworkInstance.joinable = false;
+ set_commissioniner(0, 0, 0);
+ set_online(false);
+ }
+
+ // We don't announce transitions to the "UNITIALIZED" state.
+ if (UNINITIALIZED != new_ncp_state) {
+ signal_property_changed(kWPANTUNDProperty_NCPState, ncp_state_to_string(new_ncp_state));
+ }
+
+ mNetworkRetain.handle_ncp_state_change(new_ncp_state, old_ncp_state);
+}
+
+void
+NCPInstanceBase::reinitialize_ncp(void)
+{
+ PT_INIT(&mControlPT);
+ change_ncp_state(UNINITIALIZED);
+}
+
+void
+NCPInstanceBase::reset_tasks(wpantund_status_t status)
+{
+}
+
+
+// ----------------------------------------------------------------------------
+// MARK: -
+
+
+bool
+NCPInstanceBase::is_busy(void)
+{
+ const NCPState ncp_state = get_ncp_state();
+ bool is_busy = ncp_state_is_busy(ncp_state);
+
+ if (is_initializing_ncp()) {
+ return true;
+ }
+
+ if (ncp_state == FAULT) {
+ return false;
+ }
+
+ if (get_upgrade_status() == EINPROGRESS) {
+ is_busy = true;
+ }
+
+ return is_busy;
+}
+
+StatCollector&
+NCPInstanceBase::get_stat_collector(void)
+{
+ return mStatCollector;
+}
+
+void
+NCPInstanceBase::update_busy_indication(void)
+{
+ cms_t current_time = time_ms();
+
+ if (mWasBusy != is_busy()) {
+ if (!mWasBusy
+ || (mLastChangedBusy == 0)
+ || (current_time - mLastChangedBusy >= BUSY_DEBOUNCE_TIME_IN_MS)
+ || (current_time - mLastChangedBusy < 0)
+ ) {
+ mWasBusy = !mWasBusy;
+ if(!mWasBusy) {
+ if (mLastChangedBusy == 0) {
+ syslog(LOG_INFO, "NCP is no longer busy, host sleep is permitted.");
+ } else {
+ syslog(LOG_INFO, "NCP is no longer busy, host sleep is permitted. (Was busy for %dms)",(int)(current_time - mLastChangedBusy));
+ }
+ signal_property_changed(kWPANTUNDProperty_DaemonReadyForHostSleep, true);
+ } else {
+ syslog(LOG_INFO, "NCP is now BUSY.");
+ signal_property_changed(kWPANTUNDProperty_DaemonReadyForHostSleep, false);
+ }
+ mLastChangedBusy = current_time;
+ }
+ } else if (mWasBusy
+ && (mLastChangedBusy != 0)
+ && (current_time - mLastChangedBusy > MAX_INSOMNIA_TIME_IN_MS)
+ ) {
+ syslog(LOG_ERR, "Experiencing extended insomnia. Resetting internal state.");
+
+ mLastChangedBusy = current_time;
+
+ ncp_is_misbehaving();
+ }
+}
+
+void
+NCPInstanceBase::ncp_is_misbehaving()
+{
+ mFailureCount++;
+ hard_reset_ncp();
+ reset_tasks();
+ reinitialize_ncp();
+
+ if (mFailureCount >= mFailureThreshold) {
+ change_ncp_state(FAULT);
+ }
+}
+
+// ----------------------------------------------------------------------------
+// MARK: -
+
+bool
+NCPInstanceBase::is_firmware_upgrade_required(const std::string& version)
+{
+ return mFirmwareUpgrade.is_firmware_upgrade_required(version);
+}
+
+void
+NCPInstanceBase::upgrade_firmware(void)
+{
+ change_ncp_state(UPGRADING);
+
+ set_ncp_power(true);
+
+ return mFirmwareUpgrade.upgrade_firmware();
+}
+
+int
+NCPInstanceBase::get_upgrade_status(void)
+{
+ return mFirmwareUpgrade.get_upgrade_status();
+}
+
+bool
+NCPInstanceBase::can_upgrade_firmware(void)
+{
+ return mFirmwareUpgrade.can_upgrade_firmware();
+}
diff --git a/src/wpantund/NCPInstanceBase.h b/src/wpantund/NCPInstanceBase.h
new file mode 100644
index 0000000..b614c1c
--- /dev/null
+++ b/src/wpantund/NCPInstanceBase.h
@@ -0,0 +1,353 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __wpantund__NCPInstanceBase__
+#define __wpantund__NCPInstanceBase__
+
+#include "NCPInstance.h"
+#include <set>
+#include <map>
+#include <string>
+#include "FirmwareUpgrade.h"
+#include "EventHandler.h"
+#include "NCPTypes.h"
+#include "StatCollector.h"
+#include "NetworkRetain.h"
+#include "RunawayResetBackoffManager.h"
+#include "Pcap.h"
+
+namespace nl {
+namespace wpantund {
+
+class NCPInstanceBase : public NCPInstance, public EventHandler{
+public:
+
+ enum {
+ FRAME_TYPE_DATA = 2,
+ FRAME_TYPE_INSECURE_DATA = 3,
+ FRAME_TYPE_LEGACY_DATA = 4
+ };
+
+protected:
+ NCPInstanceBase(const Settings& settings = Settings());
+
+public:
+ virtual ~NCPInstanceBase();
+
+ virtual const std::string &get_name();
+
+ virtual void set_socket_adapter(const boost::shared_ptr<SocketAdapter> &adapter);
+
+public:
+ // ========================================================================
+ // Static Functions
+
+ static bool setup_property_supported_by_class(const std::string& prop_name);
+
+
+public:
+ // ========================================================================
+ // MARK: ASync I/O
+
+ virtual cms_t get_ms_to_next_event(void);
+
+ virtual int update_fd_set(
+ fd_set *read_fd_set,
+ fd_set *write_fd_set,
+ fd_set *error_fd_set,
+ int *max_fd,
+ cms_t *timeout
+ );
+
+ virtual void process(void);
+
+ // Helpful for use with callbacks.
+ int process_event_helper(int event);
+
+ virtual StatCollector& get_stat_collector(void);
+
+protected:
+ virtual char ncp_to_driver_pump() = 0;
+ virtual char driver_to_ncp_pump() = 0;
+
+public:
+ // ========================================================================
+ // MARK: NCP Behavior
+
+ virtual void hard_reset_ncp(void);
+
+ virtual int set_ncp_power(bool power);
+
+ virtual bool can_set_ncp_power(void);
+
+public:
+ // ========================================================================
+ // MARK: Other
+
+ virtual void reinitialize_ncp(void);
+
+ virtual void reset_tasks(wpantund_status_t status = kWPANTUNDStatus_Canceled);
+
+ NCPState get_ncp_state()const;
+
+ bool is_state_change_valid(NCPState new_ncp_state)const;
+
+ //! Handles transitioning from state-to-state.
+ /*! This is the ONLY WAY to change mNCPState. */
+ void change_ncp_state(NCPState new_ncp_state);
+
+ virtual void handle_ncp_state_change(NCPState new_ncp_state, NCPState old_ncp_state);
+
+ virtual void ncp_is_misbehaving();
+
+ virtual void set_initializing_ncp(bool x);
+
+ virtual bool is_initializing_ncp()const;
+
+public:
+ // ========================================================================
+ // MARK: Network Interface Methods
+
+ int set_online(bool x);
+
+ void set_mac_address(const uint8_t addr[8]);
+
+ void set_mac_hardware_address(const uint8_t addr[8]);
+
+ void reset_interface(void);
+
+ const WPAN::NetworkInstance& get_current_network_instance(void)const;
+
+public:
+ // ========================================================================
+ // MARK: Global Address Management
+
+
+ void add_address(const struct in6_addr &address, uint8_t prefix = 64, uint32_t valid_lifetime = UINT32_MAX, uint32_t preferred_lifetime = UINT32_MAX);
+ void remove_address(const struct in6_addr &address);
+
+ void refresh_global_addresses();
+
+ //! Removes all nonpermanent global address entries
+ void clear_nonpermanent_global_addresses();
+
+ void restore_global_addresses();
+
+ bool is_address_known(const struct in6_addr &address);
+
+ bool lookup_address_for_prefix(struct in6_addr *address, const struct in6_addr &prefix, int prefix_len_in_bits = 64);
+
+ int join_multicast_group(const std::string &group_name);
+
+public:
+ // ========================================================================
+ // MARK: Subclass Hooks
+
+ virtual void address_was_added(const struct in6_addr& addr, int prefix_len);
+
+ virtual void address_was_removed(const struct in6_addr& addr, int prefix_len);
+
+public:
+ // ========================================================================
+ // MARK: Firmware Upgrade
+
+ virtual bool is_firmware_upgrade_required(const std::string& version);
+
+ virtual void upgrade_firmware(void);
+
+ virtual int get_upgrade_status(void);
+
+ virtual bool can_upgrade_firmware(void);
+
+public:
+ // ========================================================================
+ // MARK: Busy/OkToSleep
+
+ virtual bool is_busy(void);
+
+ virtual void update_busy_indication(void);
+
+public:
+ // ========================================================================
+ // MARK: IPv6 data path helpers
+
+ bool should_forward_hostbound_frame(uint8_t* type, const uint8_t* packet, size_t packet_length);
+
+ bool should_forward_ncpbound_frame(uint8_t* type, const uint8_t* packet, size_t packet_length);
+
+ void handle_normal_ipv6_from_ncp(const uint8_t* packet, size_t packet_length);
+
+ int set_commissioniner(int seconds, uint8_t traffic_type, in_port_t traffic_port);
+
+public:
+ // ========================================================================
+ // MARK: Legacy Interface Methods
+
+ void enable_legacy_interface(void);
+
+ bool is_legacy_interface_enabled(void);
+
+ void handle_alt_ipv6_from_ncp(const uint8_t* packet, size_t packet_length);
+
+public:
+
+ virtual std::set<std::string> get_supported_property_keys()const;
+
+ virtual void get_property(
+ const std::string& key,
+ CallbackWithStatusArg1 cb
+ );
+
+ virtual void set_property(
+ const std::string& key,
+ const boost::any& value,
+ CallbackWithStatus cb
+ );
+
+ virtual void signal_property_changed(
+ const std::string& key,
+ const boost::any& value = boost::any()
+ );
+
+ wpantund_status_t set_ncp_version_string(const std::string& version_string);
+
+protected:
+ // ========================================================================
+ // MARK: Protected Data
+
+ boost::shared_ptr<TunnelIPv6Interface> mPrimaryInterface;
+
+ boost::shared_ptr<SocketWrapper> mRawSerialAdapter;
+ boost::shared_ptr<SocketWrapper> mSerialAdapter;
+
+ struct nlpt mNCPToDriverPumpPT;
+ struct nlpt mDriverToNCPPumpPT;
+
+ std::map<struct in6_addr, GlobalAddressEntry> mGlobalAddresses;
+
+ IPv6PacketMatcherRule mCommissioningRule;
+ IPv6PacketMatcher mInsecureFirewall;
+ IPv6PacketMatcher mDropFirewall;
+
+ time_t mCommissioningExpiration;
+
+ std::string mNCPVersionString;
+
+ bool mEnabled;
+ bool mTerminateOnFault;
+ bool mAutoUpdateFirmware;
+ bool mAutoResume;
+ bool mAutoDeepSleep;
+ int mAutoDeepSleepTimeout; // In seconds
+ uint16_t mCommissionerPort;
+
+private:
+ NCPState mNCPState;
+ bool mIsInitializingNCP;
+
+protected:
+ //! This is set to the currently used MAC address (EUI64).
+ uint8_t mMACAddress[8];
+
+ //! This is set to the manufacturer-assigned permanent EUI64 address.
+ uint8_t mMACHardwareAddress[8];
+ union {
+ uint8_t mNCPV6Prefix[8];
+ struct in6_addr mNCPMeshLocalAddress;
+ };
+ struct in6_addr mNCPLinkLocalAddress;
+
+ WPAN::NetworkInstance mCurrentNetworkInstance;
+
+ std::set<unsigned int> mSupprotedChannels;
+
+ NodeType mNodeType;
+
+ int mFailureCount;
+ int mFailureThreshold;
+
+ RunawayResetBackoffManager mRunawayResetBackoffManager;
+
+protected:
+ // ========================================================================
+ // MARK: Legacy Interface Support
+
+ boost::shared_ptr<TunnelIPv6Interface> mLegacyInterface;
+ IPv6PacketMatcher mLegacyCommissioningMatcher;
+ uint8_t mNCPV6LegacyPrefix[8];
+ bool mLegacyInterfaceEnabled;
+ bool mNodeTypeSupportsLegacy;
+
+ PcapManager mPcapManager;
+
+private:
+ // ========================================================================
+ // MARK: Private Data
+
+ int mResetFD; //!^ File descriptor for resetting NCP.
+ char mResetFD_BeginReset; //!^ Value for entering reset
+ char mResetFD_EndReset; //!^ Value for leaving reset
+
+ int mPowerFD; //!^ File descriptor for controlling NCP power.
+ char mPowerFD_PowerOn; //!^ Value for the power being on.
+ char mPowerFD_PowerOff; //!^ Value for the power being off.
+
+ int mMCFD; //!^ File descriptor for multicast stuff.
+
+ bool mWasBusy;
+ cms_t mLastChangedBusy;
+
+ FirmwareUpgrade mFirmwareUpgrade;
+
+ NetworkRetain mNetworkRetain;
+
+ StatCollector mStatCollector; // Statistic collector
+}; // class NCPInstance
+
+}; // namespace wpantund
+
+}; // namespace nl
+
+// This callback is not sent from the NCP. It is a fake NCP
+// callback sent from the processing thread to indicate that
+// the NCP is in deep sleep.
+#define EVENT_NCP_DISABLED 0x78C9
+
+#define EVENT_NCP_CONN_RESET 0x78CB
+
+// Extracts a pointer and length from argument list and
+// returns a `nl::Data` object.
+static inline nl::Data
+va_arg_as_Data(va_list args)
+{
+ const uint8_t* data = NULL;
+ size_t data_len = 0;
+
+ data = va_arg(args, const uint8_t*);
+ data_len = va_arg(args, size_t);
+
+ // Sanity check
+ assert(data_len < 1024*1024);
+
+ return nl::Data(data, data_len);
+}
+
+#define va_arg_small(args, type) static_cast<type>(va_arg(args, int))
+
+#endif /* defined(__wpantund__NCPInstanceBase__) */
diff --git a/src/wpantund/NCPMfgInterface_v0.h b/src/wpantund/NCPMfgInterface_v0.h
new file mode 100644
index 0000000..6ba384c
--- /dev/null
+++ b/src/wpantund/NCPMfgInterface_v0.h
@@ -0,0 +1,50 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef wpantund_NCPMfgInterface_v0_h
+#define wpantund_NCPMfgInterface_v0_h
+
+#include "NCPControlInterface.h"
+
+namespace nl {
+namespace wpantund {
+
+class NCPMfgInterface_v0 {
+public:
+ virtual void mfg_start(CallbackWithStatus cb) { }
+
+
+ virtual void mfg_finish(CallbackWithStatusArg1 cb) = 0;
+ virtual void mfg_begin_test(uint8_t type, CallbackWithStatus cb) = 0;
+ virtual void mfg_end_test(uint8_t type, CallbackWithStatus cb) = 0;
+ virtual void mfg_tx_packet(const Data& packet, int16_t repeat, CallbackWithStatus cb) = 0;
+
+ virtual void mfg_clockmon(bool enable, uint32_t timerId, CallbackWithStatus cb) = 0;
+ virtual void mfg_gpio_set(uint8_t port_pin, uint8_t config, uint8_t value, CallbackWithStatus cb) = 0;
+ virtual void mfg_gpio_get(uint8_t port_pin, CallbackWithStatusArg1 cb) = 0;
+ virtual void mfg_channelcal(uint8_t channel, uint32_t duration, CallbackWithStatus cb) = 0;
+ virtual void mfg_channelcal_get(uint8_t channel, CallbackWithStatusArg1 cb) = 0;
+
+ boost::signals2::signal<void(Data, uint8_t, int8_t)> mOnMfgRXPacket;
+};
+
+}; // namespace wpantund
+}; // namespace nl
+
+#endif
diff --git a/src/wpantund/NCPMfgInterface_v1.h b/src/wpantund/NCPMfgInterface_v1.h
new file mode 100644
index 0000000..fd7fd71
--- /dev/null
+++ b/src/wpantund/NCPMfgInterface_v1.h
@@ -0,0 +1,37 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef wpantund_NCPMfgInterface_v1_h
+#define wpantund_NCPMfgInterface_v1_h
+
+#include "NCPControlInterface.h"
+
+namespace nl {
+namespace wpantund {
+
+class NCPMfgInterface_v1 {
+public:
+ virtual void mfg(const std::string& mfg_command, CallbackWithStatusArg1 cb = NilReturn()) = 0;
+
+};
+
+}; // namespace wpantund
+}; // namespace nl
+
+#endif
diff --git a/src/wpantund/NCPTypes.cpp b/src/wpantund/NCPTypes.cpp
new file mode 100644
index 0000000..0d038fb
--- /dev/null
+++ b/src/wpantund/NCPTypes.cpp
@@ -0,0 +1,393 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "NCPTypes.h"
+#include "string-utils.h"
+#include <string>
+#include "wpan-properties.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+using namespace nl;
+using namespace wpantund;
+
+
+// ----------------------------------------------------------------------------
+// MARK: -
+// MARK: Static Methods
+
+bool
+nl::wpantund::ncp_state_is_sleeping(NCPState x)
+{
+ switch(x) {
+ case DEEP_SLEEP:
+ case NET_WAKE_ASLEEP:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool
+nl::wpantund::ncp_state_has_joined(NCPState x)
+{
+ switch(x) {
+ case ASSOCIATED:
+ case ISOLATED:
+ case NET_WAKE_ASLEEP:
+ case NET_WAKE_WAKING:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool
+nl::wpantund::ncp_state_is_joining(NCPState x)
+{
+ switch(x) {
+ case ASSOCIATING:
+ case CREDENTIALS_NEEDED:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool
+nl::wpantund::ncp_state_is_interface_up(NCPState x)
+{
+ switch(x) {
+ case CREDENTIALS_NEEDED:
+ case ASSOCIATED:
+ case NET_WAKE_ASLEEP:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool
+nl::wpantund::ncp_state_is_commissioned(NCPState x)
+{
+ switch(x) {
+ case COMMISSIONED:
+ case ASSOCIATED:
+ case NET_WAKE_ASLEEP:
+ case ISOLATED:
+ case NET_WAKE_WAKING:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool
+nl::wpantund::ncp_state_is_initializing(NCPState x)
+{
+ switch(x) {
+ case UNINITIALIZED:
+ case UPGRADING:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool
+nl::wpantund::ncp_state_is_joining_or_joined(NCPState x)
+{
+ switch(x) {
+ case CREDENTIALS_NEEDED:
+ case ASSOCIATING:
+ case ASSOCIATED:
+ case ISOLATED:
+ case NET_WAKE_WAKING:
+ case NET_WAKE_ASLEEP:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool
+nl::wpantund::ncp_state_is_associated(NCPState x)
+{
+ switch(x) {
+ case ASSOCIATED:
+ case ISOLATED:
+ case NET_WAKE_WAKING:
+ case NET_WAKE_ASLEEP:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool
+nl::wpantund::ncp_state_is_detached_from_ncp(NCPState x)
+{
+ switch(x) {
+ case FAULT:
+ case UPGRADING:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool
+nl::wpantund::ncp_state_is_busy(NCPState x)
+{
+ switch(x) {
+ case DEEP_SLEEP:
+ case OFFLINE:
+ case NET_WAKE_ASLEEP:
+ case ISOLATED:
+ case ASSOCIATED:
+ case FAULT:
+ return false;
+ default:
+ return true;
+ }
+}
+
+std::string
+nl::wpantund::ncp_state_to_string(NCPState state)
+{
+ switch (state) {
+ case UNINITIALIZED: return kWPANTUNDStateUninitialized;
+ case FAULT: return kWPANTUNDStateFault;
+ case UPGRADING: return kWPANTUNDStateUpgrading;
+ case DEEP_SLEEP: return kWPANTUNDStateDeepSleep;
+ case OFFLINE: return kWPANTUNDStateOffline;
+ case COMMISSIONED: return kWPANTUNDStateCommissioned;
+ case ASSOCIATING: return kWPANTUNDStateAssociating;
+ case CREDENTIALS_NEEDED: return kWPANTUNDStateCredentialsNeeded;
+ case ASSOCIATED: return kWPANTUNDStateAssociated;
+ case ISOLATED: return kWPANTUNDStateIsolated;
+ case NET_WAKE_ASLEEP: return kWPANTUNDStateNetWake_Asleep;
+ case NET_WAKE_WAKING: return kWPANTUNDStateNetWake_Waking;
+ }
+ return std::string("unknown-state");
+}
+
+std::string
+nl::wpantund::node_type_to_string(NodeType node_type)
+{
+ std::string ret;
+
+ switch (node_type) {
+ case UNKNOWN:
+ ret = kWPANTUNDNodeType_Unknown;
+ break;
+ case END_DEVICE:
+ ret = kWPANTUNDNodeType_EndDevice;
+ break;
+ case SLEEPY_END_DEVICE:
+ ret = kWPANTUNDNodeType_SleepyEndDevice;
+ break;
+ case ROUTER:
+ ret = kWPANTUNDNodeType_Router;
+ break;
+ case LURKER:
+ ret = kWPANTUNDNodeType_NestLurker;
+ break;
+ case LEADER:
+ ret = kWPANTUNDNodeType_Leader;
+ break;
+ case COMMISSIONER:
+ ret = kWPANTUNDNodeType_Commissioner;
+ break;
+ default:
+ {
+ char cstr[16];
+ snprintf(cstr, sizeof(cstr), "(node-type-%u)", (unsigned int)node_type);
+ ret = cstr;
+ }
+ break;
+ }
+
+ return ret;
+}
+
+nl::wpantund::NodeType
+nl::wpantund::string_to_node_type(const std::string& node_type_string)
+{
+ if (strcaseequal(node_type_string.c_str(), kWPANTUNDNodeType_EndDevice) ||
+ strcaseequal(node_type_string.c_str(), "end") ||
+ strcaseequal(node_type_string.c_str(), "e") ||
+ (node_type_string == "3"))
+ {
+ return END_DEVICE;
+ }
+
+ if (strcaseequal(node_type_string.c_str(), kWPANTUNDNodeType_SleepyEndDevice) ||
+ strcaseequal(node_type_string.c_str(), "sleepy") ||
+ strcaseequal(node_type_string.c_str(), "sed") ||
+ strcaseequal(node_type_string.c_str(), "s") ||
+ (node_type_string == "4"))
+ {
+ return SLEEPY_END_DEVICE;
+ }
+
+ if (strcaseequal(node_type_string.c_str(), kWPANTUNDNodeType_Router) ||
+ strcaseequal(node_type_string.c_str(), "r") ||
+ (node_type_string == "2"))
+ {
+ return ROUTER;
+ }
+
+ if (strcaseequal(node_type_string.c_str(), kWPANTUNDNodeType_Leader))
+ {
+ return LEADER;
+ }
+
+ if (strcaseequal(node_type_string.c_str(), kWPANTUNDNodeType_NestLurker) ||
+ strcaseequal(node_type_string.c_str(), "lurker") ||
+ (node_type_string == "6"))
+ {
+ return LURKER;
+ }
+
+ return UNKNOWN;
+}
+
+std::string
+nl::wpantund::address_flags_to_string(uint8_t flags)
+{
+ std::string ret;
+ int i;
+ for (i = 7; i >=0 ; --i) {
+ uint8_t mask = (1<<i);
+ if (i == 3) {
+ ret += ' ';
+ }
+ if (!(mask & flags)) {
+ ret += '-';
+ continue;
+ }
+ switch (mask) {
+ case GA_AM_GATEWAY: //0
+ ret += 'G';
+ break;
+ case GA_AM_DHCP_SERVER: //1
+ ret += 'D';
+ break;
+ case GA_AM_SLAAC_SERVER: //2
+ ret += 'S';
+ break;
+ case GA_DHCP: // 3
+ ret += 'd';
+ break;
+ case GA_SLAAC: // 4
+ ret += 's';
+ break;
+ case GA_CONFIGURED: // 5
+ ret += 'C';
+ break;
+ case GA_REQUEST_SENT: //6
+ ret += 'R';
+ break;
+ case GA_REQUEST_FAILED: //7
+ ret += 'F';
+ break;
+ default:
+ ret += '0' + i;
+ break;
+ }
+ }
+ return ret;
+}
+
+std::string
+nl::wpantund::flags_to_string(uint8_t flags, const char flag_lookup[8])
+{
+ std::string ret;
+ int i;
+ if (flag_lookup == NULL) {
+ flag_lookup = "76543210";
+ }
+ for (i = 7; i >= 0 ; --i) {
+ uint8_t mask = (1<<i);
+ if (i == 3) {
+ ret += ' ';
+ }
+ if (!(mask & flags)) {
+ ret += '-';
+ continue;
+ }
+ ret += flag_lookup[7-i];
+ }
+ return ret;
+}
+
+NCPState
+nl::wpantund::string_to_ncp_state(const std::string& state_string)
+{
+ if (state_string == kWPANTUNDStateFault) {
+ return FAULT;
+ } else if (state_string == kWPANTUNDStateUpgrading) {
+ return UPGRADING;
+ } else if (state_string == kWPANTUNDStateDeepSleep) {
+ return DEEP_SLEEP;
+ } else if (state_string == kWPANTUNDStateCommissioned) {
+ return COMMISSIONED;
+ } else if (state_string == kWPANTUNDStateCredentialsNeeded) {
+ return CREDENTIALS_NEEDED;
+ } else if (state_string == kWPANTUNDStateIsolated) {
+ return ISOLATED;
+ } else if (state_string == kWPANTUNDStateNetWake_Asleep) {
+ return NET_WAKE_ASLEEP;
+ } else if (state_string == kWPANTUNDStateNetWake_Waking) {
+ return NET_WAKE_WAKING;
+ }
+
+ if (strnequal(state_string.c_str(), kWPANTUNDStateUninitialized, sizeof(kWPANTUNDStateUninitialized)-1)) {
+ return UNINITIALIZED;
+ } else if (strnequal(state_string.c_str(), kWPANTUNDStateOffline, sizeof(kWPANTUNDStateOffline)-1)) {
+ return OFFLINE;
+ } else if (strnequal(state_string.c_str(), kWPANTUNDStateAssociating, sizeof(kWPANTUNDStateAssociating)-1)) {
+ return ASSOCIATING;
+ } else if (strnequal(state_string.c_str(), kWPANTUNDStateAssociated, sizeof(kWPANTUNDStateAssociated)-1)) {
+ return ASSOCIATED;
+ }
+
+ // Unknown
+ return UNINITIALIZED;
+}
+
+std::string
+GlobalAddressEntry::get_description() const
+{
+ char c_string[200];
+
+ snprintf(c_string, sizeof(c_string), "valid: %u preferred: %u flags: %s (0x%02X)",
+ mValidLifetime,
+ mPreferredLifetime,
+ address_flags_to_string(mFlags).c_str(),
+ mFlags);
+
+ return std::string(c_string);
+}
diff --git a/src/wpantund/NCPTypes.h b/src/wpantund/NCPTypes.h
new file mode 100644
index 0000000..7e22959
--- /dev/null
+++ b/src/wpantund/NCPTypes.h
@@ -0,0 +1,118 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __wpantund__NCPTypes__
+#define __wpantund__NCPTypes__
+
+#include <stdint.h>
+#include "time-utils.h"
+#include <string>
+
+namespace nl {
+namespace wpantund {
+
+enum NCPState {
+ UNINITIALIZED,
+ FAULT,
+ UPGRADING,
+ DEEP_SLEEP,
+ OFFLINE,
+ COMMISSIONED,
+ ASSOCIATING,
+ CREDENTIALS_NEEDED,
+ ASSOCIATED,
+ ISOLATED,
+ NET_WAKE_WAKING,
+ NET_WAKE_ASLEEP,
+};
+
+enum NodeType {
+ UNKNOWN,
+ ROUTER,
+ END_DEVICE,
+ SLEEPY_END_DEVICE,
+ COMMISSIONER,
+ LURKER,
+ LEADER,
+};
+
+enum GlobalAddressFlags {
+ GA_AM_GATEWAY = 0x01,
+ GA_AM_DHCP_SERVER = 0x02,
+ GA_AM_SLAAC_SERVER = 0x04,
+ GA_DHCP = 0x08,
+ GA_SLAAC = 0x10,
+ GA_CONFIGURED = 0x20,
+ GA_REQUEST_SENT = 0x40,
+ GA_REQUEST_FAILED = 0x80,
+};
+
+struct GlobalAddressEntry {
+ uint32_t mValidLifetime;
+ time_t mValidLifetimeExpiration;
+ uint32_t mPreferredLifetime;
+ time_t mPreferredLifetimeExpiration;
+ uint8_t mFlags;
+ uint8_t mUserAdded:1;
+
+ std::string get_description() const;
+};
+
+struct EnergyScanResultEntry
+{
+ uint8_t mChannel;
+ int8_t mMaxRssi;
+};
+
+std::string address_flags_to_string(uint8_t flags);
+
+std::string flags_to_string(uint8_t flags, const char flag_lookup[8] = "76543210");
+
+bool ncp_state_is_sleeping(NCPState x);
+
+bool ncp_state_has_joined(NCPState x);
+
+bool ncp_state_is_joining(NCPState x);
+
+bool ncp_state_is_commissioned(NCPState x);
+
+bool ncp_state_is_busy(NCPState x);
+
+bool ncp_state_is_joining_or_joined(NCPState x);
+
+bool ncp_state_is_interface_up(NCPState x);
+
+bool ncp_state_is_detached_from_ncp(NCPState x);
+
+bool ncp_state_is_initializing(NCPState x);
+
+bool ncp_state_is_associated(NCPState x);
+
+std::string ncp_state_to_string(NCPState state);
+
+NCPState string_to_ncp_state(const std::string& state_string);
+
+std::string node_type_to_string(NodeType node_type);
+
+NodeType string_to_node_type(const std::string& node_type_string);
+
+}; // namespace wpantund
+}; // namespace nl
+
+#endif // defined(__wpantund__NCPTypes__)
diff --git a/src/wpantund/NetworkInstance.h b/src/wpantund/NetworkInstance.h
new file mode 100644
index 0000000..109d242
--- /dev/null
+++ b/src/wpantund/NetworkInstance.h
@@ -0,0 +1,172 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef wpantund_NetworkInstance_h
+#define wpantund_NetworkInstance_h
+
+#include <stdint.h>
+#include <string>
+#include <cstring>
+#include "string-utils.h"
+
+namespace nl {
+
+
+namespace wpantund {
+namespace WPAN {
+struct NetworkId {
+ std::string name;
+ uint8_t xpanid[8];
+
+ uint64_t
+ get_xpanid_as_uint64() const
+ {
+ union {
+ uint64_t val;
+ uint8_t data[8];
+ } x;
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ memcpyrev(x.data, xpanid, 8);
+#else
+ memcpy(x.data, xpanid, 8);
+#endif
+ return x.val;
+ }
+
+ void
+ set_xpanid_as_uint64(const uint64_t &_xpanid)
+ {
+ union {
+ uint64_t val;
+ uint8_t data[8];
+ } x;
+ x.val = _xpanid;
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ memcpyrev(xpanid, x.data, 8);
+#else
+ memcpy(xpanid, x.data, 8);
+#endif
+ }
+
+ NetworkId(const std::string& _name = "")
+ : name(_name)
+ {
+ }
+
+ NetworkId(
+ const std::string& _name, const uint8_t _xpanid[8]
+ )
+ : name(_name)
+ {
+ if (_xpanid) {
+ memcpy(xpanid, _xpanid, sizeof(xpanid));
+ } else {
+ memset(xpanid, 0, sizeof(xpanid));
+ }
+ }
+
+ NetworkId(
+ const std::string& _name, const uint64_t &_xpanid
+ )
+ : name(_name)
+ {
+ set_xpanid_as_uint64(_xpanid);
+ }
+
+ bool operator==(const NetworkId& rhs) const
+ {
+ return (name == rhs.name) &&
+ (0 == memcmp(xpanid, rhs.xpanid, sizeof(xpanid)));
+ }
+};
+
+struct NetworkInstance : public NetworkId {
+ uint16_t panid;
+ uint8_t channel;
+ bool joinable;
+ int8_t rssi;
+ uint8_t lqi;
+ uint8_t type;
+ uint8_t hwaddr[8];
+ uint16_t saddr;
+ uint8_t version;
+
+public:
+ NetworkInstance(
+ const std::string& _name = "",
+ const uint8_t _xpanid[8] = NULL,
+ uint16_t _panid = 0xFFFF, int _channel = 0,
+ bool _joinable = false
+ ) :
+ NetworkId(_name, _xpanid),
+ panid(_panid),
+ channel(_channel),
+ joinable(_joinable),
+ rssi(-128),
+ type(0),
+ hwaddr(),
+ version(0)
+ {
+ }
+ NetworkInstance(
+ const std::string& _name,
+ const uint64_t _xpanid,
+ uint16_t _panid = 0xFFFF, int _channel = 0,
+ bool _joinable = false
+ ) :
+ NetworkId(_name, _xpanid),
+ panid(_panid),
+ channel(_channel),
+ joinable(_joinable),
+ rssi(-128),
+ type(0),
+ hwaddr(),
+ version(0)
+ {
+ }
+
+ bool operator==(const NetworkInstance& rhs) const
+ {
+ return NetworkId::operator==(rhs)
+ && (panid == rhs.panid)
+ && (channel == rhs.channel)
+ && (type == rhs.type)
+ && (0 == memcmp(hwaddr, rhs.hwaddr, 8));
+ }
+
+ bool operator!=(const NetworkInstance& rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+ uint64_t get_hwaddr_as_uint64() const
+ {
+ union {
+ uint64_t ret;
+ uint8_t data[8];
+ };
+ memcpyrev(data, hwaddr, 8);
+ return ret;
+ }
+};
+}; // namespace WPAN
+}; // namespace wpantund
+}; // namespace nl
+
+#endif
diff --git a/src/wpantund/NetworkRetain.cpp b/src/wpantund/NetworkRetain.cpp
new file mode 100644
index 0000000..5716ca2
--- /dev/null
+++ b/src/wpantund/NetworkRetain.cpp
@@ -0,0 +1,215 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * NetworkRetain class implementation.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "assert-macros.h"
+#include "wpan-properties.h"
+#include "NetworkRetain.h"
+#include "socket-utils.h"
+
+#include <syslog.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+
+#if HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+using namespace nl;
+using namespace wpantund;
+
+NetworkRetain::NetworkRetain(void) :
+ mNetworkRetainFD(-1)
+{
+}
+
+NetworkRetain::~NetworkRetain()
+{
+ close_network_retain_fd();
+}
+
+void
+NetworkRetain::handle_ncp_state_change(NCPState new_ncp_state, NCPState old_ncp_state)
+{
+ require_quiet(mNetworkRetainFD >= 0, bail);
+
+ // Not-joined --> joined
+ if (!ncp_state_has_joined(old_ncp_state) && ncp_state_has_joined(new_ncp_state)) {
+ save_network_info();
+ }
+
+ // Initializing --> Offline
+ else if (ncp_state_is_initializing(old_ncp_state) && (new_ncp_state == OFFLINE)) {
+ recall_network_info();
+ }
+
+ // Joined --> Offline
+ else if (ncp_state_has_joined(old_ncp_state) && (new_ncp_state == OFFLINE)) {
+ erase_network_info();
+ }
+
+bail:
+ return;
+}
+
+void
+NetworkRetain::close_network_retain_fd(void)
+{
+ if (mNetworkRetainFD >= 0)
+ {
+ IGNORE_RETURN_VALUE(write(mNetworkRetainFD, "X", 1));
+ close(mNetworkRetainFD);
+ mNetworkRetainFD = -1;
+ }
+}
+
+void
+NetworkRetain::set_network_retain_command(const std::string& command)
+{
+ int status = -1;
+ pid_t pid = -1;
+
+ if (mNetworkRetainFD >= 0) {
+ close_network_retain_fd();
+ }
+
+ pid = fork_unixdomain_socket(&mNetworkRetainFD);
+
+ if (pid < 0) {
+ return;
+ }
+
+ if (pid == 0) {
+ int stdout_fd_copy = dup(STDOUT_FILENO);
+ int stdin_fd_copy = dup(STDIN_FILENO);
+ FILE* stdin_copy = NULL;
+ FILE* stdout_copy = NULL;
+
+ dup2(STDERR_FILENO,STDOUT_FILENO);
+
+ if (stdin_fd_copy >= 0) {
+ close(STDIN_FILENO);
+ stdin_copy = fdopen(stdin_fd_copy, "r");
+ }
+
+ if (stdout_fd_copy >= 0) {
+ stdout_copy = fdopen(stdout_fd_copy, "w");
+ }
+
+ // Double fork to avoid leaking zombie processes.
+ pid = fork();
+ if (pid < 0) {
+ syslog(LOG_ERR, "Call to fork() failed: %s (%d)", strerror(errno), errno);
+
+ _exit(errno);
+ }
+
+ if (0 == pid) // In child process.
+ {
+ // Set the shell environment variable if it isn't set already.
+ setenv("SHELL",SOCKET_UTILS_DEFAULT_SHELL,0);
+
+ while ((ferror(stdin_copy) == 0) && (feof(stdin_copy) == 0)) {
+ int c;
+ std::string args;
+
+ c = fgetc(stdin_copy);
+
+ switch (c) {
+ case 'R':
+ case 'E':
+ case 'S':
+ args = " ";
+ args += c;
+
+ // Execute the requested command.
+ IGNORE_RETURN_VALUE(system((command + args).c_str()));
+ break;
+
+ case 'X':
+ _exit(EXIT_SUCCESS);
+ break;
+
+ default:
+ syslog(LOG_WARNING, "Got unrecognized char 0x%x in NetworkRetain child process.", (int)c);
+ break;
+ }
+ }
+
+ _exit(EXIT_FAILURE);
+ }
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ // Wait for the first fork to return, and place the return value in errno
+ if (waitpid(pid, &status, 0) < 0) {
+ syslog(LOG_ERR, "Call to waitpid() failed: %s (%d)", strerror(errno), errno);
+ }
+
+ if (0 != WEXITSTATUS(status)) {
+ // If this has happened then the double fork failed. Clean up
+ // and pass this status along to the caller as errno.
+
+ syslog(LOG_ERR, "Child process failed: %s (%d)", strerror(WEXITSTATUS(status)), WEXITSTATUS(status));
+
+ close(mNetworkRetainFD);
+ mNetworkRetainFD = -1;
+
+ errno = WEXITSTATUS(status);
+ }
+}
+
+void
+NetworkRetain::save_network_info(void)
+{
+ syslog(LOG_NOTICE, "NetworkRetain - Saving network info...");
+ require_string(write(mNetworkRetainFD, "S", 1) == 1, bail, strerror(errno));
+bail:
+ return;
+}
+
+void
+NetworkRetain::recall_network_info(void)
+{
+ syslog(LOG_NOTICE, "NetworkRetain - Recalling/restoring network info...");
+ require_string(write(mNetworkRetainFD, "R", 1) == 1, bail, strerror(errno));
+bail:
+ return;
+}
+
+void
+NetworkRetain::erase_network_info(void)
+{
+ syslog(LOG_NOTICE, "NetworkRetaine - Erasing network info...");
+ require_string(write(mNetworkRetainFD, "E", 1) == 1, bail, strerror(errno));
+bail:
+ return;
+}
+
diff --git a/src/wpantund/NetworkRetain.h b/src/wpantund/NetworkRetain.h
new file mode 100644
index 0000000..a6ae6da
--- /dev/null
+++ b/src/wpantund/NetworkRetain.h
@@ -0,0 +1,53 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * Declaration of NetworkRetain class (Hooks for saving/restoring network info)
+ *
+ */
+
+#ifndef __wpantund__NetworkRetain__
+#define __wpantund__NetworkRetain__
+
+#include <string>
+#include "NCPTypes.h"
+
+namespace nl {
+namespace wpantund {
+
+class NetworkRetain
+{
+public:
+ NetworkRetain();
+ ~NetworkRetain();
+ void set_network_retain_command(const std::string& command);
+ void handle_ncp_state_change(NCPState new_ncp_state, NCPState old_ncp_state);
+
+private:
+ void save_network_info(void);
+ void recall_network_info(void);
+ void erase_network_info(void);
+ void close_network_retain_fd(void);
+
+private:
+ int mNetworkRetainFD;
+};
+
+}; // namespace wpantund
+}; // namespace nl
+
+#endif /* defined(__wpantund__NetworkRetain__) */
diff --git a/src/wpantund/Pcap.cpp b/src/wpantund/Pcap.cpp
new file mode 100644
index 0000000..84b5985
--- /dev/null
+++ b/src/wpantund/Pcap.cpp
@@ -0,0 +1,378 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "assert-macros.h"
+
+#include <string.h>
+#include <syslog.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include "Pcap.h"
+
+using namespace nl;
+using namespace wpantund;
+
+
+PcapPacket::PcapPacket()
+ : mLen(sizeof(PcapFrameHeader)), mStatus(kWPANTUNDStatus_Ok)
+{
+ mHeader.mSeconds = 0;
+ mHeader.mMicroSeconds = 0;
+ mHeader.mRecordedPayloadSize = sizeof(PcapPpiHeader);
+ mHeader.mActualPayloadSize = sizeof(PcapPpiHeader);
+ mHeader.mPpiHeader.mVersion = 0;
+ mHeader.mPpiHeader.mFlags = 0;
+ mHeader.mPpiHeader.mSize = sizeof(PcapPpiHeader);
+ mHeader.mPpiHeader.mDLT = 0;
+}
+
+wpantund_status_t
+PcapPacket::get_status(void)const
+{
+ return mStatus;
+}
+
+const uint8_t*
+PcapPacket::get_data_ptr(void)const
+{
+ return mData;
+}
+
+int
+PcapPacket::get_data_len(void)const
+{
+ return mLen;
+}
+
+PcapPacket&
+PcapPacket::set_timestamp(struct timeval* tv)
+{
+ if (tv == NULL) {
+ struct timeval x;
+ gettimeofday(&x, NULL);
+
+ mHeader.mSeconds = static_cast<uint32_t>(x.tv_sec);
+ mHeader.mMicroSeconds = x.tv_usec;
+
+ } else {
+ mHeader.mSeconds = static_cast<uint32_t>(tv->tv_sec);
+ mHeader.mMicroSeconds = tv->tv_usec;
+ }
+
+ return *this;
+}
+
+PcapPacket&
+PcapPacket::set_dlt(uint32_t i)
+{
+ mHeader.mPpiHeader.mDLT = i;
+ return *this;
+}
+
+PcapPacket&
+PcapPacket::append_ppi_field(uint16_t type, const uint8_t* field_ptr, int field_len)
+{
+ PcapPpiFieldHeader field_header;
+
+ assert(mLen <= sizeof(mData));
+
+ if (field_len < 0) {
+ mStatus = kWPANTUNDStatus_InvalidArgument;
+
+ } else if (mLen + field_len + sizeof(PcapPpiFieldHeader) > sizeof(mData)) {
+ mStatus = kWPANTUNDStatus_InvalidArgument;
+
+ } else {
+ field_header.mType = type;
+ field_header.mSize = field_len;
+ memcpy(mData + mLen, &field_header, sizeof(PcapPpiFieldHeader));
+ memcpy(mData + mLen + sizeof(PcapPpiFieldHeader), field_ptr, field_len);
+ mLen += field_len + sizeof(PcapPpiFieldHeader);
+ mHeader.mRecordedPayloadSize += field_len + sizeof(PcapPpiFieldHeader);
+ mHeader.mPpiHeader.mSize += field_len + sizeof(PcapPpiFieldHeader);
+ }
+
+ mHeader.mActualPayloadSize += field_len + sizeof(PcapPpiFieldHeader);
+
+ return *this;
+}
+
+PcapPacket&
+PcapPacket::append_payload(const uint8_t* payload_ptr, int payload_len)
+{
+ assert(mLen <= sizeof(mData));
+
+ if (payload_len < 0) {
+ mStatus = kWPANTUNDStatus_InvalidArgument;
+
+ } else if (mLen + payload_len > sizeof(mData)) {
+ memcpy(mData + mLen, payload_ptr, sizeof(mData) - mLen);
+ mLen = sizeof(mData);
+ mHeader.mRecordedPayloadSize += sizeof(mData) - mLen;
+
+ } else {
+ memcpy(mData + mLen, payload_ptr, payload_len);
+ mLen += payload_len;
+ mHeader.mRecordedPayloadSize += payload_len;
+ }
+
+ mHeader.mActualPayloadSize += payload_len;
+
+ return *this;
+}
+
+
+PcapManager::PcapManager()
+{
+}
+
+PcapManager::~PcapManager()
+{
+}
+
+bool
+PcapManager::is_enabled(void)
+{
+ return !mFDSet.empty();
+}
+
+const std::set<int>&
+PcapManager::get_fd_set(void)
+{
+ return mFDSet;
+}
+
+int
+PcapManager::insert_fd(int fd)
+{
+ int ret = -1;
+ int save_errno;
+ int set = 1;
+ PcapGlobalHeader header;
+
+ // Prepare the PCAP header.
+ header.mMagic = PCAP_MAGIC;
+ header.mVerMaj = PCAP_VERSION_MAJOR;
+ header.mVerMin = PCAP_VERSION_MINOR;
+ header.mGMTOffset = 0;
+ header.mAccuracy = 0;
+ header.mSnapshotLengthField = PCAP_PACKET_MAX_SIZE;
+ header.mDLT = PCAP_DLT_PPI;
+
+#ifdef SO_NOSIGPIPE
+ setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
+#endif
+
+ // Send the PCAP header.
+ ret = static_cast<int>(write(fd, &header, sizeof(header)));
+
+ if (ret < 0) {
+ save_errno = errno;
+ syslog(LOG_ERR, "PcapManager::insert_fd: Call to send() on fd %d failed: %s (%d)", fd, strerror(errno), errno);
+ goto bail;
+ }
+
+ mFDSet.insert(fd);
+
+ ret = 0;
+
+bail:
+ if (ret < 0) {
+ errno = save_errno;
+ }
+
+ return ret;
+}
+
+int
+PcapManager::new_fd(void)
+{
+ int ret = -1;
+ int save_errno;
+ int fd[2] = { -1, -1 };
+
+ ret = socketpair(PF_UNIX, SOCK_DGRAM, 0, fd);
+
+ if (ret < 0) {
+ save_errno = errno;
+ syslog(LOG_ERR, "PcapManager::new_fd: Call to socketpair() failed: %s (%d)", strerror(errno), errno);
+ goto bail;
+ }
+
+ ret = insert_fd(fd[1]);
+
+ if (ret < 0) {
+ save_errno = errno;
+ goto bail;
+ }
+
+ ret = fd[0];
+
+bail:
+
+ if (ret < 0) {
+ close(fd[0]);
+ close(fd[1]);
+
+ errno = save_errno;
+ }
+
+ return ret;
+}
+
+void
+PcapManager::close_fd_set(const std::set<int>& x)
+{
+ if (&x == &mFDSet) {
+ // Special case where we are asked to close everything.
+ std::set<int> copy(x);
+
+ close_fd_set(copy);
+
+ } else if (!x.empty()) {
+ std::set<int>::const_iterator iter;
+
+ for ( iter = x.begin()
+ ; iter != x.end()
+ ; ++iter
+ ) {
+ const int fd = *iter;
+ syslog(LOG_INFO, "PcapManager::close_fd_set: Closing FD %d", fd);
+ close(fd);
+ mFDSet.erase(fd);
+ }
+ syslog(LOG_INFO, "PcapManager: %d pcap streams remaining", static_cast<int>(mFDSet.size()));
+ }
+}
+
+void
+PcapManager::push_packet(const PcapPacket& packet)
+{
+ std::set<int>::const_iterator iter;
+ std::set<int> remove_set;
+
+ require_noerr(packet.get_status(), bail);
+
+ for ( iter = mFDSet.begin()
+ ; iter != mFDSet.end()
+ ; ++iter
+ ) {
+ int ret;
+
+ // Send the PCAP frame.
+ ret = static_cast<int>(write(
+ *iter,
+ packet.get_data_ptr(),
+ packet.get_data_len()
+ ));
+
+ __ASSERT_MACROS_check(ret >= 0);
+
+ if (ret < 0) {
+ // Since we can't remove this file descriptor
+ // from the set while we are iterating through it,
+ // we add it to the remove set for later removal.
+ remove_set.insert(*iter);
+ }
+ }
+
+ close_fd_set(remove_set);
+
+bail:
+ return;
+}
+
+int
+PcapManager::update_fd_set(fd_set *read_fd_set, fd_set *write_fd_set, fd_set *error_fd_set, int *max_fd, cms_t *timeout)
+{
+ std::set<int>::const_iterator iter;
+
+ for ( iter = mFDSet.begin()
+ ; iter != mFDSet.end()
+ ; ++iter
+ ) {
+ const int fd = *iter;
+
+ if (read_fd_set) {
+ FD_SET(fd, read_fd_set);
+ }
+
+ if (error_fd_set) {
+ FD_SET(fd, error_fd_set);
+ }
+
+ if (max_fd && (*max_fd < fd)) {
+ *max_fd = fd;
+ }
+ }
+
+ return 0;
+}
+
+void
+PcapManager::process(void)
+{
+ if (is_enabled()) {
+ fd_set fds;
+ int max_fd(-1);
+ int fds_ready;
+ struct timeval timeout = {};
+
+ FD_ZERO(&fds);
+
+ update_fd_set(&fds, NULL, &fds, &max_fd, NULL);
+
+ fds_ready = select(
+ max_fd + 1,
+ &fds,
+ NULL,
+ &fds,
+ &timeout
+ );
+
+ if (fds_ready > 0) {
+ // Tear down bad file descriptors.
+ std::set<int> remove_set;
+ std::set<int>::const_iterator iter;
+
+ for ( iter = mFDSet.begin()
+ ; (fds_ready > 0) && (iter != mFDSet.end())
+ ; ++iter
+ ) {
+ int fd = *iter;
+ if (!FD_ISSET(fd, &fds)) {
+ continue;
+ }
+ fds_ready--;
+ remove_set.insert(fd);
+ }
+
+ close_fd_set(remove_set);
+ }
+ }
+}
diff --git a/src/wpantund/Pcap.h b/src/wpantund/Pcap.h
new file mode 100644
index 0000000..86c9860
--- /dev/null
+++ b/src/wpantund/Pcap.h
@@ -0,0 +1,144 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __wpantund__Pcap__
+#define __wpantund__Pcap__
+
+#include <set>
+#include "wpan-error.h"
+#include "time-utils.h"
+
+namespace nl {
+namespace wpantund {
+
+#define PCAP_PACKET_MAX_SIZE 512
+
+#define PCAP_DLT_PPI 192
+#define PCAP_DLT_IEEE802_15_4 195
+#define PCAP_DLT_IEEE802_15_4_NOFCS 230
+
+#define PCAP_MAGIC 0xa1b2c3d4
+#define PCAP_VERSION_MAJOR 2
+#define PCAP_VERSION_MINOR 4
+
+#define PCAP_PPI_VERSION 0
+
+#define PCAP_PPI_TYPE_SPINEL 61616
+
+/* Additional reading:
+ *
+ * * DLT list: http://www.tcpdump.org/linktypes.html
+ * * Info on PPI: http://www.cacetech.com/documents/PPI%20Header%20format%201.0.7.pdf
+ */
+
+struct PcapGlobalHeader {
+ uint32_t mMagic;
+ uint16_t mVerMaj;
+ uint16_t mVerMin;
+ int32_t mGMTOffset;
+ uint32_t mAccuracy;
+ uint32_t mSnapshotLengthField;
+ uint32_t mDLT;
+};
+
+struct PcapPpiHeader {
+ uint8_t mVersion;
+ uint8_t mFlags;
+ uint16_t mSize;
+ uint32_t mDLT;
+ uint8_t mPayloadData[0];
+};
+
+struct PcapPpiFieldHeader {
+ uint16_t mType;
+ uint16_t mSize;
+ uint8_t mData[0];
+};
+
+struct PcapFrameHeader {
+ uint32_t mSeconds;
+ uint32_t mMicroSeconds;
+ uint32_t mRecordedPayloadSize;
+ uint32_t mActualPayloadSize;
+ union {
+ struct PcapPpiHeader mPpiHeader;
+ uint8_t mPayloadData[0];
+ };
+};
+
+class PcapPacket
+{
+public:
+ PcapPacket();
+
+ wpantund_status_t get_status(void)const;
+
+ const uint8_t* get_data_ptr(void)const;
+
+ int get_data_len(void)const;
+
+ PcapPacket& set_timestamp(struct timeval* tv = NULL);
+
+ PcapPacket& set_dlt(uint32_t i);
+
+ PcapPacket& append_ppi_field(uint16_t type, const uint8_t* field_ptr, int field_len);
+
+ PcapPacket& append_payload(const uint8_t* payload_ptr, int payload_len);
+
+ PcapPacket& finish(void);
+
+private:
+ union {
+ uint8_t mData[PCAP_PACKET_MAX_SIZE];
+ PcapFrameHeader mHeader;
+ };
+ int mLen;
+ wpantund_status_t mStatus;
+};
+
+class PcapManager
+{
+public:
+ PcapManager();
+ ~PcapManager();
+
+ bool is_enabled(void);
+
+ const std::set<int>& get_fd_set(void);
+
+ int new_fd(void);
+
+ int insert_fd(int fd);
+
+ void push_packet(const PcapPacket& packet);
+
+ void process(void);
+
+ int update_fd_set(fd_set *read_fd_set, fd_set *write_fd_set, fd_set *error_fd_set, int *max_fd, cms_t *timeout);
+
+ void close_fd_set(const std::set<int>& x);
+
+private:
+ std::set<int> mFDSet;
+};
+
+}; // namespace wpantund
+}; // namespace nl
+
+#endif /* defined(__wpantund__NetworkRetain__) */
diff --git a/src/wpantund/RunawayResetBackoffManager.cpp b/src/wpantund/RunawayResetBackoffManager.cpp
new file mode 100644
index 0000000..27d0981
--- /dev/null
+++ b/src/wpantund/RunawayResetBackoffManager.cpp
@@ -0,0 +1,70 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "RunawayResetBackoffManager.h"
+
+#include <cstring>
+#include <syslog.h>
+#include <sys/time.h>
+
+using namespace nl;
+using namespace nl::wpantund;
+
+// -----------------------------
+
+const int RunawayResetBackoffManager::kDecayPeriod = 15;
+const int RunawayResetBackoffManager::kBackoffThreshold = 4;
+
+RunawayResetBackoffManager::RunawayResetBackoffManager():
+ mWindowedResetCount(0),
+ mDecrementAt(0)
+{
+}
+
+float
+RunawayResetBackoffManager::delay_for_unexpected_reset(void)
+{
+ float ret = 0;
+ if (mWindowedResetCount > kBackoffThreshold) {
+ int count = mWindowedResetCount - kBackoffThreshold;
+ ret = (count * count) / 2.0f;
+ syslog(LOG_ERR, "RunawayResetBackoffManager: mWindowedResetCount = %d, will delay for %f seconds", mWindowedResetCount, ret);
+ }
+ return ret;
+}
+
+void
+RunawayResetBackoffManager::count_unexpected_reset(void)
+{
+ mWindowedResetCount++;
+ mDecrementAt = time_get_monotonic() + kDecayPeriod;
+}
+
+void
+RunawayResetBackoffManager::update(void)
+{
+ if ((mWindowedResetCount > 0) && (mDecrementAt < time_get_monotonic())) {
+ mWindowedResetCount--;
+ mDecrementAt = time_get_monotonic() + kDecayPeriod;
+ }
+}
diff --git a/src/wpantund/RunawayResetBackoffManager.h b/src/wpantund/RunawayResetBackoffManager.h
new file mode 100644
index 0000000..cec5739
--- /dev/null
+++ b/src/wpantund/RunawayResetBackoffManager.h
@@ -0,0 +1,52 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __WPANTUND_RUNAWAY_RESET_BACKOFF_MANAGER_H__
+#define __WPANTUND_RUNAWAY_RESET_BACKOFF_MANAGER_H__ 1
+
+#include "time-utils.h"
+
+namespace nl {
+namespace wpantund {
+
+class RunawayResetBackoffManager {
+public:
+ RunawayResetBackoffManager();
+
+ //! Returns the number of seconds that we should sleep after the next reset.
+ float delay_for_unexpected_reset(void);
+
+ //! Called when an unexpected reset occurs.
+ void count_unexpected_reset(void);
+
+ //! Called for every main loop to update the windowed reset count.
+ void update(void);
+
+private:
+ static const int kDecayPeriod;
+ static const int kBackoffThreshold;
+
+ int mWindowedResetCount;
+ time_t mDecrementAt;
+};
+
+}; // namespace wpantund
+}; // namespace nl
+
+#endif // __WPANTUND_RUNAWAY_RESET_BACKOFF_MANAGER_H__
diff --git a/src/wpantund/StatCollector.cpp b/src/wpantund/StatCollector.cpp
new file mode 100644
index 0000000..853e8c5
--- /dev/null
+++ b/src/wpantund/StatCollector.cpp
@@ -0,0 +1,1735 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * Statistics collector module.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <syslog.h>
+#include <arpa/inet.h>
+#include <iterator>
+#include "StatCollector.h"
+#include "any-to.h"
+#include "wpan-error.h"
+
+using namespace nl;
+using namespace wpantund;
+
+// Enable additional debug logs only in this module
+#define ENABLE_MODULE_DEBUG 0
+#if ENABLE_MODULE_DEBUG
+#define DEBUG_LOG(msg, ...) syslog(LOG_INFO, msg , ##__VA_ARGS__)
+#else
+#define DEBUG_LOG(msg, ...) do { } while(false)
+#endif
+
+
+// Number of history items to show for short version of stat "Stat:Short"
+#define STAT_COLLECTOR_SHORT_HISTORY_COUNT 10
+
+// Number of history items to show for short version of stat "Stat:LinkQuality:Short"
+#define STAT_COLLECTOR_LINK_STAT_HISTORY_SIZE 8
+
+// Log level for adding logs to syslog when user/application requests it
+#define STAT_COLLECTOR_LOG_LEVEL_USER_REQUEST LOG_INFO
+
+// Default log level for short auto logs (periodic logging)
+#define STAT_COLLECTOR_AUTO_LOG_DEFAULT_LOG_LEVEL LOG_INFO
+
+// Default period (in min) for automatically logging stat info
+#define STAT_COLLECTOR_AUTO_LOG_PERIOD_IN_MIN 30 // 30 min
+
+// Maximum allowed period for auto log (value is in min)
+#define STAT_COLLECTOR_AUTO_LOG_MAX_PERIOD (60 * 24 * 7 * 2) // Two weeks
+
+// Time stamp constants
+#define TIMESTAMP_ONE_SEC_IN_MS ((int32_t)1000)
+#define TIMESTAMP_ONE_MIN_IN_MS (TIMESTAMP_ONE_SEC_IN_MS * 60)
+#define TIMESTAMP_ONE_HOUR_IN_MS (TIMESTAMP_ONE_MIN_IN_MS * 60)
+#define TIMESTAMP_ONE_DAY_IN_MS (TIMESTAMP_ONE_HOUR_IN_MS * 24)
+#define TIMESTAMP_UNINITIALIZED_VALUE 0
+
+// IPv6 types
+#define IPV6_TYPE_UDP 0x11
+#define IPV6_TYPE_TCP 0x06
+#define IPV6_TYPE_ICMP 0x3A
+#define IPV6_ICMP_TYPE_ECHO_REQUEST 128
+#define IPV6_ICMP_TYPE_ECHO_REPLY 129
+
+// IPv6 Header Offset
+#define IPV6_HEADER_VERSION_OFFSET 0
+#define IPV6_HEADER_PAYLOAD_LEN_OFFSET 4
+#define IPV6_HEADER_TYPE_OFFSET 6
+#define IPV6_HEADER_SRC_ADDRESS_OFFSET 8
+#define IPV6_HEADER_DST_ADDRESS_OFFSET 24
+#define IPV6_UDP_HEADER_SRC_PORT_OFFSET 40
+#define IPV6_UDP_HEADER_DST_PORT_OFFSET 42
+#define IPV6_ICMP_HEADER_CODE_OFFSET 40
+
+#define IPV6_GET_UINT16(pkt,idx) ( (static_cast<uint16_t>(pkt[idx]) << 8) + static_cast<uint16_t>(pkt[idx + 1] << 0) )
+
+//===================================================================
+
+static std::string
+string_printf(const char *fmt, ...)
+{
+ va_list args;
+ char c_str_buf[512];
+ va_start(args, fmt);
+ vsnprintf(c_str_buf, sizeof(c_str_buf), fmt, args);
+ va_end(args);
+ return std::string(c_str_buf);
+}
+
+static std::string
+log_level_to_string(int log_level)
+{
+ switch(log_level) {
+ case LOG_EMERG: return "emerg";
+ case LOG_ALERT: return "alert";
+ case LOG_CRIT: return "crit";
+ case LOG_ERR: return "err";
+ case LOG_WARNING: return "warning";
+ case LOG_NOTICE: return "notice";
+ case LOG_INFO: return "info";
+ case LOG_DEBUG: return "debug";
+ }
+ return string_printf("unknown(%d)", log_level);
+}
+
+// Converts a string to a log level, returns -1 if not a valid log level
+static int
+log_level_from_string(const char *log_string)
+{
+ int log_level = -1;
+
+ if (strcaseequal(log_string, "emerg")) {
+ log_level = LOG_EMERG;
+ } else if (strcaseequal(log_string, "alert")) {
+ log_level = LOG_ALERT;
+ } else if (strcaseequal(log_string, "crit")) {
+ log_level = LOG_CRIT;
+ } else if (strcaseequal(log_string, "err") || (strcaseequal(log_string, "error"))) {
+ log_level = LOG_ERR;
+ } else if (strcaseequal(log_string, "warning")) {
+ log_level = LOG_WARNING;
+ } else if (strcaseequal(log_string, "notice")) {
+ log_level = LOG_NOTICE;
+ } else if (strcaseequal(log_string, "info")) {
+ log_level = LOG_INFO;
+ } else if (strcaseequal(log_string, "debug")) {
+ log_level = LOG_DEBUG;
+ }
+
+ return log_level;
+}
+
+//-------------------------------------------------------------------
+// IPAddress
+
+void
+StatCollector::IPAddress::read_from(const uint8_t *arr)
+{
+ memcpy(static_cast<void *>(mAddressBuffer), arr, sizeof(mAddressBuffer));
+}
+
+std::string
+StatCollector::IPAddress::to_string(void) const
+{
+ char address_string[INET6_ADDRSTRLEN] = "::";
+ inet_ntop(AF_INET6, static_cast<const void *>(mAddressBuffer), address_string, sizeof(address_string));
+ return std::string(address_string);
+}
+
+bool
+StatCollector::IPAddress::operator==(const IPAddress& lhs) const
+{
+ // Since IPv6 addresses typically start with same prefix, we intentionally
+ // start the comparison from the end of address buffer
+ for(int indx = sizeof(mAddressBuffer)/sizeof(mAddressBuffer[0]) - 1; indx ; indx--) {
+ if (mAddressBuffer[indx] != lhs.mAddressBuffer[indx]) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+StatCollector::IPAddress::operator<(const IPAddress& lhs) const
+{
+ // Since IPv6 addresses typically start with same prefix, we intentionally
+ // start the comparison from the end of address buffer
+
+ for(int indx = sizeof(mAddressBuffer)/sizeof(mAddressBuffer[0]) - 1; indx ; indx--) {
+ if (mAddressBuffer[indx] < lhs.mAddressBuffer[indx]) {
+ return true;
+ }
+
+ if (mAddressBuffer[indx] > lhs.mAddressBuffer[indx]) {
+ return false;
+ }
+ }
+
+ // If all is equal, then return false.
+ return false;
+}
+
+//-------------------------------------------------------------------
+// EUI64Address
+
+void
+StatCollector::EUI64Address::read_from(const uint8_t *arr)
+{
+ mAddress[0] = arr[3] + (arr[2] << 8) + (arr[1] << 16) + (arr[0] << 24);
+ mAddress[1] = arr[7] + (arr[6] << 8) + (arr[5] << 16) + (arr[4] << 24);
+}
+
+std::string
+StatCollector::EUI64Address::to_string(void) const
+{
+ return string_printf("%08X%08X", mAddress[0], mAddress[1]);
+}
+
+bool
+StatCollector::EUI64Address::operator==(const EUI64Address& lhs) const
+{
+ return (mAddress[1] == lhs.mAddress[1]) && (mAddress[0] == lhs.mAddress[0]);
+}
+
+bool
+StatCollector::EUI64Address::operator<(const EUI64Address& lhs) const
+{
+ if (mAddress[1] < lhs.mAddress[1]) {
+ return true;
+ }
+
+ if (mAddress[1] > lhs.mAddress[1]) {
+ return false;
+ }
+
+ if (mAddress[0] < lhs.mAddress[0]) {
+ return true;
+ }
+
+ return false;
+}
+
+//-------------------------------------------------------------------
+// TimeStamp
+
+StatCollector::TimeStamp::TimeStamp()
+{
+ mTime = TIMESTAMP_UNINITIALIZED_VALUE;
+}
+
+void
+StatCollector::TimeStamp::set_to_now(void)
+{
+ mTime = time_ms();
+
+ if (mTime == TIMESTAMP_UNINITIALIZED_VALUE) {
+ mTime--;
+ }
+}
+
+void
+StatCollector::TimeStamp::clear(void)
+{
+ mTime = TIMESTAMP_UNINITIALIZED_VALUE;
+}
+
+cms_t
+StatCollector::TimeStamp::get_ms_till_now(void) const
+{
+ return CMS_SINCE(mTime);
+}
+
+bool
+StatCollector::TimeStamp::is_expired(void) const
+{
+ if (mTime == TIMESTAMP_UNINITIALIZED_VALUE) {
+ return true;
+ }
+
+ return (get_ms_till_now() < 0);
+}
+
+bool
+StatCollector::TimeStamp::is_uninitialized(void) const
+{
+ return (mTime == TIMESTAMP_UNINITIALIZED_VALUE);
+}
+
+bool
+StatCollector::TimeStamp::operator==(const TimeStamp &lhs)
+{
+ return mTime == lhs.mTime;
+}
+
+bool
+StatCollector::TimeStamp::operator<(const TimeStamp &lhs)
+{
+ return (mTime - lhs.mTime) < 0;
+}
+
+std::string
+StatCollector::TimeStamp::to_string(void) const
+{
+ int32_t days, hours, minutes, seconds, milliseconds;
+ cms_t ms_till_now = get_ms_till_now();
+
+ if (mTime == TIMESTAMP_UNINITIALIZED_VALUE)
+ return std::string("never");
+
+ if (ms_till_now < 0)
+ return std::string("long time (>24.86 days) ago");
+
+ days = ms_till_now / TIMESTAMP_ONE_DAY_IN_MS;
+ ms_till_now %= TIMESTAMP_ONE_DAY_IN_MS;
+ hours = ms_till_now / TIMESTAMP_ONE_HOUR_IN_MS;
+ ms_till_now %= TIMESTAMP_ONE_HOUR_IN_MS;
+ minutes = ms_till_now / TIMESTAMP_ONE_MIN_IN_MS;
+ ms_till_now %= TIMESTAMP_ONE_MIN_IN_MS;
+ seconds = ms_till_now / TIMESTAMP_ONE_SEC_IN_MS;
+ milliseconds = ms_till_now % TIMESTAMP_ONE_SEC_IN_MS;
+
+ if (days != 0) {
+ return string_printf("%2d day%s %02d:%02d:%02d.%03d ago", days, (days > 1)? "s" : "",
+ hours, minutes, seconds, milliseconds);
+ }
+
+ return string_printf("%02d:%02d:%02d.%03d ago", hours, minutes, seconds, milliseconds);
+}
+
+int32_t
+StatCollector::TimeStamp::time_difference_in_ms(TimeStamp t1, TimeStamp t2)
+{
+ return (t2.mTime - t1.mTime);
+}
+
+//-------------------------------------------------------------------
+// BytesTotal
+
+StatCollector::BytesTotal::BytesTotal()
+{
+ clear();
+}
+
+void
+StatCollector::BytesTotal::clear()
+{
+ mBytes = 0;
+ mKiloBytes = 0;
+}
+
+void
+StatCollector::BytesTotal::add(uint16_t count)
+{
+ uint32_t num_bytes;
+
+ num_bytes = count;
+ num_bytes += mBytes;
+
+ mKiloBytes += (num_bytes >> 10); // divide by 1024.
+ num_bytes &= 1023; // reminder
+ mBytes = static_cast<uint16_t>(num_bytes);
+}
+
+std::string
+StatCollector::BytesTotal::to_string() const
+{
+ if (mKiloBytes == 0) {
+ return string_printf("%d bytes", mBytes);
+ }
+
+ if (mBytes == 0) {
+ return string_printf("%d Kbytes", mKiloBytes);
+ }
+
+ return string_printf("%d Kbytes & %d bytes", mKiloBytes, mBytes);
+}
+
+//-------------------------------------------------------------------
+// PacketInfo
+
+bool
+StatCollector::PacketInfo::update_from_packet(const uint8_t *packet)
+{
+ bool ret = false;
+
+ // Check the version in IPv6 header
+ if ((packet[IPV6_HEADER_VERSION_OFFSET] & 0xF0) == 0x60) {
+
+ mTimeStamp.set_to_now();
+
+ mPayloadLen = IPV6_GET_UINT16(packet, IPV6_HEADER_PAYLOAD_LEN_OFFSET);
+
+ mType = packet[IPV6_HEADER_TYPE_OFFSET];
+
+ mSrcAddress.read_from(&packet[IPV6_HEADER_SRC_ADDRESS_OFFSET]);
+ mDstAddress.read_from(&packet[IPV6_HEADER_DST_ADDRESS_OFFSET]);
+
+ if (mType == IPV6_TYPE_ICMP) {
+ mSubtype = packet[IPV6_ICMP_HEADER_CODE_OFFSET];
+ } else {
+ mSubtype = 0;
+ }
+
+ if ((mType == IPV6_TYPE_UDP) || (mType == IPV6_TYPE_TCP)) {
+ mSrcPort = IPV6_GET_UINT16(packet, IPV6_UDP_HEADER_SRC_PORT_OFFSET);
+ mDstPort = IPV6_GET_UINT16(packet, IPV6_UDP_HEADER_DST_PORT_OFFSET);
+ } else {
+ mSrcPort = 0;
+ mDstPort = 0;
+ }
+
+ ret = true;
+ }
+
+ return ret;
+}
+
+std::string
+StatCollector::PacketInfo::to_string(void) const
+{
+ std::string type_str;
+ bool has_port;
+
+ has_port = false;
+ switch(mType) {
+ case IPV6_TYPE_TCP:
+ type_str = "TCP";
+ has_port = true;
+ break;
+
+ case IPV6_TYPE_UDP:
+ type_str = "UDP";
+ has_port = true;
+ break;
+
+ case IPV6_TYPE_ICMP:
+ switch(mSubtype) {
+ case IPV6_ICMP_TYPE_ECHO_REPLY:
+ type_str = "ICMP6(echo reply)";
+ break;
+ case IPV6_ICMP_TYPE_ECHO_REQUEST:
+ type_str = "ICMP6(echo request)";
+ break;
+ default:
+ type_str = string_printf("ICMP6(code:%d)", mSubtype);
+ break;
+ }
+ break;
+
+ default:
+ type_str = string_printf("0x%02x", mType);
+ break;
+ }
+
+ if (has_port) {
+ return string_printf(
+ "%s -> type:%s len:%d from:[%s]:%d to:[%s]:%d",
+ mTimeStamp.to_string().c_str(),
+ type_str.c_str(),
+ mPayloadLen,
+ mSrcAddress.to_string().c_str(), mSrcPort,
+ mDstAddress.to_string().c_str(), mDstPort
+ );
+ }
+
+ return string_printf(
+ "%s -> type:%s len:%d from:[%s] to:[%s]",
+ mTimeStamp.to_string().c_str(),
+ type_str.c_str(),
+ mPayloadLen,
+ mSrcAddress.to_string().c_str(),
+ mDstAddress.to_string().c_str()
+ );
+}
+
+//-------------------------------------------------------------------
+// NcpStateInfo
+
+void
+StatCollector::NcpStateInfo::update(NCPState new_state)
+{
+ mTimeStamp.set_to_now();
+ mNcpState = new_state;
+}
+
+std::string
+StatCollector::NcpStateInfo::to_string(void) const
+{
+ return
+ string_printf("%s -> %s",
+ mTimeStamp.to_string().c_str(),
+ ncp_state_to_string(mNcpState).c_str()
+ );
+}
+
+bool
+StatCollector::NcpStateInfo::is_expired(void) const
+{
+ return mTimeStamp.is_expired();
+}
+
+//------------------------------------------------------------------
+// ReadyForHostSleepState
+
+void
+StatCollector::ReadyForHostSleepState::update_with_blocking_sleep_time(TimeStamp blocking_sleep_time)
+{
+ mStartBlockingHostSleepTime = blocking_sleep_time;
+ mReadyForHostSleepTime.set_to_now();
+}
+
+std::string
+StatCollector::ReadyForHostSleepState::to_string(void) const
+{
+ if (mReadyForHostSleepTime.is_uninitialized() || mStartBlockingHostSleepTime.is_uninitialized()) {
+ return "Uninitialized";
+ }
+
+ return mStartBlockingHostSleepTime.to_string() + string_printf(" host sleep was blocked for %d ms",
+ TimeStamp::time_difference_in_ms(mStartBlockingHostSleepTime, mReadyForHostSleepTime));
+}
+
+//-------------------------------------------------------------------
+// Node Stat
+
+StatCollector::NodeStat::NodeStat():
+ mNodeInfoPool(), mNodeInfoMap()
+{
+ return;
+}
+
+void
+StatCollector::NodeStat::clear()
+{
+ mNodeInfoMap.clear();
+ mNodeInfoPool.free_all();
+}
+
+StatCollector::NodeStat::NodeInfo *
+StatCollector::NodeStat::find_node_info(const IPAddress& address)
+{
+ std::map<IPAddress, NodeInfo*>::iterator it = mNodeInfoMap.find(address);
+
+ if (it == mNodeInfoMap.end())
+ return NULL;
+
+ return it->second;
+}
+
+StatCollector::NodeStat::NodeInfo *
+StatCollector::NodeStat::create_new_node_info(const IPAddress& address)
+{
+ NodeInfo *node_info_ptr = NULL;
+
+ do {
+ node_info_ptr = mNodeInfoPool.alloc();
+
+ // If we can not allocate a new node info (all objects in the pool are used),
+ // we will remove oldest node info and try again.
+ if (!node_info_ptr) {
+ remove_oldest_node_info();
+ }
+ } while (!node_info_ptr);
+
+ node_info_ptr->clear();
+
+ mNodeInfoMap.insert(std::pair<IPAddress, NodeInfo*>(address, node_info_ptr));
+
+ return node_info_ptr;
+}
+
+void
+StatCollector::NodeStat::remove_oldest_node_info(void)
+{
+ std::map<IPAddress, NodeInfo*>::iterator cur_iter, oldest_iter;
+ TimeStamp ts, oldest_ts;
+
+ for (cur_iter = oldest_iter = mNodeInfoMap.begin(); cur_iter != mNodeInfoMap.end(); cur_iter++) {
+
+ ts = cur_iter->second->get_last_rx_or_tx_time();
+
+ if (oldest_ts.is_uninitialized()) {
+ oldest_ts = ts;
+ oldest_iter = cur_iter;
+ }
+
+ if (!ts.is_uninitialized()) {
+ if (ts < oldest_ts) {
+ oldest_ts = ts;
+ oldest_iter = cur_iter;
+ }
+ }
+ }
+
+ if (oldest_iter != mNodeInfoMap.end()) {
+ NodeInfo *node_info_ptr = oldest_iter->second;
+ mNodeInfoMap.erase(oldest_iter);
+ mNodeInfoPool.free(node_info_ptr);
+
+ syslog(LOG_INFO, "StatCollector: Out of NodeInfo objects --> Deleted the oldest NodeInfo");
+ }
+}
+
+void
+StatCollector::NodeStat::update_from_inbound_packet(const PacketInfo& packet_info)
+{
+ NodeInfo *node_info_ptr;
+
+ node_info_ptr = find_node_info(packet_info.mSrcAddress);
+ if (!node_info_ptr) {
+ node_info_ptr = create_new_node_info(packet_info.mSrcAddress);
+ }
+
+ if (node_info_ptr) {
+ node_info_ptr->mRxPacketsTotal++;
+ switch(packet_info.mType) {
+ case IPV6_TYPE_UDP: node_info_ptr->mRxPacketsUDP++; break;
+ case IPV6_TYPE_TCP: node_info_ptr->mRxPacketsTCP++; break;
+ }
+ node_info_ptr->mRxHistory.force_write(packet_info);
+ }
+}
+
+void
+StatCollector::NodeStat::update_from_outbound_packet(const PacketInfo& packet_info)
+{
+ NodeInfo *node_info_ptr;
+
+ node_info_ptr = find_node_info(packet_info.mDstAddress);
+ if (!node_info_ptr) {
+ node_info_ptr = create_new_node_info(packet_info.mDstAddress);
+ }
+
+ if (node_info_ptr) {
+ node_info_ptr->mTxPacketsTotal++;
+ switch(packet_info.mType) {
+ case IPV6_TYPE_UDP: node_info_ptr->mTxPacketsUDP++; break;
+ case IPV6_TYPE_TCP: node_info_ptr->mTxPacketsTCP++; break;
+ }
+ node_info_ptr->mTxHistory.force_write(packet_info);
+ }
+}
+
+void
+StatCollector::NodeStat::add_node_info_map_iter(StringList &output, const std::map<IPAddress, NodeInfo*>::const_iterator& it) const
+{
+ output.push_back("========================================================");
+ output.push_back("Address: " + it->first.to_string());
+ it->second->add_node_info(output);
+ output.push_back("");
+}
+
+void
+StatCollector::NodeStat::add_node_stat_history(StringList& output, std::string node_indicator) const
+{
+ std::map<IPAddress, NodeInfo*>::const_iterator it;
+
+ if (node_indicator.empty()) {
+ for (it = mNodeInfoMap.begin(); it != mNodeInfoMap.end(); it++) {
+ add_node_info_map_iter(output, it);
+ }
+ } else {
+ char c = node_indicator[0];
+ if (c == '@' || c == '[') { // Ip address mode
+ std::string ip_addr_str;
+ uint8_t ip_addr_buf[16];
+
+ if (c == '@') {
+ ip_addr_str = node_indicator.substr(1);
+ } else {
+ if (node_indicator[node_indicator.length() - 1] == ']') {
+ ip_addr_str = node_indicator.substr(1, node_indicator.length() - 2);
+ } else {
+ output.push_back(string_printf("Error : Missing \']\' in address format (\'%s\')", node_indicator.c_str()));
+ return;
+ }
+ }
+
+ if (inet_pton(AF_INET6, ip_addr_str.c_str(), ip_addr_buf) > 0) {
+ IPAddress ip_address;
+ ip_address.read_from(ip_addr_buf);
+ it = mNodeInfoMap.find(ip_address);
+ if (it != mNodeInfoMap.end()) {
+ add_node_info_map_iter(output, it);
+ } else {
+ output.push_back(string_printf("Error : Address does not exist (\'%s\')", node_indicator.c_str()));
+ }
+ } else {
+ output.push_back(string_printf("Error : Improper address format (\'%s\')", node_indicator.c_str()));
+ }
+ } else { // Index mode:
+ int index;
+ index = static_cast<int>(strtol(node_indicator.c_str(), NULL, 0));
+ if (index < mNodeInfoMap.size()) {
+ it = mNodeInfoMap.begin();
+ std::advance(it, index);
+ add_node_info_map_iter(output, it);
+ } else {
+ output.push_back(string_printf("Error: Out of bound index %d (\'%s\')", index, node_indicator.c_str()));
+ }
+ }
+ }
+}
+
+void
+StatCollector::NodeStat::add_node_stat(StringList& output) const
+{
+ std::map<IPAddress, NodeInfo*>::const_iterator it;
+
+ for (it = mNodeInfoMap.begin(); it != mNodeInfoMap.end(); it++) {
+ output.push_back("========================================================");
+ output.push_back("Address: " + it->first.to_string());
+ it->second->add_tx_stat(output);
+ it->second->add_rx_stat(output);
+ output.push_back("");
+ }
+}
+
+//-------------------------------------------------------------------
+// NodeStat::NodeInfo
+
+StatCollector::NodeStat::NodeInfo::NodeInfo()
+{
+ clear();
+}
+
+void
+StatCollector::NodeStat::NodeInfo::clear(void)
+{
+ mTxPacketsTotal = 0;
+ mTxPacketsUDP = 0;
+ mTxPacketsTCP = 0;
+
+ mRxPacketsTotal = 0;
+ mRxPacketsUDP = 0;
+ mRxPacketsTCP = 0;
+
+ mRxHistory.clear();
+ mTxHistory.clear();
+}
+
+StatCollector::TimeStamp
+StatCollector::NodeStat::NodeInfo::get_last_rx_time(void) const
+{
+ TimeStamp ts;
+ const PacketInfo *pkt_info_ptr;
+
+ pkt_info_ptr = mRxHistory.back();
+ if (pkt_info_ptr) {
+ ts = pkt_info_ptr->mTimeStamp;
+ }
+ return ts;
+}
+
+StatCollector::TimeStamp
+StatCollector::NodeStat::NodeInfo::get_last_tx_time(void) const
+{
+ TimeStamp ts;
+ const PacketInfo *pkt_info_ptr;
+
+ pkt_info_ptr = mTxHistory.back();
+ if (pkt_info_ptr) {
+ ts = pkt_info_ptr->mTimeStamp;
+ }
+ return ts;
+}
+
+StatCollector::TimeStamp
+StatCollector::NodeStat::NodeInfo::get_last_rx_or_tx_time(void) const
+{
+ TimeStamp rx_time = get_last_rx_time();
+ TimeStamp tx_time = get_last_tx_time();
+
+ // If either one is uninitialized, return the other one.
+ if (rx_time.is_uninitialized()) {
+ return tx_time;
+ }
+
+ if (tx_time.is_uninitialized()) {
+ return rx_time;
+ }
+
+ if (rx_time < tx_time) {
+ return tx_time;
+ }
+
+ return rx_time;
+}
+
+void
+StatCollector::NodeStat::NodeInfo::add_tx_stat(StringList& output, bool add_last_tx_time) const
+{
+ std::string str;
+
+ str = string_printf("%d packet%s (%d udp, %d tcp, %d other) %s sent to this address",
+ mTxPacketsTotal,
+ (mTxPacketsTotal == 1)? "" : "s",
+ mTxPacketsUDP,
+ mTxPacketsTCP,
+ mTxPacketsTotal - mTxPacketsUDP - mTxPacketsTCP,
+ (mTxPacketsTotal == 1)? "was" : "were"
+ );
+
+ if (add_last_tx_time) {
+ TimeStamp last_tx_time = get_last_tx_time();
+ if (!last_tx_time.is_uninitialized()) {
+ str += " - last tx happened " + last_tx_time.to_string();
+ }
+ }
+
+ output.push_back(str);
+}
+
+void
+StatCollector::NodeStat::NodeInfo::add_rx_stat(StringList& output, bool add_last_rx_time) const
+{
+ std::string str;
+
+ str = string_printf("%d packet%s (%d udp, %d tcp, %d other) %s received from this address",
+ mRxPacketsTotal,
+ (mRxPacketsTotal == 1)? "" : "s",
+ mRxPacketsUDP,
+ mRxPacketsTCP,
+ mRxPacketsTotal - mRxPacketsUDP - mRxPacketsTCP,
+ (mRxPacketsTotal == 1)? "was" : "were"
+ );
+
+ if (add_last_rx_time) {
+ TimeStamp last_rx_time = get_last_rx_time();
+ if (!last_rx_time.is_uninitialized()) {
+ str += " - last rx happened " + last_rx_time.to_string();
+ }
+ }
+
+ output.push_back(str);
+}
+
+void
+StatCollector::NodeStat::NodeInfo::add_node_info(StringList& output) const
+{
+ add_tx_stat(output, false);
+
+ if (!mTxHistory.empty()) {
+ RingBuffer<PacketInfo, STAT_COLLECTOR_PER_NODE_TX_HISTORY_SIZE>::ReverseIterator iter;
+
+ output.push_back(string_printf("\tLast %d tx packets", mTxHistory.size()));
+ for (iter = mTxHistory.rbegin(); iter != mTxHistory.rend(); ++iter) {
+ output.push_back("\t" + iter->to_string());
+ }
+ }
+ output.push_back("");
+
+ add_rx_stat(output, false);
+
+ if (!mRxHistory.empty()) {
+ RingBuffer<PacketInfo, STAT_COLLECTOR_PER_NODE_RX_HISTORY_SIZE>::ReverseIterator iter;
+
+ output.push_back(string_printf("\tLast %d rx packets", mRxHistory.size()));
+ for (iter = mRxHistory.rbegin(); iter != mRxHistory.rend(); ++iter) {
+ output.push_back("\t" + iter->to_string());
+ }
+ }
+}
+
+//-------------------------------------------------------------------
+// LinkStat:LinkQuality
+
+StatCollector::LinkStat::LinkQuality::LinkQuality()
+ : mTimeStamp()
+{
+ mRssi = 0;
+ mLinkQualityIncomingOutgoing = 0xff;
+}
+
+void
+StatCollector::LinkStat::LinkQuality::set(int8_t rssi, uint8_t incoming_link_quality, uint8_t outgoing_link_quality)
+{
+ mRssi = rssi;
+ mLinkQualityIncomingOutgoing = ((incoming_link_quality & 0x0f) << 4) + (outgoing_link_quality & 0x0f);
+ mTimeStamp.set_to_now();
+}
+
+StatCollector::TimeStamp
+StatCollector::LinkStat::LinkQuality::get_time_stamp(void) const
+{
+ return mTimeStamp;
+}
+
+uint8_t
+StatCollector::LinkStat::LinkQuality::get_incoming_link_quality(void) const
+{
+ return (mLinkQualityIncomingOutgoing >> 4);
+}
+
+uint8_t
+StatCollector::LinkStat::LinkQuality::get_outgoing_link_quality(void) const
+{
+ return (mLinkQualityIncomingOutgoing & 0x0f);
+}
+
+std::string
+StatCollector::LinkStat::LinkQuality::to_string(void) const
+{
+ if (mTimeStamp.is_uninitialized()) {
+ return "Uninitialized";
+ }
+
+ return mTimeStamp.to_string() + string_printf("-> RSSI: %-6d LinkQuality(Incoming/Outgoing): %d/%d", mRssi,
+ get_incoming_link_quality(), get_outgoing_link_quality());
+}
+
+//-------------------------------------------------------------------
+// LinkStat::LinkInfo
+
+StatCollector::LinkStat::LinkInfo::LinkInfo() :
+ mNodeType(), mLinkQualityHistory()
+{
+ clear();
+}
+
+void
+StatCollector::LinkStat::LinkInfo::clear(void)
+{
+ mLinkQualityHistory.clear();
+}
+
+bool
+StatCollector::LinkStat::LinkInfo::empty(void) const
+{
+ return mLinkQualityHistory.empty();
+}
+
+void
+StatCollector::LinkStat::LinkInfo::add_link_info(StringList& output, int count) const
+{
+ RingBuffer<LinkQuality, STAT_COLLECTOR_LINK_QUALITY_HISTORY_SIZE>::ReverseIterator iter;
+
+ if (count == 0) {
+ count = mLinkQualityHistory.size();
+ }
+
+ for (iter = mLinkQualityHistory.rbegin(); (iter != mLinkQualityHistory.rend()) && (count != 0); ++iter, --count) {
+ output.push_back("\t" + iter->to_string());
+ }
+}
+
+StatCollector::TimeStamp
+StatCollector::LinkStat::LinkInfo::get_last_update_time(void) const
+{
+ TimeStamp ts;
+ const LinkQuality *link_quality_ptr;
+
+ link_quality_ptr = mLinkQualityHistory.back();
+ if (link_quality_ptr) {
+ ts = link_quality_ptr->get_time_stamp();
+ }
+ return ts;
+}
+
+//-------------------------------------------------------------------
+// LinkStat
+
+StatCollector::LinkStat::LinkStat()
+ : mLinkInfoPool(), mLinkInfoMap()
+{
+}
+
+void
+StatCollector::LinkStat::clear(void)
+{
+ mLinkInfoMap.clear();
+ mLinkInfoPool.free_all();
+}
+
+
+StatCollector::LinkStat::LinkInfo *
+StatCollector::LinkStat::find_link_info(const EUI64Address& address)
+{
+ std::map<EUI64Address, LinkInfo *>::iterator it = mLinkInfoMap.find(address);
+
+ if (it == mLinkInfoMap.end())
+ return NULL;
+
+ return it->second;
+}
+
+StatCollector::LinkStat::LinkInfo *
+StatCollector::LinkStat::create_new_link_info(const EUI64Address& address)
+{
+ LinkInfo *link_info_ptr = NULL;
+
+ do {
+ link_info_ptr = mLinkInfoPool.alloc();
+
+ // If we can not allocate a new link info (all objects in the pool are used),
+ // we will remove oldest one in the map and try again.
+ if (!link_info_ptr) {
+ remove_oldest_link_info();
+ }
+ } while (!link_info_ptr);
+
+ link_info_ptr->clear();
+
+ mLinkInfoMap.insert(std::pair<EUI64Address, LinkInfo*>(address, link_info_ptr));
+
+ return link_info_ptr;
+}
+
+void
+StatCollector::LinkStat::remove_oldest_link_info(void)
+{
+ std::map<EUI64Address, LinkInfo*>::iterator cur_iter, oldest_iter;
+ TimeStamp ts, oldest_ts;
+
+ for (cur_iter = oldest_iter = mLinkInfoMap.begin(); cur_iter != mLinkInfoMap.end(); cur_iter++) {
+
+ ts = cur_iter->second->get_last_update_time();
+
+ if (oldest_ts.is_uninitialized()) {
+ oldest_ts = ts;
+ oldest_iter = cur_iter;
+ }
+
+ if (!ts.is_uninitialized()) {
+ if (ts < oldest_ts) {
+ oldest_ts = ts;
+ oldest_iter = cur_iter;
+ }
+ }
+ }
+
+ if (oldest_iter != mLinkInfoMap.end()) {
+ LinkInfo *link_info_ptr = oldest_iter->second;
+ mLinkInfoMap.erase(oldest_iter);
+ mLinkInfoPool.free(link_info_ptr);
+
+ syslog(LOG_INFO, "StatCollector: Out of LinkInfo objects --> Deleted the oldest LinkInfo");
+ }
+}
+
+void
+StatCollector::LinkStat::update(const uint8_t *eui64_address_arr, int8_t rssi,
+ uint8_t incoming_link_quality, uint8_t outgoing_link_quality,
+ NodeType node_type)
+{
+ LinkQuality link_quality;
+ EUI64Address address;
+ LinkInfo *link_info_ptr;
+
+ if (eui64_address_arr) {
+
+ address.read_from(eui64_address_arr);
+
+ link_quality.set(rssi, incoming_link_quality, outgoing_link_quality);
+
+ link_info_ptr = find_link_info(address);
+ if (!link_info_ptr) {
+ link_info_ptr = create_new_link_info(address);
+ }
+
+ if (link_info_ptr) {
+ link_info_ptr->mLinkQualityHistory.force_write(link_quality);
+ link_info_ptr->mNodeType = node_type;
+ }
+ }
+}
+
+void
+StatCollector::LinkStat::add_link_stat(StringList& output, int count) const
+{
+ std::map<EUI64Address, LinkInfo*>::const_iterator it;
+
+ for (it = mLinkInfoMap.begin(); it != mLinkInfoMap.end(); ++it) {
+ output.push_back("========================================================");
+ output.push_back("EUI64 address: " + it->first.to_string() + " - Node type: " +
+ node_type_to_string(it->second->mNodeType));
+ it->second->add_link_info(output, count);
+ output.push_back("");
+ }
+}
+
+//-------------------------------------------------------------------
+// StatCollector
+
+StatCollector::StatCollector() :
+ mTxBytesTotal(), mRxBytesTotal(),
+ mRxHistory(), mTxHistory(),
+ mLastBlockingHostSleepTime(),
+ mNodeStat(), mLinkStat(),
+ mAutoLogTimer(), mLinkStatTimer()
+{
+ mControlInterface = NULL;
+
+ mTxPacketsTotal = 0;
+ mRxPacketsTotal = 0;
+ mRxPacketsUDP = 0;
+ mRxPacketsTCP = 0;
+ mRxPacketsICMP = 0;
+ mTxPacketsUDP = 0;
+ mTxPacketsTCP = 0;
+ mTxPacketsICMP = 0;
+
+ mLastReadyForHostSleepState = true;
+
+ mUserRequestLogLevel = STAT_COLLECTOR_LOG_LEVEL_USER_REQUEST;
+ mAutoLogLevel = STAT_COLLECTOR_AUTO_LOG_DEFAULT_LOG_LEVEL;
+
+ mAutoLogState = kAutoLogShort;
+ mAutoLogPeriod = STAT_COLLECTOR_AUTO_LOG_PERIOD_IN_MIN * Timer::kOneMinute;
+ update_auto_log_timer();
+}
+
+StatCollector::~StatCollector()
+{
+ mAutoLogTimer.cancel();
+}
+
+void
+StatCollector::set_ncp_control_interface(NCPControlInterface *ncp_ctrl_interface)
+{
+ if (mControlInterface == ncp_ctrl_interface) {
+ return;
+ }
+
+ if (mControlInterface) {
+ mControlInterface->mOnPropertyChanged.disconnect(
+ boost::bind(&StatCollector::property_changed, this, _1, _2)
+ );
+
+ mControlInterface->mOnNetScanBeacon.disconnect(
+ boost::bind(&StatCollector::did_rx_net_scan_beacon, this, _1)
+ );
+ }
+
+ mControlInterface = ncp_ctrl_interface;
+
+ if (mControlInterface) {
+ mControlInterface->mOnPropertyChanged.connect(
+ boost::bind(&StatCollector::property_changed, this, _1, _2)
+ );
+
+ mControlInterface->mOnNetScanBeacon.connect(
+ boost::bind(&StatCollector::did_rx_net_scan_beacon, this, _1)
+ );
+ }
+}
+
+void
+StatCollector::record_inbound_packet(const uint8_t *packet)
+{
+ PacketInfo packet_info;
+
+ if (packet_info.update_from_packet(packet)) {
+ mRxPacketsTotal++;
+ switch (packet_info.mType) {
+ case IPV6_TYPE_UDP: mRxPacketsUDP++; break;
+ case IPV6_TYPE_TCP: mRxPacketsTCP++; break;
+ case IPV6_TYPE_ICMP: mRxPacketsICMP++; break;
+ }
+ mRxBytesTotal.add(packet_info.mPayloadLen);
+ mRxHistory.force_write(packet_info);
+
+ mNodeStat.update_from_inbound_packet(packet_info);
+ }
+}
+
+void
+StatCollector::record_outbound_packet(const uint8_t *packet)
+{
+ PacketInfo packet_info;
+
+ if (packet_info.update_from_packet(packet)) {
+ mTxPacketsTotal++;
+ switch (packet_info.mType) {
+ case IPV6_TYPE_UDP: mTxPacketsUDP++; break;
+ case IPV6_TYPE_TCP: mTxPacketsTCP++; break;
+ case IPV6_TYPE_ICMP: mTxPacketsICMP++; break;
+ }
+ mTxBytesTotal.add(packet_info.mPayloadLen);
+ mTxHistory.force_write(packet_info);
+
+ mNodeStat.update_from_outbound_packet(packet_info);
+ }
+}
+
+void
+StatCollector::record_ncp_state_change(NCPState new_ncp_state)
+{
+ NcpStateInfo ncp_state_info;
+ ncp_state_info.update(new_ncp_state);
+ mNCPStateHistory.force_write(ncp_state_info);
+}
+
+void
+StatCollector::record_ncp_ready_for_host_sleep_state(bool ready_for_sleep_state)
+{
+ ReadyForHostSleepState new_state;
+
+ if (mLastReadyForHostSleepState == ready_for_sleep_state) {
+ return;
+ }
+
+ if (ready_for_sleep_state) {
+ new_state.update_with_blocking_sleep_time(mLastBlockingHostSleepTime);
+
+ mReadyForSleepHistory.force_write(new_state);
+ } else {
+ mLastBlockingHostSleepTime.set_to_now();
+ }
+
+ mLastReadyForHostSleepState = ready_for_sleep_state;
+}
+
+void
+StatCollector::add_tx_history(StringList& output, int count) const
+{
+ if (count == 0) {
+ count = mTxHistory.size();
+ }
+
+ if (!mTxHistory.empty()) {
+ RingBuffer<PacketInfo, STAT_COLLECTOR_TX_HISTORY_SIZE>::ReverseIterator iter;
+
+ output.push_back("Tx History");
+ output.push_back("-------------------------");
+ for (iter = mTxHistory.rbegin(); (iter != mTxHistory.rend()) && (count != 0); ++iter, --count) {
+ output.push_back(iter->to_string());
+ }
+ } else {
+ output.push_back("Tx history is empty");
+ }
+}
+
+void
+StatCollector::add_rx_history(StringList& output, int count) const
+{
+ if (count == 0) {
+ count = mRxHistory.size();
+ }
+
+ if (!mRxHistory.empty()) {
+ RingBuffer<PacketInfo, STAT_COLLECTOR_RX_HISTORY_SIZE>::ReverseIterator iter;
+
+ output.push_back("Rx History");
+ output.push_back("-------------------------");
+ for (iter = mRxHistory.rbegin(); (iter != mRxHistory.rend()) && (count != 0); ++iter, --count) {
+ output.push_back(iter->to_string());
+ }
+ } else {
+ output.push_back("Rx history is empty");
+ }
+}
+
+void
+StatCollector::add_ncp_state_history(StringList& output, int count) const
+{
+ if (count == 0) {
+ count = mNCPStateHistory.size();
+ }
+
+ if(!mNCPStateHistory.empty()) {
+ RingBuffer<NcpStateInfo, STAT_COLLECTOR_NCP_STATE_HISTORY_SIZE>::ReverseIterator iter;
+
+ output.push_back("NCP State History");
+ output.push_back("-------------------------");
+ for (iter = mNCPStateHistory.rbegin(); (iter != mNCPStateHistory.rend()) && (count != 0); ++iter, --count) {
+ output.push_back(iter->to_string());
+ }
+ } else {
+ output.push_back("NCP state history is empty.");
+ }
+}
+
+void
+StatCollector::add_ncp_ready_for_host_sleep_state_history(StringList& output, int count) const
+{
+ if (count == 0) {
+ count = mReadyForSleepHistory.size();
+ }
+
+ if (!mReadyForSleepHistory.empty() || (mLastReadyForHostSleepState == false)) {
+ RingBuffer<ReadyForHostSleepState, STAT_COLLECTOR_NCP_READY_FOR_HOST_SLEEP_STATE_HISTORY_SIZE>::ReverseIterator iter;
+
+ output.push_back("\'NCP Ready For Host Sleep State\' History");
+ output.push_back("-------------------------");
+
+ if (mLastReadyForHostSleepState == false) {
+ output.push_back( mLastBlockingHostSleepTime.to_string() + " host sleep was blocked till now");
+ }
+
+ for (iter = mReadyForSleepHistory.rbegin(); (iter != mReadyForSleepHistory.rend()) && (count != 0); ++iter, --count) {
+ output.push_back(iter->to_string());
+ }
+ } else {
+ output.push_back("\'NCP Ready For Host Sleep State\' history is empty.");
+ }
+}
+
+void
+StatCollector::add_tx_stat(StringList& output) const
+{
+ output.push_back (
+ string_printf("Tx: %d packet%s (%d udp, %d tcp, %d icmp6) -- ",
+ mTxPacketsTotal, (mTxPacketsTotal == 1)? "" : "s",
+ mTxPacketsUDP,
+ mTxPacketsTCP,
+ mTxPacketsICMP
+ ) +
+ mTxBytesTotal.to_string()
+ );
+}
+
+void
+StatCollector::add_rx_stat(StringList& output) const
+{
+ output.push_back (
+ string_printf("Rx: %d packet%s (%d udp, %d tcp, %d icmp6) -- ",
+ mRxPacketsTotal, (mRxPacketsTotal == 1)? "" : "s",
+ mRxPacketsUDP,
+ mRxPacketsTCP,
+ mRxPacketsICMP
+ ) +
+ mRxBytesTotal.to_string()
+ );
+}
+
+void
+StatCollector::add_all_info(StringList& output, int count) const
+{
+ add_tx_stat(output);
+ add_tx_history(output, count);
+
+ output.push_back("");
+
+ add_rx_stat(output);
+ add_rx_history(output, count);
+
+ output.push_back("");
+
+ add_ncp_state_history(output, count);
+
+ output.push_back("");
+
+ if (count == 0) {
+ mNodeStat.add_node_stat_history(output);
+ } else {
+ mNodeStat.add_node_stat(output);
+ }
+
+ output.push_back("");
+ if (count == 0) {
+ mLinkStat.add_link_stat(output);
+ } else {
+ mLinkStat.add_link_stat(output, STAT_COLLECTOR_LINK_STAT_HISTORY_SIZE);
+ }
+}
+
+bool
+StatCollector::is_a_stat_property(const std::string& key)
+{
+ // Check for the prefix to match
+ return strncaseequal(key.c_str(), kWPANTUNDProperty_Stat_Prefix , sizeof(kWPANTUNDProperty_Stat_Prefix) - 1);
+}
+
+void
+StatCollector::add_help(StringList& output) const
+{
+ output.push_back("List of statistics properties");
+ output.push_back(string_printf("\t %-26s - RX statistics (all nodes)", kWPANTUNDProperty_StatRX));
+ output.push_back(string_printf("\t %-26s - TX statistics (all nodes)", kWPANTUNDProperty_StatTX));
+ output.push_back(string_printf("\t %-26s - RX packet info history (all nodes)", kWPANTUNDProperty_StatRXHistory));
+ output.push_back(string_printf("\t %-26s - TX packet info history (all nodes)", kWPANTUNDProperty_StatTXHistory));
+ output.push_back(string_printf("\t %-26s - Both RX & TX packet info history (all nodes)", kWPANTUNDProperty_StatHistory));
+ output.push_back(string_printf("\t %-26s - NCP state change history", kWPANTUNDProperty_StatNCP));
+ output.push_back(string_printf("\t %-26s - \'Blocking Host Sleep\' state change history", kWPANTUNDProperty_StatBlockingHostSleep));
+ output.push_back(string_printf("\t %-26s - List of nodes + RX/TX statistics per node", kWPANTUNDProperty_StatNode));
+ output.push_back(string_printf("\t %-26s - List of nodes + RX/TX statistics and packet history per node", kWPANTUNDProperty_StatNodeHistory));
+ output.push_back(string_printf("\t %-26s - List of nodes + RX/TX statistics and packet history for a specific node with given IP address", kWPANTUNDProperty_StatNodeHistoryID "[<ipv6>]"));
+ output.push_back(string_printf("\t %-26s - List of nodes + RX/TX statistics and packet history for a specific node with given index", kWPANTUNDProperty_StatNodeHistoryID "<index>"));
+ output.push_back(string_printf("\t %-26s - Peer link quality history - short version", kWPANTUNDProperty_StatLinkQualityShort));
+ output.push_back(string_printf("\t %-26s - Peer link quality history - long version", kWPANTUNDProperty_StatLinkQualityLong));
+ output.push_back(string_printf("\t %-26s - All info - short version", kWPANTUNDProperty_StatShort));
+ output.push_back(string_printf("\t %-26s - All info - long version", kWPANTUNDProperty_StatLong));
+ output.push_back(string_printf("\t "));
+ output.push_back(string_printf("\t %-26s - Peer link quality information - get only", kWPANTUNDProperty_StatLinkQuality));
+ output.push_back(string_printf("\t %-26s - Period interval (in seconds) for collecting peer link quality - get/set - zero to disable", kWPANTUNDProperty_StatLinkQualityPeriod));
+ output.push_back(string_printf("\t %-26s - AutoLog information - get only", kWPANTUNDProperty_StatAutoLog));
+ output.push_back(string_printf("\t %-26s - AutoLog state (\'disabled\',\'long\',\'short\'') - get/set", kWPANTUNDProperty_StatAutoLogState));
+ output.push_back(string_printf("\t %-26s - AutoLog period in minutes - get/set", kWPANTUNDProperty_StatAutoLogPeriod));
+ output.push_back(string_printf("\t %-26s - AutoLog log level - get/set", kWPANTUNDProperty_StatAutoLogLogLevel));
+ output.push_back(string_printf("\t %-26s - Log level for user requested logs - get/set", kWPANTUNDProperty_StatUserLogRequestLogLevel));
+ output.push_back(string_printf("\t %-26s : \'emerg\', \'alert\', \'crit\', \'err\', \'warning\', \'notice\', \'info\', \'debug\'","Valid log levels"));
+ output.push_back(string_printf("\t "));
+ output.push_back(string_printf("\t %-26s - Print this help", kWPANTUNDProperty_StatHelp));
+}
+
+int
+StatCollector::get_stat_property(const std::string& key, StringList& output) const
+{
+ int return_status = kWPANTUNDStatus_Ok;
+
+ if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatShort)) {
+ add_all_info(output, STAT_COLLECTOR_SHORT_HISTORY_COUNT);
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatLong)) {
+ add_all_info(output);
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatRX)) {
+ add_rx_stat(output);
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatTX)) {
+ add_tx_stat(output);
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatRXHistory)) {
+ add_rx_stat(output);
+ add_rx_history(output);
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatTXHistory)) {
+ add_tx_stat(output);
+ add_tx_history(output);
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatHistory)) {
+ add_rx_history(output);
+ output.push_back("");
+ add_tx_history(output);
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatNCP)) {
+ add_ncp_state_history(output);
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatBlockingHostSleep)) {
+ add_ncp_ready_for_host_sleep_state_history(output);
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatNode)) {
+ mNodeStat.add_node_stat(output);
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatNodeHistory)) {
+ mNodeStat.add_node_stat_history(output);
+ } else if (strncaseequal(key.c_str(), kWPANTUNDProperty_StatNodeHistoryID, sizeof(kWPANTUNDProperty_StatNodeHistoryID) - 1)) {
+ mNodeStat.add_node_stat_history(output, key.substr(sizeof(kWPANTUNDProperty_StatNodeHistoryID) - 1));
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatLinkQualityLong)) {
+ mLinkStat.add_link_stat(output);
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatLinkQualityShort)) {
+ mLinkStat.add_link_stat(output, STAT_COLLECTOR_LINK_STAT_HISTORY_SIZE);
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatHelp)) {
+ add_help(output);
+ } else {
+ output.push_back(std::string("Unknown/unsupported stat property. Please use \"get ") + kWPANTUNDProperty_StatHelp +
+ "\" to get list of supported properties by statistics collector." );
+ return_status = kWPANTUNDStatus_PropertyNotFound;
+ }
+
+ return return_status;
+}
+
+void
+StatCollector::get_property(const std::string& key, CallbackWithStatusArg1 cb)
+{
+ // First check for AutoLog properties.
+ if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatAutoLog)) {
+ std::string str;
+ switch(mAutoLogState) {
+ case kAutoLogDisabled:
+ str = "Auto stat log is disabled.";
+ break;
+
+ case kAutoLogLong:
+ str = string_printf("Auto stat log is enabled using long version every %d min at log level \'%s\'.",
+ mAutoLogPeriod / Timer::kOneMinute, log_level_to_string(mAutoLogLevel).c_str());
+ break;
+
+ case kAutoLogShort:
+ str = string_printf("Auto stat log is enabled using short version of stat every %d min at log level \'%s\'.",
+ mAutoLogPeriod / Timer::kOneMinute, log_level_to_string(mAutoLogLevel).c_str());
+ break;
+ }
+ cb(kWPANTUNDStatus_Ok, boost::any(str));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatAutoLogState)) {
+ std::string state;
+
+ switch (mAutoLogState) {
+ case kAutoLogDisabled: state = kWPANTUNDStatAutoLogState_Disabled; break;
+ case kAutoLogShort: state = kWPANTUNDStatAutoLogState_Short; break;
+ case kAutoLogLong: state = kWPANTUNDStatAutoLogState_Long; break;
+ }
+ cb(kWPANTUNDStatus_Ok, boost::any(state));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatAutoLogPeriod)) {
+ int period_in_min = mAutoLogPeriod / Timer::kOneMinute;
+ cb(kWPANTUNDStatus_Ok, boost::any(period_in_min));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatAutoLogLogLevel)) {
+ cb(kWPANTUNDStatus_Ok, boost::any(log_level_to_string(mAutoLogLevel)));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatUserLogRequestLogLevel)) {
+ cb(kWPANTUNDStatus_Ok, boost::any(log_level_to_string(mUserRequestLogLevel)));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatLinkQuality)) {
+ int period_in_sec = static_cast<int>(mLinkStatTimer.get_interval() / Timer::kOneSecond);
+ std::string str;
+
+ if (period_in_sec == 0) {
+ str = "Periodic query of peer link quality is disabled";
+ } else {
+ str = string_printf("Peer link quality is collected every %d second%s",
+ period_in_sec, (period_in_sec == 1)? "" : "s");
+ }
+ cb(kWPANTUNDStatus_Ok, boost::any(str));
+
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatLinkQualityPeriod)) {
+ int period_in_sec = static_cast<int>(mLinkStatTimer.get_interval() / Timer::kOneSecond);
+ cb(kWPANTUNDStatus_Ok, boost::any(period_in_sec));
+
+ } else {
+ // If not an AutoLog property, check for the stat properties.
+ StringList output;
+ int status = get_stat_property(key, output);
+
+ if (status == kWPANTUNDStatus_Ok) {
+ cb(status, boost::any(output));
+ } else {
+ std::string err_str;
+ err_str = std::string("Unknown stat property. Please use \"get ") + kWPANTUNDProperty_StatHelp
+ + "\" to get help about StatCollector.";
+ cb(status, boost::any(err_str));
+ }
+ }
+}
+
+void
+StatCollector::set_property(const std::string& key, const boost::any& value, CallbackWithStatus cb)
+{
+ int status = kWPANTUNDStatus_Ok;
+
+ // First check for AutoLog properties.
+ if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatAutoLogState)) {
+ std::string new_state_str = any_to_string(value);
+ AutoLogState new_state;
+
+ if (strcaseequal(new_state_str.c_str(), kWPANTUNDStatAutoLogState_Disabled) ||
+ strcaseequal(new_state_str.c_str(), "off") ||
+ strcaseequal(new_state_str.c_str(), "no") ||
+ strcaseequal(new_state_str.c_str(), "0") )
+ {
+ new_state = kAutoLogDisabled;
+ } else if (
+ strcaseequal(new_state_str.c_str(), kWPANTUNDStatAutoLogState_Short) ||
+ strcaseequal(new_state_str.c_str(), "on") ||
+ strcaseequal(new_state_str.c_str(), "yes") ||
+ strcaseequal(new_state_str.c_str(), "1") )
+ {
+ new_state = kAutoLogShort;
+ } else if (strcaseequal(new_state_str.c_str(), kWPANTUNDStatAutoLogState_Long)) {
+ new_state = kAutoLogLong;
+ } else {
+ status = kWPANTUNDStatus_InvalidArgument;
+ }
+
+ if (status == kWPANTUNDStatus_Ok) {
+ if (new_state != mAutoLogState) {
+ mAutoLogState = new_state;
+ update_auto_log_timer();
+ }
+ }
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatAutoLogPeriod)) {
+ int period_in_min = any_to_int(value);
+ if ((period_in_min > 0) && (period_in_min <= STAT_COLLECTOR_AUTO_LOG_MAX_PERIOD)) {
+ mAutoLogPeriod = period_in_min * Timer::kOneMinute;
+ update_auto_log_timer();
+ } else {
+ status = kWPANTUNDStatus_InvalidArgument;
+ }
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatAutoLogLogLevel)) {
+ int log_level = log_level_from_string(any_to_string(value).c_str());
+ if (log_level >= 0) {
+ status = kWPANTUNDStatus_Ok;
+ mAutoLogLevel = log_level;
+ } else {
+ status = kWPANTUNDStatus_InvalidArgument;
+ }
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatUserLogRequestLogLevel)) {
+ int log_level = log_level_from_string(any_to_string(value).c_str());
+ if (log_level >= 0) {
+ status = kWPANTUNDStatus_Ok;
+ mUserRequestLogLevel = log_level;
+ } else {
+ status = kWPANTUNDStatus_InvalidArgument;
+ }
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_StatLinkQualityPeriod)) {
+ int period_in_sec = any_to_int(value);
+ if (period_in_sec >= 0) {
+ update_link_stat_timer(period_in_sec * Timer::kOneSecond);
+ }
+ } else {
+ StringList output;
+
+ status = get_stat_property(key, output);
+
+ if (status == kWPANTUNDStatus_Ok) {
+ for(StringList::iterator it = output.begin(); it != output.end(); ++it) {
+ syslog(mUserRequestLogLevel, "Stat: %s", it->c_str());
+ }
+ }
+ }
+
+ cb(status);
+}
+
+void
+StatCollector::update_auto_log_timer(void)
+{
+ if (mAutoLogState == kAutoLogDisabled) {
+ mAutoLogTimer.cancel();
+ } else {
+ mAutoLogTimer.schedule(
+ mAutoLogPeriod,
+ boost::bind(&StatCollector::auto_log_timer_did_fire, this),
+ Timer::kPeriodicFixedDelay
+ );
+
+ // Invoke the callback directly for the first iteration
+ auto_log_timer_did_fire();
+ }
+}
+
+void
+StatCollector::auto_log_timer_did_fire(void)
+{
+ StringList output;
+ int status = kWPANTUNDStatus_Canceled;
+
+ switch (mAutoLogState) {
+ case kAutoLogDisabled:
+ mAutoLogTimer.cancel();
+ break;
+
+ case kAutoLogLong:
+ status = get_stat_property(kWPANTUNDProperty_StatLong, output);
+ break;
+
+ case kAutoLogShort:
+ status = get_stat_property(kWPANTUNDProperty_StatShort, output);
+ break;
+ }
+
+ if (status == kWPANTUNDStatus_Ok) {
+ for(StringList::iterator it = output.begin(); it != output.end(); ++it) {
+ syslog(mAutoLogLevel, "Stat (autolog): %s", it->c_str());
+ }
+ }
+}
+
+void
+StatCollector::update_link_stat_timer(Timer::Interval interval)
+{
+ if (interval == 0) {
+ mLinkStatTimer.cancel();
+ } else {
+ mLinkStatTimer.schedule(
+ interval,
+ boost::bind(&StatCollector::link_stat_timer_did_fire, this),
+ Timer::kPeriodicFixedDelay
+ );
+
+ // Invoke the callback directly for the first iteration
+ link_stat_timer_did_fire();
+ }
+}
+
+void
+StatCollector::link_stat_timer_did_fire(void)
+{
+}
+
+void
+StatCollector::did_get_rip_entry_value_map(int status, const boost::any& value)
+{
+ if (status == kWPANTUNDStatus_Ok) {
+ if (value.type() == typeid(std::list<ValueMap>)) {
+ std::list<ValueMap> rip_entry_list;
+ std::list<ValueMap>::const_iterator it;
+
+ rip_entry_list = boost::any_cast< std::list<ValueMap> >(value);
+
+ for (it = rip_entry_list.begin(); it != rip_entry_list.end(); ++it) {
+ record_rip_entry(*it);
+ }
+ }
+ }
+}
+
+int
+StatCollector::record_rip_entry(const ValueMap& rip_entry)
+{
+ ValueMap::const_iterator it;
+ Data eui64;
+ int8_t rssi = 0;
+ uint8_t in_lqi = 0;
+ uint8_t out_lqi = 0;
+ NodeType node_type = UNKNOWN;
+
+
+ mLinkStat.update(eui64.data(), rssi, in_lqi, out_lqi, node_type);
+
+ return kWPANTUNDStatus_Ok;
+}
+
+void
+StatCollector::property_changed(const std::string& key, const boost::any& value)
+{
+ if (strcaseequal(key.c_str(), kWPANTUNDProperty_NCPState)) {
+ record_ncp_state_change(string_to_ncp_state(any_to_string(value)));
+ } else if (strcaseequal(key.c_str(), kWPANTUNDProperty_DaemonReadyForHostSleep)) {
+ record_ncp_ready_for_host_sleep_state(any_to_bool(value));
+ }
+}
+
+void
+StatCollector::did_rx_net_scan_beacon(const WPAN::NetworkInstance& network)
+{
+ // Log the scan result
+ syslog(LOG_NOTICE,
+ "Scan -> "
+ "Name:%-17s, "
+ "PanId:0x%04X, "
+ "Ch:%2d, "
+ "Joinable:%-3s, "
+ "XPanId:0x%02X%02X%02X%02X%02X%02X%02X%02X, "
+ "HwAddr:0x%02X%02X%02X%02X%02X%02X%02X%02X, "
+ "RSSI:%-4d, "
+ "LQI:%-3d, "
+ "ProtoId:%-3d, "
+ "Version:%2d, "
+ "ShortAddr:0x%04X ",
+
+ network.name.c_str(),
+ network.panid,
+ network.channel,
+ network.joinable? "YES" : "NO",
+ network.xpanid[0], network.xpanid[1], network.xpanid[2], network.xpanid[3],
+ network.xpanid[4], network.xpanid[5], network.xpanid[6], network.xpanid[7],
+ network.hwaddr[0], network.hwaddr[1], network.hwaddr[2], network.hwaddr[3],
+ network.hwaddr[4], network.hwaddr[5], network.hwaddr[6], network.xpanid[7],
+ network.rssi,
+ network.lqi,
+ network.type,
+ network.version,
+ network.saddr
+ );
+}
diff --git a/src/wpantund/StatCollector.h b/src/wpantund/StatCollector.h
new file mode 100644
index 0000000..ce5e4bb
--- /dev/null
+++ b/src/wpantund/StatCollector.h
@@ -0,0 +1,332 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * Declaration of Statistics collector module
+ *
+ */
+
+#ifndef wpantund_StatCollector_h
+#define wpantund_StatCollector_h
+
+#include <stdint.h>
+#include <string>
+#include <list>
+#include <map>
+#include "time-utils.h"
+#include "RingBuffer.h"
+#include "ObjectPool.h"
+#include "NCPControlInterface.h"
+#include "NCPTypes.h"
+#include "Timer.h"
+#include "ValueMap.h"
+
+namespace nl {
+namespace wpantund {
+
+// Size of the rx/tx history (for all nodes)
+#define STAT_COLLECTOR_RX_HISTORY_SIZE 64
+#define STAT_COLLECTOR_TX_HISTORY_SIZE 64
+
+// Size of the NCP state history
+#define STAT_COLLECTOR_NCP_STATE_HISTORY_SIZE 64
+
+// Size of the NCP "ReadyForHostSleep" state history
+#define STAT_COLLECTOR_NCP_READY_FOR_HOST_SLEEP_STATE_HISTORY_SIZE 64
+
+// Max number of nodes to track at the same time (nodes are tracked by IP address)
+#define STAT_COLLECTOR_MAX_NODES 64
+
+// Size of rx/tx history per node
+#define STAT_COLLECTOR_PER_NODE_RX_HISTORY_SIZE 5
+#define STAT_COLLECTOR_PER_NODE_TX_HISTORY_SIZE 5
+
+// Maximm number of peer nodes for which we store link quality
+#define STAT_COLLECTOR_MAX_LINKS 64
+
+// History length of link quality info per peer
+#define STAT_COLLECTOR_LINK_QUALITY_HISTORY_SIZE 40
+
+class StatCollector
+{
+public:
+ StatCollector();
+ virtual ~StatCollector();
+
+ void set_ncp_control_interface(NCPControlInterface *ncp_ctrl_interface);
+
+ // Static class methods
+
+ static bool is_a_stat_property(const std::string& key); // returns true if the property key is associated with stat module
+
+ void get_property(const std::string& key, CallbackWithStatusArg1 cb);
+ void set_property(const std::string& key, const boost::any& value, CallbackWithStatus cb);
+
+ // Methods to inform StatCollector about received/sent packets and state changes
+ void record_inbound_packet(const uint8_t *ipv6_packet);
+ void record_outbound_packet(const uint8_t *ipv6_packet);
+
+private:
+ // Internal types and data structures
+
+ typedef std::list<std::string> StringList;
+
+ struct IPAddress
+ {
+ std::string to_string(void) const;
+ void read_from(const uint8_t *arr);
+ bool operator==(const IPAddress& lhs) const;
+ bool operator<(const IPAddress& lhs) const;
+ private:
+ uint32_t mAddressBuffer[4];
+ };
+
+ struct EUI64Address
+ {
+ std::string to_string(void) const;
+ void read_from(const uint8_t *arr);
+
+ bool operator==(const EUI64Address& lhs) const;
+ bool operator<(const EUI64Address& lhs) const;
+ private:
+ uint32_t mAddress[2];
+ };
+
+ struct TimeStamp
+ {
+ TimeStamp();
+ void set_to_now(void);
+ void clear(void);
+ cms_t get_ms_till_now(void) const;
+ bool is_expired(void) const;
+ bool is_uninitialized(void) const;
+ std::string to_string(void) const;
+ bool operator==(const TimeStamp& lhs);
+ bool operator<(const TimeStamp& lhs);
+
+ static int32_t time_difference_in_ms(TimeStamp t1, TimeStamp t2);
+
+ private:
+ cms_t mTime;
+ };
+
+ struct PacketInfo
+ {
+ TimeStamp mTimeStamp;
+ uint16_t mPayloadLen;
+ uint8_t mType;
+ uint8_t mSubtype;
+ uint16_t mSrcPort;
+ uint16_t mDstPort;
+ IPAddress mSrcAddress;
+ IPAddress mDstAddress;
+
+ bool update_from_packet(const uint8_t *ipv6_packet);
+ std::string to_string(void) const;
+ };
+
+ struct BytesTotal
+ {
+ public:
+ BytesTotal();
+ void add(uint16_t bytes);
+ void clear(void);
+ std::string to_string(void) const;
+ private:
+ uint16_t mBytes; // Number of bytes remaining till next Kilo bytes (1024 bytes)
+ uint32_t mKiloBytes; // Can go up to 2^32 KB which is 4.3 terabytes (> 4 years of continuous exchange at 250 kbps)
+ };
+
+ struct NcpStateInfo
+ {
+ public:
+ void update(NCPState new_state);
+ std::string to_string(void) const;
+ bool is_expired(void) const;
+ private:
+ NCPState mNcpState;
+ TimeStamp mTimeStamp;
+ };
+
+ struct ReadyForHostSleepState
+ {
+ public:
+ void update_with_blocking_sleep_time(TimeStamp blocking_sleep_time);
+ std::string to_string(void) const;
+ private:
+ TimeStamp mStartBlockingHostSleepTime;
+ TimeStamp mReadyForHostSleepTime;
+ };
+
+ class NodeStat
+ {
+ public:
+ struct NodeInfo
+ {
+ public:
+ uint32_t mTxPacketsTotal;
+ uint32_t mTxPacketsUDP;
+ uint32_t mTxPacketsTCP;
+
+ uint32_t mRxPacketsTotal;
+ uint32_t mRxPacketsUDP;
+ uint32_t mRxPacketsTCP;
+
+ RingBuffer<PacketInfo, STAT_COLLECTOR_PER_NODE_RX_HISTORY_SIZE> mRxHistory;
+ RingBuffer<PacketInfo, STAT_COLLECTOR_PER_NODE_TX_HISTORY_SIZE> mTxHistory;
+
+ NodeInfo();
+ void clear();
+ TimeStamp get_last_rx_time(void) const;
+ TimeStamp get_last_tx_time(void) const;
+ TimeStamp get_last_rx_or_tx_time(void) const;
+ void add_rx_stat(StringList& output, bool add_last_rx_time = true) const;
+ void add_tx_stat(StringList& output, bool add_last_tx_time = true) const;
+ void add_node_info(StringList& output) const;
+ };
+
+ NodeStat();
+ void clear(void);
+ void update_from_inbound_packet(const PacketInfo& packet_info);
+ void update_from_outbound_packet(const PacketInfo& packet_info);
+ void add_node_stat(StringList& output) const;
+ void add_node_stat_history(StringList& output, std::string node_indicator = "") const;
+
+ private:
+ NodeInfo *find_node_info(const IPAddress& address);
+ NodeInfo *create_new_node_info(const IPAddress& address);
+ void remove_oldest_node_info(void);
+ void add_node_info_map_iter(StringList &output, const std::map<IPAddress, NodeInfo*>::const_iterator& it) const;
+
+ ObjectPool<NodeInfo, STAT_COLLECTOR_MAX_NODES> mNodeInfoPool;
+ std::map<IPAddress, NodeInfo*> mNodeInfoMap;
+ };
+
+ class LinkStat
+ {
+ public:
+ struct LinkQuality
+ {
+ LinkQuality();
+ void set(int8_t rssi, uint8_t incoming_link_quality, uint8_t outgoing_link_quality);
+ std::string to_string(void) const;
+ TimeStamp get_time_stamp(void) const;
+ private:
+ uint8_t get_incoming_link_quality(void) const;
+ uint8_t get_outgoing_link_quality(void) const;
+
+ int8_t mRssi;
+ uint8_t mLinkQualityIncomingOutgoing; // High 4 bits are for incoming, low 4 bits are for outgoing
+ TimeStamp mTimeStamp;
+ };
+
+ struct LinkInfo
+ {
+ NodeType mNodeType;
+ RingBuffer<LinkQuality, STAT_COLLECTOR_LINK_QUALITY_HISTORY_SIZE> mLinkQualityHistory;
+
+ LinkInfo();
+ void clear(void);
+ bool empty(void) const;
+ void add_link_info(StringList& output, int count = 0) const;
+ TimeStamp get_last_update_time(void) const;
+ };
+
+ LinkStat();
+ void clear();
+ void update(const uint8_t *eui64_address, int8_t rssi, uint8_t incoming_link_quality, uint8_t outgoing_link_quality,
+ NodeType node_type);
+ void add_link_stat(StringList& output, int count = 0) const;
+
+ private:
+ LinkInfo *find_link_info(const EUI64Address& address);
+ LinkInfo *create_new_link_info(const EUI64Address & address);
+ void remove_oldest_link_info(void);
+
+ ObjectPool<LinkInfo, STAT_COLLECTOR_MAX_LINKS> mLinkInfoPool;
+ std::map<EUI64Address, LinkInfo *> mLinkInfoMap;
+ };
+
+ enum AutoLogState
+ {
+ kAutoLogDisabled,
+ kAutoLogLong,
+ kAutoLogShort
+ };
+
+private:
+ void record_ncp_state_change(NCPState new_ncp_state);
+ void record_ncp_ready_for_host_sleep_state(bool ready_to_sleep);
+ void add_tx_stat(StringList& output) const;
+ void add_rx_stat(StringList& output) const;
+ void add_rx_history(StringList& output, int count = 0) const;
+ void add_tx_history(StringList& output, int count = 0) const;
+ void add_ncp_state_history(StringList& output, int count = 0) const;
+ void add_ncp_ready_for_host_sleep_state_history(StringList& output, int count = 0) const;
+ void add_help(StringList& output) const;
+ void add_all_info(StringList& output, int count = 0) const;
+ int get_stat_property(const std::string& key, StringList& output) const;
+ void update_auto_log_timer(void);
+ void auto_log_timer_did_fire(void);
+ void update_link_stat_timer(Timer::Interval interval);
+ void link_stat_timer_did_fire(void);
+ void did_get_rip_entry_value_map(int status, const boost::any& value);
+ int record_rip_entry(const ValueMap& rip_entry);
+ void property_changed(const std::string& key, const boost::any& value);
+ void did_rx_net_scan_beacon(const WPAN::NetworkInstance& network);
+
+private:
+ NCPControlInterface *mControlInterface;
+
+ uint32_t mTxPacketsTotal;
+ uint32_t mRxPacketsUDP;
+ uint32_t mRxPacketsTCP;
+ uint32_t mRxPacketsICMP;
+ BytesTotal mTxBytesTotal;
+
+ uint32_t mRxPacketsTotal;
+ uint32_t mTxPacketsUDP;
+ uint32_t mTxPacketsTCP;
+ uint32_t mTxPacketsICMP;
+ BytesTotal mRxBytesTotal;
+
+ RingBuffer<PacketInfo, STAT_COLLECTOR_RX_HISTORY_SIZE> mRxHistory;
+ RingBuffer<PacketInfo, STAT_COLLECTOR_TX_HISTORY_SIZE> mTxHistory;
+
+ RingBuffer<NcpStateInfo, STAT_COLLECTOR_NCP_STATE_HISTORY_SIZE> mNCPStateHistory;
+
+ RingBuffer<ReadyForHostSleepState, STAT_COLLECTOR_NCP_READY_FOR_HOST_SLEEP_STATE_HISTORY_SIZE> mReadyForSleepHistory;
+ bool mLastReadyForHostSleepState;
+ TimeStamp mLastBlockingHostSleepTime;
+
+ NodeStat mNodeStat;
+ LinkStat mLinkStat;
+
+ Timer mAutoLogTimer;
+ Timer mLinkStatTimer;
+
+ Timer::Interval mAutoLogPeriod;
+ enum AutoLogState mAutoLogState;
+
+ int mAutoLogLevel;
+ int mUserRequestLogLevel;
+};
+
+}; // namespace wpantund
+}; // namespace nl
+
+#endif // defined(wpantund_StatCollector_h)
diff --git a/src/wpantund/wpan-error.h b/src/wpantund/wpan-error.h
new file mode 100644
index 0000000..922bc14
--- /dev/null
+++ b/src/wpantund/wpan-error.h
@@ -0,0 +1,78 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef wpantund_wpan_error_h
+#define wpantund_wpan_error_h
+#include <stddef.h>
+
+__BEGIN_DECLS
+
+typedef enum {
+ kWPANTUNDStatus_Ok = 0,
+ kWPANTUNDStatus_Failure = 1,
+
+ kWPANTUNDStatus_InvalidArgument = 2,
+ kWPANTUNDStatus_InvalidWhenDisabled = 3,
+ kWPANTUNDStatus_InvalidForCurrentState = 4,
+ kWPANTUNDStatus_InvalidType = 5,
+ kWPANTUNDStatus_InvalidRange = 6,
+
+ kWPANTUNDStatus_Timeout = 7,
+ kWPANTUNDStatus_SocketReset = 8,
+ kWPANTUNDStatus_Busy = 9,
+
+ kWPANTUNDStatus_Already = 10,
+ kWPANTUNDStatus_Canceled = 11,
+ kWPANTUNDStatus_InProgress = 12,
+ kWPANTUNDStatus_TryAgainLater = 13,
+
+ kWPANTUNDStatus_FeatureNotSupported = 14,
+ kWPANTUNDStatus_FeatureNotImplemented = 15,
+
+ kWPANTUNDStatus_PropertyNotFound = 16,
+ kWPANTUNDStatus_PropertyEmpty = 17,
+
+ kWPANTUNDStatus_JoinFailedUnknown = 18,
+ kWPANTUNDStatus_JoinFailedAtScan = 19,
+ kWPANTUNDStatus_JoinFailedAtAuthenticate = 20,
+ kWPANTUNDStatus_FormFailedAtScan = 21,
+
+ kWPANTUNDStatus_NCP_Crashed = 22,
+ kWPANTUNDStatus_NCP_Fatal = 23,
+ kWPANTUNDStatus_NCP_InvalidArgument = 24,
+ kWPANTUNDStatus_NCP_InvalidRange = 25,
+
+ kWPANTUNDStatus_MissingXPANID = 26,
+
+ kWPANTUNDStatus_NCP_Reset = 27,
+
+ kWPANTUNDStatus_InterfaceNotFound = 28,
+
+ kWPANTUNDStatus_NCPError_First = 0xEA0000,
+ kWPANTUNDStatus_NCPError_Last = 0xEAFFFF,
+} wpantund_status_t;
+
+#define WPANTUND_NCPERROR_MASK 0xFFFF
+
+#define WPANTUND_STATUS_IS_NCPERROR(x) ((((int)x)&~WPANTUND_NCPERROR_MASK) == kWPANTUNDStatus_NCPError_First)
+#define WPANTUND_NCPERROR_TO_STATUS(x) (wpantund_status_t)((((int)x)&WPANTUND_NCPERROR_MASK)|kWPANTUNDStatus_NCPError_First)
+#define WPANTUND_STATUS_TO_NCPERROR(x) ((x)&WPANTUND_NCPERROR_MASK)
+
+__END_DECLS
+
+#endif
diff --git a/src/wpantund/wpan-properties.h b/src/wpantund/wpan-properties.h
new file mode 100644
index 0000000..0086cee
--- /dev/null
+++ b/src/wpantund/wpan-properties.h
@@ -0,0 +1,201 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * This file contains the enumeration of the properties that can be
+ * gotten or set via the "get_prop()" and "set_prop()" methods.
+ *
+ */
+
+#ifndef wpantund_wpan_properties_h
+#define wpantund_wpan_properties_h
+
+
+#define kWPANTUNDProperty_ConfigNCPSocketPath "Config:NCP:SocketPath"
+#define kWPANTUNDProperty_ConfigNCPSocketBaud "Config:NCP:SocketBaud"
+#define kWPANTUNDProperty_ConfigNCPDriverName "Config:NCP:DriverName"
+#define kWPANTUNDProperty_ConfigNCPHardResetPath "Config:NCP:HardResetPath"
+#define kWPANTUNDProperty_ConfigNCPPowerPath "Config:NCP:PowerPath"
+#define kWPANTUNDProperty_ConfigNCPReliabilityLayer "Config:NCP:ReliabilityLayer"
+#define kWPANTUNDProperty_ConfigNCPFirmwareCheckCommand "Config:NCP:FirmwareCheckCommand"
+#define kWPANTUNDProperty_ConfigNCPFirmwareUpgradeCommand "Config:NCP:FirmwareUpgradeCommand"
+#define kWPANTUNDProperty_ConfigTUNInterfaceName "Config:TUN:InterfaceName"
+#define kWPANTUNDProperty_ConfigDaemonPIDFile "Config:Daemon:PIDFile"
+#define kWPANTUNDProperty_ConfigDaemonPrivDropToUser "Config:Daemon:PrivDropToUser"
+#define kWPANTUNDProperty_ConfigDaemonChroot "Config:Daemon:Chroot"
+#define kWPANTUNDProperty_ConfigDaemonNetworkRetainCommand "Config:Daemon:NetworkRetainCommand"
+
+#define kWPANTUNDProperty_DaemonVersion "Daemon:Version"
+#define kWPANTUNDProperty_DaemonEnabled "Daemon:Enabled"
+#define kWPANTUNDProperty_DaemonSyslogMask "Daemon:SyslogMask"
+#define kWPANTUNDProperty_DaemonTerminateOnFault "Daemon:TerminateOnFault"
+#define kWPANTUNDProperty_DaemonReadyForHostSleep "Daemon:ReadyForHostSleep"
+#define kWPANTUNDProperty_DaemonAutoAssociateAfterReset "Daemon:AutoAssociateAfterReset"
+#define kWPANTUNDProperty_DaemonAutoFirmwareUpdate "Daemon:AutoFirmwareUpdate"
+#define kWPANTUNDProperty_DaemonAutoDeepSleep "Daemon:AutoDeepSleep"
+#define kWPANTUNDProperty_DaemonFaultReason "Daemon:FaultReason"
+
+#define kWPANTUNDProperty_NCPVersion "NCP:Version"
+#define kWPANTUNDProperty_NCPState "NCP:State"
+#define kWPANTUNDProperty_NCPHardwareAddress "NCP:HardwareAddress"
+#define kWPANTUNDProperty_NCPExtendedAddress "NCP:ExtendedAddress"
+#define kWPANTUNDProperty_NCPMACAddress "NCP:MACAddress"
+#define kWPANTUNDProperty_NCPChannel "NCP:Channel"
+#define kWPANTUNDProperty_NCPFrequency "NCP:Frequency"
+#define kWPANTUNDProperty_NCPTXPower "NCP:TXPower"
+#define kWPANTUNDProperty_NCPTXPowerLimit "NCP:TXPowerLimit"
+#define kWPANTUNDProperty_NCPCCAThreshold "NCP:CCAThreshold"
+#define kWPANTUNDProperty_NCPChannelMask "NCP:ChannelMask"
+#define kWPANTUNDProperty_NCPSleepyPollInterval "NCP:SleepyPollInterval"
+#define kWPANTUNDProperty_NCPRSSI "NCP:RSSI"
+
+#define kWPANTUNDProperty_NetworkName "Network:Name"
+#define kWPANTUNDProperty_NetworkXPANID "Network:XPANID"
+#define kWPANTUNDProperty_NetworkPANID "Network:PANID"
+#define kWPANTUNDProperty_NetworkNodeType "Network:NodeType"
+#define kWPANTUNDProperty_NetworkKey "Network:Key"
+#define kWPANTUNDProperty_NetworkKeyIndex "Network:KeyIndex"
+#define kWPANTUNDProperty_NetworkIsCommissioned "Network:IsCommissioned"
+
+#define kWPANTUNDProperty_IPv6LinkLocalAddress "IPv6:LinkLocalAddress"
+#define kWPANTUNDProperty_IPv6MeshLocalAddress "IPv6:MeshLocalAddress"
+#define kWPANTUNDProperty_IPv6MeshLocalPrefix "IPv6:MeshLocalPrefix"
+#define kWPANTUNDProperty_IPv6AllAddresses "IPv6:AllAddresses"
+
+#define kWPANTUNDProperty_ThreadRLOC16 "Thread:RLOC16"
+#define kWPANTUNDProperty_ThreadRouterID "Thread:RouterID"
+#define kWPANTUNDProperty_ThreadLeaderAddress "Thread:Leader:Address"
+#define kWPANTUNDProperty_ThreadLeaderRouterID "Thread:Leader:RouterID"
+#define kWPANTUNDProperty_ThreadLeaderWeight "Thread:Leader:Weight"
+#define kWPANTUNDProperty_ThreadLeaderLocalWeight "Thread:Leader:LocalWeight"
+#define kWPANTUNDProperty_ThreadLeaderNetworkData "Thread:Leader:NetworkData"
+#define kWPANTUNDProperty_ThreadStableLeaderNetworkData "Thread:Leader:StableNetworkData"
+#define kWPANTUNDProperty_ThreadNetworkData "Thread:NetworkData"
+#define kWPANTUNDProperty_ThreadChildTable "Thread:ChildTable"
+#define kWPANTUNDProperty_ThreadChildTableAsValMap "Thread:ChildTable:AsValMap"
+#define kWPANTUNDProperty_ThreadNeighborTable "Thread:NeighborTable"
+#define kWPANTUNDProperty_ThreadNeighborTableAsValMap "Thread:NeighborTable:AsValMap"
+#define kWPANTUNDProperty_ThreadNetworkDataVersion "Thread:NetworkDataVersion"
+#define kWPANTUNDProperty_ThreadStableNetworkData "Thread:StableNetworkData"
+#define kWPANTUNDProperty_ThreadStableNetworkDataVersion "Thread:StableNetworkDataVersion"
+#define kWPANTUNDProperty_ThreadPreferredRouterID "Thread:PreferredRouterID"
+
+#define kWPANTUNDProperty_OpenThreadMsgBufferCounters "OpenThread:MsgBufferCounters"
+#define kWPANTUNDProperty_OpenThreadMsgBufferCountersAsString "OpenThread:MsgBufferCounters:AsString"
+
+#define kWPANTUNDProperty_DebugIPv6GlobalIPAddressList "Debug:IPv6:GlobalIPAddressList"
+
+#define kWPANTUNDProperty_JamDetectionStatus "JamDetection:Status"
+#define kWPANTUNDProperty_JamDetectionEnable "JamDetection:Enable"
+#define kWPANTUNDProperty_JamDetectionRssiThreshold "JamDetection:RssiThreshold"
+#define kWPANTUNDProperty_JamDetectionWindow "JamDetection:Window"
+#define kWPANTUNDProperty_JamDetectionBusyPeriod "JamDetection:BusyPeriod"
+#define kWPANTUNDProperty_JamDetectionDebugHistoryBitmap "JamDetection:Debug:HistoryBitmap"
+
+#define kWPANTUNDProperty_NestLabs_NetworkAllowingJoin "com.nestlabs.internal:Network:AllowingJoin"
+#define kWPANTUNDProperty_NestLabs_NetworkPassthruPort "com.nestlabs.internal:Network:PassthruPort"
+#define kWPANTUNDProperty_NestLabs_NCPTransmitHookActive "com.nestlabs.internal:NCP:TransmitHookActive"
+#define kWPANTUNDProperty_NestLabs_LegacyPreferInterface "com.nestlabs.internal:Legacy:PreferInterface"
+#define kWPANTUNDProperty_NestLabs_LegacyMeshLocalAddress "com.nestlabs.internal:Legacy:MeshLocalAddress"
+#define kWPANTUNDProperty_NestLabs_LegacyMeshLocalPrefix "com.nestlabs.internal:Legacy:MeshLocalPrefix"
+#define kWPANTUNDProperty_NestLabs_LegacyEnabled "com.nestlabs.internal:Legacy:Enabled"
+#define kWPANTUNDProperty_NestLabs_NetworkWakeData "com.nestlabs.internal:NetworkWake:Data"
+#define kWPANTUNDProperty_NestLabs_NetworkWakeRemaining "com.nestlabs.internal:NetworkWake:Remaining"
+#define kWPANTUNDProperty_NestLabs_NetworkWakeBlacklist "com.nestlabs.internal:NetworkWake:Blacklist"
+#define kWPANTUNDProperty_NestLabs_HackUseDeepSleepOnLowPower "com.nestlabs.internal:Hack:UseDeepSleepOnLowPower"
+#define kWPANTUNDProperty_NestLabs_HackAlwaysResetToWake "com.nestlabs.internal:Hack:AlwaysResetToWake"
+
+
+#define kWPANTUNDProperty_Stat_Prefix "Stat:"
+#define kWPANTUNDProperty_StatRX "Stat:RX"
+#define kWPANTUNDProperty_StatTX "Stat:TX"
+#define kWPANTUNDProperty_StatRXHistory "Stat:RX:History"
+#define kWPANTUNDProperty_StatTXHistory "Stat:TX:History"
+#define kWPANTUNDProperty_StatHistory "Stat:History"
+#define kWPANTUNDProperty_StatNCP "Stat:NCP"
+#define kWPANTUNDProperty_StatBlockingHostSleep "Stat:BlockingHostSleep"
+#define kWPANTUNDProperty_StatNode "Stat:Node"
+#define kWPANTUNDProperty_StatNodeHistory "Stat:Node:History"
+#define kWPANTUNDProperty_StatNodeHistoryID "Stat:Node:History:"
+#define kWPANTUNDProperty_StatShort "Stat:Short"
+#define kWPANTUNDProperty_StatLong "Stat:Long"
+#define kWPANTUNDProperty_StatAutoLog "Stat:AutoLog"
+#define kWPANTUNDProperty_StatAutoLogState "Stat:AutoLog:State"
+#define kWPANTUNDProperty_StatAutoLogPeriod "Stat:AutoLog:Period"
+#define kWPANTUNDProperty_StatAutoLogLogLevel "Stat:AutoLog:LogLevel"
+#define kWPANTUNDProperty_StatUserLogRequestLogLevel "Stat:UserRequest:LogLevel"
+#define kWPANTUNDProperty_StatLinkQuality "Stat:LinkQuality"
+#define kWPANTUNDProperty_StatLinkQualityLong "Stat:LinkQuality:Long"
+#define kWPANTUNDProperty_StatLinkQualityShort "Stat:LinkQuality:Short"
+#define kWPANTUNDProperty_StatLinkQualityPeriod "Stat:LinkQuality:Period"
+#define kWPANTUNDProperty_StatHelp "Stat:Help"
+
+// ----------------------------------------------------------------------------
+
+#define kWPANTUNDNodeType_Unknown "unknown"
+#define kWPANTUNDNodeType_Router "router"
+#define kWPANTUNDNodeType_EndDevice "end-device"
+#define kWPANTUNDNodeType_SleepyEndDevice "sleepy-end-device"
+#define kWPANTUNDNodeType_NestLurker "nl-lurker"
+#define kWPANTUNDNodeType_Commissioner "commissioner"
+#define kWPANTUNDNodeType_Leader "leader"
+
+// ----------------------------------------------------------------------------
+
+// When querying the value of the association state property,
+// the returned value will be a human-readable string. Compare
+// it with one of the constants below to get the exact meaning.
+#define kWPANTUNDStateUninitialized "uninitialized"
+#define kWPANTUNDStateFault "uninitialized:fault"
+#define kWPANTUNDStateUpgrading "uninitialized:upgrading"
+#define kWPANTUNDStateDeepSleep "offline:deep-sleep"
+#define kWPANTUNDStateOffline "offline"
+#define kWPANTUNDStateCommissioned "offline:commissioned"
+#define kWPANTUNDStateAssociating "associating"
+#define kWPANTUNDStateCredentialsNeeded "associating:credentials-needed"
+#define kWPANTUNDStateAssociated "associated"
+#define kWPANTUNDStateIsolated "associated:no-parent"
+#define kWPANTUNDStateNetWake_Asleep "associated:netwake-asleep"
+#define kWPANTUNDStateNetWake_Waking "associated:netwake-waking"
+
+// ----------------------------------------------------------------------------
+
+// Values of the property kWPANTUNDProperty_StatAutoLogState
+#define kWPANTUNDStatAutoLogState_Disabled "disabled"
+#define kWPANTUNDStatAutoLogState_Long "long"
+#define kWPANTUNDStatAutoLogState_Short "short"
+
+
+// ----------------------------------------------------------------------------
+
+// Values for value map keys
+#define kWPANTUNDValueMapKey_NetworkTopology_ExtAddress "ExtAddress"
+#define kWPANTUNDValueMapKey_NetworkTopology_RLOC16 "RLOC16"
+#define kWPANTUNDValueMapKey_NetworkTopology_LinkQualityIn "LinkQualityIn"
+#define kWPANTUNDValueMapKey_NetworkTopology_AverageRssi "AverageRssi"
+#define kWPANTUNDValueMapKey_NetworkTopology_Age "Age"
+#define kWPANTUNDValueMapKey_NetworkTopology_RxOnWhenIdle "RxOnWhenIdle"
+#define kWPANTUNDValueMapKey_NetworkTopology_FullFunction "FullFunction"
+#define kWPANTUNDValueMapKey_NetworkTopology_SecureDataRequest "SecureDataRequest"
+#define kWPANTUNDValueMapKey_NetworkTopology_FullNetworkData "FullNetworkData"
+#define kWPANTUNDValueMapKey_NetworkTopology_Timeout "Timeout"
+#define kWPANTUNDValueMapKey_NetworkTopology_NetworkDataVersion "NetworkDataVersion"
+#define kWPANTUNDValueMapKey_NetworkTopology_LinkFrameCounter "LinkFrameCounter"
+#define kWPANTUNDValueMapKey_NetworkTopology_MleFrameCounter "MleFrameCounter"
+#define kWPANTUNDValueMapKey_NetworkTopology_IsChild "IsChild"
+
+#endif
diff --git a/src/wpantund/wpantund.conf b/src/wpantund/wpantund.conf
new file mode 100644
index 0000000..1d98db8
--- /dev/null
+++ b/src/wpantund/wpantund.conf
@@ -0,0 +1,154 @@
+# Example wpantund configuration file
+#
+
+# The desired name of the network interface (not supported on all platforms)
+# Default value is `wpan0`.
+#
+#Config:TUN:InterfaceName wpan0
+
+# Path to serial port used to communicate with the NCP.
+# Has special meaning when prefixed with `system:` or `serial:`.
+# If the path is an IPv4 address/port, it will use a TCP socket.
+#
+#Config:NCP:SocketPath "/dev/tty.usbmodem1234"
+#Config:NCP:SocketPath "127.0.0.1:4901"
+#Config:NCP:SocketPath "system:/usr/local/sbin/spi-server -p - -s /dev/spidev2.0"
+#Config:NCP:SocketPath "serial:/dev/ttyO1,raw,b115200,crtscts=1"
+
+# The desired NCP driver to use.
+# Default value is `spinel`.
+#
+#Config:NCP:DriverName spinel
+
+# Describes what type of serial reliability layer should be used, if any.
+# Generally this is set appropriately automatically, so you usually
+# don't need to bother setting this.
+#
+# Optional. Default value is automatic.
+#
+#Config:NCP:ReliabilityLayer libsoot
+
+# The default transmit power of the NCP, measured in dBm
+# (0 dBm is one milliwatt, can be negative)
+#
+# Optional. Default value is NCP-specific.
+#
+#NCP:TXPower 0
+
+# The CCA threshold value, measured in dBm
+#
+# Optional. Default value is NCP-specific.
+#
+#NCP:CCAThreshold -70
+
+# Path to reset pin. This socket is opened and values sent to it
+# based on the desired reset state. wpantund sends `0\n` to
+# assert the reset pin and sends `1\n` to deassert the reset pin.
+# Can be used with the same `system:` and `serial:` prefixes defined
+# above to handle special cases. On linux, you would generally
+# set this to the `value` file of the RESET GPIO.
+#
+# Optional. If not set, only software resets will be possible.
+#
+#Config:NCP:HardResetPath "/sys/class/gpio/gpio49/value"
+
+# Path to power pin. The semantics are similar to those for
+# `NCPHardResetPath` above, except that wpantund sends `0\n` to
+# indicate that the NCP power should be disabled and `1\n` to
+# indicate that the NCP power should be enabled.
+#
+# Optional. If not set, only software induced sleep will be used
+# for low-power states.
+#
+#Config:NCP:PowerPath "/sys/class/gpio/gpio11/value"
+
+# Syslog mask adjustment. This property is a set of
+# boolean masks for manipulating the bitmask used by `syslog()`.
+# The string can contain the following words that represent
+# the associated bit. The presence of the word in the string
+# indicates that that bit should be set. Prefixing the word with
+# a `-` (dash/minus) indicates that that bit should be cleared.
+# The following keywords are supported:
+#
+# * `all` (All log levels)
+# * `emerg`
+# * `alert`
+# * `crit`
+# * `err`
+# * `warn`
+# * `notice`
+# * `info`
+# * `debug`
+#
+# So, for example, to get all log messages except debugging
+# messages, you would use `all -debug`.
+#
+# Optional. The default value for non-debug builds is
+# `all -info -debug`.
+#
+#Daemon:SyslogMask "all -info -debug"
+
+# Drop root privileges to the given user (and that user's group)
+# after setting up all network interfaces and socket connections.
+# Doing this helps mitigate the implications of security exploits,
+# but may interfere with how hard resets are performed for certain
+# NCPs.
+#
+# Optional. Default value is empty, which means that privileges
+# are not dropped.
+#
+#Config:Daemon:PrivDropToUser "nobody"
+
+# Call `chroot()` to change the root directory to the directory
+# indicated, after setting up all network interfaces and socket
+# connections, but before privileges are dropped for `PrivDropToUser`
+# (if set). Doing this helps mitigate the implications of security
+# exploits, but may interfere with how hard resets are performed
+# for certain NCPs.
+#
+# Optional. Default value is empty, which means that `chroot` is
+# not called.
+#
+#Config:Daemon:Chroot "/var/empty"
+
+# Automatic firmware update enable/disable. This flag determines
+# if the automatic firmware update mechanism (which uses the
+# properties `FirmwareCheckCommand` and `FirmwareUpgradeCommand`,
+# described below) is enabled or disabled. This flag is used
+# when the driver determines that it doesn't know how to talk to
+# the version of the firmware that is running on the NCP.
+#
+# If set to true, the NCP association state will then be set to
+# `upgrading` and the firmware update process will begin. If set to
+# false, the NCP association state will change to `fault`.
+#
+# This property may be changed at runtime to more strictly
+# control when a firmware update is allowed to take place.
+#
+# Optional. The default value is false---which will prevent
+# automatic wpantund-driven firmware updates.
+#
+#Daemon:AutoFirmwareUpdate true
+
+# Firmware update check command. This command is executed with
+# the retrieved version string of the NCP appended as the last
+# argument. If the command returns `0`, a firmware update is
+# necessary. This configuration option is fairly useless without
+# the `FirmwareUpgradeCommand` option also being set, defined below.
+#
+# Optional. If left blank, wpantund-driven firmware updates will
+# be disabled.
+#
+#Config:NCP:FirmwareCheckCommand "test 'MyFunStack/1.0' !="
+#Config:NCP:FirmwareCheckCommand "/usr/local/sbin/zb-loader --is-update-required /usr/share/ncp-firmware/ip-modem-app.bin"
+
+# Firmware upgrade command. This is the command that is actually
+# executed that performs the firmware update. Before calling this
+# command, `wpantund` disconnects entirely from the NCP. While
+# this command is executing, the association state reported
+# for this interface will be `upgrading`.
+#
+# Optional. If left blank, wpantund-driven firmware updates will
+# be disabled.
+#
+#Config:NCP:FirmwareUpgradeCommand "/usr/local/sbin/zb-loader /dev/ttyO1 --app-easyload /usr/share/ncp-firmware/ip-modem-app.bin"
diff --git a/src/wpantund/wpantund.cpp b/src/wpantund/wpantund.cpp
new file mode 100644
index 0000000..a7a028b
--- /dev/null
+++ b/src/wpantund/wpantund.cpp
@@ -0,0 +1,926 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Description:
+ * This file implements the main program entry point for the
+ * WPAN Tunnel Driver, masterfuly named `wpantund`.
+ *
+ */
+
+#define DEBUG 1
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef ASSERT_MACROS_USE_SYSLOG
+#define ASSERT_MACROS_USE_SYSLOG 1
+#endif
+
+#ifndef ASSERT_MACROS_SQUELCH
+#define ASSERT_MACROS_SQUELCH 0
+#endif
+
+#include "assert-macros.h"
+
+#include "wpantund.h"
+
+#include "config-file.h"
+#include "args.h"
+#include "pt.h"
+#include "tunnel.h"
+#include "socket-utils.h"
+#include "string-utils.h"
+#include "version.h"
+#include "SuperSocket.h"
+#include "Timer.h"
+
+#include "DBUSIPCServer.h"
+#include "NCPControlInterface.h"
+#include "NCPInstance.h"
+
+#include "nlpt.h"
+
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <unistd.h>
+#include <signal.h>
+
+#include <poll.h>
+#include <sys/select.h>
+
+#include <syslog.h>
+#include <errno.h>
+#include <libgen.h>
+
+#include <exception>
+#include <algorithm>
+
+#include "any-to.h"
+#include "sec-random.h"
+
+#if HAVE_PWD_H
+#include <pwd.h>
+#endif
+
+#ifndef PREFIX
+#define PREFIX "/usr/local"
+#endif
+
+#ifndef SYSCONFDIR
+#define SYSCONFDIR PREFIX "/etc"
+#endif
+
+#ifndef DEFAULT_MAX_LOG_LEVEL
+#if DEBUG
+#define DEFAULT_MAX_LOG_LEVEL LOG_INFO
+#else
+#define DEFAULT_MAX_LOG_LEVEL LOG_NOTICE
+#endif
+#endif
+
+#ifndef WPANTUND_DEFAULT_PRIV_DROP_USER
+#define WPANTUND_DEFAULT_PRIV_DROP_USER NULL
+#endif
+
+#ifndef WPANTUND_DEFAULT_CHROOT_PATH
+#define WPANTUND_DEFAULT_CHROOT_PATH NULL
+#endif
+
+#ifndef WPANTUND_BACKTRACE
+#define WPANTUND_BACKTRACE (HAVE_EXECINFO_H || __APPLE__)
+#endif
+
+#if WPANTUND_BACKTRACE
+#include <execinfo.h>
+#if HAVE_ASM_SIGCONTEXT
+#include <asm/sigcontext.h>
+#endif
+#ifndef FAULT_BACKTRACE_STACK_DEPTH
+#define FAULT_BACKTRACE_STACK_DEPTH 20
+#endif
+#endif
+
+#ifndef SOURCE_VERSION
+#define SOURCE_VERSION PACKAGE_VERSION
+__BEGIN_DECLS
+#include "version.c.in"
+__END_DECLS
+#endif
+
+using namespace nl;
+using namespace wpantund;
+
+static arg_list_item_t option_list[] = {
+ { 'h', "help", NULL, "Print Help"},
+ { 'd', "debug", "<level>", "Enable debugging mode"},
+ { 'c', "config", "<filename>", "Config File"},
+ { 'o', "option", "<option-string>", "Config option"},
+ { 'I', "interface", "<iface>", "Network interface name"},
+ { 's', "socket", "<socket>", "Socket file"},
+ { 'b', "baudrate", "<integer>", "Baudrate"},
+ { 'v', "version", NULL, "Print version" },
+#if HAVE_PWD_H
+ { 'u', "user", NULL, "Username for dropping privileges" },
+#endif
+ { 0 }
+};
+
+static int gRet;
+
+static const char* gProcessName = "wpantund";
+static const char* gPIDFilename = NULL;
+static const char* gChroot = WPANTUND_DEFAULT_CHROOT_PATH;
+
+#if HAVE_PWD_H
+static const char* gPrivDropToUser = WPANTUND_DEFAULT_PRIV_DROP_USER;
+#endif
+
+/* ------------------------------------------------------------------------- */
+/* MARK: Signal Handlers */
+
+static sig_t gPreviousHandlerForSIGINT;
+static sig_t gPreviousHandlerForSIGTERM;
+
+static void
+signal_SIGINT(int sig)
+{
+ static const char message[] = "\nCaught SIGINT!\n";
+
+ gRet = ERRORCODE_INTERRUPT;
+
+ // Can't use syslog() because it isn't async signal safe.
+ // So we write to stderr
+ (void)write(STDERR_FILENO, message, sizeof(message)-1);
+
+ // Restore the previous handler so that if we end up getting
+ // this signal again we peform the system default action.
+ signal(SIGINT, gPreviousHandlerForSIGINT);
+ gPreviousHandlerForSIGINT = NULL;
+}
+
+static void
+signal_SIGTERM(int sig)
+{
+ static const char message[] = "\nCaught SIGTERM!\n";
+
+ gRet = ERRORCODE_QUIT;
+
+ // Can't use syslog() because it isn't async signal safe.
+ // So we write to stderr
+ IGNORE_RETURN_VALUE(write(STDERR_FILENO, message, sizeof(message)-1));
+
+ // Restore the previous handler so that if we end up getting
+ // this signal again we peform the system default action.
+ signal(SIGTERM, gPreviousHandlerForSIGTERM);
+ gPreviousHandlerForSIGTERM = NULL;
+}
+
+static void
+signal_SIGHUP(int sig)
+{
+ static const char message[] = "\nCaught SIGHUP!\n";
+
+ gRet = ERRORCODE_SIGHUP;
+
+ // Can't use syslog() because it isn't async signal safe.
+ // So we write to stderr
+ IGNORE_RETURN_VALUE(write(STDERR_FILENO, message, sizeof(message)-1));
+
+ // We don't restore the "previous handler"
+ // because we always want to let the main
+ // loop decide what to do for hangups.
+}
+
+static void
+signal_critical(int sig, siginfo_t * info, void * ucontext)
+{
+ // This is the last hurah for this process.
+ // We dump the stack, because that's all we can do.
+
+ // We call some functions here which aren't async-signal-safe,
+ // but this function isn't really useful without those calls.
+ // Since we are making a gamble (and we deadlock if we loose),
+ // we are going to set up a two-second watchdog to make sure
+ // we end up terminating like we should. The choice of a two
+ // second timeout is entirely arbitrary, and may be changed
+ // if needs warrant.
+ alarm(2);
+ signal(SIGALRM, SIG_DFL);
+
+#if WPANTUND_BACKTRACE
+ void *stack_mem[FAULT_BACKTRACE_STACK_DEPTH];
+ void **stack = stack_mem;
+ char **stack_symbols;
+ int stack_depth, i;
+ ucontext_t *uc = (ucontext_t*)ucontext;
+
+ // Shut up compiler warning.
+ (void)uc;
+
+#endif // WPANTUND_BACKTRACE
+
+ fprintf(stderr, " *** FATAL ERROR: Caught signal %d (%s):\n", sig, strsignal(sig));
+
+#if WPANTUND_BACKTRACE
+ stack_depth = backtrace(stack, FAULT_BACKTRACE_STACK_DEPTH);
+
+#if __APPLE__
+ // OS X adds an extra call onto the stack that
+ // we can leave out for clarity sake.
+ stack[1] = stack[0];
+ stack++;
+ stack_depth--;
+#endif
+
+ // Here are are trying to update the pointer in the backtrace
+ // to be the actual location of the fault.
+#if __linux__
+#if defined(__x86_64__)
+ stack[1] = (void *) uc->uc_mcontext.gregs[REG_RIP];
+#elif defined(__arm__)
+ stack[1] = (void *) uc->uc_mcontext.arm_ip;
+#else
+#warning TODO: Add this arch to signal_critical
+#endif
+
+#elif __APPLE__ // #if __linux__
+#if defined(__x86_64__)
+ stack[1] = (void *) uc->uc_mcontext->__ss.__rip;
+#endif
+
+#else //#elif __APPLE__
+#warning TODO: Add this OS to signal_critical
+#endif
+
+ // Now dump the symbols to stderr, in case syslog barfs.
+ backtrace_symbols_fd(stack, stack_depth, STDERR_FILENO);
+
+ // Load up the symbols individually, so we can output to syslog, too.
+ stack_symbols = backtrace_symbols(stack, stack_depth);
+#endif // WPANTUND_BACKTRACE
+
+ syslog(LOG_CRIT, " *** FATAL ERROR: Caught signal %d (%s):", sig, strsignal(sig));
+
+#if WPANTUND_BACKTRACE
+ for(i = 0; i != stack_depth; i++) {
+#if __APPLE__
+ syslog(LOG_CRIT, "[BT] %s", stack_symbols[i]);
+#else
+ syslog(LOG_CRIT, "[BT] %2d: %s", i, stack_symbols[i]);
+#endif
+ }
+
+ free(stack_symbols);
+#endif // WPANTUND_BACKTRACE
+
+ _exit(EXIT_FAILURE);
+}
+
+/* ------------------------------------------------------------------------- */
+/* MARK: Misc. */
+
+// TODO: Refactor and clean up.
+static int
+set_config_param(
+ void* ignored, const char* key, const char* value
+ )
+{
+ int ret = -1;
+
+ syslog(LOG_INFO, "set-config-param: \"%s\" = \"%s\"", key, value);
+
+ if (strcaseequal(key, kWPANTUNDProperty_ConfigNCPSocketBaud)) {
+ int baud = atoi(value);
+ ret = 0;
+ require(9600 <= baud, bail);
+ gSocketWrapperBaud = baud;
+#if HAVE_PWD_H
+ } else if (strcaseequal(key, kWPANTUNDProperty_ConfigDaemonPrivDropToUser)) {
+ if (value[0] == 0) {
+ gPrivDropToUser = NULL;
+ } else {
+ gPrivDropToUser = strdup(value);
+ }
+ ret = 0;
+#endif
+ } else if (strcaseequal(key, kWPANTUNDProperty_ConfigDaemonChroot)) {
+ if (value[0] == 0) {
+ gChroot = NULL;
+ } else {
+ gChroot = strdup(value);
+ }
+ ret = 0;
+ } else if (strcaseequal(key, kWPANTUNDProperty_DaemonSyslogMask)) {
+ setlogmask(strtologmask(value, setlogmask(0)));
+ ret = 0;
+ } else if (strcaseequal(key, kWPANTUNDProperty_ConfigDaemonPIDFile)) {
+ if (gPIDFilename)
+ goto bail;
+ gPIDFilename = strdup(value);
+ unlink(gPIDFilename);
+ FILE* pidfile = fopen(gPIDFilename, "w");
+ if (!pidfile) {
+ syslog(LOG_ERR, "Unable to open PID file \"%s\".", gPIDFilename);
+ goto bail;
+ }
+ fclose(pidfile);
+ ret = 0;
+ }
+
+bail:
+ if (ret == 0) {
+ syslog(LOG_INFO, "set-config-param: \"%s\" set succeded", key);
+ }
+ return ret;
+}
+
+// Used with `read_config()` to collect configuration settings into a map.
+static int
+add_to_map(
+ void* context,
+ const char* key,
+ const char* value
+) {
+ std::map<std::string, std::string> *map = static_cast<std::map<std::string, std::string>*>(context);
+ (*map)[key] = value;
+ return 0;
+}
+
+static void
+handle_error(int err)
+{
+ gRet = err;
+}
+
+std::string
+nl::wpantund::get_wpantund_version_string(void)
+{
+ std::string version = PACKAGE_VERSION;
+
+ if ((internal_build_source_version[0] == 0) || strequal(SOURCE_VERSION, internal_build_source_version)) {
+ // Ignore any coverty warnings about the following line being pointless.
+ // I assure you, it is not pointless.
+ if (strequal(PACKAGE_VERSION, SOURCE_VERSION)) {
+ version += " (";
+ version += internal_build_date;
+ version += ")";
+ } else {
+ version += " (";
+ version += SOURCE_VERSION;
+ version += "; ";
+ version += internal_build_date;
+ version += ")";
+ }
+ } else {
+ // Ignore any coverty warnings about the following line being pointless.
+ // I assure you, it is not pointless.
+ if (strequal(SOURCE_VERSION, PACKAGE_VERSION) || strequal(PACKAGE_VERSION, internal_build_source_version)) {
+ version += " (";
+ version += internal_build_source_version;
+ version += "; ";
+ version += internal_build_date;
+ version += ")";
+ } else {
+ version += " (";
+ version += SOURCE_VERSION;
+ version += "/";
+ version += internal_build_source_version;
+ version += "; ";
+ version += internal_build_date;
+ version += ")";
+ }
+ }
+ return version;
+}
+
+static void
+print_version()
+{
+ printf("wpantund %s\n", get_wpantund_version_string().c_str() );
+}
+
+/* ------------------------------------------------------------------------- */
+/* MARK: NLPT Hooks */
+
+static fd_set gReadableFDs;
+static fd_set gWritableFDs;
+static fd_set gErrorableFDs;
+
+bool
+nlpt_hook_check_read_fd_source(struct nlpt* nlpt, int fd)
+{
+
+ bool ret = false;
+ if (fd >= 0) {
+ ret = FD_ISSET(fd, &gReadableFDs) || FD_ISSET(fd, &gErrorableFDs);
+ FD_CLR(fd, &gReadableFDs);
+ FD_CLR(fd, &gErrorableFDs);
+ }
+ return ret;
+}
+
+bool
+nlpt_hook_check_write_fd_source(struct nlpt* nlpt, int fd)
+{
+ bool ret = false;
+ if (fd >= 0) {
+ ret = FD_ISSET(fd, &gWritableFDs) || FD_ISSET(fd, &gErrorableFDs);
+ FD_CLR(fd, &gWritableFDs);
+ FD_CLR(fd, &gErrorableFDs);
+ }
+ return ret;
+}
+
+static void
+syslog_dump_select_info(int loglevel, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *error_fd_set, int fd_count, cms_t timeout)
+{
+#define DUMP_FD_SET(l, x) do {\
+ int i; \
+ std::string buffer; \
+ for (i = 0; i < fd_count; i++) { \
+ if (!FD_ISSET(i, x)) { \
+ continue; \
+ } \
+ if (buffer.size() != 0) { \
+ buffer += ", "; \
+ } \
+ char str[10]; \
+ snprintf(str, sizeof(str), "%d", i); \
+ buffer += str; \
+ } \
+ syslog(l, "SELECT: %s: %s", #x, buffer.c_str()); \
+ } while (0)
+
+ // Check the log level preemptively to avoid wasted CPU.
+ if((setlogmask(0)&LOG_MASK(loglevel))) {
+ syslog(loglevel, "SELECT: fd_count=%d cms_timeout=%d", fd_count, timeout);
+
+ DUMP_FD_SET(loglevel, read_fd_set);
+ DUMP_FD_SET(loglevel, write_fd_set);
+ //DUMP_FD_SET(loglevel, error_fd_set); // Commented out to reduce log volume
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+/* MARK: Main Function */
+
+int
+main(int argc, char * argv[])
+{
+ int c;
+ int fds_ready = 0;
+ bool interface_added = false;
+ int zero_cms_in_a_row_count = 0;
+ const char* config_file = SYSCONFDIR "/wpantund.conf";
+ const char* alt_config_file = SYSCONFDIR "/wpan-tunnel-driver.conf";
+ nl::wpantund::IPCServer *ipc_server = NULL;
+ nl::wpantund::NCPInstance *ncp_instance = NULL;
+ std::map<std::string, std::string> cmd_line_settings;
+
+ // ========================================================================
+ // INITIALIZATION and ARGUMENT PARSING
+
+ gPreviousHandlerForSIGINT = signal(SIGINT, &signal_SIGINT);
+ gPreviousHandlerForSIGTERM = signal(SIGTERM, &signal_SIGTERM);
+ signal(SIGHUP, &signal_SIGHUP);
+
+ // Always ignore SIGPIPE.
+ signal(SIGPIPE, SIG_IGN);
+
+ {
+ struct sigaction sigact = { };
+ sigact.sa_sigaction = &signal_critical;
+ sigact.sa_flags = SA_RESTART | SA_SIGINFO | SA_NOCLDWAIT;
+
+ sigaction(SIGSEGV, &sigact, (struct sigaction *)NULL);
+ sigaction(SIGBUS, &sigact, (struct sigaction *)NULL);
+ sigaction(SIGILL, &sigact, (struct sigaction *)NULL);
+ sigaction(SIGABRT, &sigact, (struct sigaction *)NULL);
+ }
+
+ openlog(basename(argv[0]), LOG_PERROR | LOG_PID | LOG_CONS, LOG_DAEMON);
+
+ // Temper the amount of logging.
+ setlogmask(setlogmask(0) & LOG_UPTO(DEFAULT_MAX_LOG_LEVEL));
+
+ gRet = ERRORCODE_UNKNOWN;
+
+ if (argc && argv[0][0]) {
+ gProcessName = basename(argv[0]);
+ }
+ optind = 0;
+ while(1) {
+ static struct option long_options[] =
+ {
+ {"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'v'},
+ {"debug", no_argument, 0, 'd'},
+ {"config", required_argument, 0, 'c'},
+ {"option", required_argument, 0, 'o'},
+ {"interface", required_argument, 0, 'I'},
+ {"socket", required_argument, 0, 's'},
+ {"baudrate", required_argument, 0, 'b'},
+ {"user", required_argument, 0, 'u'},
+ {0, 0, 0, 0}
+ };
+
+ int option_index = 0;
+ c = getopt_long(argc, argv, "hvd:c:o:I:s:b:u:", long_options,
+ &option_index);
+
+ if (c == -1)
+ break;
+
+ switch(c) {
+ case 'h':
+ print_arg_list_help(option_list, argv[0], "[options]");
+ gRet = ERRORCODE_HELP;
+ goto bail;
+
+ case 'v':
+ print_version();
+ gRet = 0;
+ goto bail;
+
+ case 'd':
+ setlogmask(~0);
+ break;
+
+ case 'c':
+ config_file = optarg;
+ break;
+
+ case 'I':
+ cmd_line_settings[kWPANTUNDProperty_ConfigTUNInterfaceName] = optarg;
+ break;
+
+ case 's':
+ cmd_line_settings[kWPANTUNDProperty_ConfigNCPSocketPath] = optarg;
+ break;
+
+ case 'b':
+ cmd_line_settings[kWPANTUNDProperty_ConfigNCPSocketBaud] = optarg;
+ break;
+
+ case 'u':
+ cmd_line_settings[kWPANTUNDProperty_ConfigDaemonPrivDropToUser] = optarg;
+ break;
+
+ case 'o':
+ if ((optind >= argc) || (strncmp(argv[optind], "-", 1) == 0)) {
+ syslog(LOG_ERR, "Missing argument to '-o'.");
+ gRet = ERRORCODE_BADARG;
+ goto bail;
+ }
+ char *key = optarg;
+ char *value = argv[optind];
+ optind++;
+
+ // We handle this option after we try loading the configuration
+ // file, so that command-line specified settings can override
+ // settings read from the configuration file.
+ cmd_line_settings[key] = value;
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ fprintf(stderr,
+ "%s: error: Unexpected extra argument: \"%s\"\n",
+ argv[0],
+ argv[optind]);
+ gRet = ERRORCODE_BADARG;
+ goto bail;
+ }
+
+ // ========================================================================
+ // STARTUP
+
+ syslog(LOG_NOTICE, "Starting %s " PACKAGE_VERSION " (%s) . . .", gProcessName, internal_build_date);
+
+ if (("" SOURCE_VERSION)[0] != 0) {
+ syslog(LOG_NOTICE, "\tSOURCE_VERSION = " SOURCE_VERSION);
+ }
+
+ if (internal_build_source_version[0] != 0) {
+ syslog(LOG_NOTICE, "\tBUILD_VERSION = %s", internal_build_source_version);
+ }
+
+ if (getuid() != 0) {
+ // Warn people if we aren't root.
+ syslog(LOG_WARNING, "wpantund was not started as 'root'! If wpantund fails immediately, this is probably why.");
+ }
+
+ try {
+ std::map<std::string, std::string> settings;
+
+ // Read the configuration file into the settings map.
+ if (0 == read_config(config_file, &add_to_map, &settings)) {
+ syslog(LOG_NOTICE, "Configuration file \"%s\" read.", config_file);
+ } else if (0 == read_config(alt_config_file, &add_to_map, &settings)) {
+ syslog(LOG_NOTICE, "Configuration file \"%s\" read.", alt_config_file);
+ } else {
+ syslog(LOG_WARNING, "Configuration file \"%s\" not found, will use defaults.", config_file);
+ }
+
+ // Command line settings override configuration file settings.
+ // This is weird because the `insert()` method doesn't replace
+ // a key value pair if it already exists, so to get the desired
+ // behavior, we insert into `cmd_line_settings`, not `settings`.
+ cmd_line_settings.insert(settings.begin(), settings.end());
+
+ // Perform depricated property translation
+ {
+ std::map<std::string, std::string>::const_iterator iter;
+ settings.clear();
+
+ for (iter = cmd_line_settings.begin(); iter != cmd_line_settings.end(); iter++) {
+ std::string key(iter->first);
+ boost::any value(iter->second);
+ if (NCPControlInterface::translate_deprecated_property(key, value)) {
+ if (key.empty()) {
+ syslog(LOG_WARNING, "Configuration property \"%s\" is no longer supported. Please remove it from your configuration.", iter->first.c_str());
+ } else {
+ syslog(LOG_WARNING, "CONFIGURATION PROPERTY \"%s\" IS DEPRECATED. Please use \"%s\" instead.", iter->first.c_str(), key.c_str());
+ }
+ }
+ if (!key.empty()) {
+ settings[key] = any_to_string(value);
+ }
+ }
+ }
+
+ // Handle all of the options/settings.
+ if (!settings.empty()) {
+ std::map<std::string, std::string>::const_iterator iter;
+ std::map<std::string, std::string> settings_for_ncp_control_interface;
+
+ for(iter = settings.begin(); iter != settings.end(); iter++) {
+ if (set_config_param(NULL, iter->first.c_str(), iter->second.c_str())) {
+ // If set_config_param() doesn't like the argument,
+ // we hold onto it for now so we can try passing it as
+ // a property to the NCP instance.
+ settings_for_ncp_control_interface[iter->first] = iter->second;
+ }
+ }
+ settings = settings_for_ncp_control_interface;
+ }
+
+ //require_string(settings.count(kWPANTUNDProperty_ConfigNCPSocketPath) == 1, bail, "Missing "kWPANTUNDProperty_ConfigNCPSocketPath);
+
+ ipc_server = new DBUSIPCServer();
+
+ ncp_instance = NCPInstance::alloc(settings);
+
+ require_string(ncp_instance != NULL, bail, "Unable to create NCPInstance");
+
+ ncp_instance->mOnFatalError.connect(&handle_error);
+
+ ncp_instance->get_stat_collector().set_ncp_control_interface(&ncp_instance->get_control_interface());
+
+ } catch(std::runtime_error x) {
+ syslog(LOG_ERR, "Runtime error thrown while starting up, \"%s\"",x.what());
+ ncp_instance = NULL;
+ goto bail;
+
+ } catch(std::exception x) {
+ syslog(LOG_ERR, "Exception thrown while starting up, \"%s\"",x.what());
+ ncp_instance = NULL;
+ goto bail;
+ }
+
+ if (sec_random_init() < 0) {
+ syslog(LOG_ERR, "Call to sec_random_init() failed, errno=%d \"%s\"", errno, strerror(errno));
+ goto bail;
+ }
+
+ // ========================================================================
+ // Dropping Privileges
+
+ if (gChroot != NULL) {
+ if (getuid() == 0) {
+ if (chdir(gChroot) != 0) {
+ syslog(LOG_CRIT, "chdir: %s", strerror(errno));
+ gRet = ERRORCODE_ERRNO;
+ goto bail;
+ }
+
+ if (chroot(gChroot) != 0) {
+ syslog(LOG_CRIT, "chroot: %s", strerror(errno));
+ gRet = ERRORCODE_ERRNO;
+ goto bail;
+ } else {
+ if (chdir("/") != 0) {
+ syslog(LOG_INFO, "Failed to `chdir` after `chroot` to \"%s\"", gChroot);
+ gRet = ERRORCODE_ERRNO;
+ goto bail;
+ } else {
+ syslog(LOG_INFO, "Successfully changed root directory to \"%s\".", gChroot);
+ }
+ }
+ } else {
+ syslog(LOG_WARNING, "Not running as root, cannot chroot");
+ }
+ }
+
+#if HAVE_PWD_H
+ if (getuid() == 0) {
+ uid_t target_uid = 0;
+ gid_t target_gid = 0;
+
+ if (gPrivDropToUser != NULL) {
+ struct passwd *passwd = getpwnam(gPrivDropToUser);
+
+ if (passwd == NULL) {
+ syslog(LOG_CRIT, "getpwnam: Unable to lookup user \"%s\", cannot drop privileges.", gPrivDropToUser);
+ gRet = ERRORCODE_ERRNO;
+ goto bail;
+ }
+
+ target_uid = passwd->pw_uid;
+ target_gid = passwd->pw_gid;
+ }
+
+ if (target_gid != 0) {
+ if (setgid(target_gid) != 0) {
+ syslog(LOG_CRIT, "setgid: Unable to drop group privileges: %s", strerror(errno));
+ gRet = ERRORCODE_ERRNO;
+ goto bail;
+ } else {
+ syslog(LOG_INFO, "Group privileges dropped to GID:%d", (int)target_gid);
+ }
+ }
+
+ if (target_uid != 0) {
+ if (setuid(target_uid) != 0) {
+ syslog(LOG_CRIT, "setuid: Unable to drop user privileges: %s", strerror(errno));
+ gRet = ERRORCODE_ERRNO;
+ goto bail;
+ } else {
+ syslog(LOG_INFO, "User privileges dropped to UID:%d", (int)target_uid);
+ }
+ }
+
+ if ((target_gid == 0) || (target_uid == 0)) {
+ syslog(LOG_NOTICE, "Running as root without dropping privileges!");
+ }
+ } else if (gPrivDropToUser != NULL) {
+ syslog(LOG_NOTICE, "Not running as root, skipping dropping privileges");
+ }
+#endif // #if HAVE_PWD_H
+
+ // ========================================================================
+ // MAIN LOOP
+
+ gRet = 0;
+
+ while (!gRet) {
+ const cms_t max_main_loop_timeout(CMS_DISTANT_FUTURE);
+ cms_t cms_timeout(max_main_loop_timeout);
+ int max_fd(-1);
+ struct timeval timeout;
+
+ FD_ZERO(&gReadableFDs);
+ FD_ZERO(&gWritableFDs);
+ FD_ZERO(&gErrorableFDs);
+
+ // Update the FD masks and timeouts
+ ncp_instance->update_fd_set(&gReadableFDs, &gWritableFDs, &gErrorableFDs, &max_fd, &cms_timeout);
+ ipc_server->update_fd_set(&gReadableFDs, &gWritableFDs, &gErrorableFDs, &max_fd, &cms_timeout);
+ Timer::update_timeout(&cms_timeout);
+
+ require_string(max_fd < FD_SETSIZE, bail, "Too many file descriptors");
+
+ // Negative CMS timeout values are not valid.
+ if (cms_timeout < 0) {
+ syslog(LOG_DEBUG, "Negative CMS value: %d", cms_timeout);
+ cms_timeout = 0;
+ }
+
+ // Identify conditions where we are burning too much CPU.
+ if (cms_timeout == 0) {
+ double loadavg[3] = {-1.0, -1.0, -1.0};
+
+#if HAVE_GETLOADAVG
+ getloadavg(loadavg, 3);
+#endif
+
+ switch (++zero_cms_in_a_row_count) {
+ case 20:
+ syslog(LOG_INFO, "BUG: Main loop is thrashing! (%f %f %f)", loadavg[0], loadavg[1], loadavg[2]);
+ break;
+
+ case 200:
+ syslog(LOG_WARNING, "BUG: Main loop is still thrashing! Slowing things down. (%f %f %f)", loadavg[0], loadavg[1], loadavg[2]);
+ break;
+
+ case 1000:
+ syslog(LOG_CRIT, "BUG: Main loop had over 1000 iterations in a row with a zero timeout! Terminating. (%f %f %f)", loadavg[0], loadavg[1], loadavg[2]);
+ gRet = ERRORCODE_UNKNOWN;
+ break;
+ }
+ if (zero_cms_in_a_row_count > 200) {
+ // If the past 200 iterations have had a zero timeout,
+ // start using a minimum timeout of 10ms, so that we
+ // don't bring the rest of the system to a grinding halt.
+ cms_timeout = 10;
+ }
+ } else {
+ zero_cms_in_a_row_count = 0;
+ }
+
+ // Convert our `cms` value into timeval compatible with select().
+ timeout.tv_sec = cms_timeout / MSEC_PER_SEC;
+ timeout.tv_usec = (cms_timeout % MSEC_PER_SEC) * USEC_PER_MSEC;
+
+#if DEBUG
+ syslog_dump_select_info(
+ LOG_DEBUG,
+ &gReadableFDs,
+ &gWritableFDs,
+ &gErrorableFDs,
+ max_fd + 1,
+ cms_timeout
+ );
+#endif
+
+ // Block until we timeout or there is FD activity.
+ fds_ready = select(
+ max_fd + 1,
+ &gReadableFDs,
+ &gWritableFDs,
+ &gErrorableFDs,
+ &timeout
+ );
+
+ if (fds_ready < 0) {
+ syslog(LOG_ERR, "select() errno=\"%s\" (%d)", strerror(errno),
+ errno);
+
+ if (errno == EINTR) {
+ // EINTR isn't necessarily bad. If it was something bad,
+ // we would either already be terminated or gRet will be
+ // set and we will break out of the main loop in a moment.
+ continue;
+ }
+ gRet = ERRORCODE_ERRNO;
+ break;
+ }
+
+ // Process callback timers.
+ Timer::process();
+
+ // Process any necessary IPC actions.
+ ipc_server->process();
+
+ // Process the NCP instance.
+ ncp_instance->process();
+
+ // We only expose the interface via IPC after it is
+ // successfully initialized for the first time.
+ if (!interface_added) {
+ const boost::any value = ncp_instance->get_control_interface().get_property(kWPANTUNDProperty_NCPState);
+ if ((value.type() == boost::any(std::string()).type())
+ && (boost::any_cast<std::string>(value) != kWPANTUNDStateUninitialized)
+ ) {
+ ipc_server->add_interface(&ncp_instance->get_control_interface());
+ interface_added = true;
+ }
+ }
+ } // while (!gRet)
+
+bail:
+ syslog(LOG_NOTICE, "Cleaning up. (gRet = %d)", gRet);
+
+ if (gRet == ERRORCODE_QUIT) {
+ gRet = 0;
+ }
+
+ if (gPIDFilename) {
+ unlink(gPIDFilename);
+ }
+
+ syslog(LOG_NOTICE, "Stopped.");
+ return gRet;
+}
diff --git a/src/wpantund/wpantund.h b/src/wpantund/wpantund.h
new file mode 100644
index 0000000..192bd28
--- /dev/null
+++ b/src/wpantund/wpantund.h
@@ -0,0 +1,33 @@
+/*
+ *
+ * Copyright (c) 2016 Nest Labs, Inc.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef wpantund_h
+#define wpantund_h
+
+#include <string>
+
+namespace nl {
+namespace wpantund {
+
+std::string get_wpantund_version_string(void);
+
+};
+};
+
+#endif
diff --git a/third_party/Makefile.am b/third_party/Makefile.am
new file mode 100644
index 0000000..ca170a4
--- /dev/null
+++ b/third_party/Makefile.am
@@ -0,0 +1,761 @@
+#
+# Copyright (c) 2016 Nest Labs, Inc.
+# All rights reserved.
+#
+# This document is the property of Nest. It is considered
+# confidential and proprietary information.
+#
+# This document may not be reproduced or transmitted in any form,
+# in whole or in part, without the express written permission of
+# Nest.
+#
+
+DISTCLEANFILES = \
+ .deps \
+ Makefile \
+ $(NULL)
+
+# This line is needed for the lines below to work.
+EXTRA_DIST = $(NULL)
+
+# Protothreads
+EXTRA_DIST += \
+ pt/LICENSE \
+ pt/Makefile \
+ pt/README \
+ pt/README-VISUAL-C++.txt \
+ pt/README.google \
+ pt/doc/Doxyfile \
+ pt/doc/Makefile \
+ pt/doc/header.tex \
+ pt/doc/pt-doc.txt \
+ pt/doc/pt-mainpage.txt \
+ pt/doc/sicslogo.pdf \
+ pt/example-buffer.c \
+ pt/example-codelock.c \
+ pt/example-small.c \
+ pt/lc-addrlabels.h \
+ pt/lc-switch.h \
+ pt/lc.h \
+ pt/pt-sem.h \
+ pt/pt.h \
+ $(NULL)
+
+# Assert Macros
+EXTRA_DIST += \
+ assert-macros/LICENSE \
+ assert-macros/README.google \
+ assert-macros/assert-macros.h \
+ $(NULL)
+
+# fgetln
+EXTRA_DIST += \
+ fgetln/LICENSE \
+ fgetln/README.google \
+ fgetln/fgetln.h \
+ $(NULL)
+
+# Boost
+EXTRA_DIST += \
+ boost/LICENSE \
+ boost/README.google \
+ boost/boost/aligned_storage.hpp \
+ boost/boost/any.hpp \
+ boost/boost/assert.hpp \
+ boost/boost/bind/arg.hpp \
+ boost/boost/bind/bind.hpp \
+ boost/boost/bind/bind_cc.hpp \
+ boost/boost/bind/bind_mf2_cc.hpp \
+ boost/boost/bind/bind_mf_cc.hpp \
+ boost/boost/bind/bind_template.hpp \
+ boost/boost/bind/mem_fn.hpp \
+ boost/boost/bind/mem_fn_cc.hpp \
+ boost/boost/bind/mem_fn_template.hpp \
+ boost/boost/bind/placeholders.hpp \
+ boost/boost/bind/storage.hpp \
+ boost/boost/bind.hpp \
+ boost/boost/blank.hpp \
+ boost/boost/blank_fwd.hpp \
+ boost/boost/call_traits.hpp \
+ boost/boost/checked_delete.hpp \
+ boost/boost/config/compiler/clang.hpp \
+ boost/boost/config/compiler/gcc.hpp \
+ boost/boost/config/no_tr1/functional.hpp \
+ boost/boost/config/no_tr1/memory.hpp \
+ boost/boost/config/platform/linux.hpp \
+ boost/boost/config/platform/macos.hpp \
+ boost/boost/config/posix_features.hpp \
+ boost/boost/config/select_compiler_config.hpp \
+ boost/boost/config/select_platform_config.hpp \
+ boost/boost/config/select_stdlib_config.hpp \
+ boost/boost/config/stdlib/libcpp.hpp \
+ boost/boost/config/stdlib/libstdcpp3.hpp \
+ boost/boost/config/suffix.hpp \
+ boost/boost/config/user.hpp \
+ boost/boost/config.hpp \
+ boost/boost/core/addressof.hpp \
+ boost/boost/core/checked_delete.hpp \
+ boost/boost/core/demangle.hpp \
+ boost/boost/core/enable_if.hpp \
+ boost/boost/core/explicit_operator_bool.hpp \
+ boost/boost/core/is_same.hpp \
+ boost/boost/core/no_exceptions_support.hpp \
+ boost/boost/core/noncopyable.hpp \
+ boost/boost/core/ref.hpp \
+ boost/boost/core/swap.hpp \
+ boost/boost/core/typeinfo.hpp \
+ boost/boost/cstdint.hpp \
+ boost/boost/current_function.hpp \
+ boost/boost/detail/call_traits.hpp \
+ boost/boost/detail/indirect_traits.hpp \
+ boost/boost/detail/iterator.hpp \
+ boost/boost/detail/no_exceptions_support.hpp \
+ boost/boost/detail/reference_content.hpp \
+ boost/boost/detail/sp_typeinfo.hpp \
+ boost/boost/detail/templated_streams.hpp \
+ boost/boost/detail/workaround.hpp \
+ boost/boost/enable_shared_from_this.hpp \
+ boost/boost/exception/exception.hpp \
+ boost/boost/function/detail/function_iterate.hpp \
+ boost/boost/function/detail/maybe_include.hpp \
+ boost/boost/function/detail/prologue.hpp \
+ boost/boost/function/function_base.hpp \
+ boost/boost/function/function_fwd.hpp \
+ boost/boost/function/function_template.hpp \
+ boost/boost/function.hpp \
+ boost/boost/function_equal.hpp \
+ boost/boost/function_output_iterator.hpp \
+ boost/boost/functional/hash/hash_fwd.hpp \
+ boost/boost/functional/hash_fwd.hpp \
+ boost/boost/get_pointer.hpp \
+ boost/boost/integer.hpp \
+ boost/boost/integer_fwd.hpp \
+ boost/boost/integer_traits.hpp \
+ boost/boost/is_placeholder.hpp \
+ boost/boost/iterator/detail/config_def.hpp \
+ boost/boost/iterator/detail/config_undef.hpp \
+ boost/boost/iterator/detail/enable_if.hpp \
+ boost/boost/iterator/detail/facade_iterator_category.hpp \
+ boost/boost/iterator/interoperable.hpp \
+ boost/boost/iterator/iterator_adaptor.hpp \
+ boost/boost/iterator/iterator_categories.hpp \
+ boost/boost/iterator/iterator_facade.hpp \
+ boost/boost/iterator/iterator_traits.hpp \
+ boost/boost/iterator/reverse_iterator.hpp \
+ boost/boost/iterator.hpp \
+ boost/boost/limits.hpp \
+ boost/boost/math/common_factor_ct.hpp \
+ boost/boost/math_fwd.hpp \
+ boost/boost/mem_fn.hpp \
+ boost/boost/move/adl_move_swap.hpp \
+ boost/boost/move/algorithm.hpp \
+ boost/boost/move/core.hpp \
+ boost/boost/move/detail/config_begin.hpp \
+ boost/boost/move/detail/config_end.hpp \
+ boost/boost/move/detail/iterator_traits.hpp \
+ boost/boost/move/detail/meta_utils.hpp \
+ boost/boost/move/detail/meta_utils_core.hpp \
+ boost/boost/move/detail/std_ns_begin.hpp \
+ boost/boost/move/detail/std_ns_end.hpp \
+ boost/boost/move/detail/type_traits.hpp \
+ boost/boost/move/detail/workaround.hpp \
+ boost/boost/move/iterator.hpp \
+ boost/boost/move/move.hpp \
+ boost/boost/move/traits.hpp \
+ boost/boost/move/utility.hpp \
+ boost/boost/move/utility_core.hpp \
+ boost/boost/mpl/O1_size.hpp \
+ boost/boost/mpl/O1_size_fwd.hpp \
+ boost/boost/mpl/advance.hpp \
+ boost/boost/mpl/advance_fwd.hpp \
+ boost/boost/mpl/always.hpp \
+ boost/boost/mpl/and.hpp \
+ boost/boost/mpl/apply.hpp \
+ boost/boost/mpl/apply_fwd.hpp \
+ boost/boost/mpl/apply_wrap.hpp \
+ boost/boost/mpl/arg.hpp \
+ boost/boost/mpl/arg_fwd.hpp \
+ boost/boost/mpl/assert.hpp \
+ boost/boost/mpl/aux_/O1_size_impl.hpp \
+ boost/boost/mpl/aux_/adl_barrier.hpp \
+ boost/boost/mpl/aux_/advance_backward.hpp \
+ boost/boost/mpl/aux_/advance_forward.hpp \
+ boost/boost/mpl/aux_/arg_typedef.hpp \
+ boost/boost/mpl/aux_/arity.hpp \
+ boost/boost/mpl/aux_/arity_spec.hpp \
+ boost/boost/mpl/aux_/begin_end_impl.hpp \
+ boost/boost/mpl/aux_/clear_impl.hpp \
+ boost/boost/mpl/aux_/common_name_wknd.hpp \
+ boost/boost/mpl/aux_/comparison_op.hpp \
+ boost/boost/mpl/aux_/config/adl.hpp \
+ boost/boost/mpl/aux_/config/arrays.hpp \
+ boost/boost/mpl/aux_/config/bcc.hpp \
+ boost/boost/mpl/aux_/config/bind.hpp \
+ boost/boost/mpl/aux_/config/compiler.hpp \
+ boost/boost/mpl/aux_/config/ctps.hpp \
+ boost/boost/mpl/aux_/config/dtp.hpp \
+ boost/boost/mpl/aux_/config/eti.hpp \
+ boost/boost/mpl/aux_/config/forwarding.hpp \
+ boost/boost/mpl/aux_/config/gcc.hpp \
+ boost/boost/mpl/aux_/config/gpu.hpp \
+ boost/boost/mpl/aux_/config/has_apply.hpp \
+ boost/boost/mpl/aux_/config/has_xxx.hpp \
+ boost/boost/mpl/aux_/config/integral.hpp \
+ boost/boost/mpl/aux_/config/intel.hpp \
+ boost/boost/mpl/aux_/config/lambda.hpp \
+ boost/boost/mpl/aux_/config/msvc.hpp \
+ boost/boost/mpl/aux_/config/msvc_typename.hpp \
+ boost/boost/mpl/aux_/config/nttp.hpp \
+ boost/boost/mpl/aux_/config/overload_resolution.hpp \
+ boost/boost/mpl/aux_/config/pp_counter.hpp \
+ boost/boost/mpl/aux_/config/preprocessor.hpp \
+ boost/boost/mpl/aux_/config/static_constant.hpp \
+ boost/boost/mpl/aux_/config/ttp.hpp \
+ boost/boost/mpl/aux_/config/use_preprocessed.hpp \
+ boost/boost/mpl/aux_/config/workaround.hpp \
+ boost/boost/mpl/aux_/empty_impl.hpp \
+ boost/boost/mpl/aux_/find_if_pred.hpp \
+ boost/boost/mpl/aux_/fold_impl.hpp \
+ boost/boost/mpl/aux_/front_impl.hpp \
+ boost/boost/mpl/aux_/full_lambda.hpp \
+ boost/boost/mpl/aux_/has_apply.hpp \
+ boost/boost/mpl/aux_/has_begin.hpp \
+ boost/boost/mpl/aux_/has_size.hpp \
+ boost/boost/mpl/aux_/has_tag.hpp \
+ boost/boost/mpl/aux_/has_type.hpp \
+ boost/boost/mpl/aux_/include_preprocessed.hpp \
+ boost/boost/mpl/aux_/inserter_algorithm.hpp \
+ boost/boost/mpl/aux_/integral_wrapper.hpp \
+ boost/boost/mpl/aux_/is_msvc_eti_arg.hpp \
+ boost/boost/mpl/aux_/iter_apply.hpp \
+ boost/boost/mpl/aux_/iter_fold_if_impl.hpp \
+ boost/boost/mpl/aux_/iter_fold_impl.hpp \
+ boost/boost/mpl/aux_/lambda_arity_param.hpp \
+ boost/boost/mpl/aux_/lambda_spec.hpp \
+ boost/boost/mpl/aux_/lambda_support.hpp \
+ boost/boost/mpl/aux_/msvc_eti_base.hpp \
+ boost/boost/mpl/aux_/msvc_never_true.hpp \
+ boost/boost/mpl/aux_/msvc_type.hpp \
+ boost/boost/mpl/aux_/na.hpp \
+ boost/boost/mpl/aux_/na_assert.hpp \
+ boost/boost/mpl/aux_/na_fwd.hpp \
+ boost/boost/mpl/aux_/na_spec.hpp \
+ boost/boost/mpl/aux_/nested_type_wknd.hpp \
+ boost/boost/mpl/aux_/nttp_decl.hpp \
+ boost/boost/mpl/aux_/numeric_cast_utils.hpp \
+ boost/boost/mpl/aux_/numeric_op.hpp \
+ boost/boost/mpl/aux_/preprocessed/gcc/advance_backward.hpp \
+ boost/boost/mpl/aux_/preprocessed/gcc/advance_forward.hpp \
+ boost/boost/mpl/aux_/preprocessed/gcc/and.hpp \
+ boost/boost/mpl/aux_/preprocessed/gcc/apply.hpp \
+ boost/boost/mpl/aux_/preprocessed/gcc/apply_fwd.hpp \
+ boost/boost/mpl/aux_/preprocessed/gcc/apply_wrap.hpp \
+ boost/boost/mpl/aux_/preprocessed/gcc/arg.hpp \
+ boost/boost/mpl/aux_/preprocessed/gcc/bind.hpp \
+ boost/boost/mpl/aux_/preprocessed/gcc/bind_fwd.hpp \
+ boost/boost/mpl/aux_/preprocessed/gcc/fold_impl.hpp \
+ boost/boost/mpl/aux_/preprocessed/gcc/full_lambda.hpp \
+ boost/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp \
+ boost/boost/mpl/aux_/preprocessed/gcc/iter_fold_impl.hpp \
+ boost/boost/mpl/aux_/preprocessed/gcc/less.hpp \
+ boost/boost/mpl/aux_/preprocessed/gcc/list.hpp \
+ boost/boost/mpl/aux_/preprocessed/gcc/or.hpp \
+ boost/boost/mpl/aux_/preprocessed/gcc/placeholders.hpp \
+ boost/boost/mpl/aux_/preprocessed/gcc/quote.hpp \
+ boost/boost/mpl/aux_/preprocessed/gcc/reverse_fold_impl.hpp \
+ boost/boost/mpl/aux_/preprocessed/gcc/template_arity.hpp \
+ boost/boost/mpl/aux_/preprocessor/def_params_tail.hpp \
+ boost/boost/mpl/aux_/preprocessor/default_params.hpp \
+ boost/boost/mpl/aux_/preprocessor/enum.hpp \
+ boost/boost/mpl/aux_/preprocessor/params.hpp \
+ boost/boost/mpl/aux_/push_back_impl.hpp \
+ boost/boost/mpl/aux_/push_front_impl.hpp \
+ boost/boost/mpl/aux_/reverse_fold_impl.hpp \
+ boost/boost/mpl/aux_/static_cast.hpp \
+ boost/boost/mpl/aux_/template_arity.hpp \
+ boost/boost/mpl/aux_/template_arity_fwd.hpp \
+ boost/boost/mpl/aux_/traits_lambda_spec.hpp \
+ boost/boost/mpl/aux_/type_wrapper.hpp \
+ boost/boost/mpl/aux_/value_wknd.hpp \
+ boost/boost/mpl/aux_/yes_no.hpp \
+ boost/boost/mpl/back_inserter.hpp \
+ boost/boost/mpl/begin_end.hpp \
+ boost/boost/mpl/begin_end_fwd.hpp \
+ boost/boost/mpl/bind.hpp \
+ boost/boost/mpl/bind_fwd.hpp \
+ boost/boost/mpl/bool.hpp \
+ boost/boost/mpl/bool_fwd.hpp \
+ boost/boost/mpl/clear.hpp \
+ boost/boost/mpl/clear_fwd.hpp \
+ boost/boost/mpl/deref.hpp \
+ boost/boost/mpl/distance.hpp \
+ boost/boost/mpl/distance_fwd.hpp \
+ boost/boost/mpl/empty.hpp \
+ boost/boost/mpl/empty_fwd.hpp \
+ boost/boost/mpl/eval_if.hpp \
+ boost/boost/mpl/find_if.hpp \
+ boost/boost/mpl/fold.hpp \
+ boost/boost/mpl/front.hpp \
+ boost/boost/mpl/front_fwd.hpp \
+ boost/boost/mpl/front_inserter.hpp \
+ boost/boost/mpl/has_xxx.hpp \
+ boost/boost/mpl/identity.hpp \
+ boost/boost/mpl/if.hpp \
+ boost/boost/mpl/inserter.hpp \
+ boost/boost/mpl/int.hpp \
+ boost/boost/mpl/int_fwd.hpp \
+ boost/boost/mpl/integral_c.hpp \
+ boost/boost/mpl/integral_c_fwd.hpp \
+ boost/boost/mpl/integral_c_tag.hpp \
+ boost/boost/mpl/is_sequence.hpp \
+ boost/boost/mpl/iter_fold.hpp \
+ boost/boost/mpl/iter_fold_if.hpp \
+ boost/boost/mpl/iterator_category.hpp \
+ boost/boost/mpl/iterator_range.hpp \
+ boost/boost/mpl/iterator_tags.hpp \
+ boost/boost/mpl/lambda.hpp \
+ boost/boost/mpl/lambda_fwd.hpp \
+ boost/boost/mpl/less.hpp \
+ boost/boost/mpl/limits/arity.hpp \
+ boost/boost/mpl/limits/list.hpp \
+ boost/boost/mpl/list/aux_/O1_size.hpp \
+ boost/boost/mpl/list/aux_/begin_end.hpp \
+ boost/boost/mpl/list/aux_/clear.hpp \
+ boost/boost/mpl/list/aux_/empty.hpp \
+ boost/boost/mpl/list/aux_/front.hpp \
+ boost/boost/mpl/list/aux_/include_preprocessed.hpp \
+ boost/boost/mpl/list/aux_/item.hpp \
+ boost/boost/mpl/list/aux_/iterator.hpp \
+ boost/boost/mpl/list/aux_/pop_front.hpp \
+ boost/boost/mpl/list/aux_/preprocessed/plain/list10.hpp \
+ boost/boost/mpl/list/aux_/preprocessed/plain/list20.hpp \
+ boost/boost/mpl/list/aux_/push_back.hpp \
+ boost/boost/mpl/list/aux_/push_front.hpp \
+ boost/boost/mpl/list/aux_/size.hpp \
+ boost/boost/mpl/list/aux_/tag.hpp \
+ boost/boost/mpl/list/list0.hpp \
+ boost/boost/mpl/list/list10.hpp \
+ boost/boost/mpl/list/list20.hpp \
+ boost/boost/mpl/list.hpp \
+ boost/boost/mpl/logical.hpp \
+ boost/boost/mpl/long.hpp \
+ boost/boost/mpl/long_fwd.hpp \
+ boost/boost/mpl/max_element.hpp \
+ boost/boost/mpl/min_max.hpp \
+ boost/boost/mpl/negate.hpp \
+ boost/boost/mpl/next.hpp \
+ boost/boost/mpl/next_prior.hpp \
+ boost/boost/mpl/not.hpp \
+ boost/boost/mpl/numeric_cast.hpp \
+ boost/boost/mpl/or.hpp \
+ boost/boost/mpl/pair.hpp \
+ boost/boost/mpl/pair_view.hpp \
+ boost/boost/mpl/placeholders.hpp \
+ boost/boost/mpl/pop_front_fwd.hpp \
+ boost/boost/mpl/prior.hpp \
+ boost/boost/mpl/protect.hpp \
+ boost/boost/mpl/push_back.hpp \
+ boost/boost/mpl/push_back_fwd.hpp \
+ boost/boost/mpl/push_front.hpp \
+ boost/boost/mpl/push_front_fwd.hpp \
+ boost/boost/mpl/quote.hpp \
+ boost/boost/mpl/reverse_fold.hpp \
+ boost/boost/mpl/same_as.hpp \
+ boost/boost/mpl/sequence_tag.hpp \
+ boost/boost/mpl/sequence_tag_fwd.hpp \
+ boost/boost/mpl/size_fwd.hpp \
+ boost/boost/mpl/size_t.hpp \
+ boost/boost/mpl/size_t_fwd.hpp \
+ boost/boost/mpl/sizeof.hpp \
+ boost/boost/mpl/tag.hpp \
+ boost/boost/mpl/transform.hpp \
+ boost/boost/mpl/void.hpp \
+ boost/boost/mpl/void_fwd.hpp \
+ boost/boost/multi_index/detail/scope_guard.hpp \
+ boost/boost/next_prior.hpp \
+ boost/boost/noncopyable.hpp \
+ boost/boost/none.hpp \
+ boost/boost/none_t.hpp \
+ boost/boost/optional/bad_optional_access.hpp \
+ boost/boost/optional/optional.hpp \
+ boost/boost/optional/optional_fwd.hpp \
+ boost/boost/optional.hpp \
+ boost/boost/predef/architecture/alpha.h \
+ boost/boost/predef/architecture/arm.h \
+ boost/boost/predef/architecture/blackfin.h \
+ boost/boost/predef/architecture/convex.h \
+ boost/boost/predef/architecture/ia64.h \
+ boost/boost/predef/architecture/m68k.h \
+ boost/boost/predef/architecture/mips.h \
+ boost/boost/predef/architecture/parisc.h \
+ boost/boost/predef/architecture/ppc.h \
+ boost/boost/predef/architecture/pyramid.h \
+ boost/boost/predef/architecture/rs6k.h \
+ boost/boost/predef/architecture/sparc.h \
+ boost/boost/predef/architecture/superh.h \
+ boost/boost/predef/architecture/sys370.h \
+ boost/boost/predef/architecture/sys390.h \
+ boost/boost/predef/architecture/x86/32.h \
+ boost/boost/predef/architecture/x86/64.h \
+ boost/boost/predef/architecture/x86.h \
+ boost/boost/predef/architecture/z.h \
+ boost/boost/predef/architecture.h \
+ boost/boost/predef/compiler/borland.h \
+ boost/boost/predef/compiler/clang.h \
+ boost/boost/predef/compiler/comeau.h \
+ boost/boost/predef/compiler/compaq.h \
+ boost/boost/predef/compiler/diab.h \
+ boost/boost/predef/compiler/digitalmars.h \
+ boost/boost/predef/compiler/dignus.h \
+ boost/boost/predef/compiler/edg.h \
+ boost/boost/predef/compiler/ekopath.h \
+ boost/boost/predef/compiler/gcc.h \
+ boost/boost/predef/compiler/gcc_xml.h \
+ boost/boost/predef/compiler/greenhills.h \
+ boost/boost/predef/compiler/hp_acc.h \
+ boost/boost/predef/compiler/iar.h \
+ boost/boost/predef/compiler/ibm.h \
+ boost/boost/predef/compiler/intel.h \
+ boost/boost/predef/compiler/kai.h \
+ boost/boost/predef/compiler/llvm.h \
+ boost/boost/predef/compiler/metaware.h \
+ boost/boost/predef/compiler/metrowerks.h \
+ boost/boost/predef/compiler/microtec.h \
+ boost/boost/predef/compiler/mpw.h \
+ boost/boost/predef/compiler/palm.h \
+ boost/boost/predef/compiler/pgi.h \
+ boost/boost/predef/compiler/sgi_mipspro.h \
+ boost/boost/predef/compiler/sunpro.h \
+ boost/boost/predef/compiler/tendra.h \
+ boost/boost/predef/compiler/visualc.h \
+ boost/boost/predef/compiler/watcom.h \
+ boost/boost/predef/compiler.h \
+ boost/boost/predef/detail/_cassert.h \
+ boost/boost/predef/detail/_exception.h \
+ boost/boost/predef/detail/comp_detected.h \
+ boost/boost/predef/detail/os_detected.h \
+ boost/boost/predef/detail/test.h \
+ boost/boost/predef/hardware/simd/arm/versions.h \
+ boost/boost/predef/hardware/simd/arm.h \
+ boost/boost/predef/hardware/simd/ppc/versions.h \
+ boost/boost/predef/hardware/simd/ppc.h \
+ boost/boost/predef/hardware/simd/x86/versions.h \
+ boost/boost/predef/hardware/simd/x86.h \
+ boost/boost/predef/hardware/simd/x86_amd/versions.h \
+ boost/boost/predef/hardware/simd/x86_amd.h \
+ boost/boost/predef/hardware/simd.h \
+ boost/boost/predef/hardware.h \
+ boost/boost/predef/language/objc.h \
+ boost/boost/predef/language/stdc.h \
+ boost/boost/predef/language/stdcpp.h \
+ boost/boost/predef/language.h \
+ boost/boost/predef/library/c/_prefix.h \
+ boost/boost/predef/library/c/gnu.h \
+ boost/boost/predef/library/c/uc.h \
+ boost/boost/predef/library/c/vms.h \
+ boost/boost/predef/library/c/zos.h \
+ boost/boost/predef/library/c.h \
+ boost/boost/predef/library/std/_prefix.h \
+ boost/boost/predef/library/std/cxx.h \
+ boost/boost/predef/library/std/dinkumware.h \
+ boost/boost/predef/library/std/libcomo.h \
+ boost/boost/predef/library/std/modena.h \
+ boost/boost/predef/library/std/msl.h \
+ boost/boost/predef/library/std/roguewave.h \
+ boost/boost/predef/library/std/sgi.h \
+ boost/boost/predef/library/std/stdcpp3.h \
+ boost/boost/predef/library/std/stlport.h \
+ boost/boost/predef/library/std/vacpp.h \
+ boost/boost/predef/library/std.h \
+ boost/boost/predef/library.h \
+ boost/boost/predef/make.h \
+ boost/boost/predef/os/aix.h \
+ boost/boost/predef/os/amigaos.h \
+ boost/boost/predef/os/android.h \
+ boost/boost/predef/os/beos.h \
+ boost/boost/predef/os/bsd/bsdi.h \
+ boost/boost/predef/os/bsd/dragonfly.h \
+ boost/boost/predef/os/bsd/free.h \
+ boost/boost/predef/os/bsd/net.h \
+ boost/boost/predef/os/bsd/open.h \
+ boost/boost/predef/os/bsd.h \
+ boost/boost/predef/os/cygwin.h \
+ boost/boost/predef/os/haiku.h \
+ boost/boost/predef/os/hpux.h \
+ boost/boost/predef/os/ios.h \
+ boost/boost/predef/os/irix.h \
+ boost/boost/predef/os/linux.h \
+ boost/boost/predef/os/macos.h \
+ boost/boost/predef/os/os400.h \
+ boost/boost/predef/os/qnxnto.h \
+ boost/boost/predef/os/solaris.h \
+ boost/boost/predef/os/unix.h \
+ boost/boost/predef/os/vms.h \
+ boost/boost/predef/os/windows.h \
+ boost/boost/predef/os.h \
+ boost/boost/predef/other/endian.h \
+ boost/boost/predef/other.h \
+ boost/boost/predef/platform/mingw.h \
+ boost/boost/predef/platform/windows_desktop.h \
+ boost/boost/predef/platform/windows_phone.h \
+ boost/boost/predef/platform/windows_runtime.h \
+ boost/boost/predef/platform/windows_store.h \
+ boost/boost/predef/platform.h \
+ boost/boost/predef/version.h \
+ boost/boost/predef/version_number.h \
+ boost/boost/predef.h \
+ boost/boost/preprocessor/arithmetic/add.hpp \
+ boost/boost/preprocessor/arithmetic/dec.hpp \
+ boost/boost/preprocessor/arithmetic/detail/div_base.hpp \
+ boost/boost/preprocessor/arithmetic/div.hpp \
+ boost/boost/preprocessor/arithmetic/inc.hpp \
+ boost/boost/preprocessor/arithmetic/mod.hpp \
+ boost/boost/preprocessor/arithmetic/mul.hpp \
+ boost/boost/preprocessor/arithmetic/sub.hpp \
+ boost/boost/preprocessor/arithmetic.hpp \
+ boost/boost/preprocessor/array/data.hpp \
+ boost/boost/preprocessor/array/elem.hpp \
+ boost/boost/preprocessor/array/size.hpp \
+ boost/boost/preprocessor/cat.hpp \
+ boost/boost/preprocessor/comma_if.hpp \
+ boost/boost/preprocessor/comparison/less_equal.hpp \
+ boost/boost/preprocessor/config/config.hpp \
+ boost/boost/preprocessor/control/detail/while.hpp \
+ boost/boost/preprocessor/control/expr_if.hpp \
+ boost/boost/preprocessor/control/expr_iif.hpp \
+ boost/boost/preprocessor/control/if.hpp \
+ boost/boost/preprocessor/control/iif.hpp \
+ boost/boost/preprocessor/control/while.hpp \
+ boost/boost/preprocessor/debug/error.hpp \
+ boost/boost/preprocessor/detail/auto_rec.hpp \
+ boost/boost/preprocessor/detail/check.hpp \
+ boost/boost/preprocessor/detail/is_binary.hpp \
+ boost/boost/preprocessor/empty.hpp \
+ boost/boost/preprocessor/enum.hpp \
+ boost/boost/preprocessor/enum_params.hpp \
+ boost/boost/preprocessor/enum_shifted_params.hpp \
+ boost/boost/preprocessor/facilities/empty.hpp \
+ boost/boost/preprocessor/facilities/expand.hpp \
+ boost/boost/preprocessor/facilities/identity.hpp \
+ boost/boost/preprocessor/facilities/intercept.hpp \
+ boost/boost/preprocessor/facilities/overload.hpp \
+ boost/boost/preprocessor/identity.hpp \
+ boost/boost/preprocessor/inc.hpp \
+ boost/boost/preprocessor/iterate.hpp \
+ boost/boost/preprocessor/iteration/detail/bounds/lower1.hpp \
+ boost/boost/preprocessor/iteration/detail/bounds/upper1.hpp \
+ boost/boost/preprocessor/iteration/detail/iter/forward1.hpp \
+ boost/boost/preprocessor/iteration/iterate.hpp \
+ boost/boost/preprocessor/iteration/local.hpp \
+ boost/boost/preprocessor/iteration/self.hpp \
+ boost/boost/preprocessor/iteration.hpp \
+ boost/boost/preprocessor/list/adt.hpp \
+ boost/boost/preprocessor/list/detail/fold_left.hpp \
+ boost/boost/preprocessor/list/detail/fold_right.hpp \
+ boost/boost/preprocessor/list/fold_left.hpp \
+ boost/boost/preprocessor/list/fold_right.hpp \
+ boost/boost/preprocessor/list/reverse.hpp \
+ boost/boost/preprocessor/logical/and.hpp \
+ boost/boost/preprocessor/logical/bitand.hpp \
+ boost/boost/preprocessor/logical/bool.hpp \
+ boost/boost/preprocessor/logical/compl.hpp \
+ boost/boost/preprocessor/logical/not.hpp \
+ boost/boost/preprocessor/punctuation/comma.hpp \
+ boost/boost/preprocessor/punctuation/comma_if.hpp \
+ boost/boost/preprocessor/repeat.hpp \
+ boost/boost/preprocessor/repetition/deduce_r.hpp \
+ boost/boost/preprocessor/repetition/deduce_z.hpp \
+ boost/boost/preprocessor/repetition/detail/for.hpp \
+ boost/boost/preprocessor/repetition/enum.hpp \
+ boost/boost/preprocessor/repetition/enum_binary_params.hpp \
+ boost/boost/preprocessor/repetition/enum_params.hpp \
+ boost/boost/preprocessor/repetition/enum_params_with_a_default.hpp \
+ boost/boost/preprocessor/repetition/enum_params_with_defaults.hpp \
+ boost/boost/preprocessor/repetition/enum_shifted.hpp \
+ boost/boost/preprocessor/repetition/enum_shifted_binary_params.hpp \
+ boost/boost/preprocessor/repetition/enum_shifted_params.hpp \
+ boost/boost/preprocessor/repetition/enum_trailing.hpp \
+ boost/boost/preprocessor/repetition/enum_trailing_binary_params.hpp \
+ boost/boost/preprocessor/repetition/enum_trailing_params.hpp \
+ boost/boost/preprocessor/repetition/for.hpp \
+ boost/boost/preprocessor/repetition/repeat.hpp \
+ boost/boost/preprocessor/repetition/repeat_from_to.hpp \
+ boost/boost/preprocessor/repetition.hpp \
+ boost/boost/preprocessor/slot/detail/def.hpp \
+ boost/boost/preprocessor/slot/detail/shared.hpp \
+ boost/boost/preprocessor/slot/slot.hpp \
+ boost/boost/preprocessor/stringize.hpp \
+ boost/boost/preprocessor/tuple/detail/is_single_return.hpp \
+ boost/boost/preprocessor/tuple/eat.hpp \
+ boost/boost/preprocessor/tuple/elem.hpp \
+ boost/boost/preprocessor/tuple/rem.hpp \
+ boost/boost/preprocessor/variadic/elem.hpp \
+ boost/boost/preprocessor/variadic/size.hpp \
+ boost/boost/ref.hpp \
+ boost/boost/scoped_ptr.hpp \
+ boost/boost/shared_ptr.hpp \
+ boost/boost/signals2/connection.hpp \
+ boost/boost/signals2/detail/auto_buffer.hpp \
+ boost/boost/signals2/detail/foreign_ptr.hpp \
+ boost/boost/signals2/detail/lwm_pthreads.hpp \
+ boost/boost/signals2/detail/null_output_iterator.hpp \
+ boost/boost/signals2/detail/preprocessed_arg_type.hpp \
+ boost/boost/signals2/detail/preprocessed_arg_type_template.hpp \
+ boost/boost/signals2/detail/replace_slot_function.hpp \
+ boost/boost/signals2/detail/result_type_wrapper.hpp \
+ boost/boost/signals2/detail/signal_template.hpp \
+ boost/boost/signals2/detail/signals_common.hpp \
+ boost/boost/signals2/detail/signals_common_macros.hpp \
+ boost/boost/signals2/detail/slot_call_iterator.hpp \
+ boost/boost/signals2/detail/slot_groups.hpp \
+ boost/boost/signals2/detail/slot_template.hpp \
+ boost/boost/signals2/detail/tracked_objects_visitor.hpp \
+ boost/boost/signals2/detail/unique_lock.hpp \
+ boost/boost/signals2/expired_slot.hpp \
+ boost/boost/signals2/mutex.hpp \
+ boost/boost/signals2/optional_last_value.hpp \
+ boost/boost/signals2/preprocessed_signal.hpp \
+ boost/boost/signals2/preprocessed_slot.hpp \
+ boost/boost/signals2/signal.hpp \
+ boost/boost/signals2/signal_base.hpp \
+ boost/boost/signals2/slot.hpp \
+ boost/boost/signals2/slot_base.hpp \
+ boost/boost/signals2/trackable.hpp \
+ boost/boost/smart_ptr/bad_weak_ptr.hpp \
+ boost/boost/smart_ptr/detail/operator_bool.hpp \
+ boost/boost/smart_ptr/detail/shared_count.hpp \
+ boost/boost/smart_ptr/detail/sp_convertible.hpp \
+ boost/boost/smart_ptr/detail/sp_counted_base.hpp \
+ boost/boost/smart_ptr/detail/sp_counted_base_clang.hpp \
+ boost/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp \
+ boost/boost/smart_ptr/detail/sp_counted_impl.hpp \
+ boost/boost/smart_ptr/detail/sp_disable_deprecated.hpp \
+ boost/boost/smart_ptr/detail/sp_has_sync.hpp \
+ boost/boost/smart_ptr/detail/sp_nullptr_t.hpp \
+ boost/boost/smart_ptr/detail/spinlock.hpp \
+ boost/boost/smart_ptr/detail/spinlock_pool.hpp \
+ boost/boost/smart_ptr/detail/spinlock_sync.hpp \
+ boost/boost/smart_ptr/detail/yield_k.hpp \
+ boost/boost/smart_ptr/enable_shared_from_this.hpp \
+ boost/boost/smart_ptr/scoped_ptr.hpp \
+ boost/boost/smart_ptr/shared_ptr.hpp \
+ boost/boost/smart_ptr/weak_ptr.hpp \
+ boost/boost/static_assert.hpp \
+ boost/boost/swap.hpp \
+ boost/boost/throw_exception.hpp \
+ boost/boost/type.hpp \
+ boost/boost/type_index/ctti_type_index.hpp \
+ boost/boost/type_index/detail/compile_time_type_info.hpp \
+ boost/boost/type_index/detail/ctti_register_class.hpp \
+ boost/boost/type_index/stl_type_index.hpp \
+ boost/boost/type_index/type_index_facade.hpp \
+ boost/boost/type_index.hpp \
+ boost/boost/type_traits/add_const.hpp \
+ boost/boost/type_traits/add_lvalue_reference.hpp \
+ boost/boost/type_traits/add_pointer.hpp \
+ boost/boost/type_traits/add_reference.hpp \
+ boost/boost/type_traits/add_rvalue_reference.hpp \
+ boost/boost/type_traits/add_volatile.hpp \
+ boost/boost/type_traits/aligned_storage.hpp \
+ boost/boost/type_traits/alignment_of.hpp \
+ boost/boost/type_traits/composite_traits.hpp \
+ boost/boost/type_traits/conditional.hpp \
+ boost/boost/type_traits/decay.hpp \
+ boost/boost/type_traits/declval.hpp \
+ boost/boost/type_traits/detail/config.hpp \
+ boost/boost/type_traits/detail/has_binary_operator.hpp \
+ boost/boost/type_traits/detail/is_function_ptr_helper.hpp \
+ boost/boost/type_traits/detail/is_mem_fun_pointer_impl.hpp \
+ boost/boost/type_traits/detail/yes_no_type.hpp \
+ boost/boost/type_traits/function_traits.hpp \
+ boost/boost/type_traits/has_minus.hpp \
+ boost/boost/type_traits/has_minus_assign.hpp \
+ boost/boost/type_traits/has_nothrow_assign.hpp \
+ boost/boost/type_traits/has_nothrow_constructor.hpp \
+ boost/boost/type_traits/has_nothrow_copy.hpp \
+ boost/boost/type_traits/has_plus.hpp \
+ boost/boost/type_traits/has_plus_assign.hpp \
+ boost/boost/type_traits/has_trivial_assign.hpp \
+ boost/boost/type_traits/has_trivial_constructor.hpp \
+ boost/boost/type_traits/has_trivial_copy.hpp \
+ boost/boost/type_traits/has_trivial_destructor.hpp \
+ boost/boost/type_traits/has_trivial_move_assign.hpp \
+ boost/boost/type_traits/has_trivial_move_constructor.hpp \
+ boost/boost/type_traits/integral_constant.hpp \
+ boost/boost/type_traits/integral_promotion.hpp \
+ boost/boost/type_traits/intrinsics.hpp \
+ boost/boost/type_traits/is_abstract.hpp \
+ boost/boost/type_traits/is_arithmetic.hpp \
+ boost/boost/type_traits/is_array.hpp \
+ boost/boost/type_traits/is_assignable.hpp \
+ boost/boost/type_traits/is_base_and_derived.hpp \
+ boost/boost/type_traits/is_base_of.hpp \
+ boost/boost/type_traits/is_class.hpp \
+ boost/boost/type_traits/is_const.hpp \
+ boost/boost/type_traits/is_convertible.hpp \
+ boost/boost/type_traits/is_copy_constructible.hpp \
+ boost/boost/type_traits/is_default_constructible.hpp \
+ boost/boost/type_traits/is_destructible.hpp \
+ boost/boost/type_traits/is_empty.hpp \
+ boost/boost/type_traits/is_enum.hpp \
+ boost/boost/type_traits/is_floating_point.hpp \
+ boost/boost/type_traits/is_function.hpp \
+ boost/boost/type_traits/is_fundamental.hpp \
+ boost/boost/type_traits/is_integral.hpp \
+ boost/boost/type_traits/is_lvalue_reference.hpp \
+ boost/boost/type_traits/is_member_function_pointer.hpp \
+ boost/boost/type_traits/is_member_pointer.hpp \
+ boost/boost/type_traits/is_nothrow_move_assignable.hpp \
+ boost/boost/type_traits/is_nothrow_move_constructible.hpp \
+ boost/boost/type_traits/is_pod.hpp \
+ boost/boost/type_traits/is_pointer.hpp \
+ boost/boost/type_traits/is_reference.hpp \
+ boost/boost/type_traits/is_rvalue_reference.hpp \
+ boost/boost/type_traits/is_same.hpp \
+ boost/boost/type_traits/is_scalar.hpp \
+ boost/boost/type_traits/is_signed.hpp \
+ boost/boost/type_traits/is_stateless.hpp \
+ boost/boost/type_traits/is_union.hpp \
+ boost/boost/type_traits/is_unsigned.hpp \
+ boost/boost/type_traits/is_void.hpp \
+ boost/boost/type_traits/is_volatile.hpp \
+ boost/boost/type_traits/make_signed.hpp \
+ boost/boost/type_traits/remove_bounds.hpp \
+ boost/boost/type_traits/remove_const.hpp \
+ boost/boost/type_traits/remove_cv.hpp \
+ boost/boost/type_traits/remove_extent.hpp \
+ boost/boost/type_traits/remove_pointer.hpp \
+ boost/boost/type_traits/remove_reference.hpp \
+ boost/boost/type_traits/type_with_alignment.hpp \
+ boost/boost/utility/addressof.hpp \
+ boost/boost/utility/compare_pointees.hpp \
+ boost/boost/utility/declval.hpp \
+ boost/boost/utility/enable_if.hpp \
+ boost/boost/utility/swap.hpp \
+ boost/boost/variant/apply_visitor.hpp \
+ boost/boost/variant/detail/apply_visitor_binary.hpp \
+ boost/boost/variant/detail/apply_visitor_delayed.hpp \
+ boost/boost/variant/detail/apply_visitor_unary.hpp \
+ boost/boost/variant/detail/backup_holder.hpp \
+ boost/boost/variant/detail/cast_storage.hpp \
+ boost/boost/variant/detail/config.hpp \
+ boost/boost/variant/detail/enable_recursive_fwd.hpp \
+ boost/boost/variant/detail/forced_return.hpp \
+ boost/boost/variant/detail/generic_result_type.hpp \
+ boost/boost/variant/detail/has_result_type.hpp \
+ boost/boost/variant/detail/hash_variant.hpp \
+ boost/boost/variant/detail/initializer.hpp \
+ boost/boost/variant/detail/make_variant_list.hpp \
+ boost/boost/variant/detail/move.hpp \
+ boost/boost/variant/detail/over_sequence.hpp \
+ boost/boost/variant/detail/substitute_fwd.hpp \
+ boost/boost/variant/detail/variant_io.hpp \
+ boost/boost/variant/detail/visitation_impl.hpp \
+ boost/boost/variant/recursive_wrapper_fwd.hpp \
+ boost/boost/variant/static_visitor.hpp \
+ boost/boost/variant/variant.hpp \
+ boost/boost/variant/variant_fwd.hpp \
+ boost/boost/version.hpp \
+ boost/boost/visit_each.hpp \
+ boost/boost/weak_ptr.hpp \
+ $(NULL)
diff --git a/third_party/assert-macros/LICENSE b/third_party/assert-macros/LICENSE
new file mode 100644
index 0000000..a25d13c
--- /dev/null
+++ b/third_party/assert-macros/LICENSE
@@ -0,0 +1,26 @@
+MIT License
+===========
+
+Copyright (C) 2013 Robert Quattlebaum
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall
+be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/third_party/assert-macros/README.google b/third_party/assert-macros/README.google
new file mode 100644
index 0000000..c5e47f8
--- /dev/null
+++ b/third_party/assert-macros/README.google
@@ -0,0 +1,12 @@
+URL: https://raw.githubusercontent.com/darconeous/smcp/c3b3d11fbbe0f63aa664320d296694d24ca09b37/src/smcp/assert-macros.h
+Version: c3b3d11fbbe0f63aa664320d296694d24ca09b37
+License: MIT
+License File: LICENSE
+
+Description:
+Introduces an expanded collection of assert macros, including `check()`,
+`require()`, etc.
+
+Local Modifications:
+Minor modifications and improvements. LICENSE file has been created for
+compliance purposes. Not included in original distribution.
diff --git a/third_party/assert-macros/assert-macros.h b/third_party/assert-macros/assert-macros.h
new file mode 100644
index 0000000..f9e838b
--- /dev/null
+++ b/third_party/assert-macros/assert-macros.h
@@ -0,0 +1,164 @@
+/*! @file assert-macros.h
+** @author Robert Quattlebaum <darco@deepdarc.com>
+** @brief "Assert" and "Require" macros
+**
+** MIT-Licensed Version
+**
+** Copyright (C) 2013 Robert Quattlebaum
+**
+** Permission is hereby granted, free of charge, to any person
+** obtaining a copy of this software and associated
+** documentation files (the "Software"), to deal in the
+** Software without restriction, including without limitation
+** the rights to use, copy, modify, merge, publish, distribute,
+** sublicense, and/or sell copies of the Software, and to
+** permit persons to whom the Software is furnished to do so,
+** subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall
+** be included in all copies or substantial portions of the
+** Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+** KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+** WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+** PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+** OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+** OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+** OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**
+** See <http://www.deepdarc.com/> for other cool stuff.
+**
+** -------------------------------------------------------------------
+**
+** See <http://www.mactech.com/articles/develop/issue_11/Parent_final.html>
+** for an explanation about how to use these macros and justification
+** for using this pattern in general.
+*/
+
+#ifndef __DARC_ASSERT_MACROS__
+#define __DARC_ASSERT_MACROS__
+
+#ifndef assert_error_stream
+#if CONTIKI
+#define assert_error_stream stdout
+#else
+#define assert_error_stream stderr
+#endif
+#endif
+
+#if !DEBUG && !defined(NDEBUG)
+#define NDEBUG 1
+#endif
+
+#if ASSERT_MACROS_USE_SYSLOG
+#include <syslog.h>
+#endif
+
+#ifndef ASSERT_MACROS_SQUELCH
+#define ASSERT_MACROS_SQUELCH !DEBUG
+#endif
+
+#ifndef ASSERT_MACROS_SYSLOG_LEVEL
+#define ASSERT_MACROS_SYSLOG_LEVEL LOG_WARNING
+#endif
+
+#ifndef ASSERT_REQUIRE_FAILURE_HOOK
+#define ASSERT_REQUIRE_FAILURE_HOOK do { } while (false)
+#endif
+
+#if HAVE_ASSERTMACROS_H
+ #include <AssertMacros.h>
+#else
+#include <stdio.h>
+#include <assert.h>
+#if ASSERT_MACROS_SQUELCH
+ #define assert_printf(fmt, ...) do { } while (0)
+ #define check_string(c, s) do { } while (0)
+ #define check_noerr(c) do { } while (0)
+ #define require_action_string(c, l, a, s) \
+ do { if (!(c)) { \
+ ASSERT_REQUIRE_FAILURE_HOOK; \
+ a; \
+ goto l; \
+ } } while (0)
+#else
+ #if __AVR__
+ #define assert_printf(fmt, ...) \
+ fprintf_P(assert_error_stream, \
+ PSTR(__FILE__ ":%d: " fmt "\n"), \
+ __LINE__, \
+ __VA_ARGS__)
+ #else
+ #if ASSERT_MACROS_USE_SYSLOG
+ #define assert_printf(fmt, ...) \
+ syslog(ASSERT_MACROS_SYSLOG_LEVEL, \
+ __FILE__ ":%d: " fmt, \
+ __LINE__, \
+ __VA_ARGS__)
+ #elif ASSERT_MACROS_USE_VANILLA_PRINTF
+ #define assert_printf(fmt, ...) \
+ printf(__FILE__ ":%d: " fmt "\n", \
+ __LINE__, \
+ __VA_ARGS__)
+ #else
+ #define assert_printf(fmt, ...) \
+ fprintf(assert_error_stream, \
+ __FILE__ ":%d: " fmt "\n", \
+ __LINE__, \
+ __VA_ARGS__)
+ #endif
+ #endif
+ #define check_string(c, s) \
+ do { if (!(c)) { \
+ assert_printf("Check Failed (%s)", s); \
+ ASSERT_REQUIRE_FAILURE_HOOK; \
+ } } while (0)
+ #define check_noerr(c) \
+ do { \
+ int ASSERT_MACROS_c = (int)c; \
+ if (ASSERT_MACROS_c != 0) { \
+ assert_printf("Check Failed (error %d)", ASSERT_MACROS_c); \
+ ASSERT_REQUIRE_FAILURE_HOOK; \
+ } } while (0)
+ #define require_action_string(c, l, a, s) \
+ do { if (!(c)) { \
+ assert_printf("Requirement Failed (%s)", s); \
+ ASSERT_REQUIRE_FAILURE_HOOK; \
+ a; \
+ goto l; \
+ } } while (0)
+#endif
+
+ #define __ASSERT_MACROS_check(c) check_string(c, # c)
+#if !defined(__cplusplus)
+ #define check(c) __ASSERT_MACROS_check(c)
+#endif
+ #define require_quiet(c, l) do { if (!(c)) goto l; } while (0)
+ #define require(c, l) require_action_string(c, l, {}, # c)
+
+ #define require_noerr(c, l) require((c) == 0, l)
+ #define require_action(c, l, a) require_action_string(c, l, a, # c)
+ #define require_noerr_action(c, l, a) require_action((c) == 0, l, a)
+ #define require_string(c, l, s) \
+ require_action_string(c, l, \
+ do {} while (0), s)
+#endif
+
+#if OVERRIDE_ASSERT_H
+#undef assert
+#undef __assert
+#define assert(e) \
+ ((void)((e) ? 0 : __assert(#e, __FILE__, __LINE__)))
+#define __assert(e, file, line) \
+ do { \
+ assert_printf("failed assertion `%s'", e) ; \
+ abort(); \
+ } while (0)
+#endif // OVERRIDE_ASSERT_H
+
+// Ignores return value from function 's'
+#define IGNORE_RETURN_VALUE(s) do { if (s){} } while (0)
+
+#endif // __DARC_ASSERT_MACROS__
diff --git a/third_party/boost/LICENSE b/third_party/boost/LICENSE
new file mode 100644
index 0000000..36b7cd9
--- /dev/null
+++ b/third_party/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/third_party/boost/README.google b/third_party/boost/README.google
new file mode 100644
index 0000000..bdd133d
--- /dev/null
+++ b/third_party/boost/README.google
@@ -0,0 +1,15 @@
+URL: https://sourceforge.net/projects/boost/files/boost/1.60.0/boost_1_60_0.tar.bz2
+Version: 1.60.0
+License: Boost Software License
+License File: LICENSE
+
+Description:
+Boost is a set of libraries for the C++ programming language that
+provide support for tasks and structures such as linear algebra,
+pseudorandom number generation, multithreading, image processing,
+regular expressions, and unit testing. It contains over eighty
+individual libraries. (Not all of which are included here)
+
+Local Modifications:
+Stripped all unused files.
+
diff --git a/third_party/boost/boost/aligned_storage.hpp b/third_party/boost/boost/aligned_storage.hpp
new file mode 100644
index 0000000..f400fa9
--- /dev/null
+++ b/third_party/boost/boost/aligned_storage.hpp
@@ -0,0 +1,18 @@
+//-----------------------------------------------------------------------------
+// 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 <boost/type_traits/aligned_storage.hpp>
+
+#endif // BOOST_ALIGNED_STORAGE_HPP
diff --git a/third_party/boost/boost/any.hpp b/third_party/boost/boost/any.hpp
new file mode 100644
index 0000000..8a15e37
--- /dev/null
+++ b/third_party/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/third_party/boost/boost/assert.hpp b/third_party/boost/boost/assert.hpp
new file mode 100644
index 0000000..9650d7a
--- /dev/null
+++ b/third_party/boost/boost/assert.hpp
@@ -0,0 +1,85 @@
+//
+// boost/assert.hpp - BOOST_ASSERT(expr)
+// BOOST_ASSERT_MSG(expr, msg)
+// BOOST_VERIFY(expr)
+// BOOST_VERIFY_MSG(expr, msg)
+// BOOST_ASSERT_IS_VOID
+//
+// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
+// Copyright (c) 2007, 2014 Peter Dimov
+// Copyright (c) Beman Dawes 2011
+// Copyright (c) 2015 Ion Gaztanaga
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+// Note: There are no include guards. This is intentional.
+//
+// See http://www.boost.org/libs/assert/assert.html for documentation.
+//
+
+//
+// Stop inspect complaining about use of 'assert':
+//
+// boostinspect:naassert_macro
+//
+
+//
+// BOOST_ASSERT, BOOST_ASSERT_MSG, BOOST_ASSERT_IS_VOID
+//
+
+#undef BOOST_ASSERT
+#undef BOOST_ASSERT_MSG
+#undef BOOST_ASSERT_IS_VOID
+
+#if defined(BOOST_DISABLE_ASSERTS) || ( defined(BOOST_ENABLE_ASSERT_DEBUG_HANDLER) && defined(NDEBUG) )
+
+# define BOOST_ASSERT(expr) ((void)0)
+# define BOOST_ASSERT_MSG(expr, msg) ((void)0)
+# define BOOST_ASSERT_IS_VOID
+
+#elif defined(BOOST_ENABLE_ASSERT_HANDLER) || ( defined(BOOST_ENABLE_ASSERT_DEBUG_HANDLER) && !defined(NDEBUG) )
+
+#include <boost/config.hpp> // for BOOST_LIKELY
+#include <boost/current_function.hpp>
+
+namespace boost
+{
+ void assertion_failed(char const * expr, char const * function, char const * file, long line); // user defined
+ void assertion_failed_msg(char const * expr, char const * msg, char const * function, char const * file, long line); // user defined
+} // namespace boost
+
+#define BOOST_ASSERT(expr) (BOOST_LIKELY(!!(expr))? ((void)0): ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
+#define BOOST_ASSERT_MSG(expr, msg) (BOOST_LIKELY(!!(expr))? ((void)0): ::boost::assertion_failed_msg(#expr, msg, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
+
+#else
+
+# include <assert.h> // .h to support old libraries w/o <cassert> - effect is the same
+
+# define BOOST_ASSERT(expr) assert(expr)
+# define BOOST_ASSERT_MSG(expr, msg) assert((expr)&&(msg))
+#if defined(NDEBUG)
+# define BOOST_ASSERT_IS_VOID
+#endif
+
+#endif
+
+//
+// BOOST_VERIFY, BOOST_VERIFY_MSG
+//
+
+#undef BOOST_VERIFY
+#undef BOOST_VERIFY_MSG
+
+#if defined(BOOST_DISABLE_ASSERTS) || ( !defined(BOOST_ENABLE_ASSERT_HANDLER) && defined(NDEBUG) )
+
+# define BOOST_VERIFY(expr) ((void)(expr))
+# define BOOST_VERIFY_MSG(expr, msg) ((void)(expr))
+
+#else
+
+# define BOOST_VERIFY(expr) BOOST_ASSERT(expr)
+# define BOOST_VERIFY_MSG(expr, msg) BOOST_ASSERT_MSG(expr,msg)
+
+#endif
diff --git a/third_party/boost/boost/bind.hpp b/third_party/boost/boost/bind.hpp
new file mode 100644
index 0000000..450120c
--- /dev/null
+++ b/third_party/boost/boost/bind.hpp
@@ -0,0 +1,41 @@
+#ifndef BOOST_BIND_HPP_INCLUDED
+#define BOOST_BIND_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// bind.hpp - binds function objects to arguments
+//
+// Copyright (c) 2009, 2015 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+// See http://www.boost.org/libs/bind/bind.html for documentation.
+//
+
+#include <boost/bind/bind.hpp>
+
+#ifndef BOOST_BIND_NO_PLACEHOLDERS
+
+#if defined(BOOST_CLANG)
+# pragma clang diagnostic push
+# if __has_warning("-Wheader-hygiene")
+# pragma clang diagnostic ignored "-Wheader-hygiene"
+# endif
+#endif
+
+using namespace boost::placeholders;
+
+#if defined(BOOST_CLANG)
+# pragma clang diagnostic pop
+#endif
+
+#endif // #ifndef BOOST_BIND_NO_PLACEHOLDERS
+
+#endif // #ifndef BOOST_BIND_HPP_INCLUDED
diff --git a/third_party/boost/boost/bind/arg.hpp b/third_party/boost/boost/bind/arg.hpp
new file mode 100644
index 0000000..a74b829
--- /dev/null
+++ b/third_party/boost/boost/bind/arg.hpp
@@ -0,0 +1,62 @@
+#ifndef BOOST_BIND_ARG_HPP_INCLUDED
+#define BOOST_BIND_ARG_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// bind/arg.hpp
+//
+// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/bind/bind.html for documentation.
+//
+
+#include <boost/config.hpp>
+#include <boost/is_placeholder.hpp>
+#include <boost/static_assert.hpp>
+
+namespace boost
+{
+
+template< int I > struct arg
+{
+ BOOST_CONSTEXPR arg()
+ {
+ }
+
+ template< class T > BOOST_CONSTEXPR arg( T const & /* t */ )
+ {
+ BOOST_STATIC_ASSERT( I == is_placeholder<T>::value );
+ }
+};
+
+template< int I > BOOST_CONSTEXPR bool operator==( arg<I> const &, arg<I> const & )
+{
+ return true;
+}
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template< int I > struct is_placeholder< arg<I> >
+{
+ enum _vt { value = I };
+};
+
+template< int I > struct is_placeholder< arg<I> (*) () >
+{
+ enum _vt { value = I };
+};
+
+#endif
+
+} // namespace boost
+
+#endif // #ifndef BOOST_BIND_ARG_HPP_INCLUDED
diff --git a/third_party/boost/boost/bind/bind.hpp b/third_party/boost/boost/bind/bind.hpp
new file mode 100644
index 0000000..5a70fcb
--- /dev/null
+++ b/third_party/boost/boost/bind/bind.hpp
@@ -0,0 +1,2256 @@
+#ifndef BOOST_BIND_BIND_HPP_INCLUDED
+#define BOOST_BIND_BIND_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// bind.hpp - binds function objects to arguments
+//
+// Copyright (c) 2001-2004 Peter Dimov and Multi Media Ltd.
+// Copyright (c) 2001 David Abrahams
+// Copyright (c) 2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/bind/bind.html for documentation.
+//
+
+#include <boost/config.hpp>
+#include <boost/ref.hpp>
+#include <boost/mem_fn.hpp>
+#include <boost/type.hpp>
+#include <boost/is_placeholder.hpp>
+#include <boost/bind/arg.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/visit_each.hpp>
+#include <boost/core/enable_if.hpp>
+#include <boost/core/is_same.hpp>
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+#include <utility> // std::forward
+#endif
+
+// Borland-specific bug, visit_each() silently fails to produce code
+
+#if defined(__BORLANDC__)
+# define BOOST_BIND_VISIT_EACH boost::visit_each
+#else
+# define BOOST_BIND_VISIT_EACH visit_each
+#endif
+
+#include <boost/bind/storage.hpp>
+
+#ifdef BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable: 4512) // assignment operator could not be generated
+#endif
+
+namespace boost
+{
+
+template<class T> class weak_ptr;
+
+namespace _bi // implementation details
+{
+
+// result_traits
+
+template<class R, class F> struct result_traits
+{
+ typedef R type;
+};
+
+#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
+
+struct unspecified {};
+
+template<class F> struct result_traits<unspecified, F>
+{
+ typedef typename F::result_type type;
+};
+
+template<class F> struct result_traits< unspecified, reference_wrapper<F> >
+{
+ typedef typename F::result_type type;
+};
+
+#endif
+
+// ref_compare
+
+template<class T> bool ref_compare( T const & a, T const & b, long )
+{
+ return a == b;
+}
+
+template<int I> bool ref_compare( arg<I> const &, arg<I> const &, int )
+{
+ return true;
+}
+
+template<int I> bool ref_compare( arg<I> (*) (), arg<I> (*) (), int )
+{
+ return true;
+}
+
+template<class T> bool ref_compare( reference_wrapper<T> const & a, reference_wrapper<T> const & b, int )
+{
+ return a.get_pointer() == b.get_pointer();
+}
+
+// bind_t forward declaration for listN
+
+template<class R, class F, class L> class bind_t;
+
+template<class R, class F, class L> bool ref_compare( bind_t<R, F, L> const & a, bind_t<R, F, L> const & b, int )
+{
+ return a.compare( b );
+}
+
+// value
+
+template<class T> class value
+{
+public:
+
+ value(T const & t): t_(t) {}
+
+ T & get() { return t_; }
+ T const & get() const { return t_; }
+
+ bool operator==(value const & rhs) const
+ {
+ return t_ == rhs.t_;
+ }
+
+private:
+
+ T t_;
+};
+
+// ref_compare for weak_ptr
+
+template<class T> bool ref_compare( value< weak_ptr<T> > const & a, value< weak_ptr<T> > const & b, int )
+{
+ return !(a.get() < b.get()) && !(b.get() < a.get());
+}
+
+// type
+
+template<class T> class type {};
+
+// unwrap
+
+template<class F> struct unwrapper
+{
+ static inline F & unwrap( F & f, long )
+ {
+ return f;
+ }
+
+ template<class F2> static inline F2 & unwrap( reference_wrapper<F2> rf, int )
+ {
+ return rf.get();
+ }
+
+ template<class R, class T> static inline _mfi::dm<R, T> unwrap( R T::* pm, int )
+ {
+ return _mfi::dm<R, T>( pm );
+ }
+};
+
+// listN
+
+class list0
+{
+public:
+
+ list0() {}
+
+ template<class T> T & operator[] (_bi::value<T> & v) const { return v.get(); }
+
+ template<class T> T const & operator[] (_bi::value<T> const & v) const { return v.get(); }
+
+ template<class T> T & operator[] (reference_wrapper<T> const & v) const { return v.get(); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> & b) const { return b.eval(*this); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> const & b) const { return b.eval(*this); }
+
+ template<class R, class F, class A> R operator()(type<R>, F & f, A &, long)
+ {
+ return unwrapper<F>::unwrap(f, 0)();
+ }
+
+ template<class R, class F, class A> R operator()(type<R>, F const & f, A &, long) const
+ {
+ return unwrapper<F const>::unwrap(f, 0)();
+ }
+
+ template<class F, class A> void operator()(type<void>, F & f, A &, int)
+ {
+ unwrapper<F>::unwrap(f, 0)();
+ }
+
+ template<class F, class A> void operator()(type<void>, F const & f, A &, int) const
+ {
+ unwrapper<F const>::unwrap(f, 0)();
+ }
+
+ template<class V> void accept(V &) const
+ {
+ }
+
+ bool operator==(list0 const &) const
+ {
+ return true;
+ }
+};
+
+#ifdef BOOST_MSVC
+// MSVC is bright enough to realise that the parameter rhs
+// in operator==may be unused for some template argument types:
+#pragma warning(push)
+#pragma warning(disable:4100)
+#endif
+
+template< class A1 > class list1: private storage1< A1 >
+{
+private:
+
+ typedef storage1< A1 > base_type;
+
+public:
+
+ explicit list1( A1 a1 ): base_type( a1 ) {}
+
+ A1 operator[] (boost::arg<1>) const { return base_type::a1_; }
+
+ A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; }
+
+ template<class T> T & operator[] ( _bi::value<T> & v ) const { return v.get(); }
+
+ template<class T> T const & operator[] ( _bi::value<T> const & v ) const { return v.get(); }
+
+ template<class T> T & operator[] (reference_wrapper<T> const & v) const { return v.get(); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> & b) const { return b.eval(*this); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> const & b) const { return b.eval(*this); }
+
+ template<class R, class F, class A> R operator()(type<R>, F & f, A & a, long)
+ {
+ return unwrapper<F>::unwrap(f, 0)(a[base_type::a1_]);
+ }
+
+ template<class R, class F, class A> R operator()(type<R>, F const & f, A & a, long) const
+ {
+ return unwrapper<F const>::unwrap(f, 0)(a[base_type::a1_]);
+ }
+
+ template<class F, class A> void operator()(type<void>, F & f, A & a, int)
+ {
+ unwrapper<F>::unwrap(f, 0)(a[base_type::a1_]);
+ }
+
+ template<class F, class A> void operator()(type<void>, F const & f, A & a, int) const
+ {
+ unwrapper<F const>::unwrap(f, 0)(a[base_type::a1_]);
+ }
+
+ template<class V> void accept(V & v) const
+ {
+ base_type::accept(v);
+ }
+
+ bool operator==(list1 const & rhs) const
+ {
+ return ref_compare(base_type::a1_, rhs.a1_, 0);
+ }
+};
+
+struct logical_and;
+struct logical_or;
+
+template< class A1, class A2 > class list2: private storage2< A1, A2 >
+{
+private:
+
+ typedef storage2< A1, A2 > base_type;
+
+public:
+
+ list2( A1 a1, A2 a2 ): base_type( a1, a2 ) {}
+
+ A1 operator[] (boost::arg<1>) const { return base_type::a1_; }
+ A2 operator[] (boost::arg<2>) const { return base_type::a2_; }
+
+ A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; }
+ A2 operator[] (boost::arg<2> (*) ()) const { return base_type::a2_; }
+
+ template<class T> T & operator[] (_bi::value<T> & v) const { return v.get(); }
+
+ template<class T> T const & operator[] (_bi::value<T> const & v) const { return v.get(); }
+
+ template<class T> T & operator[] (reference_wrapper<T> const & v) const { return v.get(); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> & b) const { return b.eval(*this); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> const & b) const { return b.eval(*this); }
+
+ template<class R, class F, class A> R operator()(type<R>, F & f, A & a, long)
+ {
+ return unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_]);
+ }
+
+ template<class R, class F, class A> R operator()(type<R>, F const & f, A & a, long) const
+ {
+ return unwrapper<F const>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_]);
+ }
+
+ template<class F, class A> void operator()(type<void>, F & f, A & a, int)
+ {
+ unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_]);
+ }
+
+ template<class F, class A> void operator()(type<void>, F const & f, A & a, int) const
+ {
+ unwrapper<F const>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_]);
+ }
+
+ template<class A> bool operator()( type<bool>, logical_and & /*f*/, A & a, int )
+ {
+ return a[ base_type::a1_ ] && a[ base_type::a2_ ];
+ }
+
+ template<class A> bool operator()( type<bool>, logical_and const & /*f*/, A & a, int ) const
+ {
+ return a[ base_type::a1_ ] && a[ base_type::a2_ ];
+ }
+
+ template<class A> bool operator()( type<bool>, logical_or & /*f*/, A & a, int )
+ {
+ return a[ base_type::a1_ ] || a[ base_type::a2_ ];
+ }
+
+ template<class A> bool operator()( type<bool>, logical_or const & /*f*/, A & a, int ) const
+ {
+ return a[ base_type::a1_ ] || a[ base_type::a2_ ];
+ }
+
+ template<class V> void accept(V & v) const
+ {
+ base_type::accept(v);
+ }
+
+ bool operator==(list2 const & rhs) const
+ {
+ return ref_compare(base_type::a1_, rhs.a1_, 0) && ref_compare(base_type::a2_, rhs.a2_, 0);
+ }
+};
+
+template< class A1, class A2, class A3 > class list3: private storage3< A1, A2, A3 >
+{
+private:
+
+ typedef storage3< A1, A2, A3 > base_type;
+
+public:
+
+ list3( A1 a1, A2 a2, A3 a3 ): base_type( a1, a2, a3 ) {}
+
+ A1 operator[] (boost::arg<1>) const { return base_type::a1_; }
+ A2 operator[] (boost::arg<2>) const { return base_type::a2_; }
+ A3 operator[] (boost::arg<3>) const { return base_type::a3_; }
+
+ A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; }
+ A2 operator[] (boost::arg<2> (*) ()) const { return base_type::a2_; }
+ A3 operator[] (boost::arg<3> (*) ()) const { return base_type::a3_; }
+
+ template<class T> T & operator[] (_bi::value<T> & v) const { return v.get(); }
+
+ template<class T> T const & operator[] (_bi::value<T> const & v) const { return v.get(); }
+
+ template<class T> T & operator[] (reference_wrapper<T> const & v) const { return v.get(); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> & b) const { return b.eval(*this); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> const & b) const { return b.eval(*this); }
+
+ template<class R, class F, class A> R operator()(type<R>, F & f, A & a, long)
+ {
+ return unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_]);
+ }
+
+ template<class R, class F, class A> R operator()(type<R>, F const & f, A & a, long) const
+ {
+ return unwrapper<F const>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_]);
+ }
+
+ template<class F, class A> void operator()(type<void>, F & f, A & a, int)
+ {
+ unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_]);
+ }
+
+ template<class F, class A> void operator()(type<void>, F const & f, A & a, int) const
+ {
+ unwrapper<F const>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_]);
+ }
+
+ template<class V> void accept(V & v) const
+ {
+ base_type::accept(v);
+ }
+
+ bool operator==(list3 const & rhs) const
+ {
+ return
+
+ ref_compare( base_type::a1_, rhs.a1_, 0 ) &&
+ ref_compare( base_type::a2_, rhs.a2_, 0 ) &&
+ ref_compare( base_type::a3_, rhs.a3_, 0 );
+ }
+};
+
+template< class A1, class A2, class A3, class A4 > class list4: private storage4< A1, A2, A3, A4 >
+{
+private:
+
+ typedef storage4< A1, A2, A3, A4 > base_type;
+
+public:
+
+ list4( A1 a1, A2 a2, A3 a3, A4 a4 ): base_type( a1, a2, a3, a4 ) {}
+
+ A1 operator[] (boost::arg<1>) const { return base_type::a1_; }
+ A2 operator[] (boost::arg<2>) const { return base_type::a2_; }
+ A3 operator[] (boost::arg<3>) const { return base_type::a3_; }
+ A4 operator[] (boost::arg<4>) const { return base_type::a4_; }
+
+ A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; }
+ A2 operator[] (boost::arg<2> (*) ()) const { return base_type::a2_; }
+ A3 operator[] (boost::arg<3> (*) ()) const { return base_type::a3_; }
+ A4 operator[] (boost::arg<4> (*) ()) const { return base_type::a4_; }
+
+ template<class T> T & operator[] (_bi::value<T> & v) const { return v.get(); }
+
+ template<class T> T const & operator[] (_bi::value<T> const & v) const { return v.get(); }
+
+ template<class T> T & operator[] (reference_wrapper<T> const & v) const { return v.get(); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> & b) const { return b.eval(*this); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> const & b) const { return b.eval(*this); }
+
+ template<class R, class F, class A> R operator()(type<R>, F & f, A & a, long)
+ {
+ return unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_]);
+ }
+
+ template<class R, class F, class A> R operator()(type<R>, F const & f, A & a, long) const
+ {
+ return unwrapper<F const>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_]);
+ }
+
+ template<class F, class A> void operator()(type<void>, F & f, A & a, int)
+ {
+ unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_]);
+ }
+
+ template<class F, class A> void operator()(type<void>, F const & f, A & a, int) const
+ {
+ unwrapper<F const>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_]);
+ }
+
+ template<class V> void accept(V & v) const
+ {
+ base_type::accept(v);
+ }
+
+ bool operator==(list4 const & rhs) const
+ {
+ return
+
+ ref_compare( base_type::a1_, rhs.a1_, 0 ) &&
+ ref_compare( base_type::a2_, rhs.a2_, 0 ) &&
+ ref_compare( base_type::a3_, rhs.a3_, 0 ) &&
+ ref_compare( base_type::a4_, rhs.a4_, 0 );
+ }
+};
+
+template< class A1, class A2, class A3, class A4, class A5 > class list5: private storage5< A1, A2, A3, A4, A5 >
+{
+private:
+
+ typedef storage5< A1, A2, A3, A4, A5 > base_type;
+
+public:
+
+ list5( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5 ): base_type( a1, a2, a3, a4, a5 ) {}
+
+ A1 operator[] (boost::arg<1>) const { return base_type::a1_; }
+ A2 operator[] (boost::arg<2>) const { return base_type::a2_; }
+ A3 operator[] (boost::arg<3>) const { return base_type::a3_; }
+ A4 operator[] (boost::arg<4>) const { return base_type::a4_; }
+ A5 operator[] (boost::arg<5>) const { return base_type::a5_; }
+
+ A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; }
+ A2 operator[] (boost::arg<2> (*) ()) const { return base_type::a2_; }
+ A3 operator[] (boost::arg<3> (*) ()) const { return base_type::a3_; }
+ A4 operator[] (boost::arg<4> (*) ()) const { return base_type::a4_; }
+ A5 operator[] (boost::arg<5> (*) ()) const { return base_type::a5_; }
+
+ template<class T> T & operator[] (_bi::value<T> & v) const { return v.get(); }
+
+ template<class T> T const & operator[] (_bi::value<T> const & v) const { return v.get(); }
+
+ template<class T> T & operator[] (reference_wrapper<T> const & v) const { return v.get(); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> & b) const { return b.eval(*this); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> const & b) const { return b.eval(*this); }
+
+ template<class R, class F, class A> R operator()(type<R>, F & f, A & a, long)
+ {
+ return unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_]);
+ }
+
+ template<class R, class F, class A> R operator()(type<R>, F const & f, A & a, long) const
+ {
+ return unwrapper<F const>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_]);
+ }
+
+ template<class F, class A> void operator()(type<void>, F & f, A & a, int)
+ {
+ unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_]);
+ }
+
+ template<class F, class A> void operator()(type<void>, F const & f, A & a, int) const
+ {
+ unwrapper<F const>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_]);
+ }
+
+ template<class V> void accept(V & v) const
+ {
+ base_type::accept(v);
+ }
+
+ bool operator==(list5 const & rhs) const
+ {
+ return
+
+ ref_compare( base_type::a1_, rhs.a1_, 0 ) &&
+ ref_compare( base_type::a2_, rhs.a2_, 0 ) &&
+ ref_compare( base_type::a3_, rhs.a3_, 0 ) &&
+ ref_compare( base_type::a4_, rhs.a4_, 0 ) &&
+ ref_compare( base_type::a5_, rhs.a5_, 0 );
+ }
+};
+
+template<class A1, class A2, class A3, class A4, class A5, class A6> class list6: private storage6< A1, A2, A3, A4, A5, A6 >
+{
+private:
+
+ typedef storage6< A1, A2, A3, A4, A5, A6 > base_type;
+
+public:
+
+ list6( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6 ): base_type( a1, a2, a3, a4, a5, a6 ) {}
+
+ A1 operator[] (boost::arg<1>) const { return base_type::a1_; }
+ A2 operator[] (boost::arg<2>) const { return base_type::a2_; }
+ A3 operator[] (boost::arg<3>) const { return base_type::a3_; }
+ A4 operator[] (boost::arg<4>) const { return base_type::a4_; }
+ A5 operator[] (boost::arg<5>) const { return base_type::a5_; }
+ A6 operator[] (boost::arg<6>) const { return base_type::a6_; }
+
+ A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; }
+ A2 operator[] (boost::arg<2> (*) ()) const { return base_type::a2_; }
+ A3 operator[] (boost::arg<3> (*) ()) const { return base_type::a3_; }
+ A4 operator[] (boost::arg<4> (*) ()) const { return base_type::a4_; }
+ A5 operator[] (boost::arg<5> (*) ()) const { return base_type::a5_; }
+ A6 operator[] (boost::arg<6> (*) ()) const { return base_type::a6_; }
+
+ template<class T> T & operator[] (_bi::value<T> & v) const { return v.get(); }
+
+ template<class T> T const & operator[] (_bi::value<T> const & v) const { return v.get(); }
+
+ template<class T> T & operator[] (reference_wrapper<T> const & v) const { return v.get(); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> & b) const { return b.eval(*this); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> const & b) const { return b.eval(*this); }
+
+ template<class R, class F, class A> R operator()(type<R>, F & f, A & a, long)
+ {
+ return unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_]);
+ }
+
+ template<class R, class F, class A> R operator()(type<R>, F const & f, A & a, long) const
+ {
+ return unwrapper<F const>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_]);
+ }
+
+ template<class F, class A> void operator()(type<void>, F & f, A & a, int)
+ {
+ unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_]);
+ }
+
+ template<class F, class A> void operator()(type<void>, F const & f, A & a, int) const
+ {
+ unwrapper<F const>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_]);
+ }
+
+ template<class V> void accept(V & v) const
+ {
+ base_type::accept(v);
+ }
+
+ bool operator==(list6 const & rhs) const
+ {
+ return
+
+ ref_compare( base_type::a1_, rhs.a1_, 0 ) &&
+ ref_compare( base_type::a2_, rhs.a2_, 0 ) &&
+ ref_compare( base_type::a3_, rhs.a3_, 0 ) &&
+ ref_compare( base_type::a4_, rhs.a4_, 0 ) &&
+ ref_compare( base_type::a5_, rhs.a5_, 0 ) &&
+ ref_compare( base_type::a6_, rhs.a6_, 0 );
+ }
+};
+
+template<class A1, class A2, class A3, class A4, class A5, class A6, class A7> class list7: private storage7< A1, A2, A3, A4, A5, A6, A7 >
+{
+private:
+
+ typedef storage7< A1, A2, A3, A4, A5, A6, A7 > base_type;
+
+public:
+
+ list7( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7 ): base_type( a1, a2, a3, a4, a5, a6, a7 ) {}
+
+ A1 operator[] (boost::arg<1>) const { return base_type::a1_; }
+ A2 operator[] (boost::arg<2>) const { return base_type::a2_; }
+ A3 operator[] (boost::arg<3>) const { return base_type::a3_; }
+ A4 operator[] (boost::arg<4>) const { return base_type::a4_; }
+ A5 operator[] (boost::arg<5>) const { return base_type::a5_; }
+ A6 operator[] (boost::arg<6>) const { return base_type::a6_; }
+ A7 operator[] (boost::arg<7>) const { return base_type::a7_; }
+
+ A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; }
+ A2 operator[] (boost::arg<2> (*) ()) const { return base_type::a2_; }
+ A3 operator[] (boost::arg<3> (*) ()) const { return base_type::a3_; }
+ A4 operator[] (boost::arg<4> (*) ()) const { return base_type::a4_; }
+ A5 operator[] (boost::arg<5> (*) ()) const { return base_type::a5_; }
+ A6 operator[] (boost::arg<6> (*) ()) const { return base_type::a6_; }
+ A7 operator[] (boost::arg<7> (*) ()) const { return base_type::a7_; }
+
+ template<class T> T & operator[] (_bi::value<T> & v) const { return v.get(); }
+
+ template<class T> T const & operator[] (_bi::value<T> const & v) const { return v.get(); }
+
+ template<class T> T & operator[] (reference_wrapper<T> const & v) const { return v.get(); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> & b) const { return b.eval(*this); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> const & b) const { return b.eval(*this); }
+
+ template<class R, class F, class A> R operator()(type<R>, F & f, A & a, long)
+ {
+ return unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_]);
+ }
+
+ template<class R, class F, class A> R operator()(type<R>, F const & f, A & a, long) const
+ {
+ return unwrapper<F const>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_]);
+ }
+
+ template<class F, class A> void operator()(type<void>, F & f, A & a, int)
+ {
+ unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_]);
+ }
+
+ template<class F, class A> void operator()(type<void>, F const & f, A & a, int) const
+ {
+ unwrapper<F const>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_]);
+ }
+
+ template<class V> void accept(V & v) const
+ {
+ base_type::accept(v);
+ }
+
+ bool operator==(list7 const & rhs) const
+ {
+ return
+
+ ref_compare( base_type::a1_, rhs.a1_, 0 ) &&
+ ref_compare( base_type::a2_, rhs.a2_, 0 ) &&
+ ref_compare( base_type::a3_, rhs.a3_, 0 ) &&
+ ref_compare( base_type::a4_, rhs.a4_, 0 ) &&
+ ref_compare( base_type::a5_, rhs.a5_, 0 ) &&
+ ref_compare( base_type::a6_, rhs.a6_, 0 ) &&
+ ref_compare( base_type::a7_, rhs.a7_, 0 );
+ }
+};
+
+template< class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > class list8: private storage8< A1, A2, A3, A4, A5, A6, A7, A8 >
+{
+private:
+
+ typedef storage8< A1, A2, A3, A4, A5, A6, A7, A8 > base_type;
+
+public:
+
+ list8( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8 ): base_type( a1, a2, a3, a4, a5, a6, a7, a8 ) {}
+
+ A1 operator[] (boost::arg<1>) const { return base_type::a1_; }
+ A2 operator[] (boost::arg<2>) const { return base_type::a2_; }
+ A3 operator[] (boost::arg<3>) const { return base_type::a3_; }
+ A4 operator[] (boost::arg<4>) const { return base_type::a4_; }
+ A5 operator[] (boost::arg<5>) const { return base_type::a5_; }
+ A6 operator[] (boost::arg<6>) const { return base_type::a6_; }
+ A7 operator[] (boost::arg<7>) const { return base_type::a7_; }
+ A8 operator[] (boost::arg<8>) const { return base_type::a8_; }
+
+ A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; }
+ A2 operator[] (boost::arg<2> (*) ()) const { return base_type::a2_; }
+ A3 operator[] (boost::arg<3> (*) ()) const { return base_type::a3_; }
+ A4 operator[] (boost::arg<4> (*) ()) const { return base_type::a4_; }
+ A5 operator[] (boost::arg<5> (*) ()) const { return base_type::a5_; }
+ A6 operator[] (boost::arg<6> (*) ()) const { return base_type::a6_; }
+ A7 operator[] (boost::arg<7> (*) ()) const { return base_type::a7_; }
+ A8 operator[] (boost::arg<8> (*) ()) const { return base_type::a8_; }
+
+ template<class T> T & operator[] (_bi::value<T> & v) const { return v.get(); }
+
+ template<class T> T const & operator[] (_bi::value<T> const & v) const { return v.get(); }
+
+ template<class T> T & operator[] (reference_wrapper<T> const & v) const { return v.get(); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> & b) const { return b.eval(*this); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> const & b) const { return b.eval(*this); }
+
+ template<class R, class F, class A> R operator()(type<R>, F & f, A & a, long)
+ {
+ return unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_], a[base_type::a8_]);
+ }
+
+ template<class R, class F, class A> R operator()(type<R>, F const & f, A & a, long) const
+ {
+ return unwrapper<F const>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_], a[base_type::a8_]);
+ }
+
+ template<class F, class A> void operator()(type<void>, F & f, A & a, int)
+ {
+ unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_], a[base_type::a8_]);
+ }
+
+ template<class F, class A> void operator()(type<void>, F const & f, A & a, int) const
+ {
+ unwrapper<F const>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_], a[base_type::a8_]);
+ }
+
+ template<class V> void accept(V & v) const
+ {
+ base_type::accept(v);
+ }
+
+ bool operator==(list8 const & rhs) const
+ {
+ return
+
+ ref_compare( base_type::a1_, rhs.a1_, 0 ) &&
+ ref_compare( base_type::a2_, rhs.a2_, 0 ) &&
+ ref_compare( base_type::a3_, rhs.a3_, 0 ) &&
+ ref_compare( base_type::a4_, rhs.a4_, 0 ) &&
+ ref_compare( base_type::a5_, rhs.a5_, 0 ) &&
+ ref_compare( base_type::a6_, rhs.a6_, 0 ) &&
+ ref_compare( base_type::a7_, rhs.a7_, 0 ) &&
+ ref_compare( base_type::a8_, rhs.a8_, 0 );
+ }
+};
+
+template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> class list9: private storage9< A1, A2, A3, A4, A5, A6, A7, A8, A9 >
+{
+private:
+
+ typedef storage9< A1, A2, A3, A4, A5, A6, A7, A8, A9 > base_type;
+
+public:
+
+ list9( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9 ): base_type( a1, a2, a3, a4, a5, a6, a7, a8, a9 ) {}
+
+ A1 operator[] (boost::arg<1>) const { return base_type::a1_; }
+ A2 operator[] (boost::arg<2>) const { return base_type::a2_; }
+ A3 operator[] (boost::arg<3>) const { return base_type::a3_; }
+ A4 operator[] (boost::arg<4>) const { return base_type::a4_; }
+ A5 operator[] (boost::arg<5>) const { return base_type::a5_; }
+ A6 operator[] (boost::arg<6>) const { return base_type::a6_; }
+ A7 operator[] (boost::arg<7>) const { return base_type::a7_; }
+ A8 operator[] (boost::arg<8>) const { return base_type::a8_; }
+ A9 operator[] (boost::arg<9>) const { return base_type::a9_; }
+
+ A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; }
+ A2 operator[] (boost::arg<2> (*) ()) const { return base_type::a2_; }
+ A3 operator[] (boost::arg<3> (*) ()) const { return base_type::a3_; }
+ A4 operator[] (boost::arg<4> (*) ()) const { return base_type::a4_; }
+ A5 operator[] (boost::arg<5> (*) ()) const { return base_type::a5_; }
+ A6 operator[] (boost::arg<6> (*) ()) const { return base_type::a6_; }
+ A7 operator[] (boost::arg<7> (*) ()) const { return base_type::a7_; }
+ A8 operator[] (boost::arg<8> (*) ()) const { return base_type::a8_; }
+ A9 operator[] (boost::arg<9> (*) ()) const { return base_type::a9_; }
+
+ template<class T> T & operator[] (_bi::value<T> & v) const { return v.get(); }
+
+ template<class T> T const & operator[] (_bi::value<T> const & v) const { return v.get(); }
+
+ template<class T> T & operator[] (reference_wrapper<T> const & v) const { return v.get(); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> & b) const { return b.eval(*this); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> const & b) const { return b.eval(*this); }
+
+ template<class R, class F, class A> R operator()(type<R>, F & f, A & a, long)
+ {
+ return unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_], a[base_type::a8_], a[base_type::a9_]);
+ }
+
+ template<class R, class F, class A> R operator()(type<R>, F const & f, A & a, long) const
+ {
+ return unwrapper<F const>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_], a[base_type::a8_], a[base_type::a9_]);
+ }
+
+ template<class F, class A> void operator()(type<void>, F & f, A & a, int)
+ {
+ unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_], a[base_type::a8_], a[base_type::a9_]);
+ }
+
+ template<class F, class A> void operator()(type<void>, F const & f, A & a, int) const
+ {
+ unwrapper<F const>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_], a[base_type::a3_], a[base_type::a4_], a[base_type::a5_], a[base_type::a6_], a[base_type::a7_], a[base_type::a8_], a[base_type::a9_]);
+ }
+
+ template<class V> void accept(V & v) const
+ {
+ base_type::accept(v);
+ }
+
+ bool operator==(list9 const & rhs) const
+ {
+ return
+
+ ref_compare( base_type::a1_, rhs.a1_, 0 ) &&
+ ref_compare( base_type::a2_, rhs.a2_, 0 ) &&
+ ref_compare( base_type::a3_, rhs.a3_, 0 ) &&
+ ref_compare( base_type::a4_, rhs.a4_, 0 ) &&
+ ref_compare( base_type::a5_, rhs.a5_, 0 ) &&
+ ref_compare( base_type::a6_, rhs.a6_, 0 ) &&
+ ref_compare( base_type::a7_, rhs.a7_, 0 ) &&
+ ref_compare( base_type::a8_, rhs.a8_, 0 ) &&
+ ref_compare( base_type::a9_, rhs.a9_, 0 );
+ }
+};
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+// bind_t
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+template< class A1 > class rrlist1
+{
+private:
+
+ A1 & a1_; // not A1&& because of msvc-10.0
+
+public:
+
+ explicit rrlist1( A1 & a1 ): a1_( a1 ) {}
+
+ A1 && operator[] (boost::arg<1>) const { return std::forward<A1>( a1_ ); } // not static_cast because of g++ 4.9
+
+ A1 && operator[] (boost::arg<1> (*) ()) const { return std::forward<A1>( a1_ ); }
+
+ template<class T> T & operator[] ( _bi::value<T> & v ) const { return v.get(); }
+
+ template<class T> T const & operator[] ( _bi::value<T> const & v ) const { return v.get(); }
+
+ template<class T> T & operator[] (reference_wrapper<T> const & v) const { return v.get(); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> & b) const { return b.eval(*this); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> const & b) const { return b.eval(*this); }
+};
+
+template< class A1, class A2 > class rrlist2
+{
+private:
+
+ A1 & a1_;
+ A2 & a2_;
+
+public:
+
+ rrlist2( A1 & a1, A2 & a2 ): a1_( a1 ), a2_( a2 ) {}
+
+ A1 && operator[] (boost::arg<1>) const { return std::forward<A1>( a1_ ); }
+ A2 && operator[] (boost::arg<2>) const { return std::forward<A2>( a2_ ); }
+
+ A1 && operator[] (boost::arg<1> (*) ()) const { return std::forward<A1>( a1_ ); }
+ A2 && operator[] (boost::arg<2> (*) ()) const { return std::forward<A2>( a2_ ); }
+
+ template<class T> T & operator[] ( _bi::value<T> & v ) const { return v.get(); }
+
+ template<class T> T const & operator[] ( _bi::value<T> const & v ) const { return v.get(); }
+
+ template<class T> T & operator[] (reference_wrapper<T> const & v) const { return v.get(); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> & b) const { return b.eval(*this); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> const & b) const { return b.eval(*this); }
+};
+
+template< class A1, class A2, class A3 > class rrlist3
+{
+private:
+
+ A1 & a1_;
+ A2 & a2_;
+ A3 & a3_;
+
+public:
+
+ rrlist3( A1 & a1, A2 & a2, A3 & a3 ): a1_( a1 ), a2_( a2 ), a3_( a3 ) {}
+
+ A1 && operator[] (boost::arg<1>) const { return std::forward<A1>( a1_ ); }
+ A2 && operator[] (boost::arg<2>) const { return std::forward<A2>( a2_ ); }
+ A3 && operator[] (boost::arg<3>) const { return std::forward<A3>( a3_ ); }
+
+ A1 && operator[] (boost::arg<1> (*) ()) const { return std::forward<A1>( a1_ ); }
+ A2 && operator[] (boost::arg<2> (*) ()) const { return std::forward<A2>( a2_ ); }
+ A3 && operator[] (boost::arg<3> (*) ()) const { return std::forward<A3>( a3_ ); }
+
+ template<class T> T & operator[] ( _bi::value<T> & v ) const { return v.get(); }
+
+ template<class T> T const & operator[] ( _bi::value<T> const & v ) const { return v.get(); }
+
+ template<class T> T & operator[] (reference_wrapper<T> const & v) const { return v.get(); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> & b) const { return b.eval(*this); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> const & b) const { return b.eval(*this); }
+};
+
+template< class A1, class A2, class A3, class A4 > class rrlist4
+{
+private:
+
+ A1 & a1_;
+ A2 & a2_;
+ A3 & a3_;
+ A4 & a4_;
+
+public:
+
+ rrlist4( A1 & a1, A2 & a2, A3 & a3, A4 & a4 ): a1_( a1 ), a2_( a2 ), a3_( a3 ), a4_( a4 ) {}
+
+ A1 && operator[] (boost::arg<1>) const { return std::forward<A1>( a1_ ); }
+ A2 && operator[] (boost::arg<2>) const { return std::forward<A2>( a2_ ); }
+ A3 && operator[] (boost::arg<3>) const { return std::forward<A3>( a3_ ); }
+ A4 && operator[] (boost::arg<4>) const { return std::forward<A4>( a4_ ); }
+
+ A1 && operator[] (boost::arg<1> (*) ()) const { return std::forward<A1>( a1_ ); }
+ A2 && operator[] (boost::arg<2> (*) ()) const { return std::forward<A2>( a2_ ); }
+ A3 && operator[] (boost::arg<3> (*) ()) const { return std::forward<A3>( a3_ ); }
+ A4 && operator[] (boost::arg<4> (*) ()) const { return std::forward<A4>( a4_ ); }
+
+ template<class T> T & operator[] ( _bi::value<T> & v ) const { return v.get(); }
+
+ template<class T> T const & operator[] ( _bi::value<T> const & v ) const { return v.get(); }
+
+ template<class T> T & operator[] (reference_wrapper<T> const & v) const { return v.get(); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> & b) const { return b.eval(*this); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> const & b) const { return b.eval(*this); }
+};
+
+template< class A1, class A2, class A3, class A4, class A5 > class rrlist5
+{
+private:
+
+ A1 & a1_;
+ A2 & a2_;
+ A3 & a3_;
+ A4 & a4_;
+ A5 & a5_;
+
+public:
+
+ rrlist5( A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5 ): a1_( a1 ), a2_( a2 ), a3_( a3 ), a4_( a4 ), a5_( a5 ) {}
+
+ A1 && operator[] (boost::arg<1>) const { return std::forward<A1>( a1_ ); }
+ A2 && operator[] (boost::arg<2>) const { return std::forward<A2>( a2_ ); }
+ A3 && operator[] (boost::arg<3>) const { return std::forward<A3>( a3_ ); }
+ A4 && operator[] (boost::arg<4>) const { return std::forward<A4>( a4_ ); }
+ A5 && operator[] (boost::arg<5>) const { return std::forward<A5>( a5_ ); }
+
+ A1 && operator[] (boost::arg<1> (*) ()) const { return std::forward<A1>( a1_ ); }
+ A2 && operator[] (boost::arg<2> (*) ()) const { return std::forward<A2>( a2_ ); }
+ A3 && operator[] (boost::arg<3> (*) ()) const { return std::forward<A3>( a3_ ); }
+ A4 && operator[] (boost::arg<4> (*) ()) const { return std::forward<A4>( a4_ ); }
+ A5 && operator[] (boost::arg<5> (*) ()) const { return std::forward<A5>( a5_ ); }
+
+ template<class T> T & operator[] ( _bi::value<T> & v ) const { return v.get(); }
+
+ template<class T> T const & operator[] ( _bi::value<T> const & v ) const { return v.get(); }
+
+ template<class T> T & operator[] (reference_wrapper<T> const & v) const { return v.get(); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> & b) const { return b.eval(*this); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> const & b) const { return b.eval(*this); }
+};
+
+template< class A1, class A2, class A3, class A4, class A5, class A6 > class rrlist6
+{
+private:
+
+ A1 & a1_;
+ A2 & a2_;
+ A3 & a3_;
+ A4 & a4_;
+ A5 & a5_;
+ A6 & a6_;
+
+public:
+
+ rrlist6( A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6 ): a1_( a1 ), a2_( a2 ), a3_( a3 ), a4_( a4 ), a5_( a5 ), a6_( a6 ) {}
+
+ A1 && operator[] (boost::arg<1>) const { return std::forward<A1>( a1_ ); }
+ A2 && operator[] (boost::arg<2>) const { return std::forward<A2>( a2_ ); }
+ A3 && operator[] (boost::arg<3>) const { return std::forward<A3>( a3_ ); }
+ A4 && operator[] (boost::arg<4>) const { return std::forward<A4>( a4_ ); }
+ A5 && operator[] (boost::arg<5>) const { return std::forward<A5>( a5_ ); }
+ A6 && operator[] (boost::arg<6>) const { return std::forward<A6>( a6_ ); }
+
+ A1 && operator[] (boost::arg<1> (*) ()) const { return std::forward<A1>( a1_ ); }
+ A2 && operator[] (boost::arg<2> (*) ()) const { return std::forward<A2>( a2_ ); }
+ A3 && operator[] (boost::arg<3> (*) ()) const { return std::forward<A3>( a3_ ); }
+ A4 && operator[] (boost::arg<4> (*) ()) const { return std::forward<A4>( a4_ ); }
+ A5 && operator[] (boost::arg<5> (*) ()) const { return std::forward<A5>( a5_ ); }
+ A6 && operator[] (boost::arg<6> (*) ()) const { return std::forward<A6>( a6_ ); }
+
+ template<class T> T & operator[] ( _bi::value<T> & v ) const { return v.get(); }
+
+ template<class T> T const & operator[] ( _bi::value<T> const & v ) const { return v.get(); }
+
+ template<class T> T & operator[] (reference_wrapper<T> const & v) const { return v.get(); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> & b) const { return b.eval(*this); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> const & b) const { return b.eval(*this); }
+};
+
+template< class A1, class A2, class A3, class A4, class A5, class A6, class A7 > class rrlist7
+{
+private:
+
+ A1 & a1_;
+ A2 & a2_;
+ A3 & a3_;
+ A4 & a4_;
+ A5 & a5_;
+ A6 & a6_;
+ A7 & a7_;
+
+public:
+
+ rrlist7( A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7 ): a1_( a1 ), a2_( a2 ), a3_( a3 ), a4_( a4 ), a5_( a5 ), a6_( a6 ), a7_( a7 ) {}
+
+ A1 && operator[] (boost::arg<1>) const { return std::forward<A1>( a1_ ); }
+ A2 && operator[] (boost::arg<2>) const { return std::forward<A2>( a2_ ); }
+ A3 && operator[] (boost::arg<3>) const { return std::forward<A3>( a3_ ); }
+ A4 && operator[] (boost::arg<4>) const { return std::forward<A4>( a4_ ); }
+ A5 && operator[] (boost::arg<5>) const { return std::forward<A5>( a5_ ); }
+ A6 && operator[] (boost::arg<6>) const { return std::forward<A6>( a6_ ); }
+ A7 && operator[] (boost::arg<7>) const { return std::forward<A7>( a7_ ); }
+
+ A1 && operator[] (boost::arg<1> (*) ()) const { return std::forward<A1>( a1_ ); }
+ A2 && operator[] (boost::arg<2> (*) ()) const { return std::forward<A2>( a2_ ); }
+ A3 && operator[] (boost::arg<3> (*) ()) const { return std::forward<A3>( a3_ ); }
+ A4 && operator[] (boost::arg<4> (*) ()) const { return std::forward<A4>( a4_ ); }
+ A5 && operator[] (boost::arg<5> (*) ()) const { return std::forward<A5>( a5_ ); }
+ A6 && operator[] (boost::arg<6> (*) ()) const { return std::forward<A6>( a6_ ); }
+ A7 && operator[] (boost::arg<7> (*) ()) const { return std::forward<A7>( a7_ ); }
+
+ template<class T> T & operator[] ( _bi::value<T> & v ) const { return v.get(); }
+
+ template<class T> T const & operator[] ( _bi::value<T> const & v ) const { return v.get(); }
+
+ template<class T> T & operator[] (reference_wrapper<T> const & v) const { return v.get(); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> & b) const { return b.eval(*this); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> const & b) const { return b.eval(*this); }
+};
+
+template< class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 > class rrlist8
+{
+private:
+
+ A1 & a1_;
+ A2 & a2_;
+ A3 & a3_;
+ A4 & a4_;
+ A5 & a5_;
+ A6 & a6_;
+ A7 & a7_;
+ A8 & a8_;
+
+public:
+
+ rrlist8( A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8 ): a1_( a1 ), a2_( a2 ), a3_( a3 ), a4_( a4 ), a5_( a5 ), a6_( a6 ), a7_( a7 ), a8_( a8 ) {}
+
+ A1 && operator[] (boost::arg<1>) const { return std::forward<A1>( a1_ ); }
+ A2 && operator[] (boost::arg<2>) const { return std::forward<A2>( a2_ ); }
+ A3 && operator[] (boost::arg<3>) const { return std::forward<A3>( a3_ ); }
+ A4 && operator[] (boost::arg<4>) const { return std::forward<A4>( a4_ ); }
+ A5 && operator[] (boost::arg<5>) const { return std::forward<A5>( a5_ ); }
+ A6 && operator[] (boost::arg<6>) const { return std::forward<A6>( a6_ ); }
+ A7 && operator[] (boost::arg<7>) const { return std::forward<A7>( a7_ ); }
+ A8 && operator[] (boost::arg<8>) const { return std::forward<A8>( a8_ ); }
+
+ A1 && operator[] (boost::arg<1> (*) ()) const { return std::forward<A1>( a1_ ); }
+ A2 && operator[] (boost::arg<2> (*) ()) const { return std::forward<A2>( a2_ ); }
+ A3 && operator[] (boost::arg<3> (*) ()) const { return std::forward<A3>( a3_ ); }
+ A4 && operator[] (boost::arg<4> (*) ()) const { return std::forward<A4>( a4_ ); }
+ A5 && operator[] (boost::arg<5> (*) ()) const { return std::forward<A5>( a5_ ); }
+ A6 && operator[] (boost::arg<6> (*) ()) const { return std::forward<A6>( a6_ ); }
+ A7 && operator[] (boost::arg<7> (*) ()) const { return std::forward<A7>( a7_ ); }
+ A8 && operator[] (boost::arg<8> (*) ()) const { return std::forward<A8>( a8_ ); }
+
+ template<class T> T & operator[] ( _bi::value<T> & v ) const { return v.get(); }
+
+ template<class T> T const & operator[] ( _bi::value<T> const & v ) const { return v.get(); }
+
+ template<class T> T & operator[] (reference_wrapper<T> const & v) const { return v.get(); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> & b) const { return b.eval(*this); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> const & b) const { return b.eval(*this); }
+};
+
+template< class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 > class rrlist9
+{
+private:
+
+ A1 & a1_;
+ A2 & a2_;
+ A3 & a3_;
+ A4 & a4_;
+ A5 & a5_;
+ A6 & a6_;
+ A7 & a7_;
+ A8 & a8_;
+ A9 & a9_;
+
+public:
+
+ rrlist9( A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8, A9 & a9 ): a1_( a1 ), a2_( a2 ), a3_( a3 ), a4_( a4 ), a5_( a5 ), a6_( a6 ), a7_( a7 ), a8_( a8 ), a9_( a9 ) {}
+
+ A1 && operator[] (boost::arg<1>) const { return std::forward<A1>( a1_ ); }
+ A2 && operator[] (boost::arg<2>) const { return std::forward<A2>( a2_ ); }
+ A3 && operator[] (boost::arg<3>) const { return std::forward<A3>( a3_ ); }
+ A4 && operator[] (boost::arg<4>) const { return std::forward<A4>( a4_ ); }
+ A5 && operator[] (boost::arg<5>) const { return std::forward<A5>( a5_ ); }
+ A6 && operator[] (boost::arg<6>) const { return std::forward<A6>( a6_ ); }
+ A7 && operator[] (boost::arg<7>) const { return std::forward<A7>( a7_ ); }
+ A8 && operator[] (boost::arg<8>) const { return std::forward<A8>( a8_ ); }
+ A9 && operator[] (boost::arg<9>) const { return std::forward<A9>( a9_ ); }
+
+ A1 && operator[] (boost::arg<1> (*) ()) const { return std::forward<A1>( a1_ ); }
+ A2 && operator[] (boost::arg<2> (*) ()) const { return std::forward<A2>( a2_ ); }
+ A3 && operator[] (boost::arg<3> (*) ()) const { return std::forward<A3>( a3_ ); }
+ A4 && operator[] (boost::arg<4> (*) ()) const { return std::forward<A4>( a4_ ); }
+ A5 && operator[] (boost::arg<5> (*) ()) const { return std::forward<A5>( a5_ ); }
+ A6 && operator[] (boost::arg<6> (*) ()) const { return std::forward<A6>( a6_ ); }
+ A7 && operator[] (boost::arg<7> (*) ()) const { return std::forward<A7>( a7_ ); }
+ A8 && operator[] (boost::arg<8> (*) ()) const { return std::forward<A8>( a8_ ); }
+ A9 && operator[] (boost::arg<9> (*) ()) const { return std::forward<A9>( a9_ ); }
+
+ template<class T> T & operator[] ( _bi::value<T> & v ) const { return v.get(); }
+
+ template<class T> T const & operator[] ( _bi::value<T> const & v ) const { return v.get(); }
+
+ template<class T> T & operator[] (reference_wrapper<T> const & v) const { return v.get(); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> & b) const { return b.eval(*this); }
+
+ template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> const & b) const { return b.eval(*this); }
+};
+
+template<class R, class F, class L> class bind_t
+{
+private:
+
+ F f_;
+ L l_;
+
+public:
+
+ typedef typename result_traits<R, F>::type result_type;
+ typedef bind_t this_type;
+
+ bind_t( F f, L const & l ): f_( f ), l_( l ) {}
+
+ //
+
+ result_type operator()()
+ {
+ list0 a;
+ return l_( type<result_type>(), f_, a, 0 );
+ }
+
+ result_type operator()() const
+ {
+ list0 a;
+ return l_( type<result_type>(), f_, a, 0 );
+ }
+
+ template<class A1> result_type operator()( A1 && a1 )
+ {
+ rrlist1< A1 > a( a1 );
+ return l_( type<result_type>(), f_, a, 0 );
+ }
+
+ template<class A1> result_type operator()( A1 && a1 ) const
+ {
+ rrlist1< A1 > a( a1 );
+ return l_(type<result_type>(), f_, a, 0);
+ }
+
+ template<class A1, class A2> result_type operator()( A1 && a1, A2 && a2 )
+ {
+ rrlist2< A1, A2 > a( a1, a2 );
+ return l_( type<result_type>(), f_, a, 0 );
+ }
+
+ template<class A1, class A2> result_type operator()( A1 && a1, A2 && a2 ) const
+ {
+ rrlist2< A1, A2 > a( a1, a2 );
+ return l_( type<result_type>(), f_, a, 0 );
+ }
+
+ template<class A1, class A2, class A3> result_type operator()( A1 && a1, A2 && a2, A3 && a3 )
+ {
+ rrlist3< A1, A2, A3 > a( a1, a2, a3 );
+ return l_( type<result_type>(), f_, a, 0 );
+ }
+
+ template<class A1, class A2, class A3> result_type operator()( A1 && a1, A2 && a2, A3 && a3 ) const
+ {
+ rrlist3< A1, A2, A3 > a( a1, a2, a3 );
+ return l_( type<result_type>(), f_, a, 0 );
+ }
+
+ template<class A1, class A2, class A3, class A4> result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4 )
+ {
+ rrlist4< A1, A2, A3, A4 > a( a1, a2, a3, a4 );
+ return l_( type<result_type>(), f_, a, 0 );
+ }
+
+ template<class A1, class A2, class A3, class A4> result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4 ) const
+ {
+ rrlist4< A1, A2, A3, A4 > a( a1, a2, a3, a4 );
+ return l_( type<result_type>(), f_, a, 0 );
+ }
+
+ template<class A1, class A2, class A3, class A4, class A5> result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5 )
+ {
+ rrlist5< A1, A2, A3, A4, A5 > a( a1, a2, a3, a4, a5 );
+ return l_( type<result_type>(), f_, a, 0 );
+ }
+
+ template<class A1, class A2, class A3, class A4, class A5> result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5 ) const
+ {
+ rrlist5< A1, A2, A3, A4, A5 > a( a1, a2, a3, a4, a5 );
+ return l_( type<result_type>(), f_, a, 0 );
+ }
+
+ template<class A1, class A2, class A3, class A4, class A5, class A6> result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6 )
+ {
+ rrlist6< A1, A2, A3, A4, A5, A6 > a( a1, a2, a3, a4, a5, a6 );
+ return l_( type<result_type>(), f_, a, 0 );
+ }
+
+ template<class A1, class A2, class A3, class A4, class A5, class A6> result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6 ) const
+ {
+ rrlist6< A1, A2, A3, A4, A5, A6 > a( a1, a2, a3, a4, a5, a6 );
+ return l_( type<result_type>(), f_, a, 0 );
+ }
+
+ template<class A1, class A2, class A3, class A4, class A5, class A6, class A7> result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7 )
+ {
+ rrlist7< A1, A2, A3, A4, A5, A6, A7 > a( a1, a2, a3, a4, a5, a6, a7 );
+ return l_( type<result_type>(), f_, a, 0 );
+ }
+
+ template<class A1, class A2, class A3, class A4, class A5, class A6, class A7> result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7 ) const
+ {
+ rrlist7< A1, A2, A3, A4, A5, A6, A7 > a( a1, a2, a3, a4, a5, a6, a7 );
+ return l_( type<result_type>(), f_, a, 0 );
+ }
+
+ template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8 )
+ {
+ rrlist8< A1, A2, A3, A4, A5, A6, A7, A8 > a( a1, a2, a3, a4, a5, a6, a7, a8 );
+ return l_( type<result_type>(), f_, a, 0 );
+ }
+
+ template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8 ) const
+ {
+ rrlist8< A1, A2, A3, A4, A5, A6, A7, A8 > a( a1, a2, a3, a4, a5, a6, a7, a8 );
+ return l_( type<result_type>(), f_, a, 0 );
+ }
+
+ template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8, A9 && a9 )
+ {
+ rrlist9< A1, A2, A3, A4, A5, A6, A7, A8, A9 > a( a1, a2, a3, a4, a5, a6, a7, a8, a9 );
+ return l_( type<result_type>(), f_, a, 0 );
+ }
+
+ template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8, A9 && a9 ) const
+ {
+ rrlist9< A1, A2, A3, A4, A5, A6, A7, A8, A9 > a( a1, a2, a3, a4, a5, a6, a7, a8, a9 );
+ return l_( type<result_type>(), f_, a, 0 );
+ }
+
+ //
+
+ template<class A> result_type eval( A & a )
+ {
+ return l_( type<result_type>(), f_, a, 0 );
+ }
+
+ template<class A> result_type eval( A & a ) const
+ {
+ return l_( type<result_type>(), f_, a, 0 );
+ }
+
+ template<class V> void accept( V & v ) const
+ {
+#if !defined( BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP ) && !defined( __BORLANDC__ )
+ using boost::visit_each;
+#endif
+
+ BOOST_BIND_VISIT_EACH( v, f_, 0 );
+ l_.accept( v );
+ }
+
+ bool compare( this_type const & rhs ) const
+ {
+ return ref_compare( f_, rhs.f_, 0 ) && l_ == rhs.l_;
+ }
+};
+
+#elif !defined( BOOST_NO_VOID_RETURNS )
+
+template<class R, class F, class L> class bind_t
+{
+public:
+
+ typedef bind_t this_type;
+
+ bind_t(F f, L const & l): f_(f), l_(l) {}
+
+#define BOOST_BIND_RETURN return
+#include <boost/bind/bind_template.hpp>
+#undef BOOST_BIND_RETURN
+
+};
+
+#else // no void returns
+
+template<class R> struct bind_t_generator
+{
+
+template<class F, class L> class implementation
+{
+public:
+
+ typedef implementation this_type;
+
+ implementation(F f, L const & l): f_(f), l_(l) {}
+
+#define BOOST_BIND_RETURN return
+#include <boost/bind/bind_template.hpp>
+#undef BOOST_BIND_RETURN
+
+};
+
+};
+
+template<> struct bind_t_generator<void>
+{
+
+template<class F, class L> class implementation
+{
+private:
+
+ typedef void R;
+
+public:
+
+ typedef implementation this_type;
+
+ implementation(F f, L const & l): f_(f), l_(l) {}
+
+#define BOOST_BIND_RETURN
+#include <boost/bind/bind_template.hpp>
+#undef BOOST_BIND_RETURN
+
+};
+
+};
+
+template<class R2, class F, class L> class bind_t: public bind_t_generator<R2>::BOOST_NESTED_TEMPLATE implementation<F, L>
+{
+public:
+
+ bind_t(F f, L const & l): bind_t_generator<R2>::BOOST_NESTED_TEMPLATE implementation<F, L>(f, l) {}
+
+};
+
+#endif
+
+// function_equal
+
+#ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
+
+// put overloads in _bi, rely on ADL
+
+# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
+
+template<class R, class F, class L> bool function_equal( bind_t<R, F, L> const & a, bind_t<R, F, L> const & b )
+{
+ return a.compare(b);
+}
+
+# else
+
+template<class R, class F, class L> bool function_equal_impl( bind_t<R, F, L> const & a, bind_t<R, F, L> const & b, int )
+{
+ return a.compare(b);
+}
+
+# endif // #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
+
+#else // BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
+
+// put overloads in boost
+
+} // namespace _bi
+
+# ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
+
+template<class R, class F, class L> bool function_equal( _bi::bind_t<R, F, L> const & a, _bi::bind_t<R, F, L> const & b )
+{
+ return a.compare(b);
+}
+
+# else
+
+template<class R, class F, class L> bool function_equal_impl( _bi::bind_t<R, F, L> const & a, _bi::bind_t<R, F, L> const & b, int )
+{
+ return a.compare(b);
+}
+
+# endif // #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
+
+namespace _bi
+{
+
+#endif // BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
+
+// add_value
+
+#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || (__SUNPRO_CC >= 0x530)
+
+#if defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x582) )
+
+template<class T> struct add_value
+{
+ typedef _bi::value<T> type;
+};
+
+#else
+
+template< class T, int I > struct add_value_2
+{
+ typedef boost::arg<I> type;
+};
+
+template< class T > struct add_value_2< T, 0 >
+{
+ typedef _bi::value< T > type;
+};
+
+template<class T> struct add_value
+{
+ typedef typename add_value_2< T, boost::is_placeholder< T >::value >::type type;
+};
+
+#endif
+
+template<class T> struct add_value< value<T> >
+{
+ typedef _bi::value<T> type;
+};
+
+template<class T> struct add_value< reference_wrapper<T> >
+{
+ typedef reference_wrapper<T> type;
+};
+
+template<int I> struct add_value< arg<I> >
+{
+ typedef boost::arg<I> type;
+};
+
+template<int I> struct add_value< arg<I> (*) () >
+{
+ typedef boost::arg<I> (*type) ();
+};
+
+template<class R, class F, class L> struct add_value< bind_t<R, F, L> >
+{
+ typedef bind_t<R, F, L> type;
+};
+
+#else
+
+template<int I> struct _avt_0;
+
+template<> struct _avt_0<1>
+{
+ template<class T> struct inner
+ {
+ typedef T type;
+ };
+};
+
+template<> struct _avt_0<2>
+{
+ template<class T> struct inner
+ {
+ typedef value<T> type;
+ };
+};
+
+typedef char (&_avt_r1) [1];
+typedef char (&_avt_r2) [2];
+
+template<class T> _avt_r1 _avt_f(value<T>);
+template<class T> _avt_r1 _avt_f(reference_wrapper<T>);
+template<int I> _avt_r1 _avt_f(arg<I>);
+template<int I> _avt_r1 _avt_f(arg<I> (*) ());
+template<class R, class F, class L> _avt_r1 _avt_f(bind_t<R, F, L>);
+
+_avt_r2 _avt_f(...);
+
+template<class T> struct add_value
+{
+ static T t();
+ typedef typename _avt_0<sizeof(_avt_f(t()))>::template inner<T>::type type;
+};
+
+#endif
+
+// list_av_N
+
+template<class A1> struct list_av_1
+{
+ typedef typename add_value<A1>::type B1;
+ typedef list1<B1> type;
+};
+
+template<class A1, class A2> struct list_av_2
+{
+ typedef typename add_value<A1>::type B1;
+ typedef typename add_value<A2>::type B2;
+ typedef list2<B1, B2> type;
+};
+
+template<class A1, class A2, class A3> struct list_av_3
+{
+ typedef typename add_value<A1>::type B1;
+ typedef typename add_value<A2>::type B2;
+ typedef typename add_value<A3>::type B3;
+ typedef list3<B1, B2, B3> type;
+};
+
+template<class A1, class A2, class A3, class A4> struct list_av_4
+{
+ typedef typename add_value<A1>::type B1;
+ typedef typename add_value<A2>::type B2;
+ typedef typename add_value<A3>::type B3;
+ typedef typename add_value<A4>::type B4;
+ typedef list4<B1, B2, B3, B4> type;
+};
+
+template<class A1, class A2, class A3, class A4, class A5> struct list_av_5
+{
+ typedef typename add_value<A1>::type B1;
+ typedef typename add_value<A2>::type B2;
+ typedef typename add_value<A3>::type B3;
+ typedef typename add_value<A4>::type B4;
+ typedef typename add_value<A5>::type B5;
+ typedef list5<B1, B2, B3, B4, B5> type;
+};
+
+template<class A1, class A2, class A3, class A4, class A5, class A6> struct list_av_6
+{
+ typedef typename add_value<A1>::type B1;
+ typedef typename add_value<A2>::type B2;
+ typedef typename add_value<A3>::type B3;
+ typedef typename add_value<A4>::type B4;
+ typedef typename add_value<A5>::type B5;
+ typedef typename add_value<A6>::type B6;
+ typedef list6<B1, B2, B3, B4, B5, B6> type;
+};
+
+template<class A1, class A2, class A3, class A4, class A5, class A6, class A7> struct list_av_7
+{
+ typedef typename add_value<A1>::type B1;
+ typedef typename add_value<A2>::type B2;
+ typedef typename add_value<A3>::type B3;
+ typedef typename add_value<A4>::type B4;
+ typedef typename add_value<A5>::type B5;
+ typedef typename add_value<A6>::type B6;
+ typedef typename add_value<A7>::type B7;
+ typedef list7<B1, B2, B3, B4, B5, B6, B7> type;
+};
+
+template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> struct list_av_8
+{
+ typedef typename add_value<A1>::type B1;
+ typedef typename add_value<A2>::type B2;
+ typedef typename add_value<A3>::type B3;
+ typedef typename add_value<A4>::type B4;
+ typedef typename add_value<A5>::type B5;
+ typedef typename add_value<A6>::type B6;
+ typedef typename add_value<A7>::type B7;
+ typedef typename add_value<A8>::type B8;
+ typedef list8<B1, B2, B3, B4, B5, B6, B7, B8> type;
+};
+
+template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> struct list_av_9
+{
+ typedef typename add_value<A1>::type B1;
+ typedef typename add_value<A2>::type B2;
+ typedef typename add_value<A3>::type B3;
+ typedef typename add_value<A4>::type B4;
+ typedef typename add_value<A5>::type B5;
+ typedef typename add_value<A6>::type B6;
+ typedef typename add_value<A7>::type B7;
+ typedef typename add_value<A8>::type B8;
+ typedef typename add_value<A9>::type B9;
+ typedef list9<B1, B2, B3, B4, B5, B6, B7, B8, B9> type;
+};
+
+// operator!
+
+struct logical_not
+{
+ template<class V> bool operator()(V const & v) const { return !v; }
+};
+
+template<class R, class F, class L>
+ bind_t< bool, logical_not, list1< bind_t<R, F, L> > >
+ operator! (bind_t<R, F, L> const & f)
+{
+ typedef list1< bind_t<R, F, L> > list_type;
+ return bind_t<bool, logical_not, list_type> ( logical_not(), list_type(f) );
+}
+
+// relational operators
+
+#define BOOST_BIND_OPERATOR( op, name ) \
+\
+struct name \
+{ \
+ template<class V, class W> bool operator()(V const & v, W const & w) const { return v op w; } \
+}; \
+ \
+template<class R, class F, class L, class A2> \
+ bind_t< bool, name, list2< bind_t<R, F, L>, typename add_value<A2>::type > > \
+ operator op (bind_t<R, F, L> const & f, A2 a2) \
+{ \
+ typedef typename add_value<A2>::type B2; \
+ typedef list2< bind_t<R, F, L>, B2> list_type; \
+ return bind_t<bool, name, list_type> ( name(), list_type(f, a2) ); \
+}
+
+BOOST_BIND_OPERATOR( ==, equal )
+BOOST_BIND_OPERATOR( !=, not_equal )
+
+BOOST_BIND_OPERATOR( <, less )
+BOOST_BIND_OPERATOR( <=, less_equal )
+
+BOOST_BIND_OPERATOR( >, greater )
+BOOST_BIND_OPERATOR( >=, greater_equal )
+
+BOOST_BIND_OPERATOR( &&, logical_and )
+BOOST_BIND_OPERATOR( ||, logical_or )
+
+#undef BOOST_BIND_OPERATOR
+
+#if defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3)
+
+// resolve ambiguity with rel_ops
+
+#define BOOST_BIND_OPERATOR( op, name ) \
+\
+template<class R, class F, class L> \
+ bind_t< bool, name, list2< bind_t<R, F, L>, bind_t<R, F, L> > > \
+ operator op (bind_t<R, F, L> const & f, bind_t<R, F, L> const & g) \
+{ \
+ typedef list2< bind_t<R, F, L>, bind_t<R, F, L> > list_type; \
+ return bind_t<bool, name, list_type> ( name(), list_type(f, g) ); \
+}
+
+BOOST_BIND_OPERATOR( !=, not_equal )
+BOOST_BIND_OPERATOR( <=, less_equal )
+BOOST_BIND_OPERATOR( >, greater )
+BOOST_BIND_OPERATOR( >=, greater_equal )
+
+#endif
+
+// visit_each, ADL
+
+#if !defined( BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP ) && !defined( __BORLANDC__ ) \
+ && !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
+
+template<class V, class T> void visit_each( V & v, value<T> const & t, int )
+{
+ using boost::visit_each;
+ BOOST_BIND_VISIT_EACH( v, t.get(), 0 );
+}
+
+template<class V, class R, class F, class L> void visit_each( V & v, bind_t<R, F, L> const & t, int )
+{
+ t.accept( v );
+}
+
+#endif
+
+} // namespace _bi
+
+// visit_each, no ADL
+
+#if defined( BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP ) || defined( __BORLANDC__ ) \
+ || (defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
+
+template<class V, class T> void visit_each( V & v, _bi::value<T> const & t, int )
+{
+ BOOST_BIND_VISIT_EACH( v, t.get(), 0 );
+}
+
+template<class V, class R, class F, class L> void visit_each( V & v, _bi::bind_t<R, F, L> const & t, int )
+{
+ t.accept( v );
+}
+
+#endif
+
+// is_bind_expression
+
+template< class T > struct is_bind_expression
+{
+ enum _vt { value = 0 };
+};
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template< class R, class F, class L > struct is_bind_expression< _bi::bind_t< R, F, L > >
+{
+ enum _vt { value = 1 };
+};
+
+#endif
+
+// bind
+
+#ifndef BOOST_BIND
+#define BOOST_BIND bind
+#endif
+
+// generic function objects
+
+template<class R, class F>
+ _bi::bind_t<R, F, _bi::list0>
+ BOOST_BIND(F f)
+{
+ typedef _bi::list0 list_type;
+ return _bi::bind_t<R, F, list_type> (f, list_type());
+}
+
+template<class R, class F, class A1>
+ _bi::bind_t<R, F, typename _bi::list_av_1<A1>::type>
+ BOOST_BIND(F f, A1 a1)
+{
+ typedef typename _bi::list_av_1<A1>::type list_type;
+ return _bi::bind_t<R, F, list_type> (f, list_type(a1));
+}
+
+template<class R, class F, class A1, class A2>
+ _bi::bind_t<R, F, typename _bi::list_av_2<A1, A2>::type>
+ BOOST_BIND(F f, A1 a1, A2 a2)
+{
+ typedef typename _bi::list_av_2<A1, A2>::type list_type;
+ return _bi::bind_t<R, F, list_type> (f, list_type(a1, a2));
+}
+
+template<class R, class F, class A1, class A2, class A3>
+ _bi::bind_t<R, F, typename _bi::list_av_3<A1, A2, A3>::type>
+ BOOST_BIND(F f, A1 a1, A2 a2, A3 a3)
+{
+ typedef typename _bi::list_av_3<A1, A2, A3>::type list_type;
+ return _bi::bind_t<R, F, list_type>(f, list_type(a1, a2, a3));
+}
+
+template<class R, class F, class A1, class A2, class A3, class A4>
+ _bi::bind_t<R, F, typename _bi::list_av_4<A1, A2, A3, A4>::type>
+ BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4)
+{
+ typedef typename _bi::list_av_4<A1, A2, A3, A4>::type list_type;
+ return _bi::bind_t<R, F, list_type>(f, list_type(a1, a2, a3, a4));
+}
+
+template<class R, class F, class A1, class A2, class A3, class A4, class A5>
+ _bi::bind_t<R, F, typename _bi::list_av_5<A1, A2, A3, A4, A5>::type>
+ BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
+{
+ typedef typename _bi::list_av_5<A1, A2, A3, A4, A5>::type list_type;
+ return _bi::bind_t<R, F, list_type>(f, list_type(a1, a2, a3, a4, a5));
+}
+
+template<class R, class F, class A1, class A2, class A3, class A4, class A5, class A6>
+ _bi::bind_t<R, F, typename _bi::list_av_6<A1, A2, A3, A4, A5, A6>::type>
+ BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
+{
+ typedef typename _bi::list_av_6<A1, A2, A3, A4, A5, A6>::type list_type;
+ return _bi::bind_t<R, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6));
+}
+
+template<class R, class F, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
+ _bi::bind_t<R, F, typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type>
+ BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
+{
+ typedef typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type list_type;
+ return _bi::bind_t<R, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6, a7));
+}
+
+template<class R, class F, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
+ _bi::bind_t<R, F, typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type>
+ BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
+{
+ typedef typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type list_type;
+ return _bi::bind_t<R, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8));
+}
+
+template<class R, class F, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
+ _bi::bind_t<R, F, typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type>
+ BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
+{
+ typedef typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type list_type;
+ return _bi::bind_t<R, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9));
+}
+
+// generic function objects, alternative syntax
+
+template<class R, class F>
+ _bi::bind_t<R, F, _bi::list0>
+ BOOST_BIND(boost::type<R>, F f)
+{
+ typedef _bi::list0 list_type;
+ return _bi::bind_t<R, F, list_type> (f, list_type());
+}
+
+template<class R, class F, class A1>
+ _bi::bind_t<R, F, typename _bi::list_av_1<A1>::type>
+ BOOST_BIND(boost::type<R>, F f, A1 a1)
+{
+ typedef typename _bi::list_av_1<A1>::type list_type;
+ return _bi::bind_t<R, F, list_type> (f, list_type(a1));
+}
+
+template<class R, class F, class A1, class A2>
+ _bi::bind_t<R, F, typename _bi::list_av_2<A1, A2>::type>
+ BOOST_BIND(boost::type<R>, F f, A1 a1, A2 a2)
+{
+ typedef typename _bi::list_av_2<A1, A2>::type list_type;
+ return _bi::bind_t<R, F, list_type> (f, list_type(a1, a2));
+}
+
+template<class R, class F, class A1, class A2, class A3>
+ _bi::bind_t<R, F, typename _bi::list_av_3<A1, A2, A3>::type>
+ BOOST_BIND(boost::type<R>, F f, A1 a1, A2 a2, A3 a3)
+{
+ typedef typename _bi::list_av_3<A1, A2, A3>::type list_type;
+ return _bi::bind_t<R, F, list_type>(f, list_type(a1, a2, a3));
+}
+
+template<class R, class F, class A1, class A2, class A3, class A4>
+ _bi::bind_t<R, F, typename _bi::list_av_4<A1, A2, A3, A4>::type>
+ BOOST_BIND(boost::type<R>, F f, A1 a1, A2 a2, A3 a3, A4 a4)
+{
+ typedef typename _bi::list_av_4<A1, A2, A3, A4>::type list_type;
+ return _bi::bind_t<R, F, list_type>(f, list_type(a1, a2, a3, a4));
+}
+
+template<class R, class F, class A1, class A2, class A3, class A4, class A5>
+ _bi::bind_t<R, F, typename _bi::list_av_5<A1, A2, A3, A4, A5>::type>
+ BOOST_BIND(boost::type<R>, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
+{
+ typedef typename _bi::list_av_5<A1, A2, A3, A4, A5>::type list_type;
+ return _bi::bind_t<R, F, list_type>(f, list_type(a1, a2, a3, a4, a5));
+}
+
+template<class R, class F, class A1, class A2, class A3, class A4, class A5, class A6>
+ _bi::bind_t<R, F, typename _bi::list_av_6<A1, A2, A3, A4, A5, A6>::type>
+ BOOST_BIND(boost::type<R>, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
+{
+ typedef typename _bi::list_av_6<A1, A2, A3, A4, A5, A6>::type list_type;
+ return _bi::bind_t<R, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6));
+}
+
+template<class R, class F, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
+ _bi::bind_t<R, F, typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type>
+ BOOST_BIND(boost::type<R>, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
+{
+ typedef typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type list_type;
+ return _bi::bind_t<R, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6, a7));
+}
+
+template<class R, class F, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
+ _bi::bind_t<R, F, typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type>
+ BOOST_BIND(boost::type<R>, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
+{
+ typedef typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type list_type;
+ return _bi::bind_t<R, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8));
+}
+
+template<class R, class F, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
+ _bi::bind_t<R, F, typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type>
+ BOOST_BIND(boost::type<R>, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
+{
+ typedef typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type list_type;
+ return _bi::bind_t<R, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9));
+}
+
+#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
+
+// adaptable function objects
+
+template<class F>
+ _bi::bind_t<_bi::unspecified, F, _bi::list0>
+ BOOST_BIND(F f)
+{
+ typedef _bi::list0 list_type;
+ return _bi::bind_t<_bi::unspecified, F, list_type> (f, list_type());
+}
+
+template<class F, class A1>
+ _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_1<A1>::type>
+ BOOST_BIND(F f, A1 a1)
+{
+ typedef typename _bi::list_av_1<A1>::type list_type;
+ return _bi::bind_t<_bi::unspecified, F, list_type> (f, list_type(a1));
+}
+
+template<class F, class A1, class A2>
+ _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_2<A1, A2>::type>
+ BOOST_BIND(F f, A1 a1, A2 a2)
+{
+ typedef typename _bi::list_av_2<A1, A2>::type list_type;
+ return _bi::bind_t<_bi::unspecified, F, list_type> (f, list_type(a1, a2));
+}
+
+template<class F, class A1, class A2, class A3>
+ _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_3<A1, A2, A3>::type>
+ BOOST_BIND(F f, A1 a1, A2 a2, A3 a3)
+{
+ typedef typename _bi::list_av_3<A1, A2, A3>::type list_type;
+ return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3));
+}
+
+template<class F, class A1, class A2, class A3, class A4>
+ _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_4<A1, A2, A3, A4>::type>
+ BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4)
+{
+ typedef typename _bi::list_av_4<A1, A2, A3, A4>::type list_type;
+ return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3, a4));
+}
+
+template<class F, class A1, class A2, class A3, class A4, class A5>
+ _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_5<A1, A2, A3, A4, A5>::type>
+ BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
+{
+ typedef typename _bi::list_av_5<A1, A2, A3, A4, A5>::type list_type;
+ return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3, a4, a5));
+}
+
+template<class F, class A1, class A2, class A3, class A4, class A5, class A6>
+ _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_6<A1, A2, A3, A4, A5, A6>::type>
+ BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
+{
+ typedef typename _bi::list_av_6<A1, A2, A3, A4, A5, A6>::type list_type;
+ return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6));
+}
+
+template<class F, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
+ _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type>
+ BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
+{
+ typedef typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type list_type;
+ return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6, a7));
+}
+
+template<class F, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
+ _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type>
+ BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
+{
+ typedef typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type list_type;
+ return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8));
+}
+
+template<class F, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
+ _bi::bind_t<_bi::unspecified, F, typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type>
+ BOOST_BIND(F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
+{
+ typedef typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type list_type;
+ return _bi::bind_t<_bi::unspecified, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9));
+}
+
+#endif // !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
+
+// function pointers
+
+#define BOOST_BIND_CC
+#define BOOST_BIND_ST
+
+#include <boost/bind/bind_cc.hpp>
+
+#undef BOOST_BIND_CC
+#undef BOOST_BIND_ST
+
+#ifdef BOOST_BIND_ENABLE_STDCALL
+
+#define BOOST_BIND_CC __stdcall
+#define BOOST_BIND_ST
+
+#include <boost/bind/bind_cc.hpp>
+
+#undef BOOST_BIND_CC
+#undef BOOST_BIND_ST
+
+#endif
+
+#ifdef BOOST_BIND_ENABLE_FASTCALL
+
+#define BOOST_BIND_CC __fastcall
+#define BOOST_BIND_ST
+
+#include <boost/bind/bind_cc.hpp>
+
+#undef BOOST_BIND_CC
+#undef BOOST_BIND_ST
+
+#endif
+
+#ifdef BOOST_BIND_ENABLE_PASCAL
+
+#define BOOST_BIND_ST pascal
+#define BOOST_BIND_CC
+
+#include <boost/bind/bind_cc.hpp>
+
+#undef BOOST_BIND_ST
+#undef BOOST_BIND_CC
+
+#endif
+
+// member function pointers
+
+#define BOOST_BIND_MF_NAME(X) X
+#define BOOST_BIND_MF_CC
+
+#include <boost/bind/bind_mf_cc.hpp>
+#include <boost/bind/bind_mf2_cc.hpp>
+
+#undef BOOST_BIND_MF_NAME
+#undef BOOST_BIND_MF_CC
+
+#ifdef BOOST_MEM_FN_ENABLE_CDECL
+
+#define BOOST_BIND_MF_NAME(X) X##_cdecl
+#define BOOST_BIND_MF_CC __cdecl
+
+#include <boost/bind/bind_mf_cc.hpp>
+#include <boost/bind/bind_mf2_cc.hpp>
+
+#undef BOOST_BIND_MF_NAME
+#undef BOOST_BIND_MF_CC
+
+#endif
+
+#ifdef BOOST_MEM_FN_ENABLE_STDCALL
+
+#define BOOST_BIND_MF_NAME(X) X##_stdcall
+#define BOOST_BIND_MF_CC __stdcall
+
+#include <boost/bind/bind_mf_cc.hpp>
+#include <boost/bind/bind_mf2_cc.hpp>
+
+#undef BOOST_BIND_MF_NAME
+#undef BOOST_BIND_MF_CC
+
+#endif
+
+#ifdef BOOST_MEM_FN_ENABLE_FASTCALL
+
+#define BOOST_BIND_MF_NAME(X) X##_fastcall
+#define BOOST_BIND_MF_CC __fastcall
+
+#include <boost/bind/bind_mf_cc.hpp>
+#include <boost/bind/bind_mf2_cc.hpp>
+
+#undef BOOST_BIND_MF_NAME
+#undef BOOST_BIND_MF_CC
+
+#endif
+
+// data member pointers
+
+#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \
+ || ( defined(__BORLANDC__) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x620 ) ) )
+
+template<class R, class T, class A1>
+_bi::bind_t< R, _mfi::dm<R, T>, typename _bi::list_av_1<A1>::type >
+ BOOST_BIND(R T::*f, A1 a1)
+{
+ typedef _mfi::dm<R, T> F;
+ typedef typename _bi::list_av_1<A1>::type list_type;
+ return _bi::bind_t<R, F, list_type>( F(f), list_type(a1) );
+}
+
+#else
+
+namespace _bi
+{
+
+template< class Pm, int I > struct add_cref;
+
+template< class M, class T > struct add_cref< M T::*, 0 >
+{
+ typedef M type;
+};
+
+template< class M, class T > struct add_cref< M T::*, 1 >
+{
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable:4180)
+#endif
+ typedef M const & type;
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+};
+
+template< class R, class T > struct add_cref< R (T::*) (), 1 >
+{
+ typedef void type;
+};
+
+#if !defined(__IBMCPP__) || __IBMCPP_FUNC_CV_TMPL_ARG_DEDUCTION
+
+template< class R, class T > struct add_cref< R (T::*) () const, 1 >
+{
+ typedef void type;
+};
+
+#endif // __IBMCPP__
+
+template<class R> struct isref
+{
+ enum value_type { value = 0 };
+};
+
+template<class R> struct isref< R& >
+{
+ enum value_type { value = 1 };
+};
+
+template<class R> struct isref< R* >
+{
+ enum value_type { value = 1 };
+};
+
+template<class Pm, class A1> struct dm_result
+{
+ typedef typename add_cref< Pm, 1 >::type type;
+};
+
+template<class Pm, class R, class F, class L> struct dm_result< Pm, bind_t<R, F, L> >
+{
+ typedef typename bind_t<R, F, L>::result_type result_type;
+ typedef typename add_cref< Pm, isref< result_type >::value >::type type;
+};
+
+} // namespace _bi
+
+template< class A1, class M, class T >
+
+_bi::bind_t<
+ typename _bi::dm_result< M T::*, A1 >::type,
+ _mfi::dm<M, T>,
+ typename _bi::list_av_1<A1>::type
+>
+
+BOOST_BIND( M T::*f, A1 a1 )
+{
+ typedef typename _bi::dm_result< M T::*, A1 >::type result_type;
+ typedef _mfi::dm<M, T> F;
+ typedef typename _bi::list_av_1<A1>::type list_type;
+ return _bi::bind_t< result_type, F, list_type >( F( f ), list_type( a1 ) );
+}
+
+#endif
+
+} // namespace boost
+
+#ifndef BOOST_BIND_NO_PLACEHOLDERS
+
+# include <boost/bind/placeholders.hpp>
+
+#endif
+
+#ifdef BOOST_MSVC
+# pragma warning(default: 4512) // assignment operator could not be generated
+# pragma warning(pop)
+#endif
+
+#endif // #ifndef BOOST_BIND_BIND_HPP_INCLUDED
diff --git a/third_party/boost/boost/bind/bind_cc.hpp b/third_party/boost/boost/bind/bind_cc.hpp
new file mode 100644
index 0000000..35f8ece
--- /dev/null
+++ b/third_party/boost/boost/bind/bind_cc.hpp
@@ -0,0 +1,117 @@
+//
+// bind/bind_cc.hpp - support for different calling conventions
+//
+// Do not include this header directly.
+//
+// Copyright (c) 2001 Peter Dimov and Multi Media Ltd.
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/bind/bind.html for documentation.
+//
+
+template<class R>
+ _bi::bind_t<R, BOOST_BIND_ST R (BOOST_BIND_CC *) (), _bi::list0>
+ BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) ())
+{
+ typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) ();
+ typedef _bi::list0 list_type;
+ return _bi::bind_t<R, F, list_type> (f, list_type());
+}
+
+template<class R, class B1, class A1>
+ _bi::bind_t<R, BOOST_BIND_ST R (BOOST_BIND_CC *) (B1), typename _bi::list_av_1<A1>::type>
+ BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1), A1 a1)
+{
+ typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1);
+ typedef typename _bi::list_av_1<A1>::type list_type;
+ return _bi::bind_t<R, F, list_type> (f, list_type(a1));
+}
+
+template<class R, class B1, class B2, class A1, class A2>
+ _bi::bind_t<R, BOOST_BIND_ST R (BOOST_BIND_CC *) (B1, B2), typename _bi::list_av_2<A1, A2>::type>
+ BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1, B2), A1 a1, A2 a2)
+{
+ typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1, B2);
+ typedef typename _bi::list_av_2<A1, A2>::type list_type;
+ return _bi::bind_t<R, F, list_type> (f, list_type(a1, a2));
+}
+
+template<class R,
+ class B1, class B2, class B3,
+ class A1, class A2, class A3>
+ _bi::bind_t<R, BOOST_BIND_ST R (BOOST_BIND_CC *) (B1, B2, B3), typename _bi::list_av_3<A1, A2, A3>::type>
+ BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1, B2, B3), A1 a1, A2 a2, A3 a3)
+{
+ typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1, B2, B3);
+ typedef typename _bi::list_av_3<A1, A2, A3>::type list_type;
+ return _bi::bind_t<R, F, list_type>(f, list_type(a1, a2, a3));
+}
+
+template<class R,
+ class B1, class B2, class B3, class B4,
+ class A1, class A2, class A3, class A4>
+ _bi::bind_t<R, BOOST_BIND_ST R (BOOST_BIND_CC *) (B1, B2, B3, B4), typename _bi::list_av_4<A1, A2, A3, A4>::type>
+ BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1, B2, B3, B4), A1 a1, A2 a2, A3 a3, A4 a4)
+{
+ typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1, B2, B3, B4);
+ typedef typename _bi::list_av_4<A1, A2, A3, A4>::type list_type;
+ return _bi::bind_t<R, F, list_type>(f, list_type(a1, a2, a3, a4));
+}
+
+template<class R,
+ class B1, class B2, class B3, class B4, class B5,
+ class A1, class A2, class A3, class A4, class A5>
+ _bi::bind_t<R, BOOST_BIND_ST R (BOOST_BIND_CC *) (B1, B2, B3, B4, B5), typename _bi::list_av_5<A1, A2, A3, A4, A5>::type>
+ BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1, B2, B3, B4, B5), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
+{
+ typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1, B2, B3, B4, B5);
+ typedef typename _bi::list_av_5<A1, A2, A3, A4, A5>::type list_type;
+ return _bi::bind_t<R, F, list_type>(f, list_type(a1, a2, a3, a4, a5));
+}
+
+template<class R,
+ class B1, class B2, class B3, class B4, class B5, class B6,
+ class A1, class A2, class A3, class A4, class A5, class A6>
+ _bi::bind_t<R, BOOST_BIND_ST R (BOOST_BIND_CC *) (B1, B2, B3, B4, B5, B6), typename _bi::list_av_6<A1, A2, A3, A4, A5, A6>::type>
+ BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1, B2, B3, B4, B5, B6), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
+{
+ typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1, B2, B3, B4, B5, B6);
+ typedef typename _bi::list_av_6<A1, A2, A3, A4, A5, A6>::type list_type;
+ return _bi::bind_t<R, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6));
+}
+
+template<class R,
+ class B1, class B2, class B3, class B4, class B5, class B6, class B7,
+ class A1, class A2, class A3, class A4, class A5, class A6, class A7>
+ _bi::bind_t<R, BOOST_BIND_ST R (BOOST_BIND_CC *) (B1, B2, B3, B4, B5, B6, B7), typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type>
+ BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1, B2, B3, B4, B5, B6, B7), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
+{
+ typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1, B2, B3, B4, B5, B6, B7);
+ typedef typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type list_type;
+ return _bi::bind_t<R, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6, a7));
+}
+
+template<class R,
+ class B1, class B2, class B3, class B4, class B5, class B6, class B7, class B8,
+ class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
+ _bi::bind_t<R, BOOST_BIND_ST R (BOOST_BIND_CC *) (B1, B2, B3, B4, B5, B6, B7, B8), typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type>
+ BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1, B2, B3, B4, B5, B6, B7, B8), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
+{
+ typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1, B2, B3, B4, B5, B6, B7, B8);
+ typedef typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type list_type;
+ return _bi::bind_t<R, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8));
+}
+
+template<class R,
+ class B1, class B2, class B3, class B4, class B5, class B6, class B7, class B8, class B9,
+ class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
+ _bi::bind_t<R, BOOST_BIND_ST R (BOOST_BIND_CC *) (B1, B2, B3, B4, B5, B6, B7, B8, B9), typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type>
+ BOOST_BIND(BOOST_BIND_ST R (BOOST_BIND_CC *f) (B1, B2, B3, B4, B5, B6, B7, B8, B9), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
+{
+ typedef BOOST_BIND_ST R (BOOST_BIND_CC *F) (B1, B2, B3, B4, B5, B6, B7, B8, B9);
+ typedef typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type list_type;
+ return _bi::bind_t<R, F, list_type>(f, list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9));
+}
diff --git a/third_party/boost/boost/bind/bind_mf2_cc.hpp b/third_party/boost/boost/bind/bind_mf2_cc.hpp
new file mode 100644
index 0000000..66476bc
--- /dev/null
+++ b/third_party/boost/boost/bind/bind_mf2_cc.hpp
@@ -0,0 +1,228 @@
+//
+// bind/bind_mf2_cc.hpp - member functions, type<> syntax
+//
+// Do not include this header directly.
+//
+// Copyright (c) 2001 Peter Dimov and Multi Media Ltd.
+// Copyright (c) 2008 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+// See http://www.boost.org/libs/bind/bind.html for documentation.
+//
+
+// 0
+
+template<class Rt2, class R, class T,
+ class A1>
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf0)<R, T>, typename _bi::list_av_1<A1>::type>
+ BOOST_BIND(boost::type<Rt2>, R (BOOST_BIND_MF_CC T::*f) (), A1 a1)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf0)<R, T> F;
+ typedef typename _bi::list_av_1<A1>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1));
+}
+
+template<class Rt2, class R, class T,
+ class A1>
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf0)<R, T>, typename _bi::list_av_1<A1>::type>
+ BOOST_BIND(boost::type<Rt2>, R (BOOST_BIND_MF_CC T::*f) () const, A1 a1)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf0)<R, T> F;
+ typedef typename _bi::list_av_1<A1>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1));
+}
+
+// 1
+
+template<class Rt2, class R, class T,
+ class B1,
+ class A1, class A2>
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf1)<R, T, B1>, typename _bi::list_av_2<A1, A2>::type>
+ BOOST_BIND(boost::type<Rt2>, R (BOOST_BIND_MF_CC T::*f) (B1), A1 a1, A2 a2)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf1)<R, T, B1> F;
+ typedef typename _bi::list_av_2<A1, A2>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2));
+}
+
+template<class Rt2, class R, class T,
+ class B1,
+ class A1, class A2>
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf1)<R, T, B1>, typename _bi::list_av_2<A1, A2>::type>
+ BOOST_BIND(boost::type<Rt2>, R (BOOST_BIND_MF_CC T::*f) (B1) const, A1 a1, A2 a2)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf1)<R, T, B1> F;
+ typedef typename _bi::list_av_2<A1, A2>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2));
+}
+
+// 2
+
+template<class Rt2, class R, class T,
+ class B1, class B2,
+ class A1, class A2, class A3>
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf2)<R, T, B1, B2>, typename _bi::list_av_3<A1, A2, A3>::type>
+ BOOST_BIND(boost::type<Rt2>, R (BOOST_BIND_MF_CC T::*f) (B1, B2), A1 a1, A2 a2, A3 a3)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf2)<R, T, B1, B2> F;
+ typedef typename _bi::list_av_3<A1, A2, A3>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3));
+}
+
+template<class Rt2, class R, class T,
+ class B1, class B2,
+ class A1, class A2, class A3>
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf2)<R, T, B1, B2>, typename _bi::list_av_3<A1, A2, A3>::type>
+ BOOST_BIND(boost::type<Rt2>, R (BOOST_BIND_MF_CC T::*f) (B1, B2) const, A1 a1, A2 a2, A3 a3)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf2)<R, T, B1, B2> F;
+ typedef typename _bi::list_av_3<A1, A2, A3>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3));
+}
+
+// 3
+
+template<class Rt2, class R, class T,
+ class B1, class B2, class B3,
+ class A1, class A2, class A3, class A4>
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf3)<R, T, B1, B2, B3>, typename _bi::list_av_4<A1, A2, A3, A4>::type>
+ BOOST_BIND(boost::type<Rt2>, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3), A1 a1, A2 a2, A3 a3, A4 a4)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf3)<R, T, B1, B2, B3> F;
+ typedef typename _bi::list_av_4<A1, A2, A3, A4>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4));
+}
+
+template<class Rt2, class R, class T,
+ class B1, class B2, class B3,
+ class A1, class A2, class A3, class A4>
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf3)<R, T, B1, B2, B3>, typename _bi::list_av_4<A1, A2, A3, A4>::type>
+ BOOST_BIND(boost::type<Rt2>, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3) const, A1 a1, A2 a2, A3 a3, A4 a4)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf3)<R, T, B1, B2, B3> F;
+ typedef typename _bi::list_av_4<A1, A2, A3, A4>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4));
+}
+
+// 4
+
+template<class Rt2, class R, class T,
+ class B1, class B2, class B3, class B4,
+ class A1, class A2, class A3, class A4, class A5>
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf4)<R, T, B1, B2, B3, B4>, typename _bi::list_av_5<A1, A2, A3, A4, A5>::type>
+ BOOST_BIND(boost::type<Rt2>, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf4)<R, T, B1, B2, B3, B4> F;
+ typedef typename _bi::list_av_5<A1, A2, A3, A4, A5>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5));
+}
+
+template<class Rt2, class R, class T,
+ class B1, class B2, class B3, class B4,
+ class A1, class A2, class A3, class A4, class A5>
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf4)<R, T, B1, B2, B3, B4>, typename _bi::list_av_5<A1, A2, A3, A4, A5>::type>
+ BOOST_BIND(boost::type<Rt2>, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf4)<R, T, B1, B2, B3, B4> F;
+ typedef typename _bi::list_av_5<A1, A2, A3, A4, A5>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5));
+}
+
+// 5
+
+template<class Rt2, class R, class T,
+ class B1, class B2, class B3, class B4, class B5,
+ class A1, class A2, class A3, class A4, class A5, class A6>
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf5)<R, T, B1, B2, B3, B4, B5>, typename _bi::list_av_6<A1, A2, A3, A4, A5, A6>::type>
+ BOOST_BIND(boost::type<Rt2>, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf5)<R, T, B1, B2, B3, B4, B5> F;
+ typedef typename _bi::list_av_6<A1, A2, A3, A4, A5, A6>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6));
+}
+
+template<class Rt2, class R, class T,
+ class B1, class B2, class B3, class B4, class B5,
+ class A1, class A2, class A3, class A4, class A5, class A6>
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf5)<R, T, B1, B2, B3, B4, B5>, typename _bi::list_av_6<A1, A2, A3, A4, A5, A6>::type>
+ BOOST_BIND(boost::type<Rt2>, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf5)<R, T, B1, B2, B3, B4, B5> F;
+ typedef typename _bi::list_av_6<A1, A2, A3, A4, A5, A6>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6));
+}
+
+// 6
+
+template<class Rt2, class R, class T,
+ class B1, class B2, class B3, class B4, class B5, class B6,
+ class A1, class A2, class A3, class A4, class A5, class A6, class A7>
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf6)<R, T, B1, B2, B3, B4, B5, B6>, typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type>
+ BOOST_BIND(boost::type<Rt2>, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf6)<R, T, B1, B2, B3, B4, B5, B6> F;
+ typedef typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7));
+}
+
+template<class Rt2, class R, class T,
+ class B1, class B2, class B3, class B4, class B5, class B6,
+ class A1, class A2, class A3, class A4, class A5, class A6, class A7>
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf6)<R, T, B1, B2, B3, B4, B5, B6>, typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type>
+ BOOST_BIND(boost::type<Rt2>, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf6)<R, T, B1, B2, B3, B4, B5, B6> F;
+ typedef typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7));
+}
+
+// 7
+
+template<class Rt2, class R, class T,
+ class B1, class B2, class B3, class B4, class B5, class B6, class B7,
+ class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf7)<R, T, B1, B2, B3, B4, B5, B6, B7>, typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type>
+ BOOST_BIND(boost::type<Rt2>, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf7)<R, T, B1, B2, B3, B4, B5, B6, B7> F;
+ typedef typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8));
+}
+
+template<class Rt2, class R, class T,
+ class B1, class B2, class B3, class B4, class B5, class B6, class B7,
+ class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf7)<R, T, B1, B2, B3, B4, B5, B6, B7>, typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type>
+ BOOST_BIND(boost::type<Rt2>, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf7)<R, T, B1, B2, B3, B4, B5, B6, B7> F;
+ typedef typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8));
+}
+
+// 8
+
+template<class Rt2, class R, class T,
+ class B1, class B2, class B3, class B4, class B5, class B6, class B7, class B8,
+ class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf8)<R, T, B1, B2, B3, B4, B5, B6, B7, B8>, typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type>
+ BOOST_BIND(boost::type<Rt2>, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7, B8), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf8)<R, T, B1, B2, B3, B4, B5, B6, B7, B8> F;
+ typedef typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9));
+}
+
+template<class Rt2, class R, class T,
+ class B1, class B2, class B3, class B4, class B5, class B6, class B7, class B8,
+ class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf8)<R, T, B1, B2, B3, B4, B5, B6, B7, B8>, typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type>
+ BOOST_BIND(boost::type<Rt2>, R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7, B8) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf8)<R, T, B1, B2, B3, B4, B5, B6, B7, B8> F;
+ typedef typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9));
+}
diff --git a/third_party/boost/boost/bind/bind_mf_cc.hpp b/third_party/boost/boost/bind/bind_mf_cc.hpp
new file mode 100644
index 0000000..e149384
--- /dev/null
+++ b/third_party/boost/boost/bind/bind_mf_cc.hpp
@@ -0,0 +1,441 @@
+//
+// bind/bind_mf_cc.hpp - support for different calling conventions
+//
+// Do not include this header directly.
+//
+// Copyright (c) 2001 Peter Dimov and Multi Media Ltd.
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/bind/bind.html for documentation.
+//
+
+// 0
+
+template<class R, class T,
+ class A1>
+ _bi::bind_t<R, _mfi::BOOST_BIND_MF_NAME(mf0)<R, T>, typename _bi::list_av_1<A1>::type>
+ BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (), A1 a1)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf0)<R, T> F;
+ typedef typename _bi::list_av_1<A1>::type list_type;
+ return _bi::bind_t<R, F, list_type>(F(f), list_type(a1));
+}
+
+template<class R, class T,
+ class A1>
+ _bi::bind_t<R, _mfi::BOOST_BIND_MF_NAME(cmf0)<R, T>, typename _bi::list_av_1<A1>::type>
+ BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) () const, A1 a1)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf0)<R, T> F;
+ typedef typename _bi::list_av_1<A1>::type list_type;
+ return _bi::bind_t<R, F, list_type>(F(f), list_type(a1));
+}
+
+template<class Rt2, class R, class T,
+ class A1>
+ typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf0)<R, T>, typename _bi::list_av_1<A1>::type>
+ >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (), A1 a1)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf0)<R, T> F;
+ typedef typename _bi::list_av_1<A1>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1));
+}
+
+template<class Rt2, class R, class T,
+ class A1>
+ typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf0)<R, T>, typename _bi::list_av_1<A1>::type>
+ >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) () const, A1 a1)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf0)<R, T> F;
+ typedef typename _bi::list_av_1<A1>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1));
+}
+
+// 1
+
+template<class R, class T,
+ class B1,
+ class A1, class A2>
+ _bi::bind_t<R, _mfi::BOOST_BIND_MF_NAME(mf1)<R, T, B1>, typename _bi::list_av_2<A1, A2>::type>
+ BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1), A1 a1, A2 a2)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf1)<R, T, B1> F;
+ typedef typename _bi::list_av_2<A1, A2>::type list_type;
+ return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2));
+}
+
+template<class R, class T,
+ class B1,
+ class A1, class A2>
+ _bi::bind_t<R, _mfi::BOOST_BIND_MF_NAME(cmf1)<R, T, B1>, typename _bi::list_av_2<A1, A2>::type>
+ BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1) const, A1 a1, A2 a2)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf1)<R, T, B1> F;
+ typedef typename _bi::list_av_2<A1, A2>::type list_type;
+ return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2));
+}
+
+template<class Rt2, class R, class T,
+ class B1,
+ class A1, class A2>
+ typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf1)<R, T, B1>, typename _bi::list_av_2<A1, A2>::type>
+ >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1), A1 a1, A2 a2)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf1)<R, T, B1> F;
+ typedef typename _bi::list_av_2<A1, A2>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2));
+}
+
+template<class Rt2, class R, class T,
+ class B1,
+ class A1, class A2>
+ typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf1)<R, T, B1>, typename _bi::list_av_2<A1, A2>::type>
+ >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1) const, A1 a1, A2 a2)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf1)<R, T, B1> F;
+ typedef typename _bi::list_av_2<A1, A2>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2));
+}
+
+// 2
+
+template<class R, class T,
+ class B1, class B2,
+ class A1, class A2, class A3>
+ _bi::bind_t<R, _mfi::BOOST_BIND_MF_NAME(mf2)<R, T, B1, B2>, typename _bi::list_av_3<A1, A2, A3>::type>
+ BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2), A1 a1, A2 a2, A3 a3)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf2)<R, T, B1, B2> F;
+ typedef typename _bi::list_av_3<A1, A2, A3>::type list_type;
+ return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3));
+}
+
+template<class R, class T,
+ class B1, class B2,
+ class A1, class A2, class A3>
+ _bi::bind_t<R, _mfi::BOOST_BIND_MF_NAME(cmf2)<R, T, B1, B2>, typename _bi::list_av_3<A1, A2, A3>::type>
+ BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2) const, A1 a1, A2 a2, A3 a3)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf2)<R, T, B1, B2> F;
+ typedef typename _bi::list_av_3<A1, A2, A3>::type list_type;
+ return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3));
+}
+
+template<class Rt2, class R, class T,
+ class B1, class B2,
+ class A1, class A2, class A3>
+ typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf2)<R, T, B1, B2>, typename _bi::list_av_3<A1, A2, A3>::type>
+ >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2), A1 a1, A2 a2, A3 a3)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf2)<R, T, B1, B2> F;
+ typedef typename _bi::list_av_3<A1, A2, A3>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3));
+}
+
+template<class Rt2, class R, class T,
+ class B1, class B2,
+ class A1, class A2, class A3>
+ typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf2)<R, T, B1, B2>, typename _bi::list_av_3<A1, A2, A3>::type>
+ >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2) const, A1 a1, A2 a2, A3 a3)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf2)<R, T, B1, B2> F;
+ typedef typename _bi::list_av_3<A1, A2, A3>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3));
+}
+
+// 3
+
+template<class R, class T,
+ class B1, class B2, class B3,
+ class A1, class A2, class A3, class A4>
+ _bi::bind_t<R, _mfi::BOOST_BIND_MF_NAME(mf3)<R, T, B1, B2, B3>, typename _bi::list_av_4<A1, A2, A3, A4>::type>
+ BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3), A1 a1, A2 a2, A3 a3, A4 a4)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf3)<R, T, B1, B2, B3> F;
+ typedef typename _bi::list_av_4<A1, A2, A3, A4>::type list_type;
+ return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3, a4));
+}
+
+template<class R, class T,
+ class B1, class B2, class B3,
+ class A1, class A2, class A3, class A4>
+ _bi::bind_t<R, _mfi::BOOST_BIND_MF_NAME(cmf3)<R, T, B1, B2, B3>, typename _bi::list_av_4<A1, A2, A3, A4>::type>
+ BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3) const, A1 a1, A2 a2, A3 a3, A4 a4)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf3)<R, T, B1, B2, B3> F;
+ typedef typename _bi::list_av_4<A1, A2, A3, A4>::type list_type;
+ return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3, a4));
+}
+
+template<class Rt2, class R, class T,
+ class B1, class B2, class B3,
+ class A1, class A2, class A3, class A4>
+ typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf3)<R, T, B1, B2, B3>, typename _bi::list_av_4<A1, A2, A3, A4>::type>
+ >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3), A1 a1, A2 a2, A3 a3, A4 a4)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf3)<R, T, B1, B2, B3> F;
+ typedef typename _bi::list_av_4<A1, A2, A3, A4>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4));
+}
+
+template<class Rt2, class R, class T,
+ class B1, class B2, class B3,
+ class A1, class A2, class A3, class A4>
+ typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf3)<R, T, B1, B2, B3>, typename _bi::list_av_4<A1, A2, A3, A4>::type>
+ >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3) const, A1 a1, A2 a2, A3 a3, A4 a4)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf3)<R, T, B1, B2, B3> F;
+ typedef typename _bi::list_av_4<A1, A2, A3, A4>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4));
+}
+
+// 4
+
+template<class R, class T,
+ class B1, class B2, class B3, class B4,
+ class A1, class A2, class A3, class A4, class A5>
+ _bi::bind_t<R, _mfi::BOOST_BIND_MF_NAME(mf4)<R, T, B1, B2, B3, B4>, typename _bi::list_av_5<A1, A2, A3, A4, A5>::type>
+ BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf4)<R, T, B1, B2, B3, B4> F;
+ typedef typename _bi::list_av_5<A1, A2, A3, A4, A5>::type list_type;
+ return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5));
+}
+
+template<class R, class T,
+ class B1, class B2, class B3, class B4,
+ class A1, class A2, class A3, class A4, class A5>
+ _bi::bind_t<R, _mfi::BOOST_BIND_MF_NAME(cmf4)<R, T, B1, B2, B3, B4>, typename _bi::list_av_5<A1, A2, A3, A4, A5>::type>
+ BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf4)<R, T, B1, B2, B3, B4> F;
+ typedef typename _bi::list_av_5<A1, A2, A3, A4, A5>::type list_type;
+ return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5));
+}
+
+template<class Rt2, class R, class T,
+ class B1, class B2, class B3, class B4,
+ class A1, class A2, class A3, class A4, class A5>
+ typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf4)<R, T, B1, B2, B3, B4>, typename _bi::list_av_5<A1, A2, A3, A4, A5>::type>
+ >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf4)<R, T, B1, B2, B3, B4> F;
+ typedef typename _bi::list_av_5<A1, A2, A3, A4, A5>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5));
+}
+
+template<class Rt2, class R, class T,
+ class B1, class B2, class B3, class B4,
+ class A1, class A2, class A3, class A4, class A5>
+ typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf4)<R, T, B1, B2, B3, B4>, typename _bi::list_av_5<A1, A2, A3, A4, A5>::type>
+ >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf4)<R, T, B1, B2, B3, B4> F;
+ typedef typename _bi::list_av_5<A1, A2, A3, A4, A5>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5));
+}
+
+// 5
+
+template<class R, class T,
+ class B1, class B2, class B3, class B4, class B5,
+ class A1, class A2, class A3, class A4, class A5, class A6>
+ _bi::bind_t<R, _mfi::BOOST_BIND_MF_NAME(mf5)<R, T, B1, B2, B3, B4, B5>, typename _bi::list_av_6<A1, A2, A3, A4, A5, A6>::type>
+ BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf5)<R, T, B1, B2, B3, B4, B5> F;
+ typedef typename _bi::list_av_6<A1, A2, A3, A4, A5, A6>::type list_type;
+ return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6));
+}
+
+template<class R, class T,
+ class B1, class B2, class B3, class B4, class B5,
+ class A1, class A2, class A3, class A4, class A5, class A6>
+ _bi::bind_t<R, _mfi::BOOST_BIND_MF_NAME(cmf5)<R, T, B1, B2, B3, B4, B5>, typename _bi::list_av_6<A1, A2, A3, A4, A5, A6>::type>
+ BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf5)<R, T, B1, B2, B3, B4, B5> F;
+ typedef typename _bi::list_av_6<A1, A2, A3, A4, A5, A6>::type list_type;
+ return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6));
+}
+
+template<class Rt2, class R, class T,
+ class B1, class B2, class B3, class B4, class B5,
+ class A1, class A2, class A3, class A4, class A5, class A6>
+ typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf5)<R, T, B1, B2, B3, B4, B5>, typename _bi::list_av_6<A1, A2, A3, A4, A5, A6>::type>
+ >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf5)<R, T, B1, B2, B3, B4, B5> F;
+ typedef typename _bi::list_av_6<A1, A2, A3, A4, A5, A6>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6));
+}
+
+template<class Rt2, class R, class T,
+ class B1, class B2, class B3, class B4, class B5,
+ class A1, class A2, class A3, class A4, class A5, class A6>
+ typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf5)<R, T, B1, B2, B3, B4, B5>, typename _bi::list_av_6<A1, A2, A3, A4, A5, A6>::type>
+ >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf5)<R, T, B1, B2, B3, B4, B5> F;
+ typedef typename _bi::list_av_6<A1, A2, A3, A4, A5, A6>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6));
+}
+
+// 6
+
+template<class R, class T,
+ class B1, class B2, class B3, class B4, class B5, class B6,
+ class A1, class A2, class A3, class A4, class A5, class A6, class A7>
+ _bi::bind_t<R, _mfi::BOOST_BIND_MF_NAME(mf6)<R, T, B1, B2, B3, B4, B5, B6>, typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type>
+ BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf6)<R, T, B1, B2, B3, B4, B5, B6> F;
+ typedef typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type list_type;
+ return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7));
+}
+
+template<class R, class T,
+ class B1, class B2, class B3, class B4, class B5, class B6,
+ class A1, class A2, class A3, class A4, class A5, class A6, class A7>
+ _bi::bind_t<R, _mfi::BOOST_BIND_MF_NAME(cmf6)<R, T, B1, B2, B3, B4, B5, B6>, typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type>
+ BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf6)<R, T, B1, B2, B3, B4, B5, B6> F;
+ typedef typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type list_type;
+ return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7));
+}
+
+template<class Rt2, class R, class T,
+ class B1, class B2, class B3, class B4, class B5, class B6,
+ class A1, class A2, class A3, class A4, class A5, class A6, class A7>
+ typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf6)<R, T, B1, B2, B3, B4, B5, B6>, typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type>
+ >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf6)<R, T, B1, B2, B3, B4, B5, B6> F;
+ typedef typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7));
+}
+
+template<class Rt2, class R, class T,
+ class B1, class B2, class B3, class B4, class B5, class B6,
+ class A1, class A2, class A3, class A4, class A5, class A6, class A7>
+ typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf6)<R, T, B1, B2, B3, B4, B5, B6>, typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type>
+ >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf6)<R, T, B1, B2, B3, B4, B5, B6> F;
+ typedef typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7));
+}
+
+// 7
+
+template<class R, class T,
+ class B1, class B2, class B3, class B4, class B5, class B6, class B7,
+ class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
+ _bi::bind_t<R, _mfi::BOOST_BIND_MF_NAME(mf7)<R, T, B1, B2, B3, B4, B5, B6, B7>, typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type>
+ BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf7)<R, T, B1, B2, B3, B4, B5, B6, B7> F;
+ typedef typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type list_type;
+ return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8));
+}
+
+template<class R, class T,
+ class B1, class B2, class B3, class B4, class B5, class B6, class B7,
+ class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
+ _bi::bind_t<R, _mfi::BOOST_BIND_MF_NAME(cmf7)<R, T, B1, B2, B3, B4, B5, B6, B7>, typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type>
+ BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf7)<R, T, B1, B2, B3, B4, B5, B6, B7> F;
+ typedef typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type list_type;
+ return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8));
+}
+
+template<class Rt2, class R, class T,
+ class B1, class B2, class B3, class B4, class B5, class B6, class B7,
+ class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
+ typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf7)<R, T, B1, B2, B3, B4, B5, B6, B7>, typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type>
+ >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf7)<R, T, B1, B2, B3, B4, B5, B6, B7> F;
+ typedef typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8));
+}
+
+template<class Rt2, class R, class T,
+ class B1, class B2, class B3, class B4, class B5, class B6, class B7,
+ class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
+ typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf7)<R, T, B1, B2, B3, B4, B5, B6, B7>, typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type>
+ >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf7)<R, T, B1, B2, B3, B4, B5, B6, B7> F;
+ typedef typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8));
+}
+
+// 8
+
+template<class R, class T,
+ class B1, class B2, class B3, class B4, class B5, class B6, class B7, class B8,
+ class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
+ _bi::bind_t<R, _mfi::BOOST_BIND_MF_NAME(mf8)<R, T, B1, B2, B3, B4, B5, B6, B7, B8>, typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type>
+ BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7, B8), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf8)<R, T, B1, B2, B3, B4, B5, B6, B7, B8> F;
+ typedef typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type list_type;
+ return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9));
+}
+
+template<class R, class T,
+ class B1, class B2, class B3, class B4, class B5, class B6, class B7, class B8,
+ class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
+ _bi::bind_t<R, _mfi::BOOST_BIND_MF_NAME(cmf8)<R, T, B1, B2, B3, B4, B5, B6, B7, B8>, typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type>
+ BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7, B8) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf8)<R, T, B1, B2, B3, B4, B5, B6, B7, B8> F;
+ typedef typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type list_type;
+ return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9));
+}
+
+template<class Rt2, class R, class T,
+ class B1, class B2, class B3, class B4, class B5, class B6, class B7, class B8,
+ class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
+ typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf8)<R, T, B1, B2, B3, B4, B5, B6, B7, B8>, typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type>
+ >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7, B8), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(mf8)<R, T, B1, B2, B3, B4, B5, B6, B7, B8> F;
+ typedef typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9));
+}
+
+template<class Rt2, class R, class T,
+ class B1, class B2, class B3, class B4, class B5, class B6, class B7, class B8,
+ class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
+ typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
+ _bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf8)<R, T, B1, B2, B3, B4, B5, B6, B7, B8>, typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type>
+ >::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7, B8) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
+{
+ typedef _mfi::BOOST_BIND_MF_NAME(cmf8)<R, T, B1, B2, B3, B4, B5, B6, B7, B8> F;
+ typedef typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type list_type;
+ return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9));
+}
diff --git a/third_party/boost/boost/bind/bind_template.hpp b/third_party/boost/boost/bind/bind_template.hpp
new file mode 100644
index 0000000..411d20c
--- /dev/null
+++ b/third_party/boost/boost/bind/bind_template.hpp
@@ -0,0 +1,345 @@
+//
+// bind/bind_template.hpp
+//
+// Do not include this header directly.
+//
+// Copyright (c) 2001-2004 Peter Dimov and Multi Media Ltd.
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/bind/bind.html for documentation.
+//
+
+ typedef typename result_traits<R, F>::type result_type;
+
+ result_type operator()()
+ {
+ list0 a;
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+ result_type operator()() const
+ {
+ list0 a;
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+ template<class A1> result_type operator()(A1 & a1)
+ {
+ list1<A1 &> a(a1);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+ template<class A1> result_type operator()(A1 & a1) const
+ {
+ list1<A1 &> a(a1);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \
+ && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
+
+ template<class A1> result_type operator()(A1 const & a1)
+ {
+ list1<A1 const &> a(a1);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+ template<class A1> result_type operator()(A1 const & a1) const
+ {
+ list1<A1 const &> a(a1);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+#endif
+
+ template<class A1, class A2> result_type operator()(A1 & a1, A2 & a2)
+ {
+ list2<A1 &, A2 &> a(a1, a2);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+ template<class A1, class A2> result_type operator()(A1 & a1, A2 & a2) const
+ {
+ list2<A1 &, A2 &> a(a1, a2);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \
+ && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
+
+ template<class A1, class A2> result_type operator()(A1 const & a1, A2 & a2)
+ {
+ list2<A1 const &, A2 &> a(a1, a2);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+ template<class A1, class A2> result_type operator()(A1 const & a1, A2 & a2) const
+ {
+ list2<A1 const &, A2 &> a(a1, a2);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+
+ template<class A1, class A2> result_type operator()(A1 & a1, A2 const & a2)
+ {
+ list2<A1 &, A2 const &> a(a1, a2);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+ template<class A1, class A2> result_type operator()(A1 & a1, A2 const & a2) const
+ {
+ list2<A1 &, A2 const &> a(a1, a2);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+
+ template<class A1, class A2> result_type operator()(A1 const & a1, A2 const & a2)
+ {
+ list2<A1 const &, A2 const &> a(a1, a2);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+ template<class A1, class A2> result_type operator()(A1 const & a1, A2 const & a2) const
+ {
+ list2<A1 const &, A2 const &> a(a1, a2);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+#endif
+
+ template<class A1, class A2, class A3> result_type operator()(A1 & a1, A2 & a2, A3 & a3)
+ {
+ list3<A1 &, A2 &, A3 &> a(a1, a2, a3);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+ template<class A1, class A2, class A3> result_type operator()(A1 & a1, A2 & a2, A3 & a3) const
+ {
+ list3<A1 &, A2 &, A3 &> a(a1, a2, a3);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \
+ && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
+
+ template<class A1, class A2, class A3> result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3)
+ {
+ list3<A1 const &, A2 const &, A3 const &> a(a1, a2, a3);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+ template<class A1, class A2, class A3> result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3) const
+ {
+ list3<A1 const &, A2 const &, A3 const &> a(a1, a2, a3);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+#endif
+
+ template<class A1, class A2, class A3, class A4> result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4)
+ {
+ list4<A1 &, A2 &, A3 &, A4 &> a(a1, a2, a3, a4);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+ template<class A1, class A2, class A3, class A4> result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4) const
+ {
+ list4<A1 &, A2 &, A3 &, A4 &> a(a1, a2, a3, a4);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \
+ && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
+
+ template<class A1, class A2, class A3, class A4> result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4)
+ {
+ list4<A1 const &, A2 const &, A3 const &, A4 const &> a(a1, a2, a3, a4);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+ template<class A1, class A2, class A3, class A4> result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4) const
+ {
+ list4<A1 const &, A2 const &, A3 const &, A4 const &> a(a1, a2, a3, a4);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+#endif
+
+ template<class A1, class A2, class A3, class A4, class A5> result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5)
+ {
+ list5<A1 &, A2 &, A3 &, A4 &, A5 &> a(a1, a2, a3, a4, a5);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+ template<class A1, class A2, class A3, class A4, class A5> result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5) const
+ {
+ list5<A1 &, A2 &, A3 &, A4 &, A5 &> a(a1, a2, a3, a4, a5);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \
+ && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
+
+ template<class A1, class A2, class A3, class A4, class A5> result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5)
+ {
+ list5<A1 const &, A2 const &, A3 const &, A4 const &, A5 const &> a(a1, a2, a3, a4, a5);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+ template<class A1, class A2, class A3, class A4, class A5> result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5) const
+ {
+ list5<A1 const &, A2 const &, A3 const &, A4 const &, A5 const &> a(a1, a2, a3, a4, a5);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+#endif
+
+ template<class A1, class A2, class A3, class A4, class A5, class A6> result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6)
+ {
+ list6<A1 &, A2 &, A3 &, A4 &, A5 &, A6 &> a(a1, a2, a3, a4, a5, a6);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+ template<class A1, class A2, class A3, class A4, class A5, class A6> result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6) const
+ {
+ list6<A1 &, A2 &, A3 &, A4 &, A5 &, A6 &> a(a1, a2, a3, a4, a5, a6);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \
+ && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
+
+ template<class A1, class A2, class A3, class A4, class A5, class A6> result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6)
+ {
+ list6<A1 const &, A2 const &, A3 const &, A4 const &, A5 const &, A6 const &> a(a1, a2, a3, a4, a5, a6);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+ template<class A1, class A2, class A3, class A4, class A5, class A6> result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6) const
+ {
+ list6<A1 const &, A2 const &, A3 const &, A4 const &, A5 const &, A6 const &> a(a1, a2, a3, a4, a5, a6);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+#endif
+
+ template<class A1, class A2, class A3, class A4, class A5, class A6, class A7> result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7)
+ {
+ list7<A1 &, A2 &, A3 &, A4 &, A5 &, A6 &, A7 &> a(a1, a2, a3, a4, a5, a6, a7);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+ template<class A1, class A2, class A3, class A4, class A5, class A6, class A7> result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7) const
+ {
+ list7<A1 &, A2 &, A3 &, A4 &, A5 &, A6 &, A7 &> a(a1, a2, a3, a4, a5, a6, a7);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \
+ && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
+
+ template<class A1, class A2, class A3, class A4, class A5, class A6, class A7> result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7)
+ {
+ list7<A1 const &, A2 const &, A3 const &, A4 const &, A5 const &, A6 const &, A7 const &> a(a1, a2, a3, a4, a5, a6, a7);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+ template<class A1, class A2, class A3, class A4, class A5, class A6, class A7> result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7) const
+ {
+ list7<A1 const &, A2 const &, A3 const &, A4 const &, A5 const &, A6 const &, A7 const &> a(a1, a2, a3, a4, a5, a6, a7);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+#endif
+
+ template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8)
+ {
+ list8<A1 &, A2 &, A3 &, A4 &, A5 &, A6 &, A7 &, A8 &> a(a1, a2, a3, a4, a5, a6, a7, a8);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+ template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8) const
+ {
+ list8<A1 &, A2 &, A3 &, A4 &, A5 &, A6 &, A7 &, A8 &> a(a1, a2, a3, a4, a5, a6, a7, a8);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \
+ && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
+
+ template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8)
+ {
+ list8<A1 const &, A2 const &, A3 const &, A4 const &, A5 const &, A6 const &, A7 const &, A8 const &> a(a1, a2, a3, a4, a5, a6, a7, a8);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+ template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8) const
+ {
+ list8<A1 const &, A2 const &, A3 const &, A4 const &, A5 const &, A6 const &, A7 const &, A8 const &> a(a1, a2, a3, a4, a5, a6, a7, a8);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+#endif
+
+ template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8, A9 & a9)
+ {
+ list9<A1 &, A2 &, A3 &, A4 &, A5 &, A6 &, A7 &, A8 &, A9 &> a(a1, a2, a3, a4, a5, a6, a7, a8, a9);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+ template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> result_type operator()(A1 & a1, A2 & a2, A3 & a3, A4 & a4, A5 & a5, A6 & a6, A7 & a7, A8 & a8, A9 & a9) const
+ {
+ list9<A1 &, A2 &, A3 &, A4 &, A5 &, A6 &, A7 &, A8 &, A9 &> a(a1, a2, a3, a4, a5, a6, a7, a8, a9);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) \
+ && !BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
+
+ template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9)
+ {
+ list9<A1 const &, A2 const &, A3 const &, A4 const &, A5 const &, A6 const &, A7 const &, A8 const &, A9 const &> a(a1, a2, a3, a4, a5, a6, a7, a8, a9);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+ template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> result_type operator()(A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9) const
+ {
+ list9<A1 const &, A2 const &, A3 const &, A4 const &, A5 const &, A6 const &, A7 const &, A8 const &, A9 const &> a(a1, a2, a3, a4, a5, a6, a7, a8, a9);
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+#endif
+
+ template<class A> result_type eval(A & a)
+ {
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+ template<class A> result_type eval(A & a) const
+ {
+ BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0);
+ }
+
+ template<class V> void accept(V & v) const
+ {
+#if !defined( BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP ) && !defined( __BORLANDC__ )
+
+ using boost::visit_each;
+
+#endif
+ BOOST_BIND_VISIT_EACH(v, f_, 0);
+ l_.accept(v);
+ }
+
+ bool compare(this_type const & rhs) const
+ {
+ return ref_compare(f_, rhs.f_, 0) && l_ == rhs.l_;
+ }
+
+private:
+
+ F f_;
+ L l_;
diff --git a/third_party/boost/boost/bind/mem_fn.hpp b/third_party/boost/boost/bind/mem_fn.hpp
new file mode 100644
index 0000000..e3154e3
--- /dev/null
+++ b/third_party/boost/boost/bind/mem_fn.hpp
@@ -0,0 +1,389 @@
+#ifndef BOOST_BIND_MEM_FN_HPP_INCLUDED
+#define BOOST_BIND_MEM_FN_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// mem_fn.hpp - a generalization of std::mem_fun[_ref]
+//
+// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
+// Copyright (c) 2001 David Abrahams
+// Copyright (c) 2003-2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/bind/mem_fn.html for documentation.
+//
+
+#include <boost/config.hpp>
+#include <boost/get_pointer.hpp>
+#include <boost/detail/workaround.hpp>
+
+namespace boost
+{
+
+#if defined(BOOST_NO_VOID_RETURNS)
+
+#define BOOST_MEM_FN_CLASS_F , class F
+#define BOOST_MEM_FN_TYPEDEF(X)
+
+namespace _mfi // mem_fun_impl
+{
+
+template<class V> struct mf
+{
+
+#define BOOST_MEM_FN_RETURN return
+
+#define BOOST_MEM_FN_NAME(X) inner_##X
+#define BOOST_MEM_FN_CC
+
+#include <boost/bind/mem_fn_template.hpp>
+
+#undef BOOST_MEM_FN_CC
+#undef BOOST_MEM_FN_NAME
+
+#ifdef BOOST_MEM_FN_ENABLE_CDECL
+
+#define BOOST_MEM_FN_NAME(X) inner_##X##_cdecl
+#define BOOST_MEM_FN_CC __cdecl
+
+#include <boost/bind/mem_fn_template.hpp>
+
+#undef BOOST_MEM_FN_CC
+#undef BOOST_MEM_FN_NAME
+
+#endif
+
+#ifdef BOOST_MEM_FN_ENABLE_STDCALL
+
+#define BOOST_MEM_FN_NAME(X) inner_##X##_stdcall
+#define BOOST_MEM_FN_CC __stdcall
+
+#include <boost/bind/mem_fn_template.hpp>
+
+#undef BOOST_MEM_FN_CC
+#undef BOOST_MEM_FN_NAME
+
+#endif
+
+#ifdef BOOST_MEM_FN_ENABLE_FASTCALL
+
+#define BOOST_MEM_FN_NAME(X) inner_##X##_fastcall
+#define BOOST_MEM_FN_CC __fastcall
+
+#include <boost/bind/mem_fn_template.hpp>
+
+#undef BOOST_MEM_FN_CC
+#undef BOOST_MEM_FN_NAME
+
+#endif
+
+#undef BOOST_MEM_FN_RETURN
+
+}; // struct mf<V>
+
+template<> struct mf<void>
+{
+
+#define BOOST_MEM_FN_RETURN
+
+#define BOOST_MEM_FN_NAME(X) inner_##X
+#define BOOST_MEM_FN_CC
+
+#include <boost/bind/mem_fn_template.hpp>
+
+#undef BOOST_MEM_FN_CC
+#undef BOOST_MEM_FN_NAME
+
+#ifdef BOOST_MEM_FN_ENABLE_CDECL
+
+#define BOOST_MEM_FN_NAME(X) inner_##X##_cdecl
+#define BOOST_MEM_FN_CC __cdecl
+
+#include <boost/bind/mem_fn_template.hpp>
+
+#undef BOOST_MEM_FN_CC
+#undef BOOST_MEM_FN_NAME
+
+#endif
+
+#ifdef BOOST_MEM_FN_ENABLE_STDCALL
+
+#define BOOST_MEM_FN_NAME(X) inner_##X##_stdcall
+#define BOOST_MEM_FN_CC __stdcall
+
+#include <boost/bind/mem_fn_template.hpp>
+
+#undef BOOST_MEM_FN_CC
+#undef BOOST_MEM_FN_NAME
+
+#endif
+
+#ifdef BOOST_MEM_FN_ENABLE_FASTCALL
+
+#define BOOST_MEM_FN_NAME(X) inner_##X##_fastcall
+#define BOOST_MEM_FN_CC __fastcall
+
+#include <boost/bind/mem_fn_template.hpp>
+
+#undef BOOST_MEM_FN_CC
+#undef BOOST_MEM_FN_NAME
+
+#endif
+
+#undef BOOST_MEM_FN_RETURN
+
+}; // struct mf<void>
+
+#undef BOOST_MEM_FN_CLASS_F
+#undef BOOST_MEM_FN_TYPEDEF_F
+
+#define BOOST_MEM_FN_NAME(X) X
+#define BOOST_MEM_FN_NAME2(X) inner_##X
+#define BOOST_MEM_FN_CC
+
+#include <boost/bind/mem_fn_vw.hpp>
+
+#undef BOOST_MEM_FN_NAME
+#undef BOOST_MEM_FN_NAME2
+#undef BOOST_MEM_FN_CC
+
+#ifdef BOOST_MEM_FN_ENABLE_CDECL
+
+#define BOOST_MEM_FN_NAME(X) X##_cdecl
+#define BOOST_MEM_FN_NAME2(X) inner_##X##_cdecl
+#define BOOST_MEM_FN_CC __cdecl
+
+#include <boost/bind/mem_fn_vw.hpp>
+
+#undef BOOST_MEM_FN_NAME
+#undef BOOST_MEM_FN_NAME2
+#undef BOOST_MEM_FN_CC
+
+#endif
+
+#ifdef BOOST_MEM_FN_ENABLE_STDCALL
+
+#define BOOST_MEM_FN_NAME(X) X##_stdcall
+#define BOOST_MEM_FN_NAME2(X) inner_##X##_stdcall
+#define BOOST_MEM_FN_CC __stdcall
+
+#include <boost/bind/mem_fn_vw.hpp>
+
+#undef BOOST_MEM_FN_NAME
+#undef BOOST_MEM_FN_NAME2
+#undef BOOST_MEM_FN_CC
+
+#endif
+
+#ifdef BOOST_MEM_FN_ENABLE_FASTCALL
+
+#define BOOST_MEM_FN_NAME(X) X##_fastcall
+#define BOOST_MEM_FN_NAME2(X) inner_##X##_fastcall
+#define BOOST_MEM_FN_CC __fastcall
+
+#include <boost/bind/mem_fn_vw.hpp>
+
+#undef BOOST_MEM_FN_NAME
+#undef BOOST_MEM_FN_NAME2
+#undef BOOST_MEM_FN_CC
+
+#endif
+
+} // namespace _mfi
+
+#else // #ifdef BOOST_NO_VOID_RETURNS
+
+#define BOOST_MEM_FN_CLASS_F
+#define BOOST_MEM_FN_TYPEDEF(X) typedef X;
+
+namespace _mfi
+{
+
+#define BOOST_MEM_FN_RETURN return
+
+#define BOOST_MEM_FN_NAME(X) X
+#define BOOST_MEM_FN_CC
+
+#include <boost/bind/mem_fn_template.hpp>
+
+#undef BOOST_MEM_FN_CC
+#undef BOOST_MEM_FN_NAME
+
+#ifdef BOOST_MEM_FN_ENABLE_CDECL
+
+#define BOOST_MEM_FN_NAME(X) X##_cdecl
+#define BOOST_MEM_FN_CC __cdecl
+
+#include <boost/bind/mem_fn_template.hpp>
+
+#undef BOOST_MEM_FN_CC
+#undef BOOST_MEM_FN_NAME
+
+#endif
+
+#ifdef BOOST_MEM_FN_ENABLE_STDCALL
+
+#define BOOST_MEM_FN_NAME(X) X##_stdcall
+#define BOOST_MEM_FN_CC __stdcall
+
+#include <boost/bind/mem_fn_template.hpp>
+
+#undef BOOST_MEM_FN_CC
+#undef BOOST_MEM_FN_NAME
+
+#endif
+
+#ifdef BOOST_MEM_FN_ENABLE_FASTCALL
+
+#define BOOST_MEM_FN_NAME(X) X##_fastcall
+#define BOOST_MEM_FN_CC __fastcall
+
+#include <boost/bind/mem_fn_template.hpp>
+
+#undef BOOST_MEM_FN_CC
+#undef BOOST_MEM_FN_NAME
+
+#endif
+
+#undef BOOST_MEM_FN_RETURN
+
+} // namespace _mfi
+
+#undef BOOST_MEM_FN_CLASS_F
+#undef BOOST_MEM_FN_TYPEDEF
+
+#endif // #ifdef BOOST_NO_VOID_RETURNS
+
+#define BOOST_MEM_FN_NAME(X) X
+#define BOOST_MEM_FN_CC
+
+#include <boost/bind/mem_fn_cc.hpp>
+
+#undef BOOST_MEM_FN_NAME
+#undef BOOST_MEM_FN_CC
+
+#ifdef BOOST_MEM_FN_ENABLE_CDECL
+
+#define BOOST_MEM_FN_NAME(X) X##_cdecl
+#define BOOST_MEM_FN_CC __cdecl
+
+#include <boost/bind/mem_fn_cc.hpp>
+
+#undef BOOST_MEM_FN_NAME
+#undef BOOST_MEM_FN_CC
+
+#endif
+
+#ifdef BOOST_MEM_FN_ENABLE_STDCALL
+
+#define BOOST_MEM_FN_NAME(X) X##_stdcall
+#define BOOST_MEM_FN_CC __stdcall
+
+#include <boost/bind/mem_fn_cc.hpp>
+
+#undef BOOST_MEM_FN_NAME
+#undef BOOST_MEM_FN_CC
+
+#endif
+
+#ifdef BOOST_MEM_FN_ENABLE_FASTCALL
+
+#define BOOST_MEM_FN_NAME(X) X##_fastcall
+#define BOOST_MEM_FN_CC __fastcall
+
+#include <boost/bind/mem_fn_cc.hpp>
+
+#undef BOOST_MEM_FN_NAME
+#undef BOOST_MEM_FN_CC
+
+#endif
+
+// data member support
+
+namespace _mfi
+{
+
+template<class R, class T> class dm
+{
+public:
+
+ typedef R const & result_type;
+ typedef T const * argument_type;
+
+private:
+
+ typedef R (T::*F);
+ F f_;
+
+ template<class U> R const & call(U & u, T const *) const
+ {
+ return (u.*f_);
+ }
+
+ template<class U> R const & call(U & u, void const *) const
+ {
+ return (get_pointer(u)->*f_);
+ }
+
+public:
+
+ explicit dm(F f): f_(f) {}
+
+ R & operator()(T * p) const
+ {
+ return (p->*f_);
+ }
+
+ R const & operator()(T const * p) const
+ {
+ return (p->*f_);
+ }
+
+ template<class U> R const & operator()(U const & u) const
+ {
+ return call(u, &u);
+ }
+
+#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1300) && !BOOST_WORKAROUND(__MWERKS__, < 0x3200)
+
+ R & operator()(T & t) const
+ {
+ return (t.*f_);
+ }
+
+ R const & operator()(T const & t) const
+ {
+ return (t.*f_);
+ }
+
+#endif
+
+ bool operator==(dm const & rhs) const
+ {
+ return f_ == rhs.f_;
+ }
+
+ bool operator!=(dm const & rhs) const
+ {
+ return f_ != rhs.f_;
+ }
+};
+
+} // namespace _mfi
+
+template<class R, class T> _mfi::dm<R, T> mem_fn(R T::*f)
+{
+ return _mfi::dm<R, T>(f);
+}
+
+} // namespace boost
+
+#endif // #ifndef BOOST_BIND_MEM_FN_HPP_INCLUDED
diff --git a/third_party/boost/boost/bind/mem_fn_cc.hpp b/third_party/boost/boost/bind/mem_fn_cc.hpp
new file mode 100644
index 0000000..8b6ea0b
--- /dev/null
+++ b/third_party/boost/boost/bind/mem_fn_cc.hpp
@@ -0,0 +1,103 @@
+//
+// bind/mem_fn_cc.hpp - support for different calling conventions
+//
+// Do not include this header directly.
+//
+// Copyright (c) 2001 Peter Dimov and Multi Media Ltd.
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/bind/mem_fn.html for documentation.
+//
+
+template<class R, class T> _mfi::BOOST_MEM_FN_NAME(mf0)<R, T> mem_fn(R (BOOST_MEM_FN_CC T::*f) ())
+{
+ return _mfi::BOOST_MEM_FN_NAME(mf0)<R, T>(f);
+}
+
+template<class R, class T> _mfi::BOOST_MEM_FN_NAME(cmf0)<R, T> mem_fn(R (BOOST_MEM_FN_CC T::*f) () const)
+{
+ return _mfi::BOOST_MEM_FN_NAME(cmf0)<R, T>(f);
+}
+
+template<class R, class T, class A1> _mfi::BOOST_MEM_FN_NAME(mf1)<R, T, A1> mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1))
+{
+ return _mfi::BOOST_MEM_FN_NAME(mf1)<R, T, A1>(f);
+}
+
+template<class R, class T, class A1> _mfi::BOOST_MEM_FN_NAME(cmf1)<R, T, A1> mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1) const)
+{
+ return _mfi::BOOST_MEM_FN_NAME(cmf1)<R, T, A1>(f);
+}
+
+template<class R, class T, class A1, class A2> _mfi::BOOST_MEM_FN_NAME(mf2)<R, T, A1, A2> mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2))
+{
+ return _mfi::BOOST_MEM_FN_NAME(mf2)<R, T, A1, A2>(f);
+}
+
+template<class R, class T, class A1, class A2> _mfi::BOOST_MEM_FN_NAME(cmf2)<R, T, A1, A2> mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2) const)
+{
+ return _mfi::BOOST_MEM_FN_NAME(cmf2)<R, T, A1, A2>(f);
+}
+
+template<class R, class T, class A1, class A2, class A3> _mfi::BOOST_MEM_FN_NAME(mf3)<R, T, A1, A2, A3> mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2, A3))
+{
+ return _mfi::BOOST_MEM_FN_NAME(mf3)<R, T, A1, A2, A3>(f);
+}
+
+template<class R, class T, class A1, class A2, class A3> _mfi::BOOST_MEM_FN_NAME(cmf3)<R, T, A1, A2, A3> mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2, A3) const)
+{
+ return _mfi::BOOST_MEM_FN_NAME(cmf3)<R, T, A1, A2, A3>(f);
+}
+
+template<class R, class T, class A1, class A2, class A3, class A4> _mfi::BOOST_MEM_FN_NAME(mf4)<R, T, A1, A2, A3, A4> mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2, A3, A4))
+{
+ return _mfi::BOOST_MEM_FN_NAME(mf4)<R, T, A1, A2, A3, A4>(f);
+}
+
+template<class R, class T, class A1, class A2, class A3, class A4> _mfi::BOOST_MEM_FN_NAME(cmf4)<R, T, A1, A2, A3, A4> mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2, A3, A4) const)
+{
+ return _mfi::BOOST_MEM_FN_NAME(cmf4)<R, T, A1, A2, A3, A4>(f);
+}
+
+template<class R, class T, class A1, class A2, class A3, class A4, class A5> _mfi::BOOST_MEM_FN_NAME(mf5)<R, T, A1, A2, A3, A4, A5> mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2, A3, A4, A5))
+{
+ return _mfi::BOOST_MEM_FN_NAME(mf5)<R, T, A1, A2, A3, A4, A5>(f);
+}
+
+template<class R, class T, class A1, class A2, class A3, class A4, class A5> _mfi::BOOST_MEM_FN_NAME(cmf5)<R, T, A1, A2, A3, A4, A5> mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2, A3, A4, A5) const)
+{
+ return _mfi::BOOST_MEM_FN_NAME(cmf5)<R, T, A1, A2, A3, A4, A5>(f);
+}
+
+template<class R, class T, class A1, class A2, class A3, class A4, class A5, class A6> _mfi::BOOST_MEM_FN_NAME(mf6)<R, T, A1, A2, A3, A4, A5, A6> mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2, A3, A4, A5, A6))
+{
+ return _mfi::BOOST_MEM_FN_NAME(mf6)<R, T, A1, A2, A3, A4, A5, A6>(f);
+}
+
+template<class R, class T, class A1, class A2, class A3, class A4, class A5, class A6> _mfi::BOOST_MEM_FN_NAME(cmf6)<R, T, A1, A2, A3, A4, A5, A6> mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2, A3, A4, A5, A6) const)
+{
+ return _mfi::BOOST_MEM_FN_NAME(cmf6)<R, T, A1, A2, A3, A4, A5, A6>(f);
+}
+
+template<class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7> _mfi::BOOST_MEM_FN_NAME(mf7)<R, T, A1, A2, A3, A4, A5, A6, A7> mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2, A3, A4, A5, A6, A7))
+{
+ return _mfi::BOOST_MEM_FN_NAME(mf7)<R, T, A1, A2, A3, A4, A5, A6, A7>(f);
+}
+
+template<class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7> _mfi::BOOST_MEM_FN_NAME(cmf7)<R, T, A1, A2, A3, A4, A5, A6, A7> mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2, A3, A4, A5, A6, A7) const)
+{
+ return _mfi::BOOST_MEM_FN_NAME(cmf7)<R, T, A1, A2, A3, A4, A5, A6, A7>(f);
+}
+
+template<class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> _mfi::BOOST_MEM_FN_NAME(mf8)<R, T, A1, A2, A3, A4, A5, A6, A7, A8> mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2, A3, A4, A5, A6, A7, A8))
+{
+ return _mfi::BOOST_MEM_FN_NAME(mf8)<R, T, A1, A2, A3, A4, A5, A6, A7, A8>(f);
+}
+
+template<class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> _mfi::BOOST_MEM_FN_NAME(cmf8)<R, T, A1, A2, A3, A4, A5, A6, A7, A8> mem_fn(R (BOOST_MEM_FN_CC T::*f) (A1, A2, A3, A4, A5, A6, A7, A8) const)
+{
+ return _mfi::BOOST_MEM_FN_NAME(cmf8)<R, T, A1, A2, A3, A4, A5, A6, A7, A8>(f);
+}
diff --git a/third_party/boost/boost/bind/mem_fn_template.hpp b/third_party/boost/boost/bind/mem_fn_template.hpp
new file mode 100644
index 0000000..ff65b4b
--- /dev/null
+++ b/third_party/boost/boost/bind/mem_fn_template.hpp
@@ -0,0 +1,1047 @@
+//
+// bind/mem_fn_template.hpp
+//
+// Do not include this header directly
+//
+// Copyright (c) 2001 Peter Dimov and Multi Media Ltd.
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/bind/mem_fn.html for documentation.
+//
+
+#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
+# define BOOST_MEM_FN_ENABLE_CONST_OVERLOADS
+#endif
+
+// mf0
+
+template<class R, class T BOOST_MEM_FN_CLASS_F> class BOOST_MEM_FN_NAME(mf0)
+{
+public:
+
+ typedef R result_type;
+ typedef T * argument_type;
+
+private:
+
+ BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) ())
+ F f_;
+
+ template<class U> R call(U & u, T const *) const
+ {
+ BOOST_MEM_FN_RETURN (u.*f_)();
+ }
+
+ template<class U> R call(U & u, void const *) const
+ {
+ BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)();
+ }
+
+public:
+
+ explicit BOOST_MEM_FN_NAME(mf0)(F f): f_(f) {}
+
+ R operator()(T * p) const
+ {
+ BOOST_MEM_FN_RETURN (p->*f_)();
+ }
+
+ template<class U> R operator()(U & u) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p);
+ }
+
+#ifdef BOOST_MEM_FN_ENABLE_CONST_OVERLOADS
+
+ template<class U> R operator()(U const & u) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p);
+ }
+
+#endif
+
+ R operator()(T & t) const
+ {
+ BOOST_MEM_FN_RETURN (t.*f_)();
+ }
+
+ bool operator==(BOOST_MEM_FN_NAME(mf0) const & rhs) const
+ {
+ return f_ == rhs.f_;
+ }
+
+ bool operator!=(BOOST_MEM_FN_NAME(mf0) const & rhs) const
+ {
+ return f_ != rhs.f_;
+ }
+};
+
+// cmf0
+
+template<class R, class T BOOST_MEM_FN_CLASS_F> class BOOST_MEM_FN_NAME(cmf0)
+{
+public:
+
+ typedef R result_type;
+ typedef T const * argument_type;
+
+private:
+
+ BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) () const)
+ F f_;
+
+ template<class U> R call(U & u, T const *) const
+ {
+ BOOST_MEM_FN_RETURN (u.*f_)();
+ }
+
+ template<class U> R call(U & u, void const *) const
+ {
+ BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)();
+ }
+
+public:
+
+ explicit BOOST_MEM_FN_NAME(cmf0)(F f): f_(f) {}
+
+ template<class U> R operator()(U const & u) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p);
+ }
+
+ R operator()(T const & t) const
+ {
+ BOOST_MEM_FN_RETURN (t.*f_)();
+ }
+
+ bool operator==(BOOST_MEM_FN_NAME(cmf0) const & rhs) const
+ {
+ return f_ == rhs.f_;
+ }
+
+ bool operator!=(BOOST_MEM_FN_NAME(cmf0) const & rhs) const
+ {
+ return f_ != rhs.f_;
+ }
+};
+
+// mf1
+
+template<class R, class T, class A1 BOOST_MEM_FN_CLASS_F> class BOOST_MEM_FN_NAME(mf1)
+{
+public:
+
+ typedef R result_type;
+ typedef T * first_argument_type;
+ typedef A1 second_argument_type;
+
+private:
+
+ BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1))
+ F f_;
+
+ template<class U, class B1> R call(U & u, T const *, B1 & b1) const
+ {
+ BOOST_MEM_FN_RETURN (u.*f_)(b1);
+ }
+
+ template<class U, class B1> R call(U & u, void const *, B1 & b1) const
+ {
+ BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1);
+ }
+
+public:
+
+ explicit BOOST_MEM_FN_NAME(mf1)(F f): f_(f) {}
+
+ R operator()(T * p, A1 a1) const
+ {
+ BOOST_MEM_FN_RETURN (p->*f_)(a1);
+ }
+
+ template<class U> R operator()(U & u, A1 a1) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p, a1);
+ }
+
+#ifdef BOOST_MEM_FN_ENABLE_CONST_OVERLOADS
+
+ template<class U> R operator()(U const & u, A1 a1) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p, a1);
+ }
+
+#endif
+
+ R operator()(T & t, A1 a1) const
+ {
+ BOOST_MEM_FN_RETURN (t.*f_)(a1);
+ }
+
+ bool operator==(BOOST_MEM_FN_NAME(mf1) const & rhs) const
+ {
+ return f_ == rhs.f_;
+ }
+
+ bool operator!=(BOOST_MEM_FN_NAME(mf1) const & rhs) const
+ {
+ return f_ != rhs.f_;
+ }
+};
+
+// cmf1
+
+template<class R, class T, class A1 BOOST_MEM_FN_CLASS_F> class BOOST_MEM_FN_NAME(cmf1)
+{
+public:
+
+ typedef R result_type;
+ typedef T const * first_argument_type;
+ typedef A1 second_argument_type;
+
+private:
+
+ BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1) const)
+ F f_;
+
+ template<class U, class B1> R call(U & u, T const *, B1 & b1) const
+ {
+ BOOST_MEM_FN_RETURN (u.*f_)(b1);
+ }
+
+ template<class U, class B1> R call(U & u, void const *, B1 & b1) const
+ {
+ BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1);
+ }
+
+public:
+
+ explicit BOOST_MEM_FN_NAME(cmf1)(F f): f_(f) {}
+
+ template<class U> R operator()(U const & u, A1 a1) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p, a1);
+ }
+
+ R operator()(T const & t, A1 a1) const
+ {
+ BOOST_MEM_FN_RETURN (t.*f_)(a1);
+ }
+
+ bool operator==(BOOST_MEM_FN_NAME(cmf1) const & rhs) const
+ {
+ return f_ == rhs.f_;
+ }
+
+ bool operator!=(BOOST_MEM_FN_NAME(cmf1) const & rhs) const
+ {
+ return f_ != rhs.f_;
+ }
+};
+
+// mf2
+
+template<class R, class T, class A1, class A2 BOOST_MEM_FN_CLASS_F> class BOOST_MEM_FN_NAME(mf2)
+{
+public:
+
+ typedef R result_type;
+
+private:
+
+ BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2))
+ F f_;
+
+ template<class U, class B1, class B2> R call(U & u, T const *, B1 & b1, B2 & b2) const
+ {
+ BOOST_MEM_FN_RETURN (u.*f_)(b1, b2);
+ }
+
+ template<class U, class B1, class B2> R call(U & u, void const *, B1 & b1, B2 & b2) const
+ {
+ BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2);
+ }
+
+public:
+
+ explicit BOOST_MEM_FN_NAME(mf2)(F f): f_(f) {}
+
+ R operator()(T * p, A1 a1, A2 a2) const
+ {
+ BOOST_MEM_FN_RETURN (p->*f_)(a1, a2);
+ }
+
+ template<class U> R operator()(U & u, A1 a1, A2 a2) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p, a1, a2);
+ }
+
+#ifdef BOOST_MEM_FN_ENABLE_CONST_OVERLOADS
+
+ template<class U> R operator()(U const & u, A1 a1, A2 a2) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p, a1, a2);
+ }
+
+#endif
+
+ R operator()(T & t, A1 a1, A2 a2) const
+ {
+ BOOST_MEM_FN_RETURN (t.*f_)(a1, a2);
+ }
+
+ bool operator==(BOOST_MEM_FN_NAME(mf2) const & rhs) const
+ {
+ return f_ == rhs.f_;
+ }
+
+ bool operator!=(BOOST_MEM_FN_NAME(mf2) const & rhs) const
+ {
+ return f_ != rhs.f_;
+ }
+};
+
+// cmf2
+
+template<class R, class T, class A1, class A2 BOOST_MEM_FN_CLASS_F> class BOOST_MEM_FN_NAME(cmf2)
+{
+public:
+
+ typedef R result_type;
+
+private:
+
+ BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2) const)
+ F f_;
+
+ template<class U, class B1, class B2> R call(U & u, T const *, B1 & b1, B2 & b2) const
+ {
+ BOOST_MEM_FN_RETURN (u.*f_)(b1, b2);
+ }
+
+ template<class U, class B1, class B2> R call(U & u, void const *, B1 & b1, B2 & b2) const
+ {
+ BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2);
+ }
+
+public:
+
+ explicit BOOST_MEM_FN_NAME(cmf2)(F f): f_(f) {}
+
+ template<class U> R operator()(U const & u, A1 a1, A2 a2) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p, a1, a2);
+ }
+
+ R operator()(T const & t, A1 a1, A2 a2) const
+ {
+ BOOST_MEM_FN_RETURN (t.*f_)(a1, a2);
+ }
+
+ bool operator==(BOOST_MEM_FN_NAME(cmf2) const & rhs) const
+ {
+ return f_ == rhs.f_;
+ }
+
+ bool operator!=(BOOST_MEM_FN_NAME(cmf2) const & rhs) const
+ {
+ return f_ != rhs.f_;
+ }
+};
+
+// mf3
+
+template<class R, class T, class A1, class A2, class A3 BOOST_MEM_FN_CLASS_F> class BOOST_MEM_FN_NAME(mf3)
+{
+public:
+
+ typedef R result_type;
+
+private:
+
+ BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3))
+ F f_;
+
+ template<class U, class B1, class B2, class B3> R call(U & u, T const *, B1 & b1, B2 & b2, B3 & b3) const
+ {
+ BOOST_MEM_FN_RETURN (u.*f_)(b1, b2, b3);
+ }
+
+ template<class U, class B1, class B2, class B3> R call(U & u, void const *, B1 & b1, B2 & b2, B3 & b3) const
+ {
+ BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2, b3);
+ }
+
+public:
+
+ explicit BOOST_MEM_FN_NAME(mf3)(F f): f_(f) {}
+
+ R operator()(T * p, A1 a1, A2 a2, A3 a3) const
+ {
+ BOOST_MEM_FN_RETURN (p->*f_)(a1, a2, a3);
+ }
+
+ template<class U> R operator()(U & u, A1 a1, A2 a2, A3 a3) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p, a1, a2, a3);
+ }
+
+#ifdef BOOST_MEM_FN_ENABLE_CONST_OVERLOADS
+
+ template<class U> R operator()(U const & u, A1 a1, A2 a2, A3 a3) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p, a1, a2, a3);
+ }
+
+#endif
+
+ R operator()(T & t, A1 a1, A2 a2, A3 a3) const
+ {
+ BOOST_MEM_FN_RETURN (t.*f_)(a1, a2, a3);
+ }
+
+ bool operator==(BOOST_MEM_FN_NAME(mf3) const & rhs) const
+ {
+ return f_ == rhs.f_;
+ }
+
+ bool operator!=(BOOST_MEM_FN_NAME(mf3) const & rhs) const
+ {
+ return f_ != rhs.f_;
+ }
+};
+
+// cmf3
+
+template<class R, class T, class A1, class A2, class A3 BOOST_MEM_FN_CLASS_F> class BOOST_MEM_FN_NAME(cmf3)
+{
+public:
+
+ typedef R result_type;
+
+private:
+
+ BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3) const)
+ F f_;
+
+ template<class U, class B1, class B2, class B3> R call(U & u, T const *, B1 & b1, B2 & b2, B3 & b3) const
+ {
+ BOOST_MEM_FN_RETURN (u.*f_)(b1, b2, b3);
+ }
+
+ template<class U, class B1, class B2, class B3> R call(U & u, void const *, B1 & b1, B2 & b2, B3 & b3) const
+ {
+ BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2, b3);
+ }
+
+public:
+
+ explicit BOOST_MEM_FN_NAME(cmf3)(F f): f_(f) {}
+
+ template<class U> R operator()(U const & u, A1 a1, A2 a2, A3 a3) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p, a1, a2, a3);
+ }
+
+ R operator()(T const & t, A1 a1, A2 a2, A3 a3) const
+ {
+ BOOST_MEM_FN_RETURN (t.*f_)(a1, a2, a3);
+ }
+
+ bool operator==(BOOST_MEM_FN_NAME(cmf3) const & rhs) const
+ {
+ return f_ == rhs.f_;
+ }
+
+ bool operator!=(BOOST_MEM_FN_NAME(cmf3) const & rhs) const
+ {
+ return f_ != rhs.f_;
+ }
+};
+
+// mf4
+
+template<class R, class T, class A1, class A2, class A3, class A4 BOOST_MEM_FN_CLASS_F> class BOOST_MEM_FN_NAME(mf4)
+{
+public:
+
+ typedef R result_type;
+
+private:
+
+ BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4))
+ F f_;
+
+ template<class U, class B1, class B2, class B3, class B4> R call(U & u, T const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4) const
+ {
+ BOOST_MEM_FN_RETURN (u.*f_)(b1, b2, b3, b4);
+ }
+
+ template<class U, class B1, class B2, class B3, class B4> R call(U & u, void const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4) const
+ {
+ BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2, b3, b4);
+ }
+
+public:
+
+ explicit BOOST_MEM_FN_NAME(mf4)(F f): f_(f) {}
+
+ R operator()(T * p, A1 a1, A2 a2, A3 a3, A4 a4) const
+ {
+ BOOST_MEM_FN_RETURN (p->*f_)(a1, a2, a3, a4);
+ }
+
+ template<class U> R operator()(U & u, A1 a1, A2 a2, A3 a3, A4 a4) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p, a1, a2, a3, a4);
+ }
+
+#ifdef BOOST_MEM_FN_ENABLE_CONST_OVERLOADS
+
+ template<class U> R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p, a1, a2, a3, a4);
+ }
+
+#endif
+
+ R operator()(T & t, A1 a1, A2 a2, A3 a3, A4 a4) const
+ {
+ BOOST_MEM_FN_RETURN (t.*f_)(a1, a2, a3, a4);
+ }
+
+ bool operator==(BOOST_MEM_FN_NAME(mf4) const & rhs) const
+ {
+ return f_ == rhs.f_;
+ }
+
+ bool operator!=(BOOST_MEM_FN_NAME(mf4) const & rhs) const
+ {
+ return f_ != rhs.f_;
+ }
+};
+
+// cmf4
+
+template<class R, class T, class A1, class A2, class A3, class A4 BOOST_MEM_FN_CLASS_F> class BOOST_MEM_FN_NAME(cmf4)
+{
+public:
+
+ typedef R result_type;
+
+private:
+
+ BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4) const)
+ F f_;
+
+ template<class U, class B1, class B2, class B3, class B4> R call(U & u, T const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4) const
+ {
+ BOOST_MEM_FN_RETURN (u.*f_)(b1, b2, b3, b4);
+ }
+
+ template<class U, class B1, class B2, class B3, class B4> R call(U & u, void const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4) const
+ {
+ BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2, b3, b4);
+ }
+
+public:
+
+ explicit BOOST_MEM_FN_NAME(cmf4)(F f): f_(f) {}
+
+ template<class U> R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p, a1, a2, a3, a4);
+ }
+
+ R operator()(T const & t, A1 a1, A2 a2, A3 a3, A4 a4) const
+ {
+ BOOST_MEM_FN_RETURN (t.*f_)(a1, a2, a3, a4);
+ }
+
+ bool operator==(BOOST_MEM_FN_NAME(cmf4) const & rhs) const
+ {
+ return f_ == rhs.f_;
+ }
+
+ bool operator!=(BOOST_MEM_FN_NAME(cmf4) const & rhs) const
+ {
+ return f_ != rhs.f_;
+ }
+};
+
+// mf5
+
+template<class R, class T, class A1, class A2, class A3, class A4, class A5 BOOST_MEM_FN_CLASS_F> class BOOST_MEM_FN_NAME(mf5)
+{
+public:
+
+ typedef R result_type;
+
+private:
+
+ BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4, A5))
+ F f_;
+
+ template<class U, class B1, class B2, class B3, class B4, class B5> R call(U & u, T const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5) const
+ {
+ BOOST_MEM_FN_RETURN (u.*f_)(b1, b2, b3, b4, b5);
+ }
+
+ template<class U, class B1, class B2, class B3, class B4, class B5> R call(U & u, void const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5) const
+ {
+ BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2, b3, b4, b5);
+ }
+
+public:
+
+ explicit BOOST_MEM_FN_NAME(mf5)(F f): f_(f) {}
+
+ R operator()(T * p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const
+ {
+ BOOST_MEM_FN_RETURN (p->*f_)(a1, a2, a3, a4, a5);
+ }
+
+ template<class U> R operator()(U & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p, a1, a2, a3, a4, a5);
+ }
+
+#ifdef BOOST_MEM_FN_ENABLE_CONST_OVERLOADS
+
+ template<class U> R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p, a1, a2, a3, a4, a5);
+ }
+
+#endif
+
+ R operator()(T & t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const
+ {
+ BOOST_MEM_FN_RETURN (t.*f_)(a1, a2, a3, a4, a5);
+ }
+
+ bool operator==(BOOST_MEM_FN_NAME(mf5) const & rhs) const
+ {
+ return f_ == rhs.f_;
+ }
+
+ bool operator!=(BOOST_MEM_FN_NAME(mf5) const & rhs) const
+ {
+ return f_ != rhs.f_;
+ }
+};
+
+// cmf5
+
+template<class R, class T, class A1, class A2, class A3, class A4, class A5 BOOST_MEM_FN_CLASS_F> class BOOST_MEM_FN_NAME(cmf5)
+{
+public:
+
+ typedef R result_type;
+
+private:
+
+ BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4, A5) const)
+ F f_;
+
+ template<class U, class B1, class B2, class B3, class B4, class B5> R call(U & u, T const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5) const
+ {
+ BOOST_MEM_FN_RETURN (u.*f_)(b1, b2, b3, b4, b5);
+ }
+
+ template<class U, class B1, class B2, class B3, class B4, class B5> R call(U & u, void const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5) const
+ {
+ BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2, b3, b4, b5);
+ }
+
+public:
+
+ explicit BOOST_MEM_FN_NAME(cmf5)(F f): f_(f) {}
+
+ template<class U> R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p, a1, a2, a3, a4, a5);
+ }
+
+ R operator()(T const & t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const
+ {
+ BOOST_MEM_FN_RETURN (t.*f_)(a1, a2, a3, a4, a5);
+ }
+
+ bool operator==(BOOST_MEM_FN_NAME(cmf5) const & rhs) const
+ {
+ return f_ == rhs.f_;
+ }
+
+ bool operator!=(BOOST_MEM_FN_NAME(cmf5) const & rhs) const
+ {
+ return f_ != rhs.f_;
+ }
+};
+
+// mf6
+
+template<class R, class T, class A1, class A2, class A3, class A4, class A5, class A6 BOOST_MEM_FN_CLASS_F> class BOOST_MEM_FN_NAME(mf6)
+{
+public:
+
+ typedef R result_type;
+
+private:
+
+ BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4, A5, A6))
+ F f_;
+
+ template<class U, class B1, class B2, class B3, class B4, class B5, class B6> R call(U & u, T const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5, B6 & b6) const
+ {
+ BOOST_MEM_FN_RETURN (u.*f_)(b1, b2, b3, b4, b5, b6);
+ }
+
+ template<class U, class B1, class B2, class B3, class B4, class B5, class B6> R call(U & u, void const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5, B6 & b6) const
+ {
+ BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2, b3, b4, b5, b6);
+ }
+
+public:
+
+ explicit BOOST_MEM_FN_NAME(mf6)(F f): f_(f) {}
+
+ R operator()(T * p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const
+ {
+ BOOST_MEM_FN_RETURN (p->*f_)(a1, a2, a3, a4, a5, a6);
+ }
+
+ template<class U> R operator()(U & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p, a1, a2, a3, a4, a5, a6);
+ }
+
+#ifdef BOOST_MEM_FN_ENABLE_CONST_OVERLOADS
+
+ template<class U> R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p, a1, a2, a3, a4, a5, a6);
+ }
+
+#endif
+
+ R operator()(T & t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const
+ {
+ BOOST_MEM_FN_RETURN (t.*f_)(a1, a2, a3, a4, a5, a6);
+ }
+
+ bool operator==(BOOST_MEM_FN_NAME(mf6) const & rhs) const
+ {
+ return f_ == rhs.f_;
+ }
+
+ bool operator!=(BOOST_MEM_FN_NAME(mf6) const & rhs) const
+ {
+ return f_ != rhs.f_;
+ }
+};
+
+// cmf6
+
+template<class R, class T, class A1, class A2, class A3, class A4, class A5, class A6 BOOST_MEM_FN_CLASS_F> class BOOST_MEM_FN_NAME(cmf6)
+{
+public:
+
+ typedef R result_type;
+
+private:
+
+ BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4, A5, A6) const)
+ F f_;
+
+ template<class U, class B1, class B2, class B3, class B4, class B5, class B6> R call(U & u, T const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5, B6 & b6) const
+ {
+ BOOST_MEM_FN_RETURN (u.*f_)(b1, b2, b3, b4, b5, b6);
+ }
+
+ template<class U, class B1, class B2, class B3, class B4, class B5, class B6> R call(U & u, void const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5, B6 & b6) const
+ {
+ BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2, b3, b4, b5, b6);
+ }
+
+public:
+
+ explicit BOOST_MEM_FN_NAME(cmf6)(F f): f_(f) {}
+
+ template<class U> R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p, a1, a2, a3, a4, a5, a6);
+ }
+
+ R operator()(T const & t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const
+ {
+ BOOST_MEM_FN_RETURN (t.*f_)(a1, a2, a3, a4, a5, a6);
+ }
+
+ bool operator==(BOOST_MEM_FN_NAME(cmf6) const & rhs) const
+ {
+ return f_ == rhs.f_;
+ }
+
+ bool operator!=(BOOST_MEM_FN_NAME(cmf6) const & rhs) const
+ {
+ return f_ != rhs.f_;
+ }
+};
+
+// mf7
+
+template<class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 BOOST_MEM_FN_CLASS_F> class BOOST_MEM_FN_NAME(mf7)
+{
+public:
+
+ typedef R result_type;
+
+private:
+
+ BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4, A5, A6, A7))
+ F f_;
+
+ template<class U, class B1, class B2, class B3, class B4, class B5, class B6, class B7> R call(U & u, T const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5, B6 & b6, B7 & b7) const
+ {
+ BOOST_MEM_FN_RETURN (u.*f_)(b1, b2, b3, b4, b5, b6, b7);
+ }
+
+ template<class U, class B1, class B2, class B3, class B4, class B5, class B6, class B7> R call(U & u, void const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5, B6 & b6, B7 & b7) const
+ {
+ BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2, b3, b4, b5, b6, b7);
+ }
+
+public:
+
+ explicit BOOST_MEM_FN_NAME(mf7)(F f): f_(f) {}
+
+ R operator()(T * p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) const
+ {
+ BOOST_MEM_FN_RETURN (p->*f_)(a1, a2, a3, a4, a5, a6, a7);
+ }
+
+ template<class U> R operator()(U & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p, a1, a2, a3, a4, a5, a6, a7);
+ }
+
+#ifdef BOOST_MEM_FN_ENABLE_CONST_OVERLOADS
+
+ template<class U> R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p, a1, a2, a3, a4, a5, a6, a7);
+ }
+
+#endif
+
+ R operator()(T & t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) const
+ {
+ BOOST_MEM_FN_RETURN (t.*f_)(a1, a2, a3, a4, a5, a6, a7);
+ }
+
+ bool operator==(BOOST_MEM_FN_NAME(mf7) const & rhs) const
+ {
+ return f_ == rhs.f_;
+ }
+
+ bool operator!=(BOOST_MEM_FN_NAME(mf7) const & rhs) const
+ {
+ return f_ != rhs.f_;
+ }
+};
+
+// cmf7
+
+template<class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 BOOST_MEM_FN_CLASS_F> class BOOST_MEM_FN_NAME(cmf7)
+{
+public:
+
+ typedef R result_type;
+
+private:
+
+ BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4, A5, A6, A7) const)
+ F f_;
+
+ template<class U, class B1, class B2, class B3, class B4, class B5, class B6, class B7> R call(U & u, T const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5, B6 & b6, B7 & b7) const
+ {
+ BOOST_MEM_FN_RETURN (u.*f_)(b1, b2, b3, b4, b5, b6, b7);
+ }
+
+ template<class U, class B1, class B2, class B3, class B4, class B5, class B6, class B7> R call(U & u, void const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5, B6 & b6, B7 & b7) const
+ {
+ BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2, b3, b4, b5, b6, b7);
+ }
+
+public:
+
+ explicit BOOST_MEM_FN_NAME(cmf7)(F f): f_(f) {}
+
+ template<class U> R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p, a1, a2, a3, a4, a5, a6, a7);
+ }
+
+ R operator()(T const & t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) const
+ {
+ BOOST_MEM_FN_RETURN (t.*f_)(a1, a2, a3, a4, a5, a6, a7);
+ }
+
+ bool operator==(BOOST_MEM_FN_NAME(cmf7) const & rhs) const
+ {
+ return f_ == rhs.f_;
+ }
+
+ bool operator!=(BOOST_MEM_FN_NAME(cmf7) const & rhs) const
+ {
+ return f_ != rhs.f_;
+ }
+};
+
+// mf8
+
+template<class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 BOOST_MEM_FN_CLASS_F> class BOOST_MEM_FN_NAME(mf8)
+{
+public:
+
+ typedef R result_type;
+
+private:
+
+ BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4, A5, A6, A7, A8))
+ F f_;
+
+ template<class U, class B1, class B2, class B3, class B4, class B5, class B6, class B7, class B8> R call(U & u, T const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5, B6 & b6, B7 & b7, B8 & b8) const
+ {
+ BOOST_MEM_FN_RETURN (u.*f_)(b1, b2, b3, b4, b5, b6, b7, b8);
+ }
+
+ template<class U, class B1, class B2, class B3, class B4, class B5, class B6, class B7, class B8> R call(U & u, void const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5, B6 & b6, B7 & b7, B8 & b8) const
+ {
+ BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2, b3, b4, b5, b6, b7, b8);
+ }
+
+public:
+
+ explicit BOOST_MEM_FN_NAME(mf8)(F f): f_(f) {}
+
+ R operator()(T * p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const
+ {
+ BOOST_MEM_FN_RETURN (p->*f_)(a1, a2, a3, a4, a5, a6, a7, a8);
+ }
+
+ template<class U> R operator()(U & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p, a1, a2, a3, a4, a5, a6, a7, a8);
+ }
+
+#ifdef BOOST_MEM_FN_ENABLE_CONST_OVERLOADS
+
+ template<class U> R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p, a1, a2, a3, a4, a5, a6, a7, a8);
+ }
+
+#endif
+
+ R operator()(T & t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const
+ {
+ BOOST_MEM_FN_RETURN (t.*f_)(a1, a2, a3, a4, a5, a6, a7, a8);
+ }
+
+ bool operator==(BOOST_MEM_FN_NAME(mf8) const & rhs) const
+ {
+ return f_ == rhs.f_;
+ }
+
+ bool operator!=(BOOST_MEM_FN_NAME(mf8) const & rhs) const
+ {
+ return f_ != rhs.f_;
+ }
+};
+
+// cmf8
+
+template<class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 BOOST_MEM_FN_CLASS_F> class BOOST_MEM_FN_NAME(cmf8)
+{
+public:
+
+ typedef R result_type;
+
+private:
+
+ BOOST_MEM_FN_TYPEDEF(R (BOOST_MEM_FN_CC T::*F) (A1, A2, A3, A4, A5, A6, A7, A8) const)
+ F f_;
+
+ template<class U, class B1, class B2, class B3, class B4, class B5, class B6, class B7, class B8> R call(U & u, T const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5, B6 & b6, B7 & b7, B8 & b8) const
+ {
+ BOOST_MEM_FN_RETURN (u.*f_)(b1, b2, b3, b4, b5, b6, b7, b8);
+ }
+
+ template<class U, class B1, class B2, class B3, class B4, class B5, class B6, class B7, class B8> R call(U & u, void const *, B1 & b1, B2 & b2, B3 & b3, B4 & b4, B5 & b5, B6 & b6, B7 & b7, B8 & b8) const
+ {
+ BOOST_MEM_FN_RETURN (get_pointer(u)->*f_)(b1, b2, b3, b4, b5, b6, b7, b8);
+ }
+
+public:
+
+ explicit BOOST_MEM_FN_NAME(cmf8)(F f): f_(f) {}
+
+ R operator()(T const * p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const
+ {
+ BOOST_MEM_FN_RETURN (p->*f_)(a1, a2, a3, a4, a5, a6, a7, a8);
+ }
+
+ template<class U> R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const
+ {
+ U const * p = 0;
+ BOOST_MEM_FN_RETURN call(u, p, a1, a2, a3, a4, a5, a6, a7, a8);
+ }
+
+ R operator()(T const & t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const
+ {
+ BOOST_MEM_FN_RETURN (t.*f_)(a1, a2, a3, a4, a5, a6, a7, a8);
+ }
+
+ bool operator==(BOOST_MEM_FN_NAME(cmf8) const & rhs) const
+ {
+ return f_ == rhs.f_;
+ }
+
+ bool operator!=(BOOST_MEM_FN_NAME(cmf8) const & rhs) const
+ {
+ return f_ != rhs.f_;
+ }
+};
+
+#undef BOOST_MEM_FN_ENABLE_CONST_OVERLOADS
diff --git a/third_party/boost/boost/bind/placeholders.hpp b/third_party/boost/boost/bind/placeholders.hpp
new file mode 100644
index 0000000..b819ef4
--- /dev/null
+++ b/third_party/boost/boost/bind/placeholders.hpp
@@ -0,0 +1,62 @@
+#ifndef BOOST_BIND_PLACEHOLDERS_HPP_INCLUDED
+#define BOOST_BIND_PLACEHOLDERS_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// bind/placeholders.hpp - _N definitions
+//
+// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
+// Copyright 2015 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+// See http://www.boost.org/libs/bind/bind.html for documentation.
+//
+
+#include <boost/bind/arg.hpp>
+#include <boost/config.hpp>
+
+namespace boost
+{
+
+namespace placeholders
+{
+
+#if defined(__BORLANDC__) || defined(__GNUC__) && (__GNUC__ < 4)
+
+inline boost::arg<1> _1() { return boost::arg<1>(); }
+inline boost::arg<2> _2() { return boost::arg<2>(); }
+inline boost::arg<3> _3() { return boost::arg<3>(); }
+inline boost::arg<4> _4() { return boost::arg<4>(); }
+inline boost::arg<5> _5() { return boost::arg<5>(); }
+inline boost::arg<6> _6() { return boost::arg<6>(); }
+inline boost::arg<7> _7() { return boost::arg<7>(); }
+inline boost::arg<8> _8() { return boost::arg<8>(); }
+inline boost::arg<9> _9() { return boost::arg<9>(); }
+
+#else
+
+BOOST_STATIC_CONSTEXPR boost::arg<1> _1;
+BOOST_STATIC_CONSTEXPR boost::arg<2> _2;
+BOOST_STATIC_CONSTEXPR boost::arg<3> _3;
+BOOST_STATIC_CONSTEXPR boost::arg<4> _4;
+BOOST_STATIC_CONSTEXPR boost::arg<5> _5;
+BOOST_STATIC_CONSTEXPR boost::arg<6> _6;
+BOOST_STATIC_CONSTEXPR boost::arg<7> _7;
+BOOST_STATIC_CONSTEXPR boost::arg<8> _8;
+BOOST_STATIC_CONSTEXPR boost::arg<9> _9;
+
+#endif
+
+} // namespace placeholders
+
+} // namespace boost
+
+#endif // #ifndef BOOST_BIND_PLACEHOLDERS_HPP_INCLUDED
diff --git a/third_party/boost/boost/bind/storage.hpp b/third_party/boost/boost/bind/storage.hpp
new file mode 100644
index 0000000..be490b0
--- /dev/null
+++ b/third_party/boost/boost/bind/storage.hpp
@@ -0,0 +1,475 @@
+#ifndef BOOST_BIND_STORAGE_HPP_INCLUDED
+#define BOOST_BIND_STORAGE_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// bind/storage.hpp
+//
+// boost/bind.hpp support header, optimized storage
+//
+// Copyright (c) 2006 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+// See http://www.boost.org/libs/bind/bind.html for documentation.
+//
+
+#include <boost/config.hpp>
+#include <boost/bind/arg.hpp>
+
+#ifdef BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable: 4512) // assignment operator could not be generated
+#endif
+
+namespace boost
+{
+
+namespace _bi
+{
+
+// 1
+
+template<class A1> struct storage1
+{
+ explicit storage1( A1 a1 ): a1_( a1 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ BOOST_BIND_VISIT_EACH(v, a1_, 0);
+ }
+
+ A1 a1_;
+};
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( __BORLANDC__ )
+
+template<int I> struct storage1< boost::arg<I> >
+{
+ explicit storage1( boost::arg<I> ) {}
+
+ template<class V> void accept(V &) const { }
+
+ static boost::arg<I> a1_() { return boost::arg<I>(); }
+};
+
+template<int I> struct storage1< boost::arg<I> (*) () >
+{
+ explicit storage1( boost::arg<I> (*) () ) {}
+
+ template<class V> void accept(V &) const { }
+
+ static boost::arg<I> a1_() { return boost::arg<I>(); }
+};
+
+#endif
+
+// 2
+
+template<class A1, class A2> struct storage2: public storage1<A1>
+{
+ typedef storage1<A1> inherited;
+
+ storage2( A1 a1, A2 a2 ): storage1<A1>( a1 ), a2_( a2 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ inherited::accept(v);
+ BOOST_BIND_VISIT_EACH(v, a2_, 0);
+ }
+
+ A2 a2_;
+};
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template<class A1, int I> struct storage2< A1, boost::arg<I> >: public storage1<A1>
+{
+ typedef storage1<A1> inherited;
+
+ storage2( A1 a1, boost::arg<I> ): storage1<A1>( a1 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ inherited::accept(v);
+ }
+
+ static boost::arg<I> a2_() { return boost::arg<I>(); }
+};
+
+template<class A1, int I> struct storage2< A1, boost::arg<I> (*) () >: public storage1<A1>
+{
+ typedef storage1<A1> inherited;
+
+ storage2( A1 a1, boost::arg<I> (*) () ): storage1<A1>( a1 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ inherited::accept(v);
+ }
+
+ static boost::arg<I> a2_() { return boost::arg<I>(); }
+};
+
+#endif
+
+// 3
+
+template<class A1, class A2, class A3> struct storage3: public storage2< A1, A2 >
+{
+ typedef storage2<A1, A2> inherited;
+
+ storage3( A1 a1, A2 a2, A3 a3 ): storage2<A1, A2>( a1, a2 ), a3_( a3 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ inherited::accept(v);
+ BOOST_BIND_VISIT_EACH(v, a3_, 0);
+ }
+
+ A3 a3_;
+};
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template<class A1, class A2, int I> struct storage3< A1, A2, boost::arg<I> >: public storage2< A1, A2 >
+{
+ typedef storage2<A1, A2> inherited;
+
+ storage3( A1 a1, A2 a2, boost::arg<I> ): storage2<A1, A2>( a1, a2 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ inherited::accept(v);
+ }
+
+ static boost::arg<I> a3_() { return boost::arg<I>(); }
+};
+
+template<class A1, class A2, int I> struct storage3< A1, A2, boost::arg<I> (*) () >: public storage2< A1, A2 >
+{
+ typedef storage2<A1, A2> inherited;
+
+ storage3( A1 a1, A2 a2, boost::arg<I> (*) () ): storage2<A1, A2>( a1, a2 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ inherited::accept(v);
+ }
+
+ static boost::arg<I> a3_() { return boost::arg<I>(); }
+};
+
+#endif
+
+// 4
+
+template<class A1, class A2, class A3, class A4> struct storage4: public storage3< A1, A2, A3 >
+{
+ typedef storage3<A1, A2, A3> inherited;
+
+ storage4( A1 a1, A2 a2, A3 a3, A4 a4 ): storage3<A1, A2, A3>( a1, a2, a3 ), a4_( a4 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ inherited::accept(v);
+ BOOST_BIND_VISIT_EACH(v, a4_, 0);
+ }
+
+ A4 a4_;
+};
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template<class A1, class A2, class A3, int I> struct storage4< A1, A2, A3, boost::arg<I> >: public storage3< A1, A2, A3 >
+{
+ typedef storage3<A1, A2, A3> inherited;
+
+ storage4( A1 a1, A2 a2, A3 a3, boost::arg<I> ): storage3<A1, A2, A3>( a1, a2, a3 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ inherited::accept(v);
+ }
+
+ static boost::arg<I> a4_() { return boost::arg<I>(); }
+};
+
+template<class A1, class A2, class A3, int I> struct storage4< A1, A2, A3, boost::arg<I> (*) () >: public storage3< A1, A2, A3 >
+{
+ typedef storage3<A1, A2, A3> inherited;
+
+ storage4( A1 a1, A2 a2, A3 a3, boost::arg<I> (*) () ): storage3<A1, A2, A3>( a1, a2, a3 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ inherited::accept(v);
+ }
+
+ static boost::arg<I> a4_() { return boost::arg<I>(); }
+};
+
+#endif
+
+// 5
+
+template<class A1, class A2, class A3, class A4, class A5> struct storage5: public storage4< A1, A2, A3, A4 >
+{
+ typedef storage4<A1, A2, A3, A4> inherited;
+
+ storage5( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5 ): storage4<A1, A2, A3, A4>( a1, a2, a3, a4 ), a5_( a5 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ inherited::accept(v);
+ BOOST_BIND_VISIT_EACH(v, a5_, 0);
+ }
+
+ A5 a5_;
+};
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template<class A1, class A2, class A3, class A4, int I> struct storage5< A1, A2, A3, A4, boost::arg<I> >: public storage4< A1, A2, A3, A4 >
+{
+ typedef storage4<A1, A2, A3, A4> inherited;
+
+ storage5( A1 a1, A2 a2, A3 a3, A4 a4, boost::arg<I> ): storage4<A1, A2, A3, A4>( a1, a2, a3, a4 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ inherited::accept(v);
+ }
+
+ static boost::arg<I> a5_() { return boost::arg<I>(); }
+};
+
+template<class A1, class A2, class A3, class A4, int I> struct storage5< A1, A2, A3, A4, boost::arg<I> (*) () >: public storage4< A1, A2, A3, A4 >
+{
+ typedef storage4<A1, A2, A3, A4> inherited;
+
+ storage5( A1 a1, A2 a2, A3 a3, A4 a4, boost::arg<I> (*) () ): storage4<A1, A2, A3, A4>( a1, a2, a3, a4 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ inherited::accept(v);
+ }
+
+ static boost::arg<I> a5_() { return boost::arg<I>(); }
+};
+
+#endif
+
+// 6
+
+template<class A1, class A2, class A3, class A4, class A5, class A6> struct storage6: public storage5< A1, A2, A3, A4, A5 >
+{
+ typedef storage5<A1, A2, A3, A4, A5> inherited;
+
+ storage6( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6 ): storage5<A1, A2, A3, A4, A5>( a1, a2, a3, a4, a5 ), a6_( a6 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ inherited::accept(v);
+ BOOST_BIND_VISIT_EACH(v, a6_, 0);
+ }
+
+ A6 a6_;
+};
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template<class A1, class A2, class A3, class A4, class A5, int I> struct storage6< A1, A2, A3, A4, A5, boost::arg<I> >: public storage5< A1, A2, A3, A4, A5 >
+{
+ typedef storage5<A1, A2, A3, A4, A5> inherited;
+
+ storage6( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, boost::arg<I> ): storage5<A1, A2, A3, A4, A5>( a1, a2, a3, a4, a5 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ inherited::accept(v);
+ }
+
+ static boost::arg<I> a6_() { return boost::arg<I>(); }
+};
+
+template<class A1, class A2, class A3, class A4, class A5, int I> struct storage6< A1, A2, A3, A4, A5, boost::arg<I> (*) () >: public storage5< A1, A2, A3, A4, A5 >
+{
+ typedef storage5<A1, A2, A3, A4, A5> inherited;
+
+ storage6( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, boost::arg<I> (*) () ): storage5<A1, A2, A3, A4, A5>( a1, a2, a3, a4, a5 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ inherited::accept(v);
+ }
+
+ static boost::arg<I> a6_() { return boost::arg<I>(); }
+};
+
+#endif
+
+// 7
+
+template<class A1, class A2, class A3, class A4, class A5, class A6, class A7> struct storage7: public storage6< A1, A2, A3, A4, A5, A6 >
+{
+ typedef storage6<A1, A2, A3, A4, A5, A6> inherited;
+
+ storage7( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7 ): storage6<A1, A2, A3, A4, A5, A6>( a1, a2, a3, a4, a5, a6 ), a7_( a7 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ inherited::accept(v);
+ BOOST_BIND_VISIT_EACH(v, a7_, 0);
+ }
+
+ A7 a7_;
+};
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template<class A1, class A2, class A3, class A4, class A5, class A6, int I> struct storage7< A1, A2, A3, A4, A5, A6, boost::arg<I> >: public storage6< A1, A2, A3, A4, A5, A6 >
+{
+ typedef storage6<A1, A2, A3, A4, A5, A6> inherited;
+
+ storage7( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, boost::arg<I> ): storage6<A1, A2, A3, A4, A5, A6>( a1, a2, a3, a4, a5, a6 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ inherited::accept(v);
+ }
+
+ static boost::arg<I> a7_() { return boost::arg<I>(); }
+};
+
+template<class A1, class A2, class A3, class A4, class A5, class A6, int I> struct storage7< A1, A2, A3, A4, A5, A6, boost::arg<I> (*) () >: public storage6< A1, A2, A3, A4, A5, A6 >
+{
+ typedef storage6<A1, A2, A3, A4, A5, A6> inherited;
+
+ storage7( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, boost::arg<I> (*) () ): storage6<A1, A2, A3, A4, A5, A6>( a1, a2, a3, a4, a5, a6 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ inherited::accept(v);
+ }
+
+ static boost::arg<I> a7_() { return boost::arg<I>(); }
+};
+
+#endif
+
+// 8
+
+template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> struct storage8: public storage7< A1, A2, A3, A4, A5, A6, A7 >
+{
+ typedef storage7<A1, A2, A3, A4, A5, A6, A7> inherited;
+
+ storage8( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8 ): storage7<A1, A2, A3, A4, A5, A6, A7>( a1, a2, a3, a4, a5, a6, a7 ), a8_( a8 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ inherited::accept(v);
+ BOOST_BIND_VISIT_EACH(v, a8_, 0);
+ }
+
+ A8 a8_;
+};
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, int I> struct storage8< A1, A2, A3, A4, A5, A6, A7, boost::arg<I> >: public storage7< A1, A2, A3, A4, A5, A6, A7 >
+{
+ typedef storage7<A1, A2, A3, A4, A5, A6, A7> inherited;
+
+ storage8( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, boost::arg<I> ): storage7<A1, A2, A3, A4, A5, A6, A7>( a1, a2, a3, a4, a5, a6, a7 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ inherited::accept(v);
+ }
+
+ static boost::arg<I> a8_() { return boost::arg<I>(); }
+};
+
+template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, int I> struct storage8< A1, A2, A3, A4, A5, A6, A7, boost::arg<I> (*) () >: public storage7< A1, A2, A3, A4, A5, A6, A7 >
+{
+ typedef storage7<A1, A2, A3, A4, A5, A6, A7> inherited;
+
+ storage8( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, boost::arg<I> (*) () ): storage7<A1, A2, A3, A4, A5, A6, A7>( a1, a2, a3, a4, a5, a6, a7 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ inherited::accept(v);
+ }
+
+ static boost::arg<I> a8_() { return boost::arg<I>(); }
+};
+
+#endif
+
+// 9
+
+template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> struct storage9: public storage8< A1, A2, A3, A4, A5, A6, A7, A8 >
+{
+ typedef storage8<A1, A2, A3, A4, A5, A6, A7, A8> inherited;
+
+ storage9( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9 ): storage8<A1, A2, A3, A4, A5, A6, A7, A8>( a1, a2, a3, a4, a5, a6, a7, a8 ), a9_( a9 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ inherited::accept(v);
+ BOOST_BIND_VISIT_EACH(v, a9_, 0);
+ }
+
+ A9 a9_;
+};
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, int I> struct storage9< A1, A2, A3, A4, A5, A6, A7, A8, boost::arg<I> >: public storage8< A1, A2, A3, A4, A5, A6, A7, A8 >
+{
+ typedef storage8<A1, A2, A3, A4, A5, A6, A7, A8> inherited;
+
+ storage9( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, boost::arg<I> ): storage8<A1, A2, A3, A4, A5, A6, A7, A8>( a1, a2, a3, a4, a5, a6, a7, a8 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ inherited::accept(v);
+ }
+
+ static boost::arg<I> a9_() { return boost::arg<I>(); }
+};
+
+template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, int I> struct storage9< A1, A2, A3, A4, A5, A6, A7, A8, boost::arg<I> (*) () >: public storage8< A1, A2, A3, A4, A5, A6, A7, A8 >
+{
+ typedef storage8<A1, A2, A3, A4, A5, A6, A7, A8> inherited;
+
+ storage9( A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, boost::arg<I> (*) () ): storage8<A1, A2, A3, A4, A5, A6, A7, A8>( a1, a2, a3, a4, a5, a6, a7, a8 ) {}
+
+ template<class V> void accept(V & v) const
+ {
+ inherited::accept(v);
+ }
+
+ static boost::arg<I> a9_() { return boost::arg<I>(); }
+};
+
+#endif
+
+} // namespace _bi
+
+} // namespace boost
+
+#ifdef BOOST_MSVC
+# pragma warning(default: 4512) // assignment operator could not be generated
+# pragma warning(pop)
+#endif
+
+#endif // #ifndef BOOST_BIND_STORAGE_HPP_INCLUDED
diff --git a/third_party/boost/boost/blank.hpp b/third_party/boost/boost/blank.hpp
new file mode 100644
index 0000000..d0fe5ab
--- /dev/null
+++ b/third_party/boost/boost/blank.hpp
@@ -0,0 +1,106 @@
+//-----------------------------------------------------------------------------
+// boost blank.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2003
+// Eric Friedman
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_BLANK_HPP
+#define BOOST_BLANK_HPP
+
+#include "boost/blank_fwd.hpp"
+
+#if !defined(BOOST_NO_IOSTREAM)
+#include <iosfwd> // for std::basic_ostream forward declare
+#include "boost/detail/templated_streams.hpp"
+#endif // BOOST_NO_IOSTREAM
+
+#include "boost/mpl/bool.hpp"
+#include "boost/type_traits/is_empty.hpp"
+#include "boost/type_traits/is_pod.hpp"
+#include "boost/type_traits/is_stateless.hpp"
+
+namespace boost {
+
+struct blank
+{
+};
+
+// type traits specializations
+//
+
+template <>
+struct is_pod< blank >
+ : mpl::true_
+{
+};
+
+template <>
+struct is_empty< blank >
+ : mpl::true_
+{
+};
+
+template <>
+struct is_stateless< blank >
+ : mpl::true_
+{
+};
+
+// relational operators
+//
+
+inline bool operator==(const blank&, const blank&)
+{
+ return true;
+}
+
+inline bool operator<=(const blank&, const blank&)
+{
+ return true;
+}
+
+inline bool operator>=(const blank&, const blank&)
+{
+ return true;
+}
+
+inline bool operator!=(const blank&, const blank&)
+{
+ return false;
+}
+
+inline bool operator<(const blank&, const blank&)
+{
+ return false;
+}
+
+inline bool operator>(const blank&, const blank&)
+{
+ return false;
+}
+
+// streaming support
+//
+#if !defined(BOOST_NO_IOSTREAM)
+
+BOOST_TEMPLATED_STREAM_TEMPLATE(E,T)
+inline BOOST_TEMPLATED_STREAM(ostream, E,T)& operator<<(
+ BOOST_TEMPLATED_STREAM(ostream, E,T)& out
+ , const blank&
+ )
+{
+ // (output nothing)
+ return out;
+}
+
+#endif // BOOST_NO_IOSTREAM
+
+} // namespace boost
+
+#endif // BOOST_BLANK_HPP
diff --git a/third_party/boost/boost/blank_fwd.hpp b/third_party/boost/boost/blank_fwd.hpp
new file mode 100644
index 0000000..8bfe97c
--- /dev/null
+++ b/third_party/boost/boost/blank_fwd.hpp
@@ -0,0 +1,22 @@
+//-----------------------------------------------------------------------------
+// boost blank_fwd.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2003
+// Eric Friedman
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_BLANK_FWD_HPP
+#define BOOST_BLANK_FWD_HPP
+
+namespace boost {
+
+struct blank;
+
+} // namespace boost
+
+#endif // BOOST_BLANK_FWD_HPP
diff --git a/third_party/boost/boost/call_traits.hpp b/third_party/boost/boost/call_traits.hpp
new file mode 100644
index 0000000..2c1328e
--- /dev/null
+++ b/third_party/boost/boost/call_traits.hpp
@@ -0,0 +1,20 @@
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/utility for most recent version including documentation.
+
+// See boost/detail/call_traits.hpp
+// for full copyright notices.
+
+#ifndef BOOST_CALL_TRAITS_HPP
+#define BOOST_CALL_TRAITS_HPP
+
+#ifndef BOOST_CONFIG_HPP
+#include <boost/config.hpp>
+#endif
+
+#include <boost/detail/call_traits.hpp>
+
+#endif // BOOST_CALL_TRAITS_HPP
diff --git a/third_party/boost/boost/checked_delete.hpp b/third_party/boost/boost/checked_delete.hpp
new file mode 100644
index 0000000..fb71c78
--- /dev/null
+++ b/third_party/boost/boost/checked_delete.hpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2014 Glen Fernandes
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_CHECKED_DELETE_HPP
+#define BOOST_CHECKED_DELETE_HPP
+
+// The header file at this path is deprecated;
+// use boost/core/checked_delete.hpp instead.
+
+#include <boost/core/checked_delete.hpp>
+
+#endif
diff --git a/third_party/boost/boost/config.hpp b/third_party/boost/boost/config.hpp
new file mode 100644
index 0000000..a73f7e1
--- /dev/null
+++ b/third_party/boost/boost/config.hpp
@@ -0,0 +1,67 @@
+// Boost config.hpp configuration header file ------------------------------//
+
+// (C) Copyright John Maddock 2002.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/config for most recent version.
+
+// Boost config.hpp policy and rationale documentation has been moved to
+// http://www.boost.org/libs/config
+//
+// CAUTION: This file is intended to be completely stable -
+// DO NOT MODIFY THIS FILE!
+//
+
+#ifndef BOOST_CONFIG_HPP
+#define BOOST_CONFIG_HPP
+
+// if we don't have a user config, then use the default location:
+#if !defined(BOOST_USER_CONFIG) && !defined(BOOST_NO_USER_CONFIG)
+# define BOOST_USER_CONFIG <boost/config/user.hpp>
+#if 0
+// For dependency trackers:
+# include <boost/config/user.hpp>
+#endif
+#endif
+// include it first:
+#ifdef BOOST_USER_CONFIG
+# include BOOST_USER_CONFIG
+#endif
+
+// if we don't have a compiler config set, try and find one:
+#if !defined(BOOST_COMPILER_CONFIG) && !defined(BOOST_NO_COMPILER_CONFIG) && !defined(BOOST_NO_CONFIG)
+# include <boost/config/select_compiler_config.hpp>
+#endif
+// if we have a compiler config, include it now:
+#ifdef BOOST_COMPILER_CONFIG
+# include BOOST_COMPILER_CONFIG
+#endif
+
+// if we don't have a std library config set, try and find one:
+#if !defined(BOOST_STDLIB_CONFIG) && !defined(BOOST_NO_STDLIB_CONFIG) && !defined(BOOST_NO_CONFIG) && defined(__cplusplus)
+# include <boost/config/select_stdlib_config.hpp>
+#endif
+// if we have a std library config, include it now:
+#ifdef BOOST_STDLIB_CONFIG
+# include BOOST_STDLIB_CONFIG
+#endif
+
+// if we don't have a platform config set, try and find one:
+#if !defined(BOOST_PLATFORM_CONFIG) && !defined(BOOST_NO_PLATFORM_CONFIG) && !defined(BOOST_NO_CONFIG)
+# include <boost/config/select_platform_config.hpp>
+#endif
+// if we have a platform config, include it now:
+#ifdef BOOST_PLATFORM_CONFIG
+# include BOOST_PLATFORM_CONFIG
+#endif
+
+// get config suffix code:
+#include <boost/config/suffix.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#endif // BOOST_CONFIG_HPP
diff --git a/third_party/boost/boost/config/compiler/clang.hpp b/third_party/boost/boost/config/compiler/clang.hpp
new file mode 100644
index 0000000..329a196
--- /dev/null
+++ b/third_party/boost/boost/config/compiler/clang.hpp
@@ -0,0 +1,278 @@
+// (C) Copyright Douglas Gregor 2010
+//
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for most recent version.
+
+// Clang compiler setup.
+
+#define BOOST_HAS_PRAGMA_ONCE
+
+// Detecting `-fms-extension` compiler flag assuming that _MSC_VER defined when that flag is used.
+#if defined (_MSC_VER) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 4))
+# define BOOST_HAS_PRAGMA_DETECT_MISMATCH
+#endif
+
+// When compiling with clang before __has_extension was defined,
+// even if one writes 'defined(__has_extension) && __has_extension(xxx)',
+// clang reports a compiler error. So the only workaround found is:
+
+#ifndef __has_extension
+#define __has_extension __has_feature
+#endif
+
+#ifndef __has_attribute
+#define __has_attribute(x) 0
+#endif
+
+#if !__has_feature(cxx_exceptions) && !defined(BOOST_NO_EXCEPTIONS)
+# define BOOST_NO_EXCEPTIONS
+#endif
+
+#if !__has_feature(cxx_rtti) && !defined(BOOST_NO_RTTI)
+# define BOOST_NO_RTTI
+#endif
+
+#if !__has_feature(cxx_rtti) && !defined(BOOST_NO_TYPEID)
+# define BOOST_NO_TYPEID
+#endif
+
+#if defined(__int64) && !defined(__GNUC__)
+# define BOOST_HAS_MS_INT64
+#endif
+
+#define BOOST_HAS_NRVO
+
+// Branch prediction hints
+#if defined(__has_builtin)
+#if __has_builtin(__builtin_expect)
+#define BOOST_LIKELY(x) __builtin_expect(x, 1)
+#define BOOST_UNLIKELY(x) __builtin_expect(x, 0)
+#endif
+#endif
+
+// Clang supports "long long" in all compilation modes.
+#define BOOST_HAS_LONG_LONG
+
+//
+// We disable this if the compiler is really nvcc as it
+// doesn't actually support __int128 as of CUDA_VERSION=5000
+// even though it defines __SIZEOF_INT128__.
+// See https://svn.boost.org/trac/boost/ticket/10418
+// Only re-enable this for nvcc if you're absolutely sure
+// of the circumstances under which it's supported.
+// Similarly __SIZEOF_INT128__ is defined when targetting msvc
+// compatibility even though the required support functions are absent.
+//
+#if defined(__SIZEOF_INT128__) && !defined(__CUDACC__) && !defined(_MSC_VER)
+# define BOOST_HAS_INT128
+#endif
+
+
+//
+// Dynamic shared object (DSO) and dynamic-link library (DLL) support
+//
+#if !defined(_WIN32) && !defined(__WIN32__) && !defined(WIN32)
+# define BOOST_SYMBOL_EXPORT __attribute__((__visibility__("default")))
+# define BOOST_SYMBOL_IMPORT
+# define BOOST_SYMBOL_VISIBLE __attribute__((__visibility__("default")))
+#endif
+
+//
+// The BOOST_FALLTHROUGH macro can be used to annotate implicit fall-through
+// between switch labels.
+//
+#if __cplusplus >= 201103L && defined(__has_warning)
+# if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")
+# define BOOST_FALLTHROUGH [[clang::fallthrough]]
+# endif
+#endif
+
+#if !__has_feature(cxx_auto_type)
+# define BOOST_NO_CXX11_AUTO_DECLARATIONS
+# define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS
+#endif
+
+//
+// Currently clang on Windows using VC++ RTL does not support C++11's char16_t or char32_t
+//
+#if defined(_MSC_VER) || !(defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L)
+# define BOOST_NO_CXX11_CHAR16_T
+# define BOOST_NO_CXX11_CHAR32_T
+#endif
+
+#if !__has_feature(cxx_constexpr)
+# define BOOST_NO_CXX11_CONSTEXPR
+#endif
+
+#if !__has_feature(cxx_decltype)
+# define BOOST_NO_CXX11_DECLTYPE
+#endif
+
+#if !__has_feature(cxx_decltype_incomplete_return_types)
+# define BOOST_NO_CXX11_DECLTYPE_N3276
+#endif
+
+#if !__has_feature(cxx_defaulted_functions)
+# define BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
+#endif
+
+#if !__has_feature(cxx_deleted_functions)
+# define BOOST_NO_CXX11_DELETED_FUNCTIONS
+#endif
+
+#if !__has_feature(cxx_explicit_conversions)
+# define BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
+#endif
+
+#if !__has_feature(cxx_default_function_template_args)
+# define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS
+#endif
+
+#if !__has_feature(cxx_generalized_initializers)
+# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST
+#endif
+
+#if !__has_feature(cxx_lambdas)
+# define BOOST_NO_CXX11_LAMBDAS
+#endif
+
+#if !__has_feature(cxx_local_type_template_args)
+# define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS
+#endif
+
+#if !__has_feature(cxx_noexcept)
+# define BOOST_NO_CXX11_NOEXCEPT
+#endif
+
+#if !__has_feature(cxx_nullptr)
+# define BOOST_NO_CXX11_NULLPTR
+#endif
+
+#if !__has_feature(cxx_range_for)
+# define BOOST_NO_CXX11_RANGE_BASED_FOR
+#endif
+
+#if !__has_feature(cxx_raw_string_literals)
+# define BOOST_NO_CXX11_RAW_LITERALS
+#endif
+
+#if !__has_feature(cxx_reference_qualified_functions)
+# define BOOST_NO_CXX11_REF_QUALIFIERS
+#endif
+
+#if !__has_feature(cxx_generalized_initializers)
+# define BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
+#endif
+
+#if !__has_feature(cxx_rvalue_references)
+# define BOOST_NO_CXX11_RVALUE_REFERENCES
+#endif
+
+#if !__has_feature(cxx_strong_enums)
+# define BOOST_NO_CXX11_SCOPED_ENUMS
+#endif
+
+#if !__has_feature(cxx_static_assert)
+# define BOOST_NO_CXX11_STATIC_ASSERT
+#endif
+
+#if !__has_feature(cxx_alias_templates)
+# define BOOST_NO_CXX11_TEMPLATE_ALIASES
+#endif
+
+#if !__has_feature(cxx_unicode_literals)
+# define BOOST_NO_CXX11_UNICODE_LITERALS
+#endif
+
+#if !__has_feature(cxx_variadic_templates)
+# define BOOST_NO_CXX11_VARIADIC_TEMPLATES
+#endif
+
+#if !__has_feature(cxx_user_literals)
+# define BOOST_NO_CXX11_USER_DEFINED_LITERALS
+#endif
+
+#if !__has_feature(cxx_alignas)
+# define BOOST_NO_CXX11_ALIGNAS
+#endif
+
+#if !__has_feature(cxx_trailing_return)
+# define BOOST_NO_CXX11_TRAILING_RESULT_TYPES
+#endif
+
+#if !__has_feature(cxx_inline_namespaces)
+# define BOOST_NO_CXX11_INLINE_NAMESPACES
+#endif
+
+#if !__has_feature(cxx_override_control)
+# define BOOST_NO_CXX11_FINAL
+#endif
+
+#if !(__has_feature(__cxx_binary_literals__) || __has_extension(__cxx_binary_literals__))
+# define BOOST_NO_CXX14_BINARY_LITERALS
+#endif
+
+#if !__has_feature(__cxx_decltype_auto__)
+# define BOOST_NO_CXX14_DECLTYPE_AUTO
+#endif
+
+#if !__has_feature(__cxx_aggregate_nsdmi__)
+# define BOOST_NO_CXX14_AGGREGATE_NSDMI
+#endif
+
+#if !__has_feature(__cxx_init_captures__)
+# define BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES
+#endif
+
+#if !__has_feature(__cxx_generic_lambdas__)
+# define BOOST_NO_CXX14_GENERIC_LAMBDAS
+#endif
+
+// clang < 3.5 has a defect with dependent type, like following.
+//
+// template <class T>
+// constexpr typename enable_if<pred<T> >::type foo(T &)
+// { } // error: no return statement in constexpr function
+//
+// This issue also affects C++11 mode, but C++11 constexpr requires return stmt.
+// Therefore we don't care such case.
+//
+// Note that we can't check Clang version directly as the numbering system changes depending who's
+// creating the Clang release (see https://github.com/boostorg/config/pull/39#issuecomment-59927873)
+// so instead verify that we have a feature that was introduced at the same time as working C++14
+// constexpr (generic lambda's in this case):
+//
+#if !__has_feature(__cxx_generic_lambdas__) || !__has_feature(__cxx_relaxed_constexpr__)
+# define BOOST_NO_CXX14_CONSTEXPR
+#endif
+
+#if !__has_feature(__cxx_return_type_deduction__)
+# define BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION
+#endif
+
+#if !__has_feature(__cxx_variable_templates__)
+# define BOOST_NO_CXX14_VARIABLE_TEMPLATES
+#endif
+
+#if __cplusplus < 201400
+// All versions with __cplusplus above this value seem to support this:
+# define BOOST_NO_CXX14_DIGIT_SEPARATORS
+#endif
+//
+// __builtin_unreachable:
+#if defined(__has_builtin) && __has_builtin(__builtin_unreachable)
+#define BOOST_UNREACHABLE_RETURN(x) __builtin_unreachable();
+#endif
+
+// Clang has supported the 'unused' attribute since the first release.
+#define BOOST_ATTRIBUTE_UNUSED __attribute__((__unused__))
+
+#ifndef BOOST_COMPILER
+# define BOOST_COMPILER "Clang version " __clang_version__
+#endif
+
+// Macro used to identify the Clang compiler.
+#define BOOST_CLANG 1
diff --git a/third_party/boost/boost/config/compiler/gcc.hpp b/third_party/boost/boost/config/compiler/gcc.hpp
new file mode 100644
index 0000000..735c231
--- /dev/null
+++ b/third_party/boost/boost/config/compiler/gcc.hpp
@@ -0,0 +1,313 @@
+// (C) Copyright John Maddock 2001 - 2003.
+// (C) Copyright Darin Adler 2001 - 2002.
+// (C) Copyright Jens Maurer 2001 - 2002.
+// (C) Copyright Beman Dawes 2001 - 2003.
+// (C) Copyright Douglas Gregor 2002.
+// (C) Copyright David Abrahams 2002 - 2003.
+// (C) Copyright Synge Todo 2003.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for most recent version.
+
+// GNU C++ compiler setup.
+
+//
+// Define BOOST_GCC so we know this is "real" GCC and not some pretender:
+//
+#define BOOST_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+#if !defined(__CUDACC__)
+#define BOOST_GCC BOOST_GCC_VERSION
+#endif
+
+#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
+# define BOOST_GCC_CXX11
+#endif
+
+#if __GNUC__ == 3
+# if defined (__PATHSCALE__)
+# define BOOST_NO_TWO_PHASE_NAME_LOOKUP
+# define BOOST_NO_IS_ABSTRACT
+# endif
+
+# if __GNUC_MINOR__ < 4
+# define BOOST_NO_IS_ABSTRACT
+# endif
+# define BOOST_NO_CXX11_EXTERN_TEMPLATE
+#endif
+#if __GNUC__ < 4
+//
+// All problems to gcc-3.x and earlier here:
+//
+#define BOOST_NO_TWO_PHASE_NAME_LOOKUP
+# ifdef __OPEN64__
+# define BOOST_NO_IS_ABSTRACT
+# endif
+#endif
+
+// GCC prior to 3.4 had #pragma once too but it didn't work well with filesystem links
+#if BOOST_GCC_VERSION >= 30400
+#define BOOST_HAS_PRAGMA_ONCE
+#endif
+
+#if BOOST_GCC_VERSION < 40400
+// Previous versions of GCC did not completely implement value-initialization:
+// GCC Bug 30111, "Value-initialization of POD base class doesn't initialize
+// members", reported by Jonathan Wakely in 2006,
+// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30111 (fixed for GCC 4.4)
+// GCC Bug 33916, "Default constructor fails to initialize array members",
+// reported by Michael Elizabeth Chastain in 2007,
+// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33916 (fixed for GCC 4.2.4)
+// See also: http://www.boost.org/libs/utility/value_init.htm#compiler_issues
+#define BOOST_NO_COMPLETE_VALUE_INITIALIZATION
+#endif
+
+#if !defined(__EXCEPTIONS) && !defined(BOOST_NO_EXCEPTIONS)
+# define BOOST_NO_EXCEPTIONS
+#endif
+
+
+//
+// Threading support: Turn this on unconditionally here (except for
+// those platforms where we can know for sure). It will get turned off again
+// later if no threading API is detected.
+//
+#if !defined(__MINGW32__) && !defined(linux) && !defined(__linux) && !defined(__linux__)
+# define BOOST_HAS_THREADS
+#endif
+
+//
+// gcc has "long long"
+// Except on Darwin with standard compliance enabled (-pedantic)
+// Apple gcc helpfully defines this macro we can query
+//
+#if !defined(__DARWIN_NO_LONG_LONG)
+# define BOOST_HAS_LONG_LONG
+#endif
+
+//
+// gcc implements the named return value optimization since version 3.1
+//
+#define BOOST_HAS_NRVO
+
+// Branch prediction hints
+#define BOOST_LIKELY(x) __builtin_expect(x, 1)
+#define BOOST_UNLIKELY(x) __builtin_expect(x, 0)
+
+//
+// Dynamic shared object (DSO) and dynamic-link library (DLL) support
+//
+#if __GNUC__ >= 4
+# if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && !defined(__CYGWIN__)
+ // All Win32 development environments, including 64-bit Windows and MinGW, define
+ // _WIN32 or one of its variant spellings. Note that Cygwin is a POSIX environment,
+ // so does not define _WIN32 or its variants.
+# define BOOST_HAS_DECLSPEC
+# define BOOST_SYMBOL_EXPORT __attribute__((__dllexport__))
+# define BOOST_SYMBOL_IMPORT __attribute__((__dllimport__))
+# else
+# define BOOST_SYMBOL_EXPORT __attribute__((__visibility__("default")))
+# define BOOST_SYMBOL_IMPORT
+# endif
+# define BOOST_SYMBOL_VISIBLE __attribute__((__visibility__("default")))
+#else
+// config/platform/win32.hpp will define BOOST_SYMBOL_EXPORT, etc., unless already defined
+# define BOOST_SYMBOL_EXPORT
+#endif
+
+//
+// RTTI and typeinfo detection is possible post gcc-4.3:
+//
+#if BOOST_GCC_VERSION > 40300
+# ifndef __GXX_RTTI
+# ifndef BOOST_NO_TYPEID
+# define BOOST_NO_TYPEID
+# endif
+# ifndef BOOST_NO_RTTI
+# define BOOST_NO_RTTI
+# endif
+# endif
+#endif
+
+//
+// Recent GCC versions have __int128 when in 64-bit mode.
+//
+// We disable this if the compiler is really nvcc as it
+// doesn't actually support __int128 as of CUDA_VERSION=5000
+// even though it defines __SIZEOF_INT128__.
+// See https://svn.boost.org/trac/boost/ticket/8048
+// Only re-enable this for nvcc if you're absolutely sure
+// of the circumstances under which it's supported:
+//
+#if defined(__SIZEOF_INT128__) && !defined(__CUDACC__)
+# define BOOST_HAS_INT128
+#endif
+//
+// Recent GCC versions have a __float128 native type, we need to
+// include a std lib header to detect this - not ideal, but we'll
+// be including <cstddef> later anyway when we select the std lib.
+//
+#ifdef __cplusplus
+#include <cstddef>
+#else
+#include <stddef.h>
+#endif
+#if defined(_GLIBCXX_USE_FLOAT128) && !defined(__STRICT_ANSI__)
+# define BOOST_HAS_FLOAT128
+#endif
+
+// C++0x features in 4.3.n and later
+//
+#if (BOOST_GCC_VERSION >= 40300) && defined(BOOST_GCC_CXX11)
+// C++0x features are only enabled when -std=c++0x or -std=gnu++0x are
+// passed on the command line, which in turn defines
+// __GXX_EXPERIMENTAL_CXX0X__.
+# define BOOST_HAS_DECLTYPE
+# define BOOST_HAS_RVALUE_REFS
+# define BOOST_HAS_STATIC_ASSERT
+# define BOOST_HAS_VARIADIC_TMPL
+#else
+# define BOOST_NO_CXX11_DECLTYPE
+# define BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS
+# define BOOST_NO_CXX11_RVALUE_REFERENCES
+# define BOOST_NO_CXX11_STATIC_ASSERT
+#endif
+
+// C++0x features in 4.4.n and later
+//
+#if (BOOST_GCC_VERSION < 40400) || !defined(BOOST_GCC_CXX11)
+# define BOOST_NO_CXX11_AUTO_DECLARATIONS
+# define BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS
+# define BOOST_NO_CXX11_CHAR16_T
+# define BOOST_NO_CXX11_CHAR32_T
+# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST
+# define BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
+# define BOOST_NO_CXX11_DELETED_FUNCTIONS
+# define BOOST_NO_CXX11_TRAILING_RESULT_TYPES
+# define BOOST_NO_CXX11_INLINE_NAMESPACES
+# define BOOST_NO_CXX11_VARIADIC_TEMPLATES
+#endif
+
+#if BOOST_GCC_VERSION < 40500
+# define BOOST_NO_SFINAE_EXPR
+#endif
+
+// GCC 4.5 forbids declaration of defaulted functions in private or protected sections
+#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ == 5) || !defined(BOOST_GCC_CXX11)
+# define BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS
+#endif
+
+// C++0x features in 4.5.0 and later
+//
+#if (BOOST_GCC_VERSION < 40500) || !defined(BOOST_GCC_CXX11)
+# define BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
+# define BOOST_NO_CXX11_LAMBDAS
+# define BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS
+# define BOOST_NO_CXX11_RAW_LITERALS
+# define BOOST_NO_CXX11_UNICODE_LITERALS
+#endif
+
+// C++0x features in 4.5.1 and later
+//
+#if (BOOST_GCC_VERSION < 40501) || !defined(BOOST_GCC_CXX11)
+// scoped enums have a serious bug in 4.4.0, so define BOOST_NO_CXX11_SCOPED_ENUMS before 4.5.1
+// See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38064
+# define BOOST_NO_CXX11_SCOPED_ENUMS
+#endif
+
+// C++0x features in 4.6.n and later
+//
+#if (BOOST_GCC_VERSION < 40600) || !defined(BOOST_GCC_CXX11)
+#define BOOST_NO_CXX11_CONSTEXPR
+#define BOOST_NO_CXX11_NOEXCEPT
+#define BOOST_NO_CXX11_NULLPTR
+#define BOOST_NO_CXX11_RANGE_BASED_FOR
+#define BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX
+#endif
+
+// C++0x features in 4.7.n and later
+//
+#if (BOOST_GCC_VERSION < 40700) || !defined(BOOST_GCC_CXX11)
+# define BOOST_NO_CXX11_FINAL
+# define BOOST_NO_CXX11_TEMPLATE_ALIASES
+# define BOOST_NO_CXX11_USER_DEFINED_LITERALS
+# define BOOST_NO_CXX11_FIXED_LENGTH_VARIADIC_TEMPLATE_EXPANSION_PACKS
+#endif
+
+// C++0x features in 4.8.n and later
+//
+#if (BOOST_GCC_VERSION < 40800) || !defined(BOOST_GCC_CXX11)
+# define BOOST_NO_CXX11_ALIGNAS
+#endif
+
+// C++0x features in 4.8.1 and later
+//
+#if (BOOST_GCC_VERSION < 40801) || !defined(BOOST_GCC_CXX11)
+# define BOOST_NO_CXX11_DECLTYPE_N3276
+# define BOOST_NO_CXX11_REF_QUALIFIERS
+# define BOOST_NO_CXX14_BINARY_LITERALS
+#endif
+
+// C++14 features in 4.9.0 and later
+//
+#if (BOOST_GCC_VERSION < 40900) || (__cplusplus < 201300)
+# define BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION
+# define BOOST_NO_CXX14_GENERIC_LAMBDAS
+# define BOOST_NO_CXX14_DIGIT_SEPARATORS
+# define BOOST_NO_CXX14_DECLTYPE_AUTO
+# if !((BOOST_GCC_VERSION >= 40801) && (BOOST_GCC_VERSION < 40900) && defined(BOOST_GCC_CXX11))
+# define BOOST_NO_CXX14_INITIALIZED_LAMBDA_CAPTURES
+# endif
+#endif
+
+
+// C++ 14:
+#if !defined(__cpp_aggregate_nsdmi) || (__cpp_aggregate_nsdmi < 201304)
+# define BOOST_NO_CXX14_AGGREGATE_NSDMI
+#endif
+#if !defined(__cpp_constexpr) || (__cpp_constexpr < 201304)
+# define BOOST_NO_CXX14_CONSTEXPR
+#endif
+#if !defined(__cpp_variable_templates) || (__cpp_variable_templates < 201304)
+# define BOOST_NO_CXX14_VARIABLE_TEMPLATES
+#endif
+
+//
+// Unused attribute:
+#if __GNUC__ >= 4
+# define BOOST_ATTRIBUTE_UNUSED __attribute__((__unused__))
+#endif
+//
+// __builtin_unreachable:
+#if BOOST_GCC_VERSION >= 40800
+#define BOOST_UNREACHABLE_RETURN(x) __builtin_unreachable();
+#endif
+
+#ifndef BOOST_COMPILER
+# define BOOST_COMPILER "GNU C++ version " __VERSION__
+#endif
+
+// ConceptGCC compiler:
+// http://www.generic-programming.org/software/ConceptGCC/
+#ifdef __GXX_CONCEPTS__
+# define BOOST_HAS_CONCEPTS
+# define BOOST_COMPILER "ConceptGCC version " __VERSION__
+#endif
+
+// versions check:
+// we don't know gcc prior to version 3.30:
+#if (BOOST_GCC_VERSION< 30300)
+# error "Compiler not configured - please reconfigure"
+#endif
+//
+// last known and checked version is 4.9:
+#if (BOOST_GCC_VERSION > 40900)
+# if defined(BOOST_ASSERT_CONFIG)
+# error "Unknown compiler version - please run the configure tests and report the results"
+# else
+// we don't emit warnings here anymore since there are no defect macros defined for
+// gcc post 3.4, so any failures are gcc regressions...
+//# warning "Unknown compiler version - please run the configure tests and report the results"
+# endif
+#endif
diff --git a/third_party/boost/boost/config/no_tr1/functional.hpp b/third_party/boost/boost/config/no_tr1/functional.hpp
new file mode 100644
index 0000000..e395efc
--- /dev/null
+++ b/third_party/boost/boost/config/no_tr1/functional.hpp
@@ -0,0 +1,28 @@
+// (C) Copyright John Maddock 2005.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// The aim of this header is just to include <functional> but to do
+// so in a way that does not result in recursive inclusion of
+// the Boost TR1 components if boost/tr1/tr1/functional is in the
+// include search path. We have to do this to avoid circular
+// dependencies:
+//
+
+#ifndef BOOST_CONFIG_FUNCTIONAL
+# define BOOST_CONFIG_FUNCTIONAL
+
+# ifndef BOOST_TR1_NO_RECURSION
+# define BOOST_TR1_NO_RECURSION
+# define BOOST_CONFIG_NO_FUNCTIONAL_RECURSION
+# endif
+
+# include <functional>
+
+# ifdef BOOST_CONFIG_NO_FUNCTIONAL_RECURSION
+# undef BOOST_TR1_NO_RECURSION
+# undef BOOST_CONFIG_NO_FUNCTIONAL_RECURSION
+# endif
+
+#endif
diff --git a/third_party/boost/boost/config/no_tr1/memory.hpp b/third_party/boost/boost/config/no_tr1/memory.hpp
new file mode 100644
index 0000000..2b5d208
--- /dev/null
+++ b/third_party/boost/boost/config/no_tr1/memory.hpp
@@ -0,0 +1,28 @@
+// (C) Copyright John Maddock 2005.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// The aim of this header is just to include <memory> but to do
+// so in a way that does not result in recursive inclusion of
+// the Boost TR1 components if boost/tr1/tr1/memory is in the
+// include search path. We have to do this to avoid circular
+// dependencies:
+//
+
+#ifndef BOOST_CONFIG_MEMORY
+# define BOOST_CONFIG_MEMORY
+
+# ifndef BOOST_TR1_NO_RECURSION
+# define BOOST_TR1_NO_RECURSION
+# define BOOST_CONFIG_NO_MEMORY_RECURSION
+# endif
+
+# include <memory>
+
+# ifdef BOOST_CONFIG_NO_MEMORY_RECURSION
+# undef BOOST_TR1_NO_RECURSION
+# undef BOOST_CONFIG_NO_MEMORY_RECURSION
+# endif
+
+#endif
diff --git a/third_party/boost/boost/config/platform/linux.hpp b/third_party/boost/boost/config/platform/linux.hpp
new file mode 100644
index 0000000..ada1439
--- /dev/null
+++ b/third_party/boost/boost/config/platform/linux.hpp
@@ -0,0 +1,103 @@
+// (C) Copyright John Maddock 2001 - 2003.
+// (C) Copyright Jens Maurer 2001 - 2003.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for most recent version.
+
+// linux specific config options:
+
+#define BOOST_PLATFORM "linux"
+
+// make sure we have __GLIBC_PREREQ if available at all
+#ifdef __cplusplus
+#include <cstdlib>
+#else
+#include <stdlib.h>
+#endif
+
+//
+// <stdint.h> added to glibc 2.1.1
+// We can only test for 2.1 though:
+//
+#if defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1)))
+ // <stdint.h> defines int64_t unconditionally, but <sys/types.h> defines
+ // int64_t only if __GNUC__. Thus, assume a fully usable <stdint.h>
+ // only when using GCC.
+# if defined __GNUC__
+# define BOOST_HAS_STDINT_H
+# endif
+#endif
+
+#if defined(__LIBCOMO__)
+ //
+ // como on linux doesn't have std:: c functions:
+ // NOTE: versions of libcomo prior to beta28 have octal version numbering,
+ // e.g. version 25 is 21 (dec)
+ //
+# if __LIBCOMO_VERSION__ <= 20
+# define BOOST_NO_STDC_NAMESPACE
+# endif
+
+# if __LIBCOMO_VERSION__ <= 21
+# define BOOST_NO_SWPRINTF
+# endif
+
+#endif
+
+//
+// If glibc is past version 2 then we definitely have
+// gettimeofday, earlier versions may or may not have it:
+//
+#if defined(__GLIBC__) && (__GLIBC__ >= 2)
+# define BOOST_HAS_GETTIMEOFDAY
+#endif
+
+#ifdef __USE_POSIX199309
+# define BOOST_HAS_NANOSLEEP
+#endif
+
+#if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
+// __GLIBC_PREREQ is available since 2.1.2
+
+ // swprintf is available since glibc 2.2.0
+# if !__GLIBC_PREREQ(2,2) || (!defined(__USE_ISOC99) && !defined(__USE_UNIX98))
+# define BOOST_NO_SWPRINTF
+# endif
+#else
+# define BOOST_NO_SWPRINTF
+#endif
+
+// boilerplate code:
+#define BOOST_HAS_UNISTD_H
+#include <boost/config/posix_features.hpp>
+#ifdef __USE_GNU
+#define BOOST_HAS_PTHREAD_YIELD
+#endif
+
+#ifndef __GNUC__
+//
+// if the compiler is not gcc we still need to be able to parse
+// the GNU system headers, some of which (mainly <stdint.h>)
+// use GNU specific extensions:
+//
+# ifndef __extension__
+# define __extension__
+# endif
+# ifndef __const__
+# define __const__ const
+# endif
+# ifndef __volatile__
+# define __volatile__ volatile
+# endif
+# ifndef __signed__
+# define __signed__ signed
+# endif
+# ifndef __typeof__
+# define __typeof__ typeof
+# endif
+# ifndef __inline__
+# define __inline__ inline
+# endif
+#endif
diff --git a/third_party/boost/boost/config/platform/macos.hpp b/third_party/boost/boost/config/platform/macos.hpp
new file mode 100644
index 0000000..62b4468
--- /dev/null
+++ b/third_party/boost/boost/config/platform/macos.hpp
@@ -0,0 +1,84 @@
+// (C) Copyright John Maddock 2001 - 2003.
+// (C) Copyright Darin Adler 2001 - 2002.
+// (C) Copyright Bill Kempf 2002.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for most recent version.
+
+// Mac OS specific config options:
+
+#define BOOST_PLATFORM "Mac OS"
+
+#if __MACH__ && !defined(_MSL_USING_MSL_C)
+
+// Using the Mac OS X system BSD-style C library.
+
+# ifndef BOOST_HAS_UNISTD_H
+# define BOOST_HAS_UNISTD_H
+# endif
+//
+// Begin by including our boilerplate code for POSIX
+// feature detection, this is safe even when using
+// the MSL as Metrowerks supply their own <unistd.h>
+// to replace the platform-native BSD one. G++ users
+// should also always be able to do this on MaxOS X.
+//
+# include <boost/config/posix_features.hpp>
+# ifndef BOOST_HAS_STDINT_H
+# define BOOST_HAS_STDINT_H
+# endif
+
+//
+// BSD runtime has pthreads, sigaction, sched_yield and gettimeofday,
+// of these only pthreads are advertised in <unistd.h>, so set the
+// other options explicitly:
+//
+# define BOOST_HAS_SCHED_YIELD
+# define BOOST_HAS_GETTIMEOFDAY
+# define BOOST_HAS_SIGACTION
+
+# if (__GNUC__ < 3) && !defined( __APPLE_CC__)
+
+// GCC strange "ignore std" mode works better if you pretend everything
+// is in the std namespace, for the most part.
+
+# define BOOST_NO_STDC_NAMESPACE
+# endif
+
+# if (__GNUC__ >= 4)
+
+// Both gcc and intel require these.
+# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
+# define BOOST_HAS_NANOSLEEP
+
+# endif
+
+#else
+
+// Using the MSL C library.
+
+// We will eventually support threads in non-Carbon builds, but we do
+// not support this yet.
+# if ( defined(TARGET_API_MAC_CARBON) && TARGET_API_MAC_CARBON ) || ( defined(TARGET_CARBON) && TARGET_CARBON )
+
+# if !defined(BOOST_HAS_PTHREADS)
+// MPTasks support is deprecated/removed from Boost:
+//# define BOOST_HAS_MPTASKS
+# elif ( __dest_os == __mac_os_x )
+// We are doing a Carbon/Mach-O/MSL build which has pthreads, but only the
+// gettimeofday and no posix.
+# define BOOST_HAS_GETTIMEOFDAY
+# endif
+
+#ifdef BOOST_HAS_PTHREADS
+# define BOOST_HAS_THREADS
+#endif
+
+// The remote call manager depends on this.
+# define BOOST_BIND_ENABLE_PASCAL
+
+# endif
+
+#endif
diff --git a/third_party/boost/boost/config/posix_features.hpp b/third_party/boost/boost/config/posix_features.hpp
new file mode 100644
index 0000000..8664a95
--- /dev/null
+++ b/third_party/boost/boost/config/posix_features.hpp
@@ -0,0 +1,91 @@
+// (C) Copyright John Maddock 2001 - 2003.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+// See http://www.boost.org for most recent version.
+
+// All POSIX feature tests go in this file,
+// Note that we test _POSIX_C_SOURCE and _XOPEN_SOURCE as well
+// _POSIX_VERSION and _XOPEN_VERSION: on some systems POSIX API's
+// may be present but none-functional unless _POSIX_C_SOURCE and
+// _XOPEN_SOURCE have been defined to the right value (it's up
+// to the user to do this *before* including any header, although
+// in most cases the compiler will do this for you).
+
+# if defined(BOOST_HAS_UNISTD_H)
+# include <unistd.h>
+
+ // XOpen has <nl_types.h>, but is this the correct version check?
+# if defined(_XOPEN_VERSION) && (_XOPEN_VERSION >= 3)
+# define BOOST_HAS_NL_TYPES_H
+# endif
+
+ // POSIX version 6 requires <stdint.h>
+# if defined(_POSIX_VERSION) && (_POSIX_VERSION >= 200100)
+# define BOOST_HAS_STDINT_H
+# endif
+
+ // POSIX version 2 requires <dirent.h>
+# if defined(_POSIX_VERSION) && (_POSIX_VERSION >= 199009L)
+# define BOOST_HAS_DIRENT_H
+# endif
+
+ // POSIX version 3 requires <signal.h> to have sigaction:
+# if defined(_POSIX_VERSION) && (_POSIX_VERSION >= 199506L)
+# define BOOST_HAS_SIGACTION
+# endif
+ // POSIX defines _POSIX_THREADS > 0 for pthread support,
+ // however some platforms define _POSIX_THREADS without
+ // a value, hence the (_POSIX_THREADS+0 >= 0) check.
+ // Strictly speaking this may catch platforms with a
+ // non-functioning stub <pthreads.h>, but such occurrences should
+ // occur very rarely if at all.
+# if defined(_POSIX_THREADS) && (_POSIX_THREADS+0 >= 0) && !defined(BOOST_HAS_WINTHREADS) && !defined(BOOST_HAS_MPTASKS)
+# define BOOST_HAS_PTHREADS
+# endif
+
+ // BOOST_HAS_NANOSLEEP:
+ // This is predicated on _POSIX_TIMERS or _XOPEN_REALTIME:
+# if (defined(_POSIX_TIMERS) && (_POSIX_TIMERS+0 >= 0)) \
+ || (defined(_XOPEN_REALTIME) && (_XOPEN_REALTIME+0 >= 0))
+# define BOOST_HAS_NANOSLEEP
+# endif
+
+ // BOOST_HAS_CLOCK_GETTIME:
+ // This is predicated on _POSIX_TIMERS (also on _XOPEN_REALTIME
+ // but at least one platform - linux - defines that flag without
+ // defining clock_gettime):
+# if (defined(_POSIX_TIMERS) && (_POSIX_TIMERS+0 >= 0))
+# define BOOST_HAS_CLOCK_GETTIME
+# endif
+
+ // BOOST_HAS_SCHED_YIELD:
+ // This is predicated on _POSIX_PRIORITY_SCHEDULING or
+ // on _POSIX_THREAD_PRIORITY_SCHEDULING or on _XOPEN_REALTIME.
+# if defined(_POSIX_PRIORITY_SCHEDULING) && (_POSIX_PRIORITY_SCHEDULING+0 > 0)\
+ || (defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING+0 > 0))\
+ || (defined(_XOPEN_REALTIME) && (_XOPEN_REALTIME+0 >= 0))
+# define BOOST_HAS_SCHED_YIELD
+# endif
+
+ // BOOST_HAS_GETTIMEOFDAY:
+ // BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE:
+ // These are predicated on _XOPEN_VERSION, and appears to be first released
+ // in issue 4, version 2 (_XOPEN_VERSION > 500).
+ // Likewise for the functions log1p and expm1.
+# if defined(_XOPEN_VERSION) && (_XOPEN_VERSION+0 >= 500)
+# define BOOST_HAS_GETTIMEOFDAY
+# if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE+0 >= 500)
+# define BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
+# endif
+# ifndef BOOST_HAS_LOG1P
+# define BOOST_HAS_LOG1P
+# endif
+# ifndef BOOST_HAS_EXPM1
+# define BOOST_HAS_EXPM1
+# endif
+# endif
+
+# endif
diff --git a/third_party/boost/boost/config/select_compiler_config.hpp b/third_party/boost/boost/config/select_compiler_config.hpp
new file mode 100644
index 0000000..db71657
--- /dev/null
+++ b/third_party/boost/boost/config/select_compiler_config.hpp
@@ -0,0 +1,147 @@
+// Boost compiler configuration selection header file
+
+// (C) Copyright John Maddock 2001 - 2003.
+// (C) Copyright Martin Wille 2003.
+// (C) Copyright Guillaume Melquiond 2003.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/ for most recent version.
+
+// locate which compiler we are using and define
+// BOOST_COMPILER_CONFIG as needed:
+
+#if defined __CUDACC__
+// NVIDIA CUDA C++ compiler for GPU
+# include "boost/config/compiler/nvcc.hpp"
+
+#endif
+
+#if defined(__GCCXML__)
+// GCC-XML emulates other compilers, it has to appear first here!
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/gcc_xml.hpp"
+
+#elif defined(_CRAYC)
+// EDG based Cray compiler:
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/cray.hpp"
+
+#elif defined __COMO__
+// Comeau C++
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/comeau.hpp"
+
+#elif defined(__PATHSCALE__) && (__PATHCC__ >= 4)
+// PathScale EKOPath compiler (has to come before clang and gcc)
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/pathscale.hpp"
+
+#elif defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)
+// Intel
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/intel.hpp"
+
+#elif defined __clang__ && !defined(__CUDACC__) && !defined(__ibmxl__)
+// when using clang and cuda at same time, you want to appear as gcc
+// Clang C++ emulates GCC, so it has to appear early.
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/clang.hpp"
+
+#elif defined __DMC__
+// Digital Mars C++
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/digitalmars.hpp"
+
+# elif defined(__GNUC__) && !defined(__ibmxl__)
+// GNU C++:
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/gcc.hpp"
+
+#elif defined __KCC
+// Kai C++
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/kai.hpp"
+
+#elif defined __sgi
+// SGI MIPSpro C++
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/sgi_mipspro.hpp"
+
+#elif defined __DECCXX
+// Compaq Tru64 Unix cxx
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/compaq_cxx.hpp"
+
+#elif defined __ghs
+// Greenhills C++
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/greenhills.hpp"
+
+#elif defined __CODEGEARC__
+// CodeGear - must be checked for before Borland
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/codegear.hpp"
+
+#elif defined __BORLANDC__
+// Borland
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/borland.hpp"
+
+#elif defined __MWERKS__
+// Metrowerks CodeWarrior
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/metrowerks.hpp"
+
+#elif defined __SUNPRO_CC
+// Sun Workshop Compiler C++
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/sunpro_cc.hpp"
+
+#elif defined __HP_aCC
+// HP aCC
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/hp_acc.hpp"
+
+#elif defined(__MRC__) || defined(__SC__)
+// MPW MrCpp or SCpp
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/mpw.hpp"
+
+#elif defined(__ibmxl__)
+// IBM XL C/C++ for Linux (Little Endian)
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/xlcpp.hpp"
+
+#elif defined(__IBMCPP__)
+// IBM Visual Age or IBM XL C/C++ for Linux (Big Endian)
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/vacpp.hpp"
+
+#elif defined(__PGI)
+// Portland Group Inc.
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/pgi.hpp"
+
+#elif defined _MSC_VER
+// Microsoft Visual C++
+//
+// Must remain the last #elif since some other vendors (Metrowerks, for
+// example) also #define _MSC_VER
+# define BOOST_COMPILER_CONFIG "boost/config/compiler/visualc.hpp"
+
+#elif defined (BOOST_ASSERT_CONFIG)
+// this must come last - generate an error if we don't
+// recognise the compiler:
+# error "Unknown compiler - please configure (http://www.boost.org/libs/config/config.htm#configuring) and report the results to the main boost mailing list (http://www.boost.org/more/mailing_lists.htm#main)"
+
+#endif
+
+#if 0
+//
+// This section allows dependency scanners to find all the headers we *might* include:
+//
+#include "boost/config/compiler/gcc_xml.hpp"
+#include "boost/config/compiler/cray.hpp"
+#include "boost/config/compiler/comeau.hpp"
+#include "boost/config/compiler/pathscale.hpp"
+#include "boost/config/compiler/intel.hpp"
+#include "boost/config/compiler/clang.hpp"
+#include "boost/config/compiler/digitalmars.hpp"
+#include "boost/config/compiler/gcc.hpp"
+#include "boost/config/compiler/kai.hpp"
+#include "boost/config/compiler/sgi_mipspro.hpp"
+#include "boost/config/compiler/compaq_cxx.hpp"
+#include "boost/config/compiler/greenhills.hpp"
+#include "boost/config/compiler/codegear.hpp"
+#include "boost/config/compiler/borland.hpp"
+#include "boost/config/compiler/metrowerks.hpp"
+#include "boost/config/compiler/sunpro_cc.hpp"
+#include "boost/config/compiler/hp_acc.hpp"
+#include "boost/config/compiler/mpw.hpp"
+#include "boost/config/compiler/vacpp.hpp"
+#include "boost/config/compiler/pgi.hpp"
+#include "boost/config/compiler/visualc.hpp"
+
+#endif
diff --git a/third_party/boost/boost/config/select_platform_config.hpp b/third_party/boost/boost/config/select_platform_config.hpp
new file mode 100644
index 0000000..b914ad2
--- /dev/null
+++ b/third_party/boost/boost/config/select_platform_config.hpp
@@ -0,0 +1,136 @@
+// Boost compiler configuration selection header file
+
+// (C) Copyright John Maddock 2001 - 2002.
+// (C) Copyright Jens Maurer 2001.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for most recent version.
+
+// locate which platform we are on and define BOOST_PLATFORM_CONFIG as needed.
+// Note that we define the headers to include using "header_name" not
+// <header_name> in order to prevent macro expansion within the header
+// name (for example "linux" is a macro on linux systems).
+
+#if (defined(linux) || defined(__linux) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)) && !defined(_CRAYC)
+// linux, also other platforms (Hurd etc) that use GLIBC, should these really have their own config headers though?
+# define BOOST_PLATFORM_CONFIG "boost/config/platform/linux.hpp"
+
+#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
+// BSD:
+# define BOOST_PLATFORM_CONFIG "boost/config/platform/bsd.hpp"
+
+#elif defined(sun) || defined(__sun)
+// solaris:
+# define BOOST_PLATFORM_CONFIG "boost/config/platform/solaris.hpp"
+
+#elif defined(__sgi)
+// SGI Irix:
+# define BOOST_PLATFORM_CONFIG "boost/config/platform/irix.hpp"
+
+#elif defined(__hpux)
+// hp unix:
+# define BOOST_PLATFORM_CONFIG "boost/config/platform/hpux.hpp"
+
+#elif defined(__CYGWIN__)
+// cygwin is not win32:
+# define BOOST_PLATFORM_CONFIG "boost/config/platform/cygwin.hpp"
+
+#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+// win32:
+# define BOOST_PLATFORM_CONFIG "boost/config/platform/win32.hpp"
+
+#elif defined(__HAIKU__)
+// Haiku
+# define BOOST_PLATFORM_CONFIG "boost/config/platform/haiku.hpp"
+
+#elif defined(__BEOS__)
+// BeOS
+# define BOOST_PLATFORM_CONFIG "boost/config/platform/beos.hpp"
+
+#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
+// MacOS
+# define BOOST_PLATFORM_CONFIG "boost/config/platform/macos.hpp"
+
+#elif defined(__IBMCPP__) || defined(_AIX)
+// IBM
+# define BOOST_PLATFORM_CONFIG "boost/config/platform/aix.hpp"
+
+#elif defined(__amigaos__)
+// AmigaOS
+# define BOOST_PLATFORM_CONFIG "boost/config/platform/amigaos.hpp"
+
+#elif defined(__QNXNTO__)
+// QNX:
+# define BOOST_PLATFORM_CONFIG "boost/config/platform/qnxnto.hpp"
+
+#elif defined(__VXWORKS__)
+// vxWorks:
+# define BOOST_PLATFORM_CONFIG "boost/config/platform/vxworks.hpp"
+
+#elif defined(__SYMBIAN32__)
+// Symbian:
+# define BOOST_PLATFORM_CONFIG "boost/config/platform/symbian.hpp"
+
+#elif defined(_CRAYC)
+// Cray:
+# define BOOST_PLATFORM_CONFIG "boost/config/platform/cray.hpp"
+
+#elif defined(__VMS)
+// VMS:
+# define BOOST_PLATFORM_CONFIG "boost/config/platform/vms.hpp"
+
+#elif defined(__CloudABI__)
+// Nuxi CloudABI:
+# define BOOST_PLATFORM_CONFIG "boost/config/platform/cloudabi.hpp"
+#else
+
+# if defined(unix) \
+ || defined(__unix) \
+ || defined(_XOPEN_SOURCE) \
+ || defined(_POSIX_SOURCE)
+
+ // generic unix platform:
+
+# ifndef BOOST_HAS_UNISTD_H
+# define BOOST_HAS_UNISTD_H
+# endif
+
+# include <boost/config/posix_features.hpp>
+
+# endif
+
+# if defined (BOOST_ASSERT_CONFIG)
+ // this must come last - generate an error if we don't
+ // recognise the platform:
+# error "Unknown platform - please configure and report the results to boost.org"
+# endif
+
+#endif
+
+#if 0
+//
+// This section allows dependency scanners to find all the files we *might* include:
+//
+# include "boost/config/platform/linux.hpp"
+# include "boost/config/platform/bsd.hpp"
+# include "boost/config/platform/solaris.hpp"
+# include "boost/config/platform/irix.hpp"
+# include "boost/config/platform/hpux.hpp"
+# include "boost/config/platform/cygwin.hpp"
+# include "boost/config/platform/win32.hpp"
+# include "boost/config/platform/beos.hpp"
+# include "boost/config/platform/macos.hpp"
+# include "boost/config/platform/aix.hpp"
+# include "boost/config/platform/amigaos.hpp"
+# include "boost/config/platform/qnxnto.hpp"
+# include "boost/config/platform/vxworks.hpp"
+# include "boost/config/platform/symbian.hpp"
+# include "boost/config/platform/cray.hpp"
+# include "boost/config/platform/vms.hpp"
+# include <boost/config/posix_features.hpp>
+
+
+
+#endif
diff --git a/third_party/boost/boost/config/select_stdlib_config.hpp b/third_party/boost/boost/config/select_stdlib_config.hpp
new file mode 100644
index 0000000..a88dd7e
--- /dev/null
+++ b/third_party/boost/boost/config/select_stdlib_config.hpp
@@ -0,0 +1,104 @@
+// Boost compiler configuration selection header file
+
+// (C) Copyright John Maddock 2001 - 2003.
+// (C) Copyright Jens Maurer 2001 - 2002.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+
+// See http://www.boost.org for most recent version.
+
+// locate which std lib we are using and define BOOST_STDLIB_CONFIG as needed:
+
+// First include <cstddef> to determine if some version of STLport is in use as the std lib
+// (do not rely on this header being included since users can short-circuit this header
+// if they know whose std lib they are using.)
+#ifdef __cplusplus
+# include <cstddef>
+#else
+# include <stddef.h>
+#endif
+
+#if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
+// STLPort library; this _must_ come first, otherwise since
+// STLport typically sits on top of some other library, we
+// can end up detecting that first rather than STLport:
+# define BOOST_STDLIB_CONFIG "boost/config/stdlib/stlport.hpp"
+
+#else
+
+// If our std lib was not some version of STLport, and has not otherwise
+// been detected, then include <utility> as it is about
+// the smallest of the std lib headers that includes real C++ stuff.
+// Some std libs do not include their C++-related macros in <cstddef>
+// so this additional include makes sure we get those definitions.
+// Note: do not rely on this header being included since users can short-circuit this
+// #include if they know whose std lib they are using.
+#if !defined(__LIBCOMO__) && !defined(__STD_RWCOMPILER_H__) && !defined(_RWSTD_VER)\
+ && !defined(_LIBCPP_VERSION) && !defined(__GLIBCPP__) && !defined(__GLIBCXX__)\
+ && !defined(__STL_CONFIG_H) && !defined(__MSL_CPP__) && !defined(__IBMCPP__)\
+ && !defined(MSIPL_COMPILE_H) && !defined(_YVALS) && !defined(_CPPLIB_VER)
+#include <utility>
+#endif
+
+#if defined(__LIBCOMO__)
+// Comeau STL:
+#define BOOST_STDLIB_CONFIG "boost/config/stdlib/libcomo.hpp"
+
+#elif defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER)
+// Rogue Wave library:
+# define BOOST_STDLIB_CONFIG "boost/config/stdlib/roguewave.hpp"
+
+#elif defined(_LIBCPP_VERSION)
+// libc++
+# define BOOST_STDLIB_CONFIG "boost/config/stdlib/libcpp.hpp"
+
+#elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
+// GNU libstdc++ 3
+# define BOOST_STDLIB_CONFIG "boost/config/stdlib/libstdcpp3.hpp"
+
+#elif defined(__STL_CONFIG_H)
+// generic SGI STL
+# define BOOST_STDLIB_CONFIG "boost/config/stdlib/sgi.hpp"
+
+#elif defined(__MSL_CPP__)
+// MSL standard lib:
+# define BOOST_STDLIB_CONFIG "boost/config/stdlib/msl.hpp"
+
+#elif defined(__IBMCPP__)
+// take the default VACPP std lib
+# define BOOST_STDLIB_CONFIG "boost/config/stdlib/vacpp.hpp"
+
+#elif defined(MSIPL_COMPILE_H)
+// Modena C++ standard library
+# define BOOST_STDLIB_CONFIG "boost/config/stdlib/modena.hpp"
+
+#elif (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER)
+// Dinkumware Library (this has to appear after any possible replacement libraries):
+# define BOOST_STDLIB_CONFIG "boost/config/stdlib/dinkumware.hpp"
+
+#elif defined (BOOST_ASSERT_CONFIG)
+// this must come last - generate an error if we don't
+// recognise the library:
+# error "Unknown standard library - please configure and report the results to boost.org"
+
+#endif
+
+#endif
+
+#if 0
+//
+// This section allows dependency scanners to find all the files we *might* include:
+//
+# include "boost/config/stdlib/stlport.hpp"
+# include "boost/config/stdlib/libcomo.hpp"
+# include "boost/config/stdlib/roguewave.hpp"
+# include "boost/config/stdlib/libcpp.hpp"
+# include "boost/config/stdlib/libstdcpp3.hpp"
+# include "boost/config/stdlib/sgi.hpp"
+# include "boost/config/stdlib/msl.hpp"
+# include "boost/config/stdlib/vacpp.hpp"
+# include "boost/config/stdlib/modena.hpp"
+# include "boost/config/stdlib/dinkumware.hpp"
+#endif
diff --git a/third_party/boost/boost/config/stdlib/libcpp.hpp b/third_party/boost/boost/config/stdlib/libcpp.hpp
new file mode 100644
index 0000000..ab5d123
--- /dev/null
+++ b/third_party/boost/boost/config/stdlib/libcpp.hpp
@@ -0,0 +1,80 @@
+// (C) Copyright Christopher Jefferson 2011.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for most recent version.
+
+// config for libc++
+// Might need more in here later.
+
+#if !defined(_LIBCPP_VERSION)
+# include <ciso646>
+# if !defined(_LIBCPP_VERSION)
+# error "This is not libc++!"
+# endif
+#endif
+
+#define BOOST_STDLIB "libc++ version " BOOST_STRINGIZE(_LIBCPP_VERSION)
+
+#define BOOST_HAS_THREADS
+
+#ifdef _LIBCPP_HAS_NO_VARIADICS
+# define BOOST_NO_CXX11_HDR_TUPLE
+#endif
+
+// BOOST_NO_CXX11_ALLOCATOR should imply no support for the C++11
+// allocator model. The C++11 allocator model requires a conforming
+// std::allocator_traits which is only possible with C++11 template
+// aliases since members rebind_alloc and rebind_traits require it.
+#if defined(_LIBCPP_HAS_NO_TEMPLATE_ALIASES)
+# define BOOST_NO_CXX11_ALLOCATOR
+#endif
+
+#if __cplusplus < 201103
+# define BOOST_NO_CXX11_HDR_ARRAY
+# define BOOST_NO_CXX11_HDR_CODECVT
+# define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE
+# define BOOST_NO_CXX11_HDR_FORWARD_LIST
+# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST
+# define BOOST_NO_CXX11_HDR_MUTEX
+# define BOOST_NO_CXX11_HDR_RANDOM
+# define BOOST_NO_CXX11_HDR_RATIO
+# define BOOST_NO_CXX11_HDR_REGEX
+# define BOOST_NO_CXX11_HDR_SYSTEM_ERROR
+# define BOOST_NO_CXX11_HDR_THREAD
+# define BOOST_NO_CXX11_HDR_TUPLE
+# define BOOST_NO_CXX11_HDR_TYPEINDEX
+# define BOOST_NO_CXX11_HDR_UNORDERED_MAP
+# define BOOST_NO_CXX11_HDR_UNORDERED_SET
+# define BOOST_NO_CXX11_NUMERIC_LIMITS
+# define BOOST_NO_CXX11_ALLOCATOR
+# define BOOST_NO_CXX11_SMART_PTR
+# define BOOST_NO_CXX11_HDR_FUNCTIONAL
+# define BOOST_NO_CXX11_STD_ALIGN
+# define BOOST_NO_CXX11_ADDRESSOF
+#endif
+
+//
+// These appear to be unusable/incomplete so far:
+//
+# define BOOST_NO_CXX11_HDR_CHRONO
+# define BOOST_NO_CXX11_HDR_FUTURE
+# define BOOST_NO_CXX11_HDR_TYPE_TRAITS
+# define BOOST_NO_CXX11_ATOMIC_SMART_PTR
+# define BOOST_NO_CXX11_HDR_ATOMIC
+
+// libc++ uses a non-standard messages_base
+#define BOOST_NO_STD_MESSAGES
+
+#if defined(__has_include)
+#if !__has_include(<shared_mutex>)
+# define BOOST_NO_CXX14_HDR_SHARED_MUTEX
+#elif __cplusplus <= 201103
+# define BOOST_NO_CXX14_HDR_SHARED_MUTEX
+#endif
+#elif __cplusplus < 201402
+# define BOOST_NO_CXX14_HDR_SHARED_MUTEX
+#endif
+
+// --- end ---
diff --git a/third_party/boost/boost/config/stdlib/libstdcpp3.hpp b/third_party/boost/boost/config/stdlib/libstdcpp3.hpp
new file mode 100644
index 0000000..bcfa213
--- /dev/null
+++ b/third_party/boost/boost/config/stdlib/libstdcpp3.hpp
@@ -0,0 +1,281 @@
+// (C) Copyright John Maddock 2001.
+// (C) Copyright Jens Maurer 2001.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for most recent version.
+
+// config for libstdc++ v3
+// not much to go in here:
+
+#define BOOST_GNU_STDLIB 1
+
+#ifdef __GLIBCXX__
+#define BOOST_STDLIB "GNU libstdc++ version " BOOST_STRINGIZE(__GLIBCXX__)
+#else
+#define BOOST_STDLIB "GNU libstdc++ version " BOOST_STRINGIZE(__GLIBCPP__)
+#endif
+
+#if !defined(_GLIBCPP_USE_WCHAR_T) && !defined(_GLIBCXX_USE_WCHAR_T)
+# define BOOST_NO_CWCHAR
+# define BOOST_NO_CWCTYPE
+# define BOOST_NO_STD_WSTRING
+# define BOOST_NO_STD_WSTREAMBUF
+#endif
+
+#if defined(__osf__) && !defined(_REENTRANT) \
+ && ( defined(_GLIBCXX_HAVE_GTHR_DEFAULT) || defined(_GLIBCPP_HAVE_GTHR_DEFAULT) )
+// GCC 3 on Tru64 forces the definition of _REENTRANT when any std lib header
+// file is included, therefore for consistency we define it here as well.
+# define _REENTRANT
+#endif
+
+#ifdef __GLIBCXX__ // gcc 3.4 and greater:
+# if defined(_GLIBCXX_HAVE_GTHR_DEFAULT) \
+ || defined(_GLIBCXX__PTHREADS) \
+ || defined(_GLIBCXX_HAS_GTHREADS) \
+ || defined(_WIN32) \
+ || defined(_AIX) \
+ || defined(__HAIKU__)
+ //
+ // If the std lib has thread support turned on, then turn it on in Boost
+ // as well. We do this because some gcc-3.4 std lib headers define _REENTANT
+ // while others do not...
+ //
+# define BOOST_HAS_THREADS
+# else
+# define BOOST_DISABLE_THREADS
+# endif
+#elif defined(__GLIBCPP__) \
+ && !defined(_GLIBCPP_HAVE_GTHR_DEFAULT) \
+ && !defined(_GLIBCPP__PTHREADS)
+ // disable thread support if the std lib was built single threaded:
+# define BOOST_DISABLE_THREADS
+#endif
+
+#if (defined(linux) || defined(__linux) || defined(__linux__)) && defined(__arm__) && defined(_GLIBCPP_HAVE_GTHR_DEFAULT)
+// linux on arm apparently doesn't define _REENTRANT
+// so just turn on threading support whenever the std lib is thread safe:
+# define BOOST_HAS_THREADS
+#endif
+
+#if !defined(_GLIBCPP_USE_LONG_LONG) \
+ && !defined(_GLIBCXX_USE_LONG_LONG)\
+ && defined(BOOST_HAS_LONG_LONG)
+// May have been set by compiler/*.hpp, but "long long" without library
+// support is useless.
+# undef BOOST_HAS_LONG_LONG
+#endif
+
+// Apple doesn't seem to reliably defined a *unix* macro
+#if !defined(CYGWIN) && ( defined(__unix__) \
+ || defined(__unix) \
+ || defined(unix) \
+ || defined(__APPLE__) \
+ || defined(__APPLE) \
+ || defined(APPLE))
+# include <unistd.h>
+#endif
+
+#if defined(__GLIBCXX__) || (defined(__GLIBCPP__) && __GLIBCPP__>=20020514) // GCC >= 3.1.0
+# define BOOST_STD_EXTENSION_NAMESPACE __gnu_cxx
+# define BOOST_HAS_SLIST
+# define BOOST_HAS_HASH
+# define BOOST_SLIST_HEADER <ext/slist>
+# if !defined(__GNUC__) || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3)
+# define BOOST_HASH_SET_HEADER <ext/hash_set>
+# define BOOST_HASH_MAP_HEADER <ext/hash_map>
+# else
+# define BOOST_HASH_SET_HEADER <backward/hash_set>
+# define BOOST_HASH_MAP_HEADER <backward/hash_map>
+# endif
+#endif
+
+//
+// Decide whether we have C++11 support turned on:
+//
+#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103)
+# define BOOST_LIBSTDCXX11
+#endif
+//
+// Decide which version of libstdc++ we have, normally
+// stdlibc++ C++0x support is detected via __GNUC__, __GNUC_MINOR__, and possibly
+// __GNUC_PATCHLEVEL__ at the suggestion of Jonathan Wakely, one of the stdlibc++
+// developers. He also commented:
+//
+// "I'm not sure how useful __GLIBCXX__ is for your purposes, for instance in
+// GCC 4.2.4 it is set to 20080519 but in GCC 4.3.0 it is set to 20080305.
+// Although 4.3.0 was released earlier than 4.2.4, it has better C++0x support
+// than any release in the 4.2 series."
+//
+// Another resource for understanding stdlibc++ features is:
+// http://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#manual.intro.status.standard.200x
+//
+// However, using the GCC version number fails when the compiler is clang since this
+// only ever claims to emulate GCC-4.2, see https://svn.boost.org/trac/boost/ticket/7473
+// for a long discussion on this issue. What we can do though is use clang's __has_include
+// to detect the presence of a C++11 header that was introduced with a specific GCC release.
+// We still have to be careful though as many such headers were buggy and/or incomplete when
+// first introduced, so we only check for headers that were fully featured from day 1, and then
+// use that to infer the underlying GCC version:
+//
+#ifdef __clang__
+
+#if __has_include(<experimental/any>)
+# define BOOST_LIBSTDCXX_VERSION 50100
+#elif __has_include(<shared_mutex>)
+# define BOOST_LIBSTDCXX_VERSION 40900
+#elif __has_include(<ext/cmath>)
+# define BOOST_LIBSTDCXX_VERSION 40800
+#elif __has_include(<scoped_allocator>)
+# define BOOST_LIBSTDCXX_VERSION 40700
+#elif __has_include(<typeindex>)
+# define BOOST_LIBSTDCXX_VERSION 40600
+#elif __has_include(<future>)
+# define BOOST_LIBSTDCXX_VERSION 40500
+#elif __has_include(<ratio>)
+# define BOOST_LIBSTDCXX_VERSION 40400
+#elif __has_include(<array>)
+# define BOOST_LIBSTDCXX_VERSION 40300
+#endif
+//
+// GCC 4.8 and 9 add working versions of <atomic> and <regex> respectively.
+// However, we have no test for these as the headers were present but broken
+// in early GCC versions.
+//
+#endif
+
+#if defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5130) && (__cplusplus >= 201103L)
+//
+// Oracle Solaris compiler uses it's own verison of libstdc++ but doesn't
+// set __GNUC__
+//
+#define BOOST_LIBSTDCXX_VERSION 40800
+#endif
+
+#if !defined(BOOST_LIBSTDCXX_VERSION)
+# define BOOST_LIBSTDCXX_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+#endif
+
+// C++0x headers in GCC 4.3.0 and later
+//
+#if (BOOST_LIBSTDCXX_VERSION < 40300) || !defined(BOOST_LIBSTDCXX11)
+# define BOOST_NO_CXX11_HDR_ARRAY
+# define BOOST_NO_CXX11_HDR_TUPLE
+# define BOOST_NO_CXX11_HDR_UNORDERED_MAP
+# define BOOST_NO_CXX11_HDR_UNORDERED_SET
+# define BOOST_NO_CXX11_HDR_FUNCTIONAL
+#endif
+
+// C++0x headers in GCC 4.4.0 and later
+//
+#if (BOOST_LIBSTDCXX_VERSION < 40400) || !defined(BOOST_LIBSTDCXX11)
+# define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE
+# define BOOST_NO_CXX11_HDR_FORWARD_LIST
+# define BOOST_NO_CXX11_HDR_INITIALIZER_LIST
+# define BOOST_NO_CXX11_HDR_MUTEX
+# define BOOST_NO_CXX11_HDR_RATIO
+# define BOOST_NO_CXX11_HDR_SYSTEM_ERROR
+# define BOOST_NO_CXX11_SMART_PTR
+#else
+# define BOOST_HAS_TR1_COMPLEX_INVERSE_TRIG
+# define BOOST_HAS_TR1_COMPLEX_OVERLOADS
+#endif
+
+// C++0x features in GCC 4.5.0 and later
+//
+#if (BOOST_LIBSTDCXX_VERSION < 40500) || !defined(BOOST_LIBSTDCXX11)
+# define BOOST_NO_CXX11_NUMERIC_LIMITS
+# define BOOST_NO_CXX11_HDR_FUTURE
+# define BOOST_NO_CXX11_HDR_RANDOM
+#endif
+
+// C++0x features in GCC 4.6.0 and later
+//
+#if (BOOST_LIBSTDCXX_VERSION < 40600) || !defined(BOOST_LIBSTDCXX11)
+# define BOOST_NO_CXX11_HDR_TYPEINDEX
+# define BOOST_NO_CXX11_ADDRESSOF
+#endif
+
+// C++0x features in GCC 4.7.0 and later
+//
+#if (BOOST_LIBSTDCXX_VERSION < 40700) || !defined(BOOST_LIBSTDCXX11)
+// Note that although <chrono> existed prior to 4.7, "steady_clock" is spelled "monotonic_clock"
+// so 4.7.0 is the first truely conforming one.
+# define BOOST_NO_CXX11_HDR_CHRONO
+# define BOOST_NO_CXX11_ALLOCATOR
+#endif
+// C++0x features in GCC 4.8.0 and later
+//
+#if (BOOST_LIBSTDCXX_VERSION < 40800) || !defined(BOOST_LIBSTDCXX11)
+// Note that although <atomic> existed prior to gcc 4.8 it was largely unimplemented for many types:
+# define BOOST_NO_CXX11_HDR_ATOMIC
+# define BOOST_NO_CXX11_HDR_THREAD
+#endif
+// C++0x features in GCC 4.9.0 and later
+//
+#if (BOOST_LIBSTDCXX_VERSION < 40900) || !defined(BOOST_LIBSTDCXX11)
+// Although <regex> is present and compilable against, the actual implementation is not functional
+// even for the simplest patterns such as "\d" or "[0-9]". This is the case at least in gcc up to 4.8, inclusively.
+# define BOOST_NO_CXX11_HDR_REGEX
+#endif
+
+#if defined(__clang_major__) && ((__clang_major__ < 3) || ((__clang_major__ == 3) && (__clang_minor__ < 7)))
+// As of clang-3.6, libstdc++ header <atomic> throws up errors with clang:
+# define BOOST_NO_CXX11_HDR_ATOMIC
+#endif
+//
+// C++0x features in GCC 5.1 and later
+//
+#if (BOOST_LIBSTDCXX_VERSION < 50100) || !defined(BOOST_LIBSTDCXX11)
+# define BOOST_NO_CXX11_HDR_TYPE_TRAITS
+# define BOOST_NO_CXX11_HDR_CODECVT
+# define BOOST_NO_CXX11_ATOMIC_SMART_PTR
+# define BOOST_NO_CXX11_STD_ALIGN
+#endif
+
+#if defined(__has_include)
+#if !__has_include(<shared_mutex>)
+# define BOOST_NO_CXX14_HDR_SHARED_MUTEX
+#elif __cplusplus <= 201103
+# define BOOST_NO_CXX14_HDR_SHARED_MUTEX
+#endif
+#elif __cplusplus < 201402 || (BOOST_LIBSTDCXX_VERSION < 40900) || !defined(BOOST_LIBSTDCXX11)
+# define BOOST_NO_CXX14_HDR_SHARED_MUTEX
+#endif
+
+//
+// Headers not present on Solaris with the Oracle compiler:
+#if defined(__SUNPRO_CC)
+#define BOOST_NO_CXX11_HDR_FUTURE
+#define BOOST_NO_CXX11_HDR_FORWARD_LIST
+#define BOOST_NO_CXX11_HDR_ATOMIC
+// shared_ptr is present, but is not convertible to bool
+// which causes all kinds of problems especially in Boost.Thread
+// but probably elsewhere as well.
+#define BOOST_NO_CXX11_SMART_PTR
+#endif
+
+#if (!defined(_GLIBCXX_HAS_GTHREADS) || !defined(_GLIBCXX_USE_C99_STDINT_TR1))
+ // Headers not always available:
+# ifndef BOOST_NO_CXX11_HDR_CONDITION_VARIABLE
+# define BOOST_NO_CXX11_HDR_CONDITION_VARIABLE
+# endif
+# ifndef BOOST_NO_CXX11_HDR_MUTEX
+# define BOOST_NO_CXX11_HDR_MUTEX
+# endif
+# ifndef BOOST_NO_CXX11_HDR_THREAD
+# define BOOST_NO_CXX11_HDR_THREAD
+# endif
+# ifndef BOOST_NO_CXX14_HDR_SHARED_MUTEX
+# define BOOST_NO_CXX14_HDR_SHARED_MUTEX
+# endif
+#endif
+
+#if (!defined(_GTHREAD_USE_MUTEX_TIMEDLOCK) || (_GTHREAD_USE_MUTEX_TIMEDLOCK == 0)) && !defined(BOOST_NO_CXX11_HDR_MUTEX)
+// Timed mutexes are not always available:
+# define BOOST_NO_CXX11_HDR_MUTEX
+#endif
+
+// --- end ---
diff --git a/third_party/boost/boost/config/suffix.hpp b/third_party/boost/boost/config/suffix.hpp
new file mode 100644
index 0000000..b395e37
--- /dev/null
+++ b/third_party/boost/boost/config/suffix.hpp
@@ -0,0 +1,1007 @@
+// Boost config.hpp configuration header file ------------------------------//
+// boostinspect:ndprecated_macros -- tell the inspect tool to ignore this file
+
+// Copyright (c) 2001-2003 John Maddock
+// Copyright (c) 2001 Darin Adler
+// Copyright (c) 2001 Peter Dimov
+// Copyright (c) 2002 Bill Kempf
+// Copyright (c) 2002 Jens Maurer
+// Copyright (c) 2002-2003 David Abrahams
+// Copyright (c) 2003 Gennaro Prota
+// Copyright (c) 2003 Eric Friedman
+// Copyright (c) 2010 Eric Jourdanneau, Joel Falcou
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/ for most recent version.
+
+// Boost config.hpp policy and rationale documentation has been moved to
+// http://www.boost.org/libs/config/
+//
+// This file is intended to be stable, and relatively unchanging.
+// It should contain boilerplate code only - no compiler specific
+// code unless it is unavoidable - no changes unless unavoidable.
+
+#ifndef BOOST_CONFIG_SUFFIX_HPP
+#define BOOST_CONFIG_SUFFIX_HPP
+
+#if defined(__GNUC__) && (__GNUC__ >= 4)
+//
+// Some GCC-4.x versions issue warnings even when __extension__ is used,
+// so use this as a workaround:
+//
+#pragma GCC system_header
+#endif
+
+//
+// ensure that visibility macros are always defined, thus symplifying use
+//
+#ifndef BOOST_SYMBOL_EXPORT
+# define BOOST_SYMBOL_EXPORT
+#endif
+#ifndef BOOST_SYMBOL_IMPORT
+# define BOOST_SYMBOL_IMPORT
+#endif
+#ifndef BOOST_SYMBOL_VISIBLE
+# define BOOST_SYMBOL_VISIBLE
+#endif
+
+//
+// look for long long by looking for the appropriate macros in <limits.h>.
+// Note that we use limits.h rather than climits for maximal portability,
+// remember that since these just declare a bunch of macros, there should be
+// no namespace issues from this.
+//
+#if !defined(BOOST_HAS_LONG_LONG) && !defined(BOOST_NO_LONG_LONG) \
+ && !defined(BOOST_MSVC) && !defined(__BORLANDC__)
+# include <limits.h>
+# if (defined(ULLONG_MAX) || defined(ULONG_LONG_MAX) || defined(ULONGLONG_MAX))
+# define BOOST_HAS_LONG_LONG
+# else
+# define BOOST_NO_LONG_LONG
+# endif
+#endif
+
+// GCC 3.x will clean up all of those nasty macro definitions that
+// BOOST_NO_CTYPE_FUNCTIONS is intended to help work around, so undefine
+// it under GCC 3.x.
+#if defined(__GNUC__) && (__GNUC__ >= 3) && defined(BOOST_NO_CTYPE_FUNCTIONS)
+# undef BOOST_NO_CTYPE_FUNCTIONS
+#endif
+
+//
+// Assume any extensions are in namespace std:: unless stated otherwise:
+//
+# ifndef BOOST_STD_EXTENSION_NAMESPACE
+# define BOOST_STD_EXTENSION_NAMESPACE std
+# endif
+
+//
+// If cv-qualified specializations are not allowed, then neither are cv-void ones:
+//
+# if defined(BOOST_NO_CV_SPECIALIZATIONS) \
+ && !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
+# define BOOST_NO_CV_VOID_SPECIALIZATIONS
+# endif
+
+//
+// If there is no numeric_limits template, then it can't have any compile time
+// constants either!
+//
+# if defined(BOOST_NO_LIMITS) \
+ && !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS)
+# define BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
+# define BOOST_NO_MS_INT64_NUMERIC_LIMITS
+# define BOOST_NO_LONG_LONG_NUMERIC_LIMITS
+# endif
+
+//
+// if there is no long long then there is no specialisation
+// for numeric_limits<long long> either:
+//
+#if !defined(BOOST_HAS_LONG_LONG) && !defined(BOOST_NO_LONG_LONG_NUMERIC_LIMITS)
+# define BOOST_NO_LONG_LONG_NUMERIC_LIMITS
+#endif
+
+//
+// if there is no __int64 then there is no specialisation
+// for numeric_limits<__int64> either:
+//
+#if !defined(BOOST_HAS_MS_INT64) && !defined(BOOST_NO_MS_INT64_NUMERIC_LIMITS)
+# define BOOST_NO_MS_INT64_NUMERIC_LIMITS
+#endif
+
+//
+// if member templates are supported then so is the
+// VC6 subset of member templates:
+//
+# if !defined(BOOST_NO_MEMBER_TEMPLATES) \
+ && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
+# define BOOST_MSVC6_MEMBER_TEMPLATES
+# endif
+
+//
+// Without partial specialization, can't test for partial specialisation bugs:
+//
+# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
+ && !defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG)
+# define BOOST_BCB_PARTIAL_SPECIALIZATION_BUG
+# endif
+
+//
+// Without partial specialization, we can't have array-type partial specialisations:
+//
+# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
+ && !defined(BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS)
+# define BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS
+# endif
+
+//
+// Without partial specialization, std::iterator_traits can't work:
+//
+# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
+ && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
+# define BOOST_NO_STD_ITERATOR_TRAITS
+# endif
+
+//
+// Without partial specialization, partial
+// specialization with default args won't work either:
+//
+# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
+ && !defined(BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS)
+# define BOOST_NO_PARTIAL_SPECIALIZATION_IMPLICIT_DEFAULT_ARGS
+# endif
+
+//
+// Without member template support, we can't have template constructors
+// in the standard library either:
+//
+# if defined(BOOST_NO_MEMBER_TEMPLATES) \
+ && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) \
+ && !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)
+# define BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS
+# endif
+
+//
+// Without member template support, we can't have a conforming
+// std::allocator template either:
+//
+# if defined(BOOST_NO_MEMBER_TEMPLATES) \
+ && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) \
+ && !defined(BOOST_NO_STD_ALLOCATOR)
+# define BOOST_NO_STD_ALLOCATOR
+# endif
+
+//
+// without ADL support then using declarations will break ADL as well:
+//
+#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) && !defined(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL)
+# define BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL
+#endif
+
+//
+// Without typeid support we have no dynamic RTTI either:
+//
+#if defined(BOOST_NO_TYPEID) && !defined(BOOST_NO_RTTI)
+# define BOOST_NO_RTTI
+#endif
+
+//
+// If we have a standard allocator, then we have a partial one as well:
+//
+#if !defined(BOOST_NO_STD_ALLOCATOR)
+# define BOOST_HAS_PARTIAL_STD_ALLOCATOR
+#endif
+
+//
+// We can't have a working std::use_facet if there is no std::locale:
+//
+# if defined(BOOST_NO_STD_LOCALE) && !defined(BOOST_NO_STD_USE_FACET)
+# define BOOST_NO_STD_USE_FACET
+# endif
+
+//
+// We can't have a std::messages facet if there is no std::locale:
+//
+# if defined(BOOST_NO_STD_LOCALE) && !defined(BOOST_NO_STD_MESSAGES)
+# define BOOST_NO_STD_MESSAGES
+# endif
+
+//
+// We can't have a working std::wstreambuf if there is no std::locale:
+//
+# if defined(BOOST_NO_STD_LOCALE) && !defined(BOOST_NO_STD_WSTREAMBUF)
+# define BOOST_NO_STD_WSTREAMBUF
+# endif
+
+//
+// We can't have a <cwctype> if there is no <cwchar>:
+//
+# if defined(BOOST_NO_CWCHAR) && !defined(BOOST_NO_CWCTYPE)
+# define BOOST_NO_CWCTYPE
+# endif
+
+//
+// We can't have a swprintf if there is no <cwchar>:
+//
+# if defined(BOOST_NO_CWCHAR) && !defined(BOOST_NO_SWPRINTF)
+# define BOOST_NO_SWPRINTF
+# endif
+
+//
+// If Win32 support is turned off, then we must turn off
+// threading support also, unless there is some other
+// thread API enabled:
+//
+#if defined(BOOST_DISABLE_WIN32) && defined(_WIN32) \
+ && !defined(BOOST_DISABLE_THREADS) && !defined(BOOST_HAS_PTHREADS)
+# define BOOST_DISABLE_THREADS
+#endif
+
+//
+// Turn on threading support if the compiler thinks that it's in
+// multithreaded mode. We put this here because there are only a
+// limited number of macros that identify this (if there's any missing
+// from here then add to the appropriate compiler section):
+//
+#if (defined(__MT__) || defined(_MT) || defined(_REENTRANT) \
+ || defined(_PTHREADS) || defined(__APPLE__) || defined(__DragonFly__)) \
+ && !defined(BOOST_HAS_THREADS)
+# define BOOST_HAS_THREADS
+#endif
+
+//
+// Turn threading support off if BOOST_DISABLE_THREADS is defined:
+//
+#if defined(BOOST_DISABLE_THREADS) && defined(BOOST_HAS_THREADS)
+# undef BOOST_HAS_THREADS
+#endif
+
+//
+// Turn threading support off if we don't recognise the threading API:
+//
+#if defined(BOOST_HAS_THREADS) && !defined(BOOST_HAS_PTHREADS)\
+ && !defined(BOOST_HAS_WINTHREADS) && !defined(BOOST_HAS_BETHREADS)\
+ && !defined(BOOST_HAS_MPTASKS)
+# undef BOOST_HAS_THREADS
+#endif
+
+//
+// Turn threading detail macros off if we don't (want to) use threading
+//
+#ifndef BOOST_HAS_THREADS
+# undef BOOST_HAS_PTHREADS
+# undef BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE
+# undef BOOST_HAS_PTHREAD_YIELD
+# undef BOOST_HAS_PTHREAD_DELAY_NP
+# undef BOOST_HAS_WINTHREADS
+# undef BOOST_HAS_BETHREADS
+# undef BOOST_HAS_MPTASKS
+#endif
+
+//
+// If the compiler claims to be C99 conformant, then it had better
+// have a <stdint.h>:
+//
+# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
+# define BOOST_HAS_STDINT_H
+# ifndef BOOST_HAS_LOG1P
+# define BOOST_HAS_LOG1P
+# endif
+# ifndef BOOST_HAS_EXPM1
+# define BOOST_HAS_EXPM1
+# endif
+# endif
+
+//
+// Define BOOST_NO_SLIST and BOOST_NO_HASH if required.
+// Note that this is for backwards compatibility only.
+//
+# if !defined(BOOST_HAS_SLIST) && !defined(BOOST_NO_SLIST)
+# define BOOST_NO_SLIST
+# endif
+
+# if !defined(BOOST_HAS_HASH) && !defined(BOOST_NO_HASH)
+# define BOOST_NO_HASH
+# endif
+
+//
+// Set BOOST_SLIST_HEADER if not set already:
+//
+#if defined(BOOST_HAS_SLIST) && !defined(BOOST_SLIST_HEADER)
+# define BOOST_SLIST_HEADER <slist>
+#endif
+
+//
+// Set BOOST_HASH_SET_HEADER if not set already:
+//
+#if defined(BOOST_HAS_HASH) && !defined(BOOST_HASH_SET_HEADER)
+# define BOOST_HASH_SET_HEADER <hash_set>
+#endif
+
+//
+// Set BOOST_HASH_MAP_HEADER if not set already:
+//
+#if defined(BOOST_HAS_HASH) && !defined(BOOST_HASH_MAP_HEADER)
+# define BOOST_HASH_MAP_HEADER <hash_map>
+#endif
+
+// BOOST_HAS_ABI_HEADERS
+// This macro gets set if we have headers that fix the ABI,
+// and prevent ODR violations when linking to external libraries:
+#if defined(BOOST_ABI_PREFIX) && defined(BOOST_ABI_SUFFIX) && !defined(BOOST_HAS_ABI_HEADERS)
+# define BOOST_HAS_ABI_HEADERS
+#endif
+
+#if defined(BOOST_HAS_ABI_HEADERS) && defined(BOOST_DISABLE_ABI_HEADERS)
+# undef BOOST_HAS_ABI_HEADERS
+#endif
+
+// BOOST_NO_STDC_NAMESPACE workaround --------------------------------------//
+// Because std::size_t usage is so common, even in boost headers which do not
+// otherwise use the C library, the <cstddef> workaround is included here so
+// that ugly workaround code need not appear in many other boost headers.
+// NOTE WELL: This is a workaround for non-conforming compilers; <cstddef>
+// must still be #included in the usual places so that <cstddef> inclusion
+// works as expected with standard conforming compilers. The resulting
+// double inclusion of <cstddef> is harmless.
+
+# if defined(BOOST_NO_STDC_NAMESPACE) && defined(__cplusplus)
+# include <cstddef>
+ namespace std { using ::ptrdiff_t; using ::size_t; }
+# endif
+
+// Workaround for the unfortunate min/max macros defined by some platform headers
+
+#define BOOST_PREVENT_MACRO_SUBSTITUTION
+
+#ifndef BOOST_USING_STD_MIN
+# define BOOST_USING_STD_MIN() using std::min
+#endif
+
+#ifndef BOOST_USING_STD_MAX
+# define BOOST_USING_STD_MAX() using std::max
+#endif
+
+// BOOST_NO_STD_MIN_MAX workaround -----------------------------------------//
+
+# if defined(BOOST_NO_STD_MIN_MAX) && defined(__cplusplus)
+
+namespace std {
+ template <class _Tp>
+ inline const _Tp& min BOOST_PREVENT_MACRO_SUBSTITUTION (const _Tp& __a, const _Tp& __b) {
+ return __b < __a ? __b : __a;
+ }
+ template <class _Tp>
+ inline const _Tp& max BOOST_PREVENT_MACRO_SUBSTITUTION (const _Tp& __a, const _Tp& __b) {
+ return __a < __b ? __b : __a;
+ }
+}
+
+# endif
+
+// BOOST_STATIC_CONSTANT workaround --------------------------------------- //
+// On compilers which don't allow in-class initialization of static integral
+// constant members, we must use enums as a workaround if we want the constants
+// to be available at compile-time. This macro gives us a convenient way to
+// declare such constants.
+
+# ifdef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
+# define BOOST_STATIC_CONSTANT(type, assignment) enum { assignment }
+# else
+# define BOOST_STATIC_CONSTANT(type, assignment) static const type assignment
+# endif
+
+// BOOST_USE_FACET / HAS_FACET workaround ----------------------------------//
+// When the standard library does not have a conforming std::use_facet there
+// are various workarounds available, but they differ from library to library.
+// The same problem occurs with has_facet.
+// These macros provide a consistent way to access a locale's facets.
+// Usage:
+// replace
+// std::use_facet<Type>(loc);
+// with
+// BOOST_USE_FACET(Type, loc);
+// Note do not add a std:: prefix to the front of BOOST_USE_FACET!
+// Use for BOOST_HAS_FACET is analogous.
+
+#if defined(BOOST_NO_STD_USE_FACET)
+# ifdef BOOST_HAS_TWO_ARG_USE_FACET
+# define BOOST_USE_FACET(Type, loc) std::use_facet(loc, static_cast<Type*>(0))
+# define BOOST_HAS_FACET(Type, loc) std::has_facet(loc, static_cast<Type*>(0))
+# elif defined(BOOST_HAS_MACRO_USE_FACET)
+# define BOOST_USE_FACET(Type, loc) std::_USE(loc, Type)
+# define BOOST_HAS_FACET(Type, loc) std::_HAS(loc, Type)
+# elif defined(BOOST_HAS_STLP_USE_FACET)
+# define BOOST_USE_FACET(Type, loc) (*std::_Use_facet<Type >(loc))
+# define BOOST_HAS_FACET(Type, loc) std::has_facet< Type >(loc)
+# endif
+#else
+# define BOOST_USE_FACET(Type, loc) std::use_facet< Type >(loc)
+# define BOOST_HAS_FACET(Type, loc) std::has_facet< Type >(loc)
+#endif
+
+// BOOST_NESTED_TEMPLATE workaround ------------------------------------------//
+// Member templates are supported by some compilers even though they can't use
+// the A::template member<U> syntax, as a workaround replace:
+//
+// typedef typename A::template rebind<U> binder;
+//
+// with:
+//
+// typedef typename A::BOOST_NESTED_TEMPLATE rebind<U> binder;
+
+#ifndef BOOST_NO_MEMBER_TEMPLATE_KEYWORD
+# define BOOST_NESTED_TEMPLATE template
+#else
+# define BOOST_NESTED_TEMPLATE
+#endif
+
+// BOOST_UNREACHABLE_RETURN(x) workaround -------------------------------------//
+// Normally evaluates to nothing, unless BOOST_NO_UNREACHABLE_RETURN_DETECTION
+// is defined, in which case it evaluates to return x; Use when you have a return
+// statement that can never be reached.
+
+#ifndef BOOST_UNREACHABLE_RETURN
+# ifdef BOOST_NO_UNREACHABLE_RETURN_DETECTION
+# define BOOST_UNREACHABLE_RETURN(x) return x;
+# else
+# define BOOST_UNREACHABLE_RETURN(x)
+# endif
+#endif
+
+// BOOST_DEDUCED_TYPENAME workaround ------------------------------------------//
+//
+// Some compilers don't support the use of `typename' for dependent
+// types in deduced contexts, e.g.
+//
+// template <class T> void f(T, typename T::type);
+// ^^^^^^^^
+// Replace these declarations with:
+//
+// template <class T> void f(T, BOOST_DEDUCED_TYPENAME T::type);
+
+#ifndef BOOST_NO_DEDUCED_TYPENAME
+# define BOOST_DEDUCED_TYPENAME typename
+#else
+# define BOOST_DEDUCED_TYPENAME
+#endif
+
+#ifndef BOOST_NO_TYPENAME_WITH_CTOR
+# define BOOST_CTOR_TYPENAME typename
+#else
+# define BOOST_CTOR_TYPENAME
+#endif
+
+// long long workaround ------------------------------------------//
+// On gcc (and maybe other compilers?) long long is alway supported
+// but it's use may generate either warnings (with -ansi), or errors
+// (with -pedantic -ansi) unless it's use is prefixed by __extension__
+//
+#if defined(BOOST_HAS_LONG_LONG) && defined(__cplusplus)
+namespace boost{
+# ifdef __GNUC__
+ __extension__ typedef long long long_long_type;
+ __extension__ typedef unsigned long long ulong_long_type;
+# else
+ typedef long long long_long_type;
+ typedef unsigned long long ulong_long_type;
+# endif
+}
+#endif
+// same again for __int128:
+#if defined(BOOST_HAS_INT128) && defined(__cplusplus)
+namespace boost{
+# ifdef __GNUC__
+ __extension__ typedef __int128 int128_type;
+ __extension__ typedef unsigned __int128 uint128_type;
+# else
+ typedef __int128 int128_type;
+ typedef unsigned __int128 uint128_type;
+# endif
+}
+#endif
+// same again for __float128:
+#if defined(BOOST_HAS_FLOAT128) && defined(__cplusplus)
+namespace boost {
+# ifdef __GNUC__
+ __extension__ typedef __float128 float128_type;
+# else
+ typedef __float128 float128_type;
+# endif
+}
+#endif
+
+// BOOST_[APPEND_]EXPLICIT_TEMPLATE_[NON_]TYPE macros --------------------------//
+
+// These macros are obsolete. Port away and remove.
+
+# define BOOST_EXPLICIT_TEMPLATE_TYPE(t)
+# define BOOST_EXPLICIT_TEMPLATE_TYPE_SPEC(t)
+# define BOOST_EXPLICIT_TEMPLATE_NON_TYPE(t, v)
+# define BOOST_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v)
+
+# define BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(t)
+# define BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(t)
+# define BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE(t, v)
+# define BOOST_APPEND_EXPLICIT_TEMPLATE_NON_TYPE_SPEC(t, v)
+
+// When BOOST_NO_STD_TYPEINFO is defined, we can just import
+// the global definition into std namespace:
+#if defined(BOOST_NO_STD_TYPEINFO) && defined(__cplusplus)
+#include <typeinfo>
+namespace std{ using ::type_info; }
+#endif
+
+// ---------------------------------------------------------------------------//
+
+//
+// Helper macro BOOST_STRINGIZE:
+// Converts the parameter X to a string after macro replacement
+// on X has been performed.
+//
+#define BOOST_STRINGIZE(X) BOOST_DO_STRINGIZE(X)
+#define BOOST_DO_STRINGIZE(X) #X
+
+//
+// Helper macro BOOST_JOIN:
+// The following piece of macro magic joins the two
+// arguments together, even when one of the arguments is
+// itself a macro (see 16.3.1 in C++ standard). The key
+// is that macro expansion of macro arguments does not
+// occur in BOOST_DO_JOIN2 but does in BOOST_DO_JOIN.
+//
+#define BOOST_JOIN( X, Y ) BOOST_DO_JOIN( X, Y )
+#define BOOST_DO_JOIN( X, Y ) BOOST_DO_JOIN2(X,Y)
+#define BOOST_DO_JOIN2( X, Y ) X##Y
+
+//
+// Set some default values for compiler/library/platform names.
+// These are for debugging config setup only:
+//
+# ifndef BOOST_COMPILER
+# define BOOST_COMPILER "Unknown ISO C++ Compiler"
+# endif
+# ifndef BOOST_STDLIB
+# define BOOST_STDLIB "Unknown ISO standard library"
+# endif
+# ifndef BOOST_PLATFORM
+# if defined(unix) || defined(__unix) || defined(_XOPEN_SOURCE) \
+ || defined(_POSIX_SOURCE)
+# define BOOST_PLATFORM "Generic Unix"
+# else
+# define BOOST_PLATFORM "Unknown"
+# endif
+# endif
+
+//
+// Set some default values GPU support
+//
+# ifndef BOOST_GPU_ENABLED
+# define BOOST_GPU_ENABLED
+# endif
+
+// BOOST_FORCEINLINE ---------------------------------------------//
+// Macro to use in place of 'inline' to force a function to be inline
+#if !defined(BOOST_FORCEINLINE)
+# if defined(_MSC_VER)
+# define BOOST_FORCEINLINE __forceinline
+# elif defined(__GNUC__) && __GNUC__ > 3
+ // Clang also defines __GNUC__ (as 4)
+# define BOOST_FORCEINLINE inline __attribute__ ((__always_inline__))
+# else
+# define BOOST_FORCEINLINE inline
+# endif
+#endif
+
+// BOOST_NOINLINE ---------------------------------------------//
+// Macro to use in place of 'inline' to prevent a function to be inlined
+#if !defined(BOOST_NOINLINE)
+# if defined(_MSC_VER)
+# define BOOST_NOINLINE __declspec(noinline)
+# elif defined(__GNUC__) && __GNUC__ > 3
+ // Clang also defines __GNUC__ (as 4)
+# if defined(__CUDACC__)
+ // nvcc doesn't always parse __noinline__,
+ // see: https://svn.boost.org/trac/boost/ticket/9392
+# define BOOST_NOINLINE __attribute__ ((noinline))
+# else
+# define BOOST_NOINLINE __attribute__ ((__noinline__))
+# endif
+# else
+# define BOOST_NOINLINE
+# endif
+#endif
+
+// BOOST_NORETURN ---------------------------------------------//
+// Macro to use before a function declaration/definition to designate
+// the function as not returning normally (i.e. with a return statement
+// or by leaving the function scope, if the function return type is void).
+#if !defined(BOOST_NORETURN)
+# if defined(_MSC_VER)
+# define BOOST_NORETURN __declspec(noreturn)
+# elif defined(__GNUC__)
+# define BOOST_NORETURN __attribute__ ((__noreturn__))
+# else
+# define BOOST_NO_NORETURN
+# define BOOST_NORETURN
+# endif
+#endif
+
+// Branch prediction hints
+// These macros are intended to wrap conditional expressions that yield true or false
+//
+// if (BOOST_LIKELY(var == 10))
+// {
+// // the most probable code here
+// }
+//
+#if !defined(BOOST_LIKELY)
+# define BOOST_LIKELY(x) x
+#endif
+#if !defined(BOOST_UNLIKELY)
+# define BOOST_UNLIKELY(x) x
+#endif
+
+// Type and data alignment specification
+//
+#if !defined(BOOST_NO_CXX11_ALIGNAS)
+# define BOOST_ALIGNMENT(x) alignas(x)
+#elif defined(_MSC_VER)
+# define BOOST_ALIGNMENT(x) __declspec(align(x))
+#elif defined(__GNUC__)
+# define BOOST_ALIGNMENT(x) __attribute__ ((__aligned__(x)))
+#else
+# define BOOST_NO_ALIGNMENT
+# define BOOST_ALIGNMENT(x)
+#endif
+
+// Lack of non-public defaulted functions is implied by the lack of any defaulted functions
+#if !defined(BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS) && defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
+# define BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS
+#endif
+
+// Defaulted and deleted function declaration helpers
+// These macros are intended to be inside a class definition.
+// BOOST_DEFAULTED_FUNCTION accepts the function declaration and its
+// body, which will be used if the compiler doesn't support defaulted functions.
+// BOOST_DELETED_FUNCTION only accepts the function declaration. It
+// will expand to a private function declaration, if the compiler doesn't support
+// deleted functions. Because of this it is recommended to use BOOST_DELETED_FUNCTION
+// in the end of the class definition.
+//
+// class my_class
+// {
+// public:
+// // Default-constructible
+// BOOST_DEFAULTED_FUNCTION(my_class(), {})
+// // Copying prohibited
+// BOOST_DELETED_FUNCTION(my_class(my_class const&))
+// BOOST_DELETED_FUNCTION(my_class& operator= (my_class const&))
+// };
+//
+#if !(defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || defined(BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS))
+# define BOOST_DEFAULTED_FUNCTION(fun, body) fun = default;
+#else
+# define BOOST_DEFAULTED_FUNCTION(fun, body) fun body
+#endif
+
+#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
+# define BOOST_DELETED_FUNCTION(fun) fun = delete;
+#else
+# define BOOST_DELETED_FUNCTION(fun) private: fun;
+#endif
+
+//
+// Set BOOST_NO_DECLTYPE_N3276 when BOOST_NO_DECLTYPE is defined
+//
+#if defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
+#define BOOST_NO_CXX11_DECLTYPE_N3276 BOOST_NO_CXX11_DECLTYPE
+#endif
+
+// -------------------- Deprecated macros for 1.50 ---------------------------
+// These will go away in a future release
+
+// Use BOOST_NO_CXX11_HDR_UNORDERED_SET or BOOST_NO_CXX11_HDR_UNORDERED_MAP
+// instead of BOOST_NO_STD_UNORDERED
+#if defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP) || defined (BOOST_NO_CXX11_HDR_UNORDERED_SET)
+# ifndef BOOST_NO_CXX11_STD_UNORDERED
+# define BOOST_NO_CXX11_STD_UNORDERED
+# endif
+#endif
+
+// Use BOOST_NO_CXX11_HDR_INITIALIZER_LIST instead of BOOST_NO_INITIALIZER_LISTS
+#if defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) && !defined(BOOST_NO_INITIALIZER_LISTS)
+# define BOOST_NO_INITIALIZER_LISTS
+#endif
+
+// Use BOOST_NO_CXX11_HDR_ARRAY instead of BOOST_NO_0X_HDR_ARRAY
+#if defined(BOOST_NO_CXX11_HDR_ARRAY) && !defined(BOOST_NO_0X_HDR_ARRAY)
+# define BOOST_NO_0X_HDR_ARRAY
+#endif
+// Use BOOST_NO_CXX11_HDR_CHRONO instead of BOOST_NO_0X_HDR_CHRONO
+#if defined(BOOST_NO_CXX11_HDR_CHRONO) && !defined(BOOST_NO_0X_HDR_CHRONO)
+# define BOOST_NO_0X_HDR_CHRONO
+#endif
+// Use BOOST_NO_CXX11_HDR_CODECVT instead of BOOST_NO_0X_HDR_CODECVT
+#if defined(BOOST_NO_CXX11_HDR_CODECVT) && !defined(BOOST_NO_0X_HDR_CODECVT)
+# define BOOST_NO_0X_HDR_CODECVT
+#endif
+// Use BOOST_NO_CXX11_HDR_CONDITION_VARIABLE instead of BOOST_NO_0X_HDR_CONDITION_VARIABLE
+#if defined(BOOST_NO_CXX11_HDR_CONDITION_VARIABLE) && !defined(BOOST_NO_0X_HDR_CONDITION_VARIABLE)
+# define BOOST_NO_0X_HDR_CONDITION_VARIABLE
+#endif
+// Use BOOST_NO_CXX11_HDR_FORWARD_LIST instead of BOOST_NO_0X_HDR_FORWARD_LIST
+#if defined(BOOST_NO_CXX11_HDR_FORWARD_LIST) && !defined(BOOST_NO_0X_HDR_FORWARD_LIST)
+# define BOOST_NO_0X_HDR_FORWARD_LIST
+#endif
+// Use BOOST_NO_CXX11_HDR_FUTURE instead of BOOST_NO_0X_HDR_FUTURE
+#if defined(BOOST_NO_CXX11_HDR_FUTURE) && !defined(BOOST_NO_0X_HDR_FUTURE)
+# define BOOST_NO_0X_HDR_FUTURE
+#endif
+
+// Use BOOST_NO_CXX11_HDR_INITIALIZER_LIST
+// instead of BOOST_NO_0X_HDR_INITIALIZER_LIST or BOOST_NO_INITIALIZER_LISTS
+#ifdef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
+# ifndef BOOST_NO_0X_HDR_INITIALIZER_LIST
+# define BOOST_NO_0X_HDR_INITIALIZER_LIST
+# endif
+# ifndef BOOST_NO_INITIALIZER_LISTS
+# define BOOST_NO_INITIALIZER_LISTS
+# endif
+#endif
+
+// Use BOOST_NO_CXX11_HDR_MUTEX instead of BOOST_NO_0X_HDR_MUTEX
+#if defined(BOOST_NO_CXX11_HDR_MUTEX) && !defined(BOOST_NO_0X_HDR_MUTEX)
+# define BOOST_NO_0X_HDR_MUTEX
+#endif
+// Use BOOST_NO_CXX11_HDR_RANDOM instead of BOOST_NO_0X_HDR_RANDOM
+#if defined(BOOST_NO_CXX11_HDR_RANDOM) && !defined(BOOST_NO_0X_HDR_RANDOM)
+# define BOOST_NO_0X_HDR_RANDOM
+#endif
+// Use BOOST_NO_CXX11_HDR_RATIO instead of BOOST_NO_0X_HDR_RATIO
+#if defined(BOOST_NO_CXX11_HDR_RATIO) && !defined(BOOST_NO_0X_HDR_RATIO)
+# define BOOST_NO_0X_HDR_RATIO
+#endif
+// Use BOOST_NO_CXX11_HDR_REGEX instead of BOOST_NO_0X_HDR_REGEX
+#if defined(BOOST_NO_CXX11_HDR_REGEX) && !defined(BOOST_NO_0X_HDR_REGEX)
+# define BOOST_NO_0X_HDR_REGEX
+#endif
+// Use BOOST_NO_CXX11_HDR_SYSTEM_ERROR instead of BOOST_NO_0X_HDR_SYSTEM_ERROR
+#if defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR) && !defined(BOOST_NO_0X_HDR_SYSTEM_ERROR)
+# define BOOST_NO_0X_HDR_SYSTEM_ERROR
+#endif
+// Use BOOST_NO_CXX11_HDR_THREAD instead of BOOST_NO_0X_HDR_THREAD
+#if defined(BOOST_NO_CXX11_HDR_THREAD) && !defined(BOOST_NO_0X_HDR_THREAD)
+# define BOOST_NO_0X_HDR_THREAD
+#endif
+// Use BOOST_NO_CXX11_HDR_TUPLE instead of BOOST_NO_0X_HDR_TUPLE
+#if defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_0X_HDR_TUPLE)
+# define BOOST_NO_0X_HDR_TUPLE
+#endif
+// Use BOOST_NO_CXX11_HDR_TYPE_TRAITS instead of BOOST_NO_0X_HDR_TYPE_TRAITS
+#if defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) && !defined(BOOST_NO_0X_HDR_TYPE_TRAITS)
+# define BOOST_NO_0X_HDR_TYPE_TRAITS
+#endif
+// Use BOOST_NO_CXX11_HDR_TYPEINDEX instead of BOOST_NO_0X_HDR_TYPEINDEX
+#if defined(BOOST_NO_CXX11_HDR_TYPEINDEX) && !defined(BOOST_NO_0X_HDR_TYPEINDEX)
+# define BOOST_NO_0X_HDR_TYPEINDEX
+#endif
+// Use BOOST_NO_CXX11_HDR_UNORDERED_MAP instead of BOOST_NO_0X_HDR_UNORDERED_MAP
+#if defined(BOOST_NO_CXX11_HDR_UNORDERED_MAP) && !defined(BOOST_NO_0X_HDR_UNORDERED_MAP)
+# define BOOST_NO_0X_HDR_UNORDERED_MAP
+#endif
+// Use BOOST_NO_CXX11_HDR_UNORDERED_SET instead of BOOST_NO_0X_HDR_UNORDERED_SET
+#if defined(BOOST_NO_CXX11_HDR_UNORDERED_SET) && !defined(BOOST_NO_0X_HDR_UNORDERED_SET)
+# define BOOST_NO_0X_HDR_UNORDERED_SET
+#endif
+
+// ------------------ End of deprecated macros for 1.50 ---------------------------
+
+// -------------------- Deprecated macros for 1.51 ---------------------------
+// These will go away in a future release
+
+// Use BOOST_NO_CXX11_AUTO_DECLARATIONS instead of BOOST_NO_AUTO_DECLARATIONS
+#if defined(BOOST_NO_CXX11_AUTO_DECLARATIONS) && !defined(BOOST_NO_AUTO_DECLARATIONS)
+# define BOOST_NO_AUTO_DECLARATIONS
+#endif
+// Use BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS instead of BOOST_NO_AUTO_MULTIDECLARATIONS
+#if defined(BOOST_NO_CXX11_AUTO_MULTIDECLARATIONS) && !defined(BOOST_NO_AUTO_MULTIDECLARATIONS)
+# define BOOST_NO_AUTO_MULTIDECLARATIONS
+#endif
+// Use BOOST_NO_CXX11_CHAR16_T instead of BOOST_NO_CHAR16_T
+#if defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CHAR16_T)
+# define BOOST_NO_CHAR16_T
+#endif
+// Use BOOST_NO_CXX11_CHAR32_T instead of BOOST_NO_CHAR32_T
+#if defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CHAR32_T)
+# define BOOST_NO_CHAR32_T
+#endif
+// Use BOOST_NO_CXX11_TEMPLATE_ALIASES instead of BOOST_NO_TEMPLATE_ALIASES
+#if defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) && !defined(BOOST_NO_TEMPLATE_ALIASES)
+# define BOOST_NO_TEMPLATE_ALIASES
+#endif
+// Use BOOST_NO_CXX11_CONSTEXPR instead of BOOST_NO_CONSTEXPR
+#if defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CONSTEXPR)
+# define BOOST_NO_CONSTEXPR
+#endif
+// Use BOOST_NO_CXX11_DECLTYPE_N3276 instead of BOOST_NO_DECLTYPE_N3276
+#if defined(BOOST_NO_CXX11_DECLTYPE_N3276) && !defined(BOOST_NO_DECLTYPE_N3276)
+# define BOOST_NO_DECLTYPE_N3276
+#endif
+// Use BOOST_NO_CXX11_DECLTYPE instead of BOOST_NO_DECLTYPE
+#if defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_DECLTYPE)
+# define BOOST_NO_DECLTYPE
+#endif
+// Use BOOST_NO_CXX11_DEFAULTED_FUNCTIONS instead of BOOST_NO_DEFAULTED_FUNCTIONS
+#if defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) && !defined(BOOST_NO_DEFAULTED_FUNCTIONS)
+# define BOOST_NO_DEFAULTED_FUNCTIONS
+#endif
+// Use BOOST_NO_CXX11_DELETED_FUNCTIONS instead of BOOST_NO_DELETED_FUNCTIONS
+#if defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) && !defined(BOOST_NO_DELETED_FUNCTIONS)
+# define BOOST_NO_DELETED_FUNCTIONS
+#endif
+// Use BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS instead of BOOST_NO_EXPLICIT_CONVERSION_OPERATORS
+#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) && !defined(BOOST_NO_EXPLICIT_CONVERSION_OPERATORS)
+# define BOOST_NO_EXPLICIT_CONVERSION_OPERATORS
+#endif
+// Use BOOST_NO_CXX11_EXTERN_TEMPLATE instead of BOOST_NO_EXTERN_TEMPLATE
+#if defined(BOOST_NO_CXX11_EXTERN_TEMPLATE) && !defined(BOOST_NO_EXTERN_TEMPLATE)
+# define BOOST_NO_EXTERN_TEMPLATE
+#endif
+// Use BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS instead of BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS
+#if defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) && !defined(BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS)
+# define BOOST_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS
+#endif
+// Use BOOST_NO_CXX11_LAMBDAS instead of BOOST_NO_LAMBDAS
+#if defined(BOOST_NO_CXX11_LAMBDAS) && !defined(BOOST_NO_LAMBDAS)
+# define BOOST_NO_LAMBDAS
+#endif
+// Use BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS instead of BOOST_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS
+#if defined(BOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS) && !defined(BOOST_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS)
+# define BOOST_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS
+#endif
+// Use BOOST_NO_CXX11_NOEXCEPT instead of BOOST_NO_NOEXCEPT
+#if defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_NOEXCEPT)
+# define BOOST_NO_NOEXCEPT
+#endif
+// Use BOOST_NO_CXX11_NULLPTR instead of BOOST_NO_NULLPTR
+#if defined(BOOST_NO_CXX11_NULLPTR) && !defined(BOOST_NO_NULLPTR)
+# define BOOST_NO_NULLPTR
+#endif
+// Use BOOST_NO_CXX11_RAW_LITERALS instead of BOOST_NO_RAW_LITERALS
+#if defined(BOOST_NO_CXX11_RAW_LITERALS) && !defined(BOOST_NO_RAW_LITERALS)
+# define BOOST_NO_RAW_LITERALS
+#endif
+// Use BOOST_NO_CXX11_RVALUE_REFERENCES instead of BOOST_NO_RVALUE_REFERENCES
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_RVALUE_REFERENCES)
+# define BOOST_NO_RVALUE_REFERENCES
+#endif
+// Use BOOST_NO_CXX11_SCOPED_ENUMS instead of BOOST_NO_SCOPED_ENUMS
+#if defined(BOOST_NO_CXX11_SCOPED_ENUMS) && !defined(BOOST_NO_SCOPED_ENUMS)
+# define BOOST_NO_SCOPED_ENUMS
+#endif
+// Use BOOST_NO_CXX11_STATIC_ASSERT instead of BOOST_NO_STATIC_ASSERT
+#if defined(BOOST_NO_CXX11_STATIC_ASSERT) && !defined(BOOST_NO_STATIC_ASSERT)
+# define BOOST_NO_STATIC_ASSERT
+#endif
+// Use BOOST_NO_CXX11_STD_UNORDERED instead of BOOST_NO_STD_UNORDERED
+#if defined(BOOST_NO_CXX11_STD_UNORDERED) && !defined(BOOST_NO_STD_UNORDERED)
+# define BOOST_NO_STD_UNORDERED
+#endif
+// Use BOOST_NO_CXX11_UNICODE_LITERALS instead of BOOST_NO_UNICODE_LITERALS
+#if defined(BOOST_NO_CXX11_UNICODE_LITERALS) && !defined(BOOST_NO_UNICODE_LITERALS)
+# define BOOST_NO_UNICODE_LITERALS
+#endif
+// Use BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX instead of BOOST_NO_UNIFIED_INITIALIZATION_SYNTAX
+#if defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) && !defined(BOOST_NO_UNIFIED_INITIALIZATION_SYNTAX)
+# define BOOST_NO_UNIFIED_INITIALIZATION_SYNTAX
+#endif
+// Use BOOST_NO_CXX11_VARIADIC_TEMPLATES instead of BOOST_NO_VARIADIC_TEMPLATES
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
+# define BOOST_NO_VARIADIC_TEMPLATES
+#endif
+// Use BOOST_NO_CXX11_VARIADIC_MACROS instead of BOOST_NO_VARIADIC_MACROS
+#if defined(BOOST_NO_CXX11_VARIADIC_MACROS) && !defined(BOOST_NO_VARIADIC_MACROS)
+# define BOOST_NO_VARIADIC_MACROS
+#endif
+// Use BOOST_NO_CXX11_NUMERIC_LIMITS instead of BOOST_NO_NUMERIC_LIMITS_LOWEST
+#if defined(BOOST_NO_CXX11_NUMERIC_LIMITS) && !defined(BOOST_NO_NUMERIC_LIMITS_LOWEST)
+# define BOOST_NO_NUMERIC_LIMITS_LOWEST
+#endif
+// ------------------ End of deprecated macros for 1.51 ---------------------------
+
+
+
+//
+// Helper macros BOOST_NOEXCEPT, BOOST_NOEXCEPT_IF, BOOST_NOEXCEPT_EXPR
+// These aid the transition to C++11 while still supporting C++03 compilers
+//
+#ifdef BOOST_NO_CXX11_NOEXCEPT
+# define BOOST_NOEXCEPT
+# define BOOST_NOEXCEPT_OR_NOTHROW throw()
+# define BOOST_NOEXCEPT_IF(Predicate)
+# define BOOST_NOEXCEPT_EXPR(Expression) false
+#else
+# define BOOST_NOEXCEPT noexcept
+# define BOOST_NOEXCEPT_OR_NOTHROW noexcept
+# define BOOST_NOEXCEPT_IF(Predicate) noexcept((Predicate))
+# define BOOST_NOEXCEPT_EXPR(Expression) noexcept((Expression))
+#endif
+//
+// Helper macro BOOST_FALLTHROUGH
+// Fallback definition of BOOST_FALLTHROUGH macro used to mark intended
+// fall-through between case labels in a switch statement. We use a definition
+// that requires a semicolon after it to avoid at least one type of misuse even
+// on unsupported compilers.
+//
+#ifndef BOOST_FALLTHROUGH
+# define BOOST_FALLTHROUGH ((void)0)
+#endif
+
+//
+// constexpr workarounds
+//
+#if defined(BOOST_NO_CXX11_CONSTEXPR)
+#define BOOST_CONSTEXPR
+#define BOOST_CONSTEXPR_OR_CONST const
+#else
+#define BOOST_CONSTEXPR constexpr
+#define BOOST_CONSTEXPR_OR_CONST constexpr
+#endif
+#if defined(BOOST_NO_CXX14_CONSTEXPR)
+#define BOOST_CXX14_CONSTEXPR
+#else
+#define BOOST_CXX14_CONSTEXPR constexpr
+#endif
+
+//
+// Unused variable/typedef workarounds:
+//
+#ifndef BOOST_ATTRIBUTE_UNUSED
+# define BOOST_ATTRIBUTE_UNUSED
+#endif
+
+#define BOOST_STATIC_CONSTEXPR static BOOST_CONSTEXPR_OR_CONST
+
+//
+// Set BOOST_HAS_STATIC_ASSERT when BOOST_NO_CXX11_STATIC_ASSERT is not defined
+//
+#if !defined(BOOST_NO_CXX11_STATIC_ASSERT) && !defined(BOOST_HAS_STATIC_ASSERT)
+# define BOOST_HAS_STATIC_ASSERT
+#endif
+
+//
+// Set BOOST_HAS_RVALUE_REFS when BOOST_NO_CXX11_RVALUE_REFERENCES is not defined
+//
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_HAS_RVALUE_REFS)
+#define BOOST_HAS_RVALUE_REFS
+#endif
+
+//
+// Set BOOST_HAS_VARIADIC_TMPL when BOOST_NO_CXX11_VARIADIC_TEMPLATES is not defined
+//
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_HAS_VARIADIC_TMPL)
+#define BOOST_HAS_VARIADIC_TMPL
+#endif
+//
+// Set BOOST_NO_CXX11_FIXED_LENGTH_VARIADIC_TEMPLATE_EXPANSION_PACKS when
+// BOOST_NO_CXX11_VARIADIC_TEMPLATES is set:
+//
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_FIXED_LENGTH_VARIADIC_TEMPLATE_EXPANSION_PACKS)
+# define BOOST_NO_CXX11_FIXED_LENGTH_VARIADIC_TEMPLATE_EXPANSION_PACKS
+#endif
+
+//
+// Finish off with checks for macros that are depricated / no longer supported,
+// if any of these are set then it's very likely that much of Boost will no
+// longer work. So stop with a #error for now, but give the user a chance
+// to continue at their own risk if they really want to:
+//
+#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_CONFIG_ALLOW_DEPRECATED)
+# error "You are using a compiler which lacks features which are now a minimum requirement in order to use Boost, define BOOST_CONFIG_ALLOW_DEPRECATED if you want to continue at your own risk!!!"
+#endif
+
+#endif
diff --git a/third_party/boost/boost/config/user.hpp b/third_party/boost/boost/config/user.hpp
new file mode 100644
index 0000000..e5ce1a1
--- /dev/null
+++ b/third_party/boost/boost/config/user.hpp
@@ -0,0 +1,132 @@
+// boost/config/user.hpp ---------------------------------------------------//
+
+// (C) Copyright John Maddock 2001.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Do not check in modified versions of this file,
+// This file may be customized by the end user, but not by boost.
+
+//
+// Use this file to define a site and compiler specific
+// configuration policy:
+//
+
+// define this to locate a compiler config file:
+// #define BOOST_COMPILER_CONFIG <myheader>
+
+// define this to locate a stdlib config file:
+// #define BOOST_STDLIB_CONFIG <myheader>
+
+// define this to locate a platform config file:
+// #define BOOST_PLATFORM_CONFIG <myheader>
+
+// define this to disable compiler config,
+// use if your compiler config has nothing to set:
+// #define BOOST_NO_COMPILER_CONFIG
+
+// define this to disable stdlib config,
+// use if your stdlib config has nothing to set:
+// #define BOOST_NO_STDLIB_CONFIG
+
+// define this to disable platform config,
+// use if your platform config has nothing to set:
+// #define BOOST_NO_PLATFORM_CONFIG
+
+// define this to disable all config options,
+// excluding the user config. Use if your
+// setup is fully ISO compliant, and has no
+// useful extensions, or for autoconf generated
+// setups:
+// #define BOOST_NO_CONFIG
+
+// define this to make the config "optimistic"
+// about unknown compiler versions. Normally
+// unknown compiler versions are assumed to have
+// all the defects of the last known version, however
+// setting this flag, causes the config to assume
+// that unknown compiler versions are fully conformant
+// with the standard:
+// #define BOOST_STRICT_CONFIG
+
+// define this to cause the config to halt compilation
+// with an #error if it encounters anything unknown --
+// either an unknown compiler version or an unknown
+// compiler/platform/library:
+// #define BOOST_ASSERT_CONFIG
+
+
+// define if you want to disable threading support, even
+// when available:
+// #define BOOST_DISABLE_THREADS
+
+// define when you want to disable Win32 specific features
+// even when available:
+// #define BOOST_DISABLE_WIN32
+
+// BOOST_DISABLE_ABI_HEADERS: Stops boost headers from including any
+// prefix/suffix headers that normally control things like struct
+// packing and alignment.
+// #define BOOST_DISABLE_ABI_HEADERS
+
+// BOOST_ABI_PREFIX: A prefix header to include in place of whatever
+// boost.config would normally select, any replacement should set up
+// struct packing and alignment options as required.
+// #define BOOST_ABI_PREFIX my-header-name
+
+// BOOST_ABI_SUFFIX: A suffix header to include in place of whatever
+// boost.config would normally select, any replacement should undo
+// the effects of the prefix header.
+// #define BOOST_ABI_SUFFIX my-header-name
+
+// BOOST_ALL_DYN_LINK: Forces all libraries that have separate source,
+// to be linked as dll's rather than static libraries on Microsoft Windows
+// (this macro is used to turn on __declspec(dllimport) modifiers, so that
+// the compiler knows which symbols to look for in a dll rather than in a
+// static library). Note that there may be some libraries that can only
+// be linked in one way (statically or dynamically), in these cases this
+// macro has no effect.
+// #define BOOST_ALL_DYN_LINK
+
+// BOOST_WHATEVER_DYN_LINK: Forces library "whatever" to be linked as a dll
+// rather than a static library on Microsoft Windows: replace the WHATEVER
+// part of the macro name with the name of the library that you want to
+// dynamically link to, for example use BOOST_DATE_TIME_DYN_LINK or
+// BOOST_REGEX_DYN_LINK etc (this macro is used to turn on __declspec(dllimport)
+// modifiers, so that the compiler knows which symbols to look for in a dll
+// rather than in a static library).
+// Note that there may be some libraries that can only
+// be linked in one way (statically or dynamically),
+// in these cases this macro is unsupported.
+// #define BOOST_WHATEVER_DYN_LINK
+
+// BOOST_ALL_NO_LIB: Tells the config system not to automatically select
+// which libraries to link against.
+// Normally if a compiler supports #pragma lib, then the correct library
+// build variant will be automatically selected and linked against,
+// simply by the act of including one of that library's headers.
+// This macro turns that feature off.
+// #define BOOST_ALL_NO_LIB
+
+// BOOST_WHATEVER_NO_LIB: Tells the config system not to automatically
+// select which library to link against for library "whatever",
+// replace WHATEVER in the macro name with the name of the library;
+// for example BOOST_DATE_TIME_NO_LIB or BOOST_REGEX_NO_LIB.
+// Normally if a compiler supports #pragma lib, then the correct library
+// build variant will be automatically selected and linked against, simply
+// by the act of including one of that library's headers. This macro turns
+// that feature off.
+// #define BOOST_WHATEVER_NO_LIB
+
+// BOOST_LIB_BUILDID: Set to the same value as the value passed to Boost.Build's
+// --buildid command line option. For example if you built using:
+//
+// bjam address-model=64 --buildid=amd64
+//
+// then compile your code with:
+//
+// -DBOOST_LIB_BUILDID = amd64
+//
+// to ensure the correct libraries are selected at link time.
+// #define BOOST_LIB_BUILDID amd64
diff --git a/third_party/boost/boost/core/addressof.hpp b/third_party/boost/boost/core/addressof.hpp
new file mode 100644
index 0000000..889b582
--- /dev/null
+++ b/third_party/boost/boost/core/addressof.hpp
@@ -0,0 +1,162 @@
+// Copyright (C) 2002 Brad King (brad.king@kitware.com)
+// Douglas Gregor (gregod@cs.rpi.edu)
+//
+// Copyright (C) 2002, 2008, 2013 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// For more information, see http://www.boost.org
+
+#ifndef BOOST_CORE_ADDRESSOF_HPP
+#define BOOST_CORE_ADDRESSOF_HPP
+
+# include <boost/config.hpp>
+# include <boost/detail/workaround.hpp>
+# include <cstddef>
+
+namespace boost
+{
+
+namespace detail
+{
+
+template<class T> struct addr_impl_ref
+{
+ T & v_;
+
+ BOOST_FORCEINLINE addr_impl_ref( T & v ): v_( v ) {}
+ BOOST_FORCEINLINE operator T& () const { return v_; }
+
+private:
+ addr_impl_ref & operator=(const addr_impl_ref &);
+};
+
+template<class T> struct addressof_impl
+{
+ static BOOST_FORCEINLINE T * f( T & v, long )
+ {
+ return reinterpret_cast<T*>(
+ &const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
+ }
+
+ static BOOST_FORCEINLINE T * f( T * v, int )
+ {
+ return v;
+ }
+};
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+#if !defined( BOOST_NO_CXX11_DECLTYPE ) && ( ( defined( __clang__ ) && !defined( _LIBCPP_VERSION ) ) || defined( __INTEL_COMPILER ) )
+
+ typedef decltype(nullptr) addr_nullptr_t;
+
+#else
+
+ typedef std::nullptr_t addr_nullptr_t;
+
+#endif
+
+template<> struct addressof_impl< addr_nullptr_t >
+{
+ typedef addr_nullptr_t T;
+
+ static BOOST_FORCEINLINE T * f( T & v, int )
+ {
+ return &v;
+ }
+};
+
+template<> struct addressof_impl< addr_nullptr_t const >
+{
+ typedef addr_nullptr_t const T;
+
+ static BOOST_FORCEINLINE T * f( T & v, int )
+ {
+ return &v;
+ }
+};
+
+template<> struct addressof_impl< addr_nullptr_t volatile >
+{
+ typedef addr_nullptr_t volatile T;
+
+ static BOOST_FORCEINLINE T * f( T & v, int )
+ {
+ return &v;
+ }
+};
+
+template<> struct addressof_impl< addr_nullptr_t const volatile >
+{
+ typedef addr_nullptr_t const volatile T;
+
+ static BOOST_FORCEINLINE T * f( T & v, int )
+ {
+ return &v;
+ }
+};
+
+#endif
+
+} // namespace detail
+
+template<class T>
+BOOST_FORCEINLINE
+T * addressof( T & v )
+{
+#if (defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x610 ) ) ) || (defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5120))
+
+ return boost::detail::addressof_impl<T>::f( v, 0 );
+
+#else
+
+ return boost::detail::addressof_impl<T>::f( boost::detail::addr_impl_ref<T>( v ), 0 );
+
+#endif
+}
+
+#if defined( __SUNPRO_CC ) && BOOST_WORKAROUND( __SUNPRO_CC, BOOST_TESTED_AT( 0x590 ) )
+
+namespace detail
+{
+
+template<class T> struct addressof_addp
+{
+ typedef T * type;
+};
+
+} // namespace detail
+
+template< class T, std::size_t N >
+BOOST_FORCEINLINE
+typename detail::addressof_addp< T[N] >::type addressof( T (&t)[N] )
+{
+ return &t;
+}
+
+#endif
+
+// Borland doesn't like casting an array reference to a char reference
+// but these overloads work around the problem.
+#if defined( __BORLANDC__ ) && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+template<typename T,std::size_t N>
+BOOST_FORCEINLINE
+T (*addressof(T (&t)[N]))[N]
+{
+ return reinterpret_cast<T(*)[N]>(&t);
+}
+
+template<typename T,std::size_t N>
+BOOST_FORCEINLINE
+const T (*addressof(const T (&t)[N]))[N]
+{
+ return reinterpret_cast<const T(*)[N]>(&t);
+}
+#endif
+
+} // namespace boost
+
+#endif // BOOST_CORE_ADDRESSOF_HPP
diff --git a/third_party/boost/boost/core/checked_delete.hpp b/third_party/boost/boost/core/checked_delete.hpp
new file mode 100644
index 0000000..b086e03
--- /dev/null
+++ b/third_party/boost/boost/core/checked_delete.hpp
@@ -0,0 +1,69 @@
+#ifndef BOOST_CORE_CHECKED_DELETE_HPP
+#define BOOST_CORE_CHECKED_DELETE_HPP
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// boost/checked_delete.hpp
+//
+// Copyright (c) 2002, 2003 Peter Dimov
+// Copyright (c) 2003 Daniel Frey
+// Copyright (c) 2003 Howard Hinnant
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/core/doc/html/core/checked_delete.html for documentation.
+//
+
+namespace boost
+{
+
+// verify that types are complete for increased safety
+
+template<class T> inline void checked_delete(T * x)
+{
+ // intentionally complex - simplification causes regressions
+ typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
+ (void) sizeof(type_must_be_complete);
+ delete x;
+}
+
+template<class T> inline void checked_array_delete(T * x)
+{
+ typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
+ (void) sizeof(type_must_be_complete);
+ delete [] x;
+}
+
+template<class T> struct checked_deleter
+{
+ typedef void result_type;
+ typedef T * argument_type;
+
+ void operator()(T * x) const
+ {
+ // boost:: disables ADL
+ boost::checked_delete(x);
+ }
+};
+
+template<class T> struct checked_array_deleter
+{
+ typedef void result_type;
+ typedef T * argument_type;
+
+ void operator()(T * x) const
+ {
+ boost::checked_array_delete(x);
+ }
+};
+
+} // namespace boost
+
+#endif // #ifndef BOOST_CORE_CHECKED_DELETE_HPP
diff --git a/third_party/boost/boost/core/demangle.hpp b/third_party/boost/boost/core/demangle.hpp
new file mode 100644
index 0000000..44aeb8d
--- /dev/null
+++ b/third_party/boost/boost/core/demangle.hpp
@@ -0,0 +1,128 @@
+#ifndef BOOST_CORE_DEMANGLE_HPP_INCLUDED
+#define BOOST_CORE_DEMANGLE_HPP_INCLUDED
+
+// core::demangle
+//
+// Copyright 2014 Peter Dimov
+// Copyright 2014 Andrey Semashev
+//
+// Distributed under the 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>
+#include <string>
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#if defined( __clang__ ) && defined( __has_include )
+# if __has_include(<cxxabi.h>)
+# define BOOST_CORE_HAS_CXXABI_H
+# endif
+#elif defined( __GLIBCXX__ ) || defined( __GLIBCPP__ )
+# define BOOST_CORE_HAS_CXXABI_H
+#endif
+
+#if defined( BOOST_CORE_HAS_CXXABI_H )
+# include <cxxabi.h>
+// For some archtectures (mips, mips64, x86, x86_64) cxxabi.h in Android NDK is implemented by gabi++ library
+// (https://android.googlesource.com/platform/ndk/+/master/sources/cxx-stl/gabi++/), which does not implement
+// abi::__cxa_demangle(). We detect this implementation by checking the include guard here.
+# if defined( __GABIXX_CXXABI_H__ )
+# undef BOOST_CORE_HAS_CXXABI_H
+# else
+# include <cstdlib>
+# include <cstddef>
+# endif
+#endif
+
+namespace boost
+{
+
+namespace core
+{
+
+inline char const * demangle_alloc( char const * name ) BOOST_NOEXCEPT;
+inline void demangle_free( char const * name ) BOOST_NOEXCEPT;
+
+class scoped_demangled_name
+{
+private:
+ char const * m_p;
+
+public:
+ explicit scoped_demangled_name( char const * name ) BOOST_NOEXCEPT :
+ m_p( demangle_alloc( name ) )
+ {
+ }
+
+ ~scoped_demangled_name() BOOST_NOEXCEPT
+ {
+ demangle_free( m_p );
+ }
+
+ char const * get() const BOOST_NOEXCEPT
+ {
+ return m_p;
+ }
+
+ BOOST_DELETED_FUNCTION(scoped_demangled_name( scoped_demangled_name const& ))
+ BOOST_DELETED_FUNCTION(scoped_demangled_name& operator= ( scoped_demangled_name const& ))
+};
+
+
+#if defined( BOOST_CORE_HAS_CXXABI_H )
+
+inline char const * demangle_alloc( char const * name ) BOOST_NOEXCEPT
+{
+ int status = 0;
+ std::size_t size = 0;
+ return abi::__cxa_demangle( name, NULL, &size, &status );
+}
+
+inline void demangle_free( char const * name ) BOOST_NOEXCEPT
+{
+ std::free( const_cast< char* >( name ) );
+}
+
+inline std::string demangle( char const * name )
+{
+ scoped_demangled_name demangled_name( name );
+ char const * const p = demangled_name.get();
+ if( p )
+ {
+ return p;
+ }
+ else
+ {
+ return name;
+ }
+}
+
+#else
+
+inline char const * demangle_alloc( char const * name ) BOOST_NOEXCEPT
+{
+ return name;
+}
+
+inline void demangle_free( char const * ) BOOST_NOEXCEPT
+{
+}
+
+inline std::string demangle( char const * name )
+{
+ return name;
+}
+
+#endif
+
+} // namespace core
+
+} // namespace boost
+
+#undef BOOST_CORE_HAS_CXXABI_H
+
+#endif // #ifndef BOOST_CORE_DEMANGLE_HPP_INCLUDED
diff --git a/third_party/boost/boost/core/enable_if.hpp b/third_party/boost/boost/core/enable_if.hpp
new file mode 100644
index 0000000..b947dab
--- /dev/null
+++ b/third_party/boost/boost/core/enable_if.hpp
@@ -0,0 +1,128 @@
+// Boost enable_if library
+
+// Copyright 2003 (c) The Trustees of Indiana University.
+
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Authors: Jaakko Jarvi (jajarvi at osl.iu.edu)
+// Jeremiah Willcock (jewillco at osl.iu.edu)
+// Andrew Lumsdaine (lums at osl.iu.edu)
+
+
+#ifndef BOOST_CORE_ENABLE_IF_HPP
+#define BOOST_CORE_ENABLE_IF_HPP
+
+#include "boost/config.hpp"
+
+// Even the definition of enable_if causes problems on some compilers,
+// so it's macroed out for all compilers that do not support SFINAE
+
+#ifndef BOOST_NO_SFINAE
+
+namespace boost
+{
+ template<typename T, typename R=void>
+ struct enable_if_has_type
+ {
+ typedef R type;
+ };
+
+ template <bool B, class T = void>
+ struct enable_if_c {
+ typedef T type;
+ };
+
+ template <class T>
+ struct enable_if_c<false, T> {};
+
+ template <class Cond, class T = void>
+ struct enable_if : public enable_if_c<Cond::value, T> {};
+
+ template <bool B, class T>
+ struct lazy_enable_if_c {
+ typedef typename T::type type;
+ };
+
+ template <class T>
+ struct lazy_enable_if_c<false, T> {};
+
+ template <class Cond, class T>
+ struct lazy_enable_if : public lazy_enable_if_c<Cond::value, T> {};
+
+
+ template <bool B, class T = void>
+ struct disable_if_c {
+ typedef T type;
+ };
+
+ template <class T>
+ struct disable_if_c<true, T> {};
+
+ template <class Cond, class T = void>
+ struct disable_if : public disable_if_c<Cond::value, T> {};
+
+ template <bool B, class T>
+ struct lazy_disable_if_c {
+ typedef typename T::type type;
+ };
+
+ template <class T>
+ struct lazy_disable_if_c<true, T> {};
+
+ template <class Cond, class T>
+ struct lazy_disable_if : public lazy_disable_if_c<Cond::value, T> {};
+
+} // namespace boost
+
+#else
+
+namespace boost {
+
+ namespace detail { typedef void enable_if_default_T; }
+
+ template <typename T>
+ struct enable_if_does_not_work_on_this_compiler;
+
+ template<typename T, typename R=void>
+ struct enable_if_has_type : enable_if_does_not_work_on_this_compiler<T>
+ { };
+
+ template <bool B, class T = detail::enable_if_default_T>
+ struct enable_if_c : enable_if_does_not_work_on_this_compiler<T>
+ { };
+
+ template <bool B, class T = detail::enable_if_default_T>
+ struct disable_if_c : enable_if_does_not_work_on_this_compiler<T>
+ { };
+
+ template <bool B, class T = detail::enable_if_default_T>
+ struct lazy_enable_if_c : enable_if_does_not_work_on_this_compiler<T>
+ { };
+
+ template <bool B, class T = detail::enable_if_default_T>
+ struct lazy_disable_if_c : enable_if_does_not_work_on_this_compiler<T>
+ { };
+
+ template <class Cond, class T = detail::enable_if_default_T>
+ struct enable_if : enable_if_does_not_work_on_this_compiler<T>
+ { };
+
+ template <class Cond, class T = detail::enable_if_default_T>
+ struct disable_if : enable_if_does_not_work_on_this_compiler<T>
+ { };
+
+ template <class Cond, class T = detail::enable_if_default_T>
+ struct lazy_enable_if : enable_if_does_not_work_on_this_compiler<T>
+ { };
+
+ template <class Cond, class T = detail::enable_if_default_T>
+ struct lazy_disable_if : enable_if_does_not_work_on_this_compiler<T>
+ { };
+
+} // namespace boost
+
+#endif // BOOST_NO_SFINAE
+
+#endif
diff --git a/third_party/boost/boost/core/explicit_operator_bool.hpp b/third_party/boost/boost/core/explicit_operator_bool.hpp
new file mode 100644
index 0000000..a8936e2
--- /dev/null
+++ b/third_party/boost/boost/core/explicit_operator_bool.hpp
@@ -0,0 +1,154 @@
+/*
+ * Copyright Andrey Semashev 2007 - 2013.
+ * Distributed under the 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 explicit_operator_bool.hpp
+ * \author Andrey Semashev
+ * \date 08.03.2009
+ *
+ * This header defines a compatibility macro that implements an unspecified
+ * \c bool operator idiom, which is superseded with explicit conversion operators in
+ * C++11.
+ */
+
+#ifndef BOOST_CORE_EXPLICIT_OPERATOR_BOOL_HPP
+#define BOOST_CORE_EXPLICIT_OPERATOR_BOOL_HPP
+
+#include <boost/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+#pragma once
+#endif
+
+#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
+
+/*!
+ * \brief The macro defines an explicit operator of conversion to \c bool
+ *
+ * The macro should be used inside the definition of a class that has to
+ * support the conversion. The class should also implement <tt>operator!</tt>,
+ * in terms of which the conversion operator will be implemented.
+ */
+#define BOOST_EXPLICIT_OPERATOR_BOOL()\
+ BOOST_FORCEINLINE explicit operator bool () const\
+ {\
+ return !this->operator! ();\
+ }
+
+/*!
+ * \brief The macro defines a noexcept explicit operator of conversion to \c bool
+ *
+ * The macro should be used inside the definition of a class that has to
+ * support the conversion. The class should also implement <tt>operator!</tt>,
+ * in terms of which the conversion operator will be implemented.
+ */
+#define BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()\
+ BOOST_FORCEINLINE explicit operator bool () const BOOST_NOEXCEPT\
+ {\
+ return !this->operator! ();\
+ }
+
+/*!
+ * \brief The macro defines a constexpr explicit operator of conversion to \c bool
+ *
+ * The macro should be used inside the definition of a class that has to
+ * support the conversion. The class should also implement <tt>operator!</tt>,
+ * in terms of which the conversion operator will be implemented.
+ */
+#define BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()\
+ BOOST_FORCEINLINE BOOST_CONSTEXPR explicit operator bool () const BOOST_NOEXCEPT\
+ {\
+ return !this->operator! ();\
+ }
+
+#else // !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
+
+#if (defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)) && !defined(BOOST_NO_COMPILER_CONFIG)
+// Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
+#define BOOST_NO_UNSPECIFIED_BOOL
+#endif // (defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)) && !defined(BOOST_NO_COMPILER_CONFIG)
+
+#if !defined(BOOST_NO_UNSPECIFIED_BOOL)
+
+namespace boost {
+
+namespace detail {
+
+#if !defined(_MSC_VER) && !defined(__IBMCPP__)
+
+ struct unspecified_bool
+ {
+ // NOTE TO THE USER: If you see this in error messages then you tried
+ // to apply an unsupported operator on the object that supports
+ // explicit conversion to bool.
+ struct OPERATORS_NOT_ALLOWED;
+ static void true_value(OPERATORS_NOT_ALLOWED*) {}
+ };
+ typedef void (*unspecified_bool_type)(unspecified_bool::OPERATORS_NOT_ALLOWED*);
+
+#else
+
+ // MSVC and VACPP are too eager to convert pointer to function to void* even though they shouldn't
+ struct unspecified_bool
+ {
+ // NOTE TO THE USER: If you see this in error messages then you tried
+ // to apply an unsupported operator on the object that supports
+ // explicit conversion to bool.
+ struct OPERATORS_NOT_ALLOWED;
+ void true_value(OPERATORS_NOT_ALLOWED*) {}
+ };
+ typedef void (unspecified_bool::*unspecified_bool_type)(unspecified_bool::OPERATORS_NOT_ALLOWED*);
+
+#endif
+
+} // namespace detail
+
+} // namespace boost
+
+#define BOOST_EXPLICIT_OPERATOR_BOOL()\
+ BOOST_FORCEINLINE operator boost::detail::unspecified_bool_type () const\
+ {\
+ return (!this->operator! () ? &boost::detail::unspecified_bool::true_value : (boost::detail::unspecified_bool_type)0);\
+ }
+
+#define BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()\
+ BOOST_FORCEINLINE operator boost::detail::unspecified_bool_type () const BOOST_NOEXCEPT\
+ {\
+ return (!this->operator! () ? &boost::detail::unspecified_bool::true_value : (boost::detail::unspecified_bool_type)0);\
+ }
+
+#define BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()\
+ BOOST_FORCEINLINE BOOST_CONSTEXPR operator boost::detail::unspecified_bool_type () const BOOST_NOEXCEPT\
+ {\
+ return (!this->operator! () ? &boost::detail::unspecified_bool::true_value : (boost::detail::unspecified_bool_type)0);\
+ }
+
+#else // !defined(BOOST_NO_UNSPECIFIED_BOOL)
+
+#define BOOST_EXPLICIT_OPERATOR_BOOL()\
+ BOOST_FORCEINLINE operator bool () const\
+ {\
+ return !this->operator! ();\
+ }
+
+#define BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()\
+ BOOST_FORCEINLINE operator bool () const BOOST_NOEXCEPT\
+ {\
+ return !this->operator! ();\
+ }
+
+#define BOOST_CONSTEXPR_EXPLICIT_OPERATOR_BOOL()\
+ BOOST_FORCEINLINE BOOST_CONSTEXPR operator bool () const BOOST_NOEXCEPT\
+ {\
+ return !this->operator! ();\
+ }
+
+#endif // !defined(BOOST_NO_UNSPECIFIED_BOOL)
+
+#endif // !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
+
+#endif // BOOST_CORE_EXPLICIT_OPERATOR_BOOL_HPP
diff --git a/third_party/boost/boost/core/is_same.hpp b/third_party/boost/boost/core/is_same.hpp
new file mode 100644
index 0000000..f373c65
--- /dev/null
+++ b/third_party/boost/boost/core/is_same.hpp
@@ -0,0 +1,40 @@
+#ifndef BOOST_CORE_IS_SAME_HPP_INCLUDED
+#define BOOST_CORE_IS_SAME_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// is_same<T1,T2>::value is true when T1 == T2
+//
+// Copyright 2014 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/config.hpp>
+
+namespace boost
+{
+
+namespace core
+{
+
+template< class T1, class T2 > struct is_same
+{
+ BOOST_STATIC_CONSTANT( bool, value = false );
+};
+
+template< class T > struct is_same< T, T >
+{
+ BOOST_STATIC_CONSTANT( bool, value = true );
+};
+
+} // namespace core
+
+} // namespace boost
+
+#endif // #ifndef BOOST_CORE_IS_SAME_HPP_INCLUDED
diff --git a/third_party/boost/boost/core/no_exceptions_support.hpp b/third_party/boost/boost/core/no_exceptions_support.hpp
new file mode 100644
index 0000000..09b93c9
--- /dev/null
+++ b/third_party/boost/boost/core/no_exceptions_support.hpp
@@ -0,0 +1,44 @@
+#ifndef BOOST_CORE_NO_EXCEPTIONS_SUPPORT_HPP
+#define BOOST_CORE_NO_EXCEPTIONS_SUPPORT_HPP
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+//----------------------------------------------------------------------
+// (C) Copyright 2004 Pavel Vozenilek.
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+//
+// This file contains helper macros used when exception support may be
+// disabled (as indicated by macro BOOST_NO_EXCEPTIONS).
+//
+// Before picking up these macros you may consider using RAII techniques
+// to deal with exceptions - their syntax can be always the same with
+// or without exception support enabled.
+//----------------------------------------------------------------------
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+
+#if !(defined BOOST_NO_EXCEPTIONS)
+# define BOOST_TRY { try
+# define BOOST_CATCH(x) catch(x)
+# define BOOST_RETHROW throw;
+# define BOOST_CATCH_END }
+#else
+# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+# define BOOST_TRY { if ("")
+# define BOOST_CATCH(x) else if (!"")
+# else
+# define BOOST_TRY { if (true)
+# define BOOST_CATCH(x) else if (false)
+# endif
+# define BOOST_RETHROW
+# define BOOST_CATCH_END }
+#endif
+
+
+#endif
diff --git a/third_party/boost/boost/core/noncopyable.hpp b/third_party/boost/boost/core/noncopyable.hpp
new file mode 100644
index 0000000..6ae8c24
--- /dev/null
+++ b/third_party/boost/boost/core/noncopyable.hpp
@@ -0,0 +1,48 @@
+// Boost noncopyable.hpp header file --------------------------------------//
+
+// (C) Copyright Beman Dawes 1999-2003. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/utility for documentation.
+
+#ifndef BOOST_CORE_NONCOPYABLE_HPP
+#define BOOST_CORE_NONCOPYABLE_HPP
+
+#include <boost/config.hpp>
+
+namespace boost {
+
+// Private copy constructor and copy assignment ensure classes derived from
+// class noncopyable cannot be copied.
+
+// Contributed by Dave Abrahams
+
+namespace noncopyable_ // protection from unintended ADL
+{
+ class noncopyable
+ {
+ protected:
+#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) && !defined(BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS)
+ BOOST_CONSTEXPR noncopyable() = default;
+ ~noncopyable() = default;
+#else
+ noncopyable() {}
+ ~noncopyable() {}
+#endif
+#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
+ noncopyable( const noncopyable& ) = delete;
+ noncopyable& operator=( const noncopyable& ) = delete;
+#else
+ private: // emphasize the following members are private
+ noncopyable( const noncopyable& );
+ noncopyable& operator=( const noncopyable& );
+#endif
+ };
+}
+
+typedef noncopyable_::noncopyable noncopyable;
+
+} // namespace boost
+
+#endif // BOOST_CORE_NONCOPYABLE_HPP
diff --git a/third_party/boost/boost/core/ref.hpp b/third_party/boost/boost/core/ref.hpp
new file mode 100644
index 0000000..47dc858
--- /dev/null
+++ b/third_party/boost/boost/core/ref.hpp
@@ -0,0 +1,301 @@
+#ifndef BOOST_CORE_REF_HPP
+#define BOOST_CORE_REF_HPP
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/config.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/detail/workaround.hpp>
+
+//
+// ref.hpp - ref/cref, useful helper functions
+//
+// Copyright (C) 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+// Copyright (C) 2001, 2002 Peter Dimov
+// Copyright (C) 2002 David Abrahams
+//
+// Copyright (C) 2014 Glen Joseph Fernandes
+// glenfe at live dot com
+// Copyright (C) 2014 Agustin Berge
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/core/doc/html/core/ref.html for documentation.
+//
+
+/**
+ @file
+*/
+
+/**
+ Boost namespace.
+*/
+namespace boost
+{
+
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, == 1600 )
+
+ struct ref_workaround_tag {};
+
+#endif
+
+// reference_wrapper
+
+/**
+ @brief Contains a reference to an object of type `T`.
+
+ `reference_wrapper` is primarily used to "feed" references to
+ function templates (algorithms) that take their parameter by
+ value. It provides an implicit conversion to `T&`, which
+ usually allows the function templates to work on references
+ unmodified.
+*/
+template<class T> class reference_wrapper
+{
+public:
+ /**
+ Type `T`.
+ */
+ typedef T type;
+
+ /**
+ Constructs a `reference_wrapper` object that stores a
+ reference to `t`.
+
+ @remark Does not throw.
+ */
+ BOOST_FORCEINLINE explicit reference_wrapper(T& t): t_(boost::addressof(t)) {}
+
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, == 1600 )
+
+ BOOST_FORCEINLINE explicit reference_wrapper( T & t, ref_workaround_tag ): t_( boost::addressof( t ) ) {}
+
+#endif
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ /**
+ @remark Construction from a temporary object is disabled.
+ */
+ BOOST_DELETED_FUNCTION(reference_wrapper(T&& t))
+public:
+#endif
+
+ /**
+ @return The stored reference.
+ @remark Does not throw.
+ */
+ BOOST_FORCEINLINE operator T& () const { return *t_; }
+
+ /**
+ @return The stored reference.
+ @remark Does not throw.
+ */
+ BOOST_FORCEINLINE T& get() const { return *t_; }
+
+ /**
+ @return A pointer to the object referenced by the stored
+ reference.
+ @remark Does not throw.
+ */
+ BOOST_FORCEINLINE T* get_pointer() const { return t_; }
+
+private:
+
+ T* t_;
+};
+
+// ref
+
+/**
+ @cond
+*/
+#if defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x581) )
+# define BOOST_REF_CONST
+#else
+# define BOOST_REF_CONST const
+#endif
+/**
+ @endcond
+*/
+
+/**
+ @return `reference_wrapper<T>(t)`
+ @remark Does not throw.
+*/
+template<class T> BOOST_FORCEINLINE reference_wrapper<T> BOOST_REF_CONST ref( T & t )
+{
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, == 1600 )
+
+ return reference_wrapper<T>( t, ref_workaround_tag() );
+
+#else
+
+ return reference_wrapper<T>( t );
+
+#endif
+}
+
+// cref
+
+/**
+ @return `reference_wrapper<T const>(t)`
+ @remark Does not throw.
+*/
+template<class T> BOOST_FORCEINLINE reference_wrapper<T const> BOOST_REF_CONST cref( T const & t )
+{
+ return reference_wrapper<T const>(t);
+}
+
+#undef BOOST_REF_CONST
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+/**
+ @cond
+*/
+#if defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
+# define BOOST_REF_DELETE
+#else
+# define BOOST_REF_DELETE = delete
+#endif
+/**
+ @endcond
+*/
+
+/**
+ @remark Construction from a temporary object is disabled.
+*/
+template<class T> void ref(T const&&) BOOST_REF_DELETE;
+
+/**
+ @remark Construction from a temporary object is disabled.
+*/
+template<class T> void cref(T const&&) BOOST_REF_DELETE;
+
+#undef BOOST_REF_DELETE
+
+#endif
+
+// is_reference_wrapper
+
+/**
+ @brief Determine if a type `T` is an instantiation of
+ `reference_wrapper`.
+
+ The value static constant will be true if the type `T` is a
+ specialization of `reference_wrapper`.
+*/
+template<typename T> struct is_reference_wrapper
+{
+ BOOST_STATIC_CONSTANT( bool, value = false );
+};
+
+/**
+ @cond
+*/
+template<typename T> struct is_reference_wrapper< reference_wrapper<T> >
+{
+ BOOST_STATIC_CONSTANT( bool, value = true );
+};
+
+#if !defined(BOOST_NO_CV_SPECIALIZATIONS)
+
+template<typename T> struct is_reference_wrapper< reference_wrapper<T> const >
+{
+ BOOST_STATIC_CONSTANT( bool, value = true );
+};
+
+template<typename T> struct is_reference_wrapper< reference_wrapper<T> volatile >
+{
+ BOOST_STATIC_CONSTANT( bool, value = true );
+};
+
+template<typename T> struct is_reference_wrapper< reference_wrapper<T> const volatile >
+{
+ BOOST_STATIC_CONSTANT( bool, value = true );
+};
+
+#endif // !defined(BOOST_NO_CV_SPECIALIZATIONS)
+
+/**
+ @endcond
+*/
+
+
+// unwrap_reference
+
+/**
+ @brief Find the type in a `reference_wrapper`.
+
+ The `typedef` type is `T::type` if `T` is a
+ `reference_wrapper`, `T` otherwise.
+*/
+template<typename T> struct unwrap_reference
+{
+ typedef T type;
+};
+
+/**
+ @cond
+*/
+template<typename T> struct unwrap_reference< reference_wrapper<T> >
+{
+ typedef T type;
+};
+
+#if !defined(BOOST_NO_CV_SPECIALIZATIONS)
+
+template<typename T> struct unwrap_reference< reference_wrapper<T> const >
+{
+ typedef T type;
+};
+
+template<typename T> struct unwrap_reference< reference_wrapper<T> volatile >
+{
+ typedef T type;
+};
+
+template<typename T> struct unwrap_reference< reference_wrapper<T> const volatile >
+{
+ typedef T type;
+};
+
+#endif // !defined(BOOST_NO_CV_SPECIALIZATIONS)
+
+/**
+ @endcond
+*/
+
+// unwrap_ref
+
+/**
+ @return `unwrap_reference<T>::type&(t)`
+ @remark Does not throw.
+*/
+template<class T> BOOST_FORCEINLINE typename unwrap_reference<T>::type& unwrap_ref( T & t )
+{
+ return t;
+}
+
+// get_pointer
+
+/**
+ @cond
+*/
+template<class T> BOOST_FORCEINLINE T* get_pointer( reference_wrapper<T> const & r )
+{
+ return r.get_pointer();
+}
+/**
+ @endcond
+*/
+
+} // namespace boost
+
+#endif // #ifndef BOOST_CORE_REF_HPP
diff --git a/third_party/boost/boost/core/swap.hpp b/third_party/boost/boost/core/swap.hpp
new file mode 100644
index 0000000..baa1be9
--- /dev/null
+++ b/third_party/boost/boost/core/swap.hpp
@@ -0,0 +1,60 @@
+// Copyright (C) 2007, 2008 Steven Watanabe, Joseph Gauterin, Niels Dekker
+//
+// Distributed under the 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_CORE_SWAP_HPP
+#define BOOST_CORE_SWAP_HPP
+
+// Note: the implementation of this utility contains various workarounds:
+// - swap_impl is put outside the boost namespace, to avoid infinite
+// recursion (causing stack overflow) when swapping objects of a primitive
+// type.
+// - swap_impl has a using-directive, rather than a using-declaration,
+// because some compilers (including MSVC 7.1, Borland 5.9.3, and
+// Intel 8.1) don't do argument-dependent lookup when it has a
+// using-declaration instead.
+// - boost::swap has two template arguments, instead of one, to
+// avoid ambiguity when swapping objects of a Boost type that does
+// not have its own boost::swap overload.
+
+#include <utility> //for std::swap (C++11)
+#include <algorithm> //for std::swap (C++98)
+#include <cstddef> //for std::size_t
+#include <boost/config.hpp>
+
+namespace boost_swap_impl
+{
+ template<class T>
+ BOOST_GPU_ENABLED
+ void swap_impl(T& left, T& right)
+ {
+ using namespace std;//use std::swap if argument dependent lookup fails
+ swap(left,right);
+ }
+
+ template<class T, std::size_t N>
+ BOOST_GPU_ENABLED
+ void swap_impl(T (& left)[N], T (& right)[N])
+ {
+ for (std::size_t i = 0; i < N; ++i)
+ {
+ ::boost_swap_impl::swap_impl(left[i], right[i]);
+ }
+ }
+}
+
+namespace boost
+{
+ template<class T1, class T2>
+ BOOST_GPU_ENABLED
+ void swap(T1& left, T2& right)
+ {
+ ::boost_swap_impl::swap_impl(left, right);
+ }
+}
+
+#endif
diff --git a/third_party/boost/boost/core/typeinfo.hpp b/third_party/boost/boost/core/typeinfo.hpp
new file mode 100644
index 0000000..9dbe2c5
--- /dev/null
+++ b/third_party/boost/boost/core/typeinfo.hpp
@@ -0,0 +1,151 @@
+#ifndef BOOST_CORE_TYPEINFO_HPP_INCLUDED
+#define BOOST_CORE_TYPEINFO_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// core::typeinfo, BOOST_CORE_TYPEID
+//
+// Copyright 2007, 2014 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/config.hpp>
+
+#if defined( BOOST_NO_TYPEID )
+
+#include <boost/current_function.hpp>
+#include <functional>
+
+namespace boost
+{
+
+namespace core
+{
+
+class typeinfo
+{
+private:
+
+ typeinfo( typeinfo const& );
+ typeinfo& operator=( typeinfo const& );
+
+ char const * name_;
+
+public:
+
+ explicit typeinfo( char const * name ): name_( name )
+ {
+ }
+
+ bool operator==( typeinfo const& rhs ) const
+ {
+ return this == &rhs;
+ }
+
+ bool operator!=( typeinfo const& rhs ) const
+ {
+ return this != &rhs;
+ }
+
+ bool before( typeinfo const& rhs ) const
+ {
+ return std::less< typeinfo const* >()( this, &rhs );
+ }
+
+ char const* name() const
+ {
+ return name_;
+ }
+};
+
+inline char const * demangled_name( core::typeinfo const & ti )
+{
+ return ti.name();
+}
+
+} // namespace core
+
+namespace detail
+{
+
+template<class T> struct core_typeid_
+{
+ static boost::core::typeinfo ti_;
+
+ static char const * name()
+ {
+ return BOOST_CURRENT_FUNCTION;
+ }
+};
+
+#if defined(__SUNPRO_CC)
+// see #4199, the Sun Studio compiler gets confused about static initialization
+// constructor arguments. But an assignment works just fine.
+template<class T> boost::core::typeinfo core_typeid_< T >::ti_ = core_typeid_< T >::name();
+#else
+template<class T> boost::core::typeinfo core_typeid_< T >::ti_(core_typeid_< T >::name());
+#endif
+
+template<class T> struct core_typeid_< T & >: core_typeid_< T >
+{
+};
+
+template<class T> struct core_typeid_< T const >: core_typeid_< T >
+{
+};
+
+template<class T> struct core_typeid_< T volatile >: core_typeid_< T >
+{
+};
+
+template<class T> struct core_typeid_< T const volatile >: core_typeid_< T >
+{
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#define BOOST_CORE_TYPEID(T) (boost::detail::core_typeid_<T>::ti_)
+
+#else
+
+#include <boost/core/demangle.hpp>
+#include <typeinfo>
+
+namespace boost
+{
+
+namespace core
+{
+
+#if defined( BOOST_NO_STD_TYPEINFO )
+
+typedef ::type_info typeinfo;
+
+#else
+
+typedef std::type_info typeinfo;
+
+#endif
+
+inline std::string demangled_name( core::typeinfo const & ti )
+{
+ return core::demangle( ti.name() );
+}
+
+} // namespace core
+
+} // namespace boost
+
+#define BOOST_CORE_TYPEID(T) typeid(T)
+
+#endif
+
+#endif // #ifndef BOOST_CORE_TYPEINFO_HPP_INCLUDED
diff --git a/third_party/boost/boost/cstdint.hpp b/third_party/boost/boost/cstdint.hpp
new file mode 100644
index 0000000..0651dd5
--- /dev/null
+++ b/third_party/boost/boost/cstdint.hpp
@@ -0,0 +1,542 @@
+// boost cstdint.hpp header file ------------------------------------------//
+
+// (C) Copyright Beman Dawes 1999.
+// (C) Copyright Jens Mauer 2001
+// (C) Copyright John Maddock 2001
+// Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/integer for documentation.
+
+// Revision History
+// 31 Oct 01 use BOOST_HAS_LONG_LONG to check for "long long" (Jens M.)
+// 16 Apr 01 check LONGLONG_MAX when looking for "long long" (Jens Maurer)
+// 23 Jan 01 prefer "long" over "int" for int32_t and intmax_t (Jens Maurer)
+// 12 Nov 00 Merged <boost/stdint.h> (Jens Maurer)
+// 23 Sep 00 Added INTXX_C macro support (John Maddock).
+// 22 Sep 00 Better 64-bit support (John Maddock)
+// 29 Jun 00 Reimplement to avoid including stdint.h within namespace boost
+// 8 Aug 99 Initial version (Beman Dawes)
+
+
+#ifndef BOOST_CSTDINT_HPP
+#define BOOST_CSTDINT_HPP
+
+//
+// Since we always define the INT#_C macros as per C++0x,
+// define __STDC_CONSTANT_MACROS so that <stdint.h> does the right
+// thing if possible, and so that the user knows that the macros
+// are actually defined as per C99.
+//
+#ifndef __STDC_CONSTANT_MACROS
+# define __STDC_CONSTANT_MACROS
+#endif
+
+#include <boost/config.hpp>
+
+//
+// Note that GLIBC is a bit inconsistent about whether int64_t is defined or not
+// depending upon what headers happen to have been included first...
+// so we disable use of stdint.h when GLIBC does not define __GLIBC_HAVE_LONG_LONG.
+// See https://svn.boost.org/trac/boost/ticket/3548 and http://sources.redhat.com/bugzilla/show_bug.cgi?id=10990
+//
+#if defined(BOOST_HAS_STDINT_H) \
+ && (!defined(__GLIBC__) \
+ || defined(__GLIBC_HAVE_LONG_LONG) \
+ || (defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 17)))))
+
+// The following #include is an implementation artifact; not part of interface.
+# ifdef __hpux
+// HP-UX has a vaguely nice <stdint.h> in a non-standard location
+# include <inttypes.h>
+# ifdef __STDC_32_MODE__
+ // this is triggered with GCC, because it defines __cplusplus < 199707L
+# define BOOST_NO_INT64_T
+# endif
+# elif defined(__FreeBSD__) || defined(__IBMCPP__) || defined(_AIX)
+# include <inttypes.h>
+# else
+# include <stdint.h>
+
+// There is a bug in Cygwin two _C macros
+# if defined(__STDC_CONSTANT_MACROS) && defined(__CYGWIN__)
+# undef INTMAX_C
+# undef UINTMAX_C
+# define INTMAX_C(c) c##LL
+# define UINTMAX_C(c) c##ULL
+# endif
+
+# endif
+
+#if defined(__QNX__) && defined(__EXT_QNX)
+
+// QNX (Dinkumware stdlib) defines these as non-standard names.
+// Reflect to the standard names.
+
+typedef ::intleast8_t int_least8_t;
+typedef ::intfast8_t int_fast8_t;
+typedef ::uintleast8_t uint_least8_t;
+typedef ::uintfast8_t uint_fast8_t;
+
+typedef ::intleast16_t int_least16_t;
+typedef ::intfast16_t int_fast16_t;
+typedef ::uintleast16_t uint_least16_t;
+typedef ::uintfast16_t uint_fast16_t;
+
+typedef ::intleast32_t int_least32_t;
+typedef ::intfast32_t int_fast32_t;
+typedef ::uintleast32_t uint_least32_t;
+typedef ::uintfast32_t uint_fast32_t;
+
+# ifndef BOOST_NO_INT64_T
+
+typedef ::intleast64_t int_least64_t;
+typedef ::intfast64_t int_fast64_t;
+typedef ::uintleast64_t uint_least64_t;
+typedef ::uintfast64_t uint_fast64_t;
+
+# endif
+
+#endif
+
+namespace boost
+{
+
+ using ::int8_t;
+ using ::int_least8_t;
+ using ::int_fast8_t;
+ using ::uint8_t;
+ using ::uint_least8_t;
+ using ::uint_fast8_t;
+
+ using ::int16_t;
+ using ::int_least16_t;
+ using ::int_fast16_t;
+ using ::uint16_t;
+ using ::uint_least16_t;
+ using ::uint_fast16_t;
+
+ using ::int32_t;
+ using ::int_least32_t;
+ using ::int_fast32_t;
+ using ::uint32_t;
+ using ::uint_least32_t;
+ using ::uint_fast32_t;
+
+# ifndef BOOST_NO_INT64_T
+
+ using ::int64_t;
+ using ::int_least64_t;
+ using ::int_fast64_t;
+ using ::uint64_t;
+ using ::uint_least64_t;
+ using ::uint_fast64_t;
+
+# endif
+
+ using ::intmax_t;
+ using ::uintmax_t;
+
+} // namespace boost
+
+#elif defined(__FreeBSD__) && (__FreeBSD__ <= 4) || defined(__osf__) || defined(__VMS) || defined(__SOLARIS9__) || defined(__NetBSD__)
+// FreeBSD and Tru64 have an <inttypes.h> that contains much of what we need.
+# include <inttypes.h>
+
+namespace boost {
+
+ using ::int8_t;
+ typedef int8_t int_least8_t;
+ typedef int8_t int_fast8_t;
+ using ::uint8_t;
+ typedef uint8_t uint_least8_t;
+ typedef uint8_t uint_fast8_t;
+
+ using ::int16_t;
+ typedef int16_t int_least16_t;
+ typedef int16_t int_fast16_t;
+ using ::uint16_t;
+ typedef uint16_t uint_least16_t;
+ typedef uint16_t uint_fast16_t;
+
+ using ::int32_t;
+ typedef int32_t int_least32_t;
+ typedef int32_t int_fast32_t;
+ using ::uint32_t;
+ typedef uint32_t uint_least32_t;
+ typedef uint32_t uint_fast32_t;
+
+# ifndef BOOST_NO_INT64_T
+
+ using ::int64_t;
+ typedef int64_t int_least64_t;
+ typedef int64_t int_fast64_t;
+ using ::uint64_t;
+ typedef uint64_t uint_least64_t;
+ typedef uint64_t uint_fast64_t;
+
+ typedef int64_t intmax_t;
+ typedef uint64_t uintmax_t;
+
+# else
+
+ typedef int32_t intmax_t;
+ typedef uint32_t uintmax_t;
+
+# endif
+
+} // namespace boost
+
+#else // BOOST_HAS_STDINT_H
+
+# include <boost/limits.hpp> // implementation artifact; not part of interface
+# include <limits.h> // needed for limits macros
+
+
+namespace boost
+{
+
+// These are fairly safe guesses for some 16-bit, and most 32-bit and 64-bit
+// platforms. For other systems, they will have to be hand tailored.
+//
+// Because the fast types are assumed to be the same as the undecorated types,
+// it may be possible to hand tailor a more efficient implementation. Such
+// an optimization may be illusionary; on the Intel x86-family 386 on, for
+// example, byte arithmetic and load/stores are as fast as "int" sized ones.
+
+// 8-bit types ------------------------------------------------------------//
+
+# if UCHAR_MAX == 0xff
+ typedef signed char int8_t;
+ typedef signed char int_least8_t;
+ typedef signed char int_fast8_t;
+ typedef unsigned char uint8_t;
+ typedef unsigned char uint_least8_t;
+ typedef unsigned char uint_fast8_t;
+# else
+# error defaults not correct; you must hand modify boost/cstdint.hpp
+# endif
+
+// 16-bit types -----------------------------------------------------------//
+
+# if USHRT_MAX == 0xffff
+# if defined(__crayx1)
+ // The Cray X1 has a 16-bit short, however it is not recommend
+ // for use in performance critical code.
+ typedef short int16_t;
+ typedef short int_least16_t;
+ typedef int int_fast16_t;
+ typedef unsigned short uint16_t;
+ typedef unsigned short uint_least16_t;
+ typedef unsigned int uint_fast16_t;
+# else
+ typedef short int16_t;
+ typedef short int_least16_t;
+ typedef short int_fast16_t;
+ typedef unsigned short uint16_t;
+ typedef unsigned short uint_least16_t;
+ typedef unsigned short uint_fast16_t;
+# endif
+# elif (USHRT_MAX == 0xffffffff) && defined(__MTA__)
+ // On MTA / XMT short is 32 bits unless the -short16 compiler flag is specified
+ // MTA / XMT does support the following non-standard integer types
+ typedef __short16 int16_t;
+ typedef __short16 int_least16_t;
+ typedef __short16 int_fast16_t;
+ typedef unsigned __short16 uint16_t;
+ typedef unsigned __short16 uint_least16_t;
+ typedef unsigned __short16 uint_fast16_t;
+# elif (USHRT_MAX == 0xffffffff) && defined(CRAY)
+ // no 16-bit types on Cray:
+ typedef short int_least16_t;
+ typedef short int_fast16_t;
+ typedef unsigned short uint_least16_t;
+ typedef unsigned short uint_fast16_t;
+# else
+# error defaults not correct; you must hand modify boost/cstdint.hpp
+# endif
+
+// 32-bit types -----------------------------------------------------------//
+
+# if UINT_MAX == 0xffffffff
+ typedef int int32_t;
+ typedef int int_least32_t;
+ typedef int int_fast32_t;
+ typedef unsigned int uint32_t;
+ typedef unsigned int uint_least32_t;
+ typedef unsigned int uint_fast32_t;
+# elif (USHRT_MAX == 0xffffffff)
+ typedef short int32_t;
+ typedef short int_least32_t;
+ typedef short int_fast32_t;
+ typedef unsigned short uint32_t;
+ typedef unsigned short uint_least32_t;
+ typedef unsigned short uint_fast32_t;
+# elif ULONG_MAX == 0xffffffff
+ typedef long int32_t;
+ typedef long int_least32_t;
+ typedef long int_fast32_t;
+ typedef unsigned long uint32_t;
+ typedef unsigned long uint_least32_t;
+ typedef unsigned long uint_fast32_t;
+# elif (UINT_MAX == 0xffffffffffffffff) && defined(__MTA__)
+ // Integers are 64 bits on the MTA / XMT
+ typedef __int32 int32_t;
+ typedef __int32 int_least32_t;
+ typedef __int32 int_fast32_t;
+ typedef unsigned __int32 uint32_t;
+ typedef unsigned __int32 uint_least32_t;
+ typedef unsigned __int32 uint_fast32_t;
+# else
+# error defaults not correct; you must hand modify boost/cstdint.hpp
+# endif
+
+// 64-bit types + intmax_t and uintmax_t ----------------------------------//
+
+# if defined(BOOST_HAS_LONG_LONG) && \
+ !defined(BOOST_MSVC) && !defined(__BORLANDC__) && \
+ (!defined(__GLIBCPP__) || defined(_GLIBCPP_USE_LONG_LONG)) && \
+ (defined(ULLONG_MAX) || defined(ULONG_LONG_MAX) || defined(ULONGLONG_MAX))
+# if defined(__hpux)
+ // HP-UX's value of ULONG_LONG_MAX is unusable in preprocessor expressions
+# elif (defined(ULLONG_MAX) && ULLONG_MAX == 18446744073709551615ULL) || (defined(ULONG_LONG_MAX) && ULONG_LONG_MAX == 18446744073709551615ULL) || (defined(ULONGLONG_MAX) && ULONGLONG_MAX == 18446744073709551615ULL)
+ // 2**64 - 1
+# else
+# error defaults not correct; you must hand modify boost/cstdint.hpp
+# endif
+
+ typedef ::boost::long_long_type intmax_t;
+ typedef ::boost::ulong_long_type uintmax_t;
+ typedef ::boost::long_long_type int64_t;
+ typedef ::boost::long_long_type int_least64_t;
+ typedef ::boost::long_long_type int_fast64_t;
+ typedef ::boost::ulong_long_type uint64_t;
+ typedef ::boost::ulong_long_type uint_least64_t;
+ typedef ::boost::ulong_long_type uint_fast64_t;
+
+# elif ULONG_MAX != 0xffffffff
+
+# if ULONG_MAX == 18446744073709551615 // 2**64 - 1
+ typedef long intmax_t;
+ typedef unsigned long uintmax_t;
+ typedef long int64_t;
+ typedef long int_least64_t;
+ typedef long int_fast64_t;
+ typedef unsigned long uint64_t;
+ typedef unsigned long uint_least64_t;
+ typedef unsigned long uint_fast64_t;
+# else
+# error defaults not correct; you must hand modify boost/cstdint.hpp
+# endif
+# elif defined(__GNUC__) && defined(BOOST_HAS_LONG_LONG)
+ __extension__ typedef long long intmax_t;
+ __extension__ typedef unsigned long long uintmax_t;
+ __extension__ typedef long long int64_t;
+ __extension__ typedef long long int_least64_t;
+ __extension__ typedef long long int_fast64_t;
+ __extension__ typedef unsigned long long uint64_t;
+ __extension__ typedef unsigned long long uint_least64_t;
+ __extension__ typedef unsigned long long uint_fast64_t;
+# elif defined(BOOST_HAS_MS_INT64)
+ //
+ // we have Borland/Intel/Microsoft __int64:
+ //
+ typedef __int64 intmax_t;
+ typedef unsigned __int64 uintmax_t;
+ typedef __int64 int64_t;
+ typedef __int64 int_least64_t;
+ typedef __int64 int_fast64_t;
+ typedef unsigned __int64 uint64_t;
+ typedef unsigned __int64 uint_least64_t;
+ typedef unsigned __int64 uint_fast64_t;
+# else // assume no 64-bit integers
+# define BOOST_NO_INT64_T
+ typedef int32_t intmax_t;
+ typedef uint32_t uintmax_t;
+# endif
+
+} // namespace boost
+
+
+#endif // BOOST_HAS_STDINT_H
+
+// intptr_t/uintptr_t are defined separately because they are optional and not universally available
+#if defined(BOOST_WINDOWS) && !defined(_WIN32_WCE) && !defined(BOOST_HAS_STDINT_H)
+// Older MSVC don't have stdint.h and have intptr_t/uintptr_t defined in stddef.h
+#include <stddef.h>
+#endif
+
+// PGI seems to not support intptr_t/uintptr_t properly. BOOST_HAS_STDINT_H is not defined for this compiler by Boost.Config.
+#if !defined(__PGIC__)
+
+#if (defined(BOOST_WINDOWS) && !defined(_WIN32_WCE)) \
+ || (defined(_XOPEN_UNIX) && (_XOPEN_UNIX+0 > 0) && !defined(__UCLIBC__)) \
+ || defined(__CYGWIN__) \
+ || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) \
+ || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(sun)
+
+namespace boost {
+ using ::intptr_t;
+ using ::uintptr_t;
+}
+#define BOOST_HAS_INTPTR_T
+
+// Clang pretends to be GCC, so it'll match this condition
+#elif defined(__GNUC__) && defined(__INTPTR_TYPE__) && defined(__UINTPTR_TYPE__)
+
+namespace boost {
+ typedef __INTPTR_TYPE__ intptr_t;
+ typedef __UINTPTR_TYPE__ uintptr_t;
+}
+#define BOOST_HAS_INTPTR_T
+
+#endif
+
+#endif // !defined(__PGIC__)
+
+#endif // BOOST_CSTDINT_HPP
+
+
+/****************************************************
+
+Macro definition section:
+
+Added 23rd September 2000 (John Maddock).
+Modified 11th September 2001 to be excluded when
+BOOST_HAS_STDINT_H is defined (John Maddock).
+Modified 11th Dec 2009 to always define the
+INT#_C macros if they're not already defined (John Maddock).
+
+******************************************************/
+
+#if !defined(BOOST__STDC_CONSTANT_MACROS_DEFINED) && \
+ (!defined(INT8_C) || !defined(INT16_C) || !defined(INT32_C) || !defined(INT64_C))
+//
+// For the following code we get several warnings along the lines of:
+//
+// boost/cstdint.hpp:428:35: error: use of C99 long long integer constant
+//
+// So we declare this a system header to suppress these warnings.
+//
+#if defined(__GNUC__) && (__GNUC__ >= 4)
+#pragma GCC system_header
+#endif
+
+#include <limits.h>
+# define BOOST__STDC_CONSTANT_MACROS_DEFINED
+# if defined(BOOST_HAS_MS_INT64)
+//
+// Borland/Intel/Microsoft compilers have width specific suffixes:
+//
+#ifndef INT8_C
+# define INT8_C(value) value##i8
+#endif
+#ifndef INT16_C
+# define INT16_C(value) value##i16
+#endif
+#ifndef INT32_C
+# define INT32_C(value) value##i32
+#endif
+#ifndef INT64_C
+# define INT64_C(value) value##i64
+#endif
+# ifdef __BORLANDC__
+ // Borland bug: appending ui8 makes the type a signed char
+# define UINT8_C(value) static_cast<unsigned char>(value##u)
+# else
+# define UINT8_C(value) value##ui8
+# endif
+#ifndef UINT16_C
+# define UINT16_C(value) value##ui16
+#endif
+#ifndef UINT32_C
+# define UINT32_C(value) value##ui32
+#endif
+#ifndef UINT64_C
+# define UINT64_C(value) value##ui64
+#endif
+#ifndef INTMAX_C
+# define INTMAX_C(value) value##i64
+# define UINTMAX_C(value) value##ui64
+#endif
+
+# else
+// do it the old fashioned way:
+
+// 8-bit types ------------------------------------------------------------//
+
+# if (UCHAR_MAX == 0xff) && !defined(INT8_C)
+# define INT8_C(value) static_cast<boost::int8_t>(value)
+# define UINT8_C(value) static_cast<boost::uint8_t>(value##u)
+# endif
+
+// 16-bit types -----------------------------------------------------------//
+
+# if (USHRT_MAX == 0xffff) && !defined(INT16_C)
+# define INT16_C(value) static_cast<boost::int16_t>(value)
+# define UINT16_C(value) static_cast<boost::uint16_t>(value##u)
+# endif
+
+// 32-bit types -----------------------------------------------------------//
+#ifndef INT32_C
+# if (UINT_MAX == 0xffffffff)
+# define INT32_C(value) value
+# define UINT32_C(value) value##u
+# elif ULONG_MAX == 0xffffffff
+# define INT32_C(value) value##L
+# define UINT32_C(value) value##uL
+# endif
+#endif
+
+// 64-bit types + intmax_t and uintmax_t ----------------------------------//
+#ifndef INT64_C
+# if defined(BOOST_HAS_LONG_LONG) && \
+ (defined(ULLONG_MAX) || defined(ULONG_LONG_MAX) || defined(ULONGLONG_MAX) || defined(_ULLONG_MAX) || defined(_LLONG_MAX))
+
+# if defined(__hpux)
+ // HP-UX's value of ULONG_LONG_MAX is unusable in preprocessor expressions
+# define INT64_C(value) value##LL
+# define UINT64_C(value) value##uLL
+# elif (defined(ULLONG_MAX) && ULLONG_MAX == 18446744073709551615ULL) || \
+ (defined(ULONG_LONG_MAX) && ULONG_LONG_MAX == 18446744073709551615ULL) || \
+ (defined(ULONGLONG_MAX) && ULONGLONG_MAX == 18446744073709551615ULL) || \
+ (defined(_ULLONG_MAX) && _ULLONG_MAX == 18446744073709551615ULL) || \
+ (defined(_LLONG_MAX) && _LLONG_MAX == 9223372036854775807LL)
+
+# define INT64_C(value) value##LL
+# define UINT64_C(value) value##uLL
+# else
+# error defaults not correct; you must hand modify boost/cstdint.hpp
+# endif
+# elif ULONG_MAX != 0xffffffff
+
+# if ULONG_MAX == 18446744073709551615U // 2**64 - 1
+# define INT64_C(value) value##L
+# define UINT64_C(value) value##uL
+# else
+# error defaults not correct; you must hand modify boost/cstdint.hpp
+# endif
+# elif defined(BOOST_HAS_LONG_LONG)
+ // Usual macros not defined, work things out for ourselves:
+# if(~0uLL == 18446744073709551615ULL)
+# define INT64_C(value) value##LL
+# define UINT64_C(value) value##uLL
+# else
+# error defaults not correct; you must hand modify boost/cstdint.hpp
+# endif
+# else
+# error defaults not correct; you must hand modify boost/cstdint.hpp
+# endif
+
+# ifdef BOOST_NO_INT64_T
+# define INTMAX_C(value) INT32_C(value)
+# define UINTMAX_C(value) UINT32_C(value)
+# else
+# define INTMAX_C(value) INT64_C(value)
+# define UINTMAX_C(value) UINT64_C(value)
+# endif
+#endif
+# endif // Borland/Microsoft specific width suffixes
+
+#endif // INT#_C macros.
diff --git a/third_party/boost/boost/current_function.hpp b/third_party/boost/boost/current_function.hpp
new file mode 100644
index 0000000..5c113f8
--- /dev/null
+++ b/third_party/boost/boost/current_function.hpp
@@ -0,0 +1,71 @@
+#ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED
+#define BOOST_CURRENT_FUNCTION_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// boost/current_function.hpp - BOOST_CURRENT_FUNCTION
+//
+// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+// http://www.boost.org/libs/assert/current_function.html
+//
+
+namespace boost
+{
+
+namespace detail
+{
+
+inline void current_function_helper()
+{
+
+#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600)) || defined(__ghs__)
+
+# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__
+
+#elif defined(__DMC__) && (__DMC__ >= 0x810)
+
+# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__
+
+#elif defined(__FUNCSIG__)
+
+# define BOOST_CURRENT_FUNCTION __FUNCSIG__
+
+#elif (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 600)) || (defined(__IBMCPP__) && (__IBMCPP__ >= 500))
+
+# define BOOST_CURRENT_FUNCTION __FUNCTION__
+
+#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x550)
+
+# define BOOST_CURRENT_FUNCTION __FUNC__
+
+#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
+
+# define BOOST_CURRENT_FUNCTION __func__
+
+#elif defined(__cplusplus) && (__cplusplus >= 201103)
+
+# define BOOST_CURRENT_FUNCTION __func__
+
+#else
+
+# define BOOST_CURRENT_FUNCTION "(unknown)"
+
+#endif
+
+}
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED
diff --git a/third_party/boost/boost/detail/call_traits.hpp b/third_party/boost/boost/detail/call_traits.hpp
new file mode 100644
index 0000000..36dea00
--- /dev/null
+++ b/third_party/boost/boost/detail/call_traits.hpp
@@ -0,0 +1,172 @@
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/utility for most recent version including documentation.
+
+// call_traits: defines typedefs for function usage
+// (see libs/utility/call_traits.htm)
+
+/* Release notes:
+ 23rd July 2000:
+ Fixed array specialization. (JM)
+ Added Borland specific fixes for reference types
+ (issue raised by Steve Cleary).
+*/
+
+#ifndef BOOST_DETAIL_CALL_TRAITS_HPP
+#define BOOST_DETAIL_CALL_TRAITS_HPP
+
+#ifndef BOOST_CONFIG_HPP
+#include <boost/config.hpp>
+#endif
+#include <cstddef>
+
+#include <boost/type_traits/is_arithmetic.hpp>
+#include <boost/type_traits/is_enum.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/detail/workaround.hpp>
+
+namespace boost{
+
+namespace detail{
+
+template <typename T, bool small_>
+struct ct_imp2
+{
+ typedef const T& param_type;
+};
+
+template <typename T>
+struct ct_imp2<T, true>
+{
+ typedef const T param_type;
+};
+
+template <typename T, bool isp, bool b1, bool b2>
+struct ct_imp
+{
+ typedef const T& param_type;
+};
+
+template <typename T, bool isp, bool b2>
+struct ct_imp<T, isp, true, b2>
+{
+ typedef typename ct_imp2<T, sizeof(T) <= sizeof(void*)>::param_type param_type;
+};
+
+template <typename T, bool isp, bool b1>
+struct ct_imp<T, isp, b1, true>
+{
+ typedef typename ct_imp2<T, sizeof(T) <= sizeof(void*)>::param_type param_type;
+};
+
+template <typename T, bool b1, bool b2>
+struct ct_imp<T, true, b1, b2>
+{
+ typedef const T param_type;
+};
+
+}
+
+template <typename T>
+struct call_traits
+{
+public:
+ typedef T value_type;
+ typedef T& reference;
+ typedef const T& const_reference;
+ //
+ // C++ Builder workaround: we should be able to define a compile time
+ // constant and pass that as a single template parameter to ct_imp<T,bool>,
+ // however compiler bugs prevent this - instead pass three bool's to
+ // ct_imp<T,bool,bool,bool> and add an extra partial specialisation
+ // of ct_imp to handle the logic. (JM)
+ typedef typename boost::detail::ct_imp<
+ T,
+ ::boost::is_pointer<T>::value,
+ ::boost::is_arithmetic<T>::value,
+ ::boost::is_enum<T>::value
+ >::param_type param_type;
+};
+
+template <typename T>
+struct call_traits<T&>
+{
+ typedef T& value_type;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef T& param_type; // hh removed const
+};
+
+#if BOOST_WORKAROUND( __BORLANDC__, < 0x5A0 )
+// these are illegal specialisations; cv-qualifies applied to
+// references have no effect according to [8.3.2p1],
+// C++ Builder requires them though as it treats cv-qualified
+// references as distinct types...
+template <typename T>
+struct call_traits<T&const>
+{
+ typedef T& value_type;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef T& param_type; // hh removed const
+};
+template <typename T>
+struct call_traits<T&volatile>
+{
+ typedef T& value_type;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef T& param_type; // hh removed const
+};
+template <typename T>
+struct call_traits<T&const volatile>
+{
+ typedef T& value_type;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef T& param_type; // hh removed const
+};
+
+template <typename T>
+struct call_traits< T * >
+{
+ typedef T * value_type;
+ typedef T * & reference;
+ typedef T * const & const_reference;
+ typedef T * const param_type; // hh removed const
+};
+#endif
+#if !defined(BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS)
+template <typename T, std::size_t N>
+struct call_traits<T [N]>
+{
+private:
+ typedef T array_type[N];
+public:
+ // degrades array to pointer:
+ typedef const T* value_type;
+ typedef array_type& reference;
+ typedef const array_type& const_reference;
+ typedef const T* const param_type;
+};
+
+template <typename T, std::size_t N>
+struct call_traits<const T [N]>
+{
+private:
+ typedef const T array_type[N];
+public:
+ // degrades array to pointer:
+ typedef const T* value_type;
+ typedef array_type& reference;
+ typedef const array_type& const_reference;
+ typedef const T* const param_type;
+};
+#endif
+
+}
+
+#endif // BOOST_DETAIL_CALL_TRAITS_HPP
diff --git a/third_party/boost/boost/detail/indirect_traits.hpp b/third_party/boost/boost/detail/indirect_traits.hpp
new file mode 100644
index 0000000..f7ce383
--- /dev/null
+++ b/third_party/boost/boost/detail/indirect_traits.hpp
@@ -0,0 +1,204 @@
+// Copyright David Abrahams 2002.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+#ifndef INDIRECT_TRAITS_DWA2002131_HPP
+# define INDIRECT_TRAITS_DWA2002131_HPP
+# include <boost/type_traits/is_function.hpp>
+# include <boost/type_traits/is_reference.hpp>
+# include <boost/type_traits/is_pointer.hpp>
+# include <boost/type_traits/is_class.hpp>
+# include <boost/type_traits/is_const.hpp>
+# include <boost/type_traits/is_volatile.hpp>
+# include <boost/type_traits/is_member_function_pointer.hpp>
+# include <boost/type_traits/is_member_pointer.hpp>
+# include <boost/type_traits/remove_cv.hpp>
+# include <boost/type_traits/remove_reference.hpp>
+# include <boost/type_traits/remove_pointer.hpp>
+
+# include <boost/detail/workaround.hpp>
+
+# include <boost/mpl/eval_if.hpp>
+# include <boost/mpl/if.hpp>
+# include <boost/mpl/bool.hpp>
+# include <boost/mpl/and.hpp>
+# include <boost/mpl/not.hpp>
+# include <boost/mpl/aux_/lambda_support.hpp>
+
+
+namespace boost { namespace detail {
+
+namespace indirect_traits {
+
+template <class T>
+struct is_reference_to_const : mpl::false_
+{
+};
+
+template <class T>
+struct is_reference_to_const<T const&> : mpl::true_
+{
+};
+
+# if defined(BOOST_MSVC) && _MSC_FULL_VER <= 13102140 // vc7.01 alpha workaround
+template<class T>
+struct is_reference_to_const<T const volatile&> : mpl::true_
+{
+};
+# endif
+
+template <class T>
+struct is_reference_to_function : mpl::false_
+{
+};
+
+template <class T>
+struct is_reference_to_function<T&> : is_function<T>
+{
+};
+
+template <class T>
+struct is_pointer_to_function : mpl::false_
+{
+};
+
+// There's no such thing as a pointer-to-cv-function, so we don't need
+// specializations for those
+template <class T>
+struct is_pointer_to_function<T*> : is_function<T>
+{
+};
+
+template <class T>
+struct is_reference_to_member_function_pointer_impl : mpl::false_
+{
+};
+
+template <class T>
+struct is_reference_to_member_function_pointer_impl<T&>
+ : is_member_function_pointer<typename remove_cv<T>::type>
+{
+};
+
+
+template <class T>
+struct is_reference_to_member_function_pointer
+ : is_reference_to_member_function_pointer_impl<T>
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_reference_to_member_function_pointer,(T))
+};
+
+template <class T>
+struct is_reference_to_function_pointer_aux
+ : mpl::and_<
+ is_reference<T>
+ , is_pointer_to_function<
+ typename remove_cv<
+ typename remove_reference<T>::type
+ >::type
+ >
+ >
+{
+ // There's no such thing as a pointer-to-cv-function, so we don't need specializations for those
+};
+
+template <class T>
+struct is_reference_to_function_pointer
+ : mpl::if_<
+ is_reference_to_function<T>
+ , mpl::false_
+ , is_reference_to_function_pointer_aux<T>
+ >::type
+{
+};
+
+template <class T>
+struct is_reference_to_non_const
+ : mpl::and_<
+ is_reference<T>
+ , mpl::not_<
+ is_reference_to_const<T>
+ >
+ >
+{
+};
+
+template <class T>
+struct is_reference_to_volatile : mpl::false_
+{
+};
+
+template <class T>
+struct is_reference_to_volatile<T volatile&> : mpl::true_
+{
+};
+
+# if defined(BOOST_MSVC) && _MSC_FULL_VER <= 13102140 // vc7.01 alpha workaround
+template <class T>
+struct is_reference_to_volatile<T const volatile&> : mpl::true_
+{
+};
+# endif
+
+
+template <class T>
+struct is_reference_to_pointer : mpl::false_
+{
+};
+
+template <class T>
+struct is_reference_to_pointer<T*&> : mpl::true_
+{
+};
+
+template <class T>
+struct is_reference_to_pointer<T* const&> : mpl::true_
+{
+};
+
+template <class T>
+struct is_reference_to_pointer<T* volatile&> : mpl::true_
+{
+};
+
+template <class T>
+struct is_reference_to_pointer<T* const volatile&> : mpl::true_
+{
+};
+
+template <class T>
+struct is_reference_to_class
+ : mpl::and_<
+ is_reference<T>
+ , is_class<
+ typename remove_cv<
+ typename remove_reference<T>::type
+ >::type
+ >
+ >
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_reference_to_class,(T))
+};
+
+template <class T>
+struct is_pointer_to_class
+ : mpl::and_<
+ is_pointer<T>
+ , is_class<
+ typename remove_cv<
+ typename remove_pointer<T>::type
+ >::type
+ >
+ >
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_pointer_to_class,(T))
+};
+
+
+}
+
+using namespace indirect_traits;
+
+}} // namespace boost::python::detail
+
+#endif // INDIRECT_TRAITS_DWA2002131_HPP
diff --git a/third_party/boost/boost/detail/iterator.hpp b/third_party/boost/boost/detail/iterator.hpp
new file mode 100644
index 0000000..c2e8f1e
--- /dev/null
+++ b/third_party/boost/boost/detail/iterator.hpp
@@ -0,0 +1,26 @@
+// (C) Copyright David Abrahams 2002.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef ITERATOR_DWA122600_HPP_
+#define ITERATOR_DWA122600_HPP_
+
+// This header is obsolete and will be deprecated.
+
+#include <iterator>
+
+namespace boost
+{
+
+namespace detail
+{
+
+using std::iterator_traits;
+using std::distance;
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // ITERATOR_DWA122600_HPP_
diff --git a/third_party/boost/boost/detail/no_exceptions_support.hpp b/third_party/boost/boost/detail/no_exceptions_support.hpp
new file mode 100644
index 0000000..7d17454
--- /dev/null
+++ b/third_party/boost/boost/detail/no_exceptions_support.hpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2014 Glen Fernandes
+ *
+ * Distributed under the Boost Software 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_NO_EXCEPTIONS_SUPPORT_HPP
+#define BOOST_DETAIL_NO_EXCEPTIONS_SUPPORT_HPP
+
+// The header file at this path is deprecated;
+// use boost/core/no_exceptions_support.hpp instead.
+
+#include <boost/core/no_exceptions_support.hpp>
+
+#endif
diff --git a/third_party/boost/boost/detail/reference_content.hpp b/third_party/boost/boost/detail/reference_content.hpp
new file mode 100644
index 0000000..36b80d2
--- /dev/null
+++ b/third_party/boost/boost/detail/reference_content.hpp
@@ -0,0 +1,120 @@
+//-----------------------------------------------------------------------------
+// boost detail/reference_content.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2003
+// Eric Friedman
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_DETAIL_REFERENCE_CONTENT_HPP
+#define BOOST_DETAIL_REFERENCE_CONTENT_HPP
+
+#include "boost/config.hpp"
+
+# include "boost/mpl/bool.hpp"
+# include "boost/type_traits/has_nothrow_copy.hpp"
+
+#include "boost/mpl/void.hpp"
+
+namespace boost {
+
+namespace detail {
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) class template reference_content
+//
+// Non-Assignable wrapper for references.
+//
+template <typename RefT>
+class reference_content
+{
+private: // representation
+
+ RefT content_;
+
+public: // structors
+
+ ~reference_content()
+ {
+ }
+
+ reference_content(RefT r)
+ : content_( r )
+ {
+ }
+
+ reference_content(const reference_content& operand)
+ : content_( operand.content_ )
+ {
+ }
+
+private: // non-Assignable
+
+ reference_content& operator=(const reference_content&);
+
+public: // queries
+
+ RefT get() const
+ {
+ return content_;
+ }
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) metafunction make_reference_content
+//
+// Wraps with reference_content if specified type is reference.
+//
+
+template <typename T = mpl::void_> struct make_reference_content;
+
+
+template <typename T>
+struct make_reference_content
+{
+ typedef T type;
+};
+
+template <typename T>
+struct make_reference_content< T& >
+{
+ typedef reference_content<T&> type;
+};
+
+
+template <>
+struct make_reference_content< mpl::void_ >
+{
+ template <typename T>
+ struct apply
+ : make_reference_content<T>
+ {
+ };
+
+ typedef mpl::void_ type;
+};
+
+} // namespace detail
+
+///////////////////////////////////////////////////////////////////////////////
+// reference_content<T&> type traits specializations
+//
+
+
+template <typename T>
+struct has_nothrow_copy<
+ ::boost::detail::reference_content< T& >
+ >
+ : mpl::true_
+{
+};
+
+
+} // namespace boost
+
+#endif // BOOST_DETAIL_REFERENCE_CONTENT_HPP
diff --git a/third_party/boost/boost/detail/sp_typeinfo.hpp b/third_party/boost/boost/detail/sp_typeinfo.hpp
new file mode 100644
index 0000000..4e4de55
--- /dev/null
+++ b/third_party/boost/boost/detail/sp_typeinfo.hpp
@@ -0,0 +1,36 @@
+#ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED
+#define BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// detail/sp_typeinfo.hpp
+//
+// Deprecated, please use boost/core/typeinfo.hpp
+//
+// Copyright 2007 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/core/typeinfo.hpp>
+
+namespace boost
+{
+
+namespace detail
+{
+
+typedef boost::core::typeinfo sp_typeinfo;
+
+} // namespace detail
+
+} // namespace boost
+
+#define BOOST_SP_TYPEID(T) BOOST_CORE_TYPEID(T)
+
+#endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED
diff --git a/third_party/boost/boost/detail/templated_streams.hpp b/third_party/boost/boost/detail/templated_streams.hpp
new file mode 100644
index 0000000..82042d2
--- /dev/null
+++ b/third_party/boost/boost/detail/templated_streams.hpp
@@ -0,0 +1,74 @@
+//-----------------------------------------------------------------------------
+// boost detail/templated_streams.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2003
+// Eric Friedman
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_DETAIL_TEMPLATED_STREAMS_HPP
+#define BOOST_DETAIL_TEMPLATED_STREAMS_HPP
+
+#include "boost/config.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) BOOST_TEMPLATED_STREAM_* macros
+//
+// Provides workaround platforms without stream class templates.
+//
+
+#if !defined(BOOST_NO_STD_LOCALE)
+
+#define BOOST_TEMPLATED_STREAM_TEMPLATE(E,T) \
+ template < typename E , typename T >
+
+#define BOOST_TEMPLATED_STREAM_TEMPLATE_ALLOC(E,T,A) \
+ template < typename E , typename T , typename A >
+
+#define BOOST_TEMPLATED_STREAM_ARGS(E,T) \
+ typename E , typename T
+
+#define BOOST_TEMPLATED_STREAM_ARGS_ALLOC(E,T,A) \
+ typename E , typename T , typename A
+
+#define BOOST_TEMPLATED_STREAM_COMMA ,
+
+#define BOOST_TEMPLATED_STREAM_ELEM(E) E
+#define BOOST_TEMPLATED_STREAM_TRAITS(T) T
+#define BOOST_TEMPLATED_STREAM_ALLOC(A) A
+
+#define BOOST_TEMPLATED_STREAM(X,E,T) \
+ BOOST_JOIN(std::basic_,X)< E , T >
+
+#define BOOST_TEMPLATED_STREAM_WITH_ALLOC(X,E,T,A) \
+ BOOST_JOIN(std::basic_,X)< E , T , A >
+
+#else // defined(BOOST_NO_STD_LOCALE)
+
+#define BOOST_TEMPLATED_STREAM_TEMPLATE(E,T) /**/
+
+#define BOOST_TEMPLATED_STREAM_TEMPLATE_ALLOC(E,T,A) /**/
+
+#define BOOST_TEMPLATED_STREAM_ARGS(E,T) /**/
+
+#define BOOST_TEMPLATED_STREAM_ARGS_ALLOC(E,T,A) /**/
+
+#define BOOST_TEMPLATED_STREAM_COMMA /**/
+
+#define BOOST_TEMPLATED_STREAM_ELEM(E) char
+#define BOOST_TEMPLATED_STREAM_TRAITS(T) std::char_traits<char>
+#define BOOST_TEMPLATED_STREAM_ALLOC(A) std::allocator<char>
+
+#define BOOST_TEMPLATED_STREAM(X,E,T) \
+ std::X
+
+#define BOOST_TEMPLATED_STREAM_WITH_ALLOC(X,E,T,A) \
+ std::X
+
+#endif // BOOST_NO_STD_LOCALE
+
+#endif // BOOST_DETAIL_TEMPLATED_STREAMS_HPP
diff --git a/third_party/boost/boost/detail/workaround.hpp b/third_party/boost/boost/detail/workaround.hpp
new file mode 100644
index 0000000..8e5648e
--- /dev/null
+++ b/third_party/boost/boost/detail/workaround.hpp
@@ -0,0 +1,267 @@
+// Copyright David Abrahams 2002.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+#ifndef WORKAROUND_DWA2002126_HPP
+# define WORKAROUND_DWA2002126_HPP
+
+// Compiler/library version workaround macro
+//
+// Usage:
+//
+// #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+// // workaround for eVC4 and VC6
+// ... // workaround code here
+// #endif
+//
+// When BOOST_STRICT_CONFIG is defined, expands to 0. Otherwise, the
+// first argument must be undefined or expand to a numeric
+// value. The above expands to:
+//
+// (BOOST_MSVC) != 0 && (BOOST_MSVC) < 1300
+//
+// When used for workarounds that apply to the latest known version
+// and all earlier versions of a compiler, the following convention
+// should be observed:
+//
+// #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1301))
+//
+// The version number in this case corresponds to the last version in
+// which the workaround was known to have been required. When
+// BOOST_DETECT_OUTDATED_WORKAROUNDS is not the defined, the macro
+// BOOST_TESTED_AT(x) expands to "!= 0", which effectively activates
+// the workaround for any version of the compiler. When
+// BOOST_DETECT_OUTDATED_WORKAROUNDS is defined, a compiler warning or
+// error will be issued if the compiler version exceeds the argument
+// to BOOST_TESTED_AT(). This can be used to locate workarounds which
+// may be obsoleted by newer versions.
+
+# ifndef BOOST_STRICT_CONFIG
+
+#include <boost/config.hpp>
+
+#ifndef __BORLANDC__
+#define __BORLANDC___WORKAROUND_GUARD 1
+#else
+#define __BORLANDC___WORKAROUND_GUARD 0
+#endif
+#ifndef __CODEGEARC__
+#define __CODEGEARC___WORKAROUND_GUARD 1
+#else
+#define __CODEGEARC___WORKAROUND_GUARD 0
+#endif
+#ifndef _MSC_VER
+#define _MSC_VER_WORKAROUND_GUARD 1
+#else
+#define _MSC_VER_WORKAROUND_GUARD 0
+#endif
+#ifndef _MSC_FULL_VER
+#define _MSC_FULL_VER_WORKAROUND_GUARD 1
+#else
+#define _MSC_FULL_VER_WORKAROUND_GUARD 0
+#endif
+#ifndef BOOST_MSVC
+#define BOOST_MSVC_WORKAROUND_GUARD 1
+#else
+#define BOOST_MSVC_WORKAROUND_GUARD 0
+#endif
+#ifndef BOOST_MSVC_FULL_VER
+#define BOOST_MSVC_FULL_VER_WORKAROUND_GUARD 1
+#else
+#define BOOST_MSVC_FULL_VER_WORKAROUND_GUARD 0
+#endif
+#ifndef __GNUC__
+#define __GNUC___WORKAROUND_GUARD 1
+#else
+#define __GNUC___WORKAROUND_GUARD 0
+#endif
+#ifndef __GNUC_MINOR__
+#define __GNUC_MINOR___WORKAROUND_GUARD 1
+#else
+#define __GNUC_MINOR___WORKAROUND_GUARD 0
+#endif
+#ifndef __GNUC_PATCHLEVEL__
+#define __GNUC_PATCHLEVEL___WORKAROUND_GUARD 1
+#else
+#define __GNUC_PATCHLEVEL___WORKAROUND_GUARD 0
+#endif
+#ifndef __IBMCPP__
+#define __IBMCPP___WORKAROUND_GUARD 1
+#else
+#define __IBMCPP___WORKAROUND_GUARD 0
+#endif
+#ifndef __SUNPRO_CC
+#define __SUNPRO_CC_WORKAROUND_GUARD 1
+#else
+#define __SUNPRO_CC_WORKAROUND_GUARD 0
+#endif
+#ifndef __DECCXX_VER
+#define __DECCXX_VER_WORKAROUND_GUARD 1
+#else
+#define __DECCXX_VER_WORKAROUND_GUARD 0
+#endif
+#ifndef __MWERKS__
+#define __MWERKS___WORKAROUND_GUARD 1
+#else
+#define __MWERKS___WORKAROUND_GUARD 0
+#endif
+#ifndef __EDG__
+#define __EDG___WORKAROUND_GUARD 1
+#else
+#define __EDG___WORKAROUND_GUARD 0
+#endif
+#ifndef __EDG_VERSION__
+#define __EDG_VERSION___WORKAROUND_GUARD 1
+#else
+#define __EDG_VERSION___WORKAROUND_GUARD 0
+#endif
+#ifndef __HP_aCC
+#define __HP_aCC_WORKAROUND_GUARD 1
+#else
+#define __HP_aCC_WORKAROUND_GUARD 0
+#endif
+#ifndef __hpxstd98
+#define __hpxstd98_WORKAROUND_GUARD 1
+#else
+#define __hpxstd98_WORKAROUND_GUARD 0
+#endif
+#ifndef _CRAYC
+#define _CRAYC_WORKAROUND_GUARD 1
+#else
+#define _CRAYC_WORKAROUND_GUARD 0
+#endif
+#ifndef __DMC__
+#define __DMC___WORKAROUND_GUARD 1
+#else
+#define __DMC___WORKAROUND_GUARD 0
+#endif
+#ifndef MPW_CPLUS
+#define MPW_CPLUS_WORKAROUND_GUARD 1
+#else
+#define MPW_CPLUS_WORKAROUND_GUARD 0
+#endif
+#ifndef __COMO__
+#define __COMO___WORKAROUND_GUARD 1
+#else
+#define __COMO___WORKAROUND_GUARD 0
+#endif
+#ifndef __COMO_VERSION__
+#define __COMO_VERSION___WORKAROUND_GUARD 1
+#else
+#define __COMO_VERSION___WORKAROUND_GUARD 0
+#endif
+#ifndef __INTEL_COMPILER
+#define __INTEL_COMPILER_WORKAROUND_GUARD 1
+#else
+#define __INTEL_COMPILER_WORKAROUND_GUARD 0
+#endif
+#ifndef __ICL
+#define __ICL_WORKAROUND_GUARD 1
+#else
+#define __ICL_WORKAROUND_GUARD 0
+#endif
+#ifndef _COMPILER_VERSION
+#define _COMPILER_VERSION_WORKAROUND_GUARD 1
+#else
+#define _COMPILER_VERSION_WORKAROUND_GUARD 0
+#endif
+
+#ifndef _RWSTD_VER
+#define _RWSTD_VER_WORKAROUND_GUARD 1
+#else
+#define _RWSTD_VER_WORKAROUND_GUARD 0
+#endif
+#ifndef BOOST_RWSTD_VER
+#define BOOST_RWSTD_VER_WORKAROUND_GUARD 1
+#else
+#define BOOST_RWSTD_VER_WORKAROUND_GUARD 0
+#endif
+#ifndef __GLIBCPP__
+#define __GLIBCPP___WORKAROUND_GUARD 1
+#else
+#define __GLIBCPP___WORKAROUND_GUARD 0
+#endif
+#ifndef _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC
+#define _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC_WORKAROUND_GUARD 1
+#else
+#define _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC_WORKAROUND_GUARD 0
+#endif
+#ifndef __SGI_STL_PORT
+#define __SGI_STL_PORT_WORKAROUND_GUARD 1
+#else
+#define __SGI_STL_PORT_WORKAROUND_GUARD 0
+#endif
+#ifndef _STLPORT_VERSION
+#define _STLPORT_VERSION_WORKAROUND_GUARD 1
+#else
+#define _STLPORT_VERSION_WORKAROUND_GUARD 0
+#endif
+#ifndef __LIBCOMO_VERSION__
+#define __LIBCOMO_VERSION___WORKAROUND_GUARD 1
+#else
+#define __LIBCOMO_VERSION___WORKAROUND_GUARD 0
+#endif
+#ifndef _CPPLIB_VER
+#define _CPPLIB_VER_WORKAROUND_GUARD 1
+#else
+#define _CPPLIB_VER_WORKAROUND_GUARD 0
+#endif
+
+#ifndef BOOST_INTEL_CXX_VERSION
+#define BOOST_INTEL_CXX_VERSION_WORKAROUND_GUARD 1
+#else
+#define BOOST_INTEL_CXX_VERSION_WORKAROUND_GUARD 0
+#endif
+#ifndef BOOST_INTEL_WIN
+#define BOOST_INTEL_WIN_WORKAROUND_GUARD 1
+#else
+#define BOOST_INTEL_WIN_WORKAROUND_GUARD 0
+#endif
+#ifndef BOOST_DINKUMWARE_STDLIB
+#define BOOST_DINKUMWARE_STDLIB_WORKAROUND_GUARD 1
+#else
+#define BOOST_DINKUMWARE_STDLIB_WORKAROUND_GUARD 0
+#endif
+#ifndef BOOST_INTEL
+#define BOOST_INTEL_WORKAROUND_GUARD 1
+#else
+#define BOOST_INTEL_WORKAROUND_GUARD 0
+#endif
+// Always define to zero, if it's used it'll be defined my MPL:
+#define BOOST_MPL_CFG_GCC_WORKAROUND_GUARD 0
+
+# define BOOST_WORKAROUND(symbol, test) \
+ ((symbol ## _WORKAROUND_GUARD + 0 == 0) && \
+ (symbol != 0) && (1 % (( (symbol test) ) + 1)))
+// ^ ^ ^ ^
+// The extra level of parenthesis nesting above, along with the
+// BOOST_OPEN_PAREN indirection below, is required to satisfy the
+// broken preprocessor in MWCW 8.3 and earlier.
+//
+// The basic mechanism works as follows:
+// (symbol test) + 1 => if (symbol test) then 2 else 1
+// 1 % ((symbol test) + 1) => if (symbol test) then 1 else 0
+//
+// The complication with % is for cooperation with BOOST_TESTED_AT().
+// When "test" is BOOST_TESTED_AT(x) and
+// BOOST_DETECT_OUTDATED_WORKAROUNDS is #defined,
+//
+// symbol test => if (symbol <= x) then 1 else -1
+// (symbol test) + 1 => if (symbol <= x) then 2 else 0
+// 1 % ((symbol test) + 1) => if (symbol <= x) then 1 else divide-by-zero
+//
+
+# ifdef BOOST_DETECT_OUTDATED_WORKAROUNDS
+# define BOOST_OPEN_PAREN (
+# define BOOST_TESTED_AT(value) > value) ?(-1): BOOST_OPEN_PAREN 1
+# else
+# define BOOST_TESTED_AT(value) != ((value)-(value))
+# endif
+
+# else
+
+# define BOOST_WORKAROUND(symbol, test) 0
+
+# endif
+
+#endif // WORKAROUND_DWA2002126_HPP
diff --git a/third_party/boost/boost/enable_shared_from_this.hpp b/third_party/boost/boost/enable_shared_from_this.hpp
new file mode 100644
index 0000000..b1bb63d
--- /dev/null
+++ b/third_party/boost/boost/enable_shared_from_this.hpp
@@ -0,0 +1,18 @@
+#ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
+#define BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
+
+//
+// enable_shared_from_this.hpp
+//
+// Copyright (c) 2002 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html
+//
+
+#include <boost/smart_ptr/enable_shared_from_this.hpp>
+
+#endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
diff --git a/third_party/boost/boost/exception/exception.hpp b/third_party/boost/boost/exception/exception.hpp
new file mode 100644
index 0000000..1f2bd9c
--- /dev/null
+++ b/third_party/boost/boost/exception/exception.hpp
@@ -0,0 +1,499 @@
+//Copyright (c) 2006-2009 Emil Dotchevski and Reverge Studios, Inc.
+
+//Distributed under the Boost Software License, Version 1.0. (See accompanying
+//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef UUID_274DA366004E11DCB1DDFE2E56D89593
+#define UUID_274DA366004E11DCB1DDFE2E56D89593
+#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
+#pragma GCC system_header
+#endif
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
+#pragma warning(push,1)
+#endif
+
+namespace
+boost
+ {
+ namespace
+ exception_detail
+ {
+ template <class T>
+ class
+ refcount_ptr
+ {
+ public:
+
+ refcount_ptr():
+ px_(0)
+ {
+ }
+
+ ~refcount_ptr()
+ {
+ release();
+ }
+
+ refcount_ptr( refcount_ptr const & x ):
+ px_(x.px_)
+ {
+ add_ref();
+ }
+
+ refcount_ptr &
+ operator=( refcount_ptr const & x )
+ {
+ adopt(x.px_);
+ return *this;
+ }
+
+ void
+ adopt( T * px )
+ {
+ release();
+ px_=px;
+ add_ref();
+ }
+
+ T *
+ get() const
+ {
+ return px_;
+ }
+
+ private:
+
+ T * px_;
+
+ void
+ add_ref()
+ {
+ if( px_ )
+ px_->add_ref();
+ }
+
+ void
+ release()
+ {
+ if( px_ && px_->release() )
+ px_=0;
+ }
+ };
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+
+ template <class Tag,class T>
+ class error_info;
+
+ typedef error_info<struct throw_function_,char const *> throw_function;
+ typedef error_info<struct throw_file_,char const *> throw_file;
+ typedef error_info<struct throw_line_,int> throw_line;
+
+ template <>
+ class
+ error_info<throw_function_,char const *>
+ {
+ public:
+ typedef char const * value_type;
+ value_type v_;
+ explicit
+ error_info( value_type v ):
+ v_(v)
+ {
+ }
+ };
+
+ template <>
+ class
+ error_info<throw_file_,char const *>
+ {
+ public:
+ typedef char const * value_type;
+ value_type v_;
+ explicit
+ error_info( value_type v ):
+ v_(v)
+ {
+ }
+ };
+
+ template <>
+ class
+ error_info<throw_line_,int>
+ {
+ public:
+ typedef int value_type;
+ value_type v_;
+ explicit
+ error_info( value_type v ):
+ v_(v)
+ {
+ }
+ };
+
+#if defined(__GNUC__)
+# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+# pragma GCC visibility push (default)
+# endif
+#endif
+ class exception;
+#if defined(__GNUC__)
+# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+# pragma GCC visibility pop
+# endif
+#endif
+
+ template <class T>
+ class shared_ptr;
+
+ namespace
+ exception_detail
+ {
+ class error_info_base;
+ struct type_info_;
+
+ struct
+ error_info_container
+ {
+ virtual char const * diagnostic_information( char const * ) const = 0;
+ virtual shared_ptr<error_info_base> get( type_info_ const & ) const = 0;
+ virtual void set( shared_ptr<error_info_base> const &, type_info_ const & ) = 0;
+ virtual void add_ref() const = 0;
+ virtual bool release() const = 0;
+ virtual refcount_ptr<exception_detail::error_info_container> clone() const = 0;
+
+ protected:
+
+ ~error_info_container() throw()
+ {
+ }
+ };
+
+ template <class>
+ struct get_info;
+
+ template <>
+ struct get_info<throw_function>;
+
+ template <>
+ struct get_info<throw_file>;
+
+ template <>
+ struct get_info<throw_line>;
+
+ char const * get_diagnostic_information( exception const &, char const * );
+
+ void copy_boost_exception( exception *, exception const * );
+
+ template <class E,class Tag,class T>
+ E const & set_info( E const &, error_info<Tag,T> const & );
+
+ template <class E>
+ E const & set_info( E const &, throw_function const & );
+
+ template <class E>
+ E const & set_info( E const &, throw_file const & );
+
+ template <class E>
+ E const & set_info( E const &, throw_line const & );
+ }
+
+#if defined(__GNUC__)
+# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+# pragma GCC visibility push (default)
+# endif
+#endif
+ class
+ exception
+ {
+ //<N3757>
+ public:
+ template <class Tag> void set( typename Tag::type const & );
+ template <class Tag> typename Tag::type const * get() const;
+ //</N3757>
+
+ protected:
+
+ exception():
+ throw_function_(0),
+ throw_file_(0),
+ throw_line_(-1)
+ {
+ }
+
+#ifdef __HP_aCC
+ //On HP aCC, this protected copy constructor prevents throwing boost::exception.
+ //On all other platforms, the same effect is achieved by the pure virtual destructor.
+ exception( exception const & x ) throw():
+ data_(x.data_),
+ throw_function_(x.throw_function_),
+ throw_file_(x.throw_file_),
+ throw_line_(x.throw_line_)
+ {
+ }
+#endif
+
+ virtual ~exception() throw()
+#ifndef __HP_aCC
+ = 0 //Workaround for HP aCC, =0 incorrectly leads to link errors.
+#endif
+ ;
+
+#if (defined(__MWERKS__) && __MWERKS__<=0x3207) || (defined(_MSC_VER) && _MSC_VER<=1310)
+ public:
+#else
+ private:
+
+ template <class E>
+ friend E const & exception_detail::set_info( E const &, throw_function const & );
+
+ template <class E>
+ friend E const & exception_detail::set_info( E const &, throw_file const & );
+
+ template <class E>
+ friend E const & exception_detail::set_info( E const &, throw_line const & );
+
+ template <class E,class Tag,class T>
+ friend E const & exception_detail::set_info( E const &, error_info<Tag,T> const & );
+
+ friend char const * exception_detail::get_diagnostic_information( exception const &, char const * );
+
+ template <class>
+ friend struct exception_detail::get_info;
+ friend struct exception_detail::get_info<throw_function>;
+ friend struct exception_detail::get_info<throw_file>;
+ friend struct exception_detail::get_info<throw_line>;
+ friend void exception_detail::copy_boost_exception( exception *, exception const * );
+#endif
+ mutable exception_detail::refcount_ptr<exception_detail::error_info_container> data_;
+ mutable char const * throw_function_;
+ mutable char const * throw_file_;
+ mutable int throw_line_;
+ };
+#if defined(__GNUC__)
+# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+# pragma GCC visibility pop
+# endif
+#endif
+
+ inline
+ exception::
+ ~exception() throw()
+ {
+ }
+
+ namespace
+ exception_detail
+ {
+ template <class E>
+ E const &
+ set_info( E const & x, throw_function const & y )
+ {
+ x.throw_function_=y.v_;
+ return x;
+ }
+
+ template <class E>
+ E const &
+ set_info( E const & x, throw_file const & y )
+ {
+ x.throw_file_=y.v_;
+ return x;
+ }
+
+ template <class E>
+ E const &
+ set_info( E const & x, throw_line const & y )
+ {
+ x.throw_line_=y.v_;
+ return x;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+
+ namespace
+ exception_detail
+ {
+#if defined(__GNUC__)
+# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+# pragma GCC visibility push (default)
+# endif
+#endif
+ template <class T>
+ struct
+ error_info_injector:
+ public T,
+ public exception
+ {
+ explicit
+ error_info_injector( T const & x ):
+ T(x)
+ {
+ }
+
+ ~error_info_injector() throw()
+ {
+ }
+ };
+#if defined(__GNUC__)
+# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+# pragma GCC visibility pop
+# endif
+#endif
+
+ struct large_size { char c[256]; };
+ large_size dispatch_boost_exception( exception const * );
+
+ struct small_size { };
+ small_size dispatch_boost_exception( void const * );
+
+ template <class,int>
+ struct enable_error_info_helper;
+
+ template <class T>
+ struct
+ enable_error_info_helper<T,sizeof(large_size)>
+ {
+ typedef T type;
+ };
+
+ template <class T>
+ struct
+ enable_error_info_helper<T,sizeof(small_size)>
+ {
+ typedef error_info_injector<T> type;
+ };
+
+ template <class T>
+ struct
+ enable_error_info_return_type
+ {
+ typedef typename enable_error_info_helper<T,sizeof(exception_detail::dispatch_boost_exception(static_cast<T *>(0)))>::type type;
+ };
+ }
+
+ template <class T>
+ inline
+ typename
+ exception_detail::enable_error_info_return_type<T>::type
+ enable_error_info( T const & x )
+ {
+ typedef typename exception_detail::enable_error_info_return_type<T>::type rt;
+ return rt(x);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+
+ namespace
+ exception_detail
+ {
+#if defined(__GNUC__)
+# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+# pragma GCC visibility push (default)
+# endif
+#endif
+ class
+ clone_base
+ {
+ public:
+
+ virtual clone_base const * clone() const = 0;
+ virtual void rethrow() const = 0;
+
+ virtual
+ ~clone_base() throw()
+ {
+ }
+ };
+#if defined(__GNUC__)
+# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+# pragma GCC visibility pop
+# endif
+#endif
+
+ inline
+ void
+ copy_boost_exception( exception * a, exception const * b )
+ {
+ refcount_ptr<error_info_container> data;
+ if( error_info_container * d=b->data_.get() )
+ data = d->clone();
+ a->throw_file_ = b->throw_file_;
+ a->throw_line_ = b->throw_line_;
+ a->throw_function_ = b->throw_function_;
+ a->data_ = data;
+ }
+
+ inline
+ void
+ copy_boost_exception( void *, void const * )
+ {
+ }
+
+#if defined(__GNUC__)
+# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+# pragma GCC visibility push (default)
+# endif
+#endif
+ template <class T>
+ class
+ clone_impl:
+ public T,
+ public virtual clone_base
+ {
+ struct clone_tag { };
+ clone_impl( clone_impl const & x, clone_tag ):
+ T(x)
+ {
+ copy_boost_exception(this,&x);
+ }
+
+ public:
+
+ explicit
+ clone_impl( T const & x ):
+ T(x)
+ {
+ copy_boost_exception(this,&x);
+ }
+
+ ~clone_impl() throw()
+ {
+ }
+
+ private:
+
+ clone_base const *
+ clone() const
+ {
+ return new clone_impl(*this,clone_tag());
+ }
+
+ void
+ rethrow() const
+ {
+ throw*this;
+ }
+ };
+ }
+#if defined(__GNUC__)
+# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+# pragma GCC visibility pop
+# endif
+#endif
+
+ template <class T>
+ inline
+ exception_detail::clone_impl<T>
+ enable_current_exception( T const & x )
+ {
+ return exception_detail::clone_impl<T>(x);
+ }
+ }
+
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
+#pragma warning(pop)
+#endif
+#endif
diff --git a/third_party/boost/boost/function.hpp b/third_party/boost/boost/function.hpp
new file mode 100644
index 0000000..b72842b
--- /dev/null
+++ b/third_party/boost/boost/function.hpp
@@ -0,0 +1,66 @@
+// Boost.Function library
+
+// Copyright Douglas Gregor 2001-2003. Use, modification and
+// distribution is subject to the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// For more information, see http://www.boost.org/libs/function
+
+// William Kempf, Jesse Jones and Karl Nelson were all very helpful in the
+// design of this library.
+
+#include <functional> // unary_function, binary_function
+
+#include <boost/preprocessor/iterate.hpp>
+#include <boost/detail/workaround.hpp>
+
+#ifndef BOOST_FUNCTION_MAX_ARGS
+# define BOOST_FUNCTION_MAX_ARGS 10
+#endif // BOOST_FUNCTION_MAX_ARGS
+
+// Include the prologue here so that the use of file-level iteration
+// in anything that may be included by function_template.hpp doesn't break
+#include <boost/function/detail/prologue.hpp>
+
+// Older Visual Age C++ version do not handle the file iteration well
+#if BOOST_WORKAROUND(__IBMCPP__, >= 500) && BOOST_WORKAROUND(__IBMCPP__, < 800)
+# if BOOST_FUNCTION_MAX_ARGS >= 0
+# include <boost/function/function0.hpp>
+# endif
+# if BOOST_FUNCTION_MAX_ARGS >= 1
+# include <boost/function/function1.hpp>
+# endif
+# if BOOST_FUNCTION_MAX_ARGS >= 2
+# include <boost/function/function2.hpp>
+# endif
+# if BOOST_FUNCTION_MAX_ARGS >= 3
+# include <boost/function/function3.hpp>
+# endif
+# if BOOST_FUNCTION_MAX_ARGS >= 4
+# include <boost/function/function4.hpp>
+# endif
+# if BOOST_FUNCTION_MAX_ARGS >= 5
+# include <boost/function/function5.hpp>
+# endif
+# if BOOST_FUNCTION_MAX_ARGS >= 6
+# include <boost/function/function6.hpp>
+# endif
+# if BOOST_FUNCTION_MAX_ARGS >= 7
+# include <boost/function/function7.hpp>
+# endif
+# if BOOST_FUNCTION_MAX_ARGS >= 8
+# include <boost/function/function8.hpp>
+# endif
+# if BOOST_FUNCTION_MAX_ARGS >= 9
+# include <boost/function/function9.hpp>
+# endif
+# if BOOST_FUNCTION_MAX_ARGS >= 10
+# include <boost/function/function10.hpp>
+# endif
+#else
+// What is the '3' for?
+# define BOOST_PP_ITERATION_PARAMS_1 (3,(0,BOOST_FUNCTION_MAX_ARGS,<boost/function/detail/function_iterate.hpp>))
+# include BOOST_PP_ITERATE()
+# undef BOOST_PP_ITERATION_PARAMS_1
+#endif
diff --git a/third_party/boost/boost/function/detail/function_iterate.hpp b/third_party/boost/boost/function/detail/function_iterate.hpp
new file mode 100644
index 0000000..d144e2f
--- /dev/null
+++ b/third_party/boost/boost/function/detail/function_iterate.hpp
@@ -0,0 +1,15 @@
+// Boost.Function library
+
+// Copyright Douglas Gregor 2003. Use, modification and
+// distribution is subject to the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// For more information, see http://www.boost.org
+#if !defined(BOOST_PP_IS_ITERATING)
+# error Boost.Function - do not include this file!
+#endif
+
+#define BOOST_FUNCTION_NUM_ARGS BOOST_PP_ITERATION()
+#include <boost/function/detail/maybe_include.hpp>
+#undef BOOST_FUNCTION_NUM_ARGS
diff --git a/third_party/boost/boost/function/detail/maybe_include.hpp b/third_party/boost/boost/function/detail/maybe_include.hpp
new file mode 100644
index 0000000..92f71bb
--- /dev/null
+++ b/third_party/boost/boost/function/detail/maybe_include.hpp
@@ -0,0 +1,267 @@
+// Boost.Function library
+
+// Copyright Douglas Gregor 2003. Use, modification and
+// distribution is subject to the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// For more information, see http://www.boost.org
+
+#if BOOST_FUNCTION_NUM_ARGS == 0
+# ifndef BOOST_FUNCTION_0
+# define BOOST_FUNCTION_0
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 1
+# ifndef BOOST_FUNCTION_1
+# define BOOST_FUNCTION_1
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 2
+# ifndef BOOST_FUNCTION_2
+# define BOOST_FUNCTION_2
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 3
+# ifndef BOOST_FUNCTION_3
+# define BOOST_FUNCTION_3
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 4
+# ifndef BOOST_FUNCTION_4
+# define BOOST_FUNCTION_4
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 5
+# ifndef BOOST_FUNCTION_5
+# define BOOST_FUNCTION_5
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 6
+# ifndef BOOST_FUNCTION_6
+# define BOOST_FUNCTION_6
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 7
+# ifndef BOOST_FUNCTION_7
+# define BOOST_FUNCTION_7
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 8
+# ifndef BOOST_FUNCTION_8
+# define BOOST_FUNCTION_8
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 9
+# ifndef BOOST_FUNCTION_9
+# define BOOST_FUNCTION_9
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 10
+# ifndef BOOST_FUNCTION_10
+# define BOOST_FUNCTION_10
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 11
+# ifndef BOOST_FUNCTION_11
+# define BOOST_FUNCTION_11
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 12
+# ifndef BOOST_FUNCTION_12
+# define BOOST_FUNCTION_12
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 13
+# ifndef BOOST_FUNCTION_13
+# define BOOST_FUNCTION_13
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 14
+# ifndef BOOST_FUNCTION_14
+# define BOOST_FUNCTION_14
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 15
+# ifndef BOOST_FUNCTION_15
+# define BOOST_FUNCTION_15
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 16
+# ifndef BOOST_FUNCTION_16
+# define BOOST_FUNCTION_16
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 17
+# ifndef BOOST_FUNCTION_17
+# define BOOST_FUNCTION_17
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 18
+# ifndef BOOST_FUNCTION_18
+# define BOOST_FUNCTION_18
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 19
+# ifndef BOOST_FUNCTION_19
+# define BOOST_FUNCTION_19
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 20
+# ifndef BOOST_FUNCTION_20
+# define BOOST_FUNCTION_20
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 21
+# ifndef BOOST_FUNCTION_21
+# define BOOST_FUNCTION_21
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 22
+# ifndef BOOST_FUNCTION_22
+# define BOOST_FUNCTION_22
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 23
+# ifndef BOOST_FUNCTION_23
+# define BOOST_FUNCTION_23
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 24
+# ifndef BOOST_FUNCTION_24
+# define BOOST_FUNCTION_24
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 25
+# ifndef BOOST_FUNCTION_25
+# define BOOST_FUNCTION_25
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 26
+# ifndef BOOST_FUNCTION_26
+# define BOOST_FUNCTION_26
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 27
+# ifndef BOOST_FUNCTION_27
+# define BOOST_FUNCTION_27
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 28
+# ifndef BOOST_FUNCTION_28
+# define BOOST_FUNCTION_28
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 29
+# ifndef BOOST_FUNCTION_29
+# define BOOST_FUNCTION_29
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 30
+# ifndef BOOST_FUNCTION_30
+# define BOOST_FUNCTION_30
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 31
+# ifndef BOOST_FUNCTION_31
+# define BOOST_FUNCTION_31
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 32
+# ifndef BOOST_FUNCTION_32
+# define BOOST_FUNCTION_32
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 33
+# ifndef BOOST_FUNCTION_33
+# define BOOST_FUNCTION_33
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 34
+# ifndef BOOST_FUNCTION_34
+# define BOOST_FUNCTION_34
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 35
+# ifndef BOOST_FUNCTION_35
+# define BOOST_FUNCTION_35
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 36
+# ifndef BOOST_FUNCTION_36
+# define BOOST_FUNCTION_36
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 37
+# ifndef BOOST_FUNCTION_37
+# define BOOST_FUNCTION_37
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 38
+# ifndef BOOST_FUNCTION_38
+# define BOOST_FUNCTION_38
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 39
+# ifndef BOOST_FUNCTION_39
+# define BOOST_FUNCTION_39
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 40
+# ifndef BOOST_FUNCTION_40
+# define BOOST_FUNCTION_40
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 41
+# ifndef BOOST_FUNCTION_41
+# define BOOST_FUNCTION_41
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 42
+# ifndef BOOST_FUNCTION_42
+# define BOOST_FUNCTION_42
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 43
+# ifndef BOOST_FUNCTION_43
+# define BOOST_FUNCTION_43
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 44
+# ifndef BOOST_FUNCTION_44
+# define BOOST_FUNCTION_44
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 45
+# ifndef BOOST_FUNCTION_45
+# define BOOST_FUNCTION_45
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 46
+# ifndef BOOST_FUNCTION_46
+# define BOOST_FUNCTION_46
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 47
+# ifndef BOOST_FUNCTION_47
+# define BOOST_FUNCTION_47
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 48
+# ifndef BOOST_FUNCTION_48
+# define BOOST_FUNCTION_48
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 49
+# ifndef BOOST_FUNCTION_49
+# define BOOST_FUNCTION_49
+# include <boost/function/function_template.hpp>
+# endif
+#elif BOOST_FUNCTION_NUM_ARGS == 50
+# ifndef BOOST_FUNCTION_50
+# define BOOST_FUNCTION_50
+# include <boost/function/function_template.hpp>
+# endif
+#else
+# error Cannot handle Boost.Function objects that accept more than 50 arguments!
+#endif
diff --git a/third_party/boost/boost/function/detail/prologue.hpp b/third_party/boost/boost/function/detail/prologue.hpp
new file mode 100644
index 0000000..53d0f05
--- /dev/null
+++ b/third_party/boost/boost/function/detail/prologue.hpp
@@ -0,0 +1,26 @@
+// Boost.Function library
+
+// Copyright Douglas Gregor 2002-2003. Use, modification and
+// distribution is subject to the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// For more information, see http://www.boost.org
+
+#ifndef BOOST_FUNCTION_PROLOGUE_HPP
+#define BOOST_FUNCTION_PROLOGUE_HPP
+# include <cassert>
+# include <algorithm>
+# include <boost/config/no_tr1/functional.hpp> // unary_function, binary_function
+# include <boost/throw_exception.hpp>
+# include <boost/config.hpp>
+# include <boost/function/function_base.hpp>
+# include <boost/mem_fn.hpp>
+# include <boost/type_traits/is_integral.hpp>
+# include <boost/preprocessor/enum.hpp>
+# include <boost/preprocessor/enum_params.hpp>
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/repeat.hpp>
+# include <boost/preprocessor/inc.hpp>
+# include <boost/type_traits/is_void.hpp>
+#endif // BOOST_FUNCTION_PROLOGUE_HPP
diff --git a/third_party/boost/boost/function/function_base.hpp b/third_party/boost/boost/function/function_base.hpp
new file mode 100644
index 0000000..d683988
--- /dev/null
+++ b/third_party/boost/boost/function/function_base.hpp
@@ -0,0 +1,892 @@
+// Boost.Function library
+
+// Copyright Douglas Gregor 2001-2006
+// Copyright Emil Dotchevski 2007
+// Use, modification and distribution is subject to the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// For more information, see http://www.boost.org
+
+#ifndef BOOST_FUNCTION_BASE_HEADER
+#define BOOST_FUNCTION_BASE_HEADER
+
+#include <stdexcept>
+#include <string>
+#include <memory>
+#include <new>
+#include <boost/config.hpp>
+#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/assert.hpp>
+#include <boost/integer.hpp>
+#include <boost/type_traits/has_trivial_copy.hpp>
+#include <boost/type_traits/has_trivial_destructor.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/is_volatile.hpp>
+#include <boost/type_traits/composite_traits.hpp>
+#include <boost/ref.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#ifndef BOOST_NO_SFINAE
+# include "boost/utility/enable_if.hpp"
+#else
+# include "boost/mpl/bool.hpp"
+#endif
+#include <boost/function_equal.hpp>
+#include <boost/function/function_fwd.hpp>
+
+#if defined(BOOST_MSVC)
+# pragma warning( push )
+# pragma warning( disable : 4793 ) // complaint about native code generation
+# pragma warning( disable : 4127 ) // "conditional expression is constant"
+#endif
+
+// Define BOOST_FUNCTION_STD_NS to the namespace that contains type_info.
+#ifdef BOOST_NO_STD_TYPEINFO
+// Embedded VC++ does not have type_info in namespace std
+# define BOOST_FUNCTION_STD_NS
+#else
+# define BOOST_FUNCTION_STD_NS std
+#endif
+
+// Borrowed from Boost.Python library: determines the cases where we
+// need to use std::type_info::name to compare instead of operator==.
+#if defined( BOOST_NO_TYPEID )
+# define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) ((X)==(Y))
+#elif defined(__GNUC__) \
+ || defined(_AIX) \
+ || ( defined(__sgi) && defined(__host_mips))
+# include <cstring>
+# define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) \
+ (std::strcmp((X).name(),(Y).name()) == 0)
+# else
+# define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) ((X)==(Y))
+#endif
+
+#if defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG)
+# define BOOST_FUNCTION_TARGET_FIX(x) x
+#else
+# define BOOST_FUNCTION_TARGET_FIX(x)
+#endif // __ICL etc
+
+# define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
+ typename ::boost::enable_if_c< \
+ !(::boost::is_integral<Functor>::value), \
+ Type>::type
+
+namespace boost {
+ namespace detail {
+ namespace function {
+ class X;
+
+ /**
+ * A buffer used to store small function objects in
+ * boost::function. It is a union containing function pointers,
+ * object pointers, and a structure that resembles a bound
+ * member function pointer.
+ */
+ union function_buffer
+ {
+ // For pointers to function objects
+ mutable void* obj_ptr;
+
+ // For pointers to std::type_info objects
+ struct type_t {
+ // (get_functor_type_tag, check_functor_type_tag).
+ const detail::sp_typeinfo* type;
+
+ // Whether the type is const-qualified.
+ bool const_qualified;
+ // Whether the type is volatile-qualified.
+ bool volatile_qualified;
+ } type;
+
+ // For function pointers of all kinds
+ mutable void (*func_ptr)();
+
+ // For bound member pointers
+ struct bound_memfunc_ptr_t {
+ void (X::*memfunc_ptr)(int);
+ void* obj_ptr;
+ } bound_memfunc_ptr;
+
+ // For references to function objects. We explicitly keep
+ // track of the cv-qualifiers on the object referenced.
+ struct obj_ref_t {
+ mutable void* obj_ptr;
+ bool is_const_qualified;
+ bool is_volatile_qualified;
+ } obj_ref;
+
+ // To relax aliasing constraints
+ mutable char data;
+ };
+
+ /**
+ * The unusable class is a placeholder for unused function arguments
+ * It is also completely unusable except that it constructable from
+ * anything. This helps compilers without partial specialization to
+ * handle Boost.Function objects returning void.
+ */
+ struct unusable
+ {
+ unusable() {}
+ template<typename T> unusable(const T&) {}
+ };
+
+ /* Determine the return type. This supports compilers that do not support
+ * void returns or partial specialization by silently changing the return
+ * type to "unusable".
+ */
+ template<typename T> struct function_return_type { typedef T type; };
+
+ template<>
+ struct function_return_type<void>
+ {
+ typedef unusable type;
+ };
+
+ // The operation type to perform on the given functor/function pointer
+ enum functor_manager_operation_type {
+ clone_functor_tag,
+ move_functor_tag,
+ destroy_functor_tag,
+ check_functor_type_tag,
+ get_functor_type_tag
+ };
+
+ // Tags used to decide between different types of functions
+ struct function_ptr_tag {};
+ struct function_obj_tag {};
+ struct member_ptr_tag {};
+ struct function_obj_ref_tag {};
+
+ template<typename F>
+ class get_function_tag
+ {
+ typedef typename mpl::if_c<(is_pointer<F>::value),
+ function_ptr_tag,
+ function_obj_tag>::type ptr_or_obj_tag;
+
+ typedef typename mpl::if_c<(is_member_pointer<F>::value),
+ member_ptr_tag,
+ ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
+
+ typedef typename mpl::if_c<(is_reference_wrapper<F>::value),
+ function_obj_ref_tag,
+ ptr_or_obj_or_mem_tag>::type or_ref_tag;
+
+ public:
+ typedef or_ref_tag type;
+ };
+
+ // The trivial manager does nothing but return the same pointer (if we
+ // are cloning) or return the null pointer (if we are deleting).
+ template<typename F>
+ struct reference_manager
+ {
+ static inline void
+ manage(const function_buffer& in_buffer, function_buffer& out_buffer,
+ functor_manager_operation_type op)
+ {
+ switch (op) {
+ case clone_functor_tag:
+ out_buffer.obj_ref = in_buffer.obj_ref;
+ return;
+
+ case move_functor_tag:
+ out_buffer.obj_ref = in_buffer.obj_ref;
+ in_buffer.obj_ref.obj_ptr = 0;
+ return;
+
+ case destroy_functor_tag:
+ out_buffer.obj_ref.obj_ptr = 0;
+ return;
+
+ case check_functor_type_tag:
+ {
+ const detail::sp_typeinfo& check_type
+ = *out_buffer.type.type;
+
+ // Check whether we have the same type. We can add
+ // cv-qualifiers, but we can't take them away.
+ if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(F))
+ && (!in_buffer.obj_ref.is_const_qualified
+ || out_buffer.type.const_qualified)
+ && (!in_buffer.obj_ref.is_volatile_qualified
+ || out_buffer.type.volatile_qualified))
+ out_buffer.obj_ptr = in_buffer.obj_ref.obj_ptr;
+ else
+ out_buffer.obj_ptr = 0;
+ }
+ return;
+
+ case get_functor_type_tag:
+ out_buffer.type.type = &BOOST_SP_TYPEID(F);
+ out_buffer.type.const_qualified = in_buffer.obj_ref.is_const_qualified;
+ out_buffer.type.volatile_qualified = in_buffer.obj_ref.is_volatile_qualified;
+ return;
+ }
+ }
+ };
+
+ /**
+ * Determine if boost::function can use the small-object
+ * optimization with the function object type F.
+ */
+ template<typename F>
+ struct function_allows_small_object_optimization
+ {
+ BOOST_STATIC_CONSTANT
+ (bool,
+ value = ((sizeof(F) <= sizeof(function_buffer) &&
+ (alignment_of<function_buffer>::value
+ % alignment_of<F>::value == 0))));
+ };
+
+ template <typename F,typename A>
+ struct functor_wrapper: public F, public A
+ {
+ functor_wrapper( F f, A a ):
+ F(f),
+ A(a)
+ {
+ }
+
+ functor_wrapper(const functor_wrapper& f) :
+ F(static_cast<const F&>(f)),
+ A(static_cast<const A&>(f))
+ {
+ }
+ };
+
+ /**
+ * The functor_manager class contains a static function "manage" which
+ * can clone or destroy the given function/function object pointer.
+ */
+ template<typename Functor>
+ struct functor_manager_common
+ {
+ typedef Functor functor_type;
+
+ // Function pointers
+ static inline void
+ manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer,
+ functor_manager_operation_type op)
+ {
+ if (op == clone_functor_tag)
+ out_buffer.func_ptr = in_buffer.func_ptr;
+ else if (op == move_functor_tag) {
+ out_buffer.func_ptr = in_buffer.func_ptr;
+ in_buffer.func_ptr = 0;
+ } else if (op == destroy_functor_tag)
+ out_buffer.func_ptr = 0;
+ else if (op == check_functor_type_tag) {
+ const boost::detail::sp_typeinfo& check_type
+ = *out_buffer.type.type;
+ if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))
+ out_buffer.obj_ptr = &in_buffer.func_ptr;
+ else
+ out_buffer.obj_ptr = 0;
+ } else /* op == get_functor_type_tag */ {
+ out_buffer.type.type = &BOOST_SP_TYPEID(Functor);
+ out_buffer.type.const_qualified = false;
+ out_buffer.type.volatile_qualified = false;
+ }
+ }
+
+ // Function objects that fit in the small-object buffer.
+ static inline void
+ manage_small(const function_buffer& in_buffer, function_buffer& out_buffer,
+ functor_manager_operation_type op)
+ {
+ if (op == clone_functor_tag || op == move_functor_tag) {
+ const functor_type* in_functor =
+ reinterpret_cast<const functor_type*>(&in_buffer.data);
+ new (reinterpret_cast<void*>(&out_buffer.data)) functor_type(*in_functor);
+
+ if (op == move_functor_tag) {
+ functor_type* f = reinterpret_cast<functor_type*>(&in_buffer.data);
+ (void)f; // suppress warning about the value of f not being used (MSVC)
+ f->~Functor();
+ }
+ } else if (op == destroy_functor_tag) {
+ // Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
+ functor_type* f = reinterpret_cast<functor_type*>(&out_buffer.data);
+ (void)f; // suppress warning about the value of f not being used (MSVC)
+ f->~Functor();
+ } else if (op == check_functor_type_tag) {
+ const detail::sp_typeinfo& check_type
+ = *out_buffer.type.type;
+ if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))
+ out_buffer.obj_ptr = &in_buffer.data;
+ else
+ out_buffer.obj_ptr = 0;
+ } else /* op == get_functor_type_tag */ {
+ out_buffer.type.type = &BOOST_SP_TYPEID(Functor);
+ out_buffer.type.const_qualified = false;
+ out_buffer.type.volatile_qualified = false;
+ }
+ }
+ };
+
+ template<typename Functor>
+ struct functor_manager
+ {
+ private:
+ typedef Functor functor_type;
+
+ // Function pointers
+ static inline void
+ manager(const function_buffer& in_buffer, function_buffer& out_buffer,
+ functor_manager_operation_type op, function_ptr_tag)
+ {
+ functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
+ }
+
+ // Function objects that fit in the small-object buffer.
+ static inline void
+ manager(const function_buffer& in_buffer, function_buffer& out_buffer,
+ functor_manager_operation_type op, mpl::true_)
+ {
+ functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
+ }
+
+ // Function objects that require heap allocation
+ static inline void
+ manager(const function_buffer& in_buffer, function_buffer& out_buffer,
+ functor_manager_operation_type op, mpl::false_)
+ {
+ if (op == clone_functor_tag) {
+ // Clone the functor
+ // GCC 2.95.3 gets the CV qualifiers wrong here, so we
+ // can't do the static_cast that we should do.
+ // jewillco: Changing this to static_cast because GCC 2.95.3 is
+ // obsolete.
+ const functor_type* f =
+ static_cast<const functor_type*>(in_buffer.obj_ptr);
+ functor_type* new_f = new functor_type(*f);
+ out_buffer.obj_ptr = new_f;
+ } else if (op == move_functor_tag) {
+ out_buffer.obj_ptr = in_buffer.obj_ptr;
+ in_buffer.obj_ptr = 0;
+ } else if (op == destroy_functor_tag) {
+ /* Cast from the void pointer to the functor pointer type */
+ functor_type* f =
+ static_cast<functor_type*>(out_buffer.obj_ptr);
+ delete f;
+ out_buffer.obj_ptr = 0;
+ } else if (op == check_functor_type_tag) {
+ const detail::sp_typeinfo& check_type
+ = *out_buffer.type.type;
+ if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))
+ out_buffer.obj_ptr = in_buffer.obj_ptr;
+ else
+ out_buffer.obj_ptr = 0;
+ } else /* op == get_functor_type_tag */ {
+ out_buffer.type.type = &BOOST_SP_TYPEID(Functor);
+ out_buffer.type.const_qualified = false;
+ out_buffer.type.volatile_qualified = false;
+ }
+ }
+
+ // For function objects, we determine whether the function
+ // object can use the small-object optimization buffer or
+ // whether we need to allocate it on the heap.
+ static inline void
+ manager(const function_buffer& in_buffer, function_buffer& out_buffer,
+ functor_manager_operation_type op, function_obj_tag)
+ {
+ manager(in_buffer, out_buffer, op,
+ mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>());
+ }
+
+ // For member pointers, we use the small-object optimization buffer.
+ static inline void
+ manager(const function_buffer& in_buffer, function_buffer& out_buffer,
+ functor_manager_operation_type op, member_ptr_tag)
+ {
+ manager(in_buffer, out_buffer, op, mpl::true_());
+ }
+
+ public:
+ /* Dispatch to an appropriate manager based on whether we have a
+ function pointer or a function object pointer. */
+ static inline void
+ manage(const function_buffer& in_buffer, function_buffer& out_buffer,
+ functor_manager_operation_type op)
+ {
+ typedef typename get_function_tag<functor_type>::type tag_type;
+ switch (op) {
+ case get_functor_type_tag:
+ out_buffer.type.type = &BOOST_SP_TYPEID(functor_type);
+ out_buffer.type.const_qualified = false;
+ out_buffer.type.volatile_qualified = false;
+ return;
+
+ default:
+ manager(in_buffer, out_buffer, op, tag_type());
+ return;
+ }
+ }
+ };
+
+ template<typename Functor, typename Allocator>
+ struct functor_manager_a
+ {
+ private:
+ typedef Functor functor_type;
+
+ // Function pointers
+ static inline void
+ manager(const function_buffer& in_buffer, function_buffer& out_buffer,
+ functor_manager_operation_type op, function_ptr_tag)
+ {
+ functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
+ }
+
+ // Function objects that fit in the small-object buffer.
+ static inline void
+ manager(const function_buffer& in_buffer, function_buffer& out_buffer,
+ functor_manager_operation_type op, mpl::true_)
+ {
+ functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
+ }
+
+ // Function objects that require heap allocation
+ static inline void
+ manager(const function_buffer& in_buffer, function_buffer& out_buffer,
+ functor_manager_operation_type op, mpl::false_)
+ {
+ typedef functor_wrapper<Functor,Allocator> functor_wrapper_type;
+ typedef typename Allocator::template rebind<functor_wrapper_type>::other
+ wrapper_allocator_type;
+ typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type;
+
+ if (op == clone_functor_tag) {
+ // Clone the functor
+ // GCC 2.95.3 gets the CV qualifiers wrong here, so we
+ // can't do the static_cast that we should do.
+ const functor_wrapper_type* f =
+ static_cast<const functor_wrapper_type*>(in_buffer.obj_ptr);
+ wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f));
+ wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
+ wrapper_allocator.construct(copy, *f);
+
+ // Get back to the original pointer type
+ functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
+ out_buffer.obj_ptr = new_f;
+ } else if (op == move_functor_tag) {
+ out_buffer.obj_ptr = in_buffer.obj_ptr;
+ in_buffer.obj_ptr = 0;
+ } else if (op == destroy_functor_tag) {
+ /* Cast from the void pointer to the functor_wrapper_type */
+ functor_wrapper_type* victim =
+ static_cast<functor_wrapper_type*>(in_buffer.obj_ptr);
+ wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim));
+ wrapper_allocator.destroy(victim);
+ wrapper_allocator.deallocate(victim,1);
+ out_buffer.obj_ptr = 0;
+ } else if (op == check_functor_type_tag) {
+ const detail::sp_typeinfo& check_type
+ = *out_buffer.type.type;
+ if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))
+ out_buffer.obj_ptr = in_buffer.obj_ptr;
+ else
+ out_buffer.obj_ptr = 0;
+ } else /* op == get_functor_type_tag */ {
+ out_buffer.type.type = &BOOST_SP_TYPEID(Functor);
+ out_buffer.type.const_qualified = false;
+ out_buffer.type.volatile_qualified = false;
+ }
+ }
+
+ // For function objects, we determine whether the function
+ // object can use the small-object optimization buffer or
+ // whether we need to allocate it on the heap.
+ static inline void
+ manager(const function_buffer& in_buffer, function_buffer& out_buffer,
+ functor_manager_operation_type op, function_obj_tag)
+ {
+ manager(in_buffer, out_buffer, op,
+ mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>());
+ }
+
+ public:
+ /* Dispatch to an appropriate manager based on whether we have a
+ function pointer or a function object pointer. */
+ static inline void
+ manage(const function_buffer& in_buffer, function_buffer& out_buffer,
+ functor_manager_operation_type op)
+ {
+ typedef typename get_function_tag<functor_type>::type tag_type;
+ switch (op) {
+ case get_functor_type_tag:
+ out_buffer.type.type = &BOOST_SP_TYPEID(functor_type);
+ out_buffer.type.const_qualified = false;
+ out_buffer.type.volatile_qualified = false;
+ return;
+
+ default:
+ manager(in_buffer, out_buffer, op, tag_type());
+ return;
+ }
+ }
+ };
+
+ // A type that is only used for comparisons against zero
+ struct useless_clear_type {};
+
+#ifdef BOOST_NO_SFINAE
+ // These routines perform comparisons between a Boost.Function
+ // object and an arbitrary function object (when the last
+ // parameter is mpl::bool_<false>) or against zero (when the
+ // last parameter is mpl::bool_<true>). They are only necessary
+ // for compilers that don't support SFINAE.
+ template<typename Function, typename Functor>
+ bool
+ compare_equal(const Function& f, const Functor&, int, mpl::bool_<true>)
+ { return f.empty(); }
+
+ template<typename Function, typename Functor>
+ bool
+ compare_not_equal(const Function& f, const Functor&, int,
+ mpl::bool_<true>)
+ { return !f.empty(); }
+
+ template<typename Function, typename Functor>
+ bool
+ compare_equal(const Function& f, const Functor& g, long,
+ mpl::bool_<false>)
+ {
+ if (const Functor* fp = f.template target<Functor>())
+ return function_equal(*fp, g);
+ else return false;
+ }
+
+ template<typename Function, typename Functor>
+ bool
+ compare_equal(const Function& f, const reference_wrapper<Functor>& g,
+ int, mpl::bool_<false>)
+ {
+ if (const Functor* fp = f.template target<Functor>())
+ return fp == g.get_pointer();
+ else return false;
+ }
+
+ template<typename Function, typename Functor>
+ bool
+ compare_not_equal(const Function& f, const Functor& g, long,
+ mpl::bool_<false>)
+ {
+ if (const Functor* fp = f.template target<Functor>())
+ return !function_equal(*fp, g);
+ else return true;
+ }
+
+ template<typename Function, typename Functor>
+ bool
+ compare_not_equal(const Function& f,
+ const reference_wrapper<Functor>& g, int,
+ mpl::bool_<false>)
+ {
+ if (const Functor* fp = f.template target<Functor>())
+ return fp != g.get_pointer();
+ else return true;
+ }
+#endif // BOOST_NO_SFINAE
+
+ /**
+ * Stores the "manager" portion of the vtable for a
+ * boost::function object.
+ */
+ struct vtable_base
+ {
+ void (*manager)(const function_buffer& in_buffer,
+ function_buffer& out_buffer,
+ functor_manager_operation_type op);
+ };
+ } // end namespace function
+ } // end namespace detail
+
+/**
+ * The function_base class contains the basic elements needed for the
+ * function1, function2, function3, etc. classes. It is common to all
+ * functions (and as such can be used to tell if we have one of the
+ * functionN objects).
+ */
+class function_base
+{
+public:
+ function_base() : vtable(0) { }
+
+ /** Determine if the function is empty (i.e., has no target). */
+ bool empty() const { return !vtable; }
+
+ /** Retrieve the type of the stored function object, or BOOST_SP_TYPEID(void)
+ if this is empty. */
+ const detail::sp_typeinfo& target_type() const
+ {
+ if (!vtable) return BOOST_SP_TYPEID(void);
+
+ detail::function::function_buffer type;
+ get_vtable()->manager(functor, type, detail::function::get_functor_type_tag);
+ return *type.type.type;
+ }
+
+ template<typename Functor>
+ Functor* target()
+ {
+ if (!vtable) return 0;
+
+ detail::function::function_buffer type_result;
+ type_result.type.type = &BOOST_SP_TYPEID(Functor);
+ type_result.type.const_qualified = is_const<Functor>::value;
+ type_result.type.volatile_qualified = is_volatile<Functor>::value;
+ get_vtable()->manager(functor, type_result,
+ detail::function::check_functor_type_tag);
+ return static_cast<Functor*>(type_result.obj_ptr);
+ }
+
+ template<typename Functor>
+ const Functor* target() const
+ {
+ if (!vtable) return 0;
+
+ detail::function::function_buffer type_result;
+ type_result.type.type = &BOOST_SP_TYPEID(Functor);
+ type_result.type.const_qualified = true;
+ type_result.type.volatile_qualified = is_volatile<Functor>::value;
+ get_vtable()->manager(functor, type_result,
+ detail::function::check_functor_type_tag);
+ // GCC 2.95.3 gets the CV qualifiers wrong here, so we
+ // can't do the static_cast that we should do.
+ return static_cast<const Functor*>(type_result.obj_ptr);
+ }
+
+ template<typename F>
+ bool contains(const F& f) const
+ {
+ if (const F* fp = this->template target<F>())
+ {
+ return function_equal(*fp, f);
+ } else {
+ return false;
+ }
+ }
+
+#if defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3
+ // GCC 3.3 and newer cannot copy with the global operator==, due to
+ // problems with instantiation of function return types before it
+ // has been verified that the argument types match up.
+ template<typename Functor>
+ BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
+ operator==(Functor g) const
+ {
+ if (const Functor* fp = target<Functor>())
+ return function_equal(*fp, g);
+ else return false;
+ }
+
+ template<typename Functor>
+ BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
+ operator!=(Functor g) const
+ {
+ if (const Functor* fp = target<Functor>())
+ return !function_equal(*fp, g);
+ else return true;
+ }
+#endif
+
+public: // should be protected, but GCC 2.95.3 will fail to allow access
+ detail::function::vtable_base* get_vtable() const {
+ return reinterpret_cast<detail::function::vtable_base*>(
+ reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01));
+ }
+
+ bool has_trivial_copy_and_destroy() const {
+ return reinterpret_cast<std::size_t>(vtable) & 0x01;
+ }
+
+ detail::function::vtable_base* vtable;
+ mutable detail::function::function_buffer functor;
+};
+
+/**
+ * The bad_function_call exception class is thrown when a boost::function
+ * object is invoked
+ */
+class bad_function_call : public std::runtime_error
+{
+public:
+ bad_function_call() : std::runtime_error("call to empty boost::function") {}
+};
+
+#ifndef BOOST_NO_SFINAE
+inline bool operator==(const function_base& f,
+ detail::function::useless_clear_type*)
+{
+ return f.empty();
+}
+
+inline bool operator!=(const function_base& f,
+ detail::function::useless_clear_type*)
+{
+ return !f.empty();
+}
+
+inline bool operator==(detail::function::useless_clear_type*,
+ const function_base& f)
+{
+ return f.empty();
+}
+
+inline bool operator!=(detail::function::useless_clear_type*,
+ const function_base& f)
+{
+ return !f.empty();
+}
+#endif
+
+#ifdef BOOST_NO_SFINAE
+// Comparisons between boost::function objects and arbitrary function objects
+template<typename Functor>
+ inline bool operator==(const function_base& f, Functor g)
+ {
+ typedef mpl::bool_<(is_integral<Functor>::value)> integral;
+ return detail::function::compare_equal(f, g, 0, integral());
+ }
+
+template<typename Functor>
+ inline bool operator==(Functor g, const function_base& f)
+ {
+ typedef mpl::bool_<(is_integral<Functor>::value)> integral;
+ return detail::function::compare_equal(f, g, 0, integral());
+ }
+
+template<typename Functor>
+ inline bool operator!=(const function_base& f, Functor g)
+ {
+ typedef mpl::bool_<(is_integral<Functor>::value)> integral;
+ return detail::function::compare_not_equal(f, g, 0, integral());
+ }
+
+template<typename Functor>
+ inline bool operator!=(Functor g, const function_base& f)
+ {
+ typedef mpl::bool_<(is_integral<Functor>::value)> integral;
+ return detail::function::compare_not_equal(f, g, 0, integral());
+ }
+#else
+
+# if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
+// Comparisons between boost::function objects and arbitrary function
+// objects. GCC 3.3 and before has an obnoxious bug that prevents this
+// from working.
+template<typename Functor>
+ BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
+ operator==(const function_base& f, Functor g)
+ {
+ if (const Functor* fp = f.template target<Functor>())
+ return function_equal(*fp, g);
+ else return false;
+ }
+
+template<typename Functor>
+ BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
+ operator==(Functor g, const function_base& f)
+ {
+ if (const Functor* fp = f.template target<Functor>())
+ return function_equal(g, *fp);
+ else return false;
+ }
+
+template<typename Functor>
+ BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
+ operator!=(const function_base& f, Functor g)
+ {
+ if (const Functor* fp = f.template target<Functor>())
+ return !function_equal(*fp, g);
+ else return true;
+ }
+
+template<typename Functor>
+ BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
+ operator!=(Functor g, const function_base& f)
+ {
+ if (const Functor* fp = f.template target<Functor>())
+ return !function_equal(g, *fp);
+ else return true;
+ }
+# endif
+
+template<typename Functor>
+ BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
+ operator==(const function_base& f, reference_wrapper<Functor> g)
+ {
+ if (const Functor* fp = f.template target<Functor>())
+ return fp == g.get_pointer();
+ else return false;
+ }
+
+template<typename Functor>
+ BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
+ operator==(reference_wrapper<Functor> g, const function_base& f)
+ {
+ if (const Functor* fp = f.template target<Functor>())
+ return g.get_pointer() == fp;
+ else return false;
+ }
+
+template<typename Functor>
+ BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
+ operator!=(const function_base& f, reference_wrapper<Functor> g)
+ {
+ if (const Functor* fp = f.template target<Functor>())
+ return fp != g.get_pointer();
+ else return true;
+ }
+
+template<typename Functor>
+ BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
+ operator!=(reference_wrapper<Functor> g, const function_base& f)
+ {
+ if (const Functor* fp = f.template target<Functor>())
+ return g.get_pointer() != fp;
+ else return true;
+ }
+
+#endif // Compiler supporting SFINAE
+
+namespace detail {
+ namespace function {
+ inline bool has_empty_target(const function_base* f)
+ {
+ return f->empty();
+ }
+
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
+ inline bool has_empty_target(const void*)
+ {
+ return false;
+ }
+#else
+ inline bool has_empty_target(...)
+ {
+ return false;
+ }
+#endif
+ } // end namespace function
+} // end namespace detail
+} // end namespace boost
+
+#undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
+#undef BOOST_FUNCTION_COMPARE_TYPE_ID
+
+#if defined(BOOST_MSVC)
+# pragma warning( pop )
+#endif
+
+#endif // BOOST_FUNCTION_BASE_HEADER
diff --git a/third_party/boost/boost/function/function_fwd.hpp b/third_party/boost/boost/function/function_fwd.hpp
new file mode 100644
index 0000000..ea0bf26
--- /dev/null
+++ b/third_party/boost/boost/function/function_fwd.hpp
@@ -0,0 +1,69 @@
+// Boost.Function library
+// Copyright (C) Douglas Gregor 2008
+//
+// Use, modification and distribution is subject to the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// For more information, see http://www.boost.org
+#ifndef BOOST_FUNCTION_FWD_HPP
+#define BOOST_FUNCTION_FWD_HPP
+#include <boost/config.hpp>
+
+#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
+// Work around a compiler bug.
+// boost::python::objects::function has to be seen by the compiler before the
+// boost::function class template.
+namespace boost { namespace python { namespace objects {
+ class function;
+}}}
+#endif
+
+#if defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \
+ || !(defined(BOOST_STRICT_CONFIG) || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540)
+# define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX
+#endif
+
+namespace boost {
+ class bad_function_call;
+
+#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
+ // Preferred syntax
+ template<typename Signature> class function;
+
+ template<typename Signature>
+ inline void swap(function<Signature>& f1, function<Signature>& f2)
+ {
+ f1.swap(f2);
+ }
+#endif // have partial specialization
+
+ // Portable syntax
+ template<typename R> class function0;
+ template<typename R, typename T1> class function1;
+ template<typename R, typename T1, typename T2> class function2;
+ template<typename R, typename T1, typename T2, typename T3> class function3;
+ template<typename R, typename T1, typename T2, typename T3, typename T4>
+ class function4;
+ template<typename R, typename T1, typename T2, typename T3, typename T4,
+ typename T5>
+ class function5;
+ template<typename R, typename T1, typename T2, typename T3, typename T4,
+ typename T5, typename T6>
+ class function6;
+ template<typename R, typename T1, typename T2, typename T3, typename T4,
+ typename T5, typename T6, typename T7>
+ class function7;
+ template<typename R, typename T1, typename T2, typename T3, typename T4,
+ typename T5, typename T6, typename T7, typename T8>
+ class function8;
+ template<typename R, typename T1, typename T2, typename T3, typename T4,
+ typename T5, typename T6, typename T7, typename T8, typename T9>
+ class function9;
+ template<typename R, typename T1, typename T2, typename T3, typename T4,
+ typename T5, typename T6, typename T7, typename T8, typename T9,
+ typename T10>
+ class function10;
+}
+
+#endif
diff --git a/third_party/boost/boost/function/function_template.hpp b/third_party/boost/boost/function/function_template.hpp
new file mode 100644
index 0000000..30fa383
--- /dev/null
+++ b/third_party/boost/boost/function/function_template.hpp
@@ -0,0 +1,1190 @@
+// Boost.Function library
+
+// Copyright Douglas Gregor 2001-2006
+// Copyright Emil Dotchevski 2007
+// Use, modification and distribution is subject to the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// For more information, see http://www.boost.org
+
+// Note: this header is a header template and must NOT have multiple-inclusion
+// protection.
+#include <boost/function/detail/prologue.hpp>
+#include <boost/detail/no_exceptions_support.hpp>
+
+#if defined(BOOST_MSVC)
+# pragma warning( push )
+# pragma warning( disable : 4127 ) // "conditional expression is constant"
+#endif
+
+#define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T)
+
+#define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T)
+
+#define BOOST_FUNCTION_PARM(J,I,D) BOOST_PP_CAT(T,I) BOOST_PP_CAT(a,I)
+
+#define BOOST_FUNCTION_PARMS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_PARM,BOOST_PP_EMPTY)
+
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+# define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a)
+#else
+# include <boost/move/utility_core.hpp>
+# define BOOST_FUNCTION_ARG(J,I,D) ::boost::forward< BOOST_PP_CAT(T,I) >(BOOST_PP_CAT(a,I))
+# define BOOST_FUNCTION_ARGS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG,BOOST_PP_EMPTY)
+#endif
+
+#define BOOST_FUNCTION_ARG_TYPE(J,I,D) \
+ typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(I)),_type);
+
+#define BOOST_FUNCTION_ARG_TYPES BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG_TYPE,BOOST_PP_EMPTY)
+
+// Comma if nonzero number of arguments
+#if BOOST_FUNCTION_NUM_ARGS == 0
+# define BOOST_FUNCTION_COMMA
+#else
+# define BOOST_FUNCTION_COMMA ,
+#endif // BOOST_FUNCTION_NUM_ARGS > 0
+
+// Class names used in this version of the code
+#define BOOST_FUNCTION_FUNCTION BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS)
+#define BOOST_FUNCTION_FUNCTION_INVOKER \
+ BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS)
+#define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \
+ BOOST_JOIN(void_function_invoker,BOOST_FUNCTION_NUM_ARGS)
+#define BOOST_FUNCTION_FUNCTION_OBJ_INVOKER \
+ BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
+#define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \
+ BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
+#define BOOST_FUNCTION_FUNCTION_REF_INVOKER \
+ BOOST_JOIN(function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
+#define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER \
+ BOOST_JOIN(void_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
+#define BOOST_FUNCTION_MEMBER_INVOKER \
+ BOOST_JOIN(function_mem_invoker,BOOST_FUNCTION_NUM_ARGS)
+#define BOOST_FUNCTION_VOID_MEMBER_INVOKER \
+ BOOST_JOIN(function_void_mem_invoker,BOOST_FUNCTION_NUM_ARGS)
+#define BOOST_FUNCTION_GET_FUNCTION_INVOKER \
+ BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS)
+#define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \
+ BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
+#define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER \
+ BOOST_JOIN(get_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
+#define BOOST_FUNCTION_GET_MEMBER_INVOKER \
+ BOOST_JOIN(get_member_invoker,BOOST_FUNCTION_NUM_ARGS)
+#define BOOST_FUNCTION_GET_INVOKER \
+ BOOST_JOIN(get_invoker,BOOST_FUNCTION_NUM_ARGS)
+#define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS)
+
+#ifndef BOOST_NO_VOID_RETURNS
+# define BOOST_FUNCTION_VOID_RETURN_TYPE void
+# define BOOST_FUNCTION_RETURN(X) X
+#else
+# define BOOST_FUNCTION_VOID_RETURN_TYPE boost::detail::function::unusable
+# define BOOST_FUNCTION_RETURN(X) X; return BOOST_FUNCTION_VOID_RETURN_TYPE ()
+#endif
+
+namespace boost {
+ namespace detail {
+ namespace function {
+ template<
+ typename FunctionPtr,
+ typename R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_PARMS
+ >
+ struct BOOST_FUNCTION_FUNCTION_INVOKER
+ {
+ static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_PARMS)
+ {
+ FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
+ return f(BOOST_FUNCTION_ARGS);
+ }
+ };
+
+ template<
+ typename FunctionPtr,
+ typename R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_PARMS
+ >
+ struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER
+ {
+ static BOOST_FUNCTION_VOID_RETURN_TYPE
+ invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_PARMS)
+
+ {
+ FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
+ BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS));
+ }
+ };
+
+ template<
+ typename FunctionObj,
+ typename R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_PARMS
+ >
+ struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
+ {
+ static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_PARMS)
+
+ {
+ FunctionObj* f;
+ if (function_allows_small_object_optimization<FunctionObj>::value)
+ f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data);
+ else
+ f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
+ return (*f)(BOOST_FUNCTION_ARGS);
+ }
+ };
+
+ template<
+ typename FunctionObj,
+ typename R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_PARMS
+ >
+ struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
+ {
+ static BOOST_FUNCTION_VOID_RETURN_TYPE
+ invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_PARMS)
+
+ {
+ FunctionObj* f;
+ if (function_allows_small_object_optimization<FunctionObj>::value)
+ f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data);
+ else
+ f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
+ BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
+ }
+ };
+
+ template<
+ typename FunctionObj,
+ typename R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_PARMS
+ >
+ struct BOOST_FUNCTION_FUNCTION_REF_INVOKER
+ {
+ static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_PARMS)
+
+ {
+ FunctionObj* f =
+ reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
+ return (*f)(BOOST_FUNCTION_ARGS);
+ }
+ };
+
+ template<
+ typename FunctionObj,
+ typename R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_PARMS
+ >
+ struct BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
+ {
+ static BOOST_FUNCTION_VOID_RETURN_TYPE
+ invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_PARMS)
+
+ {
+ FunctionObj* f =
+ reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
+ BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
+ }
+ };
+
+#if BOOST_FUNCTION_NUM_ARGS > 0
+ /* Handle invocation of member pointers. */
+ template<
+ typename MemberPtr,
+ typename R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_PARMS
+ >
+ struct BOOST_FUNCTION_MEMBER_INVOKER
+ {
+ static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_PARMS)
+
+ {
+ MemberPtr* f =
+ reinterpret_cast<MemberPtr*>(&function_obj_ptr.data);
+ return boost::mem_fn(*f)(BOOST_FUNCTION_ARGS);
+ }
+ };
+
+ template<
+ typename MemberPtr,
+ typename R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_PARMS
+ >
+ struct BOOST_FUNCTION_VOID_MEMBER_INVOKER
+ {
+ static BOOST_FUNCTION_VOID_RETURN_TYPE
+ invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_PARMS)
+
+ {
+ MemberPtr* f =
+ reinterpret_cast<MemberPtr*>(&function_obj_ptr.data);
+ BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS));
+ }
+ };
+#endif
+
+ template<
+ typename FunctionPtr,
+ typename R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_PARMS
+ >
+ struct BOOST_FUNCTION_GET_FUNCTION_INVOKER
+ {
+ typedef typename mpl::if_c<(is_void<R>::value),
+ BOOST_FUNCTION_VOID_FUNCTION_INVOKER<
+ FunctionPtr,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >,
+ BOOST_FUNCTION_FUNCTION_INVOKER<
+ FunctionPtr,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >
+ >::type type;
+ };
+
+ template<
+ typename FunctionObj,
+ typename R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_PARMS
+ >
+ struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
+ {
+ typedef typename mpl::if_c<(is_void<R>::value),
+ BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER<
+ FunctionObj,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >,
+ BOOST_FUNCTION_FUNCTION_OBJ_INVOKER<
+ FunctionObj,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >
+ >::type type;
+ };
+
+ template<
+ typename FunctionObj,
+ typename R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_PARMS
+ >
+ struct BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
+ {
+ typedef typename mpl::if_c<(is_void<R>::value),
+ BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER<
+ FunctionObj,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >,
+ BOOST_FUNCTION_FUNCTION_REF_INVOKER<
+ FunctionObj,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >
+ >::type type;
+ };
+
+#if BOOST_FUNCTION_NUM_ARGS > 0
+ /* Retrieve the appropriate invoker for a member pointer. */
+ template<
+ typename MemberPtr,
+ typename R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_PARMS
+ >
+ struct BOOST_FUNCTION_GET_MEMBER_INVOKER
+ {
+ typedef typename mpl::if_c<(is_void<R>::value),
+ BOOST_FUNCTION_VOID_MEMBER_INVOKER<
+ MemberPtr,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >,
+ BOOST_FUNCTION_MEMBER_INVOKER<
+ MemberPtr,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >
+ >::type type;
+ };
+#endif
+
+ /* Given the tag returned by get_function_tag, retrieve the
+ actual invoker that will be used for the given function
+ object.
+
+ Each specialization contains an "apply" nested class template
+ that accepts the function object, return type, function
+ argument types, and allocator. The resulting "apply" class
+ contains two typedefs, "invoker_type" and "manager_type",
+ which correspond to the invoker and manager types. */
+ template<typename Tag>
+ struct BOOST_FUNCTION_GET_INVOKER { };
+
+ /* Retrieve the invoker for a function pointer. */
+ template<>
+ struct BOOST_FUNCTION_GET_INVOKER<function_ptr_tag>
+ {
+ template<typename FunctionPtr,
+ typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
+ struct apply
+ {
+ typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
+ FunctionPtr,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >::type
+ invoker_type;
+
+ typedef functor_manager<FunctionPtr> manager_type;
+ };
+
+ template<typename FunctionPtr,
+ typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
+ typename Allocator>
+ struct apply_a
+ {
+ typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
+ FunctionPtr,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >::type
+ invoker_type;
+
+ typedef functor_manager<FunctionPtr> manager_type;
+ };
+ };
+
+#if BOOST_FUNCTION_NUM_ARGS > 0
+ /* Retrieve the invoker for a member pointer. */
+ template<>
+ struct BOOST_FUNCTION_GET_INVOKER<member_ptr_tag>
+ {
+ template<typename MemberPtr,
+ typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
+ struct apply
+ {
+ typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER<
+ MemberPtr,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >::type
+ invoker_type;
+
+ typedef functor_manager<MemberPtr> manager_type;
+ };
+
+ template<typename MemberPtr,
+ typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
+ typename Allocator>
+ struct apply_a
+ {
+ typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER<
+ MemberPtr,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >::type
+ invoker_type;
+
+ typedef functor_manager<MemberPtr> manager_type;
+ };
+ };
+#endif
+
+ /* Retrieve the invoker for a function object. */
+ template<>
+ struct BOOST_FUNCTION_GET_INVOKER<function_obj_tag>
+ {
+ template<typename FunctionObj,
+ typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
+ struct apply
+ {
+ typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
+ FunctionObj,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >::type
+ invoker_type;
+
+ typedef functor_manager<FunctionObj> manager_type;
+ };
+
+ template<typename FunctionObj,
+ typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
+ typename Allocator>
+ struct apply_a
+ {
+ typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
+ FunctionObj,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >::type
+ invoker_type;
+
+ typedef functor_manager_a<FunctionObj, Allocator> manager_type;
+ };
+ };
+
+ /* Retrieve the invoker for a reference to a function object. */
+ template<>
+ struct BOOST_FUNCTION_GET_INVOKER<function_obj_ref_tag>
+ {
+ template<typename RefWrapper,
+ typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
+ struct apply
+ {
+ typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
+ typename RefWrapper::type,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >::type
+ invoker_type;
+
+ typedef reference_manager<typename RefWrapper::type> manager_type;
+ };
+
+ template<typename RefWrapper,
+ typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
+ typename Allocator>
+ struct apply_a
+ {
+ typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
+ typename RefWrapper::type,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >::type
+ invoker_type;
+
+ typedef reference_manager<typename RefWrapper::type> manager_type;
+ };
+ };
+
+
+ /**
+ * vtable for a specific boost::function instance. This
+ * structure must be an aggregate so that we can use static
+ * initialization in boost::function's assign_to and assign_to_a
+ * members. It therefore cannot have any constructors,
+ * destructors, base classes, etc.
+ */
+ template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
+ struct BOOST_FUNCTION_VTABLE
+ {
+#ifndef BOOST_NO_VOID_RETURNS
+ typedef R result_type;
+#else
+ typedef typename function_return_type<R>::type result_type;
+#endif // BOOST_NO_VOID_RETURNS
+
+ typedef result_type (*invoker_type)(function_buffer&
+ BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS);
+
+ template<typename F>
+ bool assign_to(F f, function_buffer& functor) const
+ {
+ typedef typename get_function_tag<F>::type tag;
+ return assign_to(f, functor, tag());
+ }
+ template<typename F,typename Allocator>
+ bool assign_to_a(F f, function_buffer& functor, Allocator a) const
+ {
+ typedef typename get_function_tag<F>::type tag;
+ return assign_to_a(f, functor, a, tag());
+ }
+
+ void clear(function_buffer& functor) const
+ {
+ if (base.manager)
+ base.manager(functor, functor, destroy_functor_tag);
+ }
+
+ private:
+ // Function pointers
+ template<typename FunctionPtr>
+ bool
+ assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) const
+ {
+ this->clear(functor);
+ if (f) {
+ // should be a reinterpret cast, but some compilers insist
+ // on giving cv-qualifiers to free functions
+ functor.func_ptr = reinterpret_cast<void (*)()>(f);
+ return true;
+ } else {
+ return false;
+ }
+ }
+ template<typename FunctionPtr,typename Allocator>
+ bool
+ assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag) const
+ {
+ return assign_to(f,functor,function_ptr_tag());
+ }
+
+ // Member pointers
+#if BOOST_FUNCTION_NUM_ARGS > 0
+ template<typename MemberPtr>
+ bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) const
+ {
+ // DPG TBD: Add explicit support for member function
+ // objects, so we invoke through mem_fn() but we retain the
+ // right target_type() values.
+ if (f) {
+ this->assign_to(boost::mem_fn(f), functor);
+ return true;
+ } else {
+ return false;
+ }
+ }
+ template<typename MemberPtr,typename Allocator>
+ bool assign_to_a(MemberPtr f, function_buffer& functor, Allocator a, member_ptr_tag) const
+ {
+ // DPG TBD: Add explicit support for member function
+ // objects, so we invoke through mem_fn() but we retain the
+ // right target_type() values.
+ if (f) {
+ this->assign_to_a(boost::mem_fn(f), functor, a);
+ return true;
+ } else {
+ return false;
+ }
+ }
+#endif // BOOST_FUNCTION_NUM_ARGS > 0
+
+ // Function objects
+ // Assign to a function object using the small object optimization
+ template<typename FunctionObj>
+ void
+ assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) const
+ {
+ new (reinterpret_cast<void*>(&functor.data)) FunctionObj(f);
+ }
+ template<typename FunctionObj,typename Allocator>
+ void
+ assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_) const
+ {
+ assign_functor(f,functor,mpl::true_());
+ }
+
+ // Assign to a function object allocated on the heap.
+ template<typename FunctionObj>
+ void
+ assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) const
+ {
+ functor.obj_ptr = new FunctionObj(f);
+ }
+ template<typename FunctionObj,typename Allocator>
+ void
+ assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_) const
+ {
+ typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type;
+ typedef typename Allocator::template rebind<functor_wrapper_type>::other
+ wrapper_allocator_type;
+ typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type;
+ wrapper_allocator_type wrapper_allocator(a);
+ wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
+ wrapper_allocator.construct(copy, functor_wrapper_type(f,a));
+ functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
+ functor.obj_ptr = new_f;
+ }
+
+ template<typename FunctionObj>
+ bool
+ assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) const
+ {
+ if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
+ assign_functor(f, functor,
+ mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
+ return true;
+ } else {
+ return false;
+ }
+ }
+ template<typename FunctionObj,typename Allocator>
+ bool
+ assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag) const
+ {
+ if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
+ assign_functor_a(f, functor, a,
+ mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ // Reference to a function object
+ template<typename FunctionObj>
+ bool
+ assign_to(const reference_wrapper<FunctionObj>& f,
+ function_buffer& functor, function_obj_ref_tag) const
+ {
+ functor.obj_ref.obj_ptr = (void *)(f.get_pointer());
+ functor.obj_ref.is_const_qualified = is_const<FunctionObj>::value;
+ functor.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value;
+ return true;
+ }
+ template<typename FunctionObj,typename Allocator>
+ bool
+ assign_to_a(const reference_wrapper<FunctionObj>& f,
+ function_buffer& functor, Allocator, function_obj_ref_tag) const
+ {
+ return assign_to(f,functor,function_obj_ref_tag());
+ }
+
+ public:
+ vtable_base base;
+ invoker_type invoker;
+ };
+ } // end namespace function
+ } // end namespace detail
+
+ template<
+ typename R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_PARMS
+ >
+ class BOOST_FUNCTION_FUNCTION : public function_base
+
+#if BOOST_FUNCTION_NUM_ARGS == 1
+
+ , public std::unary_function<T0,R>
+
+#elif BOOST_FUNCTION_NUM_ARGS == 2
+
+ , public std::binary_function<T0,T1,R>
+
+#endif
+
+ {
+ public:
+#ifndef BOOST_NO_VOID_RETURNS
+ typedef R result_type;
+#else
+ typedef typename boost::detail::function::function_return_type<R>::type
+ result_type;
+#endif // BOOST_NO_VOID_RETURNS
+
+ private:
+ typedef boost::detail::function::BOOST_FUNCTION_VTABLE<
+ R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
+ vtable_type;
+
+ vtable_type* get_vtable() const {
+ return reinterpret_cast<vtable_type*>(
+ reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01));
+ }
+
+ struct clear_type {};
+
+ public:
+ BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
+
+ // add signature for boost::lambda
+ template<typename Args>
+ struct sig
+ {
+ typedef result_type type;
+ };
+
+#if BOOST_FUNCTION_NUM_ARGS == 1
+ typedef T0 argument_type;
+#elif BOOST_FUNCTION_NUM_ARGS == 2
+ typedef T0 first_argument_type;
+ typedef T1 second_argument_type;
+#endif
+
+ BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS);
+ BOOST_FUNCTION_ARG_TYPES
+
+ typedef BOOST_FUNCTION_FUNCTION self_type;
+
+ BOOST_FUNCTION_FUNCTION() : function_base() { }
+
+ // MSVC chokes if the following two constructors are collapsed into
+ // one with a default parameter.
+ template<typename Functor>
+ BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f
+#ifndef BOOST_NO_SFINAE
+ ,typename boost::enable_if_c<
+ !(is_integral<Functor>::value),
+ int>::type = 0
+#endif // BOOST_NO_SFINAE
+ ) :
+ function_base()
+ {
+ this->assign_to(f);
+ }
+ template<typename Functor,typename Allocator>
+ BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a
+#ifndef BOOST_NO_SFINAE
+ ,typename boost::enable_if_c<
+ !(is_integral<Functor>::value),
+ int>::type = 0
+#endif // BOOST_NO_SFINAE
+ ) :
+ function_base()
+ {
+ this->assign_to_a(f,a);
+ }
+
+#ifndef BOOST_NO_SFINAE
+ BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { }
+#else
+ BOOST_FUNCTION_FUNCTION(int zero) : function_base()
+ {
+ BOOST_ASSERT(zero == 0);
+ }
+#endif
+
+ BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : function_base()
+ {
+ this->assign_to_own(f);
+ }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ BOOST_FUNCTION_FUNCTION(BOOST_FUNCTION_FUNCTION&& f) : function_base()
+ {
+ this->move_assign(f);
+ }
+#endif
+
+ ~BOOST_FUNCTION_FUNCTION() { clear(); }
+
+ result_type operator()(BOOST_FUNCTION_PARMS) const
+ {
+ if (this->empty())
+ boost::throw_exception(bad_function_call());
+
+ return get_vtable()->invoker
+ (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
+ }
+
+ // The distinction between when to use BOOST_FUNCTION_FUNCTION and
+ // when to use self_type is obnoxious. MSVC cannot handle self_type as
+ // the return type of these assignment operators, but Borland C++ cannot
+ // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
+ // construct.
+ template<typename Functor>
+#ifndef BOOST_NO_SFINAE
+ typename boost::enable_if_c<
+ !(is_integral<Functor>::value),
+ BOOST_FUNCTION_FUNCTION&>::type
+#else
+ BOOST_FUNCTION_FUNCTION&
+#endif
+ operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
+ {
+ this->clear();
+ BOOST_TRY {
+ this->assign_to(f);
+ } BOOST_CATCH (...) {
+ vtable = 0;
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return *this;
+ }
+ template<typename Functor,typename Allocator>
+ void assign(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a)
+ {
+ this->clear();
+ BOOST_TRY{
+ this->assign_to_a(f,a);
+ } BOOST_CATCH (...) {
+ vtable = 0;
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ }
+
+#ifndef BOOST_NO_SFINAE
+ BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
+ {
+ this->clear();
+ return *this;
+ }
+#else
+ BOOST_FUNCTION_FUNCTION& operator=(int zero)
+ {
+ BOOST_ASSERT(zero == 0);
+ this->clear();
+ return *this;
+ }
+#endif
+
+ // Assignment from another BOOST_FUNCTION_FUNCTION
+ BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
+ {
+ if (&f == this)
+ return *this;
+
+ this->clear();
+ BOOST_TRY {
+ this->assign_to_own(f);
+ } BOOST_CATCH (...) {
+ vtable = 0;
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return *this;
+ }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ // Move assignment from another BOOST_FUNCTION_FUNCTION
+ BOOST_FUNCTION_FUNCTION& operator=(BOOST_FUNCTION_FUNCTION&& f)
+ {
+
+ if (&f == this)
+ return *this;
+
+ this->clear();
+ BOOST_TRY {
+ this->move_assign(f);
+ } BOOST_CATCH (...) {
+ vtable = 0;
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return *this;
+ }
+#endif
+
+ void swap(BOOST_FUNCTION_FUNCTION& other)
+ {
+ if (&other == this)
+ return;
+
+ BOOST_FUNCTION_FUNCTION tmp;
+ tmp.move_assign(*this);
+ this->move_assign(other);
+ other.move_assign(tmp);
+ }
+
+ // Clear out a target, if there is one
+ void clear()
+ {
+ if (vtable) {
+ if (!this->has_trivial_copy_and_destroy())
+ get_vtable()->clear(this->functor);
+ vtable = 0;
+ }
+ }
+
+#if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
+ // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
+ operator bool () const { return !this->empty(); }
+#else
+ private:
+ struct dummy {
+ void nonnull() {}
+ };
+
+ typedef void (dummy::*safe_bool)();
+
+ public:
+ operator safe_bool () const
+ { return (this->empty())? 0 : &dummy::nonnull; }
+
+ bool operator!() const
+ { return this->empty(); }
+#endif
+
+ private:
+ void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
+ {
+ if (!f.empty()) {
+ this->vtable = f.vtable;
+ if (this->has_trivial_copy_and_destroy())
+ this->functor = f.functor;
+ else
+ get_vtable()->base.manager(f.functor, this->functor,
+ boost::detail::function::clone_functor_tag);
+ }
+ }
+
+ template<typename Functor>
+ void assign_to(Functor f)
+ {
+ using boost::detail::function::vtable_base;
+
+ typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
+ typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
+ typedef typename get_invoker::
+ template apply<Functor, R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS>
+ handler_type;
+
+ typedef typename handler_type::invoker_type invoker_type;
+ typedef typename handler_type::manager_type manager_type;
+
+ // Note: it is extremely important that this initialization use
+ // static initialization. Otherwise, we will have a race
+ // condition here in multi-threaded code. See
+ // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
+ static const vtable_type stored_vtable =
+ { { &manager_type::manage }, &invoker_type::invoke };
+
+ if (stored_vtable.assign_to(f, functor)) {
+ std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
+ // coverity[pointless_expression]: suppress coverity warnings on apparant if(const).
+ if (boost::has_trivial_copy_constructor<Functor>::value &&
+ boost::has_trivial_destructor<Functor>::value &&
+ boost::detail::function::function_allows_small_object_optimization<Functor>::value)
+ value |= static_cast<std::size_t>(0x01);
+ vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value);
+ } else
+ vtable = 0;
+ }
+
+ template<typename Functor,typename Allocator>
+ void assign_to_a(Functor f,Allocator a)
+ {
+ using boost::detail::function::vtable_base;
+
+ typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
+ typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
+ typedef typename get_invoker::
+ template apply_a<Functor, R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS,
+ Allocator>
+ handler_type;
+
+ typedef typename handler_type::invoker_type invoker_type;
+ typedef typename handler_type::manager_type manager_type;
+
+ // Note: it is extremely important that this initialization use
+ // static initialization. Otherwise, we will have a race
+ // condition here in multi-threaded code. See
+ // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
+ static const vtable_type stored_vtable =
+ { { &manager_type::manage }, &invoker_type::invoke };
+
+ if (stored_vtable.assign_to_a(f, functor, a)) {
+ std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
+ // coverity[pointless_expression]: suppress coverity warnings on apparant if(const).
+ if (boost::has_trivial_copy_constructor<Functor>::value &&
+ boost::has_trivial_destructor<Functor>::value &&
+ boost::detail::function::function_allows_small_object_optimization<Functor>::value)
+ value |= static_cast<std::size_t>(0x01);
+ vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value);
+ } else
+ vtable = 0;
+ }
+
+ // Moves the value from the specified argument to *this. If the argument
+ // has its function object allocated on the heap, move_assign will pass
+ // its buffer to *this, and set the argument's buffer pointer to NULL.
+ void move_assign(BOOST_FUNCTION_FUNCTION& f)
+ {
+ if (&f == this)
+ return;
+
+ BOOST_TRY {
+ if (!f.empty()) {
+ this->vtable = f.vtable;
+ if (this->has_trivial_copy_and_destroy())
+ this->functor = f.functor;
+ else
+ get_vtable()->base.manager(f.functor, this->functor,
+ boost::detail::function::move_functor_tag);
+ f.vtable = 0;
+ } else {
+ clear();
+ }
+ } BOOST_CATCH (...) {
+ vtable = 0;
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ }
+ };
+
+ template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
+ inline void swap(BOOST_FUNCTION_FUNCTION<
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >& f1,
+ BOOST_FUNCTION_FUNCTION<
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >& f2)
+ {
+ f1.swap(f2);
+ }
+
+// Poison comparisons between boost::function objects of the same type.
+template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
+ void operator==(const BOOST_FUNCTION_FUNCTION<
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS>&,
+ const BOOST_FUNCTION_FUNCTION<
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS>&);
+template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
+ void operator!=(const BOOST_FUNCTION_FUNCTION<
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS>&,
+ const BOOST_FUNCTION_FUNCTION<
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS>& );
+
+#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
+
+#if BOOST_FUNCTION_NUM_ARGS == 0
+#define BOOST_FUNCTION_PARTIAL_SPEC R (void)
+#else
+#define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T))
+#endif
+
+template<typename R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_PARMS>
+class function<BOOST_FUNCTION_PARTIAL_SPEC>
+ : public BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
+{
+ typedef BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> base_type;
+ typedef function self_type;
+
+ struct clear_type {};
+
+public:
+
+ function() : base_type() {}
+
+ template<typename Functor>
+ function(Functor f
+#ifndef BOOST_NO_SFINAE
+ ,typename boost::enable_if_c<
+ !(is_integral<Functor>::value),
+ int>::type = 0
+#endif
+ ) :
+ base_type(f)
+ {
+ }
+ template<typename Functor,typename Allocator>
+ function(Functor f, Allocator a
+#ifndef BOOST_NO_SFINAE
+ ,typename boost::enable_if_c<
+ !(is_integral<Functor>::value),
+ int>::type = 0
+#endif
+ ) :
+ base_type(f,a)
+ {
+ }
+
+#ifndef BOOST_NO_SFINAE
+ function(clear_type*) : base_type() {}
+#endif
+
+ function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
+
+ function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ // Move constructors
+ function(self_type&& f): base_type(static_cast<base_type&&>(f)){}
+ function(base_type&& f): base_type(static_cast<base_type&&>(f)){}
+#endif
+
+ self_type& operator=(const self_type& f)
+ {
+ self_type(f).swap(*this);
+ return *this;
+ }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ self_type& operator=(self_type&& f)
+ {
+ self_type(static_cast<self_type&&>(f)).swap(*this);
+ return *this;
+ }
+#endif
+
+ template<typename Functor>
+#ifndef BOOST_NO_SFINAE
+ typename boost::enable_if_c<
+ !(is_integral<Functor>::value),
+ self_type&>::type
+#else
+ self_type&
+#endif
+ operator=(Functor f)
+ {
+ self_type(f).swap(*this);
+ return *this;
+ }
+
+#ifndef BOOST_NO_SFINAE
+ self_type& operator=(clear_type*)
+ {
+ this->clear();
+ return *this;
+ }
+#endif
+
+ self_type& operator=(const base_type& f)
+ {
+ self_type(f).swap(*this);
+ return *this;
+ }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ self_type& operator=(base_type&& f)
+ {
+ self_type(static_cast<base_type&&>(f)).swap(*this);
+ return *this;
+ }
+#endif
+};
+
+#undef BOOST_FUNCTION_PARTIAL_SPEC
+#endif // have partial specialization
+
+} // end namespace boost
+
+// Cleanup after ourselves...
+#undef BOOST_FUNCTION_VTABLE
+#undef BOOST_FUNCTION_COMMA
+#undef BOOST_FUNCTION_FUNCTION
+#undef BOOST_FUNCTION_FUNCTION_INVOKER
+#undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
+#undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
+#undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
+#undef BOOST_FUNCTION_FUNCTION_REF_INVOKER
+#undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
+#undef BOOST_FUNCTION_MEMBER_INVOKER
+#undef BOOST_FUNCTION_VOID_MEMBER_INVOKER
+#undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
+#undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
+#undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
+#undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
+#undef BOOST_FUNCTION_GET_INVOKER
+#undef BOOST_FUNCTION_TEMPLATE_PARMS
+#undef BOOST_FUNCTION_TEMPLATE_ARGS
+#undef BOOST_FUNCTION_PARMS
+#undef BOOST_FUNCTION_PARM
+#ifdef BOOST_FUNCTION_ARG
+# undef BOOST_FUNCTION_ARG
+#endif
+#undef BOOST_FUNCTION_ARGS
+#undef BOOST_FUNCTION_ARG_TYPE
+#undef BOOST_FUNCTION_ARG_TYPES
+#undef BOOST_FUNCTION_VOID_RETURN_TYPE
+#undef BOOST_FUNCTION_RETURN
+
+#if defined(BOOST_MSVC)
+# pragma warning( pop )
+#endif
diff --git a/third_party/boost/boost/function_equal.hpp b/third_party/boost/boost/function_equal.hpp
new file mode 100644
index 0000000..2d76c75
--- /dev/null
+++ b/third_party/boost/boost/function_equal.hpp
@@ -0,0 +1,28 @@
+// Copyright Douglas Gregor 2004.
+// Copyright 2005 Peter Dimov
+
+// Use, modification and distribution is subject to
+// the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// For more information, see http://www.boost.org
+#ifndef BOOST_FUNCTION_EQUAL_HPP
+#define BOOST_FUNCTION_EQUAL_HPP
+
+namespace boost {
+
+template<typename F, typename G>
+ bool function_equal_impl(const F& f, const G& g, long)
+ { return f == g; }
+
+// function_equal_impl needs to be unqualified to pick
+// user overloads on two-phase compilers
+
+template<typename F, typename G>
+ bool function_equal(const F& f, const G& g)
+ { return function_equal_impl(f, g, 0); }
+
+} // end namespace boost
+
+#endif // BOOST_FUNCTION_EQUAL_HPP
diff --git a/third_party/boost/boost/function_output_iterator.hpp b/third_party/boost/boost/function_output_iterator.hpp
new file mode 100644
index 0000000..dd8c44d
--- /dev/null
+++ b/third_party/boost/boost/function_output_iterator.hpp
@@ -0,0 +1,62 @@
+// (C) Copyright Jeremy Siek 2001.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Revision History:
+
+// 27 Feb 2001 Jeremy Siek
+// Initial checkin.
+
+#ifndef BOOST_FUNCTION_OUTPUT_ITERATOR_HPP
+#define BOOST_FUNCTION_OUTPUT_ITERATOR_HPP
+
+#include <iterator>
+
+namespace boost {
+namespace iterators {
+
+ template <class UnaryFunction>
+ class function_output_iterator {
+ typedef function_output_iterator self;
+ public:
+ typedef std::output_iterator_tag iterator_category;
+ typedef void value_type;
+ typedef void difference_type;
+ typedef void pointer;
+ typedef void reference;
+
+ explicit function_output_iterator() {}
+
+ explicit function_output_iterator(const UnaryFunction& f)
+ : m_f(f) {}
+
+ struct output_proxy {
+ output_proxy(UnaryFunction& f) : m_f(f) { }
+ template <class T> output_proxy& operator=(const T& value) {
+ m_f(value);
+ return *this;
+ }
+ UnaryFunction& m_f;
+ };
+ output_proxy operator*() { return output_proxy(m_f); }
+ self& operator++() { return *this; }
+ self& operator++(int) { return *this; }
+ private:
+ UnaryFunction m_f;
+ };
+
+ template <class UnaryFunction>
+ inline function_output_iterator<UnaryFunction>
+ make_function_output_iterator(const UnaryFunction& f = UnaryFunction()) {
+ return function_output_iterator<UnaryFunction>(f);
+ }
+
+} // namespace iterators
+
+using iterators::function_output_iterator;
+using iterators::make_function_output_iterator;
+
+} // namespace boost
+
+#endif // BOOST_FUNCTION_OUTPUT_ITERATOR_HPP
diff --git a/third_party/boost/boost/functional/hash/hash_fwd.hpp b/third_party/boost/boost/functional/hash/hash_fwd.hpp
new file mode 100644
index 0000000..333ffbf
--- /dev/null
+++ b/third_party/boost/boost/functional/hash/hash_fwd.hpp
@@ -0,0 +1,36 @@
+
+// Copyright 2005-2009 Daniel James.
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Based on Peter Dimov's proposal
+// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf
+// issue 6.18.
+
+#if !defined(BOOST_FUNCTIONAL_HASH_FWD_HPP)
+#define BOOST_FUNCTIONAL_HASH_FWD_HPP
+
+#include <boost/config.hpp>
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+#pragma once
+#endif
+
+#include <cstddef>
+#include <boost/detail/workaround.hpp>
+
+namespace boost
+{
+ template <class T> struct hash;
+
+ template <class T> void hash_combine(std::size_t& seed, T const& v);
+
+ template <class It> std::size_t hash_range(It, It);
+ template <class It> void hash_range(std::size_t&, It, It);
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
+ template <class T> inline std::size_t hash_range(T*, T*);
+ template <class T> inline void hash_range(std::size_t&, T*, T*);
+#endif
+}
+
+#endif
diff --git a/third_party/boost/boost/functional/hash_fwd.hpp b/third_party/boost/boost/functional/hash_fwd.hpp
new file mode 100644
index 0000000..eea9073
--- /dev/null
+++ b/third_party/boost/boost/functional/hash_fwd.hpp
@@ -0,0 +1,11 @@
+
+// Copyright 2005-2009 Daniel James.
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/config.hpp>
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+#pragma once
+#endif
+
+#include <boost/functional/hash/hash_fwd.hpp>
diff --git a/third_party/boost/boost/get_pointer.hpp b/third_party/boost/boost/get_pointer.hpp
new file mode 100644
index 0000000..b2d96f5
--- /dev/null
+++ b/third_party/boost/boost/get_pointer.hpp
@@ -0,0 +1,76 @@
+// Copyright Peter Dimov and David Abrahams 2002.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+#ifndef GET_POINTER_DWA20021219_HPP
+#define GET_POINTER_DWA20021219_HPP
+
+#include <boost/config.hpp>
+
+// In order to avoid circular dependencies with Boost.TR1
+// we make sure that our include of <memory> doesn't try to
+// pull in the TR1 headers: that's why we use this header
+// rather than including <memory> directly:
+#include <boost/config/no_tr1/memory.hpp> // std::auto_ptr
+
+namespace boost {
+
+// get_pointer(p) extracts a ->* capable pointer from p
+
+template<class T> T * get_pointer(T * p)
+{
+ return p;
+}
+
+// get_pointer(shared_ptr<T> const & p) has been moved to shared_ptr.hpp
+
+#if !defined( BOOST_NO_AUTO_PTR )
+
+#if defined( __GNUC__ ) && (defined( __GXX_EXPERIMENTAL_CXX0X__ ) || (__cplusplus >= 201103L))
+#if defined( BOOST_GCC )
+#if BOOST_GCC >= 40600
+#define BOOST_CORE_DETAIL_DISABLE_LIBSTDCXX_DEPRECATED_WARNINGS
+#endif // BOOST_GCC >= 40600
+#elif defined( __clang__ ) && defined( __has_warning )
+#if __has_warning("-Wdeprecated-declarations")
+#define BOOST_CORE_DETAIL_DISABLE_LIBSTDCXX_DEPRECATED_WARNINGS
+#endif // __has_warning("-Wdeprecated-declarations")
+#endif
+#endif // defined( __GNUC__ ) && (defined( __GXX_EXPERIMENTAL_CXX0X__ ) || (__cplusplus >= 201103L))
+
+#if defined( BOOST_CORE_DETAIL_DISABLE_LIBSTDCXX_DEPRECATED_WARNINGS )
+// Disable libstdc++ warnings about std::auto_ptr being deprecated in C++11 mode
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#define BOOST_CORE_DETAIL_DISABLED_DEPRECATED_WARNINGS
+#endif
+
+template<class T> T * get_pointer(std::auto_ptr<T> const& p)
+{
+ return p.get();
+}
+
+#if defined( BOOST_CORE_DETAIL_DISABLE_LIBSTDCXX_DEPRECATED_WARNINGS )
+#pragma GCC diagnostic pop
+#undef BOOST_CORE_DETAIL_DISABLE_LIBSTDCXX_DEPRECATED_WARNINGS
+#endif
+
+#endif // !defined( BOOST_NO_AUTO_PTR )
+
+#if !defined( BOOST_NO_CXX11_SMART_PTR )
+
+template<class T> T * get_pointer( std::unique_ptr<T> const& p )
+{
+ return p.get();
+}
+
+template<class T> T * get_pointer( std::shared_ptr<T> const& p )
+{
+ return p.get();
+}
+
+#endif
+
+} // namespace boost
+
+#endif // GET_POINTER_DWA20021219_HPP
diff --git a/third_party/boost/boost/integer.hpp b/third_party/boost/boost/integer.hpp
new file mode 100644
index 0000000..9fa0019
--- /dev/null
+++ b/third_party/boost/boost/integer.hpp
@@ -0,0 +1,262 @@
+// boost integer.hpp header file -------------------------------------------//
+
+// Copyright Beman Dawes and Daryle Walker 1999. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/integer for documentation.
+
+// Revision History
+// 22 Sep 01 Added value-based integer templates. (Daryle Walker)
+// 01 Apr 01 Modified to use new <boost/limits.hpp> header. (John Maddock)
+// 30 Jul 00 Add typename syntax fix (Jens Maurer)
+// 28 Aug 99 Initial version
+
+#ifndef BOOST_INTEGER_HPP
+#define BOOST_INTEGER_HPP
+
+#include <boost/integer_fwd.hpp> // self include
+
+#include <boost/integer_traits.hpp> // for boost::::boost::integer_traits
+#include <boost/limits.hpp> // for ::std::numeric_limits
+#include <boost/cstdint.hpp> // for boost::int64_t and BOOST_NO_INTEGRAL_INT64_T
+#include <boost/static_assert.hpp>
+
+//
+// We simply cannot include this header on gcc without getting copious warnings of the kind:
+//
+// boost/integer.hpp:77:30: warning: use of C99 long long integer constant
+//
+// And yet there is no other reasonable implementation, so we declare this a system header
+// to suppress these warnings.
+//
+#if defined(__GNUC__) && (__GNUC__ >= 4)
+#pragma GCC system_header
+#endif
+
+namespace boost
+{
+
+ // Helper templates ------------------------------------------------------//
+
+ // fast integers from least integers
+ // int_fast_t<> works correctly for unsigned too, in spite of the name.
+ template< typename LeastInt >
+ struct int_fast_t
+ {
+ typedef LeastInt fast;
+ typedef fast type;
+ }; // imps may specialize
+
+ namespace detail{
+
+ // convert category to type
+ template< int Category > struct int_least_helper {}; // default is empty
+ template< int Category > struct uint_least_helper {}; // default is empty
+
+ // specializatons: 1=long, 2=int, 3=short, 4=signed char,
+ // 6=unsigned long, 7=unsigned int, 8=unsigned short, 9=unsigned char
+ // no specializations for 0 and 5: requests for a type > long are in error
+#ifdef BOOST_HAS_LONG_LONG
+ template<> struct int_least_helper<1> { typedef boost::long_long_type least; };
+#elif defined(BOOST_HAS_MS_INT64)
+ template<> struct int_least_helper<1> { typedef __int64 least; };
+#endif
+ template<> struct int_least_helper<2> { typedef long least; };
+ template<> struct int_least_helper<3> { typedef int least; };
+ template<> struct int_least_helper<4> { typedef short least; };
+ template<> struct int_least_helper<5> { typedef signed char least; };
+#ifdef BOOST_HAS_LONG_LONG
+ template<> struct uint_least_helper<1> { typedef boost::ulong_long_type least; };
+#elif defined(BOOST_HAS_MS_INT64)
+ template<> struct uint_least_helper<1> { typedef unsigned __int64 least; };
+#endif
+ template<> struct uint_least_helper<2> { typedef unsigned long least; };
+ template<> struct uint_least_helper<3> { typedef unsigned int least; };
+ template<> struct uint_least_helper<4> { typedef unsigned short least; };
+ template<> struct uint_least_helper<5> { typedef unsigned char least; };
+
+ template <int Bits>
+ struct exact_signed_base_helper{};
+ template <int Bits>
+ struct exact_unsigned_base_helper{};
+
+ template <> struct exact_signed_base_helper<sizeof(signed char)* CHAR_BIT> { typedef signed char exact; };
+ template <> struct exact_unsigned_base_helper<sizeof(unsigned char)* CHAR_BIT> { typedef unsigned char exact; };
+#if USHRT_MAX != UCHAR_MAX
+ template <> struct exact_signed_base_helper<sizeof(short)* CHAR_BIT> { typedef short exact; };
+ template <> struct exact_unsigned_base_helper<sizeof(unsigned short)* CHAR_BIT> { typedef unsigned short exact; };
+#endif
+#if UINT_MAX != USHRT_MAX
+ template <> struct exact_signed_base_helper<sizeof(int)* CHAR_BIT> { typedef int exact; };
+ template <> struct exact_unsigned_base_helper<sizeof(unsigned int)* CHAR_BIT> { typedef unsigned int exact; };
+#endif
+#if ULONG_MAX != UINT_MAX && ( !defined __TI_COMPILER_VERSION__ || \
+ ( __TI_COMPILER_VERSION__ >= 7000000 && !defined __TI_40BIT_LONG__ ) )
+ template <> struct exact_signed_base_helper<sizeof(long)* CHAR_BIT> { typedef long exact; };
+ template <> struct exact_unsigned_base_helper<sizeof(unsigned long)* CHAR_BIT> { typedef unsigned long exact; };
+#endif
+#if defined(BOOST_HAS_LONG_LONG) &&\
+ ((defined(ULLONG_MAX) && (ULLONG_MAX != ULONG_MAX)) ||\
+ (defined(ULONG_LONG_MAX) && (ULONG_LONG_MAX != ULONG_MAX)) ||\
+ (defined(ULONGLONG_MAX) && (ULONGLONG_MAX != ULONG_MAX)) ||\
+ (defined(_ULLONG_MAX) && (_ULLONG_MAX != ULONG_MAX)))
+ template <> struct exact_signed_base_helper<sizeof(boost::long_long_type)* CHAR_BIT> { typedef boost::long_long_type exact; };
+ template <> struct exact_unsigned_base_helper<sizeof(boost::ulong_long_type)* CHAR_BIT> { typedef boost::ulong_long_type exact; };
+#endif
+
+
+ } // namespace detail
+
+ // integer templates specifying number of bits ---------------------------//
+
+ // signed
+ template< int Bits > // bits (including sign) required
+ struct int_t : public boost::detail::exact_signed_base_helper<Bits>
+ {
+ BOOST_STATIC_ASSERT_MSG(Bits <= (int)(sizeof(boost::intmax_t) * CHAR_BIT),
+ "No suitable signed integer type with the requested number of bits is available.");
+ typedef typename boost::detail::int_least_helper
+ <
+#ifdef BOOST_HAS_LONG_LONG
+ (Bits <= (int)(sizeof(boost::long_long_type) * CHAR_BIT)) +
+#else
+ 1 +
+#endif
+ (Bits-1 <= ::std::numeric_limits<long>::digits) +
+ (Bits-1 <= ::std::numeric_limits<int>::digits) +
+ (Bits-1 <= ::std::numeric_limits<short>::digits) +
+ (Bits-1 <= ::std::numeric_limits<signed char>::digits)
+ >::least least;
+ typedef typename int_fast_t<least>::type fast;
+ };
+
+ // unsigned
+ template< int Bits > // bits required
+ struct uint_t : public boost::detail::exact_unsigned_base_helper<Bits>
+ {
+ BOOST_STATIC_ASSERT_MSG(Bits <= (int)(sizeof(boost::uintmax_t) * CHAR_BIT),
+ "No suitable unsigned integer type with the requested number of bits is available.");
+#if (defined(__BORLANDC__) || defined(__CODEGEAR__)) && defined(BOOST_NO_INTEGRAL_INT64_T)
+ // It's really not clear why this workaround should be needed... shrug I guess! JM
+ BOOST_STATIC_CONSTANT(int, s =
+ 6 +
+ (Bits <= ::std::numeric_limits<unsigned long>::digits) +
+ (Bits <= ::std::numeric_limits<unsigned int>::digits) +
+ (Bits <= ::std::numeric_limits<unsigned short>::digits) +
+ (Bits <= ::std::numeric_limits<unsigned char>::digits));
+ typedef typename detail::int_least_helper< ::boost::uint_t<Bits>::s>::least least;
+#else
+ typedef typename boost::detail::uint_least_helper
+ <
+#ifdef BOOST_HAS_LONG_LONG
+ (Bits <= (int)(sizeof(boost::long_long_type) * CHAR_BIT)) +
+#else
+ 1 +
+#endif
+ (Bits <= ::std::numeric_limits<unsigned long>::digits) +
+ (Bits <= ::std::numeric_limits<unsigned int>::digits) +
+ (Bits <= ::std::numeric_limits<unsigned short>::digits) +
+ (Bits <= ::std::numeric_limits<unsigned char>::digits)
+ >::least least;
+#endif
+ typedef typename int_fast_t<least>::type fast;
+ // int_fast_t<> works correctly for unsigned too, in spite of the name.
+ };
+
+ // integer templates specifying extreme value ----------------------------//
+
+ // signed
+#if !defined(BOOST_NO_INTEGRAL_INT64_T) && !defined(BOOST_NO_INT64_T) && defined(BOOST_HAS_LONG_LONG)
+ template< boost::long_long_type MaxValue > // maximum value to require support
+#else
+ template< long MaxValue > // maximum value to require support
+#endif
+ struct int_max_value_t
+ {
+ typedef typename boost::detail::int_least_helper
+ <
+#if !defined(BOOST_NO_INTEGRAL_INT64_T) && !defined(BOOST_NO_INT64_T) && defined(BOOST_HAS_LONG_LONG)
+ (MaxValue <= ::boost::integer_traits<boost::long_long_type>::const_max) +
+#else
+ 1 +
+#endif
+ (MaxValue <= ::boost::integer_traits<long>::const_max) +
+ (MaxValue <= ::boost::integer_traits<int>::const_max) +
+ (MaxValue <= ::boost::integer_traits<short>::const_max) +
+ (MaxValue <= ::boost::integer_traits<signed char>::const_max)
+ >::least least;
+ typedef typename int_fast_t<least>::type fast;
+ };
+
+#if !defined(BOOST_NO_INTEGRAL_INT64_T) && !defined(BOOST_NO_INT64_T) && defined(BOOST_HAS_LONG_LONG)
+ template< boost::long_long_type MinValue > // minimum value to require support
+#else
+ template< long MinValue > // minimum value to require support
+#endif
+ struct int_min_value_t
+ {
+ typedef typename boost::detail::int_least_helper
+ <
+#if !defined(BOOST_NO_INTEGRAL_INT64_T) && !defined(BOOST_NO_INT64_T) && defined(BOOST_HAS_LONG_LONG)
+ (MinValue >= ::boost::integer_traits<boost::long_long_type>::const_min) +
+#else
+ 1 +
+#endif
+ (MinValue >= ::boost::integer_traits<long>::const_min) +
+ (MinValue >= ::boost::integer_traits<int>::const_min) +
+ (MinValue >= ::boost::integer_traits<short>::const_min) +
+ (MinValue >= ::boost::integer_traits<signed char>::const_min)
+ >::least least;
+ typedef typename int_fast_t<least>::type fast;
+ };
+
+ // unsigned
+#if !defined(BOOST_NO_INTEGRAL_INT64_T) && defined(BOOST_HAS_LONG_LONG)
+ template< boost::ulong_long_type MaxValue > // minimum value to require support
+#else
+ template< unsigned long MaxValue > // minimum value to require support
+#endif
+ struct uint_value_t
+ {
+#if (defined(__BORLANDC__) || defined(__CODEGEAR__))
+ // It's really not clear why this workaround should be needed... shrug I guess! JM
+#if defined(BOOST_NO_INTEGRAL_INT64_T)
+ BOOST_STATIC_CONSTANT(unsigned, which =
+ 1 +
+ (MaxValue <= ::boost::integer_traits<unsigned long>::const_max) +
+ (MaxValue <= ::boost::integer_traits<unsigned int>::const_max) +
+ (MaxValue <= ::boost::integer_traits<unsigned short>::const_max) +
+ (MaxValue <= ::boost::integer_traits<unsigned char>::const_max));
+ typedef typename detail::int_least_helper< ::boost::uint_value_t<MaxValue>::which>::least least;
+#else // BOOST_NO_INTEGRAL_INT64_T
+ BOOST_STATIC_CONSTANT(unsigned, which =
+ 1 +
+ (MaxValue <= ::boost::integer_traits<boost::ulong_long_type>::const_max) +
+ (MaxValue <= ::boost::integer_traits<unsigned long>::const_max) +
+ (MaxValue <= ::boost::integer_traits<unsigned int>::const_max) +
+ (MaxValue <= ::boost::integer_traits<unsigned short>::const_max) +
+ (MaxValue <= ::boost::integer_traits<unsigned char>::const_max));
+ typedef typename detail::uint_least_helper< ::boost::uint_value_t<MaxValue>::which>::least least;
+#endif // BOOST_NO_INTEGRAL_INT64_T
+#else
+ typedef typename boost::detail::uint_least_helper
+ <
+#if !defined(BOOST_NO_INTEGRAL_INT64_T) && defined(BOOST_HAS_LONG_LONG)
+ (MaxValue <= ::boost::integer_traits<boost::ulong_long_type>::const_max) +
+#else
+ 1 +
+#endif
+ (MaxValue <= ::boost::integer_traits<unsigned long>::const_max) +
+ (MaxValue <= ::boost::integer_traits<unsigned int>::const_max) +
+ (MaxValue <= ::boost::integer_traits<unsigned short>::const_max) +
+ (MaxValue <= ::boost::integer_traits<unsigned char>::const_max)
+ >::least least;
+#endif
+ typedef typename int_fast_t<least>::type fast;
+ };
+
+
+} // namespace boost
+
+#endif // BOOST_INTEGER_HPP
diff --git a/third_party/boost/boost/integer_fwd.hpp b/third_party/boost/boost/integer_fwd.hpp
new file mode 100644
index 0000000..10577ae
--- /dev/null
+++ b/third_party/boost/boost/integer_fwd.hpp
@@ -0,0 +1,187 @@
+// Boost integer_fwd.hpp header file ---------------------------------------//
+
+// (C) Copyright Dave Abrahams and Daryle Walker 2001. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/integer for documentation.
+
+#ifndef BOOST_INTEGER_FWD_HPP
+#define BOOST_INTEGER_FWD_HPP
+
+#include <climits> // for UCHAR_MAX, etc.
+#include <cstddef> // for std::size_t
+
+#include <boost/config.hpp> // for BOOST_NO_INTRINSIC_WCHAR_T
+#include <boost/limits.hpp> // for std::numeric_limits
+#include <boost/cstdint.hpp> // For intmax_t
+
+
+namespace boost
+{
+
+#ifdef BOOST_NO_INTEGRAL_INT64_T
+ typedef unsigned long static_log2_argument_type;
+ typedef int static_log2_result_type;
+ typedef long static_min_max_signed_type;
+ typedef unsigned long static_min_max_unsigned_type;
+#else
+ typedef boost::uintmax_t static_min_max_unsigned_type;
+ typedef boost::intmax_t static_min_max_signed_type;
+ typedef boost::uintmax_t static_log2_argument_type;
+ typedef int static_log2_result_type;
+#endif
+
+// From <boost/cstdint.hpp> ------------------------------------------------//
+
+// Only has typedefs or using statements, with #conditionals
+
+
+// From <boost/integer_traits.hpp> -----------------------------------------//
+
+template < class T >
+ class integer_traits;
+
+template < >
+ class integer_traits< bool >;
+
+template < >
+ class integer_traits< char >;
+
+template < >
+ class integer_traits< signed char >;
+
+template < >
+ class integer_traits< unsigned char >;
+
+#ifndef BOOST_NO_INTRINSIC_WCHAR_T
+template < >
+ class integer_traits< wchar_t >;
+#endif
+
+template < >
+ class integer_traits< short >;
+
+template < >
+ class integer_traits< unsigned short >;
+
+template < >
+ class integer_traits< int >;
+
+template < >
+ class integer_traits< unsigned int >;
+
+template < >
+ class integer_traits< long >;
+
+template < >
+ class integer_traits< unsigned long >;
+
+#if !defined(BOOST_NO_INTEGRAL_INT64_T) && !defined(BOOST_NO_INT64_T) && defined(BOOST_HAS_LONG_LONG)
+template < >
+class integer_traits< ::boost::long_long_type>;
+
+template < >
+class integer_traits< ::boost::ulong_long_type >;
+#elif !defined(BOOST_NO_INTEGRAL_INT64_T) && !defined(BOOST_NO_INT64_T) && defined(BOOST_HAS_MS_INT64)
+template < >
+class integer_traits<__int64>;
+
+template < >
+class integer_traits<unsigned __int64>;
+#endif
+
+
+// From <boost/integer.hpp> ------------------------------------------------//
+
+template < typename LeastInt >
+ struct int_fast_t;
+
+template< int Bits >
+ struct int_t;
+
+template< int Bits >
+ struct uint_t;
+
+#if !defined(BOOST_NO_INTEGRAL_INT64_T) && defined(BOOST_HAS_LONG_LONG)
+ template< boost::long_long_type MaxValue > // maximum value to require support
+#else
+ template< long MaxValue > // maximum value to require support
+#endif
+ struct int_max_value_t;
+
+#if !defined(BOOST_NO_INTEGRAL_INT64_T) && defined(BOOST_HAS_LONG_LONG)
+ template< boost::long_long_type MinValue > // minimum value to require support
+#else
+ template< long MinValue > // minimum value to require support
+#endif
+ struct int_min_value_t;
+
+#if !defined(BOOST_NO_INTEGRAL_INT64_T) && defined(BOOST_HAS_LONG_LONG)
+ template< boost::ulong_long_type MaxValue > // maximum value to require support
+#else
+ template< unsigned long MaxValue > // maximum value to require support
+#endif
+ struct uint_value_t;
+
+
+// From <boost/integer/integer_mask.hpp> -----------------------------------//
+
+template < std::size_t Bit >
+ struct high_bit_mask_t;
+
+template < std::size_t Bits >
+ struct low_bits_mask_t;
+
+template < >
+ struct low_bits_mask_t< ::std::numeric_limits<unsigned char>::digits >;
+
+// From <boost/integer/static_log2.hpp> ------------------------------------//
+
+template <static_log2_argument_type Value >
+ struct static_log2;
+
+template <> struct static_log2<0u>;
+
+
+// From <boost/integer/static_min_max.hpp> ---------------------------------//
+
+template <static_min_max_signed_type Value1, static_min_max_signed_type Value2>
+ struct static_signed_min;
+
+template <static_min_max_signed_type Value1, static_min_max_signed_type Value2>
+ struct static_signed_max;
+
+template <static_min_max_unsigned_type Value1, static_min_max_unsigned_type Value2>
+ struct static_unsigned_min;
+
+template <static_min_max_unsigned_type Value1, static_min_max_unsigned_type Value2>
+ struct static_unsigned_max;
+
+
+// From <boost/integer/common_factor_ct.hpp>
+
+#ifdef BOOST_NO_INTEGRAL_INT64_T
+ typedef unsigned long static_gcd_type;
+#else
+ typedef boost::uintmax_t static_gcd_type;
+#endif
+
+template < static_gcd_type Value1, static_gcd_type Value2 >
+ struct static_gcd;
+template < static_gcd_type Value1, static_gcd_type Value2 >
+ struct static_lcm;
+
+
+// From <boost/integer/common_factor_rt.hpp>
+
+template < typename IntegerType >
+ class gcd_evaluator;
+template < typename IntegerType >
+ class lcm_evaluator;
+
+
+} // namespace boost
+
+
+#endif // BOOST_INTEGER_FWD_HPP
diff --git a/third_party/boost/boost/integer_traits.hpp b/third_party/boost/boost/integer_traits.hpp
new file mode 100644
index 0000000..26a8b4e
--- /dev/null
+++ b/third_party/boost/boost/integer_traits.hpp
@@ -0,0 +1,253 @@
+/* boost integer_traits.hpp header file
+ *
+ * Copyright Jens Maurer 2000
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * $Id$
+ *
+ * Idea by Beman Dawes, Ed Brey, Steve Cleary, and Nathan Myers
+ */
+
+// See http://www.boost.org/libs/integer for documentation.
+
+
+#ifndef BOOST_INTEGER_TRAITS_HPP
+#define BOOST_INTEGER_TRAITS_HPP
+
+#include <boost/config.hpp>
+#include <boost/limits.hpp>
+
+// These are an implementation detail and not part of the interface
+#include <limits.h>
+// we need wchar.h for WCHAR_MAX/MIN but not all platforms provide it,
+// and some may have <wchar.h> but not <cwchar> ...
+#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) && (!defined(BOOST_NO_CWCHAR) || defined(sun) || defined(__sun) || defined(__QNX__))
+#include <wchar.h>
+#endif
+
+//
+// We simply cannot include this header on gcc without getting copious warnings of the kind:
+//
+// ../../../boost/integer_traits.hpp:164:66: warning: use of C99 long long integer constant
+//
+// And yet there is no other reasonable implementation, so we declare this a system header
+// to suppress these warnings.
+//
+#if defined(__GNUC__) && (__GNUC__ >= 4)
+#pragma GCC system_header
+#endif
+
+namespace boost {
+template<class T>
+class integer_traits : public std::numeric_limits<T>
+{
+public:
+ BOOST_STATIC_CONSTANT(bool, is_integral = false);
+};
+
+namespace detail {
+template<class T, T min_val, T max_val>
+class integer_traits_base
+{
+public:
+ BOOST_STATIC_CONSTANT(bool, is_integral = true);
+ BOOST_STATIC_CONSTANT(T, const_min = min_val);
+ BOOST_STATIC_CONSTANT(T, const_max = max_val);
+};
+
+#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
+// A definition is required even for integral static constants
+template<class T, T min_val, T max_val>
+const bool integer_traits_base<T, min_val, max_val>::is_integral;
+
+template<class T, T min_val, T max_val>
+const T integer_traits_base<T, min_val, max_val>::const_min;
+
+template<class T, T min_val, T max_val>
+const T integer_traits_base<T, min_val, max_val>::const_max;
+#endif
+
+} // namespace detail
+
+template<>
+class integer_traits<bool>
+ : public std::numeric_limits<bool>,
+ public detail::integer_traits_base<bool, false, true>
+{ };
+
+template<>
+class integer_traits<char>
+ : public std::numeric_limits<char>,
+ public detail::integer_traits_base<char, CHAR_MIN, CHAR_MAX>
+{ };
+
+template<>
+class integer_traits<signed char>
+ : public std::numeric_limits<signed char>,
+ public detail::integer_traits_base<signed char, SCHAR_MIN, SCHAR_MAX>
+{ };
+
+template<>
+class integer_traits<unsigned char>
+ : public std::numeric_limits<unsigned char>,
+ public detail::integer_traits_base<unsigned char, 0, UCHAR_MAX>
+{ };
+
+#ifndef BOOST_NO_INTRINSIC_WCHAR_T
+template<>
+class integer_traits<wchar_t>
+ : public std::numeric_limits<wchar_t>,
+ // Don't trust WCHAR_MIN and WCHAR_MAX with Mac OS X's native
+ // library: they are wrong!
+#if defined(WCHAR_MIN) && defined(WCHAR_MAX) && !defined(__APPLE__)
+ public detail::integer_traits_base<wchar_t, WCHAR_MIN, WCHAR_MAX>
+#elif defined(__BORLANDC__) || defined(__CYGWIN__) || defined(__MINGW32__) || (defined(__BEOS__) && defined(__GNUC__))
+ // No WCHAR_MIN and WCHAR_MAX, whar_t is short and unsigned:
+ public detail::integer_traits_base<wchar_t, 0, 0xffff>
+#elif (defined(__sgi) && (!defined(__SGI_STL_PORT) || __SGI_STL_PORT < 0x400))\
+ || (defined __APPLE__)\
+ || (defined(__OpenBSD__) && defined(__GNUC__))\
+ || (defined(__NetBSD__) && defined(__GNUC__))\
+ || (defined(__FreeBSD__) && defined(__GNUC__))\
+ || (defined(__DragonFly__) && defined(__GNUC__))\
+ || (defined(__hpux) && defined(__GNUC__) && (__GNUC__ == 3) && !defined(__SGI_STL_PORT))
+ // No WCHAR_MIN and WCHAR_MAX, wchar_t has the same range as int.
+ // - SGI MIPSpro with native library
+ // - gcc 3.x on HP-UX
+ // - Mac OS X with native library
+ // - gcc on FreeBSD, OpenBSD and NetBSD
+ public detail::integer_traits_base<wchar_t, INT_MIN, INT_MAX>
+#else
+#error No WCHAR_MIN and WCHAR_MAX present, please adjust integer_traits<> for your compiler.
+#endif
+{ };
+#endif // BOOST_NO_INTRINSIC_WCHAR_T
+
+template<>
+class integer_traits<short>
+ : public std::numeric_limits<short>,
+ public detail::integer_traits_base<short, SHRT_MIN, SHRT_MAX>
+{ };
+
+template<>
+class integer_traits<unsigned short>
+ : public std::numeric_limits<unsigned short>,
+ public detail::integer_traits_base<unsigned short, 0, USHRT_MAX>
+{ };
+
+template<>
+class integer_traits<int>
+ : public std::numeric_limits<int>,
+ public detail::integer_traits_base<int, INT_MIN, INT_MAX>
+{ };
+
+template<>
+class integer_traits<unsigned int>
+ : public std::numeric_limits<unsigned int>,
+ public detail::integer_traits_base<unsigned int, 0, UINT_MAX>
+{ };
+
+template<>
+class integer_traits<long>
+ : public std::numeric_limits<long>,
+ public detail::integer_traits_base<long, LONG_MIN, LONG_MAX>
+{ };
+
+template<>
+class integer_traits<unsigned long>
+ : public std::numeric_limits<unsigned long>,
+ public detail::integer_traits_base<unsigned long, 0, ULONG_MAX>
+{ };
+
+#if !defined(BOOST_NO_INTEGRAL_INT64_T) && !defined(BOOST_NO_INT64_T)
+#if defined(ULLONG_MAX) && defined(BOOST_HAS_LONG_LONG)
+
+template<>
+class integer_traits< ::boost::long_long_type>
+ : public std::numeric_limits< ::boost::long_long_type>,
+ public detail::integer_traits_base< ::boost::long_long_type, LLONG_MIN, LLONG_MAX>
+{ };
+
+template<>
+class integer_traits< ::boost::ulong_long_type>
+ : public std::numeric_limits< ::boost::ulong_long_type>,
+ public detail::integer_traits_base< ::boost::ulong_long_type, 0, ULLONG_MAX>
+{ };
+
+#elif defined(ULONG_LONG_MAX) && defined(BOOST_HAS_LONG_LONG)
+
+template<>
+class integer_traits< ::boost::long_long_type> : public std::numeric_limits< ::boost::long_long_type>, public detail::integer_traits_base< ::boost::long_long_type, LONG_LONG_MIN, LONG_LONG_MAX>{ };
+template<>
+class integer_traits< ::boost::ulong_long_type>
+ : public std::numeric_limits< ::boost::ulong_long_type>,
+ public detail::integer_traits_base< ::boost::ulong_long_type, 0, ULONG_LONG_MAX>
+{ };
+
+#elif defined(ULONGLONG_MAX) && defined(BOOST_HAS_LONG_LONG)
+
+template<>
+class integer_traits< ::boost::long_long_type>
+ : public std::numeric_limits< ::boost::long_long_type>,
+ public detail::integer_traits_base< ::boost::long_long_type, LONGLONG_MIN, LONGLONG_MAX>
+{ };
+
+template<>
+class integer_traits< ::boost::ulong_long_type>
+ : public std::numeric_limits< ::boost::ulong_long_type>,
+ public detail::integer_traits_base< ::boost::ulong_long_type, 0, ULONGLONG_MAX>
+{ };
+
+#elif defined(_LLONG_MAX) && defined(_C2) && defined(BOOST_HAS_LONG_LONG)
+
+template<>
+class integer_traits< ::boost::long_long_type>
+ : public std::numeric_limits< ::boost::long_long_type>,
+ public detail::integer_traits_base< ::boost::long_long_type, -_LLONG_MAX - _C2, _LLONG_MAX>
+{ };
+
+template<>
+class integer_traits< ::boost::ulong_long_type>
+ : public std::numeric_limits< ::boost::ulong_long_type>,
+ public detail::integer_traits_base< ::boost::ulong_long_type, 0, _ULLONG_MAX>
+{ };
+
+#elif defined(BOOST_HAS_LONG_LONG)
+//
+// we have long long but no constants, this happens for example with gcc in -ansi mode,
+// we'll just have to work out the values for ourselves (assumes 2's compliment representation):
+//
+template<>
+class integer_traits< ::boost::long_long_type>
+ : public std::numeric_limits< ::boost::long_long_type>,
+ public detail::integer_traits_base< ::boost::long_long_type, (1LL << (sizeof(::boost::long_long_type) * CHAR_BIT - 1)), ~(1LL << (sizeof(::boost::long_long_type) * CHAR_BIT - 1))>
+{ };
+
+template<>
+class integer_traits< ::boost::ulong_long_type>
+ : public std::numeric_limits< ::boost::ulong_long_type>,
+ public detail::integer_traits_base< ::boost::ulong_long_type, 0, ~0uLL>
+{ };
+
+#elif defined(BOOST_HAS_MS_INT64)
+
+template<>
+class integer_traits< __int64>
+ : public std::numeric_limits< __int64>,
+ public detail::integer_traits_base< __int64, _I64_MIN, _I64_MAX>
+{ };
+
+template<>
+class integer_traits< unsigned __int64>
+ : public std::numeric_limits< unsigned __int64>,
+ public detail::integer_traits_base< unsigned __int64, 0, _UI64_MAX>
+{ };
+
+#endif
+#endif
+
+} // namespace boost
+
+#endif /* BOOST_INTEGER_TRAITS_HPP */
diff --git a/third_party/boost/boost/is_placeholder.hpp b/third_party/boost/boost/is_placeholder.hpp
new file mode 100644
index 0000000..5f1b544
--- /dev/null
+++ b/third_party/boost/boost/is_placeholder.hpp
@@ -0,0 +1,31 @@
+#ifndef BOOST_IS_PLACEHOLDER_HPP_INCLUDED
+#define BOOST_IS_PLACEHOLDER_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined( _MSC_VER ) && ( _MSC_VER >= 1020 )
+# pragma once
+#endif
+
+
+// is_placeholder.hpp - TR1 is_placeholder metafunction
+//
+// Copyright (c) 2006 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+//
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+
+namespace boost
+{
+
+template< class T > struct is_placeholder
+{
+ enum _vt { value = 0 };
+};
+
+} // namespace boost
+
+#endif // #ifndef BOOST_IS_PLACEHOLDER_HPP_INCLUDED
diff --git a/third_party/boost/boost/iterator.hpp b/third_party/boost/boost/iterator.hpp
new file mode 100644
index 0000000..c9c6197
--- /dev/null
+++ b/third_party/boost/boost/iterator.hpp
@@ -0,0 +1,20 @@
+// (C) Copyright Beman Dawes 2000. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_ITERATOR_HPP
+#define BOOST_ITERATOR_HPP
+
+// This header is obsolete and will be deprecated.
+
+#include <iterator>
+#include <cstddef> // std::ptrdiff_t
+
+namespace boost
+{
+
+using std::iterator;
+
+} // namespace boost
+
+#endif // BOOST_ITERATOR_HPP
diff --git a/third_party/boost/boost/iterator/detail/config_def.hpp b/third_party/boost/boost/iterator/detail/config_def.hpp
new file mode 100644
index 0000000..bf37fbb
--- /dev/null
+++ b/third_party/boost/boost/iterator/detail/config_def.hpp
@@ -0,0 +1,128 @@
+// (C) Copyright David Abrahams 2002.
+// (C) Copyright Jeremy Siek 2002.
+// (C) Copyright Thomas Witt 2002.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// no include guard multiple inclusion intended
+
+//
+// This is a temporary workaround until the bulk of this is
+// available in boost config.
+// 23/02/03 thw
+//
+
+#include <boost/config.hpp> // for prior
+#include <boost/detail/workaround.hpp>
+
+#ifdef BOOST_ITERATOR_CONFIG_DEF
+# error you have nested config_def #inclusion.
+#else
+# define BOOST_ITERATOR_CONFIG_DEF
+#endif
+
+// We enable this always now. Otherwise, the simple case in
+// libs/iterator/test/constant_iterator_arrow.cpp fails to compile
+// because the operator-> return is improperly deduced as a non-const
+// pointer.
+#if 1 || defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
+ || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x531))
+
+// Recall that in general, compilers without partial specialization
+// can't strip constness. Consider counting_iterator, which normally
+// passes a const Value to iterator_facade. As a result, any code
+// which makes a std::vector of the iterator's value_type will fail
+// when its allocator declares functions overloaded on reference and
+// const_reference (the same type).
+//
+// Furthermore, Borland 5.5.1 drops constness in enough ways that we
+// end up using a proxy for operator[] when we otherwise shouldn't.
+// Using reference constness gives it an extra hint that it can
+// return the value_type from operator[] directly, but is not
+// strictly necessary. Not sure how best to resolve this one.
+
+# define BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY 1
+
+#endif
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x5A0)) \
+ || (BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700) && defined(_MSC_VER)) \
+ || BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042)) \
+ || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
+
+# define BOOST_NO_LVALUE_RETURN_DETECTION
+
+# if 0 // test code
+ struct v {};
+
+ typedef char (&no)[3];
+
+ template <class T>
+ no foo(T const&, ...);
+
+ template <class T>
+ char foo(T&, int);
+
+
+ struct value_iterator
+ {
+ v operator*() const;
+ };
+
+ template <class T>
+ struct lvalue_deref_helper
+ {
+ static T& x;
+ enum { value = (sizeof(foo(*x,0)) == 1) };
+ };
+
+ int z2[(lvalue_deref_helper<v*>::value == 1) ? 1 : -1];
+ int z[(lvalue_deref_helper<value_iterator>::value) == 1 ? -1 : 1 ];
+# endif
+
+#endif
+
+#if BOOST_WORKAROUND(__MWERKS__, <=0x2407)
+# define BOOST_NO_IS_CONVERTIBLE // "is_convertible doesn't work for simple types"
+#endif
+
+#if BOOST_WORKAROUND(__GNUC__, == 3) && BOOST_WORKAROUND(__GNUC_MINOR__, < 4) && !defined(__EDG_VERSION__) \
+ || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
+# define BOOST_NO_IS_CONVERTIBLE_TEMPLATE // The following program fails to compile:
+
+# if 0 // test code
+ #include <boost/type_traits/is_convertible.hpp>
+ template <class T>
+ struct foo
+ {
+ foo(T);
+
+ template <class U>
+ foo(foo<U> const& other) : p(other.p) { }
+
+ T p;
+ };
+
+ bool x = boost::is_convertible<foo<int const*>, foo<int*> >::value;
+# endif
+
+#endif
+
+
+#if !defined(BOOST_MSVC) && (defined(BOOST_NO_SFINAE) || defined(BOOST_NO_IS_CONVERTIBLE) || defined(BOOST_NO_IS_CONVERTIBLE_TEMPLATE))
+# define BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY
+#endif
+
+# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+
+// GCC-2.95 (obsolete) eagerly instantiates templated constructors and conversion
+// operators in convertibility checks, causing premature errors.
+//
+// Borland's problems are harder to diagnose due to lack of an
+// instantiation stack backtrace. They may be due in part to the fact
+// that it drops cv-qualification willy-nilly in templates.
+# define BOOST_NO_ONE_WAY_ITERATOR_INTEROP
+# endif
+
+// no include guard; multiple inclusion intended
diff --git a/third_party/boost/boost/iterator/detail/config_undef.hpp b/third_party/boost/boost/iterator/detail/config_undef.hpp
new file mode 100644
index 0000000..a32529c
--- /dev/null
+++ b/third_party/boost/boost/iterator/detail/config_undef.hpp
@@ -0,0 +1,24 @@
+// (C) Copyright Thomas Witt 2002.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// no include guard multiple inclusion intended
+
+//
+// This is a temporary workaround until the bulk of this is
+// available in boost config.
+// 23/02/03 thw
+//
+
+#undef BOOST_NO_IS_CONVERTIBLE
+#undef BOOST_NO_IS_CONVERTIBLE_TEMPLATE
+#undef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY
+#undef BOOST_NO_LVALUE_RETURN_DETECTION
+#undef BOOST_NO_ONE_WAY_ITERATOR_INTEROP
+
+#ifdef BOOST_ITERATOR_CONFIG_DEF
+# undef BOOST_ITERATOR_CONFIG_DEF
+#else
+# error missing or nested #include config_def
+#endif
diff --git a/third_party/boost/boost/iterator/detail/enable_if.hpp b/third_party/boost/boost/iterator/detail/enable_if.hpp
new file mode 100644
index 0000000..071f5fe
--- /dev/null
+++ b/third_party/boost/boost/iterator/detail/enable_if.hpp
@@ -0,0 +1,83 @@
+// (C) Copyright David Abrahams 2002.
+// (C) Copyright Jeremy Siek 2002.
+// (C) Copyright Thomas Witt 2002.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+#ifndef BOOST_ENABLE_IF_23022003THW_HPP
+#define BOOST_ENABLE_IF_23022003THW_HPP
+
+#include <boost/detail/workaround.hpp>
+#include <boost/mpl/identity.hpp>
+
+#include <boost/iterator/detail/config_def.hpp>
+
+//
+// Boost iterators uses its own enable_if cause we need
+// special semantics for deficient compilers.
+// 23/02/03 thw
+//
+
+namespace boost
+{
+
+ namespace iterators
+ {
+ //
+ // Base machinery for all kinds of enable if
+ //
+ template<bool>
+ struct enabled
+ {
+ template<typename T>
+ struct base
+ {
+ typedef T type;
+ };
+ };
+
+ //
+ // For compilers that don't support "Substitution Failure Is Not An Error"
+ // enable_if falls back to always enabled. See comments
+ // on operator implementation for consequences.
+ //
+ template<>
+ struct enabled<false>
+ {
+ template<typename T>
+ struct base
+ {
+#ifdef BOOST_NO_SFINAE
+
+ typedef T type;
+
+ // This way to do it would give a nice error message containing
+ // invalid overload, but has the big disadvantage that
+ // there is no reference to user code in the error message.
+ //
+ // struct invalid_overload;
+ // typedef invalid_overload type;
+ //
+#endif
+ };
+ };
+
+
+ template <class Cond,
+ class Return>
+ struct enable_if
+# if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE)
+ : enabled<(Cond::value)>::template base<Return>
+# else
+ : mpl::identity<Return>
+# endif
+ {
+ };
+
+ } // namespace iterators
+
+} // namespace boost
+
+#include <boost/iterator/detail/config_undef.hpp>
+
+#endif // BOOST_ENABLE_IF_23022003THW_HPP
diff --git a/third_party/boost/boost/iterator/detail/facade_iterator_category.hpp b/third_party/boost/boost/iterator/detail/facade_iterator_category.hpp
new file mode 100644
index 0000000..67fdf44
--- /dev/null
+++ b/third_party/boost/boost/iterator/detail/facade_iterator_category.hpp
@@ -0,0 +1,193 @@
+// Copyright David Abrahams 2003. Use, modification and distribution is
+// subject to the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#ifndef FACADE_ITERATOR_CATEGORY_DWA20031118_HPP
+# define FACADE_ITERATOR_CATEGORY_DWA20031118_HPP
+
+# include <boost/iterator/iterator_categories.hpp>
+
+# include <boost/mpl/or.hpp> // used in iterator_tag inheritance logic
+# include <boost/mpl/and.hpp>
+# include <boost/mpl/if.hpp>
+# include <boost/mpl/eval_if.hpp>
+# include <boost/mpl/identity.hpp>
+# include <boost/mpl/assert.hpp>
+
+# include <boost/type_traits/is_same.hpp>
+# include <boost/type_traits/is_const.hpp>
+# include <boost/type_traits/is_reference.hpp>
+# include <boost/type_traits/is_convertible.hpp>
+
+# include <boost/type_traits/is_same.hpp>
+
+# include <boost/iterator/detail/config_def.hpp> // try to keep this last
+
+# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
+# include <boost/detail/indirect_traits.hpp>
+# endif
+
+//
+// iterator_category deduction for iterator_facade
+//
+
+namespace boost {
+namespace iterators {
+
+// forward declaration
+struct use_default;
+
+namespace detail {
+
+struct input_output_iterator_tag
+ : std::input_iterator_tag
+{
+ // Using inheritance for only input_iterator_tag helps to avoid
+ // ambiguities when a stdlib implementation dispatches on a
+ // function which is overloaded on both input_iterator_tag and
+ // output_iterator_tag, as STLPort does, in its __valid_range
+ // function. I claim it's better to avoid the ambiguity in these
+ // cases.
+ operator std::output_iterator_tag() const
+ {
+ return std::output_iterator_tag();
+ }
+};
+
+//
+// True iff the user has explicitly disabled writability of this
+// iterator. Pass the iterator_facade's Value parameter and its
+// nested ::reference type.
+//
+template <class ValueParam, class Reference>
+struct iterator_writability_disabled
+# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY // Adding Thomas' logic?
+ : mpl::or_<
+ is_const<Reference>
+ , boost::detail::indirect_traits::is_reference_to_const<Reference>
+ , is_const<ValueParam>
+ >
+# else
+ : is_const<ValueParam>
+# endif
+{};
+
+
+//
+// Convert an iterator_facade's traversal category, Value parameter,
+// and ::reference type to an appropriate old-style category.
+//
+// Due to changeset 21683, this now never results in a category convertible
+// to output_iterator_tag.
+//
+// Change at: https://svn.boost.org/trac/boost/changeset/21683
+template <class Traversal, class ValueParam, class Reference>
+struct iterator_facade_default_category
+ : mpl::eval_if<
+ mpl::and_<
+ is_reference<Reference>
+ , is_convertible<Traversal,forward_traversal_tag>
+ >
+ , mpl::eval_if<
+ is_convertible<Traversal,random_access_traversal_tag>
+ , mpl::identity<std::random_access_iterator_tag>
+ , mpl::if_<
+ is_convertible<Traversal,bidirectional_traversal_tag>
+ , std::bidirectional_iterator_tag
+ , std::forward_iterator_tag
+ >
+ >
+ , typename mpl::eval_if<
+ mpl::and_<
+ is_convertible<Traversal, single_pass_traversal_tag>
+
+ // check for readability
+ , is_convertible<Reference, ValueParam>
+ >
+ , mpl::identity<std::input_iterator_tag>
+ , mpl::identity<Traversal>
+ >
+ >
+{
+};
+
+// True iff T is convertible to an old-style iterator category.
+template <class T>
+struct is_iterator_category
+ : mpl::or_<
+ is_convertible<T,std::input_iterator_tag>
+ , is_convertible<T,std::output_iterator_tag>
+ >
+{
+};
+
+template <class T>
+struct is_iterator_traversal
+ : is_convertible<T,incrementable_traversal_tag>
+{};
+
+//
+// A composite iterator_category tag convertible to Category (a pure
+// old-style category) and Traversal (a pure traversal tag).
+// Traversal must be a strict increase of the traversal power given by
+// Category.
+//
+template <class Category, class Traversal>
+struct iterator_category_with_traversal
+ : Category, Traversal
+{
+ // Make sure this isn't used to build any categories where
+ // convertibility to Traversal is redundant. Should just use the
+ // Category element in that case.
+ BOOST_MPL_ASSERT_NOT((
+ is_convertible<
+ typename iterator_category_to_traversal<Category>::type
+ , Traversal
+ >));
+
+ BOOST_MPL_ASSERT((is_iterator_category<Category>));
+ BOOST_MPL_ASSERT_NOT((is_iterator_category<Traversal>));
+ BOOST_MPL_ASSERT_NOT((is_iterator_traversal<Category>));
+# if !BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1310))
+ BOOST_MPL_ASSERT((is_iterator_traversal<Traversal>));
+# endif
+};
+
+// Computes an iterator_category tag whose traversal is Traversal and
+// which is appropriate for an iterator
+template <class Traversal, class ValueParam, class Reference>
+struct facade_iterator_category_impl
+{
+ BOOST_MPL_ASSERT_NOT((is_iterator_category<Traversal>));
+
+ typedef typename iterator_facade_default_category<
+ Traversal,ValueParam,Reference
+ >::type category;
+
+ typedef typename mpl::if_<
+ is_same<
+ Traversal
+ , typename iterator_category_to_traversal<category>::type
+ >
+ , category
+ , iterator_category_with_traversal<category,Traversal>
+ >::type type;
+};
+
+//
+// Compute an iterator_category for iterator_facade
+//
+template <class CategoryOrTraversal, class ValueParam, class Reference>
+struct facade_iterator_category
+ : mpl::eval_if<
+ is_iterator_category<CategoryOrTraversal>
+ , mpl::identity<CategoryOrTraversal> // old-style categories are fine as-is
+ , facade_iterator_category_impl<CategoryOrTraversal,ValueParam,Reference>
+ >
+{
+};
+
+}}} // namespace boost::iterators::detail
+
+# include <boost/iterator/detail/config_undef.hpp>
+
+#endif // FACADE_ITERATOR_CATEGORY_DWA20031118_HPP
diff --git a/third_party/boost/boost/iterator/interoperable.hpp b/third_party/boost/boost/iterator/interoperable.hpp
new file mode 100644
index 0000000..6f3c872
--- /dev/null
+++ b/third_party/boost/boost/iterator/interoperable.hpp
@@ -0,0 +1,54 @@
+// (C) Copyright David Abrahams 2002.
+// (C) Copyright Jeremy Siek 2002.
+// (C) Copyright Thomas Witt 2002.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+#ifndef BOOST_INTEROPERABLE_23022003THW_HPP
+# define BOOST_INTEROPERABLE_23022003THW_HPP
+
+# include <boost/mpl/bool.hpp>
+# include <boost/mpl/or.hpp>
+
+# include <boost/type_traits/is_convertible.hpp>
+
+# include <boost/iterator/detail/config_def.hpp> // must appear last
+
+namespace boost {
+namespace iterators {
+
+ //
+ // Meta function that determines whether two
+ // iterator types are considered interoperable.
+ //
+ // Two iterator types A,B are considered interoperable if either
+ // A is convertible to B or vice versa.
+ // This interoperability definition is in sync with the
+ // standards requirements on constant/mutable container
+ // iterators (23.1 [lib.container.requirements]).
+ //
+ // For compilers that don't support is_convertible
+ // is_interoperable gives false positives. See comments
+ // on operator implementation for consequences.
+ //
+ template <typename A, typename B>
+ struct is_interoperable
+# ifdef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY
+ : mpl::true_
+# else
+ : mpl::or_<
+ is_convertible< A, B >
+ , is_convertible< B, A > >
+# endif
+ {
+ };
+
+} // namespace iterators
+
+using iterators::is_interoperable;
+
+} // namespace boost
+
+# include <boost/iterator/detail/config_undef.hpp>
+
+#endif // BOOST_INTEROPERABLE_23022003THW_HPP
diff --git a/third_party/boost/boost/iterator/iterator_adaptor.hpp b/third_party/boost/boost/iterator/iterator_adaptor.hpp
new file mode 100644
index 0000000..87cfd05
--- /dev/null
+++ b/third_party/boost/boost/iterator/iterator_adaptor.hpp
@@ -0,0 +1,360 @@
+// (C) Copyright David Abrahams 2002.
+// (C) Copyright Jeremy Siek 2002.
+// (C) Copyright Thomas Witt 2002.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+#ifndef BOOST_ITERATOR_ADAPTOR_23022003THW_HPP
+#define BOOST_ITERATOR_ADAPTOR_23022003THW_HPP
+
+#include <boost/static_assert.hpp>
+#include <boost/iterator.hpp>
+#include <boost/detail/iterator.hpp>
+
+#include <boost/iterator/iterator_categories.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/iterator/detail/enable_if.hpp>
+
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/not.hpp>
+#include <boost/mpl/or.hpp>
+
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+
+#ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
+# include <boost/type_traits/remove_reference.hpp>
+#endif
+
+#include <boost/type_traits/add_reference.hpp>
+#include <boost/iterator/detail/config_def.hpp>
+
+#include <boost/iterator/iterator_traits.hpp>
+
+namespace boost {
+namespace iterators {
+
+ // Used as a default template argument internally, merely to
+ // indicate "use the default", this can also be passed by users
+ // explicitly in order to specify that the default should be used.
+ struct use_default;
+
+} // namespace iterators
+
+using iterators::use_default;
+
+// the incompleteness of use_default causes massive problems for
+// is_convertible (naturally). This workaround is fortunately not
+// needed for vc6/vc7.
+template<class To>
+struct is_convertible<use_default,To>
+ : mpl::false_ {};
+
+namespace iterators {
+
+ namespace detail
+ {
+
+ //
+ // Result type used in enable_if_convertible meta function.
+ // This can be an incomplete type, as only pointers to
+ // enable_if_convertible< ... >::type are used.
+ // We could have used void for this, but conversion to
+ // void* is just to easy.
+ //
+ struct enable_type;
+ }
+
+
+ //
+ // enable_if for use in adapted iterators constructors.
+ //
+ // In order to provide interoperability between adapted constant and
+ // mutable iterators, adapted iterators will usually provide templated
+ // conversion constructors of the following form
+ //
+ // template <class BaseIterator>
+ // class adapted_iterator :
+ // public iterator_adaptor< adapted_iterator<Iterator>, Iterator >
+ // {
+ // public:
+ //
+ // ...
+ //
+ // template <class OtherIterator>
+ // adapted_iterator(
+ // OtherIterator const& it
+ // , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0);
+ //
+ // ...
+ // };
+ //
+ // enable_if_convertible is used to remove those overloads from the overload
+ // set that cannot be instantiated. For all practical purposes only overloads
+ // for constant/mutable interaction will remain. This has the advantage that
+ // meta functions like boost::is_convertible do not return false positives,
+ // as they can only look at the signature of the conversion constructor
+ // and not at the actual instantiation.
+ //
+ // enable_if_interoperable can be safely used in user code. It falls back to
+ // always enabled for compilers that don't support enable_if or is_convertible.
+ // There is no need for compiler specific workarounds in user code.
+ //
+ // The operators implementation relies on boost::is_convertible not returning
+ // false positives for user/library defined iterator types. See comments
+ // on operator implementation for consequences.
+ //
+# if defined(BOOST_NO_IS_CONVERTIBLE) || defined(BOOST_NO_SFINAE)
+
+ template <class From, class To>
+ struct enable_if_convertible
+ {
+ typedef boost::iterators::detail::enable_type type;
+ };
+
+# elif BOOST_WORKAROUND(_MSC_FULL_VER, BOOST_TESTED_AT(13102292))
+
+ // For some reason vc7.1 needs us to "cut off" instantiation
+ // of is_convertible in a few cases.
+ template<typename From, typename To>
+ struct enable_if_convertible
+ : iterators::enable_if<
+ mpl::or_<
+ is_same<From,To>
+ , is_convertible<From, To>
+ >
+ , boost::iterators::detail::enable_type
+ >
+ {};
+
+# else
+
+ template<typename From, typename To>
+ struct enable_if_convertible
+ : iterators::enable_if<
+ is_convertible<From, To>
+ , boost::iterators::detail::enable_type
+ >
+ {};
+
+# endif
+
+ //
+ // Default template argument handling for iterator_adaptor
+ //
+ namespace detail
+ {
+ // If T is use_default, return the result of invoking
+ // DefaultNullaryFn, otherwise return T.
+ template <class T, class DefaultNullaryFn>
+ struct ia_dflt_help
+ : mpl::eval_if<
+ is_same<T, use_default>
+ , DefaultNullaryFn
+ , mpl::identity<T>
+ >
+ {
+ };
+
+ // A metafunction which computes an iterator_adaptor's base class,
+ // a specialization of iterator_facade.
+ template <
+ class Derived
+ , class Base
+ , class Value
+ , class Traversal
+ , class Reference
+ , class Difference
+ >
+ struct iterator_adaptor_base
+ {
+ typedef iterator_facade<
+ Derived
+
+# ifdef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY
+ , typename boost::iterators::detail::ia_dflt_help<
+ Value
+ , mpl::eval_if<
+ is_same<Reference,use_default>
+ , iterator_value<Base>
+ , remove_reference<Reference>
+ >
+ >::type
+# else
+ , typename boost::iterators::detail::ia_dflt_help<
+ Value, iterator_value<Base>
+ >::type
+# endif
+
+ , typename boost::iterators::detail::ia_dflt_help<
+ Traversal
+ , iterator_traversal<Base>
+ >::type
+
+ , typename boost::iterators::detail::ia_dflt_help<
+ Reference
+ , mpl::eval_if<
+ is_same<Value,use_default>
+ , iterator_reference<Base>
+ , add_reference<Value>
+ >
+ >::type
+
+ , typename boost::iterators::detail::ia_dflt_help<
+ Difference, iterator_difference<Base>
+ >::type
+ >
+ type;
+ };
+
+ // workaround for aC++ CR JAGaf33512
+ template <class Tr1, class Tr2>
+ inline void iterator_adaptor_assert_traversal ()
+ {
+ BOOST_STATIC_ASSERT((is_convertible<Tr1, Tr2>::value));
+ }
+ }
+
+ //
+ // Iterator Adaptor
+ //
+ // The parameter ordering changed slightly with respect to former
+ // versions of iterator_adaptor The idea is that when the user needs
+ // to fiddle with the reference type it is highly likely that the
+ // iterator category has to be adjusted as well. Any of the
+ // following four template arguments may be ommitted or explicitly
+ // replaced by use_default.
+ //
+ // Value - if supplied, the value_type of the resulting iterator, unless
+ // const. If const, a conforming compiler strips constness for the
+ // value_type. If not supplied, iterator_traits<Base>::value_type is used
+ //
+ // Category - the traversal category of the resulting iterator. If not
+ // supplied, iterator_traversal<Base>::type is used.
+ //
+ // Reference - the reference type of the resulting iterator, and in
+ // particular, the result type of operator*(). If not supplied but
+ // Value is supplied, Value& is used. Otherwise
+ // iterator_traits<Base>::reference is used.
+ //
+ // Difference - the difference_type of the resulting iterator. If not
+ // supplied, iterator_traits<Base>::difference_type is used.
+ //
+ template <
+ class Derived
+ , class Base
+ , class Value = use_default
+ , class Traversal = use_default
+ , class Reference = use_default
+ , class Difference = use_default
+ >
+ class iterator_adaptor
+ : public boost::iterators::detail::iterator_adaptor_base<
+ Derived, Base, Value, Traversal, Reference, Difference
+ >::type
+ {
+ friend class iterator_core_access;
+
+ protected:
+ typedef typename boost::iterators::detail::iterator_adaptor_base<
+ Derived, Base, Value, Traversal, Reference, Difference
+ >::type super_t;
+ public:
+ iterator_adaptor() {}
+
+ explicit iterator_adaptor(Base const &iter)
+ : m_iterator(iter)
+ {
+ }
+
+ typedef Base base_type;
+
+ Base const& base() const
+ { return m_iterator; }
+
+ protected:
+ // for convenience in derived classes
+ typedef iterator_adaptor<Derived,Base,Value,Traversal,Reference,Difference> iterator_adaptor_;
+
+ //
+ // lvalue access to the Base object for Derived
+ //
+ Base const& base_reference() const
+ { return m_iterator; }
+
+ Base& base_reference()
+ { return m_iterator; }
+
+ private:
+ //
+ // Core iterator interface for iterator_facade. This is private
+ // to prevent temptation for Derived classes to use it, which
+ // will often result in an error. Derived classes should use
+ // base_reference(), above, to get direct access to m_iterator.
+ //
+ typename super_t::reference dereference() const
+ { return *m_iterator; }
+
+ template <
+ class OtherDerived, class OtherIterator, class V, class C, class R, class D
+ >
+ bool equal(iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& x) const
+ {
+ // Maybe readd with same_distance
+ // BOOST_STATIC_ASSERT(
+ // (detail::same_category_and_difference<Derived,OtherDerived>::value)
+ // );
+ return m_iterator == x.base();
+ }
+
+ typedef typename iterator_category_to_traversal<
+ typename super_t::iterator_category
+ >::type my_traversal;
+
+# define BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(cat) \
+ boost::iterators::detail::iterator_adaptor_assert_traversal<my_traversal, cat>();
+
+ void advance(typename super_t::difference_type n)
+ {
+ BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag)
+ m_iterator += n;
+ }
+
+ void increment() { ++m_iterator; }
+
+ void decrement()
+ {
+ BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(bidirectional_traversal_tag)
+ --m_iterator;
+ }
+
+ template <
+ class OtherDerived, class OtherIterator, class V, class C, class R, class D
+ >
+ typename super_t::difference_type distance_to(
+ iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> const& y) const
+ {
+ BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL(random_access_traversal_tag)
+ // Maybe readd with same_distance
+ // BOOST_STATIC_ASSERT(
+ // (detail::same_category_and_difference<Derived,OtherDerived>::value)
+ // );
+ return y.base() - m_iterator;
+ }
+
+# undef BOOST_ITERATOR_ADAPTOR_ASSERT_TRAVERSAL
+
+ private: // data members
+ Base m_iterator;
+ };
+
+} // namespace iterators
+
+using iterators::iterator_adaptor;
+using iterators::enable_if_convertible;
+
+} // namespace boost
+
+#include <boost/iterator/detail/config_undef.hpp>
+
+#endif // BOOST_ITERATOR_ADAPTOR_23022003THW_HPP
diff --git a/third_party/boost/boost/iterator/iterator_categories.hpp b/third_party/boost/boost/iterator/iterator_categories.hpp
new file mode 100644
index 0000000..71202c9
--- /dev/null
+++ b/third_party/boost/boost/iterator/iterator_categories.hpp
@@ -0,0 +1,215 @@
+// (C) Copyright Jeremy Siek 2002.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_ITERATOR_CATEGORIES_HPP
+# define BOOST_ITERATOR_CATEGORIES_HPP
+
+# include <boost/config.hpp>
+# include <boost/detail/iterator.hpp>
+# include <boost/iterator/detail/config_def.hpp>
+
+# include <boost/detail/workaround.hpp>
+
+# include <boost/mpl/eval_if.hpp>
+# include <boost/mpl/identity.hpp>
+# include <boost/mpl/placeholders.hpp>
+# include <boost/mpl/aux_/lambda_support.hpp>
+
+# include <boost/type_traits/is_convertible.hpp>
+
+# include <boost/static_assert.hpp>
+
+namespace boost {
+namespace iterators {
+
+//
+// Traversal Categories
+//
+
+struct no_traversal_tag {};
+
+struct incrementable_traversal_tag
+ : no_traversal_tag
+{
+// incrementable_traversal_tag() {}
+// incrementable_traversal_tag(std::output_iterator_tag const&) {};
+};
+
+struct single_pass_traversal_tag
+ : incrementable_traversal_tag
+{
+// single_pass_traversal_tag() {}
+// single_pass_traversal_tag(std::input_iterator_tag const&) {};
+};
+
+struct forward_traversal_tag
+ : single_pass_traversal_tag
+{
+// forward_traversal_tag() {}
+// forward_traversal_tag(std::forward_iterator_tag const&) {};
+};
+
+struct bidirectional_traversal_tag
+ : forward_traversal_tag
+{
+// bidirectional_traversal_tag() {};
+// bidirectional_traversal_tag(std::bidirectional_iterator_tag const&) {};
+};
+
+struct random_access_traversal_tag
+ : bidirectional_traversal_tag
+{
+// random_access_traversal_tag() {};
+// random_access_traversal_tag(std::random_access_iterator_tag const&) {};
+};
+
+namespace detail
+{
+ //
+ // Convert a "strictly old-style" iterator category to a traversal
+ // tag. This is broken out into a separate metafunction to reduce
+ // the cost of instantiating iterator_category_to_traversal, below,
+ // for new-style types.
+ //
+ template <class Cat>
+ struct old_category_to_traversal
+ : mpl::eval_if<
+ is_convertible<Cat,std::random_access_iterator_tag>
+ , mpl::identity<random_access_traversal_tag>
+ , mpl::eval_if<
+ is_convertible<Cat,std::bidirectional_iterator_tag>
+ , mpl::identity<bidirectional_traversal_tag>
+ , mpl::eval_if<
+ is_convertible<Cat,std::forward_iterator_tag>
+ , mpl::identity<forward_traversal_tag>
+ , mpl::eval_if<
+ is_convertible<Cat,std::input_iterator_tag>
+ , mpl::identity<single_pass_traversal_tag>
+ , mpl::eval_if<
+ is_convertible<Cat,std::output_iterator_tag>
+ , mpl::identity<incrementable_traversal_tag>
+ , void
+ >
+ >
+ >
+ >
+ >
+ {};
+
+} // namespace detail
+
+//
+// Convert an iterator category into a traversal tag
+//
+template <class Cat>
+struct iterator_category_to_traversal
+ : mpl::eval_if< // if already convertible to a traversal tag, we're done.
+ is_convertible<Cat,incrementable_traversal_tag>
+ , mpl::identity<Cat>
+ , boost::iterators::detail::old_category_to_traversal<Cat>
+ >
+{};
+
+// Trait to get an iterator's traversal category
+template <class Iterator = mpl::_1>
+struct iterator_traversal
+ : iterator_category_to_traversal<
+ typename boost::detail::iterator_traits<Iterator>::iterator_category
+ >
+{};
+
+# ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT
+// Hack because BOOST_MPL_AUX_LAMBDA_SUPPORT doesn't seem to work
+// out well. Instantiating the nested apply template also
+// requires instantiating iterator_traits on the
+// placeholder. Instead we just specialize it as a metafunction
+// class.
+template <>
+struct iterator_traversal<mpl::_1>
+{
+ template <class T>
+ struct apply : iterator_traversal<T>
+ {};
+};
+template <>
+struct iterator_traversal<mpl::_>
+ : iterator_traversal<mpl::_1>
+{};
+# endif
+
+//
+// Convert an iterator traversal to one of the traversal tags.
+//
+template <class Traversal>
+struct pure_traversal_tag
+ : mpl::eval_if<
+ is_convertible<Traversal,random_access_traversal_tag>
+ , mpl::identity<random_access_traversal_tag>
+ , mpl::eval_if<
+ is_convertible<Traversal,bidirectional_traversal_tag>
+ , mpl::identity<bidirectional_traversal_tag>
+ , mpl::eval_if<
+ is_convertible<Traversal,forward_traversal_tag>
+ , mpl::identity<forward_traversal_tag>
+ , mpl::eval_if<
+ is_convertible<Traversal,single_pass_traversal_tag>
+ , mpl::identity<single_pass_traversal_tag>
+ , mpl::eval_if<
+ is_convertible<Traversal,incrementable_traversal_tag>
+ , mpl::identity<incrementable_traversal_tag>
+ , void
+ >
+ >
+ >
+ >
+ >
+{
+};
+
+//
+// Trait to retrieve one of the iterator traversal tags from the iterator category or traversal.
+//
+template <class Iterator = mpl::_1>
+struct pure_iterator_traversal
+ : pure_traversal_tag<typename iterator_traversal<Iterator>::type>
+{};
+
+# ifdef BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT
+template <>
+struct pure_iterator_traversal<mpl::_1>
+{
+ template <class T>
+ struct apply : pure_iterator_traversal<T>
+ {};
+};
+template <>
+struct pure_iterator_traversal<mpl::_>
+ : pure_iterator_traversal<mpl::_1>
+{};
+# endif
+
+} // namespace iterators
+
+using iterators::no_traversal_tag;
+using iterators::incrementable_traversal_tag;
+using iterators::single_pass_traversal_tag;
+using iterators::forward_traversal_tag;
+using iterators::bidirectional_traversal_tag;
+using iterators::random_access_traversal_tag;
+using iterators::iterator_category_to_traversal;
+using iterators::iterator_traversal;
+
+// This import is needed for backward compatibility with Boost.Range:
+// boost/range/detail/demote_iterator_traversal_tag.hpp
+// It should be removed when that header is fixed.
+namespace detail {
+using iterators::pure_traversal_tag;
+} // namespace detail
+
+} // namespace boost
+
+#include <boost/iterator/detail/config_undef.hpp>
+
+#endif // BOOST_ITERATOR_CATEGORIES_HPP
diff --git a/third_party/boost/boost/iterator/iterator_facade.hpp b/third_party/boost/boost/iterator/iterator_facade.hpp
new file mode 100644
index 0000000..7b11d0a
--- /dev/null
+++ b/third_party/boost/boost/iterator/iterator_facade.hpp
@@ -0,0 +1,980 @@
+// (C) Copyright David Abrahams 2002.
+// (C) Copyright Jeremy Siek 2002.
+// (C) Copyright Thomas Witt 2002.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+#ifndef BOOST_ITERATOR_FACADE_23022003THW_HPP
+#define BOOST_ITERATOR_FACADE_23022003THW_HPP
+
+#include <boost/config.hpp>
+#include <boost/iterator.hpp>
+#include <boost/iterator/interoperable.hpp>
+#include <boost/iterator/iterator_traits.hpp>
+#include <boost/iterator/iterator_categories.hpp>
+
+#include <boost/iterator/detail/facade_iterator_category.hpp>
+#include <boost/iterator/detail/enable_if.hpp>
+
+#include <boost/static_assert.hpp>
+#include <boost/utility/addressof.hpp>
+
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/add_const.hpp>
+#include <boost/type_traits/add_pointer.hpp>
+#include <boost/type_traits/add_lvalue_reference.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/is_pod.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/not.hpp>
+#include <boost/mpl/always.hpp>
+#include <boost/mpl/apply.hpp>
+#include <boost/mpl/identity.hpp>
+
+#include <boost/iterator/detail/config_def.hpp> // this goes last
+
+namespace boost {
+namespace iterators {
+
+ // This forward declaration is required for the friend declaration
+ // in iterator_core_access
+ template <class I, class V, class TC, class R, class D> class iterator_facade;
+
+ namespace detail
+ {
+ // A binary metafunction class that always returns bool. VC6
+ // ICEs on mpl::always<bool>, probably because of the default
+ // parameters.
+ struct always_bool2
+ {
+ template <class T, class U>
+ struct apply
+ {
+ typedef bool type;
+ };
+ };
+
+ // The type trait checks if the category or traversal is at least as advanced as the specified required traversal
+ template< typename CategoryOrTraversal, typename Required >
+ struct is_traversal_at_least :
+ public boost::is_convertible< typename iterator_category_to_traversal< CategoryOrTraversal >::type, Required >
+ {};
+
+ //
+ // enable if for use in operator implementation.
+ //
+ template <
+ class Facade1
+ , class Facade2
+ , class Return
+ >
+ struct enable_if_interoperable :
+ public boost::iterators::enable_if<
+ is_interoperable< Facade1, Facade2 >
+ , Return
+ >
+ {};
+
+ //
+ // enable if for use in implementation of operators specific for random access traversal.
+ //
+ template <
+ class Facade1
+ , class Facade2
+ , class Return
+ >
+ struct enable_if_interoperable_and_random_access_traversal :
+ public boost::iterators::enable_if<
+ mpl::and_<
+ is_interoperable< Facade1, Facade2 >
+ , is_traversal_at_least< typename iterator_category< Facade1 >::type, random_access_traversal_tag >
+ , is_traversal_at_least< typename iterator_category< Facade2 >::type, random_access_traversal_tag >
+ >
+ , Return
+ >
+ {};
+
+ //
+ // Generates associated types for an iterator_facade with the
+ // given parameters.
+ //
+ template <
+ class ValueParam
+ , class CategoryOrTraversal
+ , class Reference
+ , class Difference
+ >
+ struct iterator_facade_types
+ {
+ typedef typename facade_iterator_category<
+ CategoryOrTraversal, ValueParam, Reference
+ >::type iterator_category;
+
+ typedef typename remove_const<ValueParam>::type value_type;
+
+ // Not the real associated pointer type
+ typedef typename mpl::eval_if<
+ boost::iterators::detail::iterator_writability_disabled<ValueParam,Reference>
+ , add_pointer<const value_type>
+ , add_pointer<value_type>
+ >::type pointer;
+
+# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
+ && (BOOST_WORKAROUND(_STLPORT_VERSION, BOOST_TESTED_AT(0x452)) \
+ || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, BOOST_TESTED_AT(310))) \
+ || BOOST_WORKAROUND(BOOST_RWSTD_VER, BOOST_TESTED_AT(0x20101)) \
+ || BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, <= 310)
+
+ // To interoperate with some broken library/compiler
+ // combinations, user-defined iterators must be derived from
+ // std::iterator. It is possible to implement a standard
+ // library for broken compilers without this limitation.
+# define BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE 1
+
+ typedef
+ iterator<iterator_category, value_type, Difference, pointer, Reference>
+ base;
+# endif
+ };
+
+ // iterators whose dereference operators reference the same value
+ // for all iterators into the same sequence (like many input
+ // iterators) need help with their postfix ++: the referenced
+ // value must be read and stored away before the increment occurs
+ // so that *a++ yields the originally referenced element and not
+ // the next one.
+ template <class Iterator>
+ class postfix_increment_proxy
+ {
+ typedef typename iterator_value<Iterator>::type value_type;
+ public:
+ explicit postfix_increment_proxy(Iterator const& x)
+ : stored_value(*x)
+ {}
+
+ // Returning a mutable reference allows nonsense like
+ // (*r++).mutate(), but it imposes fewer assumptions about the
+ // behavior of the value_type. In particular, recall that
+ // (*r).mutate() is legal if operator* returns by value.
+ value_type&
+ operator*() const
+ {
+ return this->stored_value;
+ }
+ private:
+ mutable value_type stored_value;
+ };
+
+ //
+ // In general, we can't determine that such an iterator isn't
+ // writable -- we also need to store a copy of the old iterator so
+ // that it can be written into.
+ template <class Iterator>
+ class writable_postfix_increment_proxy
+ {
+ typedef typename iterator_value<Iterator>::type value_type;
+ public:
+ explicit writable_postfix_increment_proxy(Iterator const& x)
+ : stored_value(*x)
+ , stored_iterator(x)
+ {}
+
+ // Dereferencing must return a proxy so that both *r++ = o and
+ // value_type(*r++) can work. In this case, *r is the same as
+ // *r++, and the conversion operator below is used to ensure
+ // readability.
+ writable_postfix_increment_proxy const&
+ operator*() const
+ {
+ return *this;
+ }
+
+ // Provides readability of *r++
+ operator value_type&() const
+ {
+ return stored_value;
+ }
+
+ // Provides writability of *r++
+ template <class T>
+ T const& operator=(T const& x) const
+ {
+ *this->stored_iterator = x;
+ return x;
+ }
+
+ // This overload just in case only non-const objects are writable
+ template <class T>
+ T& operator=(T& x) const
+ {
+ *this->stored_iterator = x;
+ return x;
+ }
+
+ // Provides X(r++)
+ operator Iterator const&() const
+ {
+ return stored_iterator;
+ }
+
+ private:
+ mutable value_type stored_value;
+ Iterator stored_iterator;
+ };
+
+# ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+
+ template <class Reference, class Value>
+ struct is_non_proxy_reference_impl
+ {
+ static Reference r;
+
+ template <class R>
+ static typename mpl::if_<
+ is_convertible<
+ R const volatile*
+ , Value const volatile*
+ >
+ , char[1]
+ , char[2]
+ >::type& helper(R const&);
+
+ BOOST_STATIC_CONSTANT(bool, value = sizeof(helper(r)) == 1);
+ };
+
+ template <class Reference, class Value>
+ struct is_non_proxy_reference
+ : mpl::bool_<
+ is_non_proxy_reference_impl<Reference, Value>::value
+ >
+ {};
+# else
+ template <class Reference, class Value>
+ struct is_non_proxy_reference
+ : is_convertible<
+ typename remove_reference<Reference>::type
+ const volatile*
+ , Value const volatile*
+ >
+ {};
+# endif
+
+ // A metafunction to choose the result type of postfix ++
+ //
+ // Because the C++98 input iterator requirements say that *r++ has
+ // type T (value_type), implementations of some standard
+ // algorithms like lexicographical_compare may use constructions
+ // like:
+ //
+ // *r++ < *s++
+ //
+ // If *r++ returns a proxy (as required if r is writable but not
+ // multipass), this sort of expression will fail unless the proxy
+ // supports the operator<. Since there are any number of such
+ // operations, we're not going to try to support them. Therefore,
+ // even if r++ returns a proxy, *r++ will only return a proxy if
+ // *r also returns a proxy.
+ template <class Iterator, class Value, class Reference, class CategoryOrTraversal>
+ struct postfix_increment_result
+ : mpl::eval_if<
+ mpl::and_<
+ // A proxy is only needed for readable iterators
+ is_convertible<
+ Reference
+ // Use add_lvalue_reference to form `reference to Value` due to
+ // some (strict) C++03 compilers (e.g. `gcc -std=c++03`) reject
+ // 'reference-to-reference' in the template which described in CWG
+ // DR106.
+ // http://www.open-std.org/Jtc1/sc22/wg21/docs/cwg_defects.html#106
+ , typename add_lvalue_reference<Value const>::type
+ >
+
+ // No multipass iterator can have values that disappear
+ // before positions can be re-visited
+ , mpl::not_<
+ is_convertible<
+ typename iterator_category_to_traversal<CategoryOrTraversal>::type
+ , forward_traversal_tag
+ >
+ >
+ >
+ , mpl::if_<
+ is_non_proxy_reference<Reference,Value>
+ , postfix_increment_proxy<Iterator>
+ , writable_postfix_increment_proxy<Iterator>
+ >
+ , mpl::identity<Iterator>
+ >
+ {};
+
+ // operator->() needs special support for input iterators to strictly meet the
+ // standard's requirements. If *i is not a reference type, we must still
+ // produce an lvalue to which a pointer can be formed. We do that by
+ // returning a proxy object containing an instance of the reference object.
+ template <class Reference, class Pointer>
+ struct operator_arrow_dispatch // proxy references
+ {
+ struct proxy
+ {
+ explicit proxy(Reference const & x) : m_ref(x) {}
+ Reference* operator->() { return boost::addressof(m_ref); }
+ // This function is needed for MWCW and BCC, which won't call
+ // operator-> again automatically per 13.3.1.2 para 8
+ operator Reference*() { return boost::addressof(m_ref); }
+ Reference m_ref;
+ };
+ typedef proxy result_type;
+ static result_type apply(Reference const & x)
+ {
+ return result_type(x);
+ }
+ };
+
+ template <class T, class Pointer>
+ struct operator_arrow_dispatch<T&, Pointer> // "real" references
+ {
+ typedef Pointer result_type;
+ static result_type apply(T& x)
+ {
+ return boost::addressof(x);
+ }
+ };
+
+ // A proxy return type for operator[], needed to deal with
+ // iterators that may invalidate referents upon destruction.
+ // Consider the temporary iterator in *(a + n)
+ template <class Iterator>
+ class operator_brackets_proxy
+ {
+ // Iterator is actually an iterator_facade, so we do not have to
+ // go through iterator_traits to access the traits.
+ typedef typename Iterator::reference reference;
+ typedef typename Iterator::value_type value_type;
+
+ public:
+ operator_brackets_proxy(Iterator const& iter)
+ : m_iter(iter)
+ {}
+
+ operator reference() const
+ {
+ return *m_iter;
+ }
+
+ operator_brackets_proxy& operator=(value_type const& val)
+ {
+ *m_iter = val;
+ return *this;
+ }
+
+ private:
+ Iterator m_iter;
+ };
+
+ // A metafunction that determines whether operator[] must return a
+ // proxy, or whether it can simply return a copy of the value_type.
+ template <class ValueType, class Reference>
+ struct use_operator_brackets_proxy
+ : mpl::not_<
+ mpl::and_<
+ // Really we want an is_copy_constructible trait here,
+ // but is_POD will have to suffice in the meantime.
+ boost::is_POD<ValueType>
+ , iterator_writability_disabled<ValueType,Reference>
+ >
+ >
+ {};
+
+ template <class Iterator, class Value, class Reference>
+ struct operator_brackets_result
+ {
+ typedef typename mpl::if_<
+ use_operator_brackets_proxy<Value,Reference>
+ , operator_brackets_proxy<Iterator>
+ , Value
+ >::type type;
+ };
+
+ template <class Iterator>
+ operator_brackets_proxy<Iterator> make_operator_brackets_result(Iterator const& iter, mpl::true_)
+ {
+ return operator_brackets_proxy<Iterator>(iter);
+ }
+
+ template <class Iterator>
+ typename Iterator::value_type make_operator_brackets_result(Iterator const& iter, mpl::false_)
+ {
+ return *iter;
+ }
+
+ struct choose_difference_type
+ {
+ template <class I1, class I2>
+ struct apply
+ :
+# ifdef BOOST_NO_ONE_WAY_ITERATOR_INTEROP
+ iterator_difference<I1>
+# else
+ mpl::eval_if<
+ is_convertible<I2,I1>
+ , iterator_difference<I1>
+ , iterator_difference<I2>
+ >
+# endif
+ {};
+
+ };
+
+ template <
+ class Derived
+ , class Value
+ , class CategoryOrTraversal
+ , class Reference
+ , class Difference
+ , bool IsBidirectionalTraversal
+ , bool IsRandomAccessTraversal
+ >
+ class iterator_facade_base;
+
+ } // namespace detail
+
+
+ // Macros which describe the declarations of binary operators
+# ifdef BOOST_NO_STRICT_ITERATOR_INTEROPERABILITY
+# define BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, enabler) \
+ template < \
+ class Derived1, class V1, class TC1, class Reference1, class Difference1 \
+ , class Derived2, class V2, class TC2, class Reference2, class Difference2 \
+ > \
+ prefix typename mpl::apply2<result_type,Derived1,Derived2>::type \
+ operator op( \
+ iterator_facade<Derived1, V1, TC1, Reference1, Difference1> const& lhs \
+ , iterator_facade<Derived2, V2, TC2, Reference2, Difference2> const& rhs)
+# else
+# define BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, enabler) \
+ template < \
+ class Derived1, class V1, class TC1, class Reference1, class Difference1 \
+ , class Derived2, class V2, class TC2, class Reference2, class Difference2 \
+ > \
+ prefix typename enabler< \
+ Derived1, Derived2 \
+ , typename mpl::apply2<result_type,Derived1,Derived2>::type \
+ >::type \
+ operator op( \
+ iterator_facade<Derived1, V1, TC1, Reference1, Difference1> const& lhs \
+ , iterator_facade<Derived2, V2, TC2, Reference2, Difference2> const& rhs)
+# endif
+
+# define BOOST_ITERATOR_FACADE_INTEROP_HEAD(prefix, op, result_type) \
+ BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, boost::iterators::detail::enable_if_interoperable)
+
+# define BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(prefix, op, result_type) \
+ BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL(prefix, op, result_type, boost::iterators::detail::enable_if_interoperable_and_random_access_traversal)
+
+# define BOOST_ITERATOR_FACADE_PLUS_HEAD(prefix,args) \
+ template <class Derived, class V, class TC, class R, class D> \
+ prefix typename boost::iterators::enable_if< \
+ boost::iterators::detail::is_traversal_at_least< TC, boost::iterators::random_access_traversal_tag >, \
+ Derived \
+ >::type operator+ args
+
+ //
+ // Helper class for granting access to the iterator core interface.
+ //
+ // The simple core interface is used by iterator_facade. The core
+ // interface of a user/library defined iterator type should not be made public
+ // so that it does not clutter the public interface. Instead iterator_core_access
+ // should be made friend so that iterator_facade can access the core
+ // interface through iterator_core_access.
+ //
+ class iterator_core_access
+ {
+# if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
+ // Tasteless as this may seem, making all members public allows member templates
+ // to work in the absence of member template friends.
+ public:
+# else
+
+ template <class I, class V, class TC, class R, class D> friend class iterator_facade;
+ template <class I, class V, class TC, class R, class D, bool IsBidirectionalTraversal, bool IsRandomAccessTraversal>
+ friend class detail::iterator_facade_base;
+
+# define BOOST_ITERATOR_FACADE_RELATION(op) \
+ BOOST_ITERATOR_FACADE_INTEROP_HEAD(friend,op, boost::iterators::detail::always_bool2);
+
+ BOOST_ITERATOR_FACADE_RELATION(==)
+ BOOST_ITERATOR_FACADE_RELATION(!=)
+
+# undef BOOST_ITERATOR_FACADE_RELATION
+
+# define BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(op) \
+ BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(friend,op, boost::iterators::detail::always_bool2);
+
+ BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<)
+ BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>)
+ BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<=)
+ BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>=)
+
+# undef BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION
+
+ BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(
+ friend, -, boost::iterators::detail::choose_difference_type)
+ ;
+
+ BOOST_ITERATOR_FACADE_PLUS_HEAD(
+ friend inline
+ , (iterator_facade<Derived, V, TC, R, D> const&
+ , typename Derived::difference_type)
+ )
+ ;
+
+ BOOST_ITERATOR_FACADE_PLUS_HEAD(
+ friend inline
+ , (typename Derived::difference_type
+ , iterator_facade<Derived, V, TC, R, D> const&)
+ )
+ ;
+
+# endif
+
+ template <class Facade>
+ static typename Facade::reference dereference(Facade const& f)
+ {
+ return f.dereference();
+ }
+
+ template <class Facade>
+ static void increment(Facade& f)
+ {
+ f.increment();
+ }
+
+ template <class Facade>
+ static void decrement(Facade& f)
+ {
+ f.decrement();
+ }
+
+ template <class Facade1, class Facade2>
+ static bool equal(Facade1 const& f1, Facade2 const& f2, mpl::true_)
+ {
+ return f1.equal(f2);
+ }
+
+ template <class Facade1, class Facade2>
+ static bool equal(Facade1 const& f1, Facade2 const& f2, mpl::false_)
+ {
+ return f2.equal(f1);
+ }
+
+ template <class Facade>
+ static void advance(Facade& f, typename Facade::difference_type n)
+ {
+ f.advance(n);
+ }
+
+ template <class Facade1, class Facade2>
+ static typename Facade1::difference_type distance_from(
+ Facade1 const& f1, Facade2 const& f2, mpl::true_)
+ {
+ return -f1.distance_to(f2);
+ }
+
+ template <class Facade1, class Facade2>
+ static typename Facade2::difference_type distance_from(
+ Facade1 const& f1, Facade2 const& f2, mpl::false_)
+ {
+ return f2.distance_to(f1);
+ }
+
+ //
+ // Curiously Recurring Template interface.
+ //
+ template <class I, class V, class TC, class R, class D>
+ static I& derived(iterator_facade<I,V,TC,R,D>& facade)
+ {
+ return *static_cast<I*>(&facade);
+ }
+
+ template <class I, class V, class TC, class R, class D>
+ static I const& derived(iterator_facade<I,V,TC,R,D> const& facade)
+ {
+ return *static_cast<I const*>(&facade);
+ }
+
+ // objects of this class are useless
+ BOOST_DELETED_FUNCTION(iterator_core_access())
+ };
+
+ namespace detail {
+
+ // Implementation for forward traversal iterators
+ template <
+ class Derived
+ , class Value
+ , class CategoryOrTraversal
+ , class Reference
+ , class Difference
+ >
+ class iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, false, false >
+# ifdef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE
+ : public boost::iterators::detail::iterator_facade_types<
+ Value, CategoryOrTraversal, Reference, Difference
+ >::base
+# undef BOOST_ITERATOR_FACADE_NEEDS_ITERATOR_BASE
+# endif
+ {
+ private:
+ typedef boost::iterators::detail::iterator_facade_types<
+ Value, CategoryOrTraversal, Reference, Difference
+ > associated_types;
+
+ typedef boost::iterators::detail::operator_arrow_dispatch<
+ Reference
+ , typename associated_types::pointer
+ > operator_arrow_dispatch_;
+
+ public:
+ typedef typename associated_types::value_type value_type;
+ typedef Reference reference;
+ typedef Difference difference_type;
+
+ typedef typename operator_arrow_dispatch_::result_type pointer;
+
+ typedef typename associated_types::iterator_category iterator_category;
+
+ public:
+ reference operator*() const
+ {
+ return iterator_core_access::dereference(this->derived());
+ }
+
+ pointer operator->() const
+ {
+ return operator_arrow_dispatch_::apply(*this->derived());
+ }
+
+ Derived& operator++()
+ {
+ iterator_core_access::increment(this->derived());
+ return this->derived();
+ }
+
+ protected:
+ //
+ // Curiously Recurring Template interface.
+ //
+ Derived& derived()
+ {
+ return *static_cast<Derived*>(this);
+ }
+
+ Derived const& derived() const
+ {
+ return *static_cast<Derived const*>(this);
+ }
+ };
+
+ // Implementation for bidirectional traversal iterators
+ template <
+ class Derived
+ , class Value
+ , class CategoryOrTraversal
+ , class Reference
+ , class Difference
+ >
+ class iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, false > :
+ public iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, false, false >
+ {
+ public:
+ Derived& operator--()
+ {
+ iterator_core_access::decrement(this->derived());
+ return this->derived();
+ }
+
+ Derived operator--(int)
+ {
+ Derived tmp(this->derived());
+ --*this;
+ return tmp;
+ }
+ };
+
+ // Implementation for random access traversal iterators
+ template <
+ class Derived
+ , class Value
+ , class CategoryOrTraversal
+ , class Reference
+ , class Difference
+ >
+ class iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, true > :
+ public iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, false >
+ {
+ private:
+ typedef iterator_facade_base< Derived, Value, CategoryOrTraversal, Reference, Difference, true, false > base_type;
+
+ public:
+ typedef typename base_type::reference reference;
+ typedef typename base_type::difference_type difference_type;
+
+ public:
+ typename boost::iterators::detail::operator_brackets_result<Derived, Value, reference>::type
+ operator[](difference_type n) const
+ {
+ typedef boost::iterators::detail::use_operator_brackets_proxy<Value, Reference> use_proxy;
+
+ return boost::iterators::detail::make_operator_brackets_result<Derived>(
+ this->derived() + n
+ , use_proxy()
+ );
+ }
+
+ Derived& operator+=(difference_type n)
+ {
+ iterator_core_access::advance(this->derived(), n);
+ return this->derived();
+ }
+
+ Derived& operator-=(difference_type n)
+ {
+ iterator_core_access::advance(this->derived(), -n);
+ return this->derived();
+ }
+
+ Derived operator-(difference_type x) const
+ {
+ Derived result(this->derived());
+ return result -= x;
+ }
+ };
+
+ } // namespace detail
+
+ //
+ // iterator_facade - use as a public base class for defining new
+ // standard-conforming iterators.
+ //
+ template <
+ class Derived // The derived iterator type being constructed
+ , class Value
+ , class CategoryOrTraversal
+ , class Reference = Value&
+ , class Difference = std::ptrdiff_t
+ >
+ class iterator_facade :
+ public detail::iterator_facade_base<
+ Derived,
+ Value,
+ CategoryOrTraversal,
+ Reference,
+ Difference,
+ detail::is_traversal_at_least< CategoryOrTraversal, bidirectional_traversal_tag >::value,
+ detail::is_traversal_at_least< CategoryOrTraversal, random_access_traversal_tag >::value
+ >
+ {
+ protected:
+ // For use by derived classes
+ typedef iterator_facade<Derived,Value,CategoryOrTraversal,Reference,Difference> iterator_facade_;
+ };
+
+ template <class I, class V, class TC, class R, class D>
+ inline typename boost::iterators::detail::postfix_increment_result<I,V,R,TC>::type
+ operator++(
+ iterator_facade<I,V,TC,R,D>& i
+ , int
+ )
+ {
+ typename boost::iterators::detail::postfix_increment_result<I,V,R,TC>::type
+ tmp(*static_cast<I*>(&i));
+
+ ++i;
+
+ return tmp;
+ }
+
+
+ //
+ // Comparison operator implementation. The library supplied operators
+ // enables the user to provide fully interoperable constant/mutable
+ // iterator types. I.e. the library provides all operators
+ // for all mutable/constant iterator combinations.
+ //
+ // Note though that this kind of interoperability for constant/mutable
+ // iterators is not required by the standard for container iterators.
+ // All the standard asks for is a conversion mutable -> constant.
+ // Most standard library implementations nowadays provide fully interoperable
+ // iterator implementations, but there are still heavily used implementations
+ // that do not provide them. (Actually it's even worse, they do not provide
+ // them for only a few iterators.)
+ //
+ // ?? Maybe a BOOST_ITERATOR_NO_FULL_INTEROPERABILITY macro should
+ // enable the user to turn off mixed type operators
+ //
+ // The library takes care to provide only the right operator overloads.
+ // I.e.
+ //
+ // bool operator==(Iterator, Iterator);
+ // bool operator==(ConstIterator, Iterator);
+ // bool operator==(Iterator, ConstIterator);
+ // bool operator==(ConstIterator, ConstIterator);
+ //
+ // ...
+ //
+ // In order to do so it uses c++ idioms that are not yet widely supported
+ // by current compiler releases. The library is designed to degrade gracefully
+ // in the face of compiler deficiencies. In general compiler
+ // deficiencies result in less strict error checking and more obscure
+ // error messages, functionality is not affected.
+ //
+ // For full operation compiler support for "Substitution Failure Is Not An Error"
+ // (aka. enable_if) and boost::is_convertible is required.
+ //
+ // The following problems occur if support is lacking.
+ //
+ // Pseudo code
+ //
+ // ---------------
+ // AdaptorA<Iterator1> a1;
+ // AdaptorA<Iterator2> a2;
+ //
+ // // This will result in a no such overload error in full operation
+ // // If enable_if or is_convertible is not supported
+ // // The instantiation will fail with an error hopefully indicating that
+ // // there is no operator== for Iterator1, Iterator2
+ // // The same will happen if no enable_if is used to remove
+ // // false overloads from the templated conversion constructor
+ // // of AdaptorA.
+ //
+ // a1 == a2;
+ // ----------------
+ //
+ // AdaptorA<Iterator> a;
+ // AdaptorB<Iterator> b;
+ //
+ // // This will result in a no such overload error in full operation
+ // // If enable_if is not supported the static assert used
+ // // in the operator implementation will fail.
+ // // This will accidently work if is_convertible is not supported.
+ //
+ // a == b;
+ // ----------------
+ //
+
+# ifdef BOOST_NO_ONE_WAY_ITERATOR_INTEROP
+# define BOOST_ITERATOR_CONVERTIBLE(a,b) mpl::true_()
+# else
+# define BOOST_ITERATOR_CONVERTIBLE(a,b) is_convertible<a,b>()
+# endif
+
+# define BOOST_ITERATOR_FACADE_INTEROP(op, result_type, return_prefix, base_op) \
+ BOOST_ITERATOR_FACADE_INTEROP_HEAD(inline, op, result_type) \
+ { \
+ /* For those compilers that do not support enable_if */ \
+ BOOST_STATIC_ASSERT(( \
+ is_interoperable< Derived1, Derived2 >::value \
+ )); \
+ return_prefix iterator_core_access::base_op( \
+ *static_cast<Derived1 const*>(&lhs) \
+ , *static_cast<Derived2 const*>(&rhs) \
+ , BOOST_ITERATOR_CONVERTIBLE(Derived2,Derived1) \
+ ); \
+ }
+
+# define BOOST_ITERATOR_FACADE_RELATION(op, return_prefix, base_op) \
+ BOOST_ITERATOR_FACADE_INTEROP( \
+ op \
+ , boost::iterators::detail::always_bool2 \
+ , return_prefix \
+ , base_op \
+ )
+
+ BOOST_ITERATOR_FACADE_RELATION(==, return, equal)
+ BOOST_ITERATOR_FACADE_RELATION(!=, return !, equal)
+
+# undef BOOST_ITERATOR_FACADE_RELATION
+
+
+# define BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS(op, result_type, return_prefix, base_op) \
+ BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD(inline, op, result_type) \
+ { \
+ /* For those compilers that do not support enable_if */ \
+ BOOST_STATIC_ASSERT(( \
+ is_interoperable< Derived1, Derived2 >::value && \
+ boost::iterators::detail::is_traversal_at_least< typename iterator_category< Derived1 >::type, random_access_traversal_tag >::value && \
+ boost::iterators::detail::is_traversal_at_least< typename iterator_category< Derived2 >::type, random_access_traversal_tag >::value \
+ )); \
+ return_prefix iterator_core_access::base_op( \
+ *static_cast<Derived1 const*>(&lhs) \
+ , *static_cast<Derived2 const*>(&rhs) \
+ , BOOST_ITERATOR_CONVERTIBLE(Derived2,Derived1) \
+ ); \
+ }
+
+# define BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(op, return_prefix, base_op) \
+ BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS( \
+ op \
+ , boost::iterators::detail::always_bool2 \
+ , return_prefix \
+ , base_op \
+ )
+
+ BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<, return 0 >, distance_from)
+ BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>, return 0 <, distance_from)
+ BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(<=, return 0 >=, distance_from)
+ BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION(>=, return 0 <=, distance_from)
+
+# undef BOOST_ITERATOR_FACADE_RANDOM_ACCESS_RELATION
+
+ // operator- requires an additional part in the static assertion
+ BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS(
+ -
+ , boost::iterators::detail::choose_difference_type
+ , return
+ , distance_from
+ )
+
+# undef BOOST_ITERATOR_FACADE_INTEROP
+# undef BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS
+
+# define BOOST_ITERATOR_FACADE_PLUS(args) \
+ BOOST_ITERATOR_FACADE_PLUS_HEAD(inline, args) \
+ { \
+ Derived tmp(static_cast<Derived const&>(i)); \
+ return tmp += n; \
+ }
+
+ BOOST_ITERATOR_FACADE_PLUS((
+ iterator_facade<Derived, V, TC, R, D> const& i
+ , typename Derived::difference_type n
+ ))
+
+ BOOST_ITERATOR_FACADE_PLUS((
+ typename Derived::difference_type n
+ , iterator_facade<Derived, V, TC, R, D> const& i
+ ))
+
+# undef BOOST_ITERATOR_FACADE_PLUS
+# undef BOOST_ITERATOR_FACADE_PLUS_HEAD
+
+# undef BOOST_ITERATOR_FACADE_INTEROP_HEAD
+# undef BOOST_ITERATOR_FACADE_INTEROP_RANDOM_ACCESS_HEAD
+# undef BOOST_ITERATOR_FACADE_INTEROP_HEAD_IMPL
+
+} // namespace iterators
+
+using iterators::iterator_core_access;
+using iterators::iterator_facade;
+
+} // namespace boost
+
+#include <boost/iterator/detail/config_undef.hpp>
+
+#endif // BOOST_ITERATOR_FACADE_23022003THW_HPP
diff --git a/third_party/boost/boost/iterator/iterator_traits.hpp b/third_party/boost/boost/iterator/iterator_traits.hpp
new file mode 100644
index 0000000..1a5f1e0
--- /dev/null
+++ b/third_party/boost/boost/iterator/iterator_traits.hpp
@@ -0,0 +1,60 @@
+// Copyright David Abrahams 2003.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+#ifndef ITERATOR_TRAITS_DWA200347_HPP
+# define ITERATOR_TRAITS_DWA200347_HPP
+
+# include <boost/detail/iterator.hpp>
+# include <boost/detail/workaround.hpp>
+
+namespace boost {
+namespace iterators {
+
+// Macro for supporting old compilers, no longer needed but kept
+// for backwards compatibility (it was documented).
+#define BOOST_ITERATOR_CATEGORY iterator_category
+
+
+template <class Iterator>
+struct iterator_value
+{
+ typedef typename boost::detail::iterator_traits<Iterator>::value_type type;
+};
+
+template <class Iterator>
+struct iterator_reference
+{
+ typedef typename boost::detail::iterator_traits<Iterator>::reference type;
+};
+
+
+template <class Iterator>
+struct iterator_pointer
+{
+ typedef typename boost::detail::iterator_traits<Iterator>::pointer type;
+};
+
+template <class Iterator>
+struct iterator_difference
+{
+ typedef typename boost::detail::iterator_traits<Iterator>::difference_type type;
+};
+
+template <class Iterator>
+struct iterator_category
+{
+ typedef typename boost::detail::iterator_traits<Iterator>::iterator_category type;
+};
+
+} // namespace iterators
+
+using iterators::iterator_value;
+using iterators::iterator_reference;
+using iterators::iterator_pointer;
+using iterators::iterator_difference;
+using iterators::iterator_category;
+
+} // namespace boost
+
+#endif // ITERATOR_TRAITS_DWA200347_HPP
diff --git a/third_party/boost/boost/iterator/reverse_iterator.hpp b/third_party/boost/boost/iterator/reverse_iterator.hpp
new file mode 100644
index 0000000..3bef39e
--- /dev/null
+++ b/third_party/boost/boost/iterator/reverse_iterator.hpp
@@ -0,0 +1,74 @@
+// (C) Copyright David Abrahams 2002.
+// (C) Copyright Jeremy Siek 2002.
+// (C) Copyright Thomas Witt 2002.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+#ifndef BOOST_REVERSE_ITERATOR_23022003THW_HPP
+#define BOOST_REVERSE_ITERATOR_23022003THW_HPP
+
+#include <boost/next_prior.hpp>
+#include <boost/iterator.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
+
+namespace boost {
+namespace iterators {
+
+ //
+ //
+ //
+ template <class Iterator>
+ class reverse_iterator
+ : public iterator_adaptor< reverse_iterator<Iterator>, Iterator >
+ {
+ typedef iterator_adaptor< reverse_iterator<Iterator>, Iterator > super_t;
+
+ friend class iterator_core_access;
+
+ public:
+ reverse_iterator() {}
+
+ explicit reverse_iterator(Iterator x)
+ : super_t(x) {}
+
+ template<class OtherIterator>
+ reverse_iterator(
+ reverse_iterator<OtherIterator> const& r
+ , typename enable_if_convertible<OtherIterator, Iterator>::type* = 0
+ )
+ : super_t(r.base())
+ {}
+
+ private:
+ typename super_t::reference dereference() const { return *boost::prior(this->base()); }
+
+ void increment() { --this->base_reference(); }
+ void decrement() { ++this->base_reference(); }
+
+ void advance(typename super_t::difference_type n)
+ {
+ this->base_reference() += -n;
+ }
+
+ template <class OtherIterator>
+ typename super_t::difference_type
+ distance_to(reverse_iterator<OtherIterator> const& y) const
+ {
+ return this->base_reference() - y.base();
+ }
+ };
+
+ template <class BidirectionalIterator>
+ inline reverse_iterator<BidirectionalIterator> make_reverse_iterator(BidirectionalIterator x)
+ {
+ return reverse_iterator<BidirectionalIterator>(x);
+ }
+
+} // namespace iterators
+
+using iterators::reverse_iterator;
+using iterators::make_reverse_iterator;
+
+} // namespace boost
+
+#endif // BOOST_REVERSE_ITERATOR_23022003THW_HPP
diff --git a/third_party/boost/boost/limits.hpp b/third_party/boost/boost/limits.hpp
new file mode 100644
index 0000000..d335de2
--- /dev/null
+++ b/third_party/boost/boost/limits.hpp
@@ -0,0 +1,145 @@
+
+// (C) Copyright John maddock 1999.
+// (C) David Abrahams 2002. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// use this header as a workaround for missing <limits>
+
+// See http://www.boost.org/libs/compatibility/index.html for documentation.
+
+#ifndef BOOST_LIMITS
+#define BOOST_LIMITS
+
+#include <boost/config.hpp>
+
+#ifdef BOOST_NO_LIMITS
+# error "There is no std::numeric_limits suppport available."
+#else
+# include <limits>
+#endif
+
+#if (defined(BOOST_HAS_LONG_LONG) && defined(BOOST_NO_LONG_LONG_NUMERIC_LIMITS)) \
+ || (defined(BOOST_HAS_MS_INT64) && defined(BOOST_NO_MS_INT64_NUMERIC_LIMITS))
+// Add missing specializations for numeric_limits:
+#ifdef BOOST_HAS_MS_INT64
+# define BOOST_LLT __int64
+# define BOOST_ULLT unsigned __int64
+#else
+# define BOOST_LLT ::boost::long_long_type
+# define BOOST_ULLT ::boost::ulong_long_type
+#endif
+
+#include <climits> // for CHAR_BIT
+
+namespace std
+{
+ template<>
+ class numeric_limits<BOOST_LLT>
+ {
+ public:
+
+ BOOST_STATIC_CONSTANT(bool, is_specialized = true);
+#ifdef BOOST_HAS_MS_INT64
+ static BOOST_LLT min BOOST_PREVENT_MACRO_SUBSTITUTION (){ return 0x8000000000000000i64; }
+ static BOOST_LLT max BOOST_PREVENT_MACRO_SUBSTITUTION (){ return 0x7FFFFFFFFFFFFFFFi64; }
+#elif defined(LLONG_MAX)
+ static BOOST_LLT min BOOST_PREVENT_MACRO_SUBSTITUTION (){ return LLONG_MIN; }
+ static BOOST_LLT max BOOST_PREVENT_MACRO_SUBSTITUTION (){ return LLONG_MAX; }
+#elif defined(LONGLONG_MAX)
+ static BOOST_LLT min BOOST_PREVENT_MACRO_SUBSTITUTION (){ return LONGLONG_MIN; }
+ static BOOST_LLT max BOOST_PREVENT_MACRO_SUBSTITUTION (){ return LONGLONG_MAX; }
+#else
+ static BOOST_LLT min BOOST_PREVENT_MACRO_SUBSTITUTION (){ return 1LL << (sizeof(BOOST_LLT) * CHAR_BIT - 1); }
+ static BOOST_LLT max BOOST_PREVENT_MACRO_SUBSTITUTION (){ return ~(min)(); }
+#endif
+ BOOST_STATIC_CONSTANT(int, digits = sizeof(BOOST_LLT) * CHAR_BIT -1);
+ BOOST_STATIC_CONSTANT(int, digits10 = (CHAR_BIT * sizeof (BOOST_LLT) - 1) * 301L / 1000);
+ BOOST_STATIC_CONSTANT(bool, is_signed = true);
+ BOOST_STATIC_CONSTANT(bool, is_integer = true);
+ BOOST_STATIC_CONSTANT(bool, is_exact = true);
+ BOOST_STATIC_CONSTANT(int, radix = 2);
+ static BOOST_LLT epsilon() throw() { return 0; };
+ static BOOST_LLT round_error() throw() { return 0; };
+
+ BOOST_STATIC_CONSTANT(int, min_exponent = 0);
+ BOOST_STATIC_CONSTANT(int, min_exponent10 = 0);
+ BOOST_STATIC_CONSTANT(int, max_exponent = 0);
+ BOOST_STATIC_CONSTANT(int, max_exponent10 = 0);
+
+ BOOST_STATIC_CONSTANT(bool, has_infinity = false);
+ BOOST_STATIC_CONSTANT(bool, has_quiet_NaN = false);
+ BOOST_STATIC_CONSTANT(bool, has_signaling_NaN = false);
+ BOOST_STATIC_CONSTANT(bool, has_denorm = false);
+ BOOST_STATIC_CONSTANT(bool, has_denorm_loss = false);
+ static BOOST_LLT infinity() throw() { return 0; };
+ static BOOST_LLT quiet_NaN() throw() { return 0; };
+ static BOOST_LLT signaling_NaN() throw() { return 0; };
+ static BOOST_LLT denorm_min() throw() { return 0; };
+
+ BOOST_STATIC_CONSTANT(bool, is_iec559 = false);
+ BOOST_STATIC_CONSTANT(bool, is_bounded = true);
+ BOOST_STATIC_CONSTANT(bool, is_modulo = true);
+
+ BOOST_STATIC_CONSTANT(bool, traps = false);
+ BOOST_STATIC_CONSTANT(bool, tinyness_before = false);
+ BOOST_STATIC_CONSTANT(float_round_style, round_style = round_toward_zero);
+
+ };
+
+ template<>
+ class numeric_limits<BOOST_ULLT>
+ {
+ public:
+
+ BOOST_STATIC_CONSTANT(bool, is_specialized = true);
+#ifdef BOOST_HAS_MS_INT64
+ static BOOST_ULLT min BOOST_PREVENT_MACRO_SUBSTITUTION (){ return 0ui64; }
+ static BOOST_ULLT max BOOST_PREVENT_MACRO_SUBSTITUTION (){ return 0xFFFFFFFFFFFFFFFFui64; }
+#elif defined(ULLONG_MAX) && defined(ULLONG_MIN)
+ static BOOST_ULLT min BOOST_PREVENT_MACRO_SUBSTITUTION (){ return ULLONG_MIN; }
+ static BOOST_ULLT max BOOST_PREVENT_MACRO_SUBSTITUTION (){ return ULLONG_MAX; }
+#elif defined(ULONGLONG_MAX) && defined(ULONGLONG_MIN)
+ static BOOST_ULLT min BOOST_PREVENT_MACRO_SUBSTITUTION (){ return ULONGLONG_MIN; }
+ static BOOST_ULLT max BOOST_PREVENT_MACRO_SUBSTITUTION (){ return ULONGLONG_MAX; }
+#else
+ static BOOST_ULLT min BOOST_PREVENT_MACRO_SUBSTITUTION (){ return 0uLL; }
+ static BOOST_ULLT max BOOST_PREVENT_MACRO_SUBSTITUTION (){ return ~0uLL; }
+#endif
+ BOOST_STATIC_CONSTANT(int, digits = sizeof(BOOST_LLT) * CHAR_BIT);
+ BOOST_STATIC_CONSTANT(int, digits10 = (CHAR_BIT * sizeof (BOOST_LLT)) * 301L / 1000);
+ BOOST_STATIC_CONSTANT(bool, is_signed = false);
+ BOOST_STATIC_CONSTANT(bool, is_integer = true);
+ BOOST_STATIC_CONSTANT(bool, is_exact = true);
+ BOOST_STATIC_CONSTANT(int, radix = 2);
+ static BOOST_ULLT epsilon() throw() { return 0; };
+ static BOOST_ULLT round_error() throw() { return 0; };
+
+ BOOST_STATIC_CONSTANT(int, min_exponent = 0);
+ BOOST_STATIC_CONSTANT(int, min_exponent10 = 0);
+ BOOST_STATIC_CONSTANT(int, max_exponent = 0);
+ BOOST_STATIC_CONSTANT(int, max_exponent10 = 0);
+
+ BOOST_STATIC_CONSTANT(bool, has_infinity = false);
+ BOOST_STATIC_CONSTANT(bool, has_quiet_NaN = false);
+ BOOST_STATIC_CONSTANT(bool, has_signaling_NaN = false);
+ BOOST_STATIC_CONSTANT(bool, has_denorm = false);
+ BOOST_STATIC_CONSTANT(bool, has_denorm_loss = false);
+ static BOOST_ULLT infinity() throw() { return 0; };
+ static BOOST_ULLT quiet_NaN() throw() { return 0; };
+ static BOOST_ULLT signaling_NaN() throw() { return 0; };
+ static BOOST_ULLT denorm_min() throw() { return 0; };
+
+ BOOST_STATIC_CONSTANT(bool, is_iec559 = false);
+ BOOST_STATIC_CONSTANT(bool, is_bounded = true);
+ BOOST_STATIC_CONSTANT(bool, is_modulo = true);
+
+ BOOST_STATIC_CONSTANT(bool, traps = false);
+ BOOST_STATIC_CONSTANT(bool, tinyness_before = false);
+ BOOST_STATIC_CONSTANT(float_round_style, round_style = round_toward_zero);
+
+ };
+}
+#endif
+
+#endif
diff --git a/third_party/boost/boost/math/common_factor_ct.hpp b/third_party/boost/boost/math/common_factor_ct.hpp
new file mode 100644
index 0000000..173e797
--- /dev/null
+++ b/third_party/boost/boost/math/common_factor_ct.hpp
@@ -0,0 +1,97 @@
+// Boost common_factor_ct.hpp header file ----------------------------------//
+
+// (C) Copyright Daryle Walker and Stephen Cleary 2001-2002.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org for updates, documentation, and revision history.
+
+#ifndef BOOST_MATH_COMMON_FACTOR_CT_HPP
+#define BOOST_MATH_COMMON_FACTOR_CT_HPP
+
+#include <boost/math_fwd.hpp> // self include
+#include <boost/config.hpp> // for BOOST_STATIC_CONSTANT, etc.
+#include <boost/mpl/integral_c.hpp>
+
+namespace boost
+{
+namespace math
+{
+
+// Implementation details --------------------------------------------------//
+
+namespace detail
+{
+ // Build GCD with Euclid's recursive algorithm
+ template < static_gcd_type Value1, static_gcd_type Value2 >
+ struct static_gcd_helper_t
+ {
+ private:
+ BOOST_STATIC_CONSTANT( static_gcd_type, new_value1 = Value2 );
+ BOOST_STATIC_CONSTANT( static_gcd_type, new_value2 = Value1 % Value2 );
+
+ #ifndef __BORLANDC__
+ #define BOOST_DETAIL_GCD_HELPER_VAL(Value) static_cast<static_gcd_type>(Value)
+ #else
+ typedef static_gcd_helper_t self_type;
+ #define BOOST_DETAIL_GCD_HELPER_VAL(Value) (self_type:: Value )
+ #endif
+
+ typedef static_gcd_helper_t< BOOST_DETAIL_GCD_HELPER_VAL(new_value1),
+ BOOST_DETAIL_GCD_HELPER_VAL(new_value2) > next_step_type;
+
+ #undef BOOST_DETAIL_GCD_HELPER_VAL
+
+ public:
+ BOOST_STATIC_CONSTANT( static_gcd_type, value = next_step_type::value );
+ };
+
+ // Non-recursive case
+ template < static_gcd_type Value1 >
+ struct static_gcd_helper_t< Value1, 0UL >
+ {
+ BOOST_STATIC_CONSTANT( static_gcd_type, value = Value1 );
+ };
+
+ // Build the LCM from the GCD
+ template < static_gcd_type Value1, static_gcd_type Value2 >
+ struct static_lcm_helper_t
+ {
+ typedef static_gcd_helper_t<Value1, Value2> gcd_type;
+
+ BOOST_STATIC_CONSTANT( static_gcd_type, value = Value1 / gcd_type::value
+ * Value2 );
+ };
+
+ // Special case for zero-GCD values
+ template < >
+ struct static_lcm_helper_t< 0UL, 0UL >
+ {
+ BOOST_STATIC_CONSTANT( static_gcd_type, value = 0UL );
+ };
+
+} // namespace detail
+
+
+// Compile-time greatest common divisor evaluator class declaration --------//
+
+template < static_gcd_type Value1, static_gcd_type Value2 >
+struct static_gcd : public mpl::integral_c<static_gcd_type, (detail::static_gcd_helper_t<Value1, Value2>::value) >
+{
+}; // boost::math::static_gcd
+
+
+// Compile-time least common multiple evaluator class declaration ----------//
+
+template < static_gcd_type Value1, static_gcd_type Value2 >
+struct static_lcm : public mpl::integral_c<static_gcd_type, (detail::static_lcm_helper_t<Value1, Value2>::value) >
+{
+}; // boost::math::static_lcm
+
+
+} // namespace math
+} // namespace boost
+
+
+#endif // BOOST_MATH_COMMON_FACTOR_CT_HPP
diff --git a/third_party/boost/boost/math_fwd.hpp b/third_party/boost/boost/math_fwd.hpp
new file mode 100644
index 0000000..f9b7915
--- /dev/null
+++ b/third_party/boost/boost/math_fwd.hpp
@@ -0,0 +1,108 @@
+// Boost math_fwd.hpp header file ------------------------------------------//
+
+// (C) Copyright Hubert Holin and Daryle Walker 2001-2002. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/math for documentation.
+
+#ifndef BOOST_MATH_FWD_HPP
+#define BOOST_MATH_FWD_HPP
+
+#include <boost/cstdint.hpp>
+
+namespace boost
+{
+namespace math
+{
+
+
+// From <boost/math/quaternion.hpp> ----------------------------------------//
+
+template < typename T >
+ class quaternion;
+
+template < >
+ class quaternion< float >;
+template < >
+ class quaternion< double >;
+template < >
+ class quaternion< long double >;
+
+// Also has many function templates (including operators)
+
+
+// From <boost/math/octonion.hpp> ------------------------------------------//
+
+template < typename T >
+ class octonion;
+
+template < >
+ class octonion< float >;
+template < >
+ class octonion< double >;
+template < >
+ class octonion< long double >;
+
+// Also has many function templates (including operators)
+
+
+// From <boost/math/special_functions/acosh.hpp> ---------------------------//
+
+// Only has function template
+
+
+// From <boost/math/special_functions/asinh.hpp> ---------------------------//
+
+// Only has function template
+
+
+// From <boost/math/special_functions/atanh.hpp> ---------------------------//
+
+// Only has function template
+
+
+// From <boost/math/special_functions/sinc.hpp> ----------------------------//
+
+// Only has function templates
+
+
+// From <boost/math/special_functions/sinhc.hpp> ---------------------------//
+
+// Only has function templates
+
+
+// From <boost/math/common_factor.hpp> -------------------------------------//
+
+// Only #includes other headers
+
+
+// From <boost/math/common_factor_ct.hpp> ----------------------------------//
+
+#ifdef BOOST_NO_INTEGRAL_INT64_T
+ typedef unsigned long static_gcd_type;
+#else
+ typedef boost::uintmax_t static_gcd_type;
+#endif
+
+template < static_gcd_type Value1, static_gcd_type Value2 >
+ struct static_gcd;
+template < static_gcd_type Value1, static_gcd_type Value2 >
+ struct static_lcm;
+
+
+// From <boost/math/common_factor_rt.hpp> ----------------------------------//
+
+template < typename IntegerType >
+ class gcd_evaluator;
+template < typename IntegerType >
+ class lcm_evaluator;
+
+// Also has a couple of function templates
+
+
+} // namespace math
+} // namespace boost
+
+
+#endif // BOOST_MATH_FWD_HPP
diff --git a/third_party/boost/boost/mem_fn.hpp b/third_party/boost/boost/mem_fn.hpp
new file mode 100644
index 0000000..3bcd2c5
--- /dev/null
+++ b/third_party/boost/boost/mem_fn.hpp
@@ -0,0 +1,24 @@
+#ifndef BOOST_MEM_FN_HPP_INCLUDED
+#define BOOST_MEM_FN_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// mem_fn.hpp - a generalization of std::mem_fun[_ref]
+//
+// Copyright (c) 2009 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+// See http://www.boost.org/libs/bind/mem_fn.html for documentation.
+//
+
+#include <boost/bind/mem_fn.hpp>
+
+#endif // #ifndef BOOST_MEM_FN_HPP_INCLUDED
diff --git a/third_party/boost/boost/move/adl_move_swap.hpp b/third_party/boost/boost/move/adl_move_swap.hpp
new file mode 100644
index 0000000..fcd5f19
--- /dev/null
+++ b/third_party/boost/boost/move/adl_move_swap.hpp
@@ -0,0 +1,233 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright 2007, 2008 Steven Watanabe, Joseph Gauterin, Niels Dekker
+// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_MOVE_ADL_MOVE_SWAP_HPP
+#define BOOST_MOVE_ADL_MOVE_SWAP_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+//Based on Boost.Core's swap.
+//Many thanks to Steven Watanabe, Joseph Gauterin and Niels Dekker.
+
+#include <boost/config.hpp>
+#include <cstddef> //for std::size_t
+
+//Try to avoid including <algorithm>, as it's quite big
+#if defined(_MSC_VER) && defined(BOOST_DINKUMWARE_STDLIB)
+ #include <utility> //Dinkum libraries define std::swap in utility which is lighter than algorithm
+#elif defined(BOOST_GNU_STDLIB)
+ //For non-GCC compilers, where GNUC version is not very reliable, or old GCC versions
+ //use the good old stl_algobase header, which is quite lightweight
+ #if !defined(BOOST_GCC) || ((__GNUC__ < 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ < 3)))
+ #include <bits/stl_algobase.h>
+ #elif (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
+ //In GCC 4.3 a tiny stl_move.h was created with swap and move utilities
+ #include <bits/stl_move.h>
+ #else
+ //In GCC 4.4 stl_move.h was renamed to move.h
+ #include <bits/move.h>
+ #endif
+#elif defined(_LIBCPP_VERSION)
+ #include <type_traits> //The initial import of libc++ defines std::swap and still there
+#elif __cplusplus >= 201103L
+ #include <utility> //Fallback for C++ >= 2011
+#else
+ #include <algorithm> //Fallback for C++98/03
+#endif
+
+#include <boost/move/utility_core.hpp> //for boost::move
+
+#if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+namespace boost_move_member_swap {
+
+struct dont_care
+{
+ dont_care(...);
+};
+
+struct private_type
+{
+ static private_type p;
+ private_type const &operator,(int) const;
+};
+
+typedef char yes_type;
+struct no_type{ char dummy[2]; };
+
+template<typename T>
+no_type is_private_type(T const &);
+
+yes_type is_private_type(private_type const &);
+
+template <typename Type>
+class has_member_function_named_swap
+{
+ struct BaseMixin
+ {
+ void swap();
+ };
+
+ struct Base : public Type, public BaseMixin { Base(); };
+ template <typename T, T t> class Helper{};
+
+ template <typename U>
+ static no_type deduce(U*, Helper<void (BaseMixin::*)(), &U::swap>* = 0);
+ static yes_type deduce(...);
+
+ public:
+ static const bool value = sizeof(yes_type) == sizeof(deduce((Base*)(0)));
+};
+
+template<typename Fun, bool HasFunc>
+struct has_member_swap_impl
+{
+ static const bool value = false;
+};
+
+template<typename Fun>
+struct has_member_swap_impl<Fun, true>
+{
+ struct FunWrap : Fun
+ {
+ FunWrap();
+
+ using Fun::swap;
+ private_type swap(dont_care) const;
+ };
+
+ static Fun &declval_fun();
+ static FunWrap declval_wrap();
+
+ static bool const value =
+ sizeof(no_type) == sizeof(is_private_type( (declval_wrap().swap(declval_fun()), 0)) );
+};
+
+template<typename Fun>
+struct has_member_swap : public has_member_swap_impl
+ <Fun, has_member_function_named_swap<Fun>::value>
+{};
+
+} //namespace boost_move_member_swap
+
+namespace boost_move_adl_swap{
+
+template<class P1, class P2, bool = P1::value>
+struct and_op_impl
+{ static const bool value = false; };
+
+template<class P1, class P2>
+struct and_op_impl<P1, P2, true>
+{ static const bool value = P2::value; };
+
+template<class P1, class P2>
+struct and_op
+ : and_op_impl<P1, P2>
+{};
+
+//////
+
+template<class P1, class P2, bool = P1::value>
+struct and_op_not_impl
+{ static const bool value = false; };
+
+template<class P1, class P2>
+struct and_op_not_impl<P1, P2, true>
+{ static const bool value = !P2::value; };
+
+template<class P1, class P2>
+struct and_op_not
+ : and_op_not_impl<P1, P2>
+{};
+
+template<class T>
+void swap_proxy(T& x, T& y, typename boost::move_detail::enable_if_c<!boost::move_detail::has_move_emulation_enabled_impl<T>::value>::type* = 0)
+{
+ //use std::swap if argument dependent lookup fails
+ //Use using directive ("using namespace xxx;") instead as some older compilers
+ //don't do ADL with using declarations ("using ns::func;").
+ using namespace std;
+ swap(x, y);
+}
+
+template<class T>
+void swap_proxy(T& x, T& y
+ , typename boost::move_detail::enable_if< and_op_not_impl<boost::move_detail::has_move_emulation_enabled_impl<T>
+ , boost_move_member_swap::has_member_swap<T> >
+ >::type* = 0)
+{ T t(::boost::move(x)); x = ::boost::move(y); y = ::boost::move(t); }
+
+template<class T>
+void swap_proxy(T& x, T& y
+ , typename boost::move_detail::enable_if< and_op_impl< boost::move_detail::has_move_emulation_enabled_impl<T>
+ , boost_move_member_swap::has_member_swap<T> >
+ >::type* = 0)
+{ x.swap(y); }
+
+} //namespace boost_move_adl_swap{
+
+#else
+
+namespace boost_move_adl_swap{
+
+template<class T>
+void swap_proxy(T& x, T& y)
+{
+ using std::swap;
+ swap(x, y);
+}
+
+} //namespace boost_move_adl_swap{
+
+#endif //#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+namespace boost_move_adl_swap{
+
+template<class T, std::size_t N>
+void swap_proxy(T (& x)[N], T (& y)[N])
+{
+ for (std::size_t i = 0; i < N; ++i){
+ ::boost_move_adl_swap::swap_proxy(x[i], y[i]);
+ }
+}
+
+} //namespace boost_move_adl_swap {
+
+#endif //!defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+namespace boost{
+
+//! Exchanges the values of a and b, using Argument Dependent Lookup (ADL) to select a
+//! specialized swap function if available. If no specialized swap function is available,
+//! std::swap is used.
+//!
+//! <b>Exception</b>: If T uses Boost.Move's move emulation and the compiler has
+//! no rvalue references then:
+//!
+//! - If T has a <code>T::swap(T&)</code> member, that member is called.
+//! - Otherwise a move-based swap is called, equivalent to:
+//! <code>T t(::boost::move(x)); x = ::boost::move(y); y = ::boost::move(t);</code>.
+template<class T>
+void adl_move_swap(T& x, T& y)
+{
+ ::boost_move_adl_swap::swap_proxy(x, y);
+}
+
+} //namespace boost{
+
+#endif //#ifndef BOOST_MOVE_ADL_MOVE_SWAP_HPP
diff --git a/third_party/boost/boost/move/algorithm.hpp b/third_party/boost/boost/move/algorithm.hpp
new file mode 100644
index 0000000..fbda0f4
--- /dev/null
+++ b/third_party/boost/boost/move/algorithm.hpp
@@ -0,0 +1,282 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+
+#ifndef BOOST_MOVE_ALGORITHM_HPP
+#define BOOST_MOVE_ALGORITHM_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+
+#include <boost/move/utility_core.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/detail/no_exceptions_support.hpp>
+
+#include <algorithm> //copy, copy_backward
+#include <memory> //uninitialized_copy
+
+namespace boost {
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// move
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#if !defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
+
+ //! <b>Effects</b>: Moves elements in the range [first,last) into the range [result,result + (last -
+ //! first)) starting from first and proceeding to last. For each non-negative integer n < (last-first),
+ //! performs *(result + n) = ::boost::move (*(first + n)).
+ //!
+ //! <b>Effects</b>: result + (last - first).
+ //!
+ //! <b>Requires</b>: result shall not be in the range [first,last).
+ //!
+ //! <b>Complexity</b>: Exactly last - first move assignments.
+ template <typename I, // I models InputIterator
+ typename O> // O models OutputIterator
+ O move(I f, I l, O result)
+ {
+ while (f != l) {
+ *result = ::boost::move(*f);
+ ++f; ++result;
+ }
+ return result;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // move_backward
+ //
+ //////////////////////////////////////////////////////////////////////////////
+
+ //! <b>Effects</b>: Moves elements in the range [first,last) into the range
+ //! [result - (last-first),result) starting from last - 1 and proceeding to
+ //! first. For each positive integer n <= (last - first),
+ //! performs *(result - n) = ::boost::move(*(last - n)).
+ //!
+ //! <b>Requires</b>: result shall not be in the range [first,last).
+ //!
+ //! <b>Returns</b>: result - (last - first).
+ //!
+ //! <b>Complexity</b>: Exactly last - first assignments.
+ template <typename I, // I models BidirectionalIterator
+ typename O> // O models BidirectionalIterator
+ O move_backward(I f, I l, O result)
+ {
+ while (f != l) {
+ --l; --result;
+ *result = ::boost::move(*l);
+ }
+ return result;
+ }
+
+#else
+
+ using ::std::move_backward;
+
+#endif //!defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// uninitialized_move
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! <b>Effects</b>:
+//! \code
+//! for (; first != last; ++result, ++first)
+//! new (static_cast<void*>(&*result))
+//! typename iterator_traits<ForwardIterator>::value_type(boost::move(*first));
+//! \endcode
+//!
+//! <b>Returns</b>: result
+template
+ <typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+F uninitialized_move(I f, I l, F r
+ /// @cond
+// ,typename ::boost::move_detail::enable_if<has_move_emulation_enabled<typename std::iterator_traits<I>::value_type> >::type* = 0
+ /// @endcond
+ )
+{
+ typedef typename std::iterator_traits<I>::value_type input_value_type;
+
+ F back = r;
+ BOOST_TRY{
+ while (f != l) {
+ void * const addr = static_cast<void*>(::boost::move_detail::addressof(*r));
+ ::new(addr) input_value_type(::boost::move(*f));
+ ++f; ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ back->~input_value_type();
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return r;
+}
+
+/// @cond
+/*
+template
+ <typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+F uninitialized_move(I f, I l, F r,
+ typename ::boost::move_detail::disable_if<has_move_emulation_enabled<typename std::iterator_traits<I>::value_type> >::type* = 0)
+{
+ return std::uninitialized_copy(f, l, r);
+}
+*/
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// uninitialized_copy_or_move
+//
+//////////////////////////////////////////////////////////////////////////////
+
+namespace move_detail {
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline F uninitialized_move_move_iterator(I f, I l, F r
+// ,typename ::boost::move_detail::enable_if< has_move_emulation_enabled<typename I::value_type> >::type* = 0
+)
+{
+ return ::boost::uninitialized_move(f, l, r);
+}
+/*
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+F uninitialized_move_move_iterator(I f, I l, F r,
+ typename ::boost::move_detail::disable_if< has_move_emulation_enabled<typename I::value_type> >::type* = 0)
+{
+ return std::uninitialized_copy(f.base(), l.base(), r);
+}
+*/
+} //namespace move_detail {
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline F uninitialized_copy_or_move(I f, I l, F r,
+ typename ::boost::move_detail::enable_if< move_detail::is_move_iterator<I> >::type* = 0)
+{
+ return ::boost::move_detail::uninitialized_move_move_iterator(f, l, r);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// copy_or_move
+//
+//////////////////////////////////////////////////////////////////////////////
+
+namespace move_detail {
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline F move_move_iterator(I f, I l, F r
+// ,typename ::boost::move_detail::enable_if< has_move_emulation_enabled<typename I::value_type> >::type* = 0
+)
+{
+ return ::boost::move(f, l, r);
+}
+/*
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+F move_move_iterator(I f, I l, F r,
+ typename ::boost::move_detail::disable_if< has_move_emulation_enabled<typename I::value_type> >::type* = 0)
+{
+ return std::copy(f.base(), l.base(), r);
+}
+*/
+
+} //namespace move_detail {
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline F copy_or_move(I f, I l, F r,
+ typename ::boost::move_detail::enable_if< move_detail::is_move_iterator<I> >::type* = 0)
+{
+ return ::boost::move_detail::move_move_iterator(f, l, r);
+}
+
+/// @endcond
+
+//! <b>Effects</b>:
+//! \code
+//! for (; first != last; ++result, ++first)
+//! new (static_cast<void*>(&*result))
+//! typename iterator_traits<ForwardIterator>::value_type(*first);
+//! \endcode
+//!
+//! <b>Returns</b>: result
+//!
+//! <b>Note</b>: This function is provided because
+//! <i>std::uninitialized_copy</i> from some STL implementations
+//! is not compatible with <i>move_iterator</i>
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline F uninitialized_copy_or_move(I f, I l, F r
+ /// @cond
+ ,typename ::boost::move_detail::disable_if< move_detail::is_move_iterator<I> >::type* = 0
+ /// @endcond
+ )
+{
+ return std::uninitialized_copy(f, l, r);
+}
+
+//! <b>Effects</b>:
+//! \code
+//! for (; first != last; ++result, ++first)
+//! *result = *first;
+//! \endcode
+//!
+//! <b>Returns</b>: result
+//!
+//! <b>Note</b>: This function is provided because
+//! <i>std::uninitialized_copy</i> from some STL implementations
+//! is not compatible with <i>move_iterator</i>
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline F copy_or_move(I f, I l, F r
+ /// @cond
+ ,typename ::boost::move_detail::disable_if< move_detail::is_move_iterator<I> >::type* = 0
+ /// @endcond
+ )
+{
+ return std::copy(f, l, r);
+}
+
+} //namespace boost {
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_ALGORITHM_HPP
diff --git a/third_party/boost/boost/move/core.hpp b/third_party/boost/boost/move/core.hpp
new file mode 100644
index 0000000..54aece0
--- /dev/null
+++ b/third_party/boost/boost/move/core.hpp
@@ -0,0 +1,501 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+//! This header implements macros to define movable classes and
+//! move-aware functions
+
+#ifndef BOOST_MOVE_CORE_HPP
+#define BOOST_MOVE_CORE_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/workaround.hpp>
+
+// @cond
+
+//boost_move_no_copy_constructor_or_assign typedef
+//used to detect noncopyable types for other Boost libraries.
+#if defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ #define BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE) \
+ private:\
+ TYPE(TYPE &);\
+ TYPE& operator=(TYPE &);\
+ public:\
+ typedef int boost_move_no_copy_constructor_or_assign; \
+ private:\
+ //
+#else
+ #define BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE) \
+ public:\
+ TYPE(TYPE const &) = delete;\
+ TYPE& operator=(TYPE const &) = delete;\
+ public:\
+ typedef int boost_move_no_copy_constructor_or_assign; \
+ private:\
+ //
+#endif //BOOST_NO_CXX11_DELETED_FUNCTIONS
+
+// @endcond
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+ #include <boost/move/detail/type_traits.hpp>
+
+ #if defined(BOOST_MOVE_ADDRESS_SANITIZER_ON)
+ #define BOOST_MOVE_TO_RV_CAST(RV_TYPE, ARG) reinterpret_cast<RV_TYPE>(ARG)
+ #else
+ #define BOOST_MOVE_TO_RV_CAST(RV_TYPE, ARG) static_cast<RV_TYPE>(ARG)
+ #endif
+
+ //Move emulation rv breaks standard aliasing rules so add workarounds for some compilers
+ #if defined(__GNUC__) && (__GNUC__ >= 4) && \
+ (\
+ defined(BOOST_GCC) || \
+ (defined(BOOST_INTEL) && (BOOST_INTEL_CXX_VERSION >= 1300)) \
+ )
+ #define BOOST_MOVE_ATTRIBUTE_MAY_ALIAS __attribute__((__may_alias__))
+ #else
+ #define BOOST_MOVE_ATTRIBUTE_MAY_ALIAS
+ #endif
+
+ namespace boost {
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // struct rv
+ //
+ //////////////////////////////////////////////////////////////////////////////
+ template <class T>
+ class rv
+ : public ::boost::move_detail::if_c
+ < ::boost::move_detail::is_class<T>::value
+ , T
+ , ::boost::move_detail::nat
+ >::type
+ {
+ rv();
+ ~rv() throw();
+ rv(rv const&);
+ void operator=(rv const&);
+ } BOOST_MOVE_ATTRIBUTE_MAY_ALIAS;
+
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // is_rv
+ //
+ //////////////////////////////////////////////////////////////////////////////
+
+ namespace move_detail {
+
+ template <class T>
+ struct is_rv
+ //Derive from integral constant because some Boost code assummes it has
+ //a "type" internal typedef
+ : integral_constant<bool, ::boost::move_detail::is_rv_impl<T>::value >
+ {};
+
+ template <class T>
+ struct is_not_rv
+ {
+ static const bool value = !is_rv<T>::value;
+ };
+
+ } //namespace move_detail {
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // has_move_emulation_enabled
+ //
+ //////////////////////////////////////////////////////////////////////////////
+ template<class T>
+ struct has_move_emulation_enabled
+ : ::boost::move_detail::has_move_emulation_enabled_impl<T>
+ {};
+
+ template<class T>
+ struct has_move_emulation_disabled
+ {
+ static const bool value = !::boost::move_detail::has_move_emulation_enabled_impl<T>::value;
+ };
+
+ } //namespace boost {
+
+ #define BOOST_RV_REF(TYPE)\
+ ::boost::rv< TYPE >& \
+ //
+
+ #define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
+ ::boost::rv< TYPE<ARG1, ARG2> >& \
+ //
+
+ #define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
+ ::boost::rv< TYPE<ARG1, ARG2, ARG3> >& \
+ //
+
+ #define BOOST_RV_REF_BEG\
+ ::boost::rv< \
+ //
+
+ #define BOOST_RV_REF_END\
+ >& \
+ //
+
+ #define BOOST_RV_REF_BEG_IF_CXX11 \
+ \
+ //
+
+ #define BOOST_RV_REF_END_IF_CXX11 \
+ \
+ //
+
+ #define BOOST_FWD_REF(TYPE)\
+ const TYPE & \
+ //
+
+ #define BOOST_COPY_ASSIGN_REF(TYPE)\
+ const ::boost::rv< TYPE >& \
+ //
+
+ #define BOOST_COPY_ASSIGN_REF_BEG \
+ const ::boost::rv< \
+ //
+
+ #define BOOST_COPY_ASSIGN_REF_END \
+ >& \
+ //
+
+ #define BOOST_COPY_ASSIGN_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
+ const ::boost::rv< TYPE<ARG1, ARG2> >& \
+ //
+
+ #define BOOST_COPY_ASSIGN_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
+ const ::boost::rv< TYPE<ARG1, ARG2, ARG3> >& \
+ //
+
+ #define BOOST_CATCH_CONST_RLVALUE(TYPE)\
+ const ::boost::rv< TYPE >& \
+ //
+
+ namespace boost {
+ namespace move_detail {
+
+ template <class Ret, class T>
+ inline typename ::boost::move_detail::enable_if_c
+ < ::boost::move_detail::is_lvalue_reference<Ret>::value ||
+ !::boost::has_move_emulation_enabled<T>::value
+ , T&>::type
+ move_return(T& x) BOOST_NOEXCEPT
+ {
+ return x;
+ }
+
+ template <class Ret, class T>
+ inline typename ::boost::move_detail::enable_if_c
+ < !::boost::move_detail::is_lvalue_reference<Ret>::value &&
+ ::boost::has_move_emulation_enabled<T>::value
+ , ::boost::rv<T>&>::type
+ move_return(T& x) BOOST_NOEXCEPT
+ {
+ return *BOOST_MOVE_TO_RV_CAST(::boost::rv<T>*, ::boost::move_detail::addressof(x));
+ }
+
+ template <class Ret, class T>
+ inline typename ::boost::move_detail::enable_if_c
+ < !::boost::move_detail::is_lvalue_reference<Ret>::value &&
+ ::boost::has_move_emulation_enabled<T>::value
+ , ::boost::rv<T>&>::type
+ move_return(::boost::rv<T>& x) BOOST_NOEXCEPT
+ {
+ return x;
+ }
+
+ } //namespace move_detail {
+ } //namespace boost {
+
+ #define BOOST_MOVE_RET(RET_TYPE, REF)\
+ boost::move_detail::move_return< RET_TYPE >(REF)
+ //
+
+ #define BOOST_MOVE_BASE(BASE_TYPE, ARG) \
+ ::boost::move((BASE_TYPE&)(ARG))
+ //
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // BOOST_MOVABLE_BUT_NOT_COPYABLE
+ //
+ //////////////////////////////////////////////////////////////////////////////
+ #define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\
+ BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE)\
+ public:\
+ operator ::boost::rv<TYPE>&() \
+ { return *BOOST_MOVE_TO_RV_CAST(::boost::rv<TYPE>*, this); }\
+ operator const ::boost::rv<TYPE>&() const \
+ { return *BOOST_MOVE_TO_RV_CAST(const ::boost::rv<TYPE>*, this); }\
+ private:\
+ //
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // BOOST_COPYABLE_AND_MOVABLE
+ //
+ //////////////////////////////////////////////////////////////////////////////
+
+ #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\
+ public:\
+ TYPE& operator=(TYPE &t)\
+ { this->operator=(const_cast<const TYPE &>(t)); return *this;}\
+ public:\
+ operator ::boost::rv<TYPE>&() \
+ { return *BOOST_MOVE_TO_RV_CAST(::boost::rv<TYPE>*, this); }\
+ operator const ::boost::rv<TYPE>&() const \
+ { return *BOOST_MOVE_TO_RV_CAST(const ::boost::rv<TYPE>*, this); }\
+ private:\
+ //
+
+ #define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\
+ public:\
+ operator ::boost::rv<TYPE>&() \
+ { return *BOOST_MOVE_TO_RV_CAST(::boost::rv<TYPE>*, this); }\
+ operator const ::boost::rv<TYPE>&() const \
+ { return *BOOST_MOVE_TO_RV_CAST(const ::boost::rv<TYPE>*, this); }\
+ private:\
+ //
+
+ namespace boost{
+ namespace move_detail{
+
+ template< class T>
+ struct forward_type
+ { typedef const T &type; };
+
+ template< class T>
+ struct forward_type< boost::rv<T> >
+ { typedef T type; };
+
+ }}
+
+#else //BOOST_NO_CXX11_RVALUE_REFERENCES
+
+ //! This macro marks a type as movable but not copyable, disabling copy construction
+ //! and assignment. The user will need to write a move constructor/assignment as explained
+ //! in the documentation to fully write a movable but not copyable class.
+ #define BOOST_MOVABLE_BUT_NOT_COPYABLE(TYPE)\
+ BOOST_MOVE_IMPL_NO_COPY_CTOR_OR_ASSIGN(TYPE)\
+ public:\
+ typedef int boost_move_emulation_t;\
+ //
+
+ //! This macro marks a type as copyable and movable.
+ //! The user will need to write a move constructor/assignment and a copy assignment
+ //! as explained in the documentation to fully write a copyable and movable class.
+ #define BOOST_COPYABLE_AND_MOVABLE(TYPE)\
+ //
+
+ #if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+ #define BOOST_COPYABLE_AND_MOVABLE_ALT(TYPE)\
+ //
+ #endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+ namespace boost {
+
+ //!This trait yields to a compile-time true boolean if T was marked as
+ //!BOOST_MOVABLE_BUT_NOT_COPYABLE or BOOST_COPYABLE_AND_MOVABLE and
+ //!rvalue references are not available on the platform. False otherwise.
+ template<class T>
+ struct has_move_emulation_enabled
+ {
+ static const bool value = false;
+ };
+
+ template<class T>
+ struct has_move_emulation_disabled
+ {
+ static const bool value = true;
+ };
+
+ } //namespace boost{
+
+ //!This macro is used to achieve portable syntax in move
+ //!constructors and assignments for classes marked as
+ //!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE
+ #define BOOST_RV_REF(TYPE)\
+ TYPE && \
+ //
+
+ //!This macro is used to achieve portable syntax in move
+ //!constructors and assignments for template classes marked as
+ //!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE.
+ //!As macros have problems with comma-separated template arguments,
+ //!the template argument must be preceded with BOOST_RV_REF_BEG
+ //!and ended with BOOST_RV_REF_END
+ #define BOOST_RV_REF_BEG\
+ \
+ //
+
+ //!This macro is used to achieve portable syntax in move
+ //!constructors and assignments for template classes marked as
+ //!BOOST_COPYABLE_AND_MOVABLE or BOOST_MOVABLE_BUT_NOT_COPYABLE.
+ //!As macros have problems with comma-separated template arguments,
+ //!the template argument must be preceded with BOOST_RV_REF_BEG
+ //!and ended with BOOST_RV_REF_END
+ #define BOOST_RV_REF_END\
+ && \
+ //
+
+ //!This macro expands to BOOST_RV_REF_BEG if BOOST_NO_CXX11_RVALUE_REFERENCES
+ //!is not defined, empty otherwise
+ #define BOOST_RV_REF_BEG_IF_CXX11 \
+ BOOST_RV_REF_BEG \
+ //
+
+ //!This macro expands to BOOST_RV_REF_END if BOOST_NO_CXX11_RVALUE_REFERENCES
+ //!is not defined, empty otherwise
+ #define BOOST_RV_REF_END_IF_CXX11 \
+ BOOST_RV_REF_END \
+ //
+
+ //!This macro is used to achieve portable syntax in copy
+ //!assignment for classes marked as BOOST_COPYABLE_AND_MOVABLE.
+ #define BOOST_COPY_ASSIGN_REF(TYPE)\
+ const TYPE & \
+ //
+
+ //! This macro is used to implement portable perfect forwarding
+ //! as explained in the documentation.
+ #define BOOST_FWD_REF(TYPE)\
+ TYPE && \
+ //
+
+ #if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+ #define BOOST_RV_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
+ TYPE<ARG1, ARG2> && \
+ //
+
+ #define BOOST_RV_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
+ TYPE<ARG1, ARG2, ARG3> && \
+ //
+
+ #define BOOST_COPY_ASSIGN_REF_BEG \
+ const \
+ //
+
+ #define BOOST_COPY_ASSIGN_REF_END \
+ & \
+ //
+
+ #define BOOST_COPY_ASSIGN_REF_2_TEMPL_ARGS(TYPE, ARG1, ARG2)\
+ const TYPE<ARG1, ARG2> & \
+ //
+
+ #define BOOST_COPY_ASSIGN_REF_3_TEMPL_ARGS(TYPE, ARG1, ARG2, ARG3)\
+ const TYPE<ARG1, ARG2, ARG3>& \
+ //
+
+ #define BOOST_CATCH_CONST_RLVALUE(TYPE)\
+ const TYPE & \
+ //
+
+ #endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+ #if !defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+ //!This macro is used to achieve portable move return semantics.
+ //!The C++11 Standard allows implicit move returns when the object to be returned
+ //!is designated by a lvalue and:
+ //! - The criteria for elision of a copy operation are met OR
+ //! - The criteria would be met save for the fact that the source object is a function parameter
+ //!
+ //!For C++11 conforming compilers this macros only yields to REF:
+ //! <code>return BOOST_MOVE_RET(RET_TYPE, REF);</code> -> <code>return REF;</code>
+ //!
+ //!For compilers without rvalue references
+ //!this macro does an explicit move if the move emulation is activated
+ //!and the return type (RET_TYPE) is not a reference.
+ //!
+ //!For non-conforming compilers with rvalue references like Visual 2010 & 2012,
+ //!an explicit move is performed if RET_TYPE is not a reference.
+ //!
+ //! <b>Caution</b>: When using this macro in non-conforming or C++03
+ //!compilers, a move will be performed even if the C++11 standard does not allow it
+ //!(e.g. returning a static variable). The user is responsible for using this macro
+ //!only to return local objects that met C++11 criteria.
+ #define BOOST_MOVE_RET(RET_TYPE, REF)\
+ REF
+ //
+
+ #else //!defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+ #include <boost/move/detail/meta_utils.hpp>
+
+ namespace boost {
+ namespace move_detail {
+
+ template <class Ret, class T>
+ inline typename ::boost::move_detail::enable_if_c
+ < ::boost::move_detail::is_lvalue_reference<Ret>::value
+ , T&>::type
+ move_return(T& x) BOOST_NOEXCEPT
+ {
+ return x;
+ }
+
+ template <class Ret, class T>
+ inline typename ::boost::move_detail::enable_if_c
+ < !::boost::move_detail::is_lvalue_reference<Ret>::value
+ , Ret && >::type
+ move_return(T&& t) BOOST_NOEXCEPT
+ {
+ return static_cast< Ret&& >(t);
+ }
+
+ } //namespace move_detail {
+ } //namespace boost {
+
+ #define BOOST_MOVE_RET(RET_TYPE, REF)\
+ boost::move_detail::move_return< RET_TYPE >(REF)
+ //
+
+ #endif //!defined(BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG) || defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+ //!This macro is used to achieve portable optimal move constructors.
+ //!
+ //!When implementing the move constructor, in C++03 compilers the moved-from argument must be
+ //!cast to the base type before calling `::boost::move()` due to rvalue reference limitations.
+ //!
+ //!In C++11 compilers the cast from a rvalue reference of a derived type to a rvalue reference of
+ //!a base type is implicit.
+ #define BOOST_MOVE_BASE(BASE_TYPE, ARG) \
+ ::boost::move((BASE_TYPE&)(ARG))
+ //
+
+ namespace boost {
+ namespace move_detail {
+
+ template< class T> struct forward_type { typedef T type; };
+
+ }}
+
+#endif //BOOST_NO_CXX11_RVALUE_REFERENCES
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_CORE_HPP
diff --git a/third_party/boost/boost/move/detail/config_begin.hpp b/third_party/boost/boost/move/detail/config_begin.hpp
new file mode 100644
index 0000000..342390b
--- /dev/null
+++ b/third_party/boost/boost/move/detail/config_begin.hpp
@@ -0,0 +1,19 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_CONFIG_HPP
+#include <boost/config.hpp>
+#endif
+
+#ifdef BOOST_MSVC
+# pragma warning (push)
+# pragma warning (disable : 4324) // structure was padded due to __declspec(align())
+# pragma warning (disable : 4675) // "function": resolved overload was found by argument-dependent lookup
+# pragma warning (disable : 4996) // "function": was declared deprecated (_CRT_SECURE_NO_DEPRECATE/_SCL_SECURE_NO_WARNINGS)
+#endif
diff --git a/third_party/boost/boost/move/detail/config_end.hpp b/third_party/boost/boost/move/detail/config_end.hpp
new file mode 100644
index 0000000..71a99e9
--- /dev/null
+++ b/third_party/boost/boost/move/detail/config_end.hpp
@@ -0,0 +1,12 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#if defined BOOST_MSVC
+# pragma warning (pop)
+#endif
diff --git a/third_party/boost/boost/move/detail/iterator_traits.hpp b/third_party/boost/boost/move/detail/iterator_traits.hpp
new file mode 100644
index 0000000..a75ee03
--- /dev/null
+++ b/third_party/boost/boost/move/detail/iterator_traits.hpp
@@ -0,0 +1,73 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2014-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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+
+#ifndef BOOST_MOVE_DETAIL_ITERATOR_TRAITS_HPP
+#define BOOST_MOVE_DETAIL_ITERATOR_TRAITS_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <cstddef>
+
+#include <boost/move/detail/std_ns_begin.hpp>
+BOOST_MOVE_STD_NS_BEG
+
+struct input_iterator_tag;
+struct forward_iterator_tag;
+struct bidirectional_iterator_tag;
+struct random_access_iterator_tag;
+struct output_iterator_tag;
+
+BOOST_MOVE_STD_NS_END
+#include <boost/move/detail/std_ns_end.hpp>
+
+namespace boost{ namespace movelib{
+
+template<class Iterator>
+struct iterator_traits
+{
+ typedef typename Iterator::difference_type difference_type;
+ typedef typename Iterator::value_type value_type;
+ typedef typename Iterator::pointer pointer;
+ typedef typename Iterator::reference reference;
+ typedef typename Iterator::iterator_category iterator_category;
+};
+
+template<class T>
+struct iterator_traits<T*>
+{
+ typedef std::ptrdiff_t difference_type;
+ typedef T value_type;
+ typedef T* pointer;
+ typedef T& reference;
+ typedef std::random_access_iterator_tag iterator_category;
+};
+
+template<class T>
+struct iterator_traits<const T*>
+{
+ typedef std::ptrdiff_t difference_type;
+ typedef T value_type;
+ typedef const T* pointer;
+ typedef const T& reference;
+ typedef std::random_access_iterator_tag iterator_category;
+};
+
+}} //namespace boost { namespace movelib{
+
+#endif //#ifndef BOOST_MOVE_DETAIL_ITERATOR_TRAITS_HPP
diff --git a/third_party/boost/boost/move/detail/meta_utils.hpp b/third_party/boost/boost/move/detail/meta_utils.hpp
new file mode 100644
index 0000000..323c13a
--- /dev/null
+++ b/third_party/boost/boost/move/detail/meta_utils.hpp
@@ -0,0 +1,564 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+
+#ifndef BOOST_MOVE_DETAIL_META_UTILS_HPP
+#define BOOST_MOVE_DETAIL_META_UTILS_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+#include <boost/move/detail/meta_utils_core.hpp>
+#include <cstddef> //for std::size_t
+
+//Small meta-typetraits to support move
+
+namespace boost {
+
+//Forward declare boost::rv
+template <class T> class rv;
+
+namespace move_detail {
+
+//////////////////////////////////////
+// is_different
+//////////////////////////////////////
+template<class T, class U>
+struct is_different
+{
+ static const bool value = !is_same<T, U>::value;
+};
+
+//////////////////////////////////////
+// apply
+//////////////////////////////////////
+template<class F, class Param>
+struct apply
+{
+ typedef typename F::template apply<Param>::type type;
+};
+
+//////////////////////////////////////
+// bool_
+//////////////////////////////////////
+
+template< bool C_ >
+struct bool_ : integral_constant<bool, C_>
+{
+ operator bool() const { return C_; }
+ bool operator()() const { return C_; }
+};
+
+typedef bool_<true> true_;
+typedef bool_<false> false_;
+
+//////////////////////////////////////
+// nat
+//////////////////////////////////////
+struct nat{};
+
+//////////////////////////////////////
+// yes_type/no_type
+//////////////////////////////////////
+typedef char yes_type;
+
+struct no_type
+{
+ char _[2];
+};
+
+//////////////////////////////////////
+// natify
+//////////////////////////////////////
+template <class T> struct natify{};
+
+//////////////////////////////////////
+// remove_reference
+//////////////////////////////////////
+template<class T>
+struct remove_reference
+{
+ typedef T type;
+};
+
+template<class T>
+struct remove_reference<T&>
+{
+ typedef T type;
+};
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+template<class T>
+struct remove_reference<T&&>
+{
+ typedef T type;
+};
+
+#else
+
+template<class T>
+struct remove_reference< rv<T> >
+{
+ typedef T type;
+};
+
+template<class T>
+struct remove_reference< rv<T> &>
+{
+ typedef T type;
+};
+
+template<class T>
+struct remove_reference< const rv<T> &>
+{
+ typedef T type;
+};
+
+#endif
+
+//////////////////////////////////////
+// remove_pointer
+//////////////////////////////////////
+
+template< class T > struct remove_pointer { typedef T type; };
+template< class T > struct remove_pointer<T*> { typedef T type; };
+template< class T > struct remove_pointer<T* const> { typedef T type; };
+template< class T > struct remove_pointer<T* volatile> { typedef T type; };
+template< class T > struct remove_pointer<T* const volatile> { typedef T type; };
+
+//////////////////////////////////////
+// add_pointer
+//////////////////////////////////////
+template< class T >
+struct add_pointer
+{
+ typedef typename remove_reference<T>::type* type;
+};
+
+//////////////////////////////////////
+// add_const
+//////////////////////////////////////
+template<class T>
+struct add_const
+{
+ typedef const T type;
+};
+
+template<class T>
+struct add_const<T&>
+{
+ typedef const T& type;
+};
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+template<class T>
+struct add_const<T&&>
+{
+ typedef T&& type;
+};
+
+#endif
+
+//////////////////////////////////////
+// add_lvalue_reference
+//////////////////////////////////////
+template<class T>
+struct add_lvalue_reference
+{ typedef T& type; };
+
+template<class T> struct add_lvalue_reference<T&> { typedef T& type; };
+template<> struct add_lvalue_reference<void> { typedef void type; };
+template<> struct add_lvalue_reference<const void> { typedef const void type; };
+template<> struct add_lvalue_reference<volatile void> { typedef volatile void type; };
+template<> struct add_lvalue_reference<const volatile void>{ typedef const volatile void type; };
+
+template<class T>
+struct add_const_lvalue_reference
+{
+ typedef typename remove_reference<T>::type t_unreferenced;
+ typedef typename add_const<t_unreferenced>::type t_unreferenced_const;
+ typedef typename add_lvalue_reference
+ <t_unreferenced_const>::type type;
+};
+
+//////////////////////////////////////
+// is_lvalue_reference
+//////////////////////////////////////
+template<class T>
+struct is_lvalue_reference
+{
+ static const bool value = false;
+};
+
+template<class T>
+struct is_lvalue_reference<T&>
+{
+ static const bool value = true;
+};
+
+
+//////////////////////////////////////
+// identity
+//////////////////////////////////////
+template <class T>
+struct identity
+{
+ typedef T type;
+ typedef typename add_const_lvalue_reference<T>::type reference;
+ reference operator()(reference t)
+ { return t; }
+};
+
+//////////////////////////////////////
+// is_class_or_union
+//////////////////////////////////////
+template<class T>
+struct is_class_or_union
+{
+ struct twochar { char dummy[2]; };
+ template <class U>
+ static char is_class_or_union_tester(void(U::*)(void));
+ template <class U>
+ static twochar is_class_or_union_tester(...);
+ static const bool value = sizeof(is_class_or_union_tester<T>(0)) == sizeof(char);
+};
+
+//////////////////////////////////////
+// addressof
+//////////////////////////////////////
+template<class T>
+struct addr_impl_ref
+{
+ T & v_;
+ inline addr_impl_ref( T & v ): v_( v ) {}
+ inline operator T& () const { return v_; }
+
+ private:
+ addr_impl_ref & operator=(const addr_impl_ref &);
+};
+
+template<class T>
+struct addressof_impl
+{
+ static inline T * f( T & v, long )
+ {
+ return reinterpret_cast<T*>(
+ &const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
+ }
+
+ static inline T * f( T * v, int )
+ { return v; }
+};
+
+template<class T>
+inline T * addressof( T & v )
+{
+ return ::boost::move_detail::addressof_impl<T>::f
+ ( ::boost::move_detail::addr_impl_ref<T>( v ), 0 );
+}
+
+//////////////////////////////////////
+// has_pointer_type
+//////////////////////////////////////
+template <class T>
+struct has_pointer_type
+{
+ struct two { char c[2]; };
+ template <class U> static two test(...);
+ template <class U> static char test(typename U::pointer* = 0);
+ static const bool value = sizeof(test<T>(0)) == 1;
+};
+
+//////////////////////////////////////
+// is_convertible
+//////////////////////////////////////
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+
+//use intrinsic since in MSVC
+//overaligned types can't go through ellipsis
+template <class T, class U>
+struct is_convertible
+{
+ static const bool value = __is_convertible_to(T, U);
+};
+
+#else
+
+template <class T, class U>
+class is_convertible
+{
+ typedef typename add_lvalue_reference<T>::type t_reference;
+ typedef char true_t;
+ class false_t { char dummy[2]; };
+ static false_t dispatch(...);
+ static true_t dispatch(U);
+ static t_reference trigger();
+ public:
+ static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t);
+};
+
+#endif
+
+template<
+ bool C
+ , typename F1
+ , typename F2
+ >
+struct eval_if_c
+ : if_c<C,F1,F2>::type
+{};
+
+template<
+ typename C
+ , typename T1
+ , typename T2
+ >
+struct eval_if
+ : if_<C,T1,T2>::type
+{};
+
+
+#if defined(BOOST_GCC) && (BOOST_GCC <= 40000)
+#define BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN
+#endif
+
+template<class T, class U, class R = void>
+struct enable_if_convertible
+ : enable_if< is_convertible<T, U>, R>
+{};
+
+template<class T, class U, class R = void>
+struct disable_if_convertible
+ : disable_if< is_convertible<T, U>, R>
+{};
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// and_
+//
+//////////////////////////////////////////////////////////////////////////////
+template<bool, class B = true_, class C = true_, class D = true_>
+struct and_impl
+ : and_impl<B::value, C, D>
+{};
+
+template<>
+struct and_impl<true, true_, true_, true_>
+{
+ static const bool value = true;
+};
+
+template<class B, class C, class D>
+struct and_impl<false, B, C, D>
+{
+ static const bool value = false;
+};
+
+template<class A, class B, class C = true_, class D = true_>
+struct and_
+ : and_impl<A::value, B, C, D>
+{};
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// or_
+//
+//////////////////////////////////////////////////////////////////////////////
+template<bool, class B = false_, class C = false_, class D = false_>
+struct or_impl
+ : or_impl<B::value, C, D>
+{};
+
+template<>
+struct or_impl<false, false_, false_, false_>
+{
+ static const bool value = false;
+};
+
+template<class B, class C, class D>
+struct or_impl<true, B, C, D>
+{
+ static const bool value = true;
+};
+
+template<class A, class B, class C = false_, class D = false_>
+struct or_
+ : or_impl<A::value, B, C, D>
+{};
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// not_
+//
+//////////////////////////////////////////////////////////////////////////////
+template<class T>
+struct not_
+{
+ static const bool value = !T::value;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// enable_if_and / disable_if_and / enable_if_or / disable_if_or
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template<class R, class A, class B, class C = true_, class D = true_>
+struct enable_if_and
+ : enable_if_c< and_<A, B, C, D>::value, R>
+{};
+
+template<class R, class A, class B, class C = true_, class D = true_>
+struct disable_if_and
+ : disable_if_c< and_<A, B, C, D>::value, R>
+{};
+
+template<class R, class A, class B, class C = false_, class D = false_>
+struct enable_if_or
+ : enable_if_c< or_<A, B, C, D>::value, R>
+{};
+
+template<class R, class A, class B, class C = false_, class D = false_>
+struct disable_if_or
+ : disable_if_c< or_<A, B, C, D>::value, R>
+{};
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// has_move_emulation_enabled_impl
+//
+//////////////////////////////////////////////////////////////////////////////
+template<class T>
+struct has_move_emulation_enabled_impl
+ : is_convertible< T, ::boost::rv<T>& >
+{};
+
+template<class T>
+struct has_move_emulation_enabled_impl<T&>
+{ static const bool value = false; };
+
+template<class T>
+struct has_move_emulation_enabled_impl< ::boost::rv<T> >
+{ static const bool value = false; };
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// is_rv_impl
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template <class T>
+struct is_rv_impl
+{ static const bool value = false; };
+
+template <class T>
+struct is_rv_impl< rv<T> >
+{ static const bool value = true; };
+
+template <class T>
+struct is_rv_impl< const rv<T> >
+{ static const bool value = true; };
+
+// Code from Jeffrey Lee Hellrung, many thanks
+
+template< class T >
+struct is_rvalue_reference
+{ static const bool value = false; };
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+template< class T >
+struct is_rvalue_reference< T&& >
+{ static const bool value = true; };
+
+#else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+template< class T >
+struct is_rvalue_reference< boost::rv<T>& >
+{ static const bool value = true; };
+
+template< class T >
+struct is_rvalue_reference< const boost::rv<T>& >
+{ static const bool value = true; };
+
+#endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+template< class T >
+struct add_rvalue_reference
+{ typedef T&& type; };
+
+#else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+namespace detail_add_rvalue_reference
+{
+ template< class T
+ , bool emulation = has_move_emulation_enabled_impl<T>::value
+ , bool rv = is_rv_impl<T>::value >
+ struct add_rvalue_reference_impl { typedef T type; };
+
+ template< class T, bool emulation>
+ struct add_rvalue_reference_impl< T, emulation, true > { typedef T & type; };
+
+ template< class T, bool rv >
+ struct add_rvalue_reference_impl< T, true, rv > { typedef ::boost::rv<T>& type; };
+} // namespace detail_add_rvalue_reference
+
+template< class T >
+struct add_rvalue_reference
+ : detail_add_rvalue_reference::add_rvalue_reference_impl<T>
+{ };
+
+template< class T >
+struct add_rvalue_reference<T &>
+{ typedef T & type; };
+
+#endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+template< class T > struct remove_rvalue_reference { typedef T type; };
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template< class T > struct remove_rvalue_reference< T&& > { typedef T type; };
+#else // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template< class T > struct remove_rvalue_reference< rv<T> > { typedef T type; };
+ template< class T > struct remove_rvalue_reference< const rv<T> > { typedef T type; };
+ template< class T > struct remove_rvalue_reference< volatile rv<T> > { typedef T type; };
+ template< class T > struct remove_rvalue_reference< const volatile rv<T> > { typedef T type; };
+ template< class T > struct remove_rvalue_reference< rv<T>& > { typedef T type; };
+ template< class T > struct remove_rvalue_reference< const rv<T>& > { typedef T type; };
+ template< class T > struct remove_rvalue_reference< volatile rv<T>& > { typedef T type; };
+ template< class T > struct remove_rvalue_reference< const volatile rv<T>& >{ typedef T type; };
+#endif // #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+// Ideas from Boost.Move review, Jeffrey Lee Hellrung:
+//
+//- TypeTraits metafunctions is_lvalue_reference, add_lvalue_reference, and remove_lvalue_reference ?
+// Perhaps add_reference and remove_reference can be modified so that they behave wrt emulated rvalue
+// references the same as wrt real rvalue references, i.e., add_reference< rv<T>& > -> T& rather than
+// rv<T>& (since T&& & -> T&).
+//
+//- Add'l TypeTraits has_[trivial_]move_{constructor,assign}...?
+//
+//- An as_lvalue(T& x) function, which amounts to an identity operation in C++0x, but strips emulated
+// rvalue references in C++03. This may be necessary to prevent "accidental moves".
+
+} //namespace move_detail {
+} //namespace boost {
+
+#endif //#ifndef BOOST_MOVE_DETAIL_META_UTILS_HPP
diff --git a/third_party/boost/boost/move/detail/meta_utils_core.hpp b/third_party/boost/boost/move/detail/meta_utils_core.hpp
new file mode 100644
index 0000000..7efdd20
--- /dev/null
+++ b/third_party/boost/boost/move/detail/meta_utils_core.hpp
@@ -0,0 +1,120 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+
+#ifndef BOOST_MOVE_DETAIL_META_UTILS_CORE_HPP
+#define BOOST_MOVE_DETAIL_META_UTILS_CORE_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+//Small meta-typetraits to support move
+
+namespace boost {
+namespace move_detail {
+
+//////////////////////////////////////
+// if_c
+//////////////////////////////////////
+template<bool C, typename T1, typename T2>
+struct if_c
+{
+ typedef T1 type;
+};
+
+template<typename T1, typename T2>
+struct if_c<false,T1,T2>
+{
+ typedef T2 type;
+};
+
+//////////////////////////////////////
+// if_
+//////////////////////////////////////
+template<typename T1, typename T2, typename T3>
+struct if_ : if_c<0 != T1::value, T2, T3>
+{};
+
+//////////////////////////////////////
+// enable_if_c
+//////////////////////////////////////
+template <bool B, class T = void>
+struct enable_if_c
+{
+ typedef T type;
+};
+
+template <class T>
+struct enable_if_c<false, T> {};
+
+//////////////////////////////////////
+// enable_if
+//////////////////////////////////////
+template <class Cond, class T = void>
+struct enable_if : enable_if_c<Cond::value, T> {};
+
+//////////////////////////////////////
+// disable_if_c
+//////////////////////////////////////
+template <bool B, class T = void>
+struct disable_if_c
+ : enable_if_c<!B, T>
+{};
+
+//////////////////////////////////////
+// disable_if
+//////////////////////////////////////
+template <class Cond, class T = void>
+struct disable_if : enable_if_c<!Cond::value, T> {};
+
+//////////////////////////////////////
+// integral_constant
+//////////////////////////////////////
+template<class T, T v>
+struct integral_constant
+{
+ static const T value = v;
+ typedef T value_type;
+ typedef integral_constant<T, v> type;
+
+ operator T() const { return value; }
+ T operator()() const { return value; }
+};
+
+typedef integral_constant<bool, true > true_type;
+typedef integral_constant<bool, false > false_type;
+
+
+//////////////////////////////////////
+// is_same
+//////////////////////////////////////
+template<class T, class U>
+struct is_same
+{
+ static const bool value = false;
+};
+
+template<class T>
+struct is_same<T, T>
+{
+ static const bool value = true;
+};
+
+} //namespace move_detail {
+} //namespace boost {
+
+#endif //#ifndef BOOST_MOVE_DETAIL_META_UTILS_CORE_HPP
diff --git a/third_party/boost/boost/move/detail/std_ns_begin.hpp b/third_party/boost/boost/move/detail/std_ns_begin.hpp
new file mode 100644
index 0000000..ea76e6b
--- /dev/null
+++ b/third_party/boost/boost/move/detail/std_ns_begin.hpp
@@ -0,0 +1,29 @@
+#//////////////////////////////////////////////////////////////////////////////
+#//
+#// (C) Copyright Ion Gaztanaga 2015-2015.
+#// Distributed under the Boost Software License, Version 1.0.
+#// (See accompanying file LICENSE_1_0.txt or copy at
+#// http://www.boost.org/LICENSE_1_0.txt)
+#//
+#// See http://www.boost.org/libs/move for documentation.
+#//
+#//////////////////////////////////////////////////////////////////////////////
+#
+#if defined(_LIBCPP_VERSION)
+ #if defined(__clang__)
+ #define BOOST_MOVE_STD_NS_GCC_DIAGNOSTIC_PUSH
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wc++11-extensions"
+ #endif
+ #define BOOST_MOVE_STD_NS_BEG _LIBCPP_BEGIN_NAMESPACE_STD
+ #define BOOST_MOVE_STD_NS_END _LIBCPP_END_NAMESPACE_STD
+#elif defined(BOOST_GNU_STDLIB) && defined(_GLIBCXX_BEGIN_NAMESPACE_VERSION) //GCC >= 4.6
+ #define BOOST_MOVE_STD_NS_BEG namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION
+ #define BOOST_MOVE_STD_NS_END _GLIBCXX_END_NAMESPACE_VERSION } // namespace
+#elif defined(BOOST_GNU_STDLIB) && defined(_GLIBCXX_BEGIN_NAMESPACE) //GCC >= 4.2
+ #define BOOST_MOVE_STD_NS_BEG _GLIBCXX_BEGIN_NAMESPACE(std)
+ #define BOOST_MOVE_STD_NS_END _GLIBCXX_END_NAMESPACE
+#else
+ #define BOOST_MOVE_STD_NS_BEG namespace std{
+ #define BOOST_MOVE_STD_NS_END }
+#endif
diff --git a/third_party/boost/boost/move/detail/std_ns_end.hpp b/third_party/boost/boost/move/detail/std_ns_end.hpp
new file mode 100644
index 0000000..0975059
--- /dev/null
+++ b/third_party/boost/boost/move/detail/std_ns_end.hpp
@@ -0,0 +1,14 @@
+#//////////////////////////////////////////////////////////////////////////////
+#//
+#// (C) Copyright Ion Gaztanaga 2015-2015.
+#// Distributed under the Boost Software License, Version 1.0.
+#// (See accompanying file LICENSE_1_0.txt or copy at
+#// http://www.boost.org/LICENSE_1_0.txt)
+#//
+#// See http://www.boost.org/libs/move for documentation.
+#//
+#//////////////////////////////////////////////////////////////////////////////
+#ifdef BOOST_MOVE_STD_NS_GCC_DIAGNOSTIC_PUSH
+ #pragma GCC diagnostic pop
+ #undef BOOST_MOVE_STD_NS_GCC_DIAGNOSTIC_PUSH
+#endif //BOOST_MOVE_STD_NS_GCC_DIAGNOSTIC_PUSH
diff --git a/third_party/boost/boost/move/detail/type_traits.hpp b/third_party/boost/boost/move/detail/type_traits.hpp
new file mode 100644
index 0000000..7f7b087
--- /dev/null
+++ b/third_party/boost/boost/move/detail/type_traits.hpp
@@ -0,0 +1,1078 @@
+//////////////////////////////////////////////////////////////////////////////
+// (C) Copyright John Maddock 2000.
+// (C) Copyright Ion Gaztanaga 2005-2015.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+// The alignment and Type traits implementation comes from
+// John Maddock's TypeTraits library.
+//
+// Some other tricks come from Howard Hinnant's papers and StackOverflow replies
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_MOVE_DETAIL_TYPE_TRAITS_HPP
+#define BOOST_MOVE_DETAIL_TYPE_TRAITS_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/workaround.hpp>
+
+// move/detail
+#include <boost/move/detail/meta_utils.hpp>
+// other
+#include <boost/assert.hpp>
+#include <boost/static_assert.hpp>
+// std
+#include <cstddef>
+
+//Use of Boost.TypeTraits leads to long preprocessed source code due to
+//MPL dependencies. We'll use intrinsics directly and make or own
+//simplified version of TypeTraits.
+//If someday Boost.TypeTraits dependencies are minimized, we should
+//revisit this file redirecting code to Boost.TypeTraits traits.
+
+//These traits don't care about volatile, reference or other checks
+//made by Boost.TypeTraits because no volatile or reference types
+//can be hold in Boost.Containers. This helps to avoid any Boost.TypeTraits
+//dependency.
+
+// Helper macros for builtin compiler support.
+// If your compiler has builtin support for any of the following
+// traits concepts, then redefine the appropriate macros to pick
+// up on the compiler support:
+//
+// (these should largely ignore cv-qualifiers)
+// BOOST_MOVE_IS_POD(T) should evaluate to true if T is a POD type
+// BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) should evaluate to true if "T x;" has no effect
+// BOOST_MOVE_HAS_TRIVIAL_COPY(T) should evaluate to true if T(t) <==> memcpy
+// BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) should evaluate to true if T(boost::move(t)) <==> memcpy
+// BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) should evaluate to true if t = u <==> memcpy
+// BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T) should evaluate to true if t = boost::move(u) <==> memcpy
+// BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) should evaluate to true if ~T() has no effect
+// BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) should evaluate to true if "T x;" can not throw
+// BOOST_MOVE_HAS_NOTHROW_COPY(T) should evaluate to true if T(t) can not throw
+// BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) should evaluate to true if t = u can not throw
+// BOOST_MOVE_IS_ENUM(T) should evaluate to true it t is a union type.
+//
+// The following can also be defined: when detected our implementation is greatly simplified.
+//
+// BOOST_ALIGNMENT_OF(T) should evaluate to the alignment requirements of type T.
+
+#if defined(__MSL_CPP__) && (__MSL_CPP__ >= 0x8000)
+ // Metrowerks compiler is acquiring intrinsic type traits support
+ // post version 8. We hook into the published interface to pick up
+ // user defined specializations as well as compiler intrinsics as
+ // and when they become available:
+# include <msl_utility>
+# define BOOST_MOVE_IS_UNION(T) BOOST_STD_EXTENSION_NAMESPACE::is_union<T>::value
+# define BOOST_MOVE_IS_POD(T) BOOST_STD_EXTENSION_NAMESPACE::is_POD<T>::value
+# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) BOOST_STD_EXTENSION_NAMESPACE::has_trivial_default_ctor<T>::value
+# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) BOOST_STD_EXTENSION_NAMESPACE::has_trivial_copy_ctor<T>::value
+# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) BOOST_STD_EXTENSION_NAMESPACE::has_trivial_assignment<T>::value
+# define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) BOOST_STD_EXTENSION_NAMESPACE::has_trivial_dtor<T>::value
+#endif
+
+#if (defined(BOOST_MSVC) && defined(BOOST_MSVC_FULL_VER) && (BOOST_MSVC_FULL_VER >=140050215))\
+ || (defined(BOOST_INTEL) && defined(_MSC_VER) && (_MSC_VER >= 1500))
+# define BOOST_MOVE_IS_UNION(T) __is_union(T)
+# define BOOST_MOVE_IS_POD(T) (__is_pod(T) && __has_trivial_constructor(T))
+# define BOOST_MOVE_IS_EMPTY(T) __is_empty(T)
+# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) __has_trivial_constructor(T)
+# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__has_trivial_copy(T)|| ::boost::move_detail::is_pod<T>::value)
+# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T) || ::boost::move_detail::is_pod<T>::value)
+# define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) (__has_trivial_destructor(T) || ::boost::move_detail::is_pod<T>::value)
+# define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) (__has_nothrow_constructor(T) || ::boost::move_detail::is_trivially_default_constructible<T>::value)
+# define BOOST_MOVE_HAS_NOTHROW_COPY(T) (__has_nothrow_copy(T) || ::boost::move_detail::is_trivially_copy_constructible<T>::value)
+# define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) (__has_nothrow_assign(T) || ::boost::move_detail::is_trivially_copy_assignable<T>::value)
+
+# define BOOST_MOVE_IS_ENUM(T) __is_enum(T)
+# if defined(_MSC_VER) && (_MSC_VER >= 1700)
+# define BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) (__has_trivial_move_constructor(T) || ::boost::move_detail::is_pod<T>::value)
+# define BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T) (__has_trivial_move_assign(T) || ::boost::move_detail::is_pod<T>::value)
+# endif
+#endif
+
+#if defined(BOOST_CLANG) && defined(__has_feature)
+
+# if __has_feature(is_union)
+# define BOOST_MOVE_IS_UNION(T) __is_union(T)
+# endif
+# if (!defined(__GLIBCXX__) || (__GLIBCXX__ >= 20080306 && __GLIBCXX__ != 20080519)) && __has_feature(is_pod)
+# define BOOST_MOVE_IS_POD(T) __is_pod(T)
+# endif
+# if (!defined(__GLIBCXX__) || (__GLIBCXX__ >= 20080306 && __GLIBCXX__ != 20080519)) && __has_feature(is_empty)
+# define BOOST_MOVE_IS_EMPTY(T) __is_empty(T)
+# endif
+# if __has_feature(has_trivial_constructor)
+# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) __has_trivial_constructor(T)
+# endif
+# if __has_feature(has_trivial_copy)
+# //There are problems with deleted copy constructors detected as trivially copyable.
+# //http://stackoverflow.com/questions/12754886/has-trivial-copy-behaves-differently-in-clang-and-gcc-whos-right
+# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__has_trivial_copy(T) && ::boost::move_detail::is_copy_constructible<T>::value)
+# endif
+# if __has_feature(has_trivial_assign)
+# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T) )
+# endif
+# if __has_feature(has_trivial_destructor)
+# define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) __has_trivial_destructor(T)
+# endif
+# if __has_feature(has_nothrow_constructor)
+# define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) __has_nothrow_constructor(T)
+# endif
+# if __has_feature(has_nothrow_copy)
+# define BOOST_MOVE_HAS_NOTHROW_COPY(T) (__has_nothrow_copy(T))
+# endif
+# if __has_feature(is_nothrow_copy_assignable)
+# define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) (__has_nothrow_assign(T))
+# endif
+# if __has_feature(is_enum)
+# define BOOST_MOVE_IS_ENUM(T) __is_enum(T)
+# endif
+# if __has_feature(has_trivial_move_constructor)
+# define BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) __has_trivial_move_constructor(T)
+# endif
+# if __has_feature(has_trivial_move_assign)
+# define BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T) __has_trivial_move_assign(T)
+# endif
+# define BOOST_MOVE_ALIGNMENT_OF(T) __alignof(T)
+#endif
+
+#if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3) && !defined(__GCCXML__))) && !defined(BOOST_CLANG)
+
+#ifdef BOOST_INTEL
+# define BOOST_MOVE_INTEL_TT_OPTS || ::boost::move_detail::is_pod<T>::value
+#else
+# define BOOST_MOVE_INTEL_TT_OPTS
+#endif
+
+# define BOOST_MOVE_IS_UNION(T) __is_union(T)
+# define BOOST_MOVE_IS_POD(T) __is_pod(T)
+# define BOOST_MOVE_IS_EMPTY(T) __is_empty(T)
+# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) ((__has_trivial_constructor(T) BOOST_MOVE_INTEL_TT_OPTS))
+# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) ((__has_trivial_copy(T) BOOST_MOVE_INTEL_TT_OPTS))
+# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) ((__has_trivial_assign(T) BOOST_MOVE_INTEL_TT_OPTS) )
+# define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) (__has_trivial_destructor(T) BOOST_MOVE_INTEL_TT_OPTS)
+# define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) (__has_nothrow_constructor(T) BOOST_MOVE_INTEL_TT_OPTS)
+# define BOOST_MOVE_HAS_NOTHROW_COPY(T) ((__has_nothrow_copy(T) BOOST_MOVE_INTEL_TT_OPTS))
+# define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) ((__has_nothrow_assign(T) BOOST_MOVE_INTEL_TT_OPTS))
+
+# define BOOST_MOVE_IS_ENUM(T) __is_enum(T)
+# if (!defined(unix) && !defined(__unix__)) || defined(__LP64__)
+ // GCC sometimes lies about alignment requirements
+ // of type double on 32-bit unix platforms, use the
+ // old implementation instead in that case:
+# define BOOST_MOVE_ALIGNMENT_OF(T) __alignof__(T)
+# endif
+#endif
+
+#if defined(__ghs__) && (__GHS_VERSION_NUMBER >= 600)
+
+# define BOOST_MOVE_IS_UNION(T) __is_union(T)
+# define BOOST_MOVE_IS_POD(T) __is_pod(T)
+# define BOOST_MOVE_IS_EMPTY(T) __is_empty(T)
+# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) __has_trivial_constructor(T)
+# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__has_trivial_copy(T))
+# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T))
+# define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) __has_trivial_destructor(T)
+# define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) __has_nothrow_constructor(T)
+# define BOOST_MOVE_HAS_NOTHROW_COPY(T) (__has_nothrow_copy(T))
+# define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) (__has_nothrow_assign(T))
+
+# define BOOST_MOVE_IS_ENUM(T) __is_enum(T)
+# define BOOST_MOVE_ALIGNMENT_OF(T) __alignof__(T)
+#endif
+
+# if defined(__CODEGEARC__)
+# define BOOST_MOVE_IS_UNION(T) __is_union(T)
+# define BOOST_MOVE_IS_POD(T) __is_pod(T)
+# define BOOST_MOVE_IS_EMPTY(T) __is_empty(T)
+# define BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T) (__has_trivial_default_constructor(T))
+# define BOOST_MOVE_HAS_TRIVIAL_COPY(T) (__has_trivial_copy_constructor(T))
+# define BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T))
+# define BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T) (__has_trivial_destructor(T))
+# define BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T) (__has_nothrow_default_constructor(T))
+# define BOOST_MOVE_HAS_NOTHROW_COPY(T) (__has_nothrow_copy_constructor(T))
+# define BOOST_MOVE_HAS_NOTHROW_ASSIGN(T) (__has_nothrow_assign(T))
+
+# define BOOST_MOVE_IS_ENUM(T) __is_enum(T)
+# define BOOST_MOVE_ALIGNMENT_OF(T) alignof(T)
+
+#endif
+
+//Fallback definitions
+
+#ifdef BOOST_MOVE_IS_UNION
+ #define BOOST_MOVE_IS_UNION_IMPL(T) BOOST_MOVE_IS_UNION(T)
+#else
+ #define BOOST_MOVE_IS_UNION_IMPL(T) false
+#endif
+
+#ifdef BOOST_MOVE_IS_POD
+ //in some compilers the intrinsic is limited to class types so add scalar and void
+ #define BOOST_MOVE_IS_POD_IMPL(T) (::boost::move_detail::is_scalar<T>::value ||\
+ ::boost::move_detail::is_void<T>::value ||\
+ BOOST_MOVE_IS_POD(T))
+#else
+ #define BOOST_MOVE_IS_POD_IMPL(T) \
+ (::boost::move_detail::is_scalar<T>::value || ::boost::move_detail::is_void<T>::value)
+#endif
+
+#ifdef BOOST_MOVE_IS_EMPTY
+ #define BOOST_MOVE_IS_EMPTY_IMPL(T) BOOST_MOVE_IS_EMPTY(T)
+#else
+ #define BOOST_MOVE_IS_EMPTY_IMPL(T) ::boost::move_detail::is_empty_nonintrinsic<T>::value
+#endif
+
+#ifdef BOOST_MOVE_HAS_TRIVIAL_COPY
+ #define BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_COPY(T)
+#else
+ #define BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
+#endif
+
+#ifdef BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR
+ #define BOOST_MOVE_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_CONSTRUCTOR(T)
+#else
+ #define BOOST_MOVE_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
+#endif
+
+#ifdef BOOST_MOVE_HAS_TRIVIAL_COPY
+ #define BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_COPY(T)
+#else
+ #define BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
+#endif
+
+#ifdef BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR
+ #define BOOST_MOVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T)
+#else
+ #define BOOST_MOVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
+#endif
+
+#ifdef BOOST_MOVE_HAS_TRIVIAL_ASSIGN
+ #define BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T) BOOST_MOVE_HAS_TRIVIAL_ASSIGN(T)
+#else
+ #define BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T) ::boost::move_detail::is_pod<T>::value
+#endif
+
+#ifdef BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN
+ #define BOOST_MOVE_IS_TRIVIALLY_MOVE_ASSIGNABLE(T) BOOST_MOVE_HAS_TRIVIAL_MOVE_ASSIGN(T)
+#else
+ #define BOOST_MOVE_IS_TRIVIALLY_MOVE_ASSIGNABLE(T) ::boost::move_detail::is_pod<T>::value
+#endif
+
+#ifdef BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR
+ #define BOOST_MOVE_IS_TRIVIALLY_DESTRUCTIBLE(T) BOOST_MOVE_HAS_TRIVIAL_DESTRUCTOR(T)
+#else
+ #define BOOST_MOVE_IS_TRIVIALLY_DESTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
+#endif
+
+#ifdef BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR
+ #define BOOST_MOVE_IS_NOTHROW_DEFAULT_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_NOTHROW_CONSTRUCTOR(T)
+#else
+ #define BOOST_MOVE_IS_NOTHROW_DEFAULT_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
+#endif
+
+#ifdef BOOST_MOVE_HAS_NOTHROW_COPY
+ #define BOOST_MOVE_IS_NOTHROW_COPY_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_NOTHROW_COPY(T)
+#else
+ #define BOOST_MOVE_IS_NOTHROW_COPY_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
+#endif
+
+#ifdef BOOST_MOVE_HAS_NOTHROW_MOVE
+ #define BOOST_MOVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE(T) BOOST_MOVE_HAS_NOTHROW_MOVE(T)
+#else
+ #define BOOST_MOVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE(T) ::boost::move_detail::is_pod<T>::value
+#endif
+
+#ifdef BOOST_MOVE_HAS_NOTHROW_ASSIGN
+ #define BOOST_MOVE_IS_NOTHROW_COPY_ASSIGNABLE(T) BOOST_MOVE_HAS_NOTHROW_ASSIGN(T)
+#else
+ #define BOOST_MOVE_IS_NOTHROW_COPY_ASSIGNABLE(T) ::boost::move_detail::is_pod<T>::value
+#endif
+
+#ifdef BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN
+ #define BOOST_MOVE_IS_NOTHROW_MOVE_ASSIGNABLE(T) BOOST_MOVE_HAS_NOTHROW_MOVE_ASSIGN(T)
+#else
+ #define BOOST_MOVE_IS_NOTHROW_MOVE_ASSIGNABLE(T) ::boost::move_detail::is_pod<T>::value
+#endif
+
+#ifdef BOOST_MOVE_IS_ENUM
+ #define BOOST_MOVE_IS_ENUM_IMPL(T) BOOST_MOVE_IS_ENUM(T)
+#else
+ #define BOOST_MOVE_IS_ENUM_IMPL(T) ::boost::move_detail::is_enum_nonintrinsic<T>::value
+#endif
+
+namespace boost {
+namespace move_detail {
+
+//////////////////////////
+// is_reference
+//////////////////////////
+template<class T>
+struct is_reference
+{ static const bool value = false; };
+
+template<class T>
+struct is_reference<T&>
+{ static const bool value = true; };
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+template<class T>
+struct is_reference<T&&>
+{ static const bool value = true; };
+#endif
+
+//////////////////////////
+// is_pointer
+//////////////////////////
+template<class T>
+struct is_pointer
+{ static const bool value = false; };
+
+template<class T>
+struct is_pointer<T*>
+{ static const bool value = true; };
+
+//////////////////////////
+// is_const
+//////////////////////////
+template<class T>
+struct is_const
+{ static const bool value = false; };
+
+template<class T>
+struct is_const<const T>
+{ static const bool value = true; };
+
+//////////////////////////
+// unvoid_ref
+//////////////////////////
+template <typename T> struct unvoid_ref : add_lvalue_reference<T>{};
+template <> struct unvoid_ref<void> { typedef unvoid_ref & type; };
+template <> struct unvoid_ref<const void> { typedef unvoid_ref & type; };
+template <> struct unvoid_ref<volatile void> { typedef unvoid_ref & type; };
+template <> struct unvoid_ref<const volatile void> { typedef unvoid_ref & type; };
+
+template <typename T>
+struct add_reference : add_lvalue_reference<T>
+{};
+
+//////////////////////////
+// add_const_reference
+//////////////////////////
+template <class T>
+struct add_const_reference
+{ typedef const T &type; };
+
+template <class T>
+struct add_const_reference<T&>
+{ typedef T& type; };
+
+//////////////////////////
+// add_const_if_c
+//////////////////////////
+template<class T, bool Add>
+struct add_const_if_c
+ : if_c<Add, typename add_const<T>::type, T>
+{};
+
+//////////////////////////
+// remove_const
+//////////////////////////
+template<class T>
+struct remove_const
+{ typedef T type; };
+
+template<class T>
+struct remove_const< const T>
+{ typedef T type; };
+
+//////////////////////////
+// remove_cv
+//////////////////////////
+template<typename T> struct remove_cv { typedef T type; };
+template<typename T> struct remove_cv<const T> { typedef T type; };
+template<typename T> struct remove_cv<const volatile T> { typedef T type; };
+template<typename T> struct remove_cv<volatile T> { typedef T type; };
+
+//////////////////////////
+// make_unsigned
+//////////////////////////
+template <class T>
+struct make_unsigned_impl { typedef T type; };
+template <> struct make_unsigned_impl<signed char> { typedef unsigned char type; };
+template <> struct make_unsigned_impl<signed short> { typedef unsigned short type; };
+template <> struct make_unsigned_impl<signed int> { typedef unsigned int type; };
+template <> struct make_unsigned_impl<signed long> { typedef unsigned long type; };
+#ifdef BOOST_HAS_LONG_LONG
+template <> struct make_unsigned_impl< ::boost::long_long_type > { typedef ::boost::ulong_long_type type; };
+#endif
+
+template <class T>
+struct make_unsigned
+ : make_unsigned_impl<typename remove_cv<T>::type>
+{};
+
+//////////////////////////
+// is_floating_point
+//////////////////////////
+template<class T> struct is_floating_point_cv { static const bool value = false; };
+template<> struct is_floating_point_cv<float> { static const bool value = true; };
+template<> struct is_floating_point_cv<double> { static const bool value = true; };
+template<> struct is_floating_point_cv<long double> { static const bool value = true; };
+
+template<class T>
+struct is_floating_point
+ : is_floating_point_cv<typename remove_cv<T>::type>
+{};
+
+//////////////////////////
+// is_integral
+//////////////////////////
+template<class T> struct is_integral_cv { static const bool value = false; };
+template<> struct is_integral_cv< bool>{ static const bool value = true; };
+template<> struct is_integral_cv< char>{ static const bool value = true; };
+template<> struct is_integral_cv< unsigned char>{ static const bool value = true; };
+template<> struct is_integral_cv< signed char>{ static const bool value = true; };
+#ifndef BOOST_NO_CXX11_CHAR16_T
+template<> struct is_integral_cv< char16_t>{ static const bool value = true; };
+#endif
+#ifndef BOOST_NO_CXX11_CHAR32_T
+template<> struct is_integral_cv< char32_t>{ static const bool value = true; };
+#endif
+#ifndef BOOST_NO_INTRINSIC_WCHAR_T
+template<> struct is_integral_cv< wchar_t>{ static const bool value = true; };
+#endif
+template<> struct is_integral_cv< short>{ static const bool value = true; };
+template<> struct is_integral_cv< unsigned short>{ static const bool value = true; };
+template<> struct is_integral_cv< int>{ static const bool value = true; };
+template<> struct is_integral_cv< unsigned int>{ static const bool value = true; };
+template<> struct is_integral_cv< long>{ static const bool value = true; };
+template<> struct is_integral_cv< unsigned long>{ static const bool value = true; };
+#ifdef BOOST_HAS_LONG_LONG
+template<> struct is_integral_cv< ::boost:: long_long_type>{ static const bool value = true; };
+template<> struct is_integral_cv< ::boost::ulong_long_type>{ static const bool value = true; };
+#endif
+
+template<class T>
+struct is_integral
+ : public is_integral_cv<typename remove_cv<T>::type>
+{};
+
+//////////////////////////////////////
+// remove_all_extents
+//////////////////////////////////////
+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;};
+
+//////////////////////////
+// is_scalar
+//////////////////////////
+template<class T>
+struct is_scalar
+{ static const bool value = is_integral<T>::value || is_floating_point<T>::value; };
+
+//////////////////////////
+// is_void
+//////////////////////////
+template<class T>
+struct is_void_cv
+{ static const bool value = false; };
+
+template<>
+struct is_void_cv<void>
+{ static const bool value = true; };
+
+template<class T>
+struct is_void
+ : is_void_cv<typename remove_cv<T>::type>
+{};
+
+//////////////////////////////////////
+// is_array
+//////////////////////////////////////
+template<class T>
+struct is_array
+{ static const bool value = false; };
+
+template<class T>
+struct is_array<T[]>
+{ static const bool value = true; };
+
+template<class T, std::size_t N>
+struct is_array<T[N]>
+{ static const bool value = true; };
+
+//////////////////////////////////////
+// is_member_pointer
+//////////////////////////////////////
+template <class T> struct is_member_pointer_cv { static const bool value = false; };
+template <class T, class U>struct is_member_pointer_cv<T U::*> { static const bool value = true; };
+
+template <class T>
+struct is_member_pointer
+ : is_member_pointer_cv<typename remove_cv<T>::type>
+{};
+
+//////////////////////////////////////
+// is_nullptr_t
+//////////////////////////////////////
+template <class T>
+struct is_nullptr_t_cv
+{ static const bool value = false; };
+
+#if !defined(BOOST_NO_CXX11_NULLPTR)
+template <>
+struct is_nullptr_t_cv
+ #if !defined(BOOST_NO_CXX11_DECLTYPE)
+ <decltype(nullptr)>
+ #else
+ <std::nullptr_t>
+ #endif
+{ static const bool value = true; };
+#endif
+
+template <class T>
+struct is_nullptr_t
+ : is_nullptr_t_cv<typename remove_cv<T>::type>
+{};
+
+//////////////////////////////////////
+// is_function
+//////////////////////////////////////
+//Inspired by libc++, thanks to Howard Hinnant
+//For a function to pointer an lvalue of function type T can be implicitly converted to a prvalue
+//pointer to that function. This does not apply to non-static member functions because lvalues
+//that refer to non-static member functions do not exist.
+template <class T>
+struct is_reference_convertible_to_pointer
+{
+ struct twochar { char dummy[2]; };
+ template <class U> static char test(U*);
+ template <class U> static twochar test(...);
+ static T& source();
+ static const bool value = sizeof(char) == sizeof(test<T>(source()));
+};
+//Filter out:
+// - class types that might have implicit conversions
+// - void (to avoid forming a reference to void later)
+// - references (e.g.: filtering reference to functions)
+// - nullptr_t (convertible to pointer)
+template < class T
+ , bool Filter = is_class_or_union<T>::value ||
+ is_void<T>::value ||
+ is_reference<T>::value ||
+ is_nullptr_t<T>::value >
+struct is_function_impl
+{ static const bool value = is_reference_convertible_to_pointer<T>::value; };
+
+template <class T>
+struct is_function_impl<T, true>
+{ static const bool value = false; };
+
+template <class T>
+struct is_function
+ : is_function_impl<T>
+{};
+
+//////////////////////////////////////
+// is_union
+//////////////////////////////////////
+template<class T>
+struct is_union_noextents_cv
+{ static const bool value = BOOST_MOVE_IS_UNION_IMPL(T); };
+
+template<class T>
+struct is_union
+ : is_union_noextents_cv<typename remove_cv<typename remove_all_extents<T>::type>::type>
+{};
+
+//////////////////////////////////////
+// is_class
+//////////////////////////////////////
+template <class T>
+struct is_class
+{
+ static const bool value = is_class_or_union<T>::value && ! is_union<T>::value;
+};
+
+
+//////////////////////////////////////
+// is_arithmetic
+//////////////////////////////////////
+template <class T>
+struct is_arithmetic
+{
+ static const bool value = is_floating_point<T>::value ||
+ is_integral<T>::value;
+};
+
+//////////////////////////////////////
+// is_member_function_pointer
+//////////////////////////////////////
+template <class T>
+struct is_member_function_pointer_cv
+{
+ static const bool value = false;
+};
+
+template <class T, class C>
+struct is_member_function_pointer_cv<T C::*>
+ : is_function<T>
+{};
+
+template <class T>
+struct is_member_function_pointer
+ : is_member_function_pointer_cv<typename remove_cv<T>::type>
+{};
+
+//////////////////////////////////////
+// is_enum
+//////////////////////////////////////
+#if !defined(BOOST_MOVE_IS_ENUM)
+//Based on (http://howardhinnant.github.io/TypeHiearchy.pdf)
+template <class T>
+struct is_enum_nonintrinsic
+{
+ static const bool value = !is_arithmetic<T>::value &&
+ !is_reference<T>::value &&
+ !is_class_or_union<T>::value &&
+ !is_array<T>::value &&
+ !is_void<T>::value &&
+ !is_nullptr_t<T>::value &&
+ !is_member_pointer<T>::value &&
+ !is_pointer<T>::value &&
+ !is_function<T>::value;
+};
+#endif
+
+template <class T>
+struct is_enum
+{ static const bool value = BOOST_MOVE_IS_ENUM_IMPL(T); };
+
+//////////////////////////////////////
+// is_pod
+//////////////////////////////////////
+template<class T>
+struct is_pod_noextents_cv //for non-c++11 compilers, a safe fallback
+{ static const bool value = BOOST_MOVE_IS_POD_IMPL(T); };
+
+template<class T>
+struct is_pod
+ : is_pod_noextents_cv<typename remove_cv<typename remove_all_extents<T>::type>::type>
+{};
+
+//////////////////////////////////////
+// is_empty
+//////////////////////////////////////
+#if !defined(BOOST_MOVE_IS_EMPTY)
+
+template <typename T>
+struct empty_helper_t1 : public T
+{
+ empty_helper_t1(); // hh compiler bug workaround
+ int i[256];
+ private:
+
+ empty_helper_t1(const empty_helper_t1&);
+ empty_helper_t1& operator=(const empty_helper_t1&);
+};
+
+struct empty_helper_t2 { int i[256]; };
+
+template <typename T, bool IsClass = is_class<T>::value >
+struct is_empty_nonintrinsic
+{
+ static const bool value = false;
+};
+
+template <typename T>
+struct is_empty_nonintrinsic<T, true>
+{
+ static const bool value = sizeof(empty_helper_t1<T>) == sizeof(empty_helper_t2);
+};
+#endif
+
+template <class T>
+struct is_empty
+{ static const bool value = BOOST_MOVE_IS_EMPTY_IMPL(T); };
+
+
+template<class T>
+struct has_boost_move_no_copy_constructor_or_assign_type
+{
+ template <class U>
+ static yes_type test(typename U::boost_move_no_copy_constructor_or_assign*);
+
+ template <class U>
+ static no_type test(...);
+
+ static const bool value = sizeof(test<T>(0)) == sizeof(yes_type);
+};
+
+//////////////////////////////////////
+// is_copy_constructible
+//////////////////////////////////////
+#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) && !defined(BOOST_NO_CXX11_DECLTYPE) \
+ && !defined(BOOST_INTEL_CXX_VERSION) && \
+ !(defined(BOOST_MSVC) && _MSC_VER == 1800)
+#define BOOST_MOVE_TT_CXX11_IS_COPY_CONSTRUCTIBLE
+#endif
+
+template<class T>
+struct is_copy_constructible
+{
+ // Intel compiler has problems with SFINAE for copy constructors and deleted functions:
+ //
+ // error: function *function_name* cannot be referenced -- it is a deleted function
+ // static yes_type test(U&, decltype(U(boost::declval<U&>()))* = 0);
+ // ^
+ // MSVC 12.0 (Visual 2013) has problems when the copy constructor has been deleted. See:
+ // https://connect.microsoft.com/VisualStudio/feedback/details/800328/std-is-copy-constructible-is-broken
+ #if defined(BOOST_MOVE_TT_CXX11_IS_COPY_CONSTRUCTIBLE)
+ template<class U> static typename add_reference<U>::type source();
+ static no_type test(...);
+ #ifdef BOOST_NO_CXX11_DECLTYPE
+ template <class U>
+ static yes_type test(U&, bool_<sizeof(U(source<U>()))>* = 0);
+ #else
+ template <class U>
+ static yes_type test(U&, decltype(U(source<U>()))* = 0);
+ #endif
+ static const bool value = sizeof(test(source<T>())) == sizeof(yes_type);
+ #else
+ static const bool value = !has_boost_move_no_copy_constructor_or_assign_type<T>::value;
+ #endif
+};
+
+
+//////////////////////////////////////
+// is_copy_assignable
+//////////////////////////////////////
+#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) && !defined(BOOST_NO_CXX11_DECLTYPE) \
+ && !defined(BOOST_INTEL_CXX_VERSION) && \
+ !(defined(BOOST_MSVC) && _MSC_VER == 1800)
+#define BOOST_MOVE_TT_CXX11_IS_COPY_ASSIGNABLE
+#endif
+
+template <class T>
+struct is_copy_assignable
+{
+// Intel compiler has problems with SFINAE for copy constructors and deleted functions:
+//
+// error: function *function_name* cannot be referenced -- it is a deleted function
+// static boost::type_traits::yes_type test(T1&, decltype(T1(boost::declval<T1&>()))* = 0);
+// ^
+//
+// MSVC 12.0 (Visual 2013) has problems when the copy constructor has been deleted. See:
+// https://connect.microsoft.com/VisualStudio/feedback/details/800328/std-is-copy-constructible-is-broken
+#if defined(BOOST_MOVE_TT_CXX11_IS_COPY_ASSIGNABLE)
+ typedef char yes_type;
+ struct no_type { char dummy[2]; };
+
+ template <class U> static typename add_reference<U>::type source();
+ template <class U> static decltype(source<U&>() = source<const U&>(), yes_type() ) test(int);
+ template <class> static no_type test(...);
+
+ static const bool value = sizeof(test<T>(0)) == sizeof(yes_type);
+#else
+ static const bool value = !has_boost_move_no_copy_constructor_or_assign_type<T>::value;
+#endif
+};
+
+//////////////////////////////////////
+// is_trivially_destructible
+//////////////////////////////////////
+template<class T>
+struct is_trivially_destructible
+{ static const bool value = BOOST_MOVE_IS_TRIVIALLY_DESTRUCTIBLE(T); };
+
+//////////////////////////////////////
+// is_trivially_default_constructible
+//////////////////////////////////////
+template<class T>
+struct is_trivially_default_constructible
+{ static const bool value = BOOST_MOVE_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE(T); };
+
+//////////////////////////////////////
+// is_trivially_copy_constructible
+//////////////////////////////////////
+template<class T>
+struct is_trivially_copy_constructible
+{
+ //In several compilers BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE return true even with
+ //deleted copy constructors so make sure the type is copy constructible.
+ static const bool value = ::boost::move_detail::is_pod<T>::value ||
+ ( ::boost::move_detail::is_copy_constructible<T>::value &&
+ BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) );
+};
+
+//////////////////////////////////////
+// is_trivially_move_constructible
+//////////////////////////////////////
+template<class T>
+struct is_trivially_move_constructible
+{ static const bool value = BOOST_MOVE_IS_TRIVIALLY_MOVE_CONSTRUCTIBLE(T); };
+
+//////////////////////////////////////
+// is_trivially_copy_assignable
+//////////////////////////////////////
+template<class T>
+struct is_trivially_copy_assignable
+{
+ //In several compilers BOOST_MOVE_IS_TRIVIALLY_COPY_CONSTRUCTIBLE return true even with
+ //deleted copy constructors so make sure the type is copy constructible.
+ static const bool value = ::boost::move_detail::is_pod<T>::value ||
+ ( ::boost::move_detail::is_copy_assignable<T>::value &&
+ BOOST_MOVE_IS_TRIVIALLY_COPY_ASSIGNABLE(T) );
+};
+
+//////////////////////////////////////
+// is_trivially_move_assignable
+//////////////////////////////////////
+template<class T>
+struct is_trivially_move_assignable
+{ static const bool value = BOOST_MOVE_IS_TRIVIALLY_MOVE_ASSIGNABLE(T); };
+
+//////////////////////////////////////
+// is_nothrow_default_constructible
+//////////////////////////////////////
+template<class T>
+struct is_nothrow_default_constructible
+ : is_pod<T>
+{ static const bool value = BOOST_MOVE_IS_NOTHROW_DEFAULT_CONSTRUCTIBLE(T); };
+
+//////////////////////////////////////
+// is_nothrow_copy_constructible
+//////////////////////////////////////
+template<class T>
+struct is_nothrow_copy_constructible
+{ static const bool value = BOOST_MOVE_IS_NOTHROW_COPY_CONSTRUCTIBLE(T); };
+
+//////////////////////////////////////
+// is_nothrow_move_constructible
+//////////////////////////////////////
+template<class T>
+struct is_nothrow_move_constructible
+{ static const bool value = BOOST_MOVE_IS_NOTHROW_MOVE_CONSTRUCTIBLE(T); };
+
+//////////////////////////////////////
+// is_nothrow_copy_assignable
+//////////////////////////////////////
+template<class T>
+struct is_nothrow_copy_assignable
+{ static const bool value = BOOST_MOVE_IS_NOTHROW_COPY_ASSIGNABLE(T); };
+
+//////////////////////////////////////
+// is_nothrow_move_assignable
+//////////////////////////////////////
+template<class T>
+struct is_nothrow_move_assignable
+{ static const bool value = BOOST_MOVE_IS_NOTHROW_MOVE_ASSIGNABLE(T); };
+
+//////////////////////////////////////
+// is_nothrow_swappable
+//////////////////////////////////////
+template<class T>
+struct is_nothrow_swappable
+{
+ static const bool value = is_empty<T>::value || is_pod<T>::value;
+};
+
+//////////////////////////////////////
+// alignment_of
+//////////////////////////////////////
+template <typename T>
+struct alignment_of_hack
+{
+ T t1;
+ char c;
+ T t2;
+ alignment_of_hack();
+};
+
+template <unsigned A, unsigned S>
+struct alignment_logic
+{ static const std::size_t value = A < S ? A : S; };
+
+template< typename T >
+struct alignment_of_impl
+#if defined(BOOST_MSVC) && (BOOST_MSVC >= 1400)
+ // With MSVC both the native __alignof operator
+ // and our own logic gets things wrong from time to time :-(
+ // Using a combination of the two seems to make the most of a bad job:
+ : alignment_logic< sizeof(alignment_of_hack<T>) - 2*sizeof(T), __alignof(T)>
+{};
+#elif !defined(BOOST_MOVE_ALIGNMENT_OF)
+ : alignment_logic< sizeof(alignment_of_hack<T>) - 2*sizeof(T), sizeof(T)>
+{};
+#else
+{ static const std::size_t value = BOOST_MOVE_ALIGNMENT_OF(T); };
+#endif
+
+template< typename T >
+struct alignment_of
+ : alignment_of_impl<T>
+{};
+
+class alignment_dummy;
+typedef void (*function_ptr)();
+typedef int (alignment_dummy::*member_ptr);
+typedef int (alignment_dummy::*member_function_ptr)();
+struct alignment_struct
+{ long double dummy[4]; };
+
+/////////////////////////////
+// max_align_t
+/////////////////////////////
+//This is not standard, but should work with all compilers
+union max_align
+{
+ char char_;
+ short short_;
+ int int_;
+ long long_;
+ #ifdef BOOST_HAS_LONG_LONG
+ ::boost::long_long_type long_long_;
+ #endif
+ float float_;
+ double double_;
+ void * void_ptr_;
+ long double long_double_[4];
+ alignment_dummy *unknown_class_ptr_;
+ function_ptr function_ptr_;
+ member_function_ptr member_function_ptr_;
+ alignment_struct alignment_struct_;
+};
+
+typedef union max_align max_align_t;
+
+/////////////////////////////
+// aligned_storage
+/////////////////////////////
+
+#if !defined(BOOST_NO_ALIGNMENT)
+
+template<std::size_t Len, std::size_t Align>
+struct aligned_storage_impl;
+
+#define BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(A)\
+template<std::size_t Len>\
+struct BOOST_ALIGNMENT(A) aligned_storage_impl<Len, A>\
+{\
+ char dummy[Len];\
+ typedef aligned_storage_impl<Len, A> type;\
+};\
+//
+
+//Up to 4K alignment (typical page size)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x1)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x2)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x4)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x8)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x10)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x20)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x40)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x80)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x100)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x200)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x400)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x800)
+BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT(0x1000)
+
+#undef BOOST_MOVE_ALIGNED_STORAGE_WITH_BOOST_ALIGNMENT
+
+#else //BOOST_NO_ALIGNMENT
+
+template<class T, std::size_t Len>
+union aligned_union
+{
+ T aligner;
+ char dummy[Len];
+};
+
+template<std::size_t Len, std::size_t Align, class T, bool Ok>
+struct aligned_next;
+
+template<std::size_t Len, std::size_t Align, class T>
+struct aligned_next<Len, Align, T, true>
+{
+ BOOST_STATIC_ASSERT((alignment_of<T>::value == Align));
+ typedef aligned_union<T, Len> type;
+};
+
+//End of search defaults to max_align_t
+template<std::size_t Len, std::size_t Align>
+struct aligned_next<Len, Align, max_align_t, false>
+{ typedef aligned_union<max_align_t, Len> type; };
+
+//Now define a search list through types
+#define BOOST_MOVE_ALIGNED_NEXT_STEP(TYPE, NEXT_TYPE)\
+ template<std::size_t Len, std::size_t Align>\
+ struct aligned_next<Len, Align, TYPE, false>\
+ : aligned_next<Len, Align, NEXT_TYPE, Align == alignment_of<NEXT_TYPE>::value>\
+ {};\
+ //
+ BOOST_MOVE_ALIGNED_NEXT_STEP(long double, max_align_t)
+ BOOST_MOVE_ALIGNED_NEXT_STEP(double, long double)
+ #ifdef BOOST_HAS_LONG_LONG
+ BOOST_MOVE_ALIGNED_NEXT_STEP(::boost::long_long_type, double)
+ BOOST_MOVE_ALIGNED_NEXT_STEP(long, ::boost::long_long_type)
+ #else
+ BOOST_MOVE_ALIGNED_NEXT_STEP(long, double)
+ #endif
+ BOOST_MOVE_ALIGNED_NEXT_STEP(int, long)
+ BOOST_MOVE_ALIGNED_NEXT_STEP(short, int)
+ BOOST_MOVE_ALIGNED_NEXT_STEP(char, short)
+#undef BOOST_MOVE_ALIGNED_NEXT_STEP
+
+template<std::size_t Len, std::size_t Align>
+struct aligned_storage_impl
+ : aligned_next<Len, Align, char, Align == alignment_of<char>::value>
+{};
+
+#endif
+
+template<std::size_t Len, std::size_t Align = alignment_of<max_align_t>::value>
+struct aligned_storage
+{
+ //Sanity checks for input parameters
+ BOOST_STATIC_ASSERT(Align > 0);
+
+ //Sanity checks for output type
+ typedef typename aligned_storage_impl<Len ? Len : 1, Align>::type type;
+ static const std::size_t value = alignment_of<type>::value;
+ BOOST_STATIC_ASSERT(value >= Align);
+ BOOST_STATIC_ASSERT((value % Align) == 0);
+
+ //Just in case someone instantiates aligned_storage
+ //instead of aligned_storage::type (typical error).
+ private:
+ aligned_storage();
+};
+
+} //namespace move_detail {
+} //namespace boost {
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_DETAIL_TYPE_TRAITS_HPP
diff --git a/third_party/boost/boost/move/detail/workaround.hpp b/third_party/boost/boost/move/detail/workaround.hpp
new file mode 100644
index 0000000..b3f81b1
--- /dev/null
+++ b/third_party/boost/boost/move/detail/workaround.hpp
@@ -0,0 +1,55 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2014-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)
+//
+// See http://www.boost.org/libs/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_MOVE_DETAIL_WORKAROUND_HPP
+#define BOOST_MOVE_DETAIL_WORKAROUND_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ #define BOOST_MOVE_PERFECT_FORWARDING
+#endif
+
+#if defined(__has_feature)
+ #define BOOST_MOVE_HAS_FEATURE __has_feature
+#else
+ #define BOOST_MOVE_HAS_FEATURE(x) 0
+#endif
+
+#if BOOST_MOVE_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
+ #define BOOST_MOVE_ADDRESS_SANITIZER_ON
+#endif
+
+//Macros for documentation purposes. For code, expands to the argument
+#define BOOST_MOVE_IMPDEF(TYPE) TYPE
+#define BOOST_MOVE_SEEDOC(TYPE) TYPE
+#define BOOST_MOVE_DOC0PTR(TYPE) TYPE
+#define BOOST_MOVE_DOC1ST(TYPE1, TYPE2) TYPE2
+#define BOOST_MOVE_I ,
+#define BOOST_MOVE_DOCIGN(T1) T1
+
+#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 5) && !defined(__clang__)
+ //Pre-standard rvalue binding rules
+ #define BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
+#elif defined(_MSC_VER) && (_MSC_VER == 1600)
+ //Standard rvalue binding rules but with some bugs
+ #define BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG
+ #define BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG
+#elif defined(_MSC_VER) && (_MSC_VER == 1700)
+ #define BOOST_MOVE_MSVC_AUTO_MOVE_RETURN_BUG
+#endif
+
+#endif //#ifndef BOOST_MOVE_DETAIL_WORKAROUND_HPP
diff --git a/third_party/boost/boost/move/iterator.hpp b/third_party/boost/boost/move/iterator.hpp
new file mode 100644
index 0000000..1b39e26
--- /dev/null
+++ b/third_party/boost/boost/move/iterator.hpp
@@ -0,0 +1,312 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+
+#ifndef BOOST_MOVE_ITERATOR_HPP
+#define BOOST_MOVE_ITERATOR_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/detail/iterator_traits.hpp>
+#include <boost/move/utility_core.hpp>
+
+namespace boost {
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// move_iterator
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! Class template move_iterator is an iterator adaptor with the same behavior
+//! as the underlying iterator except that its dereference operator implicitly
+//! converts the value returned by the underlying iterator's dereference operator
+//! to an rvalue reference. Some generic algorithms can be called with move
+//! iterators to replace copying with moving.
+template <class It>
+class move_iterator
+{
+ public:
+ typedef It iterator_type;
+ typedef typename boost::movelib::iterator_traits<iterator_type>::value_type value_type;
+ #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_MOVE_DOXYGEN_INVOKED)
+ typedef value_type && reference;
+ #else
+ typedef typename ::boost::move_detail::if_
+ < ::boost::has_move_emulation_enabled<value_type>
+ , ::boost::rv<value_type>&
+ , value_type & >::type reference;
+ #endif
+ typedef It pointer;
+ typedef typename boost::movelib::iterator_traits<iterator_type>::difference_type difference_type;
+ typedef typename boost::movelib::iterator_traits<iterator_type>::iterator_category iterator_category;
+
+ move_iterator()
+ {}
+
+ explicit move_iterator(It i)
+ : m_it(i)
+ {}
+
+ template <class U>
+ move_iterator(const move_iterator<U>& u)
+ : m_it(u.base())
+ {}
+
+ iterator_type base() const
+ { return m_it; }
+
+ reference operator*() const
+ {
+ #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
+ return *m_it;
+ #else
+ return ::boost::move(*m_it);
+ #endif
+ }
+
+ pointer operator->() const
+ { return m_it; }
+
+ move_iterator& operator++()
+ { ++m_it; return *this; }
+
+ move_iterator<iterator_type> operator++(int)
+ { move_iterator<iterator_type> tmp(*this); ++(*this); return tmp; }
+
+ move_iterator& operator--()
+ { --m_it; return *this; }
+
+ move_iterator<iterator_type> operator--(int)
+ { move_iterator<iterator_type> tmp(*this); --(*this); return tmp; }
+
+ move_iterator<iterator_type> operator+ (difference_type n) const
+ { return move_iterator<iterator_type>(m_it + n); }
+
+ move_iterator& operator+=(difference_type n)
+ { m_it += n; return *this; }
+
+ move_iterator<iterator_type> operator- (difference_type n) const
+ { return move_iterator<iterator_type>(m_it - n); }
+
+ move_iterator& operator-=(difference_type n)
+ { m_it -= n; return *this; }
+
+ reference operator[](difference_type n) const
+ {
+ #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
+ return m_it[n];
+ #else
+ return ::boost::move(m_it[n]);
+ #endif
+ }
+
+ friend bool operator==(const move_iterator& x, const move_iterator& y)
+ { return x.base() == y.base(); }
+
+ friend bool operator!=(const move_iterator& x, const move_iterator& y)
+ { return x.base() != y.base(); }
+
+ friend bool operator< (const move_iterator& x, const move_iterator& y)
+ { return x.base() < y.base(); }
+
+ friend bool operator<=(const move_iterator& x, const move_iterator& y)
+ { return x.base() <= y.base(); }
+
+ friend bool operator> (const move_iterator& x, const move_iterator& y)
+ { return x.base() > y.base(); }
+
+ friend bool operator>=(const move_iterator& x, const move_iterator& y)
+ { return x.base() >= y.base(); }
+
+ friend difference_type operator-(const move_iterator& x, const move_iterator& y)
+ { return x.base() - y.base(); }
+
+ friend move_iterator operator+(difference_type n, const move_iterator& x)
+ { return move_iterator(x.base() + n); }
+
+ private:
+ It m_it;
+};
+
+//is_move_iterator
+namespace move_detail {
+
+template <class I>
+struct is_move_iterator
+{
+ static const bool value = false;
+};
+
+template <class I>
+struct is_move_iterator< ::boost::move_iterator<I> >
+{
+ static const bool value = true;
+};
+
+} //namespace move_detail {
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// move_iterator
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//!
+//! <b>Returns</b>: move_iterator<It>(i).
+template<class It>
+inline move_iterator<It> make_move_iterator(const It &it)
+{ return move_iterator<It>(it); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// back_move_insert_iterator
+//
+//////////////////////////////////////////////////////////////////////////////
+
+
+//! A move insert iterator that move constructs elements at the
+//! back of a container
+template <typename C> // C models Container
+class back_move_insert_iterator
+{
+ C* container_m;
+
+ public:
+ typedef C container_type;
+ typedef typename C::value_type value_type;
+ typedef typename C::reference reference;
+ typedef typename C::pointer pointer;
+ typedef typename C::difference_type difference_type;
+ typedef std::output_iterator_tag iterator_category;
+
+ explicit back_move_insert_iterator(C& x) : container_m(&x) { }
+
+ back_move_insert_iterator& operator=(reference x)
+ { container_m->push_back(boost::move(x)); return *this; }
+
+ back_move_insert_iterator& operator=(BOOST_RV_REF(value_type) x)
+ { reference rx = x; return this->operator=(rx); }
+
+ back_move_insert_iterator& operator*() { return *this; }
+ back_move_insert_iterator& operator++() { return *this; }
+ back_move_insert_iterator& operator++(int) { return *this; }
+};
+
+//!
+//! <b>Returns</b>: back_move_insert_iterator<C>(x).
+template <typename C> // C models Container
+inline back_move_insert_iterator<C> back_move_inserter(C& x)
+{
+ return back_move_insert_iterator<C>(x);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// front_move_insert_iterator
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! A move insert iterator that move constructs elements int the
+//! front of a container
+template <typename C> // C models Container
+class front_move_insert_iterator
+{
+ C* container_m;
+
+public:
+ typedef C container_type;
+ typedef typename C::value_type value_type;
+ typedef typename C::reference reference;
+ typedef typename C::pointer pointer;
+ typedef typename C::difference_type difference_type;
+ typedef std::output_iterator_tag iterator_category;
+
+ explicit front_move_insert_iterator(C& x) : container_m(&x) { }
+
+ front_move_insert_iterator& operator=(reference x)
+ { container_m->push_front(boost::move(x)); return *this; }
+
+ front_move_insert_iterator& operator=(BOOST_RV_REF(value_type) x)
+ { reference rx = x; return this->operator=(rx); }
+
+ front_move_insert_iterator& operator*() { return *this; }
+ front_move_insert_iterator& operator++() { return *this; }
+ front_move_insert_iterator& operator++(int) { return *this; }
+};
+
+//!
+//! <b>Returns</b>: front_move_insert_iterator<C>(x).
+template <typename C> // C models Container
+inline front_move_insert_iterator<C> front_move_inserter(C& x)
+{
+ return front_move_insert_iterator<C>(x);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// insert_move_iterator
+//
+//////////////////////////////////////////////////////////////////////////////
+template <typename C> // C models Container
+class move_insert_iterator
+{
+ C* container_m;
+ typename C::iterator pos_;
+
+ public:
+ typedef C container_type;
+ typedef typename C::value_type value_type;
+ typedef typename C::reference reference;
+ typedef typename C::pointer pointer;
+ typedef typename C::difference_type difference_type;
+ typedef std::output_iterator_tag iterator_category;
+
+ explicit move_insert_iterator(C& x, typename C::iterator pos)
+ : container_m(&x), pos_(pos)
+ {}
+
+ move_insert_iterator& operator=(reference x)
+ {
+ pos_ = container_m->insert(pos_, ::boost::move(x));
+ ++pos_;
+ return *this;
+ }
+
+ move_insert_iterator& operator=(BOOST_RV_REF(value_type) x)
+ { reference rx = x; return this->operator=(rx); }
+
+ move_insert_iterator& operator*() { return *this; }
+ move_insert_iterator& operator++() { return *this; }
+ move_insert_iterator& operator++(int) { return *this; }
+};
+
+//!
+//! <b>Returns</b>: move_insert_iterator<C>(x, it).
+template <typename C> // C models Container
+inline move_insert_iterator<C> move_inserter(C& x, typename C::iterator it)
+{
+ return move_insert_iterator<C>(x, it);
+}
+
+} //namespace boost {
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_ITERATOR_HPP
diff --git a/third_party/boost/boost/move/move.hpp b/third_party/boost/boost/move/move.hpp
new file mode 100644
index 0000000..62dddbc
--- /dev/null
+++ b/third_party/boost/boost/move/move.hpp
@@ -0,0 +1,35 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright David Abrahams, Vicente Botet 2009.
+// (C) Copyright Ion Gaztanaga 2009-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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+//! A general library header that includes
+//! the rest of top-level headers.
+
+#ifndef BOOST_MOVE_MOVE_HPP
+#define BOOST_MOVE_MOVE_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/move/traits.hpp>
+#include <boost/move/algorithm.hpp>
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_MOVE_HPP
diff --git a/third_party/boost/boost/move/traits.hpp b/third_party/boost/boost/move/traits.hpp
new file mode 100644
index 0000000..b48b8f6
--- /dev/null
+++ b/third_party/boost/boost/move/traits.hpp
@@ -0,0 +1,77 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2009-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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+
+#ifndef BOOST_MOVE_TRAITS_HPP
+#define BOOST_MOVE_TRAITS_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+#include <boost/move/core.hpp>
+#endif
+#include <boost/move/detail/meta_utils.hpp>
+#include <boost/move/detail/type_traits.hpp>
+
+namespace boost {
+
+//! If this trait yields to true
+//! (<i>has_trivial_destructor_after_move <T>::value == true</i>)
+//! means that if T is used as argument of a move construction/assignment,
+//! there is no need to call T's destructor.
+//! This optimization tipically is used to improve containers' performance.
+//!
+//! By default this trait is true if the type has trivial destructor,
+//! every class should specialize this trait if it wants to improve performance
+//! when inserted in containers.
+template <class T>
+struct has_trivial_destructor_after_move
+ : ::boost::move_detail::is_trivially_destructible<T>
+{};
+
+//! By default this traits returns
+//! <pre>boost::is_nothrow_move_constructible<T>::value && boost::is_nothrow_move_assignable<T>::value </pre>.
+//! Classes with non-throwing move constructor
+//! and assignment can specialize this trait to obtain some performance improvements.
+template <class T>
+struct has_nothrow_move
+{
+ static const bool value = boost::move_detail::is_nothrow_move_constructible<T>::value &&
+ boost::move_detail::is_nothrow_move_assignable<T>::value;
+};
+
+namespace move_detail {
+
+template <class T>
+struct is_nothrow_move_constructible_or_uncopyable
+{
+ //The standard requires is_nothrow_move_constructible for move_if_noexcept
+ //but a user (usually in C++03) might specialize has_nothrow_move which includes it
+ static const bool value = is_nothrow_move_constructible<T>::value ||
+ has_nothrow_move<T>::value ||
+ !is_copy_constructible<T>::value;
+};
+
+} //move_detail {
+} //namespace boost {
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_TRAITS_HPP
diff --git a/third_party/boost/boost/move/utility.hpp b/third_party/boost/boost/move/utility.hpp
new file mode 100644
index 0000000..8f9c20b
--- /dev/null
+++ b/third_party/boost/boost/move/utility.hpp
@@ -0,0 +1,149 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+//! This header includes core utilities from <tt><boost/move/utility_core.hpp></tt> and defines
+//! some more advanced utilities such as:
+
+#ifndef BOOST_MOVE_MOVE_UTILITY_HPP
+#define BOOST_MOVE_MOVE_UTILITY_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/traits.hpp>
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+ namespace boost {
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // move_if_noexcept()
+ //
+ //////////////////////////////////////////////////////////////////////////////
+
+ template <class T>
+ inline typename ::boost::move_detail::enable_if_c
+ < enable_move_utility_emulation<T>::value && !has_move_emulation_enabled<T>::value
+ , typename ::boost::move_detail::add_const<T>::type &
+ >::type
+ move_if_noexcept(T& x) BOOST_NOEXCEPT
+ {
+ return x;
+ }
+
+ template <class T>
+ inline typename ::boost::move_detail::enable_if_c
+ < enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value
+ && ::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value, rv<T>&>::type
+ move_if_noexcept(T& x) BOOST_NOEXCEPT
+ {
+ return *static_cast<rv<T>* >(::boost::move_detail::addressof(x));
+ }
+
+ template <class T>
+ inline typename ::boost::move_detail::enable_if_c
+ < enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value
+ && ::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value
+ , rv<T>&
+ >::type
+ move_if_noexcept(rv<T>& x) BOOST_NOEXCEPT
+ {
+ return x;
+ }
+
+ template <class T>
+ inline typename ::boost::move_detail::enable_if_c
+ < enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value
+ && !::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value
+ , typename ::boost::move_detail::add_const<T>::type &
+ >::type
+ move_if_noexcept(T& x) BOOST_NOEXCEPT
+ {
+ return x;
+ }
+
+ template <class T>
+ inline typename ::boost::move_detail::enable_if_c
+ < enable_move_utility_emulation<T>::value && has_move_emulation_enabled<T>::value
+ && !::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value
+ , typename ::boost::move_detail::add_const<T>::type &
+ >::type
+ move_if_noexcept(rv<T>& x) BOOST_NOEXCEPT
+ {
+ return x;
+ }
+
+ } //namespace boost
+
+#else //#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+ #if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
+ #include <utility>
+
+ namespace boost{
+
+ using ::std::move_if_noexcept;
+
+ } //namespace boost
+
+ #else //!BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE
+
+ namespace boost {
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // move_if_noexcept()
+ //
+ //////////////////////////////////////////////////////////////////////////////
+ #if defined(BOOST_MOVE_DOXYGEN_INVOKED)
+ //! This function provides a way to convert a reference into a rvalue reference
+ //! in compilers with rvalue references. For other compilers converts T & into
+ //! <i>::boost::rv<T> &</i> so that move emulation is activated. Reference
+ //! would be converted to rvalue reference only if input type is nothrow move
+ //! constructible or if it has no copy constructor. In all other cases const
+ //! reference would be returned
+ template <class T>
+ rvalue_reference_or_const_lvalue_reference move_if_noexcept(input_reference) noexcept;
+
+ #else //BOOST_MOVE_DOXYGEN_INVOKED
+
+ template <class T>
+ typename ::boost::move_detail::enable_if_c
+ < ::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value, T&&>::type
+ move_if_noexcept(T& x) BOOST_NOEXCEPT
+ { return ::boost::move(x); }
+
+ template <class T>
+ typename ::boost::move_detail::enable_if_c
+ < !::boost::move_detail::is_nothrow_move_constructible_or_uncopyable<T>::value, const T&>::type
+ move_if_noexcept(T& x) BOOST_NOEXCEPT
+ { return x; }
+
+ #endif //BOOST_MOVE_DOXYGEN_INVOKED
+
+ } //namespace boost {
+
+ #endif //#if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
+
+#endif //BOOST_NO_CXX11_RVALUE_REFERENCES
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_MOVE_UTILITY_HPP
diff --git a/third_party/boost/boost/move/utility_core.hpp b/third_party/boost/boost/move/utility_core.hpp
new file mode 100644
index 0000000..1b932c3
--- /dev/null
+++ b/third_party/boost/boost/move/utility_core.hpp
@@ -0,0 +1,317 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-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)
+//
+// See http://www.boost.org/libs/move for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! \file
+//! This header defines core utilities to ease the development
+//! of move-aware functions. This header minimizes dependencies
+//! from other libraries.
+
+#ifndef BOOST_MOVE_MOVE_UTILITY_CORE_HPP
+#define BOOST_MOVE_MOVE_UTILITY_CORE_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/config_begin.hpp>
+#include <boost/move/core.hpp>
+#include <boost/move/detail/meta_utils.hpp>
+#include <boost/static_assert.hpp>
+
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+ namespace boost {
+
+ template<class T>
+ struct enable_move_utility_emulation
+ {
+ static const bool value = true;
+ };
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // move()
+ //
+ //////////////////////////////////////////////////////////////////////////////
+
+ template <class T>
+ inline typename ::boost::move_detail::enable_if_and
+ < T &
+ , enable_move_utility_emulation<T>
+ , has_move_emulation_disabled<T>
+ >::type
+ move(T& x) BOOST_NOEXCEPT
+ {
+ return x;
+ }
+
+ template <class T>
+ inline typename ::boost::move_detail::enable_if_and
+ < rv<T>&
+ , enable_move_utility_emulation<T>
+ , has_move_emulation_enabled<T>
+ >::type
+ move(T& x) BOOST_NOEXCEPT
+ {
+ return *BOOST_MOVE_TO_RV_CAST(::boost::rv<T>*, ::boost::move_detail::addressof(x) );
+ }
+
+ template <class T>
+ inline typename ::boost::move_detail::enable_if_and
+ < rv<T>&
+ , enable_move_utility_emulation<T>
+ , has_move_emulation_enabled<T>
+ >::type
+ move(rv<T>& x) BOOST_NOEXCEPT
+ {
+ return x;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // forward()
+ //
+ //////////////////////////////////////////////////////////////////////////////
+
+ template <class T>
+ inline typename ::boost::move_detail::enable_if_and
+ < T &
+ , enable_move_utility_emulation<T>
+ , ::boost::move_detail::is_rv<T>
+ >::type
+ forward(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT
+ {
+ return const_cast<T&>(x);
+ }
+
+ template <class T>
+ inline typename ::boost::move_detail::enable_if_and
+ < const T &
+ , enable_move_utility_emulation<T>
+ , ::boost::move_detail::is_not_rv<T>
+ >::type
+ forward(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT
+ {
+ return x;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // move_if_not_lvalue_reference()
+ //
+ //////////////////////////////////////////////////////////////////////////////
+
+ template <class T>
+ inline typename ::boost::move_detail::enable_if_and
+ < T &
+ , enable_move_utility_emulation<T>
+ , ::boost::move_detail::is_rv<T>
+ >::type
+ move_if_not_lvalue_reference(const typename ::boost::move_detail::identity<T>::type &x) BOOST_NOEXCEPT
+ {
+ return const_cast<T&>(x);
+ }
+
+ template <class T>
+ inline typename ::boost::move_detail::enable_if_and
+ < typename ::boost::move_detail::add_lvalue_reference<T>::type
+ , enable_move_utility_emulation<T>
+ , ::boost::move_detail::is_not_rv<T>
+ , ::boost::move_detail::or_
+ < ::boost::move_detail::is_lvalue_reference<T>
+ , has_move_emulation_disabled<T>
+ >
+ >::type
+ move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type &x) BOOST_NOEXCEPT
+ {
+ return x;
+ }
+
+ template <class T>
+ inline typename ::boost::move_detail::enable_if_and
+ < rv<T>&
+ , enable_move_utility_emulation<T>
+ , ::boost::move_detail::is_not_rv<T>
+ , ::boost::move_detail::and_
+ < ::boost::move_detail::not_< ::boost::move_detail::is_lvalue_reference<T> >
+ , has_move_emulation_enabled<T>
+ >
+ >::type
+ move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type &x) BOOST_NOEXCEPT
+ {
+ return move(x);
+ }
+
+ } //namespace boost
+
+#else //#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+ #if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
+ #include <utility>
+
+ namespace boost{
+
+ using ::std::move;
+ using ::std::forward;
+
+ } //namespace boost
+
+ #else //!BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE
+
+ namespace boost {
+
+ //! This trait's internal boolean `value` is false in compilers with rvalue references
+ //! and true in compilers without rvalue references.
+ //!
+ //! A user can specialize this trait for a type T to false to SFINAE out `move` and `forward`
+ //! so that the user can define a different move emulation for that type in namespace boost
+ //! (e.g. another Boost library for its types) and avoid any overload ambiguity.
+ template<class T>
+ struct enable_move_utility_emulation
+ {
+ static const bool value = false;
+ };
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // move
+ //
+ //////////////////////////////////////////////////////////////////////////////
+
+ #if defined(BOOST_MOVE_DOXYGEN_INVOKED)
+ //! This function provides a way to convert a reference into a rvalue reference
+ //! in compilers with rvalue references. For other compilers if `T` is Boost.Move
+ //! enabled type then it converts `T&` into <tt>::boost::rv<T> &</tt> so that
+ //! move emulation is activated, else it returns `T &`.
+ template <class T>
+ rvalue_reference move(input_reference) noexcept;
+
+ #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
+
+ //Old move approach, lvalues could bind to rvalue references
+ template <class T>
+ inline typename ::boost::move_detail::remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT
+ { return t; }
+
+ #else //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
+
+ template <class T>
+ inline typename ::boost::move_detail::remove_reference<T>::type && move(T&& t) BOOST_NOEXCEPT
+ { return static_cast<typename ::boost::move_detail::remove_reference<T>::type &&>(t); }
+
+ #endif //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // forward
+ //
+ //////////////////////////////////////////////////////////////////////////////
+
+
+ #if defined(BOOST_MOVE_DOXYGEN_INVOKED)
+ //! This function provides limited form of forwarding that is usually enough for
+ //! in-place construction and avoids the exponential overloading for
+ //! achieve the limited forwarding in C++03.
+ //!
+ //! For compilers with rvalue references this function provides perfect forwarding.
+ //!
+ //! Otherwise:
+ //! * If input_reference binds to const ::boost::rv<T> & then it output_reference is
+ //! ::boost::rv<T> &
+ //!
+ //! * Else, output_reference is equal to input_reference.
+ template <class T> output_reference forward(input_reference) noexcept;
+ #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
+
+ //Old move approach, lvalues could bind to rvalue references
+
+ template <class T>
+ inline T&& forward(typename ::boost::move_detail::identity<T>::type&& t) BOOST_NOEXCEPT
+ { return t; }
+
+ #else //Old move
+
+ template <class T>
+ inline T&& forward(typename ::boost::move_detail::remove_reference<T>::type& t) BOOST_NOEXCEPT
+ { return static_cast<T&&>(t); }
+
+ template <class T>
+ inline T&& forward(typename ::boost::move_detail::remove_reference<T>::type&& t) BOOST_NOEXCEPT
+ {
+ //"boost::forward<T> error: 'T' is a lvalue reference, can't forward as rvalue.";
+ BOOST_STATIC_ASSERT(!boost::move_detail::is_lvalue_reference<T>::value);
+ return static_cast<T&&>(t);
+ }
+
+ #endif //BOOST_MOVE_DOXYGEN_INVOKED
+
+ //////////////////////////////////////////////////////////////////////////////
+ //
+ // move_if_not_lvalue_reference
+ //
+ //////////////////////////////////////////////////////////////////////////////
+
+
+ #if defined(BOOST_MOVE_DOXYGEN_INVOKED)
+ //! <b>Effects</b>: Calls `boost::move` if `input_reference` is not a lvalue reference.
+ //! Otherwise returns the reference
+ template <class T> output_reference move_if_not_lvalue_reference(input_reference) noexcept;
+ #elif defined(BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES)
+
+ //Old move approach, lvalues could bind to rvalue references
+
+ template <class T>
+ inline T&& move_if_not_lvalue_reference(typename ::boost::move_detail::identity<T>::type&& t) BOOST_NOEXCEPT
+ { return t; }
+
+ #else //Old move
+
+ template <class T>
+ inline T&& move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type& t) BOOST_NOEXCEPT
+ { return static_cast<T&&>(t); }
+
+ template <class T>
+ inline T&& move_if_not_lvalue_reference(typename ::boost::move_detail::remove_reference<T>::type&& t) BOOST_NOEXCEPT
+ {
+ //"boost::forward<T> error: 'T' is a lvalue reference, can't forward as rvalue.";
+ BOOST_STATIC_ASSERT(!boost::move_detail::is_lvalue_reference<T>::value);
+ return static_cast<T&&>(t);
+ }
+
+ #endif //BOOST_MOVE_DOXYGEN_INVOKED
+
+ } //namespace boost {
+
+ #endif //#if defined(BOOST_MOVE_USE_STANDARD_LIBRARY_MOVE)
+
+#endif //BOOST_NO_CXX11_RVALUE_REFERENCES
+
+#if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+namespace boost{
+namespace move_detail{
+
+template <typename T>
+typename boost::move_detail::add_rvalue_reference<T>::type declval();
+
+} //namespace move_detail{
+} //namespace boost{
+
+#endif //#if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
+
+
+#include <boost/move/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_MOVE_MOVE_UTILITY_CORE_HPP
diff --git a/third_party/boost/boost/mpl/O1_size.hpp b/third_party/boost/boost/mpl/O1_size.hpp
new file mode 100644
index 0000000..517276e
--- /dev/null
+++ b/third_party/boost/boost/mpl/O1_size.hpp
@@ -0,0 +1,40 @@
+
+#ifndef BOOST_MPL_O1_SIZE_HPP_INCLUDED
+#define BOOST_MPL_O1_SIZE_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/O1_size_fwd.hpp>
+#include <boost/mpl/sequence_tag.hpp>
+#include <boost/mpl/aux_/O1_size_impl.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+
+namespace boost { namespace mpl {
+
+// returns sequence size if it's an O(1) operation; otherwise returns -1
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(Sequence)
+ >
+struct O1_size
+ : O1_size_impl< typename sequence_tag<Sequence>::type >
+ ::template apply< Sequence >
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1, O1_size, (Sequence))
+};
+
+BOOST_MPL_AUX_NA_SPEC(1, O1_size)
+
+}}
+
+#endif // BOOST_MPL_O1_SIZE_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/O1_size_fwd.hpp b/third_party/boost/boost/mpl/O1_size_fwd.hpp
new file mode 100644
index 0000000..bba2897
--- /dev/null
+++ b/third_party/boost/boost/mpl/O1_size_fwd.hpp
@@ -0,0 +1,24 @@
+
+#ifndef BOOST_MPL_O1_SIZE_FWD_HPP_INCLUDED
+#define BOOST_MPL_O1_SIZE_FWD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+namespace boost { namespace mpl {
+
+template< typename Tag > struct O1_size_impl;
+template< typename Sequence > struct O1_size;
+
+}}
+
+#endif // BOOST_MPL_O1_SIZE_FWD_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/advance.hpp b/third_party/boost/boost/mpl/advance.hpp
new file mode 100644
index 0000000..8cde024
--- /dev/null
+++ b/third_party/boost/boost/mpl/advance.hpp
@@ -0,0 +1,76 @@
+
+#ifndef BOOST_MPL_ADVANCE_HPP_INCLUDED
+#define BOOST_MPL_ADVANCE_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/advance_fwd.hpp>
+#include <boost/mpl/less.hpp>
+#include <boost/mpl/negate.hpp>
+#include <boost/mpl/long.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/tag.hpp>
+#include <boost/mpl/apply_wrap.hpp>
+#include <boost/mpl/aux_/advance_forward.hpp>
+#include <boost/mpl/aux_/advance_backward.hpp>
+#include <boost/mpl/aux_/value_wknd.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/nttp_decl.hpp>
+
+namespace boost { namespace mpl {
+
+// default implementation for forward/bidirectional iterators
+template< typename Tag >
+struct advance_impl
+{
+ template< typename Iterator, typename N > struct apply
+ {
+ typedef typename less< N,long_<0> >::type backward_;
+ typedef typename if_< backward_, negate<N>, N >::type offset_;
+
+ typedef typename if_<
+ backward_
+ , aux::advance_backward< BOOST_MPL_AUX_VALUE_WKND(offset_)::value >
+ , aux::advance_forward< BOOST_MPL_AUX_VALUE_WKND(offset_)::value >
+ >::type f_;
+
+ typedef typename apply_wrap1<f_,Iterator>::type type;
+ };
+};
+
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(Iterator)
+ , typename BOOST_MPL_AUX_NA_PARAM(N)
+ >
+struct advance
+ : advance_impl< typename tag<Iterator>::type >
+ ::template apply<Iterator,N>
+{
+};
+
+template<
+ typename Iterator
+ , BOOST_MPL_AUX_NTTP_DECL(long, N)
+ >
+struct advance_c
+ : advance_impl< typename tag<Iterator>::type >
+ ::template apply<Iterator,long_<N> >
+{
+};
+
+BOOST_MPL_AUX_NA_SPEC(2, advance)
+
+}}
+
+#endif // BOOST_MPL_ADVANCE_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/advance_fwd.hpp b/third_party/boost/boost/mpl/advance_fwd.hpp
new file mode 100644
index 0000000..5bf75a1
--- /dev/null
+++ b/third_party/boost/boost/mpl/advance_fwd.hpp
@@ -0,0 +1,28 @@
+
+#ifndef BOOST_MPL_ADVANCE_FWD_HPP_INCLUDED
+#define BOOST_MPL_ADVANCE_FWD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/common_name_wknd.hpp>
+
+namespace boost { namespace mpl {
+
+BOOST_MPL_AUX_COMMON_NAME_WKND(advance)
+
+template< typename Tag > struct advance_impl;
+template< typename Iterator, typename N > struct advance;
+
+}}
+
+#endif // BOOST_MPL_ADVANCE_FWD_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/always.hpp b/third_party/boost/boost/mpl/always.hpp
new file mode 100644
index 0000000..5863813
--- /dev/null
+++ b/third_party/boost/boost/mpl/always.hpp
@@ -0,0 +1,38 @@
+
+#ifndef BOOST_MPL_ALWAYS_HPP_INCLUDED
+#define BOOST_MPL_ALWAYS_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/preprocessor/default_params.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/mpl/aux_/arity_spec.hpp>
+
+namespace boost { namespace mpl {
+
+template< typename Value > struct always
+{
+ template<
+ BOOST_MPL_PP_DEFAULT_PARAMS(BOOST_MPL_LIMIT_METAFUNCTION_ARITY, typename T, na)
+ >
+ struct apply
+ {
+ typedef Value type;
+ };
+};
+
+BOOST_MPL_AUX_ARITY_SPEC(0, always)
+
+}}
+
+#endif // BOOST_MPL_ALWAYS_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/and.hpp b/third_party/boost/boost/mpl/and.hpp
new file mode 100644
index 0000000..6465ff0
--- /dev/null
+++ b/third_party/boost/boost/mpl/and.hpp
@@ -0,0 +1,60 @@
+
+#ifndef BOOST_MPL_AND_HPP_INCLUDED
+#define BOOST_MPL_AND_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/use_preprocessed.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE)
+
+# include <boost/mpl/bool.hpp>
+# include <boost/mpl/aux_/nested_type_wknd.hpp>
+# include <boost/mpl/aux_/na_spec.hpp>
+# include <boost/mpl/aux_/lambda_support.hpp>
+
+// agurt, 19/may/04: workaround a conflict with <iso646.h> header's
+// 'or' and 'and' macros, see http://tinyurl.com/3et69; 'defined(and)'
+// has to be checked in a separate condition, otherwise GCC complains
+// about 'and' being an alternative token
+#if defined(_MSC_VER) && !defined(__clang__)
+#ifndef __GCCXML__
+#if defined(and)
+# pragma push_macro("and")
+# undef and
+# define and(x)
+#endif
+#endif
+#endif
+
+# define BOOST_MPL_PREPROCESSED_HEADER and.hpp
+# include <boost/mpl/aux_/include_preprocessed.hpp>
+
+#if defined(_MSC_VER) && !defined(__clang__)
+#ifndef __GCCXML__
+#if defined(and)
+# pragma pop_macro("and")
+#endif
+#endif
+#endif
+
+#else
+
+# define AUX778076_OP_NAME and_
+# define AUX778076_OP_VALUE1 false
+# define AUX778076_OP_VALUE2 true
+# include <boost/mpl/aux_/logical_op.hpp>
+
+#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#endif // BOOST_MPL_AND_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/apply.hpp b/third_party/boost/boost/mpl/apply.hpp
new file mode 100644
index 0000000..06087ad
--- /dev/null
+++ b/third_party/boost/boost/mpl/apply.hpp
@@ -0,0 +1,229 @@
+
+#if !defined(BOOST_PP_IS_ITERATING)
+
+///// header body
+
+#ifndef BOOST_MPL_APPLY_HPP_INCLUDED
+#define BOOST_MPL_APPLY_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_PREPROCESSING_MODE)
+# include <boost/mpl/apply_fwd.hpp>
+# include <boost/mpl/apply_wrap.hpp>
+# include <boost/mpl/placeholders.hpp>
+# include <boost/mpl/lambda.hpp>
+# include <boost/mpl/aux_/na.hpp>
+# include <boost/mpl/aux_/lambda_support.hpp>
+#endif
+
+#include <boost/mpl/aux_/config/use_preprocessed.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE)
+
+# define BOOST_MPL_PREPROCESSED_HEADER apply.hpp
+# include <boost/mpl/aux_/include_preprocessed.hpp>
+
+#else
+
+# include <boost/mpl/limits/arity.hpp>
+# include <boost/mpl/aux_/preprocessor/params.hpp>
+# include <boost/mpl/aux_/preprocessor/default_params.hpp>
+# include <boost/mpl/aux_/preprocessor/partial_spec_params.hpp>
+# include <boost/mpl/aux_/preprocessor/enum.hpp>
+# include <boost/mpl/aux_/config/lambda.hpp>
+# include <boost/mpl/aux_/config/dtp.hpp>
+# include <boost/mpl/aux_/nttp_decl.hpp>
+# include <boost/mpl/aux_/config/eti.hpp>
+# include <boost/mpl/aux_/config/msvc.hpp>
+# include <boost/mpl/aux_/config/workaround.hpp>
+
+# include <boost/preprocessor/comma_if.hpp>
+# include <boost/preprocessor/inc.hpp>
+# include <boost/preprocessor/iterate.hpp>
+# include <boost/preprocessor/cat.hpp>
+
+namespace boost { namespace mpl {
+
+// local macros, #undef-ined at the end of the header
+# define AUX778076_APPLY_PARAMS(param) \
+ BOOST_MPL_PP_PARAMS( \
+ BOOST_MPL_LIMIT_METAFUNCTION_ARITY \
+ , param \
+ ) \
+ /**/
+
+# define AUX778076_APPLY_DEF_PARAMS(param, value) \
+ BOOST_MPL_PP_DEFAULT_PARAMS( \
+ BOOST_MPL_LIMIT_METAFUNCTION_ARITY \
+ , param \
+ , value \
+ ) \
+ /**/
+
+# define AUX778076_APPLY_N_PARAMS(n, param) \
+ BOOST_MPL_PP_PARAMS(n, param) \
+ /**/
+
+# define AUX778076_APPLY_N_COMMA_PARAMS(n, param) \
+ BOOST_PP_COMMA_IF(n) \
+ BOOST_MPL_PP_PARAMS(n, param) \
+ /**/
+
+# define AUX778076_APPLY_N_PARTIAL_SPEC_PARAMS(n, param, def) \
+ BOOST_PP_COMMA_IF(n) \
+ BOOST_MPL_PP_PARTIAL_SPEC_PARAMS(n, param, def) \
+ /**/
+
+# define AUX778076_APPLY_N_SPEC_PARAMS(n, param) \
+ BOOST_MPL_PP_ENUM(BOOST_PP_INC(n), param) \
+ /**/
+
+
+#define BOOST_PP_ITERATION_PARAMS_1 \
+ (3,(0, BOOST_MPL_LIMIT_METAFUNCTION_ARITY, <boost/mpl/apply.hpp>))
+#include BOOST_PP_ITERATE()
+
+# if !defined(BOOST_MPL_CFG_NO_APPLY_TEMPLATE)
+// real C++ version is already taken care of
+# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+
+namespace aux {
+// apply_count_args
+#define AUX778076_COUNT_ARGS_PREFIX apply
+#define AUX778076_COUNT_ARGS_DEFAULT na
+#define AUX778076_COUNT_ARGS_ARITY BOOST_MPL_LIMIT_METAFUNCTION_ARITY
+#include <boost/mpl/aux_/count_args.hpp>
+}
+
+
+template<
+ typename F, AUX778076_APPLY_DEF_PARAMS(typename T, na)
+ >
+struct apply
+ : aux::apply_chooser<
+ aux::apply_count_args< AUX778076_APPLY_PARAMS(T) >::value
+ >::template result_< F, AUX778076_APPLY_PARAMS(T) >::type
+{
+};
+
+# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+# endif // BOOST_MPL_CFG_NO_APPLY_TEMPLATE
+
+# undef AUX778076_APPLY_N_SPEC_PARAMS
+# undef AUX778076_APPLY_N_PARTIAL_SPEC_PARAMS
+# undef AUX778076_APPLY_N_COMMA_PARAMS
+# undef AUX778076_APPLY_N_PARAMS
+# undef AUX778076_APPLY_DEF_PARAMS
+# undef AUX778076_APPLY_PARAMS
+
+}}
+
+#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#endif // BOOST_MPL_APPLY_HPP_INCLUDED
+
+///// iteration, depth == 1
+
+// For gcc 4.4 compatability, we must include the
+// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
+#else // BOOST_PP_IS_ITERATING
+#if BOOST_PP_ITERATION_DEPTH() == 1
+
+# define i_ BOOST_PP_FRAME_ITERATION(1)
+
+template<
+ typename F AUX778076_APPLY_N_COMMA_PARAMS(i_, typename T)
+ >
+struct BOOST_PP_CAT(apply,i_)
+#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+ : BOOST_PP_CAT(apply_wrap,i_)<
+ typename lambda<F>::type
+ AUX778076_APPLY_N_COMMA_PARAMS(i_, T)
+ >
+{
+#else
+{
+ typedef typename BOOST_PP_CAT(apply_wrap,i_)<
+ typename lambda<F>::type
+ AUX778076_APPLY_N_COMMA_PARAMS(i_, T)
+ >::type type;
+#endif
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(
+ BOOST_PP_INC(i_)
+ , BOOST_PP_CAT(apply,i_)
+ , (F AUX778076_APPLY_N_COMMA_PARAMS(i_,T))
+ )
+};
+
+
+#if defined(BOOST_MPL_CFG_MSVC_ETI_BUG)
+/// workaround for ETI bug
+template<>
+struct BOOST_PP_CAT(apply,i_)<AUX778076_APPLY_N_SPEC_PARAMS(i_, int)>
+{
+ typedef int type;
+};
+#endif
+
+# if !defined(BOOST_MPL_CFG_NO_APPLY_TEMPLATE)
+# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+
+#if i_ == BOOST_MPL_LIMIT_METAFUNCTION_ARITY
+/// primary template (not a specialization!)
+template<
+ typename F AUX778076_APPLY_N_COMMA_PARAMS(i_, typename T)
+ >
+struct apply
+ : BOOST_PP_CAT(apply,i_)< F AUX778076_APPLY_N_COMMA_PARAMS(i_, T) >
+{
+};
+#else
+template<
+ typename F AUX778076_APPLY_N_COMMA_PARAMS(i_, typename T)
+ >
+struct apply< F AUX778076_APPLY_N_PARTIAL_SPEC_PARAMS(i_, T, na) >
+ : BOOST_PP_CAT(apply,i_)< F AUX778076_APPLY_N_COMMA_PARAMS(i_, T) >
+{
+};
+#endif
+
+# else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+
+#if !defined(BOOST_MPL_CFG_NO_APPLY_TEMPLATE)
+namespace aux {
+
+template<>
+struct apply_chooser<i_>
+{
+ template<
+ typename F, AUX778076_APPLY_PARAMS(typename T)
+ >
+ struct result_
+ {
+ typedef BOOST_PP_CAT(apply,i_)<
+ F AUX778076_APPLY_N_COMMA_PARAMS(i_, T)
+ > type;
+ };
+};
+
+} // namespace aux
+#endif
+
+# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+# endif // BOOST_MPL_CFG_NO_APPLY_TEMPLATE
+
+# undef i_
+
+#endif // BOOST_PP_ITERATION_DEPTH()
+#endif // BOOST_PP_IS_ITERATING
diff --git a/third_party/boost/boost/mpl/apply_fwd.hpp b/third_party/boost/boost/mpl/apply_fwd.hpp
new file mode 100644
index 0000000..dc66b1d
--- /dev/null
+++ b/third_party/boost/boost/mpl/apply_fwd.hpp
@@ -0,0 +1,107 @@
+
+#if !defined(BOOST_PP_IS_ITERATING)
+
+///// header body
+
+#ifndef BOOST_MPL_APPLY_FWD_HPP_INCLUDED
+#define BOOST_MPL_APPLY_FWD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_PREPROCESSING_MODE)
+# include <boost/mpl/aux_/na.hpp>
+#endif
+
+#include <boost/mpl/aux_/config/use_preprocessed.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE)
+
+# define BOOST_MPL_PREPROCESSED_HEADER apply_fwd.hpp
+# include <boost/mpl/aux_/include_preprocessed.hpp>
+
+#else
+
+# include <boost/mpl/limits/arity.hpp>
+# include <boost/mpl/aux_/preprocessor/params.hpp>
+# include <boost/mpl/aux_/preprocessor/default_params.hpp>
+# include <boost/mpl/aux_/config/ctps.hpp>
+# include <boost/mpl/aux_/nttp_decl.hpp>
+
+# include <boost/preprocessor/comma_if.hpp>
+# include <boost/preprocessor/iterate.hpp>
+# include <boost/preprocessor/cat.hpp>
+
+// agurt, 15/jan/02: top-level 'apply' template gives an ICE on MSVC
+// (for known reasons)
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+# define BOOST_MPL_CFG_NO_APPLY_TEMPLATE
+#endif
+
+namespace boost { namespace mpl {
+
+// local macro, #undef-ined at the end of the header
+# define AUX778076_APPLY_DEF_PARAMS(param, value) \
+ BOOST_MPL_PP_DEFAULT_PARAMS( \
+ BOOST_MPL_LIMIT_METAFUNCTION_ARITY \
+ , param \
+ , value \
+ ) \
+ /**/
+
+# define AUX778076_APPLY_N_COMMA_PARAMS(n, param) \
+ BOOST_PP_COMMA_IF(n) \
+ BOOST_MPL_PP_PARAMS(n, param) \
+ /**/
+
+# if !defined(BOOST_MPL_CFG_NO_APPLY_TEMPLATE)
+
+#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+// forward declaration
+template<
+ typename F, AUX778076_APPLY_DEF_PARAMS(typename T, na)
+ >
+struct apply;
+#else
+namespace aux {
+template< BOOST_AUX_NTTP_DECL(int, arity_) > struct apply_chooser;
+}
+#endif
+
+# endif // BOOST_MPL_CFG_NO_APPLY_TEMPLATE
+
+#define BOOST_PP_ITERATION_PARAMS_1 \
+ (3,(0, BOOST_MPL_LIMIT_METAFUNCTION_ARITY, <boost/mpl/apply_fwd.hpp>))
+#include BOOST_PP_ITERATE()
+
+
+# undef AUX778076_APPLY_N_COMMA_PARAMS
+# undef AUX778076_APPLY_DEF_PARAMS
+
+}}
+
+#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#endif // BOOST_MPL_APPLY_FWD_HPP_INCLUDED
+
+///// iteration
+
+#else
+#define i_ BOOST_PP_FRAME_ITERATION(1)
+
+template<
+ typename F AUX778076_APPLY_N_COMMA_PARAMS(i_, typename T)
+ >
+struct BOOST_PP_CAT(apply,i_);
+
+#undef i_
+#endif // BOOST_PP_IS_ITERATING
diff --git a/third_party/boost/boost/mpl/apply_wrap.hpp b/third_party/boost/boost/mpl/apply_wrap.hpp
new file mode 100644
index 0000000..24ede22
--- /dev/null
+++ b/third_party/boost/boost/mpl/apply_wrap.hpp
@@ -0,0 +1,234 @@
+
+#if !defined(BOOST_PP_IS_ITERATING)
+
+///// header body
+
+#ifndef BOOST_MPL_APPLY_WRAP_HPP_INCLUDED
+#define BOOST_MPL_APPLY_WRAP_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2008
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_PREPROCESSING_MODE)
+# include <boost/mpl/aux_/arity.hpp>
+# include <boost/mpl/aux_/has_apply.hpp>
+# include <boost/mpl/aux_/na.hpp>
+# include <boost/mpl/aux_/msvc_never_true.hpp>
+#endif
+
+#include <boost/mpl/aux_/config/use_preprocessed.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE)
+
+# define BOOST_MPL_PREPROCESSED_HEADER apply_wrap.hpp
+# include <boost/mpl/aux_/include_preprocessed.hpp>
+
+#else
+
+# include <boost/mpl/limits/arity.hpp>
+# include <boost/mpl/aux_/preprocessor/params.hpp>
+# include <boost/mpl/aux_/preprocessor/enum.hpp>
+# include <boost/mpl/aux_/preprocessor/add.hpp>
+# include <boost/mpl/aux_/config/bcc.hpp>
+# include <boost/mpl/aux_/config/ctps.hpp>
+# include <boost/mpl/aux_/config/dtp.hpp>
+# include <boost/mpl/aux_/config/eti.hpp>
+# include <boost/mpl/aux_/config/msvc.hpp>
+# include <boost/mpl/aux_/config/workaround.hpp>
+
+# include <boost/preprocessor/comma_if.hpp>
+# include <boost/preprocessor/logical/and.hpp>
+# include <boost/preprocessor/inc.hpp>
+# include <boost/preprocessor/iterate.hpp>
+
+
+namespace boost { namespace mpl {
+
+// local macros, #undef-ined at the end of the header
+# define AUX778076_APPLY_WRAP_PARAMS(n, param) \
+ BOOST_MPL_PP_PARAMS(n, param) \
+ /**/
+
+# define AUX778076_APPLY_WRAP_SPEC_PARAMS(n, param) \
+ BOOST_MPL_PP_ENUM(BOOST_PP_INC(n), param) \
+ /**/
+
+
+#define BOOST_PP_ITERATION_PARAMS_1 \
+ (3,(0, BOOST_MPL_LIMIT_METAFUNCTION_ARITY, <boost/mpl/apply_wrap.hpp>))
+#include BOOST_PP_ITERATE()
+
+
+# undef AUX778076_APPLY_WRAP_SPEC_PARAMS
+# undef AUX778076_APPLY_WRAP_PARAMS
+
+}}
+
+#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#endif // BOOST_MPL_APPLY_WRAP_HPP_INCLUDED
+
+///// iteration, depth == 1
+
+// For gcc 4.4 compatability, we must include the
+// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
+#else // BOOST_PP_IS_ITERATING
+#if BOOST_PP_ITERATION_DEPTH() == 1
+
+# define i_ BOOST_PP_FRAME_ITERATION(1)
+
+# if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+// MSVC version
+
+#define AUX778076_MSVC_DTW_NAME BOOST_PP_CAT(msvc_apply,i_)
+#define AUX778076_MSVC_DTW_ORIGINAL_NAME apply
+#define AUX778076_MSVC_DTW_ARITY i_
+#include <boost/mpl/aux_/msvc_dtw.hpp>
+
+template<
+ typename F BOOST_PP_COMMA_IF(i_) AUX778076_APPLY_WRAP_PARAMS(i_, typename T)
+ >
+struct BOOST_PP_CAT(apply_wrap,i_)
+{
+ // Metafunction forwarding confuses vc6
+ typedef typename BOOST_PP_CAT(msvc_apply,i_)<F>::template result_<
+ AUX778076_APPLY_WRAP_PARAMS(i_, T)
+ >::type type;
+};
+
+# elif defined(BOOST_MPL_CFG_BROKEN_DEFAULT_PARAMETERS_IN_NESTED_TEMPLATES)
+// MWCW/Borland version
+
+template<
+ int N, typename F BOOST_PP_COMMA_IF(i_) AUX778076_APPLY_WRAP_PARAMS(i_, typename T)
+ >
+struct BOOST_PP_CAT(apply_wrap_impl,i_);
+
+#define BOOST_PP_ITERATION_PARAMS_2 \
+ (3,(0, BOOST_MPL_LIMIT_METAFUNCTION_ARITY - i_, <boost/mpl/apply_wrap.hpp>))
+#include BOOST_PP_ITERATE()
+
+template<
+ typename F BOOST_PP_COMMA_IF(i_) AUX778076_APPLY_WRAP_PARAMS(i_, typename T)
+ >
+struct BOOST_PP_CAT(apply_wrap,i_)
+ : BOOST_PP_CAT(apply_wrap_impl,i_)<
+ ::boost::mpl::aux::arity<F,i_>::value
+ , F
+ BOOST_PP_COMMA_IF(i_) AUX778076_APPLY_WRAP_PARAMS(i_, T)
+ >::type
+{
+};
+
+# else
+// ISO98 C++, with minor concession to vc7
+
+template<
+ typename F BOOST_PP_COMMA_IF(i_) AUX778076_APPLY_WRAP_PARAMS(i_, typename T)
+#if i_ == 0
+ , typename has_apply_ = typename aux::has_apply<F>::type
+#endif
+ >
+struct BOOST_PP_CAT(apply_wrap,i_)
+// metafunction forwarding confuses MSVC 7.0
+#if !BOOST_WORKAROUND(BOOST_MSVC, == 1300)
+ : F::template apply< AUX778076_APPLY_WRAP_PARAMS(i_, T) >
+{
+#else
+{
+ typedef typename F::template apply<
+ AUX778076_APPLY_WRAP_PARAMS(i_, T)
+ >::type type;
+#endif
+};
+
+#if i_ == 0 && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+template< typename F >
+struct BOOST_PP_CAT(apply_wrap,i_)<F,true_>
+ : F::apply
+{
+};
+#endif
+
+# endif // workarounds
+
+#if defined(BOOST_MPL_CFG_MSVC_ETI_BUG)
+/// workaround for ETI bug
+template<>
+struct BOOST_PP_CAT(apply_wrap,i_)<AUX778076_APPLY_WRAP_SPEC_PARAMS(i_, int)>
+{
+ typedef int type;
+};
+#endif
+
+# undef i_
+
+///// iteration, depth == 2
+
+#elif BOOST_PP_ITERATION_DEPTH() == 2
+
+# define j_ BOOST_PP_FRAME_ITERATION(2)
+
+#if i_ == 0 && j_ == 0 \
+ && defined(BOOST_MPL_CFG_BCC590_WORKAROUNDS) \
+ && !defined(BOOST_MPL_CFG_NO_HAS_APPLY)
+
+template< typename F, bool F_has_apply >
+struct apply_wrap_impl0_bcb {
+ typedef typename F::template apply< na > type;
+};
+
+template< typename F >
+struct apply_wrap_impl0_bcb< F, true > {
+ typedef typename F::apply type;
+};
+
+template<
+ typename F BOOST_PP_COMMA_IF(i_) AUX778076_APPLY_WRAP_PARAMS(i_, typename T)
+ >
+struct BOOST_PP_CAT(apply_wrap_impl,i_)<
+ BOOST_MPL_PP_ADD(i_, j_)
+ , F
+ BOOST_PP_COMMA_IF(i_) AUX778076_APPLY_WRAP_PARAMS(i_, T)
+ >
+{
+ typedef apply_wrap_impl0_bcb< F, aux::has_apply< F >::value >::type type;
+};
+#else
+
+template<
+ typename F BOOST_PP_COMMA_IF(i_) AUX778076_APPLY_WRAP_PARAMS(i_, typename T)
+ >
+struct BOOST_PP_CAT(apply_wrap_impl,i_)<
+ BOOST_MPL_PP_ADD(i_, j_)
+ , F
+ BOOST_PP_COMMA_IF(i_) AUX778076_APPLY_WRAP_PARAMS(i_, T)
+ >
+{
+ typedef typename F::template apply<
+ AUX778076_APPLY_WRAP_PARAMS(i_, T)
+#if i_ == 0 && j_ == 0
+/// since the defaults are "lost", we have to pass *something* even for nullary
+/// metafunction classes
+ na
+#else
+ BOOST_PP_COMMA_IF(BOOST_PP_AND(i_, j_)) BOOST_MPL_PP_ENUM(j_, na)
+#endif
+ > type;
+};
+
+#endif
+
+# undef j_
+
+#endif // BOOST_PP_ITERATION_DEPTH()
+#endif // BOOST_PP_IS_ITERATING
diff --git a/third_party/boost/boost/mpl/arg.hpp b/third_party/boost/boost/mpl/arg.hpp
new file mode 100644
index 0000000..2c7051c
--- /dev/null
+++ b/third_party/boost/boost/mpl/arg.hpp
@@ -0,0 +1,131 @@
+
+#if !defined(BOOST_PP_IS_ITERATING)
+
+///// header body
+
+#ifndef BOOST_MPL_ARG_HPP_INCLUDED
+#define BOOST_MPL_ARG_HPP_INCLUDED
+
+// Copyright Peter Dimov 2001-2002
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_PREPROCESSING_MODE)
+# include <boost/mpl/arg_fwd.hpp>
+# include <boost/mpl/aux_/na.hpp>
+# include <boost/mpl/aux_/na_assert.hpp>
+# include <boost/mpl/aux_/arity_spec.hpp>
+# include <boost/mpl/aux_/arg_typedef.hpp>
+#endif
+
+#include <boost/mpl/aux_/config/static_constant.hpp>
+#include <boost/mpl/aux_/config/use_preprocessed.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE)
+
+# define BOOST_MPL_PREPROCESSED_HEADER arg.hpp
+# include <boost/mpl/aux_/include_preprocessed.hpp>
+
+#else
+
+# include <boost/mpl/limits/arity.hpp>
+# include <boost/mpl/aux_/preprocessor/default_params.hpp>
+# include <boost/mpl/aux_/preprocessor/params.hpp>
+# include <boost/mpl/aux_/config/lambda.hpp>
+# include <boost/mpl/aux_/config/dtp.hpp>
+# include <boost/mpl/aux_/nttp_decl.hpp>
+
+# include <boost/preprocessor/iterate.hpp>
+# include <boost/preprocessor/inc.hpp>
+# include <boost/preprocessor/cat.hpp>
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+
+// local macro, #undef-ined at the end of the header
+#if !defined(BOOST_MPL_CFG_NO_DEFAULT_PARAMETERS_IN_NESTED_TEMPLATES)
+# define AUX778076_ARG_N_DEFAULT_PARAMS(param,value) \
+ BOOST_MPL_PP_DEFAULT_PARAMS( \
+ BOOST_MPL_LIMIT_METAFUNCTION_ARITY \
+ , param \
+ , value \
+ ) \
+ /**/
+#else
+# define AUX778076_ARG_N_DEFAULT_PARAMS(param,value) \
+ BOOST_MPL_PP_PARAMS( \
+ BOOST_MPL_LIMIT_METAFUNCTION_ARITY \
+ , param \
+ ) \
+ /**/
+#endif
+
+#define BOOST_PP_ITERATION_PARAMS_1 \
+ (3,(0, BOOST_MPL_LIMIT_METAFUNCTION_ARITY, <boost/mpl/arg.hpp>))
+#include BOOST_PP_ITERATE()
+
+
+# undef AUX778076_ARG_N_DEFAULT_PARAMS
+
+BOOST_MPL_AUX_NONTYPE_ARITY_SPEC(1,int,arg)
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+
+#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#endif // BOOST_MPL_ARG_HPP_INCLUDED
+
+///// iteration
+
+#else
+#define i_ BOOST_PP_FRAME_ITERATION(1)
+
+#if i_ > 0
+
+template<> struct arg<i_>
+{
+ BOOST_STATIC_CONSTANT(int, value = i_);
+ typedef arg<BOOST_PP_INC(i_)> next;
+ BOOST_MPL_AUX_ARG_TYPEDEF(na, tag)
+ BOOST_MPL_AUX_ARG_TYPEDEF(na, type)
+
+ template<
+ AUX778076_ARG_N_DEFAULT_PARAMS(typename U, na)
+ >
+ struct apply
+ {
+ typedef BOOST_PP_CAT(U,i_) type;
+ BOOST_MPL_AUX_ASSERT_NOT_NA(type);
+ };
+};
+
+#else
+
+template<> struct arg<-1>
+{
+ BOOST_STATIC_CONSTANT(int, value = -1);
+ BOOST_MPL_AUX_ARG_TYPEDEF(na, tag)
+ BOOST_MPL_AUX_ARG_TYPEDEF(na, type)
+
+ template<
+ AUX778076_ARG_N_DEFAULT_PARAMS(typename U, na)
+ >
+ struct apply
+ {
+ typedef U1 type;
+ BOOST_MPL_AUX_ASSERT_NOT_NA(type);
+ };
+};
+
+#endif // i_ > 0
+
+#undef i_
+#endif // BOOST_PP_IS_ITERATING
diff --git a/third_party/boost/boost/mpl/arg_fwd.hpp b/third_party/boost/boost/mpl/arg_fwd.hpp
new file mode 100644
index 0000000..a4bfc2f
--- /dev/null
+++ b/third_party/boost/boost/mpl/arg_fwd.hpp
@@ -0,0 +1,28 @@
+
+#ifndef BOOST_MPL_ARG_FWD_HPP_INCLUDED
+#define BOOST_MPL_ARG_FWD_HPP_INCLUDED
+
+// Copyright Peter Dimov 2001-2002
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/adl_barrier.hpp>
+#include <boost/mpl/aux_/nttp_decl.hpp>
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+
+template< BOOST_MPL_AUX_NTTP_DECL(int, N) > struct arg;
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+BOOST_MPL_AUX_ADL_BARRIER_DECL(arg)
+
+#endif // BOOST_MPL_ARG_FWD_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/assert.hpp b/third_party/boost/boost/mpl/assert.hpp
new file mode 100644
index 0000000..8bf8c97
--- /dev/null
+++ b/third_party/boost/boost/mpl/assert.hpp
@@ -0,0 +1,439 @@
+
+#ifndef BOOST_MPL_ASSERT_HPP_INCLUDED
+#define BOOST_MPL_ASSERT_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2006
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/not.hpp>
+#include <boost/mpl/aux_/value_wknd.hpp>
+#include <boost/mpl/aux_/nested_type_wknd.hpp>
+#include <boost/mpl/aux_/yes_no.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/mpl/aux_/adl_barrier.hpp>
+
+#include <boost/mpl/aux_/config/nttp.hpp>
+#include <boost/mpl/aux_/config/dtp.hpp>
+#include <boost/mpl/aux_/config/gcc.hpp>
+#include <boost/mpl/aux_/config/msvc.hpp>
+#include <boost/mpl/aux_/config/gpu.hpp>
+#include <boost/mpl/aux_/config/static_constant.hpp>
+#include <boost/mpl/aux_/config/pp_counter.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+#include <boost/preprocessor/cat.hpp>
+
+#include <boost/config.hpp> // make sure 'size_t' is placed into 'std'
+#include <cstddef>
+
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1700)
+#include <boost/mpl/if.hpp>
+#endif
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610)) \
+ || (BOOST_MPL_CFG_GCC != 0) \
+ || BOOST_WORKAROUND(__IBMCPP__, <= 600)
+# define BOOST_MPL_CFG_ASSERT_USE_RELATION_NAMES
+#endif
+
+#if BOOST_WORKAROUND(__MWERKS__, < 0x3202) \
+ || BOOST_WORKAROUND(__EDG_VERSION__, <= 238) \
+ || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610)) \
+ || BOOST_WORKAROUND(__DMC__, BOOST_TESTED_AT(0x840))
+# define BOOST_MPL_CFG_ASSERT_BROKEN_POINTER_TO_POINTER_TO_MEMBER
+#endif
+
+// agurt, 10/nov/06: use enums for Borland (which cannot cope with static constants)
+// and GCC (which issues "unused variable" warnings when static constants are used
+// at a function scope)
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610)) \
+ || (BOOST_MPL_CFG_GCC != 0) || (BOOST_MPL_CFG_GPU != 0)
+# define BOOST_MPL_AUX_ASSERT_CONSTANT(T, expr) enum { expr }
+#else
+# define BOOST_MPL_AUX_ASSERT_CONSTANT(T, expr) BOOST_STATIC_CONSTANT(T, expr)
+#endif
+
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+
+struct failed {};
+
+// agurt, 24/aug/04: MSVC 7.1 workaround here and below: return/accept
+// 'assert<false>' by reference; can't apply it unconditionally -- apparently it
+// degrades the quality of GCC diagnostics
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
+# define AUX778076_ASSERT_ARG(x) x&
+#else
+# define AUX778076_ASSERT_ARG(x) x
+#endif
+
+template< bool C > struct assert { typedef void* type; };
+template<> struct assert<false> { typedef AUX778076_ASSERT_ARG(assert) type; };
+
+template< bool C >
+int assertion_failed( typename assert<C>::type );
+
+template< bool C >
+struct assertion
+{
+ static int failed( assert<false> );
+};
+
+template<>
+struct assertion<true>
+{
+ static int failed( void* );
+};
+
+struct assert_
+{
+#if !defined(BOOST_MPL_CFG_NO_DEFAULT_PARAMETERS_IN_NESTED_TEMPLATES)
+ template< typename T1, typename T2 = na, typename T3 = na, typename T4 = na > struct types {};
+#endif
+ static assert_ const arg;
+ enum relations { equal = 1, not_equal, greater, greater_equal, less, less_equal };
+};
+
+
+#if !defined(BOOST_MPL_CFG_ASSERT_USE_RELATION_NAMES)
+
+bool operator==( failed, failed );
+bool operator!=( failed, failed );
+bool operator>( failed, failed );
+bool operator>=( failed, failed );
+bool operator<( failed, failed );
+bool operator<=( failed, failed );
+
+#if defined(__EDG_VERSION__)
+template< bool (*)(failed, failed), long x, long y > struct assert_relation {};
+# define BOOST_MPL_AUX_ASSERT_RELATION(x, y, r) assert_relation<r,x,y>
+#else
+template< BOOST_MPL_AUX_NTTP_DECL(long, x), BOOST_MPL_AUX_NTTP_DECL(long, y), bool (*)(failed, failed) >
+struct assert_relation {};
+# define BOOST_MPL_AUX_ASSERT_RELATION(x, y, r) assert_relation<x,y,r>
+#endif
+
+#else // BOOST_MPL_CFG_ASSERT_USE_RELATION_NAMES
+
+boost::mpl::aux::weighted_tag<1>::type operator==( assert_, assert_ );
+boost::mpl::aux::weighted_tag<2>::type operator!=( assert_, assert_ );
+boost::mpl::aux::weighted_tag<3>::type operator>( assert_, assert_ );
+boost::mpl::aux::weighted_tag<4>::type operator>=( assert_, assert_ );
+boost::mpl::aux::weighted_tag<5>::type operator<( assert_, assert_ );
+boost::mpl::aux::weighted_tag<6>::type operator<=( assert_, assert_ );
+
+template< assert_::relations r, long x, long y > struct assert_relation {};
+
+#endif
+
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1700)
+
+template<class Pred>
+struct extract_assert_pred;
+
+template<class Pred>
+struct extract_assert_pred<void(Pred)> { typedef Pred type; };
+
+template<class Pred>
+struct eval_assert {
+ typedef typename extract_assert_pred<Pred>::type P;
+ typedef typename P::type p_type;
+ typedef typename ::boost::mpl::if_c<p_type::value,
+ AUX778076_ASSERT_ARG(assert<false>),
+ failed ************ P::************
+ >::type type;
+};
+
+template<class Pred>
+struct eval_assert_not {
+ typedef typename extract_assert_pred<Pred>::type P;
+ typedef typename P::type p_type;
+ typedef typename ::boost::mpl::if_c<!p_type::value,
+ AUX778076_ASSERT_ARG(assert<false>),
+ failed ************ ::boost::mpl::not_<P>::************
+ >::type type;
+};
+
+template< typename T >
+T make_assert_arg();
+
+#elif !defined(BOOST_MPL_CFG_ASSERT_BROKEN_POINTER_TO_POINTER_TO_MEMBER)
+
+template< bool > struct assert_arg_pred_impl { typedef int type; };
+template<> struct assert_arg_pred_impl<true> { typedef void* type; };
+
+template< typename P > struct assert_arg_pred
+{
+ typedef typename P::type p_type;
+ typedef typename assert_arg_pred_impl< p_type::value >::type type;
+};
+
+template< typename P > struct assert_arg_pred_not
+{
+ typedef typename P::type p_type;
+ BOOST_MPL_AUX_ASSERT_CONSTANT( bool, p = !p_type::value );
+ typedef typename assert_arg_pred_impl<p>::type type;
+};
+
+template< typename Pred >
+failed ************ (Pred::************
+ assert_arg( void (*)(Pred), typename assert_arg_pred<Pred>::type )
+ );
+
+template< typename Pred >
+failed ************ (boost::mpl::not_<Pred>::************
+ assert_not_arg( void (*)(Pred), typename assert_arg_pred_not<Pred>::type )
+ );
+
+template< typename Pred >
+AUX778076_ASSERT_ARG(assert<false>)
+assert_arg( void (*)(Pred), typename assert_arg_pred_not<Pred>::type );
+
+template< typename Pred >
+AUX778076_ASSERT_ARG(assert<false>)
+assert_not_arg( void (*)(Pred), typename assert_arg_pred<Pred>::type );
+
+
+#else // BOOST_MPL_CFG_ASSERT_BROKEN_POINTER_TO_POINTER_TO_MEMBER
+
+template< bool c, typename Pred > struct assert_arg_type_impl
+{
+ typedef failed ************ Pred::* mwcw83_wknd;
+ typedef mwcw83_wknd ************* type;
+};
+
+template< typename Pred > struct assert_arg_type_impl<true,Pred>
+{
+ typedef AUX778076_ASSERT_ARG(assert<false>) type;
+};
+
+template< typename Pred > struct assert_arg_type
+ : assert_arg_type_impl< BOOST_MPL_AUX_VALUE_WKND(BOOST_MPL_AUX_NESTED_TYPE_WKND(Pred))::value, Pred >
+{
+};
+
+template< typename Pred >
+typename assert_arg_type<Pred>::type
+assert_arg(void (*)(Pred), int);
+
+template< typename Pred >
+typename assert_arg_type< boost::mpl::not_<Pred> >::type
+assert_not_arg(void (*)(Pred), int);
+
+# if !defined(BOOST_MPL_CFG_ASSERT_USE_RELATION_NAMES)
+template< long x, long y, bool (*r)(failed, failed) >
+typename assert_arg_type_impl< false,BOOST_MPL_AUX_ASSERT_RELATION(x,y,r) >::type
+assert_rel_arg( BOOST_MPL_AUX_ASSERT_RELATION(x,y,r) );
+# else
+template< assert_::relations r, long x, long y >
+typename assert_arg_type_impl< false,assert_relation<r,x,y> >::type
+assert_rel_arg( assert_relation<r,x,y> );
+# endif
+
+#endif // BOOST_MPL_CFG_ASSERT_BROKEN_POINTER_TO_POINTER_TO_MEMBER
+
+#undef AUX778076_ASSERT_ARG
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1700)
+
+// BOOST_MPL_ASSERT((pred<x,...>))
+
+#define BOOST_MPL_ASSERT(pred) \
+BOOST_MPL_AUX_ASSERT_CONSTANT( \
+ std::size_t \
+ , BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \
+ boost::mpl::assertion_failed<false>( \
+ boost::mpl::make_assert_arg< \
+ typename boost::mpl::eval_assert<void pred>::type \
+ >() \
+ ) \
+ ) \
+ ) \
+/**/
+
+// BOOST_MPL_ASSERT_NOT((pred<x,...>))
+
+#define BOOST_MPL_ASSERT_NOT(pred) \
+BOOST_MPL_AUX_ASSERT_CONSTANT( \
+ std::size_t \
+ , BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \
+ boost::mpl::assertion_failed<false>( \
+ boost::mpl::make_assert_arg< \
+ typename boost::mpl::eval_assert_not<void pred>::type \
+ >() \
+ ) \
+ ) \
+ ) \
+/**/
+
+#else
+
+// BOOST_MPL_ASSERT((pred<x,...>))
+
+#define BOOST_MPL_ASSERT(pred) \
+BOOST_MPL_AUX_ASSERT_CONSTANT( \
+ std::size_t \
+ , BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \
+ boost::mpl::assertion_failed<false>( \
+ boost::mpl::assert_arg( (void (*) pred)0, 1 ) \
+ ) \
+ ) \
+ ) \
+/**/
+
+// BOOST_MPL_ASSERT_NOT((pred<x,...>))
+
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
+# define BOOST_MPL_ASSERT_NOT(pred) \
+enum { \
+ BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \
+ boost::mpl::assertion<false>::failed( \
+ boost::mpl::assert_not_arg( (void (*) pred)0, 1 ) \
+ ) \
+ ) \
+}\
+/**/
+#else
+# define BOOST_MPL_ASSERT_NOT(pred) \
+BOOST_MPL_AUX_ASSERT_CONSTANT( \
+ std::size_t \
+ , BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \
+ boost::mpl::assertion_failed<false>( \
+ boost::mpl::assert_not_arg( (void (*) pred)0, 1 ) \
+ ) \
+ ) \
+ ) \
+/**/
+#endif
+
+#endif
+
+// BOOST_MPL_ASSERT_RELATION(x, ==|!=|<=|<|>=|>, y)
+
+#if defined(BOOST_MPL_CFG_ASSERT_USE_RELATION_NAMES)
+
+# if !defined(BOOST_MPL_CFG_ASSERT_BROKEN_POINTER_TO_POINTER_TO_MEMBER)
+// agurt, 9/nov/06: 'enum' below is a workaround for gcc 4.0.4/4.1.1 bugs #29522 and #29518
+# define BOOST_MPL_ASSERT_RELATION_IMPL(counter, x, rel, y) \
+enum { BOOST_PP_CAT(mpl_assert_rel_value,counter) = (x rel y) }; \
+BOOST_MPL_AUX_ASSERT_CONSTANT( \
+ std::size_t \
+ , BOOST_PP_CAT(mpl_assertion_in_line_,counter) = sizeof( \
+ boost::mpl::assertion_failed<BOOST_PP_CAT(mpl_assert_rel_value,counter)>( \
+ (boost::mpl::failed ************ ( boost::mpl::assert_relation< \
+ boost::mpl::assert_::relations( sizeof( \
+ boost::mpl::assert_::arg rel boost::mpl::assert_::arg \
+ ) ) \
+ , x \
+ , y \
+ >::************)) 0 ) \
+ ) \
+ ) \
+/**/
+# else
+# define BOOST_MPL_ASSERT_RELATION_IMPL(counter, x, rel, y) \
+BOOST_MPL_AUX_ASSERT_CONSTANT( \
+ std::size_t \
+ , BOOST_PP_CAT(mpl_assert_rel,counter) = sizeof( \
+ boost::mpl::assert_::arg rel boost::mpl::assert_::arg \
+ ) \
+ ); \
+BOOST_MPL_AUX_ASSERT_CONSTANT( bool, BOOST_PP_CAT(mpl_assert_rel_value,counter) = (x rel y) ); \
+BOOST_MPL_AUX_ASSERT_CONSTANT( \
+ std::size_t \
+ , BOOST_PP_CAT(mpl_assertion_in_line_,counter) = sizeof( \
+ boost::mpl::assertion_failed<BOOST_PP_CAT(mpl_assert_rel_value,counter)>( \
+ boost::mpl::assert_rel_arg( boost::mpl::assert_relation< \
+ boost::mpl::assert_::relations(BOOST_PP_CAT(mpl_assert_rel,counter)) \
+ , x \
+ , y \
+ >() ) \
+ ) \
+ ) \
+ ) \
+/**/
+# endif
+
+# define BOOST_MPL_ASSERT_RELATION(x, rel, y) \
+BOOST_MPL_ASSERT_RELATION_IMPL(BOOST_MPL_AUX_PP_COUNTER(), x, rel, y) \
+/**/
+
+#else // !BOOST_MPL_CFG_ASSERT_USE_RELATION_NAMES
+
+# if defined(BOOST_MPL_CFG_ASSERT_BROKEN_POINTER_TO_POINTER_TO_MEMBER)
+# define BOOST_MPL_ASSERT_RELATION(x, rel, y) \
+BOOST_MPL_AUX_ASSERT_CONSTANT( \
+ std::size_t \
+ , BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \
+ boost::mpl::assertion_failed<(x rel y)>( boost::mpl::assert_rel_arg( \
+ boost::mpl::BOOST_MPL_AUX_ASSERT_RELATION(x,y,(&boost::mpl::operator rel))() \
+ ) ) \
+ ) \
+ ) \
+/**/
+# else
+# define BOOST_MPL_ASSERT_RELATION(x, rel, y) \
+BOOST_MPL_AUX_ASSERT_CONSTANT( \
+ std::size_t \
+ , BOOST_PP_CAT(mpl_assertion_in_line_,BOOST_MPL_AUX_PP_COUNTER()) = sizeof( \
+ boost::mpl::assertion_failed<(x rel y)>( (boost::mpl::failed ************ ( \
+ boost::mpl::BOOST_MPL_AUX_ASSERT_RELATION(x,y,(&boost::mpl::operator rel))::************))0 ) \
+ ) \
+ ) \
+/**/
+# endif
+
+#endif
+
+
+// BOOST_MPL_ASSERT_MSG( (pred<x,...>::value), USER_PROVIDED_MESSAGE, (types<x,...>) )
+
+#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3202))
+# define BOOST_MPL_ASSERT_MSG_IMPL( counter, c, msg, types_ ) \
+struct msg; \
+typedef struct BOOST_PP_CAT(msg,counter) : boost::mpl::assert_ \
+{ \
+ using boost::mpl::assert_::types; \
+ static boost::mpl::failed ************ (msg::************ assert_arg()) types_ \
+ { return 0; } \
+} BOOST_PP_CAT(mpl_assert_arg,counter); \
+BOOST_MPL_AUX_ASSERT_CONSTANT( \
+ std::size_t \
+ , BOOST_PP_CAT(mpl_assertion_in_line_,counter) = sizeof( \
+ boost::mpl::assertion<(c)>::failed( BOOST_PP_CAT(mpl_assert_arg,counter)::assert_arg() ) \
+ ) \
+ ) \
+/**/
+#else
+# define BOOST_MPL_ASSERT_MSG_IMPL( counter, c, msg, types_ ) \
+struct msg; \
+typedef struct BOOST_PP_CAT(msg,counter) : boost::mpl::assert_ \
+{ \
+ static boost::mpl::failed ************ (msg::************ assert_arg()) types_ \
+ { return 0; } \
+} BOOST_PP_CAT(mpl_assert_arg,counter); \
+BOOST_MPL_AUX_ASSERT_CONSTANT( \
+ std::size_t \
+ , BOOST_PP_CAT(mpl_assertion_in_line_,counter) = sizeof( \
+ boost::mpl::assertion_failed<(c)>( BOOST_PP_CAT(mpl_assert_arg,counter)::assert_arg() ) \
+ ) \
+ ) \
+/**/
+#endif
+
+#define BOOST_MPL_ASSERT_MSG( c, msg, types_ ) \
+BOOST_MPL_ASSERT_MSG_IMPL( BOOST_MPL_AUX_PP_COUNTER(), c, msg, types_ ) \
+/**/
+
+#endif // BOOST_MPL_ASSERT_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/O1_size_impl.hpp b/third_party/boost/boost/mpl/aux_/O1_size_impl.hpp
new file mode 100644
index 0000000..de64dda
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/O1_size_impl.hpp
@@ -0,0 +1,87 @@
+
+#ifndef BOOST_MPL_O1_SIZE_IMPL_HPP_INCLUDED
+#define BOOST_MPL_O1_SIZE_IMPL_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/O1_size_fwd.hpp>
+#include <boost/mpl/long.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/aux_/has_size.hpp>
+#include <boost/mpl/aux_/config/forwarding.hpp>
+#include <boost/mpl/aux_/config/static_constant.hpp>
+#include <boost/mpl/aux_/config/msvc.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+namespace boost { namespace mpl {
+
+// default implementation - returns 'Sequence::size' if sequence has a 'size'
+// member, and -1 otherwise; conrete sequences might override it by
+// specializing either the 'O1_size_impl' or the primary 'O1_size' template
+
+# if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) \
+ && !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
+
+namespace aux {
+template< typename Sequence > struct O1_size_impl
+ : Sequence::size
+{
+};
+}
+
+template< typename Tag >
+struct O1_size_impl
+{
+ template< typename Sequence > struct apply
+#if !defined(BOOST_MPL_CFG_NO_NESTED_FORWARDING)
+ : if_<
+ aux::has_size<Sequence>
+ , aux::O1_size_impl<Sequence>
+ , long_<-1>
+ >::type
+ {
+#else
+ {
+ typedef typename if_<
+ aux::has_size<Sequence>
+ , aux::O1_size_impl<Sequence>
+ , long_<-1>
+ >::type type;
+
+ BOOST_STATIC_CONSTANT(long, value =
+ (if_<
+ aux::has_size<Sequence>
+ , aux::O1_size_impl<Sequence>
+ , long_<-1>
+ >::type::value)
+ );
+#endif
+ };
+};
+
+# else // BOOST_MSVC
+
+template< typename Tag >
+struct O1_size_impl
+{
+ template< typename Sequence > struct apply
+ : long_<-1>
+ {
+ };
+};
+
+# endif
+
+}}
+
+#endif // BOOST_MPL_O1_SIZE_IMPL_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/adl_barrier.hpp b/third_party/boost/boost/mpl/aux_/adl_barrier.hpp
new file mode 100644
index 0000000..0d28876
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/adl_barrier.hpp
@@ -0,0 +1,48 @@
+
+#ifndef BOOST_MPL_AUX_ADL_BARRIER_HPP_INCLUDED
+#define BOOST_MPL_AUX_ADL_BARRIER_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 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/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/adl.hpp>
+#include <boost/mpl/aux_/config/gcc.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_ADL_BARRIER_NAMESPACE)
+
+# define BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE mpl_
+# define BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN namespace mpl_ {
+# define BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE }
+# define BOOST_MPL_AUX_ADL_BARRIER_DECL(type) \
+ namespace boost { namespace mpl { \
+ using ::BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE::type; \
+ } } \
+/**/
+
+#if !defined(BOOST_MPL_PREPROCESSING_MODE)
+namespace BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE { namespace aux {} }
+namespace boost { namespace mpl { using namespace BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE;
+namespace aux { using namespace BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE::aux; }
+}}
+#endif
+
+#else // BOOST_MPL_CFG_NO_ADL_BARRIER_NAMESPACE
+
+# define BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE boost::mpl
+# define BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN namespace boost { namespace mpl {
+# define BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE }}
+# define BOOST_MPL_AUX_ADL_BARRIER_DECL(type) /**/
+
+#endif
+
+#endif // BOOST_MPL_AUX_ADL_BARRIER_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/advance_backward.hpp b/third_party/boost/boost/mpl/aux_/advance_backward.hpp
new file mode 100644
index 0000000..886d850
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/advance_backward.hpp
@@ -0,0 +1,128 @@
+
+#if !defined(BOOST_PP_IS_ITERATING)
+
+///// header body
+
+#ifndef BOOST_MPL_AUX778076_ADVANCE_BACKWARD_HPP_INCLUDED
+#define BOOST_MPL_AUX778076_ADVANCE_BACKWARD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_PREPROCESSING_MODE)
+# include <boost/mpl/prior.hpp>
+# include <boost/mpl/apply_wrap.hpp>
+#endif
+
+#include <boost/mpl/aux_/config/use_preprocessed.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE)
+
+# define BOOST_MPL_PREPROCESSED_HEADER advance_backward.hpp
+# include <boost/mpl/aux_/include_preprocessed.hpp>
+
+#else
+
+# include <boost/mpl/limits/unrolling.hpp>
+# include <boost/mpl/aux_/nttp_decl.hpp>
+# include <boost/mpl/aux_/config/eti.hpp>
+
+# include <boost/preprocessor/iterate.hpp>
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/inc.hpp>
+
+namespace boost { namespace mpl { namespace aux {
+
+// forward declaration
+template< BOOST_MPL_AUX_NTTP_DECL(long, N) > struct advance_backward;
+
+# define BOOST_PP_ITERATION_PARAMS_1 \
+ (3,(0, BOOST_MPL_LIMIT_UNROLLING, <boost/mpl/aux_/advance_backward.hpp>))
+# include BOOST_PP_ITERATE()
+
+// implementation for N that exceeds BOOST_MPL_LIMIT_UNROLLING
+template< BOOST_MPL_AUX_NTTP_DECL(long, N) >
+struct advance_backward
+{
+ template< typename Iterator > struct apply
+ {
+ typedef typename apply_wrap1<
+ advance_backward<BOOST_MPL_LIMIT_UNROLLING>
+ , Iterator
+ >::type chunk_result_;
+
+ typedef typename apply_wrap1<
+ advance_backward<(
+ (N - BOOST_MPL_LIMIT_UNROLLING) < 0
+ ? 0
+ : N - BOOST_MPL_LIMIT_UNROLLING
+ )>
+ , chunk_result_
+ >::type type;
+ };
+};
+
+}}}
+
+#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#endif // BOOST_MPL_AUX778076_ADVANCE_BACKWARD_HPP_INCLUDED
+
+///// iteration, depth == 1
+
+// For gcc 4.4 compatability, we must include the
+// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
+#else // BOOST_PP_IS_ITERATING
+#if BOOST_PP_ITERATION_DEPTH() == 1
+#define i_ BOOST_PP_FRAME_ITERATION(1)
+
+template<>
+struct advance_backward< BOOST_PP_FRAME_ITERATION(1) >
+{
+ template< typename Iterator > struct apply
+ {
+ typedef Iterator iter0;
+
+#if i_ > 0
+# define BOOST_PP_ITERATION_PARAMS_2 \
+ (3,(1, BOOST_PP_FRAME_ITERATION(1), <boost/mpl/aux_/advance_backward.hpp>))
+# include BOOST_PP_ITERATE()
+#endif
+
+ typedef BOOST_PP_CAT(iter,BOOST_PP_FRAME_ITERATION(1)) type;
+ };
+
+#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG)
+ /// ETI workaround
+ template<> struct apply<int>
+ {
+ typedef int type;
+ };
+#endif
+};
+
+#undef i_
+
+///// iteration, depth == 2
+
+#elif BOOST_PP_ITERATION_DEPTH() == 2
+
+# define AUX778076_ITER_0 BOOST_PP_CAT(iter,BOOST_PP_DEC(BOOST_PP_FRAME_ITERATION(2)))
+# define AUX778076_ITER_1 BOOST_PP_CAT(iter,BOOST_PP_FRAME_ITERATION(2))
+
+ typedef typename prior<AUX778076_ITER_0>::type AUX778076_ITER_1;
+
+# undef AUX778076_ITER_1
+# undef AUX778076_ITER_0
+
+#endif // BOOST_PP_ITERATION_DEPTH()
+#endif // BOOST_PP_IS_ITERATING
diff --git a/third_party/boost/boost/mpl/aux_/advance_forward.hpp b/third_party/boost/boost/mpl/aux_/advance_forward.hpp
new file mode 100644
index 0000000..5cb720f
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/advance_forward.hpp
@@ -0,0 +1,127 @@
+
+#if !defined(BOOST_PP_IS_ITERATING)
+
+///// header body
+
+#ifndef BOOST_MPL_AUX_ADVANCE_FORWARD_HPP_INCLUDED
+#define BOOST_MPL_AUX_ADVANCE_FORWARD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_PREPROCESSING_MODE)
+# include <boost/mpl/next.hpp>
+# include <boost/mpl/apply_wrap.hpp>
+#endif
+
+#include <boost/mpl/aux_/config/use_preprocessed.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE)
+
+# define BOOST_MPL_PREPROCESSED_HEADER advance_forward.hpp
+# include <boost/mpl/aux_/include_preprocessed.hpp>
+
+#else
+
+# include <boost/mpl/limits/unrolling.hpp>
+# include <boost/mpl/aux_/nttp_decl.hpp>
+# include <boost/mpl/aux_/config/eti.hpp>
+
+# include <boost/preprocessor/iterate.hpp>
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/inc.hpp>
+
+namespace boost { namespace mpl { namespace aux {
+
+// forward declaration
+template< BOOST_MPL_AUX_NTTP_DECL(long, N) > struct advance_forward;
+
+# define BOOST_PP_ITERATION_PARAMS_1 \
+ (3,(0, BOOST_MPL_LIMIT_UNROLLING, <boost/mpl/aux_/advance_forward.hpp>))
+# include BOOST_PP_ITERATE()
+
+// implementation for N that exceeds BOOST_MPL_LIMIT_UNROLLING
+template< BOOST_MPL_AUX_NTTP_DECL(long, N) >
+struct advance_forward
+{
+ template< typename Iterator > struct apply
+ {
+ typedef typename apply_wrap1<
+ advance_forward<BOOST_MPL_LIMIT_UNROLLING>
+ , Iterator
+ >::type chunk_result_;
+
+ typedef typename apply_wrap1<
+ advance_forward<(
+ (N - BOOST_MPL_LIMIT_UNROLLING) < 0
+ ? 0
+ : N - BOOST_MPL_LIMIT_UNROLLING
+ )>
+ , chunk_result_
+ >::type type;
+ };
+};
+
+}}}
+
+#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#endif // BOOST_MPL_AUX_ADVANCE_FORWARD_HPP_INCLUDED
+
+///// iteration, depth == 1
+
+// For gcc 4.4 compatability, we must include the
+// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
+#else // BOOST_PP_IS_ITERATING
+#if BOOST_PP_ITERATION_DEPTH() == 1
+#define i_ BOOST_PP_FRAME_ITERATION(1)
+
+template<>
+struct advance_forward< BOOST_PP_FRAME_ITERATION(1) >
+{
+ template< typename Iterator > struct apply
+ {
+ typedef Iterator iter0;
+
+#if i_ > 0
+# define BOOST_PP_ITERATION_PARAMS_2 \
+ (3,(1, i_, <boost/mpl/aux_/advance_forward.hpp>))
+# include BOOST_PP_ITERATE()
+#endif
+ typedef BOOST_PP_CAT(iter,i_) type;
+ };
+
+#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG)
+ /// ETI workaround
+ template<> struct apply<int>
+ {
+ typedef int type;
+ };
+#endif
+};
+
+#undef i_
+
+///// iteration, depth == 2
+
+#elif BOOST_PP_ITERATION_DEPTH() == 2
+
+# define AUX778076_ITER_0 BOOST_PP_CAT(iter,BOOST_PP_DEC(BOOST_PP_FRAME_ITERATION(2)))
+# define AUX778076_ITER_1 BOOST_PP_CAT(iter,BOOST_PP_FRAME_ITERATION(2))
+
+ typedef typename next<AUX778076_ITER_0>::type AUX778076_ITER_1;
+
+# undef AUX778076_ITER_1
+# undef AUX778076_ITER_0
+
+#endif // BOOST_PP_ITERATION_DEPTH()
+#endif // BOOST_PP_IS_ITERATING
diff --git a/third_party/boost/boost/mpl/aux_/arg_typedef.hpp b/third_party/boost/boost/mpl/aux_/arg_typedef.hpp
new file mode 100644
index 0000000..c80b04a
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/arg_typedef.hpp
@@ -0,0 +1,31 @@
+
+#ifndef BOOST_MPL_AUX_ARG_TYPEDEF_HPP_INCLUDED
+#define BOOST_MPL_AUX_ARG_TYPEDEF_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/lambda.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+#if defined(BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT) \
+ || BOOST_WORKAROUND(__DMC__, BOOST_TESTED_AT(0x840))
+
+# define BOOST_MPL_AUX_ARG_TYPEDEF(T, name) typedef T name;
+
+#else
+
+# define BOOST_MPL_AUX_ARG_TYPEDEF(T, name) /**/
+
+#endif
+
+#endif // BOOST_MPL_AUX_ARG_TYPEDEF_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/arity.hpp b/third_party/boost/boost/mpl/aux_/arity.hpp
new file mode 100644
index 0000000..d1bb010
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/arity.hpp
@@ -0,0 +1,39 @@
+
+#ifndef BOOST_MPL_AUX_ARITY_HPP_INCLUDED
+#define BOOST_MPL_AUX_ARITY_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/dtp.hpp>
+
+#if defined(BOOST_MPL_CFG_BROKEN_DEFAULT_PARAMETERS_IN_NESTED_TEMPLATES)
+
+# include <boost/mpl/aux_/nttp_decl.hpp>
+# include <boost/mpl/aux_/config/static_constant.hpp>
+
+namespace boost { namespace mpl { namespace aux {
+
+// agurt, 15/mar/02: it's possible to implement the template so that it will
+// "just work" and do not require any specialization, but not on the compilers
+// that require the arity workaround in the first place
+template< typename F, BOOST_MPL_AUX_NTTP_DECL(int, N) >
+struct arity
+{
+ BOOST_STATIC_CONSTANT(int, value = N);
+};
+
+}}}
+
+#endif // BOOST_MPL_CFG_BROKEN_DEFAULT_PARAMETERS_IN_NESTED_TEMPLATES
+
+#endif // BOOST_MPL_AUX_ARITY_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/arity_spec.hpp b/third_party/boost/boost/mpl/aux_/arity_spec.hpp
new file mode 100644
index 0000000..652b0a6
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/arity_spec.hpp
@@ -0,0 +1,67 @@
+
+#ifndef BOOST_MPL_AUX_ARITY_SPEC_HPP_INCLUDED
+#define BOOST_MPL_AUX_ARITY_SPEC_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/limits/arity.hpp>
+#include <boost/mpl/aux_/config/dtp.hpp>
+#include <boost/mpl/aux_/preprocessor/params.hpp>
+#include <boost/mpl/aux_/arity.hpp>
+#include <boost/mpl/aux_/template_arity_fwd.hpp>
+#include <boost/mpl/aux_/config/ttp.hpp>
+#include <boost/mpl/aux_/config/lambda.hpp>
+#include <boost/mpl/aux_/config/static_constant.hpp>
+
+#if defined(BOOST_MPL_CFG_BROKEN_DEFAULT_PARAMETERS_IN_NESTED_TEMPLATES)
+# define BOOST_MPL_AUX_NONTYPE_ARITY_SPEC(i,type,name) \
+namespace aux { \
+template< BOOST_MPL_AUX_NTTP_DECL(int, N), BOOST_MPL_PP_PARAMS(i,type T) > \
+struct arity< \
+ name< BOOST_MPL_PP_PARAMS(i,T) > \
+ , N \
+ > \
+{ \
+ BOOST_STATIC_CONSTANT(int \
+ , value = BOOST_MPL_LIMIT_METAFUNCTION_ARITY \
+ ); \
+}; \
+} \
+/**/
+#else
+# define BOOST_MPL_AUX_NONTYPE_ARITY_SPEC(i,type,name) /**/
+#endif
+
+# define BOOST_MPL_AUX_ARITY_SPEC(i,name) \
+ BOOST_MPL_AUX_NONTYPE_ARITY_SPEC(i,typename,name) \
+/**/
+
+
+#if defined(BOOST_MPL_CFG_EXTENDED_TEMPLATE_PARAMETERS_MATCHING) \
+ && !defined(BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT)
+# define BOOST_MPL_AUX_TEMPLATE_ARITY_SPEC(i, name) \
+namespace aux { \
+template< BOOST_MPL_PP_PARAMS(i,typename T) > \
+struct template_arity< name<BOOST_MPL_PP_PARAMS(i,T)> > \
+ : int_<i> \
+{ \
+}; \
+} \
+/**/
+#else
+# define BOOST_MPL_AUX_TEMPLATE_ARITY_SPEC(i, name) /**/
+#endif
+
+
+#endif // BOOST_MPL_AUX_ARITY_SPEC_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/begin_end_impl.hpp b/third_party/boost/boost/mpl/aux_/begin_end_impl.hpp
new file mode 100644
index 0000000..1ba612c
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/begin_end_impl.hpp
@@ -0,0 +1,101 @@
+
+#ifndef BOOST_MPL_AUX_BEGIN_END_IMPL_HPP_INCLUDED
+#define BOOST_MPL_AUX_BEGIN_END_IMPL_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/begin_end_fwd.hpp>
+#include <boost/mpl/sequence_tag_fwd.hpp>
+#include <boost/mpl/void.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/aux_/has_begin.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/mpl/aux_/traits_lambda_spec.hpp>
+#include <boost/mpl/aux_/config/eti.hpp>
+
+namespace boost { namespace mpl {
+
+
+namespace aux {
+
+template< typename Sequence >
+struct begin_type
+{
+ typedef typename Sequence::begin type;
+};
+template< typename Sequence >
+struct end_type
+{
+ typedef typename Sequence::end type;
+};
+
+}
+
+// default implementation; conrete sequences might override it by
+// specializing either the 'begin_impl/end_impl' or the primary
+// 'begin/end' templates
+
+template< typename Tag >
+struct begin_impl
+{
+ template< typename Sequence > struct apply
+ {
+ typedef typename eval_if<aux::has_begin<Sequence, true_>,
+ aux::begin_type<Sequence>, void_>::type type;
+ };
+};
+
+template< typename Tag >
+struct end_impl
+{
+ template< typename Sequence > struct apply
+ {
+ typedef typename eval_if<aux::has_begin<Sequence, true_>,
+ aux::end_type<Sequence>, void_>::type type;
+ };
+};
+
+// specialize 'begin_trait/end_trait' for two pre-defined tags
+
+# define AUX778076_IMPL_SPEC(name, tag, result) \
+template<> \
+struct name##_impl<tag> \
+{ \
+ template< typename Sequence > struct apply \
+ { \
+ typedef result type; \
+ }; \
+}; \
+/**/
+
+// a sequence with nested 'begin/end' typedefs; just query them
+AUX778076_IMPL_SPEC(begin, nested_begin_end_tag, typename Sequence::begin)
+AUX778076_IMPL_SPEC(end, nested_begin_end_tag, typename Sequence::end)
+
+// if a type 'T' does not contain 'begin/end' or 'tag' members
+// and doesn't specialize either 'begin/end' or 'begin_impl/end_impl'
+// templates, then we end up here
+AUX778076_IMPL_SPEC(begin, non_sequence_tag, void_)
+AUX778076_IMPL_SPEC(end, non_sequence_tag, void_)
+AUX778076_IMPL_SPEC(begin, na, void_)
+AUX778076_IMPL_SPEC(end, na, void_)
+
+# undef AUX778076_IMPL_SPEC
+
+
+BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC_IMPL(1,begin_impl)
+BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC_IMPL(1,end_impl)
+
+}}
+
+#endif // BOOST_MPL_AUX_BEGIN_END_IMPL_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/clear_impl.hpp b/third_party/boost/boost/mpl/aux_/clear_impl.hpp
new file mode 100644
index 0000000..1319b4e
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/clear_impl.hpp
@@ -0,0 +1,35 @@
+
+#ifndef BOOST_MPL_AUX_CLEAR_IMPL_HPP_INCLUDED
+#define BOOST_MPL_AUX_CLEAR_IMPL_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/clear_fwd.hpp>
+#include <boost/mpl/aux_/traits_lambda_spec.hpp>
+#include <boost/mpl/aux_/config/eti.hpp>
+
+namespace boost { namespace mpl {
+
+// no default implementation; the definition is needed to make MSVC happy
+
+template< typename Tag >
+struct clear_impl
+{
+ template< typename Sequence > struct apply;
+};
+
+BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(1, clear_impl)
+
+}}
+
+#endif // BOOST_MPL_AUX_CLEAR_IMPL_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/common_name_wknd.hpp b/third_party/boost/boost/mpl/aux_/common_name_wknd.hpp
new file mode 100644
index 0000000..2a81bdc
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/common_name_wknd.hpp
@@ -0,0 +1,34 @@
+
+#ifndef BOOST_MPL_AUX_COMMON_NAME_WKND_HPP_INCLUDED
+#define BOOST_MPL_AUX_COMMON_NAME_WKND_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 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/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+#if BOOST_WORKAROUND(__BORLANDC__, < 0x561)
+// agurt, 12/nov/02: to suppress the bogus "Cannot have both a template class
+// and function named 'xxx'" diagnostic
+# define BOOST_MPL_AUX_COMMON_NAME_WKND(name) \
+namespace name_##wknd { \
+template< typename > void name(); \
+} \
+/**/
+
+#else
+
+# define BOOST_MPL_AUX_COMMON_NAME_WKND(name) /**/
+
+#endif // __BORLANDC__
+
+#endif // BOOST_MPL_AUX_COMMON_NAME_WKND_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/comparison_op.hpp b/third_party/boost/boost/mpl/aux_/comparison_op.hpp
new file mode 100644
index 0000000..fd218b1
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/comparison_op.hpp
@@ -0,0 +1,83 @@
+
+// NO INCLUDE GUARDS, THE HEADER IS INTENDED FOR MULTIPLE INCLUSION
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_PREPROCESSING_MODE)
+# include <boost/mpl/bool.hpp>
+# include <boost/mpl/aux_/value_wknd.hpp>
+#endif
+
+#if !defined(AUX778076_OP_PREFIX)
+# define AUX778076_OP_PREFIX AUX778076_OP_NAME
+#endif
+
+#define AUX778076_OP_ARITY 2
+
+#include <boost/mpl/aux_/numeric_op.hpp>
+#include <boost/mpl/aux_/config/static_constant.hpp>
+#include <boost/mpl/aux_/config/use_preprocessed.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE)
+
+# define BOOST_MPL_PREPROCESSED_HEADER AUX778076_OP_PREFIX.hpp
+# include <boost/mpl/aux_/include_preprocessed.hpp>
+
+#else
+
+# include <boost/mpl/aux_/config/integral.hpp>
+# include <boost/preprocessor/cat.hpp>
+
+namespace boost { namespace mpl {
+
+// MSVC workaround: implement less in terms of greater
+#if 0 AUX778076_OP_TOKEN 1 && !(1 AUX778076_OP_TOKEN 0) && !(0 AUX778076_OP_TOKEN 0)
+# define AUX778076_OP(N1, N2) \
+ ( BOOST_MPL_AUX_VALUE_WKND(N2)::value > BOOST_MPL_AUX_VALUE_WKND(N1)::value ) \
+/**/
+#else
+# define AUX778076_OP(N1, N2) \
+ ( BOOST_MPL_AUX_VALUE_WKND(N1)::value \
+ AUX778076_OP_TOKEN BOOST_MPL_AUX_VALUE_WKND(N2)::value \
+ ) \
+/**/
+#endif
+
+template<>
+struct AUX778076_OP_IMPL_NAME<integral_c_tag,integral_c_tag>
+{
+ template< typename N1, typename N2 > struct apply
+#if !defined(BOOST_MPL_CFG_NO_NESTED_VALUE_ARITHMETIC)
+ : bool_< AUX778076_OP(N1, N2) >
+ {
+#else
+ {
+ BOOST_STATIC_CONSTANT(bool, value = AUX778076_OP(N1, N2));
+ typedef bool_<value> type;
+#endif
+ };
+};
+
+#undef AUX778076_OP
+
+}}
+
+#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+
+#undef AUX778076_OP_TAG_NAME
+#undef AUX778076_OP_IMPL_NAME
+#undef AUX778076_OP_ARITY
+#undef AUX778076_OP_PREFIX
+#undef AUX778076_OP_NAME
+#undef AUX778076_OP_TOKEN
diff --git a/third_party/boost/boost/mpl/aux_/config/adl.hpp b/third_party/boost/boost/mpl/aux_/config/adl.hpp
new file mode 100644
index 0000000..b8d02de
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/adl.hpp
@@ -0,0 +1,40 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_ADL_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_ADL_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 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/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/msvc.hpp>
+#include <boost/mpl/aux_/config/intel.hpp>
+#include <boost/mpl/aux_/config/gcc.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+// agurt, 25/apr/04: technically, the ADL workaround is only needed for GCC,
+// but putting everything expect public, user-specializable metafunctions into
+// a separate global namespace has a nice side effect of reducing the length
+// of template instantiation symbols, so we apply the workaround on all
+// platforms that can handle it
+
+#if !defined(BOOST_MPL_CFG_NO_ADL_BARRIER_NAMESPACE) \
+ && ( BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \
+ || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610)) \
+ || BOOST_WORKAROUND(__DMC__, BOOST_TESTED_AT(0x840)) \
+ || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3202)) \
+ || BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, BOOST_TESTED_AT(810)) \
+ )
+
+# define BOOST_MPL_CFG_NO_ADL_BARRIER_NAMESPACE
+
+#endif
+
+#endif // BOOST_MPL_AUX_CONFIG_ADL_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/arrays.hpp b/third_party/boost/boost/mpl/aux_/config/arrays.hpp
new file mode 100644
index 0000000..7c6998b
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/arrays.hpp
@@ -0,0 +1,30 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_ARRAYS_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_ARRAYS_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2003-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/msvc.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_DEPENDENT_ARRAY_TYPES) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE) \
+ && ( BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610)) \
+ || BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \
+ )
+
+# define BOOST_MPL_CFG_NO_DEPENDENT_ARRAY_TYPES
+
+#endif
+
+#endif // BOOST_MPL_AUX_CONFIG_ARRAYS_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/bcc.hpp b/third_party/boost/boost/mpl/aux_/config/bcc.hpp
new file mode 100644
index 0000000..e628875
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/bcc.hpp
@@ -0,0 +1,28 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_BCC_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_BCC_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2008
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date: 2004-09-02 10:41:37 -0500 (Thu, 02 Sep 2004) $
+// $Revision: 24874 $
+
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+#if !defined(BOOST_MPL_CFG_BCC590_WORKAROUNDS) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE) \
+ && BOOST_WORKAROUND(__BORLANDC__, >= 0x590) \
+ && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610))
+
+# define BOOST_MPL_CFG_BCC590_WORKAROUNDS
+
+#endif
+
+#endif // BOOST_MPL_AUX_CONFIG_BCC_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/bind.hpp b/third_party/boost/boost/mpl/aux_/config/bind.hpp
new file mode 100644
index 0000000..58a87f0
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/bind.hpp
@@ -0,0 +1,33 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_BIND_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_BIND_HPP_INCLUDED
+
+// Copyright David Abrahams 2002
+// Copyright Aleksey Gurtovoy 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/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/msvc.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_BIND_TEMPLATE) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE) \
+ && ( BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \
+ || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610)) \
+ )
+
+# define BOOST_MPL_CFG_NO_BIND_TEMPLATE
+
+#endif
+
+//#define BOOST_MPL_CFG_NO_UNNAMED_PLACEHOLDER_SUPPORT
+
+#endif // BOOST_MPL_AUX_CONFIG_BIND_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/compiler.hpp b/third_party/boost/boost/mpl/aux_/config/compiler.hpp
new file mode 100644
index 0000000..bb84638
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/compiler.hpp
@@ -0,0 +1,66 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_COMPILER_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_COMPILER_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2008
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_CFG_COMPILER_DIR)
+
+# include <boost/mpl/aux_/config/dtp.hpp>
+# include <boost/mpl/aux_/config/ttp.hpp>
+# include <boost/mpl/aux_/config/ctps.hpp>
+# include <boost/mpl/aux_/config/msvc.hpp>
+# include <boost/mpl/aux_/config/gcc.hpp>
+# include <boost/mpl/aux_/config/workaround.hpp>
+
+# if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+# define BOOST_MPL_CFG_COMPILER_DIR msvc60
+
+# elif BOOST_WORKAROUND(BOOST_MSVC, == 1300)
+# define BOOST_MPL_CFG_COMPILER_DIR msvc70
+
+# elif BOOST_WORKAROUND(BOOST_MPL_CFG_GCC, BOOST_TESTED_AT(0x0304))
+# define BOOST_MPL_CFG_COMPILER_DIR gcc
+
+# elif BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610))
+# if !defined(BOOST_MPL_CFG_NO_DEFAULT_PARAMETERS_IN_NESTED_TEMPLATES)
+# define BOOST_MPL_CFG_COMPILER_DIR bcc551
+# elif BOOST_WORKAROUND(__BORLANDC__, >= 0x590)
+# define BOOST_MPL_CFG_COMPILER_DIR bcc
+# else
+# define BOOST_MPL_CFG_COMPILER_DIR bcc_pre590
+# endif
+
+# elif BOOST_WORKAROUND(__DMC__, BOOST_TESTED_AT(0x840))
+# define BOOST_MPL_CFG_COMPILER_DIR dmc
+
+# elif defined(__MWERKS__)
+# if defined(BOOST_MPL_CFG_BROKEN_DEFAULT_PARAMETERS_IN_NESTED_TEMPLATES)
+# define BOOST_MPL_CFG_COMPILER_DIR mwcw
+# else
+# define BOOST_MPL_CFG_COMPILER_DIR plain
+# endif
+
+# elif defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+# define BOOST_MPL_CFG_COMPILER_DIR no_ctps
+
+# elif defined(BOOST_MPL_CFG_NO_TEMPLATE_TEMPLATE_PARAMETERS)
+# define BOOST_MPL_CFG_COMPILER_DIR no_ttp
+
+# else
+# define BOOST_MPL_CFG_COMPILER_DIR plain
+# endif
+
+#endif // BOOST_MPL_CFG_COMPILER_DIR
+
+#endif // BOOST_MPL_AUX_CONFIG_COMPILER_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/ctps.hpp b/third_party/boost/boost/mpl/aux_/config/ctps.hpp
new file mode 100644
index 0000000..130384f
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/ctps.hpp
@@ -0,0 +1,30 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_CTPS_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_CTPS_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/workaround.hpp>
+#include <boost/config.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_NONTYPE_TEMPLATE_PARTIAL_SPEC) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE) \
+ && BOOST_WORKAROUND(__BORLANDC__, < 0x582)
+
+# define BOOST_MPL_CFG_NO_NONTYPE_TEMPLATE_PARTIAL_SPEC
+
+#endif
+
+// BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION is defined in <boost/config.hpp>
+
+#endif // BOOST_MPL_AUX_CONFIG_CTPS_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/dtp.hpp b/third_party/boost/boost/mpl/aux_/config/dtp.hpp
new file mode 100644
index 0000000..7b76cb9
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/dtp.hpp
@@ -0,0 +1,46 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_DTP_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_DTP_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+// MWCW 7.x-8.0 "losts" default template parameters of nested class
+// templates when their owner classes are passed as arguments to other
+// templates; Borland 5.5.1 "forgets" them from the very beginning (if
+// the owner class is a class template), and Borland 5.6 isn't even
+// able to compile a definition of nested class template with DTP
+
+#if !defined(BOOST_MPL_CFG_NO_DEFAULT_PARAMETERS_IN_NESTED_TEMPLATES) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE) \
+ && BOOST_WORKAROUND(__BORLANDC__, >= 0x560) \
+ && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610))
+
+# define BOOST_MPL_CFG_NO_DEFAULT_PARAMETERS_IN_NESTED_TEMPLATES
+
+#endif
+
+
+#if !defined(BOOST_MPL_CFG_BROKEN_DEFAULT_PARAMETERS_IN_NESTED_TEMPLATES) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE) \
+ && ( BOOST_WORKAROUND(__MWERKS__, <= 0x3001) \
+ || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610)) \
+ || defined(BOOST_MPL_CFG_NO_DEFAULT_PARAMETERS_IN_NESTED_TEMPLATES) \
+ )
+
+# define BOOST_MPL_CFG_BROKEN_DEFAULT_PARAMETERS_IN_NESTED_TEMPLATES
+
+#endif
+
+#endif // BOOST_MPL_AUX_CONFIG_DTP_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/eti.hpp b/third_party/boost/boost/mpl/aux_/config/eti.hpp
new file mode 100644
index 0000000..b9e8f44
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/eti.hpp
@@ -0,0 +1,47 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_ETI_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_ETI_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/msvc.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+// flags for MSVC 6.5's so-called "early template instantiation bug"
+#if !defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE) \
+ && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+
+# define BOOST_MPL_CFG_MSVC_60_ETI_BUG
+
+#endif
+
+#if !defined(BOOST_MPL_CFG_MSVC_70_ETI_BUG) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE) \
+ && BOOST_WORKAROUND(BOOST_MSVC, == 1300)
+
+# define BOOST_MPL_CFG_MSVC_70_ETI_BUG
+
+#endif
+
+#if !defined(BOOST_MPL_CFG_MSVC_ETI_BUG) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE) \
+ && ( defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG) \
+ || defined(BOOST_MPL_CFG_MSVC_70_ETI_BUG) \
+ )
+
+# define BOOST_MPL_CFG_MSVC_ETI_BUG
+
+#endif
+
+#endif // BOOST_MPL_AUX_CONFIG_ETI_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/forwarding.hpp b/third_party/boost/boost/mpl/aux_/config/forwarding.hpp
new file mode 100644
index 0000000..9793096
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/forwarding.hpp
@@ -0,0 +1,27 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_FORWARDING_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_FORWARDING_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_NESTED_FORWARDING) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE) \
+ && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610))
+
+# define BOOST_MPL_CFG_NO_NESTED_FORWARDING
+
+#endif
+
+#endif // BOOST_MPL_AUX_CONFIG_FORWARDING_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/gcc.hpp b/third_party/boost/boost/mpl/aux_/config/gcc.hpp
new file mode 100644
index 0000000..80b7efd
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/gcc.hpp
@@ -0,0 +1,23 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_GCC_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_GCC_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if defined(__GNUC__) && !defined(__EDG_VERSION__)
+# define BOOST_MPL_CFG_GCC ((__GNUC__ << 8) | __GNUC_MINOR__)
+#else
+# define BOOST_MPL_CFG_GCC 0
+#endif
+
+#endif // BOOST_MPL_AUX_CONFIG_GCC_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/gpu.hpp b/third_party/boost/boost/mpl/aux_/config/gpu.hpp
new file mode 100644
index 0000000..0e5ed78
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/gpu.hpp
@@ -0,0 +1,35 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_GPU_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_GPU_HPP_INCLUDED
+
+// Copyright Eric Niebler 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)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/config.hpp>
+
+#if !defined(BOOST_MPL_CFG_GPU_ENABLED) \
+
+# define BOOST_MPL_CFG_GPU_ENABLED BOOST_GPU_ENABLED
+
+#endif
+
+#if defined __CUDACC__
+
+# define BOOST_MPL_CFG_GPU 1
+
+#else
+
+# define BOOST_MPL_CFG_GPU 0
+
+#endif
+
+#endif // BOOST_MPL_AUX_CONFIG_GPU_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/has_apply.hpp b/third_party/boost/boost/mpl/aux_/config/has_apply.hpp
new file mode 100644
index 0000000..ec85046
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/has_apply.hpp
@@ -0,0 +1,32 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_HAS_APPLY_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_HAS_APPLY_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/has_xxx.hpp>
+#include <boost/mpl/aux_/config/msvc.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_HAS_APPLY) \
+ && ( defined(BOOST_MPL_CFG_NO_HAS_XXX) \
+ || BOOST_WORKAROUND(__EDG_VERSION__, < 300) \
+ || BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \
+ || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3202)) \
+ )
+
+# define BOOST_MPL_CFG_NO_HAS_APPLY
+
+#endif
+
+#endif // BOOST_MPL_AUX_CONFIG_HAS_APPLY_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/has_xxx.hpp b/third_party/boost/boost/mpl/aux_/config/has_xxx.hpp
new file mode 100644
index 0000000..d9198a7
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/has_xxx.hpp
@@ -0,0 +1,34 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_HAS_XXX_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_HAS_XXX_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2002-2004
+// Copyright David Abrahams 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/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/overload_resolution.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+// agurt, 11/jan/03: signals a stub-only 'has_xxx' implementation
+
+#if !defined(BOOST_MPL_CFG_NO_HAS_XXX) \
+ && ( defined(BOOST_MPL_CFG_BROKEN_OVERLOAD_RESOLUTION) \
+ || BOOST_WORKAROUND(__GNUC__, <= 2) \
+ || BOOST_WORKAROUND(__DMC__, BOOST_TESTED_AT(0x840)) \
+ )
+
+# define BOOST_MPL_CFG_NO_HAS_XXX
+# define BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE
+
+#endif
+
+#endif // BOOST_MPL_AUX_CONFIG_HAS_XXX_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/integral.hpp b/third_party/boost/boost/mpl/aux_/config/integral.hpp
new file mode 100644
index 0000000..46ac9b2
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/integral.hpp
@@ -0,0 +1,38 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_INTEGRAL_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_INTEGRAL_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/msvc.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+#if !defined(BOOST_MPL_CFG_BCC_INTEGRAL_CONSTANTS) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE) \
+ && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610))
+
+# define BOOST_MPL_CFG_BCC_INTEGRAL_CONSTANTS
+
+#endif
+
+#if !defined(BOOST_MPL_CFG_NO_NESTED_VALUE_ARITHMETIC) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE) \
+ && ( BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \
+ || BOOST_WORKAROUND(__EDG_VERSION__, <= 238) \
+ )
+
+# define BOOST_MPL_CFG_NO_NESTED_VALUE_ARITHMETIC
+
+#endif
+
+#endif // BOOST_MPL_AUX_CONFIG_INTEGRAL_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/intel.hpp b/third_party/boost/boost/mpl/aux_/config/intel.hpp
new file mode 100644
index 0000000..da01738
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/intel.hpp
@@ -0,0 +1,21 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_INTEL_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_INTEL_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+
+// BOOST_INTEL_CXX_VERSION is defined here:
+#include <boost/config.hpp>
+
+#endif // BOOST_MPL_AUX_CONFIG_INTEL_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/lambda.hpp b/third_party/boost/boost/mpl/aux_/config/lambda.hpp
new file mode 100644
index 0000000..b6d91b5
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/lambda.hpp
@@ -0,0 +1,32 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_LAMBDA_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_LAMBDA_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 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/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/ttp.hpp>
+#include <boost/mpl/aux_/config/ctps.hpp>
+
+// agurt, 15/jan/02: full-fledged implementation requires both
+// template template parameters _and_ partial specialization
+
+#if !defined(BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT) \
+ && ( defined(BOOST_MPL_CFG_NO_TEMPLATE_TEMPLATE_PARAMETERS) \
+ || defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
+ )
+
+# define BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT
+
+#endif
+
+#endif // BOOST_MPL_AUX_CONFIG_LAMBDA_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/msvc.hpp b/third_party/boost/boost/mpl/aux_/config/msvc.hpp
new file mode 100644
index 0000000..8b9ae41
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/msvc.hpp
@@ -0,0 +1,21 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_MSVC_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_MSVC_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 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/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+
+// BOOST_MSVC is defined here:
+#include <boost/config.hpp>
+
+#endif // BOOST_MPL_AUX_CONFIG_MSVC_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/msvc_typename.hpp b/third_party/boost/boost/mpl/aux_/config/msvc_typename.hpp
new file mode 100644
index 0000000..7577908
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/msvc_typename.hpp
@@ -0,0 +1,26 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_MSVC_TYPENAME_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_MSVC_TYPENAME_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/msvc.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
+# define BOOST_MSVC_TYPENAME
+#else
+# define BOOST_MSVC_TYPENAME typename
+#endif
+
+#endif // BOOST_MPL_AUX_CONFIG_MSVC_TYPENAME_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/nttp.hpp b/third_party/boost/boost/mpl/aux_/config/nttp.hpp
new file mode 100644
index 0000000..85233ef
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/nttp.hpp
@@ -0,0 +1,41 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_NTTP_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_NTTP_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/msvc.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+// MSVC 6.5 ICE-s on the code as simple as this (see "aux_/nttp_decl.hpp"
+// for a workaround):
+//
+// namespace std {
+// template< typename Char > struct string;
+// }
+//
+// void foo(std::string<char>);
+//
+// namespace boost { namespace mpl {
+// template< int > struct arg;
+// }}
+
+#if !defined(BOOST_MPL_CFG_NTTP_BUG) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE) \
+ && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+
+# define BOOST_MPL_CFG_NTTP_BUG
+
+#endif
+
+#endif // BOOST_MPL_AUX_CONFIG_NTTP_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/overload_resolution.hpp b/third_party/boost/boost/mpl/aux_/config/overload_resolution.hpp
new file mode 100644
index 0000000..8ac8259
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/overload_resolution.hpp
@@ -0,0 +1,29 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_OVERLOAD_RESOLUTION_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_OVERLOAD_RESOLUTION_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 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/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+#if !defined(BOOST_MPL_CFG_BROKEN_OVERLOAD_RESOLUTION) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE) \
+ && ( BOOST_WORKAROUND(__BORLANDC__, < 0x590) \
+ || BOOST_WORKAROUND(__MWERKS__, < 0x3001) \
+ )
+
+# define BOOST_MPL_CFG_BROKEN_OVERLOAD_RESOLUTION
+
+#endif
+
+#endif // BOOST_MPL_AUX_CONFIG_OVERLOAD_RESOLUTION_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/pp_counter.hpp b/third_party/boost/boost/mpl/aux_/config/pp_counter.hpp
new file mode 100644
index 0000000..a0d1340
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/pp_counter.hpp
@@ -0,0 +1,26 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_PP_COUNTER_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_PP_COUNTER_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2006
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_AUX_PP_COUNTER)
+# include <boost/mpl/aux_/config/msvc.hpp>
+# if BOOST_WORKAROUND(BOOST_MSVC, >= 1300)
+# define BOOST_MPL_AUX_PP_COUNTER() __COUNTER__
+# else
+# define BOOST_MPL_AUX_PP_COUNTER() __LINE__
+# endif
+#endif
+
+#endif // BOOST_MPL_AUX_CONFIG_PP_COUNTER_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/preprocessor.hpp b/third_party/boost/boost/mpl/aux_/config/preprocessor.hpp
new file mode 100644
index 0000000..1522724
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/preprocessor.hpp
@@ -0,0 +1,39 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_PREPROCESSOR_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_PREPROCESSOR_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+#if !defined(BOOST_MPL_CFG_BROKEN_PP_MACRO_EXPANSION) \
+ && ( BOOST_WORKAROUND(__MWERKS__, <= 0x3003) \
+ || BOOST_WORKAROUND(__BORLANDC__, < 0x582) \
+ || BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(502)) \
+ )
+
+# define BOOST_MPL_CFG_BROKEN_PP_MACRO_EXPANSION
+
+#endif
+
+#if !defined(BOOST_MPL_CFG_NO_OWN_PP_PRIMITIVES)
+# define BOOST_MPL_CFG_NO_OWN_PP_PRIMITIVES
+#endif
+
+#if !defined(BOOST_NEEDS_TOKEN_PASTING_OP_FOR_TOKENS_JUXTAPOSING) \
+ && BOOST_WORKAROUND(__DMC__, BOOST_TESTED_AT(0x840))
+# define BOOST_NEEDS_TOKEN_PASTING_OP_FOR_TOKENS_JUXTAPOSING
+#endif
+
+
+#endif // BOOST_MPL_AUX_CONFIG_PREPROCESSOR_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/static_constant.hpp b/third_party/boost/boost/mpl/aux_/config/static_constant.hpp
new file mode 100644
index 0000000..90b5ce5
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/static_constant.hpp
@@ -0,0 +1,25 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_STATIC_CONSTANT_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_STATIC_CONSTANT_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_PREPROCESSING_MODE)
+// BOOST_STATIC_CONSTANT is defined here:
+# include <boost/config.hpp>
+#else
+// undef the macro for the preprocessing mode
+# undef BOOST_STATIC_CONSTANT
+#endif
+
+#endif // BOOST_MPL_AUX_CONFIG_STATIC_CONSTANT_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/ttp.hpp b/third_party/boost/boost/mpl/aux_/config/ttp.hpp
new file mode 100644
index 0000000..cb68533
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/ttp.hpp
@@ -0,0 +1,41 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_TTP_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_TTP_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/msvc.hpp>
+#include <boost/mpl/aux_/config/gcc.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_TEMPLATE_TEMPLATE_PARAMETERS) \
+ && ( defined(BOOST_NO_TEMPLATE_TEMPLATES) \
+ || BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x590) ) \
+ )
+
+# define BOOST_MPL_CFG_NO_TEMPLATE_TEMPLATE_PARAMETERS
+
+#endif
+
+
+#if !defined(BOOST_MPL_CFG_EXTENDED_TEMPLATE_PARAMETERS_MATCHING) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE) \
+ && ( BOOST_WORKAROUND(BOOST_MPL_CFG_GCC, BOOST_TESTED_AT(0x0302)) \
+ || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610)) \
+ )
+
+# define BOOST_MPL_CFG_EXTENDED_TEMPLATE_PARAMETERS_MATCHING
+
+#endif
+
+#endif // BOOST_MPL_AUX_CONFIG_TTP_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/use_preprocessed.hpp b/third_party/boost/boost/mpl/aux_/config/use_preprocessed.hpp
new file mode 100644
index 0000000..a741e55
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/use_preprocessed.hpp
@@ -0,0 +1,19 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_USE_PREPROCESSED_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_USE_PREPROCESSED_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+// #define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+
+#endif // BOOST_MPL_AUX_CONFIG_USE_PREPROCESSED_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/config/workaround.hpp b/third_party/boost/boost/mpl/aux_/config/workaround.hpp
new file mode 100644
index 0000000..b379bfd
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/config/workaround.hpp
@@ -0,0 +1,19 @@
+
+#ifndef BOOST_MPL_AUX_CONFIG_WORKAROUND_HPP_INCLUDED
+#define BOOST_MPL_AUX_CONFIG_WORKAROUND_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 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/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/detail/workaround.hpp>
+
+#endif // BOOST_MPL_AUX_CONFIG_WORKAROUND_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/empty_impl.hpp b/third_party/boost/boost/mpl/aux_/empty_impl.hpp
new file mode 100644
index 0000000..aeb0caa
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/empty_impl.hpp
@@ -0,0 +1,43 @@
+
+#ifndef BOOST_MPL_AUX_EMPTY_IMPL_HPP_INCLUDED
+#define BOOST_MPL_AUX_EMPTY_IMPL_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/empty_fwd.hpp>
+#include <boost/mpl/begin_end.hpp>
+#include <boost/mpl/aux_/traits_lambda_spec.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+namespace boost { namespace mpl {
+
+// default implementation; conrete sequences might override it by
+// specializing either the 'empty_impl' or the primary 'empty' template
+
+template< typename Tag >
+struct empty_impl
+{
+ template< typename Sequence > struct apply
+ : is_same<
+ typename begin<Sequence>::type
+ , typename end<Sequence>::type
+ >
+ {
+ };
+};
+
+BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(1,empty_impl)
+
+}}
+
+#endif // BOOST_MPL_AUX_EMPTY_IMPL_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/find_if_pred.hpp b/third_party/boost/boost/mpl/aux_/find_if_pred.hpp
new file mode 100644
index 0000000..ebff52a
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/find_if_pred.hpp
@@ -0,0 +1,31 @@
+
+#ifndef BOOST_MPL_AUX_FIND_IF_PRED_HPP_INCLUDED
+#define BOOST_MPL_AUX_FIND_IF_PRED_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+// Copyright Eric Friedman 2002
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+#include <boost/mpl/aux_/iter_apply.hpp>
+#include <boost/mpl/not.hpp>
+
+namespace boost { namespace mpl { namespace aux {
+
+template< typename Predicate >
+struct find_if_pred
+{
+ template< typename Iterator >
+ struct apply
+ {
+ typedef not_< aux::iter_apply1<Predicate,Iterator> > type;
+ };
+};
+
+}}}
+
+#endif // BOOST_MPL_AUX_FIND_IF_PRED_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/fold_impl.hpp b/third_party/boost/boost/mpl/aux_/fold_impl.hpp
new file mode 100644
index 0000000..75ff7ba
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/fold_impl.hpp
@@ -0,0 +1,43 @@
+
+#ifndef BOOST_MPL_AUX_FOLD_IMPL_HPP_INCLUDED
+#define BOOST_MPL_AUX_FOLD_IMPL_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_PREPROCESSING_MODE)
+# include <boost/mpl/next_prior.hpp>
+# include <boost/mpl/apply.hpp>
+# include <boost/mpl/deref.hpp>
+# include <boost/mpl/aux_/config/ctps.hpp>
+# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+# include <boost/mpl/if.hpp>
+# include <boost/type_traits/is_same.hpp>
+# endif
+#endif
+
+#include <boost/mpl/aux_/config/use_preprocessed.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE)
+
+# define BOOST_MPL_PREPROCESSED_HEADER fold_impl.hpp
+# include <boost/mpl/aux_/include_preprocessed.hpp>
+
+#else
+
+# define AUX778076_FOLD_IMPL_OP(iter) typename deref<iter>::type
+# define AUX778076_FOLD_IMPL_NAME_PREFIX fold
+# include <boost/mpl/aux_/fold_impl_body.hpp>
+
+#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#endif // BOOST_MPL_AUX_FOLD_IMPL_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/front_impl.hpp b/third_party/boost/boost/mpl/aux_/front_impl.hpp
new file mode 100644
index 0000000..6e4ef74
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/front_impl.hpp
@@ -0,0 +1,41 @@
+
+#ifndef BOOST_MPL_AUX_FRONT_IMPL_HPP_INCLUDED
+#define BOOST_MPL_AUX_FRONT_IMPL_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/front_fwd.hpp>
+#include <boost/mpl/begin_end.hpp>
+#include <boost/mpl/deref.hpp>
+#include <boost/mpl/aux_/traits_lambda_spec.hpp>
+
+namespace boost { namespace mpl {
+
+// default implementation; conrete sequences might override it by
+// specializing either the 'front_impl' or the primary 'front' template
+
+template< typename Tag >
+struct front_impl
+{
+ template< typename Sequence > struct apply
+ {
+ typedef typename begin<Sequence>::type iter_;
+ typedef typename deref<iter_>::type type;
+ };
+};
+
+BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(1,front_impl)
+
+}}
+
+#endif // BOOST_MPL_AUX_FRONT_IMPL_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/full_lambda.hpp b/third_party/boost/boost/mpl/aux_/full_lambda.hpp
new file mode 100644
index 0000000..0218781
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/full_lambda.hpp
@@ -0,0 +1,354 @@
+
+#if !defined(BOOST_PP_IS_ITERATING)
+
+///// header body
+
+#ifndef BOOST_MPL_AUX_FULL_LAMBDA_HPP_INCLUDED
+#define BOOST_MPL_AUX_FULL_LAMBDA_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_PREPROCESSING_MODE)
+# include <boost/mpl/lambda_fwd.hpp>
+# include <boost/mpl/bind_fwd.hpp>
+# include <boost/mpl/protect.hpp>
+# include <boost/mpl/quote.hpp>
+# include <boost/mpl/arg.hpp>
+# include <boost/mpl/bool.hpp>
+# include <boost/mpl/int_fwd.hpp>
+# include <boost/mpl/aux_/template_arity.hpp>
+# include <boost/mpl/aux_/na_spec.hpp>
+# include <boost/mpl/aux_/config/ttp.hpp>
+# if defined(BOOST_MPL_CFG_EXTENDED_TEMPLATE_PARAMETERS_MATCHING)
+# include <boost/mpl/if.hpp>
+# endif
+#endif
+
+#include <boost/mpl/aux_/lambda_arity_param.hpp>
+#include <boost/mpl/aux_/config/use_preprocessed.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE)
+
+# define BOOST_MPL_PREPROCESSED_HEADER full_lambda.hpp
+# include <boost/mpl/aux_/include_preprocessed.hpp>
+
+#else
+
+# include <boost/mpl/limits/arity.hpp>
+# include <boost/mpl/aux_/preprocessor/default_params.hpp>
+# include <boost/mpl/aux_/preprocessor/params.hpp>
+# include <boost/mpl/aux_/preprocessor/enum.hpp>
+# include <boost/mpl/aux_/preprocessor/repeat.hpp>
+# include <boost/mpl/aux_/config/dmc_ambiguous_ctps.hpp>
+
+# include <boost/preprocessor/iterate.hpp>
+# include <boost/preprocessor/comma_if.hpp>
+# include <boost/preprocessor/inc.hpp>
+# include <boost/preprocessor/cat.hpp>
+
+namespace boost { namespace mpl {
+
+// local macros, #undef-ined at the end of the header
+# define AUX778076_LAMBDA_PARAMS(i_, param) \
+ BOOST_MPL_PP_PARAMS(i_, param) \
+ /**/
+
+# define AUX778076_BIND_PARAMS(param) \
+ BOOST_MPL_PP_PARAMS( \
+ BOOST_MPL_LIMIT_METAFUNCTION_ARITY \
+ , param \
+ ) \
+ /**/
+
+# define AUX778076_BIND_N_PARAMS(i_, param) \
+ BOOST_PP_COMMA_IF(i_) \
+ BOOST_MPL_PP_PARAMS(i_, param) \
+ /**/
+
+# define AUX778076_ARITY_PARAM(param) \
+ BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(param) \
+ /**/
+
+
+#define n_ BOOST_MPL_LIMIT_METAFUNCTION_ARITY
+namespace aux {
+
+template<
+ BOOST_MPL_PP_DEFAULT_PARAMS(n_,bool C,false)
+ >
+struct lambda_or
+ : true_
+{
+};
+
+template<>
+struct lambda_or< BOOST_MPL_PP_ENUM(n_,false) >
+ : false_
+{
+};
+
+} // namespace aux
+#undef n_
+
+template<
+ typename T
+ , typename Tag
+ AUX778076_ARITY_PARAM(typename Arity)
+ >
+struct lambda
+{
+ typedef false_ is_le;
+ typedef T result_;
+ typedef T type;
+};
+
+template<
+ typename T
+ >
+struct is_lambda_expression
+ : lambda<T>::is_le
+{
+};
+
+
+template< int N, typename Tag >
+struct lambda< arg<N>,Tag AUX778076_ARITY_PARAM(int_<-1>) >
+{
+ typedef true_ is_le;
+ typedef mpl::arg<N> result_; // qualified for the sake of MIPSpro 7.41
+ typedef mpl::protect<result_> type;
+};
+
+
+#define BOOST_PP_ITERATION_PARAMS_1 \
+ (3,(0, BOOST_MPL_LIMIT_METAFUNCTION_ARITY, <boost/mpl/aux_/full_lambda.hpp>))
+#include BOOST_PP_ITERATE()
+
+/// special case for 'protect'
+template< typename T, typename Tag >
+struct lambda< mpl::protect<T>,Tag AUX778076_ARITY_PARAM(int_<1>) >
+{
+ typedef false_ is_le;
+ typedef mpl::protect<T> result_;
+ typedef result_ type;
+};
+
+/// specializations for the main 'bind' form
+template<
+ typename F, AUX778076_BIND_PARAMS(typename T)
+ , typename Tag
+ >
+struct lambda<
+ bind<F,AUX778076_BIND_PARAMS(T)>
+ , Tag
+ AUX778076_ARITY_PARAM(int_<BOOST_PP_INC(BOOST_MPL_LIMIT_METAFUNCTION_ARITY)>)
+ >
+{
+ typedef false_ is_le;
+ typedef bind<F, AUX778076_BIND_PARAMS(T)> result_;
+ typedef result_ type;
+};
+
+
+#if defined(BOOST_MPL_CFG_EXTENDED_TEMPLATE_PARAMETERS_MATCHING)
+
+template<
+ typename F
+ , typename Tag1
+ , typename Tag2
+ , typename Arity
+ >
+struct lambda<
+ lambda<F,Tag1,Arity>
+ , Tag2
+ , int_<3>
+ >
+{
+ typedef lambda< F,Tag2 > l1;
+ typedef lambda< Tag1,Tag2 > l2;
+
+ typedef typename l1::is_le is_le;
+ typedef bind1< quote1<aux::template_arity>, typename l1::result_ > arity_;
+ typedef lambda< typename if_<is_le,arity_,Arity>::type,Tag2 > l3;
+
+ typedef aux::le_result3<is_le, Tag2, mpl::lambda, l1, l2, l3> le_result_;
+ typedef typename le_result_::result_ result_;
+ typedef typename le_result_::type type;
+};
+
+#elif !defined(BOOST_MPL_CFG_DMC_AMBIGUOUS_CTPS)
+
+/// workaround for MWCW 8.3+/EDG < 303, leads to ambiguity on Digital Mars
+template<
+ typename F, typename Tag1, typename Tag2
+ >
+struct lambda<
+ lambda< F,Tag1 >
+ , Tag2
+ >
+{
+ typedef lambda< F,Tag2 > l1;
+ typedef lambda< Tag1,Tag2 > l2;
+
+ typedef typename l1::is_le is_le;
+ typedef aux::le_result2<is_le, Tag2, mpl::lambda, l1, l2> le_result_;
+ typedef typename le_result_::result_ result_;
+ typedef typename le_result_::type type;
+};
+
+#endif
+
+# undef AUX778076_ARITY_PARAM
+# undef AUX778076_BIND_N_PARAMS
+# undef AUX778076_BIND_PARAMS
+# undef AUX778076_LAMBDA_PARAMS
+
+#if !defined(BOOST_MPL_CFG_EXTENDED_TEMPLATE_PARAMETERS_MATCHING)
+BOOST_MPL_AUX_NA_SPEC(2, lambda)
+#else
+BOOST_MPL_AUX_NA_SPEC2(2, 3, lambda)
+#endif
+
+}}
+
+#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#endif // BOOST_MPL_AUX_FULL_LAMBDA_HPP_INCLUDED
+
+///// iteration, depth == 1
+
+// For gcc 4.4 compatability, we must include the
+// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
+#else // BOOST_PP_IS_ITERATING
+#if BOOST_PP_ITERATION_DEPTH() == 1
+#define i_ BOOST_PP_FRAME_ITERATION(1)
+
+#if i_ > 0
+
+namespace aux {
+
+# define AUX778076_RESULT(unused, i_, T) \
+ BOOST_PP_COMMA_IF(i_) \
+ typename BOOST_PP_CAT(T, BOOST_PP_INC(i_))::result_ \
+ /**/
+
+# define AUX778076_TYPE(unused, i_, T) \
+ BOOST_PP_COMMA_IF(i_) \
+ typename BOOST_PP_CAT(T, BOOST_PP_INC(i_))::type \
+ /**/
+
+template<
+ typename IsLE, typename Tag
+ , template< AUX778076_LAMBDA_PARAMS(i_, typename P) > class F
+ , AUX778076_LAMBDA_PARAMS(i_, typename L)
+ >
+struct BOOST_PP_CAT(le_result,i_)
+{
+ typedef F<
+ BOOST_MPL_PP_REPEAT(i_, AUX778076_TYPE, L)
+ > result_;
+
+ typedef result_ type;
+};
+
+template<
+ typename Tag
+ , template< AUX778076_LAMBDA_PARAMS(i_, typename P) > class F
+ , AUX778076_LAMBDA_PARAMS(i_, typename L)
+ >
+struct BOOST_PP_CAT(le_result,i_)< true_,Tag,F,AUX778076_LAMBDA_PARAMS(i_, L) >
+{
+ typedef BOOST_PP_CAT(bind,i_)<
+ BOOST_PP_CAT(quote,i_)<F,Tag>
+ , BOOST_MPL_PP_REPEAT(i_, AUX778076_RESULT, L)
+ > result_;
+
+ typedef mpl::protect<result_> type;
+};
+
+# undef AUX778076_TYPE
+# undef AUX778076_RESULT
+
+} // namespace aux
+
+
+# define AUX778076_LAMBDA_TYPEDEF(unused, i_, T) \
+ typedef lambda< BOOST_PP_CAT(T, BOOST_PP_INC(i_)), Tag > \
+ BOOST_PP_CAT(l,BOOST_PP_INC(i_)); \
+/**/
+
+# define AUX778076_IS_LE_TYPEDEF(unused, i_, unused2) \
+ typedef typename BOOST_PP_CAT(l,BOOST_PP_INC(i_))::is_le \
+ BOOST_PP_CAT(is_le,BOOST_PP_INC(i_)); \
+/**/
+
+# define AUX778076_IS_LAMBDA_EXPR(unused, i_, unused2) \
+ BOOST_PP_COMMA_IF(i_) \
+ BOOST_PP_CAT(is_le,BOOST_PP_INC(i_))::value \
+/**/
+
+template<
+ template< AUX778076_LAMBDA_PARAMS(i_, typename P) > class F
+ , AUX778076_LAMBDA_PARAMS(i_, typename T)
+ , typename Tag
+ >
+struct lambda<
+ F<AUX778076_LAMBDA_PARAMS(i_, T)>
+ , Tag
+ AUX778076_ARITY_PARAM(int_<i_>)
+ >
+{
+ BOOST_MPL_PP_REPEAT(i_, AUX778076_LAMBDA_TYPEDEF, T)
+ BOOST_MPL_PP_REPEAT(i_, AUX778076_IS_LE_TYPEDEF, unused)
+
+ typedef typename aux::lambda_or<
+ BOOST_MPL_PP_REPEAT(i_, AUX778076_IS_LAMBDA_EXPR, unused)
+ >::type is_le;
+
+ typedef aux::BOOST_PP_CAT(le_result,i_)<
+ is_le, Tag, F, AUX778076_LAMBDA_PARAMS(i_, l)
+ > le_result_;
+
+ typedef typename le_result_::result_ result_;
+ typedef typename le_result_::type type;
+};
+
+
+# undef AUX778076_IS_LAMBDA_EXPR
+# undef AUX778076_IS_LE_TYPEDEF
+# undef AUX778076_LAMBDA_TYPEDEF
+
+#endif // i_ > 0
+
+template<
+ typename F AUX778076_BIND_N_PARAMS(i_, typename T)
+ , typename Tag
+ >
+struct lambda<
+ BOOST_PP_CAT(bind,i_)<F AUX778076_BIND_N_PARAMS(i_, T)>
+ , Tag
+ AUX778076_ARITY_PARAM(int_<BOOST_PP_INC(i_)>)
+ >
+{
+ typedef false_ is_le;
+ typedef BOOST_PP_CAT(bind,i_)<
+ F
+ AUX778076_BIND_N_PARAMS(i_, T)
+ > result_;
+
+ typedef result_ type;
+};
+
+#undef i_
+#endif // BOOST_PP_ITERATION_DEPTH()
+#endif // BOOST_PP_IS_ITERATING
diff --git a/third_party/boost/boost/mpl/aux_/has_apply.hpp b/third_party/boost/boost/mpl/aux_/has_apply.hpp
new file mode 100644
index 0000000..0bc3b52
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/has_apply.hpp
@@ -0,0 +1,32 @@
+
+#ifndef BOOST_MPL_AUX_HAS_APPLY_HPP_INCLUDED
+#define BOOST_MPL_AUX_HAS_APPLY_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/has_xxx.hpp>
+#include <boost/mpl/aux_/config/has_apply.hpp>
+
+namespace boost { namespace mpl { namespace aux {
+#if !defined(BOOST_MPL_CFG_NO_HAS_APPLY)
+BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_apply, apply, false)
+#else
+template< typename T, typename fallback_ = false_ >
+struct has_apply
+ : fallback_
+{
+};
+#endif
+}}}
+
+#endif // BOOST_MPL_AUX_HAS_APPLY_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/has_begin.hpp b/third_party/boost/boost/mpl/aux_/has_begin.hpp
new file mode 100644
index 0000000..bfb0fee
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/has_begin.hpp
@@ -0,0 +1,23 @@
+
+#ifndef BOOST_MPL_AUX_HAS_BEGIN_HPP_INCLUDED
+#define BOOST_MPL_AUX_HAS_BEGIN_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 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/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/has_xxx.hpp>
+
+namespace boost { namespace mpl { namespace aux {
+BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_begin, begin, true)
+}}}
+
+#endif // BOOST_MPL_AUX_HAS_BEGIN_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/has_size.hpp b/third_party/boost/boost/mpl/aux_/has_size.hpp
new file mode 100644
index 0000000..83dbfe7
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/has_size.hpp
@@ -0,0 +1,23 @@
+
+#ifndef BOOST_MPL_AUX_HAS_SIZE_HPP_INCLUDED
+#define BOOST_MPL_AUX_HAS_SIZE_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 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/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/has_xxx.hpp>
+
+namespace boost { namespace mpl { namespace aux {
+BOOST_MPL_HAS_XXX_TRAIT_DEF(size)
+}}}
+
+#endif // BOOST_MPL_AUX_HAS_SIZE_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/has_tag.hpp b/third_party/boost/boost/mpl/aux_/has_tag.hpp
new file mode 100644
index 0000000..55154a1
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/has_tag.hpp
@@ -0,0 +1,23 @@
+
+#ifndef BOOST_MPL_AUX_HAS_TAG_HPP_INCLUDED
+#define BOOST_MPL_AUX_HAS_TAG_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 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/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/has_xxx.hpp>
+
+namespace boost { namespace mpl { namespace aux {
+BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_tag, tag, false)
+}}}
+
+#endif // BOOST_MPL_AUX_HAS_TAG_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/has_type.hpp b/third_party/boost/boost/mpl/aux_/has_type.hpp
new file mode 100644
index 0000000..6f37667
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/has_type.hpp
@@ -0,0 +1,23 @@
+
+#ifndef BOOST_MPL_AUX_HAS_TYPE_HPP_INCLUDED
+#define BOOST_MPL_AUX_HAS_TYPE_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 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/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/has_xxx.hpp>
+
+namespace boost { namespace mpl { namespace aux {
+BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_type, type, true)
+}}}
+
+#endif // BOOST_MPL_AUX_HAS_TYPE_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/include_preprocessed.hpp b/third_party/boost/boost/mpl/aux_/include_preprocessed.hpp
new file mode 100644
index 0000000..7698b5a
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/include_preprocessed.hpp
@@ -0,0 +1,42 @@
+
+// NO INCLUDE GUARDS, THE HEADER IS INTENDED FOR MULTIPLE INCLUSION
+
+// Copyright Aleksey Gurtovoy 2000-2006
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/compiler.hpp>
+#include <boost/mpl/aux_/config/preprocessor.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/stringize.hpp>
+
+#if !defined(BOOST_NEEDS_TOKEN_PASTING_OP_FOR_TOKENS_JUXTAPOSING)
+# define AUX778076_PREPROCESSED_HEADER \
+ BOOST_MPL_CFG_COMPILER_DIR/BOOST_MPL_PREPROCESSED_HEADER \
+/**/
+#else
+# define AUX778076_PREPROCESSED_HEADER \
+ BOOST_PP_CAT(BOOST_MPL_CFG_COMPILER_DIR,/)##BOOST_MPL_PREPROCESSED_HEADER \
+/**/
+#endif
+
+#if BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(700))
+# define AUX778076_INCLUDE_STRING BOOST_PP_STRINGIZE(boost/mpl/aux_/preprocessed/AUX778076_PREPROCESSED_HEADER)
+# include AUX778076_INCLUDE_STRING
+# undef AUX778076_INCLUDE_STRING
+#else
+# include BOOST_PP_STRINGIZE(boost/mpl/aux_/preprocessed/AUX778076_PREPROCESSED_HEADER)
+#endif
+
+# undef AUX778076_PREPROCESSED_HEADER
+
+#undef BOOST_MPL_PREPROCESSED_HEADER
diff --git a/third_party/boost/boost/mpl/aux_/inserter_algorithm.hpp b/third_party/boost/boost/mpl/aux_/inserter_algorithm.hpp
new file mode 100644
index 0000000..21f58b3
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/inserter_algorithm.hpp
@@ -0,0 +1,159 @@
+
+#ifndef BOOST_MPL_AUX_INSERTER_ALGORITHM_HPP_INCLUDED
+#define BOOST_MPL_AUX_INSERTER_ALGORITHM_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2003-2004
+// Copyright David Abrahams 2003-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/back_inserter.hpp>
+#include <boost/mpl/front_inserter.hpp>
+#include <boost/mpl/push_back.hpp>
+#include <boost/mpl/push_front.hpp>
+#include <boost/mpl/back_inserter.hpp>
+#include <boost/mpl/front_inserter.hpp>
+#include <boost/mpl/clear.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/mpl/aux_/common_name_wknd.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/preprocessor/params.hpp>
+#include <boost/mpl/aux_/preprocessor/default_params.hpp>
+#include <boost/mpl/aux_/config/ctps.hpp>
+
+#include <boost/preprocessor/arithmetic/dec.hpp>
+
+#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+
+# define BOOST_MPL_AUX_INSERTER_ALGORITHM_DEF(arity, name) \
+BOOST_MPL_AUX_COMMON_NAME_WKND(name) \
+template< \
+ BOOST_MPL_PP_DEFAULT_PARAMS(arity, typename P, na) \
+ > \
+struct name \
+ : aux::name##_impl<BOOST_MPL_PP_PARAMS(arity, P)> \
+{ \
+}; \
+\
+template< \
+ BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), typename P) \
+ > \
+struct name< BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P),na > \
+ : if_< has_push_back< typename clear<P1>::type> \
+ , aux::name##_impl< \
+ BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P) \
+ , back_inserter< typename clear<P1>::type > \
+ > \
+ , aux::reverse_##name##_impl< \
+ BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P) \
+ , front_inserter< typename clear<P1>::type > \
+ > \
+ >::type \
+{ \
+}; \
+\
+template< \
+ BOOST_MPL_PP_DEFAULT_PARAMS(arity, typename P, na) \
+ > \
+struct reverse_##name \
+ : aux::reverse_##name##_impl<BOOST_MPL_PP_PARAMS(arity, P)> \
+{ \
+}; \
+\
+template< \
+ BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), typename P) \
+ > \
+struct reverse_##name< BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P),na > \
+ : if_< has_push_back<P1> \
+ , aux::reverse_##name##_impl< \
+ BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P) \
+ , back_inserter< typename clear<P1>::type > \
+ > \
+ , aux::name##_impl< \
+ BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P) \
+ , front_inserter< typename clear<P1>::type > \
+ > \
+ >::type \
+{ \
+}; \
+BOOST_MPL_AUX_NA_SPEC(arity, name) \
+BOOST_MPL_AUX_NA_SPEC(arity, reverse_##name) \
+/**/
+
+#else
+
+# define BOOST_MPL_AUX_INSERTER_ALGORITHM_DEF(arity, name) \
+BOOST_MPL_AUX_COMMON_NAME_WKND(name) \
+template< \
+ BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), typename P) \
+ > \
+struct def_##name##_impl \
+ : if_< has_push_back<P1> \
+ , aux::name##_impl< \
+ BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P) \
+ , back_inserter< typename clear<P1>::type > \
+ > \
+ , aux::reverse_##name##_impl< \
+ BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P) \
+ , front_inserter< typename clear<P1>::type > \
+ > \
+ >::type \
+{ \
+}; \
+\
+template< \
+ BOOST_MPL_PP_DEFAULT_PARAMS(arity, typename P, na) \
+ > \
+struct name \
+{ \
+ typedef typename eval_if< \
+ is_na<BOOST_PP_CAT(P, arity)> \
+ , def_##name##_impl<BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P)> \
+ , aux::name##_impl<BOOST_MPL_PP_PARAMS(arity, P)> \
+ >::type type; \
+}; \
+\
+template< \
+ BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), typename P) \
+ > \
+struct def_reverse_##name##_impl \
+ : if_< has_push_back<P1> \
+ , aux::reverse_##name##_impl< \
+ BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P) \
+ , back_inserter< typename clear<P1>::type > \
+ > \
+ , aux::name##_impl< \
+ BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P) \
+ , front_inserter< typename clear<P1>::type > \
+ > \
+ >::type \
+{ \
+}; \
+template< \
+ BOOST_MPL_PP_DEFAULT_PARAMS(arity, typename P, na) \
+ > \
+struct reverse_##name \
+{ \
+ typedef typename eval_if< \
+ is_na<BOOST_PP_CAT(P, arity)> \
+ , def_reverse_##name##_impl<BOOST_MPL_PP_PARAMS(BOOST_PP_DEC(arity), P)> \
+ , aux::reverse_##name##_impl<BOOST_MPL_PP_PARAMS(arity, P)> \
+ >::type type; \
+}; \
+BOOST_MPL_AUX_NA_SPEC(arity, name) \
+BOOST_MPL_AUX_NA_SPEC(arity, reverse_##name) \
+/**/
+
+#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+
+#endif // BOOST_MPL_AUX_INSERTER_ALGORITHM_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/integral_wrapper.hpp b/third_party/boost/boost/mpl/aux_/integral_wrapper.hpp
new file mode 100644
index 0000000..8840958
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/integral_wrapper.hpp
@@ -0,0 +1,93 @@
+
+// Copyright Aleksey Gurtovoy 2000-2006
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+// NO INCLUDE GUARDS, THE HEADER IS INTENDED FOR MULTIPLE INCLUSION!
+
+#include <boost/mpl/integral_c_tag.hpp>
+#include <boost/mpl/aux_/static_cast.hpp>
+#include <boost/mpl/aux_/nttp_decl.hpp>
+#include <boost/mpl/aux_/config/static_constant.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+#include <boost/preprocessor/cat.hpp>
+
+#if !defined(AUX_WRAPPER_NAME)
+# define AUX_WRAPPER_NAME BOOST_PP_CAT(AUX_WRAPPER_VALUE_TYPE,_)
+#endif
+
+#if !defined(AUX_WRAPPER_PARAMS)
+# define AUX_WRAPPER_PARAMS(N) BOOST_MPL_AUX_NTTP_DECL(AUX_WRAPPER_VALUE_TYPE, N)
+#endif
+
+#if !defined(AUX_WRAPPER_INST)
+# if BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
+# define AUX_WRAPPER_INST(value) AUX_WRAPPER_NAME< value >
+# else
+# define AUX_WRAPPER_INST(value) BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE::AUX_WRAPPER_NAME< value >
+# endif
+#endif
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+
+template< AUX_WRAPPER_PARAMS(N) >
+struct AUX_WRAPPER_NAME
+{
+ BOOST_STATIC_CONSTANT(AUX_WRAPPER_VALUE_TYPE, value = N);
+// agurt, 08/mar/03: SGI MIPSpro C++ workaround, have to #ifdef because some
+// other compilers (e.g. MSVC) are not particulary happy about it
+#if BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
+ typedef struct AUX_WRAPPER_NAME type;
+#else
+ typedef AUX_WRAPPER_NAME type;
+#endif
+ typedef AUX_WRAPPER_VALUE_TYPE value_type;
+ typedef integral_c_tag tag;
+
+// have to #ifdef here: some compilers don't like the 'N + 1' form (MSVC),
+// while some other don't like 'value + 1' (Borland), and some don't like
+// either
+#if BOOST_WORKAROUND(__EDG_VERSION__, <= 243)
+ private:
+ BOOST_STATIC_CONSTANT(AUX_WRAPPER_VALUE_TYPE, next_value = BOOST_MPL_AUX_STATIC_CAST(AUX_WRAPPER_VALUE_TYPE, (N + 1)));
+ BOOST_STATIC_CONSTANT(AUX_WRAPPER_VALUE_TYPE, prior_value = BOOST_MPL_AUX_STATIC_CAST(AUX_WRAPPER_VALUE_TYPE, (N - 1)));
+ public:
+ typedef AUX_WRAPPER_INST(next_value) next;
+ typedef AUX_WRAPPER_INST(prior_value) prior;
+#elif BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x561)) \
+ || BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(502)) \
+ || (BOOST_WORKAROUND(__HP_aCC, <= 53800) && (BOOST_WORKAROUND(__hpxstd98, != 1)))
+ typedef AUX_WRAPPER_INST( BOOST_MPL_AUX_STATIC_CAST(AUX_WRAPPER_VALUE_TYPE, (N + 1)) ) next;
+ typedef AUX_WRAPPER_INST( BOOST_MPL_AUX_STATIC_CAST(AUX_WRAPPER_VALUE_TYPE, (N - 1)) ) prior;
+#else
+ typedef AUX_WRAPPER_INST( BOOST_MPL_AUX_STATIC_CAST(AUX_WRAPPER_VALUE_TYPE, (value + 1)) ) next;
+ typedef AUX_WRAPPER_INST( BOOST_MPL_AUX_STATIC_CAST(AUX_WRAPPER_VALUE_TYPE, (value - 1)) ) prior;
+#endif
+
+ // enables uniform function call syntax for families of overloaded
+ // functions that return objects of both arithmetic ('int', 'long',
+ // 'double', etc.) and wrapped integral types (for an example, see
+ // "mpl/example/power.cpp")
+ BOOST_CONSTEXPR operator AUX_WRAPPER_VALUE_TYPE() const { return static_cast<AUX_WRAPPER_VALUE_TYPE>(this->value); }
+};
+
+#if !defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION)
+template< AUX_WRAPPER_PARAMS(N) >
+AUX_WRAPPER_VALUE_TYPE const AUX_WRAPPER_INST(N)::value;
+#endif
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+
+#undef AUX_WRAPPER_NAME
+#undef AUX_WRAPPER_PARAMS
+#undef AUX_WRAPPER_INST
+#undef AUX_WRAPPER_VALUE_TYPE
diff --git a/third_party/boost/boost/mpl/aux_/is_msvc_eti_arg.hpp b/third_party/boost/boost/mpl/aux_/is_msvc_eti_arg.hpp
new file mode 100644
index 0000000..b555d91
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/is_msvc_eti_arg.hpp
@@ -0,0 +1,64 @@
+
+#ifndef BOOST_MPL_AUX_IS_MSVC_ETI_ARG_HPP_INCLUDED
+#define BOOST_MPL_AUX_IS_MSVC_ETI_ARG_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/yes_no.hpp>
+#include <boost/mpl/aux_/config/eti.hpp>
+#include <boost/mpl/aux_/config/static_constant.hpp>
+
+namespace boost { namespace mpl { namespace aux {
+
+#if defined(BOOST_MPL_CFG_MSVC_ETI_BUG)
+
+#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG)
+
+template< typename T >
+struct is_msvc_eti_arg
+{
+ BOOST_STATIC_CONSTANT(bool, value = false);
+};
+
+#else // BOOST_MPL_CFG_MSVC_60_ETI_BUG
+
+struct eti_int_convertible
+{
+ eti_int_convertible(int);
+};
+
+template< typename T >
+struct is_msvc_eti_arg
+{
+ static no_tag test(...);
+ static yes_tag test(eti_int_convertible);
+ static T& get();
+
+ BOOST_STATIC_CONSTANT(bool, value =
+ sizeof(test(get())) == sizeof(yes_tag)
+ );
+};
+
+#endif
+
+template<>
+struct is_msvc_eti_arg<int>
+{
+ BOOST_STATIC_CONSTANT(bool, value = true);
+};
+
+#endif // BOOST_MPL_CFG_MSVC_ETI_BUG
+
+}}}
+
+#endif // BOOST_MPL_AUX_IS_MSVC_ETI_ARG_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/iter_apply.hpp b/third_party/boost/boost/mpl/aux_/iter_apply.hpp
new file mode 100644
index 0000000..edbcd27
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/iter_apply.hpp
@@ -0,0 +1,47 @@
+
+#ifndef BOOST_MPL_ITER_APPLY_HPP_INCLUDED
+#define BOOST_MPL_ITER_APPLY_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 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/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/apply.hpp>
+#include <boost/mpl/deref.hpp>
+
+namespace boost { namespace mpl { namespace aux {
+
+template<
+ typename F
+ , typename Iterator
+ >
+struct iter_apply1
+ : apply1< F,typename deref<Iterator>::type >
+{
+};
+
+template<
+ typename F
+ , typename Iterator1
+ , typename Iterator2
+ >
+struct iter_apply2
+ : apply2<
+ F
+ , typename deref<Iterator1>::type
+ , typename deref<Iterator2>::type
+ >
+{
+};
+
+}}}
+
+#endif // BOOST_MPL_ITER_APPLY_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/iter_fold_if_impl.hpp b/third_party/boost/boost/mpl/aux_/iter_fold_if_impl.hpp
new file mode 100644
index 0000000..66e2e33
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/iter_fold_if_impl.hpp
@@ -0,0 +1,210 @@
+
+#ifndef BOOST_MPL_AUX_ITER_FOLD_IF_IMPL_HPP_INCLUDED
+#define BOOST_MPL_AUX_ITER_FOLD_IF_IMPL_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+// Copyright David Abrahams 2001-2002
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_PREPROCESSING_MODE)
+# include <boost/mpl/identity.hpp>
+# include <boost/mpl/next.hpp>
+# include <boost/mpl/if.hpp>
+# include <boost/mpl/apply.hpp>
+# include <boost/mpl/aux_/value_wknd.hpp>
+#endif
+
+#include <boost/mpl/aux_/config/use_preprocessed.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE)
+
+# define BOOST_MPL_PREPROCESSED_HEADER iter_fold_if_impl.hpp
+# include <boost/mpl/aux_/include_preprocessed.hpp>
+
+#else
+
+# include <boost/mpl/limits/unrolling.hpp>
+# include <boost/preprocessor/arithmetic/sub.hpp>
+# include <boost/preprocessor/repeat.hpp>
+# include <boost/preprocessor/inc.hpp>
+# include <boost/preprocessor/dec.hpp>
+# include <boost/preprocessor/cat.hpp>
+
+namespace boost { namespace mpl { namespace aux {
+
+template< typename Iterator, typename State >
+struct iter_fold_if_null_step
+{
+ typedef State state;
+ typedef Iterator iterator;
+};
+
+template< bool >
+struct iter_fold_if_step_impl
+{
+ template<
+ typename Iterator
+ , typename State
+ , typename StateOp
+ , typename IteratorOp
+ >
+ struct result_
+ {
+ typedef typename apply2<StateOp,State,Iterator>::type state;
+ typedef typename IteratorOp::type iterator;
+ };
+};
+
+template<>
+struct iter_fold_if_step_impl<false>
+{
+ template<
+ typename Iterator
+ , typename State
+ , typename StateOp
+ , typename IteratorOp
+ >
+ struct result_
+ {
+ typedef State state;
+ typedef Iterator iterator;
+ };
+};
+
+// agurt, 25/jun/02: MSVC 6.5 workaround, had to get rid of inheritance
+// here and in 'iter_fold_if_backward_step', because sometimes it interfered
+// with the "early template instantiation bug" in _really_ ugly ways
+template<
+ typename Iterator
+ , typename State
+ , typename ForwardOp
+ , typename Predicate
+ >
+struct iter_fold_if_forward_step
+{
+ typedef typename apply2<Predicate,State,Iterator>::type not_last;
+ typedef typename iter_fold_if_step_impl<
+ BOOST_MPL_AUX_MSVC_VALUE_WKND(not_last)::value
+ >::template result_< Iterator,State,ForwardOp,mpl::next<Iterator> > impl_;
+
+ typedef typename impl_::state state;
+ typedef typename impl_::iterator iterator;
+};
+
+template<
+ typename Iterator
+ , typename State
+ , typename BackwardOp
+ , typename Predicate
+ >
+struct iter_fold_if_backward_step
+{
+ typedef typename apply2<Predicate,State,Iterator>::type not_last;
+ typedef typename iter_fold_if_step_impl<
+ BOOST_MPL_AUX_MSVC_VALUE_WKND(not_last)::value
+ >::template result_< Iterator,State,BackwardOp,identity<Iterator> > impl_;
+
+ typedef typename impl_::state state;
+ typedef typename impl_::iterator iterator;
+};
+
+
+// local macros, #undef-ined at the end of the header
+
+# define AUX_ITER_FOLD_FORWARD_STEP(unused, i, unused2) \
+ typedef iter_fold_if_forward_step< \
+ typename BOOST_PP_CAT(forward_step,i)::iterator \
+ , typename BOOST_PP_CAT(forward_step,i)::state \
+ , ForwardOp \
+ , ForwardPredicate \
+ > BOOST_PP_CAT(forward_step, BOOST_PP_INC(i)); \
+ /**/
+
+# define AUX_ITER_FOLD_BACKWARD_STEP_FUNC(i) \
+ typedef iter_fold_if_backward_step< \
+ typename BOOST_PP_CAT(forward_step,BOOST_PP_DEC(i))::iterator \
+ , typename BOOST_PP_CAT(backward_step,i)::state \
+ , BackwardOp \
+ , BackwardPredicate \
+ > BOOST_PP_CAT(backward_step,BOOST_PP_DEC(i)); \
+ /**/
+
+# define AUX_ITER_FOLD_BACKWARD_STEP(unused, i, unused2) \
+ AUX_ITER_FOLD_BACKWARD_STEP_FUNC( \
+ BOOST_PP_SUB_D(1,BOOST_MPL_LIMIT_UNROLLING,i) \
+ ) \
+ /**/
+
+# define AUX_LAST_FORWARD_STEP \
+ BOOST_PP_CAT(forward_step, BOOST_MPL_LIMIT_UNROLLING) \
+ /**/
+
+# define AUX_LAST_BACKWARD_STEP \
+ BOOST_PP_CAT(backward_step, BOOST_MPL_LIMIT_UNROLLING) \
+ /**/
+
+template<
+ typename Iterator
+ , typename State
+ , typename ForwardOp
+ , typename ForwardPredicate
+ , typename BackwardOp
+ , typename BackwardPredicate
+ >
+struct iter_fold_if_impl
+{
+ private:
+ typedef iter_fold_if_null_step<Iterator,State> forward_step0;
+ BOOST_PP_REPEAT(
+ BOOST_MPL_LIMIT_UNROLLING
+ , AUX_ITER_FOLD_FORWARD_STEP
+ , unused
+ )
+
+ typedef typename if_<
+ typename AUX_LAST_FORWARD_STEP::not_last
+ , iter_fold_if_impl<
+ typename AUX_LAST_FORWARD_STEP::iterator
+ , typename AUX_LAST_FORWARD_STEP::state
+ , ForwardOp
+ , ForwardPredicate
+ , BackwardOp
+ , BackwardPredicate
+ >
+ , iter_fold_if_null_step<
+ typename AUX_LAST_FORWARD_STEP::iterator
+ , typename AUX_LAST_FORWARD_STEP::state
+ >
+ >::type AUX_LAST_BACKWARD_STEP;
+
+ BOOST_PP_REPEAT(
+ BOOST_MPL_LIMIT_UNROLLING
+ , AUX_ITER_FOLD_BACKWARD_STEP
+ , unused
+ )
+
+ public:
+ typedef typename backward_step0::state state;
+ typedef typename AUX_LAST_BACKWARD_STEP::iterator iterator;
+};
+
+# undef AUX_LAST_BACKWARD_STEP
+# undef AUX_LAST_FORWARD_STEP
+# undef AUX_ITER_FOLD_BACKWARD_STEP
+# undef AUX_ITER_FOLD_BACKWARD_STEP_FUNC
+# undef AUX_ITER_FOLD_FORWARD_STEP
+
+}}}
+
+#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#endif // BOOST_MPL_AUX_ITER_FOLD_IF_IMPL_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/iter_fold_impl.hpp b/third_party/boost/boost/mpl/aux_/iter_fold_impl.hpp
new file mode 100644
index 0000000..cb24338
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/iter_fold_impl.hpp
@@ -0,0 +1,42 @@
+
+#ifndef BOOST_MPL_AUX_ITER_FOLD_IMPL_HPP_INCLUDED
+#define BOOST_MPL_AUX_ITER_FOLD_IMPL_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_PREPROCESSING_MODE)
+# include <boost/mpl/next_prior.hpp>
+# include <boost/mpl/apply.hpp>
+# include <boost/mpl/aux_/config/ctps.hpp>
+# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+# include <boost/mpl/if.hpp>
+# include <boost/type_traits/is_same.hpp>
+# endif
+#endif
+
+#include <boost/mpl/aux_/config/use_preprocessed.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE)
+
+# define BOOST_MPL_PREPROCESSED_HEADER iter_fold_impl.hpp
+# include <boost/mpl/aux_/include_preprocessed.hpp>
+
+#else
+
+# define AUX778076_FOLD_IMPL_OP(iter) iter
+# define AUX778076_FOLD_IMPL_NAME_PREFIX iter_fold
+# include <boost/mpl/aux_/fold_impl_body.hpp>
+
+#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#endif // BOOST_MPL_AUX_ITER_FOLD_IMPL_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/lambda_arity_param.hpp b/third_party/boost/boost/mpl/aux_/lambda_arity_param.hpp
new file mode 100644
index 0000000..f3aaa49
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/lambda_arity_param.hpp
@@ -0,0 +1,25 @@
+
+#ifndef BOOST_MPL_AUX_LAMBDA_ARITY_PARAM_HPP_INCLUDED
+#define BOOST_MPL_AUX_LAMBDA_ARITY_PARAM_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/ttp.hpp>
+
+#if !defined(BOOST_MPL_CFG_EXTENDED_TEMPLATE_PARAMETERS_MATCHING)
+# define BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(param)
+#else
+# define BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(param) , param
+#endif
+
+#endif // BOOST_MPL_AUX_LAMBDA_ARITY_PARAM_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/lambda_spec.hpp b/third_party/boost/boost/mpl/aux_/lambda_spec.hpp
new file mode 100644
index 0000000..015d5be
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/lambda_spec.hpp
@@ -0,0 +1,49 @@
+
+#ifndef BOOST_MPL_AUX_LAMBDA_SPEC_HPP_INCLUDED
+#define BOOST_MPL_AUX_LAMBDA_SPEC_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2007
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/void.hpp>
+#include <boost/mpl/lambda_fwd.hpp>
+#include <boost/mpl/int_fwd.hpp>
+#include <boost/mpl/aux_/preprocessor/params.hpp>
+#include <boost/mpl/aux_/lambda_arity_param.hpp>
+#include <boost/mpl/aux_/config/lambda.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT)
+
+# define BOOST_MPL_AUX_PASS_THROUGH_LAMBDA_SPEC(i, name) \
+template< \
+ BOOST_MPL_PP_PARAMS(i, typename T) \
+ , typename Tag \
+ > \
+struct lambda< \
+ name< BOOST_MPL_PP_PARAMS(i, T) > \
+ , Tag \
+ BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(int_<i>) \
+ > \
+{ \
+ typedef false_ is_le; \
+ typedef name< BOOST_MPL_PP_PARAMS(i, T) > result_; \
+ typedef result_ type; \
+}; \
+/**/
+
+#else
+
+# define BOOST_MPL_AUX_PASS_THROUGH_LAMBDA_SPEC(i, name) /**/
+
+#endif
+
+#endif // BOOST_MPL_AUX_LAMBDA_SPEC_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/lambda_support.hpp b/third_party/boost/boost/mpl/aux_/lambda_support.hpp
new file mode 100644
index 0000000..b1017b8
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/lambda_support.hpp
@@ -0,0 +1,169 @@
+
+#ifndef BOOST_MPL_AUX_LAMBDA_SUPPORT_HPP_INCLUDED
+#define BOOST_MPL_AUX_LAMBDA_SUPPORT_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/lambda.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT)
+
+# define BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(i, name, params) /**/
+# define BOOST_MPL_AUX_LAMBDA_SUPPORT(i,name,params) /**/
+
+#else
+
+# include <boost/mpl/int_fwd.hpp>
+# include <boost/mpl/aux_/yes_no.hpp>
+# include <boost/mpl/aux_/na_fwd.hpp>
+# include <boost/mpl/aux_/preprocessor/params.hpp>
+# include <boost/mpl/aux_/preprocessor/enum.hpp>
+# include <boost/mpl/aux_/config/msvc.hpp>
+# include <boost/mpl/aux_/config/workaround.hpp>
+
+# include <boost/preprocessor/tuple/to_list.hpp>
+# include <boost/preprocessor/list/for_each_i.hpp>
+# include <boost/preprocessor/inc.hpp>
+# include <boost/preprocessor/cat.hpp>
+
+# define BOOST_MPL_AUX_LAMBDA_SUPPORT_ARG_TYPEDEF_FUNC(R,typedef_,i,param) \
+ typedef_ param BOOST_PP_CAT(arg,BOOST_PP_INC(i)); \
+ /**/
+
+// agurt, 07/mar/03: restore an old revision for the sake of SGI MIPSpro C++
+#if BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
+
+# define BOOST_MPL_AUX_LAMBDA_SUPPORT(i, name, params) \
+ typedef BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE::int_<i> arity; \
+ BOOST_PP_LIST_FOR_EACH_I_R( \
+ 1 \
+ , BOOST_MPL_AUX_LAMBDA_SUPPORT_ARG_TYPEDEF_FUNC \
+ , typedef \
+ , BOOST_PP_TUPLE_TO_LIST(i,params) \
+ ) \
+ struct rebind \
+ { \
+ template< BOOST_MPL_PP_PARAMS(i,typename U) > struct apply \
+ : name< BOOST_MPL_PP_PARAMS(i,U) > \
+ { \
+ }; \
+ }; \
+ /**/
+
+# define BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(i, name, params) \
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(i, name, params) \
+ /**/
+
+#elif BOOST_WORKAROUND(__EDG_VERSION__, <= 244) && !defined(BOOST_INTEL_CXX_VERSION)
+// agurt, 18/jan/03: old EDG-based compilers actually enforce 11.4 para 9
+// (in strict mode), so we have to provide an alternative to the
+// MSVC-optimized implementation
+
+# define BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(i, name, params) \
+ typedef BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE::int_<i> arity; \
+ BOOST_PP_LIST_FOR_EACH_I_R( \
+ 1 \
+ , BOOST_MPL_AUX_LAMBDA_SUPPORT_ARG_TYPEDEF_FUNC \
+ , typedef \
+ , BOOST_PP_TUPLE_TO_LIST(i,params) \
+ ) \
+ struct rebind; \
+/**/
+
+# define BOOST_MPL_AUX_LAMBDA_SUPPORT(i, name, params) \
+ BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(i, name, params) \
+}; \
+template< BOOST_MPL_PP_PARAMS(i,typename T) > \
+struct name<BOOST_MPL_PP_PARAMS(i,T)>::rebind \
+{ \
+ template< BOOST_MPL_PP_PARAMS(i,typename U) > struct apply \
+ : name< BOOST_MPL_PP_PARAMS(i,U) > \
+ { \
+ }; \
+/**/
+
+#else // __EDG_VERSION__
+
+namespace boost { namespace mpl { namespace aux {
+template< typename T > struct has_rebind_tag;
+}}}
+
+# define BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(i, name, params) \
+ typedef BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE::int_<i> arity; \
+ BOOST_PP_LIST_FOR_EACH_I_R( \
+ 1 \
+ , BOOST_MPL_AUX_LAMBDA_SUPPORT_ARG_TYPEDEF_FUNC \
+ , typedef \
+ , BOOST_PP_TUPLE_TO_LIST(i,params) \
+ ) \
+ friend class BOOST_PP_CAT(name,_rebind); \
+ typedef BOOST_PP_CAT(name,_rebind) rebind; \
+/**/
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610))
+# define BOOST_MPL_AUX_LAMBDA_SUPPORT_HAS_REBIND(i, name, params) \
+template< BOOST_MPL_PP_PARAMS(i,typename T) > \
+::boost::mpl::aux::yes_tag operator|( \
+ ::boost::mpl::aux::has_rebind_tag<int> \
+ , name<BOOST_MPL_PP_PARAMS(i,T)>* \
+ ); \
+::boost::mpl::aux::no_tag operator|( \
+ ::boost::mpl::aux::has_rebind_tag<int> \
+ , name< BOOST_MPL_PP_ENUM(i,::boost::mpl::na) >* \
+ ); \
+/**/
+#elif !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+# define BOOST_MPL_AUX_LAMBDA_SUPPORT_HAS_REBIND(i, name, params) \
+template< BOOST_MPL_PP_PARAMS(i,typename T) > \
+::boost::mpl::aux::yes_tag operator|( \
+ ::boost::mpl::aux::has_rebind_tag<int> \
+ , ::boost::mpl::aux::has_rebind_tag< name<BOOST_MPL_PP_PARAMS(i,T)> >* \
+ ); \
+/**/
+#else
+# define BOOST_MPL_AUX_LAMBDA_SUPPORT_HAS_REBIND(i, name, params) /**/
+#endif
+
+# if !defined(__BORLANDC__)
+# define BOOST_MPL_AUX_LAMBDA_SUPPORT(i, name, params) \
+ BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(i, name, params) \
+}; \
+BOOST_MPL_AUX_LAMBDA_SUPPORT_HAS_REBIND(i, name, params) \
+class BOOST_PP_CAT(name,_rebind) \
+{ \
+ public: \
+ template< BOOST_MPL_PP_PARAMS(i,typename U) > struct apply \
+ : name< BOOST_MPL_PP_PARAMS(i,U) > \
+ { \
+ }; \
+/**/
+# else
+# define BOOST_MPL_AUX_LAMBDA_SUPPORT(i, name, params) \
+ BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(i, name, params) \
+}; \
+BOOST_MPL_AUX_LAMBDA_SUPPORT_HAS_REBIND(i, name, params) \
+class BOOST_PP_CAT(name,_rebind) \
+{ \
+ public: \
+ template< BOOST_MPL_PP_PARAMS(i,typename U) > struct apply \
+ { \
+ typedef typename name< BOOST_MPL_PP_PARAMS(i,U) >::type type; \
+ }; \
+/**/
+# endif // __BORLANDC__
+
+#endif // __EDG_VERSION__
+
+#endif // BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT
+
+#endif // BOOST_MPL_AUX_LAMBDA_SUPPORT_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/msvc_eti_base.hpp b/third_party/boost/boost/mpl/aux_/msvc_eti_base.hpp
new file mode 100644
index 0000000..82dbd6b
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/msvc_eti_base.hpp
@@ -0,0 +1,77 @@
+
+#ifndef BOOST_MPL_AUX_MSVC_ETI_BASE_HPP_INCLUDED
+#define BOOST_MPL_AUX_MSVC_ETI_BASE_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/is_msvc_eti_arg.hpp>
+#include <boost/mpl/aux_/config/eti.hpp>
+#include <boost/mpl/aux_/config/gcc.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+namespace boost { namespace mpl { namespace aux {
+
+#if defined(BOOST_MPL_CFG_MSVC_70_ETI_BUG)
+
+template< bool > struct msvc_eti_base_impl
+{
+ template< typename T > struct result_
+ : T
+ {
+ typedef T type;
+ };
+};
+
+template<> struct msvc_eti_base_impl<true>
+{
+ template< typename T > struct result_
+ {
+ typedef result_ type;
+ typedef result_ first;
+ typedef result_ second;
+ typedef result_ tag;
+ enum { value = 0 };
+ };
+};
+
+template< typename T > struct msvc_eti_base
+ : msvc_eti_base_impl< is_msvc_eti_arg<T>::value >
+ ::template result_<T>
+{
+};
+
+#else // !BOOST_MPL_CFG_MSVC_70_ETI_BUG
+
+template< typename T > struct msvc_eti_base
+ : T
+{
+#if BOOST_WORKAROUND(BOOST_MPL_CFG_GCC, BOOST_TESTED_AT(0x0304))
+ msvc_eti_base();
+#endif
+ typedef T type;
+};
+
+#endif
+
+template<> struct msvc_eti_base<int>
+{
+ typedef msvc_eti_base type;
+ typedef msvc_eti_base first;
+ typedef msvc_eti_base second;
+ typedef msvc_eti_base tag;
+ enum { value = 0 };
+};
+
+}}}
+
+#endif // BOOST_MPL_AUX_MSVC_ETI_BASE_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/msvc_never_true.hpp b/third_party/boost/boost/mpl/aux_/msvc_never_true.hpp
new file mode 100644
index 0000000..28650eb
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/msvc_never_true.hpp
@@ -0,0 +1,34 @@
+
+#ifndef BOOST_MPL_AUX_MSVC_NEVER_TRUE_HPP_INCLUDED
+#define BOOST_MPL_AUX_MSVC_NEVER_TRUE_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/msvc.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
+
+namespace boost { namespace mpl { namespace aux {
+
+template< typename T >
+struct msvc_never_true
+{
+ enum { value = false };
+};
+
+}}}
+
+#endif // BOOST_MSVC
+
+#endif // BOOST_MPL_AUX_MSVC_NEVER_TRUE_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/msvc_type.hpp b/third_party/boost/boost/mpl/aux_/msvc_type.hpp
new file mode 100644
index 0000000..9e90694
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/msvc_type.hpp
@@ -0,0 +1,62 @@
+
+#ifndef BOOST_MPL_AUX_MSVC_TYPE_HPP_INCLUDED
+#define BOOST_MPL_AUX_MSVC_TYPE_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/eti.hpp>
+#include <boost/mpl/aux_/is_msvc_eti_arg.hpp>
+
+namespace boost { namespace mpl { namespace aux {
+
+#if defined(BOOST_MPL_CFG_MSVC_70_ETI_BUG)
+
+template< bool > struct msvc_type_impl
+{
+ template< typename T > struct result_
+ {
+ typedef typename T::type type;
+ };
+};
+
+template<> struct msvc_type_impl<true>
+{
+ template< typename T > struct result_
+ {
+ typedef result_ type;
+ };
+};
+
+template< typename T > struct msvc_type
+ : msvc_type_impl< is_msvc_eti_arg<T>::value >
+ ::template result_<T>
+{
+};
+
+#else // BOOST_MPL_CFG_MSVC_70_ETI_BUG
+
+template< typename T > struct msvc_type
+{
+ typedef typename T::type type;
+};
+
+template<> struct msvc_type<int>
+{
+ typedef int type;
+};
+
+#endif
+
+}}}
+
+#endif // BOOST_MPL_AUX_MSVC_TYPE_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/na.hpp b/third_party/boost/boost/mpl/aux_/na.hpp
new file mode 100644
index 0000000..5102233
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/na.hpp
@@ -0,0 +1,95 @@
+
+#ifndef BOOST_MPL_AUX_NA_HPP_INCLUDED
+#define BOOST_MPL_AUX_NA_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/aux_/na_fwd.hpp>
+#include <boost/mpl/aux_/config/msvc.hpp>
+#include <boost/mpl/aux_/config/ctps.hpp>
+
+namespace boost { namespace mpl {
+
+template< typename T >
+struct is_na
+ : false_
+{
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+ using false_::value;
+#endif
+};
+
+template<>
+struct is_na<na>
+ : true_
+{
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+ using true_::value;
+#endif
+};
+
+template< typename T >
+struct is_not_na
+ : true_
+{
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+ using true_::value;
+#endif
+};
+
+template<>
+struct is_not_na<na>
+ : false_
+{
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+ using false_::value;
+#endif
+};
+
+#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+template< typename T, typename U > struct if_na
+{
+ typedef T type;
+};
+
+template< typename U > struct if_na<na,U>
+{
+ typedef U type;
+};
+#else
+template< typename T > struct if_na_impl
+{
+ template< typename U > struct apply
+ {
+ typedef T type;
+ };
+};
+
+template<> struct if_na_impl<na>
+{
+ template< typename U > struct apply
+ {
+ typedef U type;
+ };
+};
+
+template< typename T, typename U > struct if_na
+ : if_na_impl<T>::template apply<U>
+{
+};
+#endif
+
+}}
+
+#endif // BOOST_MPL_AUX_NA_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/na_assert.hpp b/third_party/boost/boost/mpl/aux_/na_assert.hpp
new file mode 100644
index 0000000..067ceba
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/na_assert.hpp
@@ -0,0 +1,34 @@
+
+#ifndef BOOST_MPL_AUX_NA_ASSERT_HPP_INCLUDED
+#define BOOST_MPL_AUX_NA_ASSERT_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/mpl/aux_/config/msvc.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+#if !BOOST_WORKAROUND(_MSC_FULL_VER, <= 140050601) \
+ && !BOOST_WORKAROUND(__EDG_VERSION__, <= 243)
+# include <boost/mpl/assert.hpp>
+# define BOOST_MPL_AUX_ASSERT_NOT_NA(x) \
+ BOOST_MPL_ASSERT_NOT((boost::mpl::is_na<type>)) \
+/**/
+#else
+# include <boost/static_assert.hpp>
+# define BOOST_MPL_AUX_ASSERT_NOT_NA(x) \
+ BOOST_STATIC_ASSERT(!boost::mpl::is_na<x>::value) \
+/**/
+#endif
+
+#endif // BOOST_MPL_AUX_NA_ASSERT_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/na_fwd.hpp b/third_party/boost/boost/mpl/aux_/na_fwd.hpp
new file mode 100644
index 0000000..cf9002f
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/na_fwd.hpp
@@ -0,0 +1,31 @@
+
+#ifndef BOOST_MPL_AUX_NA_FWD_HPP_INCLUDED
+#define BOOST_MPL_AUX_NA_FWD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/adl_barrier.hpp>
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+
+// n.a. == not available
+struct na
+{
+ typedef na type;
+ enum { value = 0 };
+};
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+BOOST_MPL_AUX_ADL_BARRIER_DECL(na)
+
+#endif // BOOST_MPL_AUX_NA_FWD_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/na_spec.hpp b/third_party/boost/boost/mpl/aux_/na_spec.hpp
new file mode 100644
index 0000000..c10c4d7
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/na_spec.hpp
@@ -0,0 +1,175 @@
+
+#ifndef BOOST_MPL_AUX_NA_SPEC_HPP_INCLUDED
+#define BOOST_MPL_AUX_NA_SPEC_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_PREPROCESSING_MODE)
+# include <boost/mpl/lambda_fwd.hpp>
+# include <boost/mpl/int.hpp>
+# include <boost/mpl/bool.hpp>
+# include <boost/mpl/aux_/na.hpp>
+# include <boost/mpl/aux_/arity.hpp>
+# include <boost/mpl/aux_/template_arity_fwd.hpp>
+#endif
+
+#include <boost/mpl/aux_/preprocessor/params.hpp>
+#include <boost/mpl/aux_/preprocessor/enum.hpp>
+#include <boost/mpl/aux_/preprocessor/def_params_tail.hpp>
+#include <boost/mpl/aux_/lambda_arity_param.hpp>
+#include <boost/mpl/aux_/config/dtp.hpp>
+#include <boost/mpl/aux_/config/eti.hpp>
+#include <boost/mpl/aux_/nttp_decl.hpp>
+#include <boost/mpl/aux_/config/ttp.hpp>
+#include <boost/mpl/aux_/config/lambda.hpp>
+#include <boost/mpl/aux_/config/overload_resolution.hpp>
+
+
+#define BOOST_MPL_AUX_NA_PARAMS(i) \
+ BOOST_MPL_PP_ENUM(i, na) \
+/**/
+
+#if defined(BOOST_MPL_CFG_BROKEN_DEFAULT_PARAMETERS_IN_NESTED_TEMPLATES)
+# define BOOST_MPL_AUX_NA_SPEC_ARITY(i, name) \
+namespace aux { \
+template< BOOST_MPL_AUX_NTTP_DECL(int, N) > \
+struct arity< \
+ name< BOOST_MPL_AUX_NA_PARAMS(i) > \
+ , N \
+ > \
+ : int_< BOOST_MPL_LIMIT_METAFUNCTION_ARITY > \
+{ \
+}; \
+} \
+/**/
+#else
+# define BOOST_MPL_AUX_NA_SPEC_ARITY(i, name) /**/
+#endif
+
+#define BOOST_MPL_AUX_NA_SPEC_MAIN(i, name) \
+template<> \
+struct name< BOOST_MPL_AUX_NA_PARAMS(i) > \
+{ \
+ template< \
+ BOOST_MPL_PP_PARAMS(i, typename T) \
+ BOOST_MPL_PP_NESTED_DEF_PARAMS_TAIL(i, typename T, na) \
+ > \
+ struct apply \
+ : name< BOOST_MPL_PP_PARAMS(i, T) > \
+ { \
+ }; \
+}; \
+/**/
+
+#if defined(BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT)
+# define BOOST_MPL_AUX_NA_SPEC_LAMBDA(i, name) \
+template<> \
+struct lambda< \
+ name< BOOST_MPL_AUX_NA_PARAMS(i) > \
+ , void_ \
+ , true_ \
+ > \
+{ \
+ typedef false_ is_le; \
+ typedef name< BOOST_MPL_AUX_NA_PARAMS(i) > type; \
+}; \
+template<> \
+struct lambda< \
+ name< BOOST_MPL_AUX_NA_PARAMS(i) > \
+ , void_ \
+ , false_ \
+ > \
+{ \
+ typedef false_ is_le; \
+ typedef name< BOOST_MPL_AUX_NA_PARAMS(i) > type; \
+}; \
+/**/
+#else
+# define BOOST_MPL_AUX_NA_SPEC_LAMBDA(i, name) \
+template< typename Tag > \
+struct lambda< \
+ name< BOOST_MPL_AUX_NA_PARAMS(i) > \
+ , Tag \
+ BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(int_<-1>) \
+ > \
+{ \
+ typedef false_ is_le; \
+ typedef name< BOOST_MPL_AUX_NA_PARAMS(i) > result_; \
+ typedef name< BOOST_MPL_AUX_NA_PARAMS(i) > type; \
+}; \
+/**/
+#endif
+
+#if defined(BOOST_MPL_CFG_EXTENDED_TEMPLATE_PARAMETERS_MATCHING) \
+ || defined(BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT) \
+ && defined(BOOST_MPL_CFG_BROKEN_OVERLOAD_RESOLUTION)
+# define BOOST_MPL_AUX_NA_SPEC_TEMPLATE_ARITY(i, j, name) \
+namespace aux { \
+template< BOOST_MPL_PP_PARAMS(j, typename T) > \
+struct template_arity< \
+ name< BOOST_MPL_PP_PARAMS(j, T) > \
+ > \
+ : int_<j> \
+{ \
+}; \
+\
+template<> \
+struct template_arity< \
+ name< BOOST_MPL_PP_ENUM(i, na) > \
+ > \
+ : int_<-1> \
+{ \
+}; \
+} \
+/**/
+#else
+# define BOOST_MPL_AUX_NA_SPEC_TEMPLATE_ARITY(i, j, name) /**/
+#endif
+
+#if defined(BOOST_MPL_CFG_MSVC_ETI_BUG)
+# define BOOST_MPL_AUX_NA_SPEC_ETI(i, name) \
+template<> \
+struct name< BOOST_MPL_PP_ENUM(i, int) > \
+{ \
+ typedef int type; \
+ enum { value = 0 }; \
+}; \
+/**/
+#else
+# define BOOST_MPL_AUX_NA_SPEC_ETI(i, name) /**/
+#endif
+
+#define BOOST_MPL_AUX_NA_PARAM(param) param = na
+
+#define BOOST_MPL_AUX_NA_SPEC_NO_ETI(i, name) \
+BOOST_MPL_AUX_NA_SPEC_MAIN(i, name) \
+BOOST_MPL_AUX_NA_SPEC_LAMBDA(i, name) \
+BOOST_MPL_AUX_NA_SPEC_ARITY(i, name) \
+BOOST_MPL_AUX_NA_SPEC_TEMPLATE_ARITY(i, i, name) \
+/**/
+
+#define BOOST_MPL_AUX_NA_SPEC(i, name) \
+BOOST_MPL_AUX_NA_SPEC_NO_ETI(i, name) \
+BOOST_MPL_AUX_NA_SPEC_ETI(i, name) \
+/**/
+
+#define BOOST_MPL_AUX_NA_SPEC2(i, j, name) \
+BOOST_MPL_AUX_NA_SPEC_MAIN(i, name) \
+BOOST_MPL_AUX_NA_SPEC_ETI(i, name) \
+BOOST_MPL_AUX_NA_SPEC_LAMBDA(i, name) \
+BOOST_MPL_AUX_NA_SPEC_ARITY(i, name) \
+BOOST_MPL_AUX_NA_SPEC_TEMPLATE_ARITY(i, j, name) \
+/**/
+
+
+#endif // BOOST_MPL_AUX_NA_SPEC_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/nested_type_wknd.hpp b/third_party/boost/boost/mpl/aux_/nested_type_wknd.hpp
new file mode 100644
index 0000000..cd5f2f6
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/nested_type_wknd.hpp
@@ -0,0 +1,48 @@
+
+#ifndef BOOST_MPL_AUX_NESTED_TYPE_WKND_HPP_INCLUDED
+#define BOOST_MPL_AUX_NESTED_TYPE_WKND_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/gcc.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+#if BOOST_WORKAROUND(BOOST_MPL_CFG_GCC, BOOST_TESTED_AT(0x0302)) \
+ || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x561)) \
+ || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x530)) \
+ || BOOST_WORKAROUND(__DMC__, BOOST_TESTED_AT(0x840))
+
+namespace boost { namespace mpl { namespace aux {
+template< typename T > struct nested_type_wknd
+ : T::type
+{
+};
+}}}
+
+#if BOOST_WORKAROUND(__DMC__, BOOST_TESTED_AT(0x840))
+# define BOOST_MPL_AUX_NESTED_TYPE_WKND(T) \
+ aux::nested_type_wknd<T> \
+/**/
+#else
+# define BOOST_MPL_AUX_NESTED_TYPE_WKND(T) \
+ ::boost::mpl::aux::nested_type_wknd<T> \
+/**/
+#endif
+
+#else // !BOOST_MPL_CFG_GCC et al.
+
+# define BOOST_MPL_AUX_NESTED_TYPE_WKND(T) T::type
+
+#endif
+
+#endif // BOOST_MPL_AUX_NESTED_TYPE_WKND_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/nttp_decl.hpp b/third_party/boost/boost/mpl/aux_/nttp_decl.hpp
new file mode 100644
index 0000000..6c41cba
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/nttp_decl.hpp
@@ -0,0 +1,35 @@
+
+#ifndef BOOST_MPL_AUX_NTTP_DECL_HPP_INCLUDED
+#define BOOST_MPL_AUX_NTTP_DECL_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/nttp.hpp>
+
+#if defined(BOOST_MPL_CFG_NTTP_BUG)
+
+typedef bool _mpl_nttp_bool;
+typedef int _mpl_nttp_int;
+typedef unsigned _mpl_nttp_unsigned;
+typedef long _mpl_nttp_long;
+
+# include <boost/preprocessor/cat.hpp>
+# define BOOST_MPL_AUX_NTTP_DECL(T, x) BOOST_PP_CAT(_mpl_nttp_,T) x /**/
+
+#else
+
+# define BOOST_MPL_AUX_NTTP_DECL(T, x) T x /**/
+
+#endif
+
+#endif // BOOST_MPL_AUX_NTTP_DECL_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/numeric_cast_utils.hpp b/third_party/boost/boost/mpl/aux_/numeric_cast_utils.hpp
new file mode 100644
index 0000000..b197748
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/numeric_cast_utils.hpp
@@ -0,0 +1,77 @@
+
+#ifndef BOOST_MPL_AUX_NUMERIC_CAST_HPP_INCLUDED
+#define BOOST_MPL_AUX_NUMERIC_CAST_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2003-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/numeric_cast.hpp>
+#include <boost/mpl/apply_wrap.hpp>
+#include <boost/mpl/aux_/config/forwarding.hpp>
+
+namespace boost { namespace mpl { namespace aux {
+
+template<
+ typename F
+ , typename Tag1
+ , typename Tag2
+ >
+struct cast1st_impl
+{
+ template< typename N1, typename N2 > struct apply
+#if !defined(BOOST_MPL_CFG_NO_NESTED_FORWARDING)
+ : apply_wrap2<
+ F
+ , typename apply_wrap1< BOOST_MPL_AUX_NUMERIC_CAST<Tag1,Tag2>,N1 >::type
+ , N2
+ >
+ {
+#else
+ {
+ typedef typename apply_wrap2<
+ F
+ , typename apply_wrap1< BOOST_MPL_AUX_NUMERIC_CAST<Tag1,Tag2>,N1 >::type
+ , N2
+ >::type type;
+#endif
+ };
+};
+
+template<
+ typename F
+ , typename Tag1
+ , typename Tag2
+ >
+struct cast2nd_impl
+{
+ template< typename N1, typename N2 > struct apply
+#if !defined(BOOST_MPL_CFG_NO_NESTED_FORWARDING)
+ : apply_wrap2<
+ F
+ , N1
+ , typename apply_wrap1< BOOST_MPL_AUX_NUMERIC_CAST<Tag2,Tag1>,N2 >::type
+ >
+ {
+#else
+ {
+ typedef typename apply_wrap2<
+ F
+ , N1
+ , typename apply_wrap1< BOOST_MPL_AUX_NUMERIC_CAST<Tag2,Tag1>,N2 >::type
+ >::type type;
+#endif
+ };
+};
+
+}}}
+
+#endif // BOOST_MPL_AUX_NUMERIC_CAST_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/numeric_op.hpp b/third_party/boost/boost/mpl/aux_/numeric_op.hpp
new file mode 100644
index 0000000..68bdd31
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/numeric_op.hpp
@@ -0,0 +1,315 @@
+
+#if !defined(BOOST_PP_IS_ITERATING)
+
+///// header body
+
+// NO INCLUDE GUARDS, THE HEADER IS INTENDED FOR MULTIPLE INCLUSION!
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_PREPROCESSING_MODE)
+# include <boost/mpl/numeric_cast.hpp>
+# include <boost/mpl/apply_wrap.hpp>
+# include <boost/mpl/if.hpp>
+# include <boost/mpl/tag.hpp>
+# include <boost/mpl/aux_/numeric_cast_utils.hpp>
+# include <boost/mpl/aux_/na.hpp>
+# include <boost/mpl/aux_/na_spec.hpp>
+# include <boost/mpl/aux_/lambda_support.hpp>
+# include <boost/mpl/aux_/msvc_eti_base.hpp>
+# include <boost/mpl/aux_/value_wknd.hpp>
+# include <boost/mpl/aux_/config/eti.hpp>
+# include <boost/mpl/aux_/nttp_decl.hpp>
+#endif
+
+#include <boost/mpl/aux_/config/static_constant.hpp>
+
+#if defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \
+ || defined(BOOST_MPL_PREPROCESSING_MODE)
+
+# include <boost/mpl/limits/arity.hpp>
+# include <boost/mpl/aux_/preprocessor/partial_spec_params.hpp>
+# include <boost/mpl/aux_/preprocessor/def_params_tail.hpp>
+# include <boost/mpl/aux_/preprocessor/repeat.hpp>
+# include <boost/mpl/aux_/preprocessor/ext_params.hpp>
+# include <boost/mpl/aux_/preprocessor/params.hpp>
+# include <boost/mpl/aux_/preprocessor/enum.hpp>
+# include <boost/mpl/aux_/preprocessor/add.hpp>
+# include <boost/mpl/aux_/preprocessor/sub.hpp>
+# include <boost/mpl/aux_/config/ctps.hpp>
+# include <boost/mpl/aux_/config/eti.hpp>
+# include <boost/mpl/aux_/config/msvc.hpp>
+# include <boost/mpl/aux_/config/workaround.hpp>
+
+# include <boost/preprocessor/dec.hpp>
+# include <boost/preprocessor/inc.hpp>
+# include <boost/preprocessor/iterate.hpp>
+# include <boost/preprocessor/cat.hpp>
+
+
+#if !defined(AUX778076_OP_ARITY)
+# define AUX778076_OP_ARITY BOOST_MPL_LIMIT_METAFUNCTION_ARITY
+#endif
+
+#if !defined(AUX778076_OP_IMPL_NAME)
+# define AUX778076_OP_IMPL_NAME BOOST_PP_CAT(AUX778076_OP_PREFIX,_impl)
+#endif
+
+#if !defined(AUX778076_OP_TAG_NAME)
+# define AUX778076_OP_TAG_NAME BOOST_PP_CAT(AUX778076_OP_PREFIX,_tag)
+#endif
+
+namespace boost { namespace mpl {
+
+template<
+ typename Tag1
+ , typename Tag2
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
+ , BOOST_MPL_AUX_NTTP_DECL(int, tag1_) = BOOST_MPL_AUX_MSVC_VALUE_WKND(Tag1)::value
+ , BOOST_MPL_AUX_NTTP_DECL(int, tag2_) = BOOST_MPL_AUX_MSVC_VALUE_WKND(Tag2)::value
+ >
+struct AUX778076_OP_IMPL_NAME
+ : if_c<
+ ( tag1_ > tag2_ )
+#else
+ >
+struct AUX778076_OP_IMPL_NAME
+ : if_c<
+ ( BOOST_MPL_AUX_NESTED_VALUE_WKND(int, Tag1)
+ > BOOST_MPL_AUX_NESTED_VALUE_WKND(int, Tag2)
+ )
+#endif
+ , aux::cast2nd_impl< AUX778076_OP_IMPL_NAME<Tag1,Tag1>,Tag1,Tag2 >
+ , aux::cast1st_impl< AUX778076_OP_IMPL_NAME<Tag2,Tag2>,Tag1,Tag2 >
+ >::type
+{
+};
+
+/// for Digital Mars C++/compilers with no CTPS/TTP support
+template<> struct AUX778076_OP_IMPL_NAME<na,na>
+{
+ template< typename U1, typename U2 > struct apply
+ {
+ typedef apply type;
+ BOOST_STATIC_CONSTANT(int, value = 0);
+ };
+};
+
+#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+template< typename Tag > struct AUX778076_OP_IMPL_NAME<na,Tag>
+{
+ template< typename U1, typename U2 > struct apply
+ {
+ typedef apply type;
+ BOOST_STATIC_CONSTANT(int, value = 0);
+ };
+};
+
+template< typename Tag > struct AUX778076_OP_IMPL_NAME<Tag,na>
+{
+ template< typename U1, typename U2 > struct apply
+ {
+ typedef apply type;
+ BOOST_STATIC_CONSTANT(int, value = 0);
+ };
+};
+#else
+template<> struct AUX778076_OP_IMPL_NAME<na,integral_c_tag>
+{
+ template< typename U1, typename U2 > struct apply
+ {
+ typedef apply type;
+ BOOST_STATIC_CONSTANT(int, value = 0);
+ };
+};
+
+template<> struct AUX778076_OP_IMPL_NAME<integral_c_tag,na>
+{
+ template< typename U1, typename U2 > struct apply
+ {
+ typedef apply type;
+ BOOST_STATIC_CONSTANT(int, value = 0);
+ };
+};
+#endif
+
+
+#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
+ && BOOST_WORKAROUND(BOOST_MSVC, >= 1300)
+template< typename T > struct AUX778076_OP_TAG_NAME
+ : tag<T,na>
+{
+};
+#else
+template< typename T > struct AUX778076_OP_TAG_NAME
+{
+ typedef typename T::tag type;
+};
+#endif
+
+
+#if AUX778076_OP_ARITY != 2
+
+# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+
+# define AUX778076_OP_RIGHT_OPERAND(unused, i, N) , BOOST_PP_CAT(N, BOOST_MPL_PP_ADD(i, 2))>
+# define AUX778076_OP_N_CALLS(i, N) \
+ BOOST_MPL_PP_REPEAT( BOOST_PP_DEC(i), BOOST_MPL_PP_REPEAT_IDENTITY_FUNC, AUX778076_OP_NAME< ) \
+ N1 BOOST_MPL_PP_REPEAT( BOOST_MPL_PP_SUB(i, 1), AUX778076_OP_RIGHT_OPERAND, N ) \
+/**/
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(N1)
+ , typename BOOST_MPL_AUX_NA_PARAM(N2)
+ BOOST_MPL_PP_DEF_PARAMS_TAIL(2, typename N, na)
+ >
+struct AUX778076_OP_NAME
+ : AUX778076_OP_N_CALLS(AUX778076_OP_ARITY, N)
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(
+ AUX778076_OP_ARITY
+ , AUX778076_OP_NAME
+ , ( BOOST_MPL_PP_PARAMS(AUX778076_OP_ARITY, N) )
+ )
+};
+
+#define BOOST_PP_ITERATION_PARAMS_1 \
+ (3,( BOOST_PP_DEC(AUX778076_OP_ARITY), 2, <boost/mpl/aux_/numeric_op.hpp> ))
+#include BOOST_PP_ITERATE()
+
+# undef AUX778076_OP_N_CALLS
+# undef AUX778076_OP_RIGHT_OPERAND
+
+# else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+
+/// forward declaration
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(N1)
+ , typename BOOST_MPL_AUX_NA_PARAM(N2)
+ >
+struct BOOST_PP_CAT(AUX778076_OP_NAME,2);
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(N1)
+ , typename BOOST_MPL_AUX_NA_PARAM(N2)
+ BOOST_MPL_PP_DEF_PARAMS_TAIL(2, typename N, na)
+ >
+struct AUX778076_OP_NAME
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
+ : aux::msvc_eti_base< typename if_<
+#else
+ : if_<
+#endif
+ is_na<N3>
+ , BOOST_PP_CAT(AUX778076_OP_NAME,2)<N1,N2>
+ , AUX778076_OP_NAME<
+ BOOST_PP_CAT(AUX778076_OP_NAME,2)<N1,N2>
+ , BOOST_MPL_PP_EXT_PARAMS(3, BOOST_PP_INC(AUX778076_OP_ARITY), N)
+ >
+ >::type
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
+ >
+#endif
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(
+ AUX778076_OP_ARITY
+ , AUX778076_OP_NAME
+ , ( BOOST_MPL_PP_PARAMS(AUX778076_OP_ARITY, N) )
+ )
+};
+
+template<
+ typename N1
+ , typename N2
+ >
+struct BOOST_PP_CAT(AUX778076_OP_NAME,2)
+
+#endif
+
+#else // AUX778076_OP_ARITY == 2
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(N1)
+ , typename BOOST_MPL_AUX_NA_PARAM(N2)
+ >
+struct AUX778076_OP_NAME
+
+#endif
+
+#if !defined(BOOST_MPL_CFG_MSVC_ETI_BUG)
+ : AUX778076_OP_IMPL_NAME<
+ typename AUX778076_OP_TAG_NAME<N1>::type
+ , typename AUX778076_OP_TAG_NAME<N2>::type
+ >::template apply<N1,N2>::type
+#else
+ : aux::msvc_eti_base< typename apply_wrap2<
+ AUX778076_OP_IMPL_NAME<
+ typename AUX778076_OP_TAG_NAME<N1>::type
+ , typename AUX778076_OP_TAG_NAME<N2>::type
+ >
+ , N1
+ , N2
+ >::type >::type
+#endif
+{
+#if AUX778076_OP_ARITY != 2
+
+# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+ BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(
+ AUX778076_OP_ARITY
+ , AUX778076_OP_NAME
+ , ( BOOST_MPL_PP_PARTIAL_SPEC_PARAMS(2, N, na) )
+ )
+# else
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(2, BOOST_PP_CAT(AUX778076_OP_NAME,2), (N1, N2))
+# endif
+
+#else
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(2, AUX778076_OP_NAME, (N1, N2))
+#endif
+};
+
+BOOST_MPL_AUX_NA_SPEC2(2, AUX778076_OP_ARITY, AUX778076_OP_NAME)
+
+}}
+
+#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+
+///// iteration, depth == 1
+
+// For gcc 4.4 compatability, we must include the
+// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
+#else // BOOST_PP_IS_ITERATING
+#if BOOST_PP_ITERATION_DEPTH() == 1
+
+# define i_ BOOST_PP_FRAME_ITERATION(1)
+
+template<
+ BOOST_MPL_PP_PARAMS(i_, typename N)
+ >
+struct AUX778076_OP_NAME<BOOST_MPL_PP_PARTIAL_SPEC_PARAMS(i_, N, na)>
+#if i_ != 2
+ : AUX778076_OP_N_CALLS(i_, N)
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(
+ AUX778076_OP_ARITY
+ , AUX778076_OP_NAME
+ , ( BOOST_MPL_PP_PARTIAL_SPEC_PARAMS(i_, N, na) )
+ )
+};
+#endif
+
+# undef i_
+
+#endif // BOOST_PP_ITERATION_DEPTH()
+#endif // BOOST_PP_IS_ITERATING
diff --git a/third_party/boost/boost/mpl/aux_/preprocessed/gcc/advance_backward.hpp b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/advance_backward.hpp
new file mode 100644
index 0000000..e8c7a32
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/advance_backward.hpp
@@ -0,0 +1,96 @@
+
+// Copyright Aleksey Gurtovoy 2000-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)
+//
+
+// Preprocessed version of "boost/mpl/aux_/advance_backward.hpp" header
+// -- DO NOT modify by hand!
+
+namespace boost { namespace mpl { namespace aux {
+
+template< long N > struct advance_backward;
+template<>
+struct advance_backward<0>
+{
+ template< typename Iterator > struct apply
+ {
+ typedef Iterator iter0;
+ typedef iter0 type;
+ };
+};
+
+template<>
+struct advance_backward<1>
+{
+ template< typename Iterator > struct apply
+ {
+ typedef Iterator iter0;
+ typedef typename prior<iter0>::type iter1;
+ typedef iter1 type;
+ };
+};
+
+template<>
+struct advance_backward<2>
+{
+ template< typename Iterator > struct apply
+ {
+ typedef Iterator iter0;
+ typedef typename prior<iter0>::type iter1;
+ typedef typename prior<iter1>::type iter2;
+ typedef iter2 type;
+ };
+};
+
+template<>
+struct advance_backward<3>
+{
+ template< typename Iterator > struct apply
+ {
+ typedef Iterator iter0;
+ typedef typename prior<iter0>::type iter1;
+ typedef typename prior<iter1>::type iter2;
+ typedef typename prior<iter2>::type iter3;
+ typedef iter3 type;
+ };
+};
+
+template<>
+struct advance_backward<4>
+{
+ template< typename Iterator > struct apply
+ {
+ typedef Iterator iter0;
+ typedef typename prior<iter0>::type iter1;
+ typedef typename prior<iter1>::type iter2;
+ typedef typename prior<iter2>::type iter3;
+ typedef typename prior<iter3>::type iter4;
+ typedef iter4 type;
+ };
+};
+
+template< long N >
+struct advance_backward
+{
+ template< typename Iterator > struct apply
+ {
+ typedef typename apply_wrap1<
+ advance_backward<4>
+ , Iterator
+ >::type chunk_result_;
+
+ typedef typename apply_wrap1<
+ advance_backward<(
+ (N - 4) < 0
+ ? 0
+ : N - 4
+ )>
+ , chunk_result_
+ >::type type;
+ };
+};
+
+}}}
diff --git a/third_party/boost/boost/mpl/aux_/preprocessed/gcc/advance_forward.hpp b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/advance_forward.hpp
new file mode 100644
index 0000000..e244fff
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/advance_forward.hpp
@@ -0,0 +1,96 @@
+
+// Copyright Aleksey Gurtovoy 2000-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)
+//
+
+// Preprocessed version of "boost/mpl/aux_/advance_forward.hpp" header
+// -- DO NOT modify by hand!
+
+namespace boost { namespace mpl { namespace aux {
+
+template< long N > struct advance_forward;
+template<>
+struct advance_forward<0>
+{
+ template< typename Iterator > struct apply
+ {
+ typedef Iterator iter0;
+ typedef iter0 type;
+ };
+};
+
+template<>
+struct advance_forward<1>
+{
+ template< typename Iterator > struct apply
+ {
+ typedef Iterator iter0;
+ typedef typename next<iter0>::type iter1;
+ typedef iter1 type;
+ };
+};
+
+template<>
+struct advance_forward<2>
+{
+ template< typename Iterator > struct apply
+ {
+ typedef Iterator iter0;
+ typedef typename next<iter0>::type iter1;
+ typedef typename next<iter1>::type iter2;
+ typedef iter2 type;
+ };
+};
+
+template<>
+struct advance_forward<3>
+{
+ template< typename Iterator > struct apply
+ {
+ typedef Iterator iter0;
+ typedef typename next<iter0>::type iter1;
+ typedef typename next<iter1>::type iter2;
+ typedef typename next<iter2>::type iter3;
+ typedef iter3 type;
+ };
+};
+
+template<>
+struct advance_forward<4>
+{
+ template< typename Iterator > struct apply
+ {
+ typedef Iterator iter0;
+ typedef typename next<iter0>::type iter1;
+ typedef typename next<iter1>::type iter2;
+ typedef typename next<iter2>::type iter3;
+ typedef typename next<iter3>::type iter4;
+ typedef iter4 type;
+ };
+};
+
+template< long N >
+struct advance_forward
+{
+ template< typename Iterator > struct apply
+ {
+ typedef typename apply_wrap1<
+ advance_forward<4>
+ , Iterator
+ >::type chunk_result_;
+
+ typedef typename apply_wrap1<
+ advance_forward<(
+ (N - 4) < 0
+ ? 0
+ : N - 4
+ )>
+ , chunk_result_
+ >::type type;
+ };
+};
+
+}}}
diff --git a/third_party/boost/boost/mpl/aux_/preprocessed/gcc/and.hpp b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/and.hpp
new file mode 100644
index 0000000..899d4fe
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/and.hpp
@@ -0,0 +1,69 @@
+
+// Copyright Aleksey Gurtovoy 2000-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)
+//
+
+// Preprocessed version of "boost/mpl/and.hpp" header
+// -- DO NOT modify by hand!
+
+namespace boost { namespace mpl {
+
+namespace aux {
+
+template< bool C_, typename T1, typename T2, typename T3, typename T4 >
+struct and_impl
+ : false_
+{
+};
+
+template< typename T1, typename T2, typename T3, typename T4 >
+struct and_impl< true,T1,T2,T3,T4 >
+ : and_impl<
+ BOOST_MPL_AUX_NESTED_TYPE_WKND(T1)::value
+ , T2, T3, T4
+ , true_
+ >
+{
+};
+
+template<>
+struct and_impl<
+ true
+ , true_, true_, true_, true_
+ >
+ : true_
+{
+};
+
+} // namespace aux
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(T1)
+ , typename BOOST_MPL_AUX_NA_PARAM(T2)
+ , typename T3 = true_, typename T4 = true_, typename T5 = true_
+ >
+struct and_
+
+ : aux::and_impl<
+ BOOST_MPL_AUX_NESTED_TYPE_WKND(T1)::value
+ , T2, T3, T4, T5
+ >
+
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(
+ 5
+ , and_
+ , ( T1, T2, T3, T4, T5)
+ )
+};
+
+BOOST_MPL_AUX_NA_SPEC2(
+ 2
+ , 5
+ , and_
+ )
+
+}}
diff --git a/third_party/boost/boost/mpl/aux_/preprocessed/gcc/apply.hpp b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/apply.hpp
new file mode 100644
index 0000000..55b3097
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/apply.hpp
@@ -0,0 +1,168 @@
+
+// Copyright Aleksey Gurtovoy 2000-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)
+//
+
+// Preprocessed version of "boost/mpl/apply.hpp" header
+// -- DO NOT modify by hand!
+
+namespace boost { namespace mpl {
+
+template<
+ typename F
+ >
+struct apply0
+
+ : apply_wrap0<
+ typename lambda<F>::type
+
+ >
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(
+ 1
+ , apply0
+ , (F )
+ )
+};
+
+template<
+ typename F
+ >
+struct apply< F,na,na,na,na,na >
+ : apply0<F>
+{
+};
+
+template<
+ typename F, typename T1
+ >
+struct apply1
+
+ : apply_wrap1<
+ typename lambda<F>::type
+ , T1
+ >
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(
+ 2
+ , apply1
+ , (F, T1)
+ )
+};
+
+template<
+ typename F, typename T1
+ >
+struct apply< F,T1,na,na,na,na >
+ : apply1< F,T1 >
+{
+};
+
+template<
+ typename F, typename T1, typename T2
+ >
+struct apply2
+
+ : apply_wrap2<
+ typename lambda<F>::type
+ , T1, T2
+ >
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(
+ 3
+ , apply2
+ , (F, T1, T2)
+ )
+};
+
+template<
+ typename F, typename T1, typename T2
+ >
+struct apply< F,T1,T2,na,na,na >
+ : apply2< F,T1,T2 >
+{
+};
+
+template<
+ typename F, typename T1, typename T2, typename T3
+ >
+struct apply3
+
+ : apply_wrap3<
+ typename lambda<F>::type
+ , T1, T2, T3
+ >
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(
+ 4
+ , apply3
+ , (F, T1, T2, T3)
+ )
+};
+
+template<
+ typename F, typename T1, typename T2, typename T3
+ >
+struct apply< F,T1,T2,T3,na,na >
+ : apply3< F,T1,T2,T3 >
+{
+};
+
+template<
+ typename F, typename T1, typename T2, typename T3, typename T4
+ >
+struct apply4
+
+ : apply_wrap4<
+ typename lambda<F>::type
+ , T1, T2, T3, T4
+ >
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(
+ 5
+ , apply4
+ , (F, T1, T2, T3, T4)
+ )
+};
+
+template<
+ typename F, typename T1, typename T2, typename T3, typename T4
+ >
+struct apply< F,T1,T2,T3,T4,na >
+ : apply4< F,T1,T2,T3,T4 >
+{
+};
+
+template<
+ typename F, typename T1, typename T2, typename T3, typename T4
+ , typename T5
+ >
+struct apply5
+
+ : apply_wrap5<
+ typename lambda<F>::type
+ , T1, T2, T3, T4, T5
+ >
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(
+ 6
+ , apply5
+ , (F, T1, T2, T3, T4, T5)
+ )
+};
+
+/// primary template (not a specialization!)
+
+template<
+ typename F, typename T1, typename T2, typename T3, typename T4
+ , typename T5
+ >
+struct apply
+ : apply5< F,T1,T2,T3,T4,T5 >
+{
+};
+
+}}
diff --git a/third_party/boost/boost/mpl/aux_/preprocessed/gcc/apply_fwd.hpp b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/apply_fwd.hpp
new file mode 100644
index 0000000..5f1c7de
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/apply_fwd.hpp
@@ -0,0 +1,51 @@
+
+// Copyright Aleksey Gurtovoy 2000-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)
+//
+
+// Preprocessed version of "boost/mpl/apply_fwd.hpp" header
+// -- DO NOT modify by hand!
+
+namespace boost { namespace mpl {
+
+template<
+ typename F, typename T1 = na, typename T2 = na, typename T3 = na
+ , typename T4 = na, typename T5 = na
+ >
+struct apply;
+
+template<
+ typename F
+ >
+struct apply0;
+
+template<
+ typename F, typename T1
+ >
+struct apply1;
+
+template<
+ typename F, typename T1, typename T2
+ >
+struct apply2;
+
+template<
+ typename F, typename T1, typename T2, typename T3
+ >
+struct apply3;
+
+template<
+ typename F, typename T1, typename T2, typename T3, typename T4
+ >
+struct apply4;
+
+template<
+ typename F, typename T1, typename T2, typename T3, typename T4
+ , typename T5
+ >
+struct apply5;
+
+}}
diff --git a/third_party/boost/boost/mpl/aux_/preprocessed/gcc/apply_wrap.hpp b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/apply_wrap.hpp
new file mode 100644
index 0000000..94ca5d7
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/apply_wrap.hpp
@@ -0,0 +1,83 @@
+
+// Copyright Aleksey Gurtovoy 2000-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)
+//
+
+// Preprocessed version of "boost/mpl/apply_wrap.hpp" header
+// -- DO NOT modify by hand!
+
+namespace boost { namespace mpl {
+
+template<
+ typename F
+
+ , typename has_apply_ = typename aux::has_apply<F>::type
+
+ >
+struct apply_wrap0
+
+ : F::template apply< >
+{
+};
+
+template< typename F >
+struct apply_wrap0< F,true_ >
+ : F::apply
+{
+};
+
+template<
+ typename F, typename T1
+
+ >
+struct apply_wrap1
+
+ : F::template apply<T1>
+{
+};
+
+template<
+ typename F, typename T1, typename T2
+
+ >
+struct apply_wrap2
+
+ : F::template apply< T1,T2 >
+{
+};
+
+template<
+ typename F, typename T1, typename T2, typename T3
+
+ >
+struct apply_wrap3
+
+ : F::template apply< T1,T2,T3 >
+{
+};
+
+template<
+ typename F, typename T1, typename T2, typename T3, typename T4
+
+ >
+struct apply_wrap4
+
+ : F::template apply< T1,T2,T3,T4 >
+{
+};
+
+template<
+ typename F, typename T1, typename T2, typename T3, typename T4
+ , typename T5
+
+ >
+struct apply_wrap5
+
+ : F::template apply< T1,T2,T3,T4,T5 >
+{
+};
+
+}}
diff --git a/third_party/boost/boost/mpl/aux_/preprocessed/gcc/arg.hpp b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/arg.hpp
new file mode 100644
index 0000000..dd64011
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/arg.hpp
@@ -0,0 +1,123 @@
+
+// Copyright Peter Dimov 2001-2002
+// Copyright Aleksey Gurtovoy 2001-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)
+//
+
+// Preprocessed version of "boost/mpl/arg.hpp" header
+// -- DO NOT modify by hand!
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+template<> struct arg< -1 >
+{
+ BOOST_STATIC_CONSTANT(int, value = -1);
+ BOOST_MPL_AUX_ARG_TYPEDEF(na, tag)
+ BOOST_MPL_AUX_ARG_TYPEDEF(na, type)
+
+ template<
+ typename U1 = na, typename U2 = na, typename U3 = na
+ , typename U4 = na, typename U5 = na
+ >
+ struct apply
+ {
+ typedef U1 type;
+ BOOST_MPL_AUX_ASSERT_NOT_NA(type);
+ };
+};
+
+template<> struct arg<1>
+{
+ BOOST_STATIC_CONSTANT(int, value = 1);
+ typedef arg<2> next;
+ BOOST_MPL_AUX_ARG_TYPEDEF(na, tag)
+ BOOST_MPL_AUX_ARG_TYPEDEF(na, type)
+
+ template<
+ typename U1 = na, typename U2 = na, typename U3 = na
+ , typename U4 = na, typename U5 = na
+ >
+ struct apply
+ {
+ typedef U1 type;
+ BOOST_MPL_AUX_ASSERT_NOT_NA(type);
+ };
+};
+
+template<> struct arg<2>
+{
+ BOOST_STATIC_CONSTANT(int, value = 2);
+ typedef arg<3> next;
+ BOOST_MPL_AUX_ARG_TYPEDEF(na, tag)
+ BOOST_MPL_AUX_ARG_TYPEDEF(na, type)
+
+ template<
+ typename U1 = na, typename U2 = na, typename U3 = na
+ , typename U4 = na, typename U5 = na
+ >
+ struct apply
+ {
+ typedef U2 type;
+ BOOST_MPL_AUX_ASSERT_NOT_NA(type);
+ };
+};
+
+template<> struct arg<3>
+{
+ BOOST_STATIC_CONSTANT(int, value = 3);
+ typedef arg<4> next;
+ BOOST_MPL_AUX_ARG_TYPEDEF(na, tag)
+ BOOST_MPL_AUX_ARG_TYPEDEF(na, type)
+
+ template<
+ typename U1 = na, typename U2 = na, typename U3 = na
+ , typename U4 = na, typename U5 = na
+ >
+ struct apply
+ {
+ typedef U3 type;
+ BOOST_MPL_AUX_ASSERT_NOT_NA(type);
+ };
+};
+
+template<> struct arg<4>
+{
+ BOOST_STATIC_CONSTANT(int, value = 4);
+ typedef arg<5> next;
+ BOOST_MPL_AUX_ARG_TYPEDEF(na, tag)
+ BOOST_MPL_AUX_ARG_TYPEDEF(na, type)
+
+ template<
+ typename U1 = na, typename U2 = na, typename U3 = na
+ , typename U4 = na, typename U5 = na
+ >
+ struct apply
+ {
+ typedef U4 type;
+ BOOST_MPL_AUX_ASSERT_NOT_NA(type);
+ };
+};
+
+template<> struct arg<5>
+{
+ BOOST_STATIC_CONSTANT(int, value = 5);
+ typedef arg<6> next;
+ BOOST_MPL_AUX_ARG_TYPEDEF(na, tag)
+ BOOST_MPL_AUX_ARG_TYPEDEF(na, type)
+
+ template<
+ typename U1 = na, typename U2 = na, typename U3 = na
+ , typename U4 = na, typename U5 = na
+ >
+ struct apply
+ {
+ typedef U5 type;
+ BOOST_MPL_AUX_ASSERT_NOT_NA(type);
+ };
+};
+
+BOOST_MPL_AUX_NONTYPE_ARITY_SPEC(1,int, arg)
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
diff --git a/third_party/boost/boost/mpl/aux_/preprocessed/gcc/bind.hpp b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/bind.hpp
new file mode 100644
index 0000000..65c61b5
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/bind.hpp
@@ -0,0 +1,560 @@
+
+// Copyright Peter Dimov 2001
+// Copyright Aleksey Gurtovoy 2001-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)
+//
+
+// Preprocessed version of "boost/mpl/bind.hpp" header
+// -- DO NOT modify by hand!
+
+namespace boost { namespace mpl {
+
+namespace aux {
+
+template<
+ typename T, typename U1, typename U2, typename U3, typename U4
+ , typename U5
+ >
+struct resolve_bind_arg
+{
+ typedef T type;
+};
+
+template<
+ typename T
+ , typename Arg
+ >
+struct replace_unnamed_arg
+{
+ typedef Arg next;
+ typedef T type;
+};
+
+template<
+ typename Arg
+ >
+struct replace_unnamed_arg< arg< -1 >, Arg >
+{
+ typedef typename Arg::next next;
+ typedef Arg type;
+};
+
+template<
+ int N, typename U1, typename U2, typename U3, typename U4, typename U5
+ >
+struct resolve_bind_arg< arg<N>, U1, U2, U3, U4, U5 >
+{
+ typedef typename apply_wrap5<mpl::arg<N>, U1, U2, U3, U4, U5>::type type;
+};
+
+template<
+ typename F, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename U1, typename U2, typename U3, typename U4
+ , typename U5
+ >
+struct resolve_bind_arg< bind< F,T1,T2,T3,T4,T5 >, U1, U2, U3, U4, U5 >
+{
+ typedef bind< F,T1,T2,T3,T4,T5 > f_;
+ typedef typename apply_wrap5< f_,U1,U2,U3,U4,U5 >::type type;
+};
+
+} // namespace aux
+
+template<
+ typename F
+ >
+struct bind0
+{
+ template<
+ typename U1 = na, typename U2 = na, typename U3 = na
+ , typename U4 = na, typename U5 = na
+ >
+ struct apply
+ {
+ private:
+ typedef aux::replace_unnamed_arg< F, mpl::arg<1> > r0;
+ typedef typename r0::type a0;
+ typedef typename r0::next n1;
+ typedef typename aux::resolve_bind_arg< a0,U1,U2,U3,U4,U5 >::type f_;
+ ///
+ public:
+ typedef typename apply_wrap0<
+ f_
+ >::type type;
+
+ };
+};
+
+namespace aux {
+
+template<
+ typename F, typename U1, typename U2, typename U3, typename U4
+ , typename U5
+ >
+struct resolve_bind_arg<
+ bind0<F>, U1, U2, U3, U4, U5
+ >
+{
+ typedef bind0<F> f_;
+ typedef typename apply_wrap5< f_,U1,U2,U3,U4,U5 >::type type;
+};
+
+} // namespace aux
+
+BOOST_MPL_AUX_ARITY_SPEC(1, bind0)
+BOOST_MPL_AUX_TEMPLATE_ARITY_SPEC(1, bind0)
+
+template<
+ typename F
+ >
+struct bind< F,na,na,na,na,na >
+ : bind0<F>
+{
+};
+
+template<
+ typename F, typename T1
+ >
+struct bind1
+{
+ template<
+ typename U1 = na, typename U2 = na, typename U3 = na
+ , typename U4 = na, typename U5 = na
+ >
+ struct apply
+ {
+ private:
+ typedef aux::replace_unnamed_arg< F, mpl::arg<1> > r0;
+ typedef typename r0::type a0;
+ typedef typename r0::next n1;
+ typedef typename aux::resolve_bind_arg< a0,U1,U2,U3,U4,U5 >::type f_;
+ ///
+ typedef aux::replace_unnamed_arg< T1,n1 > r1;
+ typedef typename r1::type a1;
+ typedef typename r1::next n2;
+ typedef aux::resolve_bind_arg< a1,U1,U2,U3,U4,U5 > t1;
+ ///
+ public:
+ typedef typename apply_wrap1<
+ f_
+ , typename t1::type
+ >::type type;
+
+ };
+};
+
+namespace aux {
+
+template<
+ typename F, typename T1, typename U1, typename U2, typename U3
+ , typename U4, typename U5
+ >
+struct resolve_bind_arg<
+ bind1< F,T1 >, U1, U2, U3, U4, U5
+ >
+{
+ typedef bind1< F,T1 > f_;
+ typedef typename apply_wrap5< f_,U1,U2,U3,U4,U5 >::type type;
+};
+
+} // namespace aux
+
+BOOST_MPL_AUX_ARITY_SPEC(2, bind1)
+BOOST_MPL_AUX_TEMPLATE_ARITY_SPEC(2, bind1)
+
+template<
+ typename F, typename T1
+ >
+struct bind< F,T1,na,na,na,na >
+ : bind1< F,T1 >
+{
+};
+
+template<
+ typename F, typename T1, typename T2
+ >
+struct bind2
+{
+ template<
+ typename U1 = na, typename U2 = na, typename U3 = na
+ , typename U4 = na, typename U5 = na
+ >
+ struct apply
+ {
+ private:
+ typedef aux::replace_unnamed_arg< F, mpl::arg<1> > r0;
+ typedef typename r0::type a0;
+ typedef typename r0::next n1;
+ typedef typename aux::resolve_bind_arg< a0,U1,U2,U3,U4,U5 >::type f_;
+ ///
+ typedef aux::replace_unnamed_arg< T1,n1 > r1;
+ typedef typename r1::type a1;
+ typedef typename r1::next n2;
+ typedef aux::resolve_bind_arg< a1,U1,U2,U3,U4,U5 > t1;
+ ///
+ typedef aux::replace_unnamed_arg< T2,n2 > r2;
+ typedef typename r2::type a2;
+ typedef typename r2::next n3;
+ typedef aux::resolve_bind_arg< a2,U1,U2,U3,U4,U5 > t2;
+ ///
+ public:
+ typedef typename apply_wrap2<
+ f_
+ , typename t1::type, typename t2::type
+ >::type type;
+
+ };
+};
+
+namespace aux {
+
+template<
+ typename F, typename T1, typename T2, typename U1, typename U2
+ , typename U3, typename U4, typename U5
+ >
+struct resolve_bind_arg<
+ bind2< F,T1,T2 >, U1, U2, U3, U4, U5
+ >
+{
+ typedef bind2< F,T1,T2 > f_;
+ typedef typename apply_wrap5< f_,U1,U2,U3,U4,U5 >::type type;
+};
+
+} // namespace aux
+
+BOOST_MPL_AUX_ARITY_SPEC(3, bind2)
+BOOST_MPL_AUX_TEMPLATE_ARITY_SPEC(3, bind2)
+
+template<
+ typename F, typename T1, typename T2
+ >
+struct bind< F,T1,T2,na,na,na >
+ : bind2< F,T1,T2 >
+{
+};
+
+template<
+ typename F, typename T1, typename T2, typename T3
+ >
+struct bind3
+{
+ template<
+ typename U1 = na, typename U2 = na, typename U3 = na
+ , typename U4 = na, typename U5 = na
+ >
+ struct apply
+ {
+ private:
+ typedef aux::replace_unnamed_arg< F, mpl::arg<1> > r0;
+ typedef typename r0::type a0;
+ typedef typename r0::next n1;
+ typedef typename aux::resolve_bind_arg< a0,U1,U2,U3,U4,U5 >::type f_;
+ ///
+ typedef aux::replace_unnamed_arg< T1,n1 > r1;
+ typedef typename r1::type a1;
+ typedef typename r1::next n2;
+ typedef aux::resolve_bind_arg< a1,U1,U2,U3,U4,U5 > t1;
+ ///
+ typedef aux::replace_unnamed_arg< T2,n2 > r2;
+ typedef typename r2::type a2;
+ typedef typename r2::next n3;
+ typedef aux::resolve_bind_arg< a2,U1,U2,U3,U4,U5 > t2;
+ ///
+ typedef aux::replace_unnamed_arg< T3,n3 > r3;
+ typedef typename r3::type a3;
+ typedef typename r3::next n4;
+ typedef aux::resolve_bind_arg< a3,U1,U2,U3,U4,U5 > t3;
+ ///
+ public:
+ typedef typename apply_wrap3<
+ f_
+ , typename t1::type, typename t2::type, typename t3::type
+ >::type type;
+
+ };
+};
+
+namespace aux {
+
+template<
+ typename F, typename T1, typename T2, typename T3, typename U1
+ , typename U2, typename U3, typename U4, typename U5
+ >
+struct resolve_bind_arg<
+ bind3< F,T1,T2,T3 >, U1, U2, U3, U4, U5
+ >
+{
+ typedef bind3< F,T1,T2,T3 > f_;
+ typedef typename apply_wrap5< f_,U1,U2,U3,U4,U5 >::type type;
+};
+
+} // namespace aux
+
+BOOST_MPL_AUX_ARITY_SPEC(4, bind3)
+BOOST_MPL_AUX_TEMPLATE_ARITY_SPEC(4, bind3)
+
+template<
+ typename F, typename T1, typename T2, typename T3
+ >
+struct bind< F,T1,T2,T3,na,na >
+ : bind3< F,T1,T2,T3 >
+{
+};
+
+template<
+ typename F, typename T1, typename T2, typename T3, typename T4
+ >
+struct bind4
+{
+ template<
+ typename U1 = na, typename U2 = na, typename U3 = na
+ , typename U4 = na, typename U5 = na
+ >
+ struct apply
+ {
+ private:
+ typedef aux::replace_unnamed_arg< F, mpl::arg<1> > r0;
+ typedef typename r0::type a0;
+ typedef typename r0::next n1;
+ typedef typename aux::resolve_bind_arg< a0,U1,U2,U3,U4,U5 >::type f_;
+ ///
+ typedef aux::replace_unnamed_arg< T1,n1 > r1;
+ typedef typename r1::type a1;
+ typedef typename r1::next n2;
+ typedef aux::resolve_bind_arg< a1,U1,U2,U3,U4,U5 > t1;
+ ///
+ typedef aux::replace_unnamed_arg< T2,n2 > r2;
+ typedef typename r2::type a2;
+ typedef typename r2::next n3;
+ typedef aux::resolve_bind_arg< a2,U1,U2,U3,U4,U5 > t2;
+ ///
+ typedef aux::replace_unnamed_arg< T3,n3 > r3;
+ typedef typename r3::type a3;
+ typedef typename r3::next n4;
+ typedef aux::resolve_bind_arg< a3,U1,U2,U3,U4,U5 > t3;
+ ///
+ typedef aux::replace_unnamed_arg< T4,n4 > r4;
+ typedef typename r4::type a4;
+ typedef typename r4::next n5;
+ typedef aux::resolve_bind_arg< a4,U1,U2,U3,U4,U5 > t4;
+ ///
+ public:
+ typedef typename apply_wrap4<
+ f_
+ , typename t1::type, typename t2::type, typename t3::type
+ , typename t4::type
+ >::type type;
+
+ };
+};
+
+namespace aux {
+
+template<
+ typename F, typename T1, typename T2, typename T3, typename T4
+ , typename U1, typename U2, typename U3, typename U4, typename U5
+ >
+struct resolve_bind_arg<
+ bind4< F,T1,T2,T3,T4 >, U1, U2, U3, U4, U5
+ >
+{
+ typedef bind4< F,T1,T2,T3,T4 > f_;
+ typedef typename apply_wrap5< f_,U1,U2,U3,U4,U5 >::type type;
+};
+
+} // namespace aux
+
+BOOST_MPL_AUX_ARITY_SPEC(5, bind4)
+BOOST_MPL_AUX_TEMPLATE_ARITY_SPEC(5, bind4)
+
+template<
+ typename F, typename T1, typename T2, typename T3, typename T4
+ >
+struct bind< F,T1,T2,T3,T4,na >
+ : bind4< F,T1,T2,T3,T4 >
+{
+};
+
+template<
+ typename F, typename T1, typename T2, typename T3, typename T4
+ , typename T5
+ >
+struct bind5
+{
+ template<
+ typename U1 = na, typename U2 = na, typename U3 = na
+ , typename U4 = na, typename U5 = na
+ >
+ struct apply
+ {
+ private:
+ typedef aux::replace_unnamed_arg< F, mpl::arg<1> > r0;
+ typedef typename r0::type a0;
+ typedef typename r0::next n1;
+ typedef typename aux::resolve_bind_arg< a0,U1,U2,U3,U4,U5 >::type f_;
+ ///
+ typedef aux::replace_unnamed_arg< T1,n1 > r1;
+ typedef typename r1::type a1;
+ typedef typename r1::next n2;
+ typedef aux::resolve_bind_arg< a1,U1,U2,U3,U4,U5 > t1;
+ ///
+ typedef aux::replace_unnamed_arg< T2,n2 > r2;
+ typedef typename r2::type a2;
+ typedef typename r2::next n3;
+ typedef aux::resolve_bind_arg< a2,U1,U2,U3,U4,U5 > t2;
+ ///
+ typedef aux::replace_unnamed_arg< T3,n3 > r3;
+ typedef typename r3::type a3;
+ typedef typename r3::next n4;
+ typedef aux::resolve_bind_arg< a3,U1,U2,U3,U4,U5 > t3;
+ ///
+ typedef aux::replace_unnamed_arg< T4,n4 > r4;
+ typedef typename r4::type a4;
+ typedef typename r4::next n5;
+ typedef aux::resolve_bind_arg< a4,U1,U2,U3,U4,U5 > t4;
+ ///
+ typedef aux::replace_unnamed_arg< T5,n5 > r5;
+ typedef typename r5::type a5;
+ typedef typename r5::next n6;
+ typedef aux::resolve_bind_arg< a5,U1,U2,U3,U4,U5 > t5;
+ ///
+ public:
+ typedef typename apply_wrap5<
+ f_
+ , typename t1::type, typename t2::type, typename t3::type
+ , typename t4::type, typename t5::type
+ >::type type;
+
+ };
+};
+
+namespace aux {
+
+template<
+ typename F, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename U1, typename U2, typename U3, typename U4
+ , typename U5
+ >
+struct resolve_bind_arg<
+ bind5< F,T1,T2,T3,T4,T5 >, U1, U2, U3, U4, U5
+ >
+{
+ typedef bind5< F,T1,T2,T3,T4,T5 > f_;
+ typedef typename apply_wrap5< f_,U1,U2,U3,U4,U5 >::type type;
+};
+
+} // namespace aux
+
+BOOST_MPL_AUX_ARITY_SPEC(6, bind5)
+BOOST_MPL_AUX_TEMPLATE_ARITY_SPEC(6, bind5)
+
+/// primary template (not a specialization!)
+
+template<
+ typename F, typename T1, typename T2, typename T3, typename T4
+ , typename T5
+ >
+struct bind
+ : bind5< F,T1,T2,T3,T4,T5 >
+{
+};
+
+/// if_/eval_if specializations
+template< template< typename T1, typename T2, typename T3 > class F, typename Tag >
+struct quote3;
+
+template< typename T1, typename T2, typename T3 > struct if_;
+
+template<
+ typename Tag, typename T1, typename T2, typename T3
+ >
+struct bind3<
+ quote3< if_,Tag >
+ , T1, T2, T3
+ >
+{
+ template<
+ typename U1 = na, typename U2 = na, typename U3 = na
+ , typename U4 = na, typename U5 = na
+ >
+ struct apply
+ {
+ private:
+ typedef mpl::arg<1> n1;
+ typedef aux::replace_unnamed_arg< T1,n1 > r1;
+ typedef typename r1::type a1;
+ typedef typename r1::next n2;
+ typedef aux::resolve_bind_arg< a1,U1,U2,U3,U4,U5 > t1;
+ ///
+ typedef aux::replace_unnamed_arg< T2,n2 > r2;
+ typedef typename r2::type a2;
+ typedef typename r2::next n3;
+ typedef aux::resolve_bind_arg< a2,U1,U2,U3,U4,U5 > t2;
+ ///
+ typedef aux::replace_unnamed_arg< T3,n3 > r3;
+ typedef typename r3::type a3;
+ typedef typename r3::next n4;
+ typedef aux::resolve_bind_arg< a3,U1,U2,U3,U4,U5 > t3;
+ ///
+ typedef typename if_<
+ typename t1::type
+ , t2, t3
+ >::type f_;
+
+ public:
+ typedef typename f_::type type;
+ };
+};
+
+template<
+ template< typename T1, typename T2, typename T3 > class F, typename Tag
+ >
+struct quote3;
+
+template< typename T1, typename T2, typename T3 > struct eval_if;
+
+template<
+ typename Tag, typename T1, typename T2, typename T3
+ >
+struct bind3<
+ quote3< eval_if,Tag >
+ , T1, T2, T3
+ >
+{
+ template<
+ typename U1 = na, typename U2 = na, typename U3 = na
+ , typename U4 = na, typename U5 = na
+ >
+ struct apply
+ {
+ private:
+ typedef mpl::arg<1> n1;
+ typedef aux::replace_unnamed_arg< T1,n1 > r1;
+ typedef typename r1::type a1;
+ typedef typename r1::next n2;
+ typedef aux::resolve_bind_arg< a1,U1,U2,U3,U4,U5 > t1;
+ ///
+ typedef aux::replace_unnamed_arg< T2,n2 > r2;
+ typedef typename r2::type a2;
+ typedef typename r2::next n3;
+ typedef aux::resolve_bind_arg< a2,U1,U2,U3,U4,U5 > t2;
+ ///
+ typedef aux::replace_unnamed_arg< T3,n3 > r3;
+ typedef typename r3::type a3;
+ typedef typename r3::next n4;
+ typedef aux::resolve_bind_arg< a3,U1,U2,U3,U4,U5 > t3;
+ ///
+ typedef typename eval_if<
+ typename t1::type
+ , t2, t3
+ >::type f_;
+
+ public:
+ typedef typename f_::type type;
+ };
+};
+
+}}
diff --git a/third_party/boost/boost/mpl/aux_/preprocessed/gcc/bind_fwd.hpp b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/bind_fwd.hpp
new file mode 100644
index 0000000..480e181
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/bind_fwd.hpp
@@ -0,0 +1,51 @@
+
+// Copyright Aleksey Gurtovoy 2000-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)
+//
+
+// Preprocessed version of "boost/mpl/bind_fwd.hpp" header
+// -- DO NOT modify by hand!
+
+namespace boost { namespace mpl {
+
+template<
+ typename F, typename T1 = na, typename T2 = na, typename T3 = na
+ , typename T4 = na, typename T5 = na
+ >
+struct bind;
+
+template<
+ typename F
+ >
+struct bind0;
+
+template<
+ typename F, typename T1
+ >
+struct bind1;
+
+template<
+ typename F, typename T1, typename T2
+ >
+struct bind2;
+
+template<
+ typename F, typename T1, typename T2, typename T3
+ >
+struct bind3;
+
+template<
+ typename F, typename T1, typename T2, typename T3, typename T4
+ >
+struct bind4;
+
+template<
+ typename F, typename T1, typename T2, typename T3, typename T4
+ , typename T5
+ >
+struct bind5;
+
+}}
diff --git a/third_party/boost/boost/mpl/aux_/preprocessed/gcc/fold_impl.hpp b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/fold_impl.hpp
new file mode 100644
index 0000000..8bc6ab7
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/fold_impl.hpp
@@ -0,0 +1,180 @@
+
+// Copyright Aleksey Gurtovoy 2000-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)
+//
+
+// Preprocessed version of "boost/mpl/aux_/fold_impl.hpp" header
+// -- DO NOT modify by hand!
+
+namespace boost { namespace mpl { namespace aux {
+
+/// forward declaration
+
+template<
+ int N
+ , typename First
+ , typename Last
+ , typename State
+ , typename ForwardOp
+ >
+struct fold_impl;
+
+template<
+ typename First
+ , typename Last
+ , typename State
+ , typename ForwardOp
+ >
+struct fold_impl< 0,First,Last,State,ForwardOp >
+{
+ typedef First iter0;
+ typedef State state0;
+ typedef state0 state;
+ typedef iter0 iterator;
+};
+
+template<
+ typename First
+ , typename Last
+ , typename State
+ , typename ForwardOp
+ >
+struct fold_impl< 1,First,Last,State,ForwardOp >
+{
+ typedef First iter0;
+ typedef State state0;
+ typedef typename apply2< ForwardOp, state0, typename deref<iter0>::type >::type state1;
+ typedef typename mpl::next<iter0>::type iter1;
+
+
+ typedef state1 state;
+ typedef iter1 iterator;
+};
+
+template<
+ typename First
+ , typename Last
+ , typename State
+ , typename ForwardOp
+ >
+struct fold_impl< 2,First,Last,State,ForwardOp >
+{
+ typedef First iter0;
+ typedef State state0;
+ typedef typename apply2< ForwardOp, state0, typename deref<iter0>::type >::type state1;
+ typedef typename mpl::next<iter0>::type iter1;
+ typedef typename apply2< ForwardOp, state1, typename deref<iter1>::type >::type state2;
+ typedef typename mpl::next<iter1>::type iter2;
+
+
+ typedef state2 state;
+ typedef iter2 iterator;
+};
+
+template<
+ typename First
+ , typename Last
+ , typename State
+ , typename ForwardOp
+ >
+struct fold_impl< 3,First,Last,State,ForwardOp >
+{
+ typedef First iter0;
+ typedef State state0;
+ typedef typename apply2< ForwardOp, state0, typename deref<iter0>::type >::type state1;
+ typedef typename mpl::next<iter0>::type iter1;
+ typedef typename apply2< ForwardOp, state1, typename deref<iter1>::type >::type state2;
+ typedef typename mpl::next<iter1>::type iter2;
+ typedef typename apply2< ForwardOp, state2, typename deref<iter2>::type >::type state3;
+ typedef typename mpl::next<iter2>::type iter3;
+
+
+ typedef state3 state;
+ typedef iter3 iterator;
+};
+
+template<
+ typename First
+ , typename Last
+ , typename State
+ , typename ForwardOp
+ >
+struct fold_impl< 4,First,Last,State,ForwardOp >
+{
+ typedef First iter0;
+ typedef State state0;
+ typedef typename apply2< ForwardOp, state0, typename deref<iter0>::type >::type state1;
+ typedef typename mpl::next<iter0>::type iter1;
+ typedef typename apply2< ForwardOp, state1, typename deref<iter1>::type >::type state2;
+ typedef typename mpl::next<iter1>::type iter2;
+ typedef typename apply2< ForwardOp, state2, typename deref<iter2>::type >::type state3;
+ typedef typename mpl::next<iter2>::type iter3;
+ typedef typename apply2< ForwardOp, state3, typename deref<iter3>::type >::type state4;
+ typedef typename mpl::next<iter3>::type iter4;
+
+
+ typedef state4 state;
+ typedef iter4 iterator;
+};
+
+template<
+ int N
+ , typename First
+ , typename Last
+ , typename State
+ , typename ForwardOp
+ >
+struct fold_impl
+{
+ typedef fold_impl<
+ 4
+ , First
+ , Last
+ , State
+ , ForwardOp
+ > chunk_;
+
+ typedef fold_impl<
+ ( (N - 4) < 0 ? 0 : N - 4 )
+ , typename chunk_::iterator
+ , Last
+ , typename chunk_::state
+ , ForwardOp
+ > res_;
+
+ typedef typename res_::state state;
+ typedef typename res_::iterator iterator;
+};
+
+template<
+ typename First
+ , typename Last
+ , typename State
+ , typename ForwardOp
+ >
+struct fold_impl< -1,First,Last,State,ForwardOp >
+ : fold_impl<
+ -1
+ , typename mpl::next<First>::type
+ , Last
+ , typename apply2<ForwardOp,State, typename deref<First>::type>::type
+ , ForwardOp
+ >
+{
+};
+
+template<
+ typename Last
+ , typename State
+ , typename ForwardOp
+ >
+struct fold_impl< -1,Last,Last,State,ForwardOp >
+{
+ typedef State state;
+ typedef Last iterator;
+};
+
+}}}
diff --git a/third_party/boost/boost/mpl/aux_/preprocessed/gcc/full_lambda.hpp b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/full_lambda.hpp
new file mode 100644
index 0000000..05c6b75
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/full_lambda.hpp
@@ -0,0 +1,557 @@
+
+// Copyright Aleksey Gurtovoy 2001-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)
+//
+
+// Preprocessed version of "boost/mpl/aux_/full_lambda.hpp" header
+// -- DO NOT modify by hand!
+
+namespace boost { namespace mpl {
+
+namespace aux {
+
+template<
+ bool C1 = false, bool C2 = false, bool C3 = false, bool C4 = false
+ , bool C5 = false
+ >
+struct lambda_or
+ : true_
+{
+};
+
+template<>
+struct lambda_or< false,false,false,false,false >
+ : false_
+{
+};
+
+} // namespace aux
+
+template<
+ typename T
+ , typename Tag
+ , typename Arity
+ >
+struct lambda
+{
+ typedef false_ is_le;
+ typedef T result_;
+ typedef T type;
+};
+
+template<
+ typename T
+ >
+struct is_lambda_expression
+ : lambda<T>::is_le
+{
+};
+
+template< int N, typename Tag >
+struct lambda< arg<N>,Tag, int_< -1 > >
+{
+ typedef true_ is_le;
+ typedef mpl::arg<N> result_; // qualified for the sake of MIPSpro 7.41
+ typedef mpl::protect<result_> type;
+};
+
+template<
+ typename F
+ , typename Tag
+ >
+struct lambda<
+ bind0<F>
+ , Tag
+ , int_<1>
+ >
+{
+ typedef false_ is_le;
+ typedef bind0<
+ F
+ > result_;
+
+ typedef result_ type;
+};
+
+namespace aux {
+
+template<
+ typename IsLE, typename Tag
+ , template< typename P1 > class F
+ , typename L1
+ >
+struct le_result1
+{
+ typedef F<
+ typename L1::type
+ > result_;
+
+ typedef result_ type;
+};
+
+template<
+ typename Tag
+ , template< typename P1 > class F
+ , typename L1
+ >
+struct le_result1< true_,Tag,F,L1 >
+{
+ typedef bind1<
+ quote1< F,Tag >
+ , typename L1::result_
+ > result_;
+
+ typedef mpl::protect<result_> type;
+};
+
+} // namespace aux
+
+template<
+ template< typename P1 > class F
+ , typename T1
+ , typename Tag
+ >
+struct lambda<
+ F<T1>
+ , Tag
+ , int_<1>
+ >
+{
+ typedef lambda< T1,Tag > l1;
+ typedef typename l1::is_le is_le1;
+ typedef typename aux::lambda_or<
+ is_le1::value
+ >::type is_le;
+
+ typedef aux::le_result1<
+ is_le, Tag, F, l1
+ > le_result_;
+
+ typedef typename le_result_::result_ result_;
+ typedef typename le_result_::type type;
+};
+
+template<
+ typename F, typename T1
+ , typename Tag
+ >
+struct lambda<
+ bind1< F,T1 >
+ , Tag
+ , int_<2>
+ >
+{
+ typedef false_ is_le;
+ typedef bind1<
+ F
+ , T1
+ > result_;
+
+ typedef result_ type;
+};
+
+namespace aux {
+
+template<
+ typename IsLE, typename Tag
+ , template< typename P1, typename P2 > class F
+ , typename L1, typename L2
+ >
+struct le_result2
+{
+ typedef F<
+ typename L1::type, typename L2::type
+ > result_;
+
+ typedef result_ type;
+};
+
+template<
+ typename Tag
+ , template< typename P1, typename P2 > class F
+ , typename L1, typename L2
+ >
+struct le_result2< true_,Tag,F,L1,L2 >
+{
+ typedef bind2<
+ quote2< F,Tag >
+ , typename L1::result_, typename L2::result_
+ > result_;
+
+ typedef mpl::protect<result_> type;
+};
+
+} // namespace aux
+
+template<
+ template< typename P1, typename P2 > class F
+ , typename T1, typename T2
+ , typename Tag
+ >
+struct lambda<
+ F< T1,T2 >
+ , Tag
+ , int_<2>
+ >
+{
+ typedef lambda< T1,Tag > l1;
+ typedef lambda< T2,Tag > l2;
+
+ typedef typename l1::is_le is_le1;
+ typedef typename l2::is_le is_le2;
+
+
+ typedef typename aux::lambda_or<
+ is_le1::value, is_le2::value
+ >::type is_le;
+
+ typedef aux::le_result2<
+ is_le, Tag, F, l1, l2
+ > le_result_;
+
+ typedef typename le_result_::result_ result_;
+ typedef typename le_result_::type type;
+};
+
+template<
+ typename F, typename T1, typename T2
+ , typename Tag
+ >
+struct lambda<
+ bind2< F,T1,T2 >
+ , Tag
+ , int_<3>
+ >
+{
+ typedef false_ is_le;
+ typedef bind2<
+ F
+ , T1, T2
+ > result_;
+
+ typedef result_ type;
+};
+
+namespace aux {
+
+template<
+ typename IsLE, typename Tag
+ , template< typename P1, typename P2, typename P3 > class F
+ , typename L1, typename L2, typename L3
+ >
+struct le_result3
+{
+ typedef F<
+ typename L1::type, typename L2::type, typename L3::type
+ > result_;
+
+ typedef result_ type;
+};
+
+template<
+ typename Tag
+ , template< typename P1, typename P2, typename P3 > class F
+ , typename L1, typename L2, typename L3
+ >
+struct le_result3< true_,Tag,F,L1,L2,L3 >
+{
+ typedef bind3<
+ quote3< F,Tag >
+ , typename L1::result_, typename L2::result_, typename L3::result_
+ > result_;
+
+ typedef mpl::protect<result_> type;
+};
+
+} // namespace aux
+
+template<
+ template< typename P1, typename P2, typename P3 > class F
+ , typename T1, typename T2, typename T3
+ , typename Tag
+ >
+struct lambda<
+ F< T1,T2,T3 >
+ , Tag
+ , int_<3>
+ >
+{
+ typedef lambda< T1,Tag > l1;
+ typedef lambda< T2,Tag > l2;
+ typedef lambda< T3,Tag > l3;
+
+ typedef typename l1::is_le is_le1;
+ typedef typename l2::is_le is_le2;
+ typedef typename l3::is_le is_le3;
+
+
+ typedef typename aux::lambda_or<
+ is_le1::value, is_le2::value, is_le3::value
+ >::type is_le;
+
+ typedef aux::le_result3<
+ is_le, Tag, F, l1, l2, l3
+ > le_result_;
+
+ typedef typename le_result_::result_ result_;
+ typedef typename le_result_::type type;
+};
+
+template<
+ typename F, typename T1, typename T2, typename T3
+ , typename Tag
+ >
+struct lambda<
+ bind3< F,T1,T2,T3 >
+ , Tag
+ , int_<4>
+ >
+{
+ typedef false_ is_le;
+ typedef bind3<
+ F
+ , T1, T2, T3
+ > result_;
+
+ typedef result_ type;
+};
+
+namespace aux {
+
+template<
+ typename IsLE, typename Tag
+ , template< typename P1, typename P2, typename P3, typename P4 > class F
+ , typename L1, typename L2, typename L3, typename L4
+ >
+struct le_result4
+{
+ typedef F<
+ typename L1::type, typename L2::type, typename L3::type
+ , typename L4::type
+ > result_;
+
+ typedef result_ type;
+};
+
+template<
+ typename Tag
+ , template< typename P1, typename P2, typename P3, typename P4 > class F
+ , typename L1, typename L2, typename L3, typename L4
+ >
+struct le_result4< true_,Tag,F,L1,L2,L3,L4 >
+{
+ typedef bind4<
+ quote4< F,Tag >
+ , typename L1::result_, typename L2::result_, typename L3::result_
+ , typename L4::result_
+ > result_;
+
+ typedef mpl::protect<result_> type;
+};
+
+} // namespace aux
+
+template<
+ template< typename P1, typename P2, typename P3, typename P4 > class F
+ , typename T1, typename T2, typename T3, typename T4
+ , typename Tag
+ >
+struct lambda<
+ F< T1,T2,T3,T4 >
+ , Tag
+ , int_<4>
+ >
+{
+ typedef lambda< T1,Tag > l1;
+ typedef lambda< T2,Tag > l2;
+ typedef lambda< T3,Tag > l3;
+ typedef lambda< T4,Tag > l4;
+
+ typedef typename l1::is_le is_le1;
+ typedef typename l2::is_le is_le2;
+ typedef typename l3::is_le is_le3;
+ typedef typename l4::is_le is_le4;
+
+
+ typedef typename aux::lambda_or<
+ is_le1::value, is_le2::value, is_le3::value, is_le4::value
+ >::type is_le;
+
+ typedef aux::le_result4<
+ is_le, Tag, F, l1, l2, l3, l4
+ > le_result_;
+
+ typedef typename le_result_::result_ result_;
+ typedef typename le_result_::type type;
+};
+
+template<
+ typename F, typename T1, typename T2, typename T3, typename T4
+ , typename Tag
+ >
+struct lambda<
+ bind4< F,T1,T2,T3,T4 >
+ , Tag
+ , int_<5>
+ >
+{
+ typedef false_ is_le;
+ typedef bind4<
+ F
+ , T1, T2, T3, T4
+ > result_;
+
+ typedef result_ type;
+};
+
+namespace aux {
+
+template<
+ typename IsLE, typename Tag
+ , template< typename P1, typename P2, typename P3, typename P4, typename P5 > class F
+ , typename L1, typename L2, typename L3, typename L4, typename L5
+ >
+struct le_result5
+{
+ typedef F<
+ typename L1::type, typename L2::type, typename L3::type
+ , typename L4::type, typename L5::type
+ > result_;
+
+ typedef result_ type;
+};
+
+template<
+ typename Tag
+ , template< typename P1, typename P2, typename P3, typename P4, typename P5 > class F
+ , typename L1, typename L2, typename L3, typename L4, typename L5
+ >
+struct le_result5< true_,Tag,F,L1,L2,L3,L4,L5 >
+{
+ typedef bind5<
+ quote5< F,Tag >
+ , typename L1::result_, typename L2::result_, typename L3::result_
+ , typename L4::result_, typename L5::result_
+ > result_;
+
+ typedef mpl::protect<result_> type;
+};
+
+} // namespace aux
+
+template<
+ template<
+ typename P1, typename P2, typename P3, typename P4
+ , typename P5
+ >
+ class F
+ , typename T1, typename T2, typename T3, typename T4, typename T5
+ , typename Tag
+ >
+struct lambda<
+ F< T1,T2,T3,T4,T5 >
+ , Tag
+ , int_<5>
+ >
+{
+ typedef lambda< T1,Tag > l1;
+ typedef lambda< T2,Tag > l2;
+ typedef lambda< T3,Tag > l3;
+ typedef lambda< T4,Tag > l4;
+ typedef lambda< T5,Tag > l5;
+
+ typedef typename l1::is_le is_le1;
+ typedef typename l2::is_le is_le2;
+ typedef typename l3::is_le is_le3;
+ typedef typename l4::is_le is_le4;
+ typedef typename l5::is_le is_le5;
+
+
+ typedef typename aux::lambda_or<
+ is_le1::value, is_le2::value, is_le3::value, is_le4::value
+ , is_le5::value
+ >::type is_le;
+
+ typedef aux::le_result5<
+ is_le, Tag, F, l1, l2, l3, l4, l5
+ > le_result_;
+
+ typedef typename le_result_::result_ result_;
+ typedef typename le_result_::type type;
+};
+
+template<
+ typename F, typename T1, typename T2, typename T3, typename T4
+ , typename T5
+ , typename Tag
+ >
+struct lambda<
+ bind5< F,T1,T2,T3,T4,T5 >
+ , Tag
+ , int_<6>
+ >
+{
+ typedef false_ is_le;
+ typedef bind5<
+ F
+ , T1, T2, T3, T4, T5
+ > result_;
+
+ typedef result_ type;
+};
+
+/// special case for 'protect'
+template< typename T, typename Tag >
+struct lambda< mpl::protect<T>,Tag, int_<1> >
+{
+ typedef false_ is_le;
+ typedef mpl::protect<T> result_;
+ typedef result_ type;
+};
+
+/// specializations for the main 'bind' form
+
+template<
+ typename F, typename T1, typename T2, typename T3, typename T4
+ , typename T5
+ , typename Tag
+ >
+struct lambda<
+ bind< F,T1,T2,T3,T4,T5 >
+ , Tag
+ , int_<6>
+ >
+{
+ typedef false_ is_le;
+ typedef bind< F,T1,T2,T3,T4,T5 > result_;
+ typedef result_ type;
+};
+
+template<
+ typename F
+ , typename Tag1
+ , typename Tag2
+ , typename Arity
+ >
+struct lambda<
+ lambda< F,Tag1,Arity >
+ , Tag2
+ , int_<3>
+ >
+{
+ typedef lambda< F,Tag2 > l1;
+ typedef lambda< Tag1,Tag2 > l2;
+ typedef typename l1::is_le is_le;
+ typedef bind1< quote1<aux::template_arity>, typename l1::result_ > arity_;
+ typedef lambda< typename if_< is_le,arity_,Arity >::type, Tag2 > l3;
+ typedef aux::le_result3<is_le, Tag2, mpl::lambda, l1, l2, l3> le_result_;
+ typedef typename le_result_::result_ result_;
+ typedef typename le_result_::type type;
+};
+
+BOOST_MPL_AUX_NA_SPEC2(2, 3, lambda)
+
+}}
diff --git a/third_party/boost/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp
new file mode 100644
index 0000000..fba0051
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp
@@ -0,0 +1,133 @@
+
+// Copyright Aleksey Gurtovoy 2001-2004
+// Copyright David Abrahams 2001-2002
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// Preprocessed version of "boost/mpl/aux_/iter_fold_if_impl.hpp" header
+// -- DO NOT modify by hand!
+
+namespace boost { namespace mpl { namespace aux {
+
+template< typename Iterator, typename State >
+struct iter_fold_if_null_step
+{
+ typedef State state;
+ typedef Iterator iterator;
+};
+
+template< bool >
+struct iter_fold_if_step_impl
+{
+ template<
+ typename Iterator
+ , typename State
+ , typename StateOp
+ , typename IteratorOp
+ >
+ struct result_
+ {
+ typedef typename apply2< StateOp,State,Iterator >::type state;
+ typedef typename IteratorOp::type iterator;
+ };
+};
+
+template<>
+struct iter_fold_if_step_impl<false>
+{
+ template<
+ typename Iterator
+ , typename State
+ , typename StateOp
+ , typename IteratorOp
+ >
+ struct result_
+ {
+ typedef State state;
+ typedef Iterator iterator;
+ };
+};
+
+template<
+ typename Iterator
+ , typename State
+ , typename ForwardOp
+ , typename Predicate
+ >
+struct iter_fold_if_forward_step
+{
+ typedef typename apply2< Predicate,State,Iterator >::type not_last;
+ typedef typename iter_fold_if_step_impl<
+ BOOST_MPL_AUX_MSVC_VALUE_WKND(not_last)::value
+ >::template result_< Iterator,State,ForwardOp, mpl::next<Iterator> > impl_;
+
+ typedef typename impl_::state state;
+ typedef typename impl_::iterator iterator;
+};
+
+template<
+ typename Iterator
+ , typename State
+ , typename BackwardOp
+ , typename Predicate
+ >
+struct iter_fold_if_backward_step
+{
+ typedef typename apply2< Predicate,State,Iterator >::type not_last;
+ typedef typename iter_fold_if_step_impl<
+ BOOST_MPL_AUX_MSVC_VALUE_WKND(not_last)::value
+ >::template result_< Iterator,State,BackwardOp, identity<Iterator> > impl_;
+
+ typedef typename impl_::state state;
+ typedef typename impl_::iterator iterator;
+};
+
+template<
+ typename Iterator
+ , typename State
+ , typename ForwardOp
+ , typename ForwardPredicate
+ , typename BackwardOp
+ , typename BackwardPredicate
+ >
+struct iter_fold_if_impl
+{
+ private:
+ typedef iter_fold_if_null_step< Iterator,State > forward_step0;
+ typedef iter_fold_if_forward_step< typename forward_step0::iterator, typename forward_step0::state, ForwardOp, ForwardPredicate > forward_step1;
+ typedef iter_fold_if_forward_step< typename forward_step1::iterator, typename forward_step1::state, ForwardOp, ForwardPredicate > forward_step2;
+ typedef iter_fold_if_forward_step< typename forward_step2::iterator, typename forward_step2::state, ForwardOp, ForwardPredicate > forward_step3;
+ typedef iter_fold_if_forward_step< typename forward_step3::iterator, typename forward_step3::state, ForwardOp, ForwardPredicate > forward_step4;
+
+
+ typedef typename if_<
+ typename forward_step4::not_last
+ , iter_fold_if_impl<
+ typename forward_step4::iterator
+ , typename forward_step4::state
+ , ForwardOp
+ , ForwardPredicate
+ , BackwardOp
+ , BackwardPredicate
+ >
+ , iter_fold_if_null_step<
+ typename forward_step4::iterator
+ , typename forward_step4::state
+ >
+ >::type backward_step4;
+
+ typedef iter_fold_if_backward_step< typename forward_step3::iterator, typename backward_step4::state, BackwardOp, BackwardPredicate > backward_step3;
+ typedef iter_fold_if_backward_step< typename forward_step2::iterator, typename backward_step3::state, BackwardOp, BackwardPredicate > backward_step2;
+ typedef iter_fold_if_backward_step< typename forward_step1::iterator, typename backward_step2::state, BackwardOp, BackwardPredicate > backward_step1;
+ typedef iter_fold_if_backward_step< typename forward_step0::iterator, typename backward_step1::state, BackwardOp, BackwardPredicate > backward_step0;
+
+
+ public:
+ typedef typename backward_step0::state state;
+ typedef typename backward_step4::iterator iterator;
+};
+
+}}}
diff --git a/third_party/boost/boost/mpl/aux_/preprocessed/gcc/iter_fold_impl.hpp b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/iter_fold_impl.hpp
new file mode 100644
index 0000000..e4453de
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/iter_fold_impl.hpp
@@ -0,0 +1,180 @@
+
+// Copyright Aleksey Gurtovoy 2000-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)
+//
+
+// Preprocessed version of "boost/mpl/aux_/iter_fold_impl.hpp" header
+// -- DO NOT modify by hand!
+
+namespace boost { namespace mpl { namespace aux {
+
+/// forward declaration
+
+template<
+ int N
+ , typename First
+ , typename Last
+ , typename State
+ , typename ForwardOp
+ >
+struct iter_fold_impl;
+
+template<
+ typename First
+ , typename Last
+ , typename State
+ , typename ForwardOp
+ >
+struct iter_fold_impl< 0,First,Last,State,ForwardOp >
+{
+ typedef First iter0;
+ typedef State state0;
+ typedef state0 state;
+ typedef iter0 iterator;
+};
+
+template<
+ typename First
+ , typename Last
+ , typename State
+ , typename ForwardOp
+ >
+struct iter_fold_impl< 1,First,Last,State,ForwardOp >
+{
+ typedef First iter0;
+ typedef State state0;
+ typedef typename apply2< ForwardOp,state0,iter0 >::type state1;
+ typedef typename mpl::next<iter0>::type iter1;
+
+
+ typedef state1 state;
+ typedef iter1 iterator;
+};
+
+template<
+ typename First
+ , typename Last
+ , typename State
+ , typename ForwardOp
+ >
+struct iter_fold_impl< 2,First,Last,State,ForwardOp >
+{
+ typedef First iter0;
+ typedef State state0;
+ typedef typename apply2< ForwardOp,state0,iter0 >::type state1;
+ typedef typename mpl::next<iter0>::type iter1;
+ typedef typename apply2< ForwardOp,state1,iter1 >::type state2;
+ typedef typename mpl::next<iter1>::type iter2;
+
+
+ typedef state2 state;
+ typedef iter2 iterator;
+};
+
+template<
+ typename First
+ , typename Last
+ , typename State
+ , typename ForwardOp
+ >
+struct iter_fold_impl< 3,First,Last,State,ForwardOp >
+{
+ typedef First iter0;
+ typedef State state0;
+ typedef typename apply2< ForwardOp,state0,iter0 >::type state1;
+ typedef typename mpl::next<iter0>::type iter1;
+ typedef typename apply2< ForwardOp,state1,iter1 >::type state2;
+ typedef typename mpl::next<iter1>::type iter2;
+ typedef typename apply2< ForwardOp,state2,iter2 >::type state3;
+ typedef typename mpl::next<iter2>::type iter3;
+
+
+ typedef state3 state;
+ typedef iter3 iterator;
+};
+
+template<
+ typename First
+ , typename Last
+ , typename State
+ , typename ForwardOp
+ >
+struct iter_fold_impl< 4,First,Last,State,ForwardOp >
+{
+ typedef First iter0;
+ typedef State state0;
+ typedef typename apply2< ForwardOp,state0,iter0 >::type state1;
+ typedef typename mpl::next<iter0>::type iter1;
+ typedef typename apply2< ForwardOp,state1,iter1 >::type state2;
+ typedef typename mpl::next<iter1>::type iter2;
+ typedef typename apply2< ForwardOp,state2,iter2 >::type state3;
+ typedef typename mpl::next<iter2>::type iter3;
+ typedef typename apply2< ForwardOp,state3,iter3 >::type state4;
+ typedef typename mpl::next<iter3>::type iter4;
+
+
+ typedef state4 state;
+ typedef iter4 iterator;
+};
+
+template<
+ int N
+ , typename First
+ , typename Last
+ , typename State
+ , typename ForwardOp
+ >
+struct iter_fold_impl
+{
+ typedef iter_fold_impl<
+ 4
+ , First
+ , Last
+ , State
+ , ForwardOp
+ > chunk_;
+
+ typedef iter_fold_impl<
+ ( (N - 4) < 0 ? 0 : N - 4 )
+ , typename chunk_::iterator
+ , Last
+ , typename chunk_::state
+ , ForwardOp
+ > res_;
+
+ typedef typename res_::state state;
+ typedef typename res_::iterator iterator;
+};
+
+template<
+ typename First
+ , typename Last
+ , typename State
+ , typename ForwardOp
+ >
+struct iter_fold_impl< -1,First,Last,State,ForwardOp >
+ : iter_fold_impl<
+ -1
+ , typename mpl::next<First>::type
+ , Last
+ , typename apply2< ForwardOp,State,First >::type
+ , ForwardOp
+ >
+{
+};
+
+template<
+ typename Last
+ , typename State
+ , typename ForwardOp
+ >
+struct iter_fold_impl< -1,Last,Last,State,ForwardOp >
+{
+ typedef State state;
+ typedef Last iterator;
+};
+
+}}}
diff --git a/third_party/boost/boost/mpl/aux_/preprocessed/gcc/less.hpp b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/less.hpp
new file mode 100644
index 0000000..e57fc20
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/less.hpp
@@ -0,0 +1,94 @@
+
+// Copyright Aleksey Gurtovoy 2000-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)
+//
+
+// Preprocessed version of "boost/mpl/less.hpp" header
+// -- DO NOT modify by hand!
+
+namespace boost { namespace mpl {
+
+template<
+ typename Tag1
+ , typename Tag2
+ >
+struct less_impl
+ : if_c<
+ ( BOOST_MPL_AUX_NESTED_VALUE_WKND(int, Tag1)
+ > BOOST_MPL_AUX_NESTED_VALUE_WKND(int, Tag2)
+ )
+
+ , aux::cast2nd_impl< less_impl< Tag1,Tag1 >,Tag1, Tag2 >
+ , aux::cast1st_impl< less_impl< Tag2,Tag2 >,Tag1, Tag2 >
+ >::type
+{
+};
+
+/// for Digital Mars C++/compilers with no CTPS/TTP support
+template<> struct less_impl< na,na >
+{
+ template< typename U1, typename U2 > struct apply
+ {
+ typedef apply type;
+ BOOST_STATIC_CONSTANT(int, value = 0);
+ };
+};
+
+template< typename Tag > struct less_impl< na,Tag >
+{
+ template< typename U1, typename U2 > struct apply
+ {
+ typedef apply type;
+ BOOST_STATIC_CONSTANT(int, value = 0);
+ };
+};
+
+template< typename Tag > struct less_impl< Tag,na >
+{
+ template< typename U1, typename U2 > struct apply
+ {
+ typedef apply type;
+ BOOST_STATIC_CONSTANT(int, value = 0);
+ };
+};
+
+template< typename T > struct less_tag
+{
+ typedef typename T::tag type;
+};
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(N1)
+ , typename BOOST_MPL_AUX_NA_PARAM(N2)
+ >
+struct less
+
+ : less_impl<
+ typename less_tag<N1>::type
+ , typename less_tag<N2>::type
+ >::template apply< N1,N2 >::type
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(2, less, (N1, N2))
+
+};
+
+BOOST_MPL_AUX_NA_SPEC2(2, 2, less)
+
+}}
+
+namespace boost { namespace mpl {
+
+template<>
+struct less_impl< integral_c_tag,integral_c_tag >
+{
+ template< typename N1, typename N2 > struct apply
+
+ : bool_< ( BOOST_MPL_AUX_VALUE_WKND(N2)::value > BOOST_MPL_AUX_VALUE_WKND(N1)::value ) >
+ {
+ };
+};
+
+}}
diff --git a/third_party/boost/boost/mpl/aux_/preprocessed/gcc/list.hpp b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/list.hpp
new file mode 100644
index 0000000..055767c
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/list.hpp
@@ -0,0 +1,322 @@
+
+// Copyright Aleksey Gurtovoy 2000-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)
+//
+
+// Preprocessed version of "boost/mpl/list.hpp" header
+// -- DO NOT modify by hand!
+
+namespace boost { namespace mpl {
+
+template<
+ typename T0 = na, typename T1 = na, typename T2 = na, typename T3 = na
+ , typename T4 = na, typename T5 = na, typename T6 = na, typename T7 = na
+ , typename T8 = na, typename T9 = na, typename T10 = na, typename T11 = na
+ , typename T12 = na, typename T13 = na, typename T14 = na
+ , typename T15 = na, typename T16 = na, typename T17 = na
+ , typename T18 = na, typename T19 = na
+ >
+struct list;
+
+template<
+
+ >
+struct list<
+ na, na, na, na, na, na, na, na, na, na, na, na, na, na, na, na, na
+ , na, na, na
+ >
+ : list0< >
+{
+ typedef list0< >::type type;
+};
+
+template<
+ typename T0
+ >
+struct list<
+ T0, na, na, na, na, na, na, na, na, na, na, na, na, na, na, na, na
+ , na, na, na
+ >
+ : list1<T0>
+{
+ typedef typename list1<T0>::type type;
+};
+
+template<
+ typename T0, typename T1
+ >
+struct list<
+ T0, T1, na, na, na, na, na, na, na, na, na, na, na, na, na, na, na
+ , na, na, na
+ >
+ : list2< T0,T1 >
+{
+ typedef typename list2< T0,T1 >::type type;
+};
+
+template<
+ typename T0, typename T1, typename T2
+ >
+struct list<
+ T0, T1, T2, na, na, na, na, na, na, na, na, na, na, na, na, na, na
+ , na, na, na
+ >
+ : list3< T0,T1,T2 >
+{
+ typedef typename list3< T0,T1,T2 >::type type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3
+ >
+struct list<
+ T0, T1, T2, T3, na, na, na, na, na, na, na, na, na, na, na, na, na
+ , na, na, na
+ >
+ : list4< T0,T1,T2,T3 >
+{
+ typedef typename list4< T0,T1,T2,T3 >::type type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ >
+struct list<
+ T0, T1, T2, T3, T4, na, na, na, na, na, na, na, na, na, na, na, na
+ , na, na, na
+ >
+ : list5< T0,T1,T2,T3,T4 >
+{
+ typedef typename list5< T0,T1,T2,T3,T4 >::type type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5
+ >
+struct list<
+ T0, T1, T2, T3, T4, T5, na, na, na, na, na, na, na, na, na, na, na
+ , na, na, na
+ >
+ : list6< T0,T1,T2,T3,T4,T5 >
+{
+ typedef typename list6< T0,T1,T2,T3,T4,T5 >::type type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6
+ >
+struct list<
+ T0, T1, T2, T3, T4, T5, T6, na, na, na, na, na, na, na, na, na, na
+ , na, na, na
+ >
+ : list7< T0,T1,T2,T3,T4,T5,T6 >
+{
+ typedef typename list7< T0,T1,T2,T3,T4,T5,T6 >::type type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7
+ >
+struct list<
+ T0, T1, T2, T3, T4, T5, T6, T7, na, na, na, na, na, na, na, na, na
+ , na, na, na
+ >
+ : list8< T0,T1,T2,T3,T4,T5,T6,T7 >
+{
+ typedef typename list8< T0,T1,T2,T3,T4,T5,T6,T7 >::type type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7, typename T8
+ >
+struct list<
+ T0, T1, T2, T3, T4, T5, T6, T7, T8, na, na, na, na, na, na, na, na
+ , na, na, na
+ >
+ : list9< T0,T1,T2,T3,T4,T5,T6,T7,T8 >
+{
+ typedef typename list9< T0,T1,T2,T3,T4,T5,T6,T7,T8 >::type type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7, typename T8, typename T9
+ >
+struct list<
+ T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, na, na, na, na, na, na, na
+ , na, na, na
+ >
+ : list10< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9 >
+{
+ typedef typename list10< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9 >::type type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7, typename T8, typename T9
+ , typename T10
+ >
+struct list<
+ T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, na, na, na, na, na, na
+ , na, na, na
+ >
+ : list11< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10 >
+{
+ typedef typename list11< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10 >::type type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7, typename T8, typename T9
+ , typename T10, typename T11
+ >
+struct list<
+ T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, na, na, na, na
+ , na, na, na, na
+ >
+ : list12< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11 >
+{
+ typedef typename list12< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11 >::type type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7, typename T8, typename T9
+ , typename T10, typename T11, typename T12
+ >
+struct list<
+ T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, na, na, na
+ , na, na, na, na
+ >
+ : list13< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12 >
+{
+ typedef typename list13< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12 >::type type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7, typename T8, typename T9
+ , typename T10, typename T11, typename T12, typename T13
+ >
+struct list<
+ T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, na, na
+ , na, na, na, na
+ >
+ : list14< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13 >
+{
+ typedef typename list14< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13 >::type type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7, typename T8, typename T9
+ , typename T10, typename T11, typename T12, typename T13, typename T14
+ >
+struct list<
+ T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, na
+ , na, na, na, na
+ >
+ : list15<
+ T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14
+ >
+{
+ typedef typename list15< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14 >::type type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7, typename T8, typename T9
+ , typename T10, typename T11, typename T12, typename T13, typename T14
+ , typename T15
+ >
+struct list<
+ T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14
+ , T15, na, na, na, na
+ >
+ : list16<
+ T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14
+ , T15
+ >
+{
+ typedef typename list16< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15 >::type type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7, typename T8, typename T9
+ , typename T10, typename T11, typename T12, typename T13, typename T14
+ , typename T15, typename T16
+ >
+struct list<
+ T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14
+ , T15, T16, na, na, na
+ >
+ : list17<
+ T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14
+ , T15, T16
+ >
+{
+ typedef typename list17< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16 >::type type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7, typename T8, typename T9
+ , typename T10, typename T11, typename T12, typename T13, typename T14
+ , typename T15, typename T16, typename T17
+ >
+struct list<
+ T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14
+ , T15, T16, T17, na, na
+ >
+ : list18<
+ T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14
+ , T15, T16, T17
+ >
+{
+ typedef typename list18< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17 >::type type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7, typename T8, typename T9
+ , typename T10, typename T11, typename T12, typename T13, typename T14
+ , typename T15, typename T16, typename T17, typename T18
+ >
+struct list<
+ T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14
+ , T15, T16, T17, T18, na
+ >
+ : list19<
+ T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14
+ , T15, T16, T17, T18
+ >
+{
+ typedef typename list19< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18 >::type type;
+};
+
+/// primary template (not a specialization!)
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7, typename T8, typename T9
+ , typename T10, typename T11, typename T12, typename T13, typename T14
+ , typename T15, typename T16, typename T17, typename T18, typename T19
+ >
+struct list
+ : list20<
+ T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14
+ , T15, T16, T17, T18, T19
+ >
+{
+ typedef typename list20< T0,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19 >::type type;
+};
+
+}}
diff --git a/third_party/boost/boost/mpl/aux_/preprocessed/gcc/or.hpp b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/or.hpp
new file mode 100644
index 0000000..3a4e9aa
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/or.hpp
@@ -0,0 +1,69 @@
+
+// Copyright Aleksey Gurtovoy 2000-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)
+//
+
+// Preprocessed version of "boost/mpl/or.hpp" header
+// -- DO NOT modify by hand!
+
+namespace boost { namespace mpl {
+
+namespace aux {
+
+template< bool C_, typename T1, typename T2, typename T3, typename T4 >
+struct or_impl
+ : true_
+{
+};
+
+template< typename T1, typename T2, typename T3, typename T4 >
+struct or_impl< false,T1,T2,T3,T4 >
+ : or_impl<
+ BOOST_MPL_AUX_NESTED_TYPE_WKND(T1)::value
+ , T2, T3, T4
+ , false_
+ >
+{
+};
+
+template<>
+struct or_impl<
+ false
+ , false_, false_, false_, false_
+ >
+ : false_
+{
+};
+
+} // namespace aux
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(T1)
+ , typename BOOST_MPL_AUX_NA_PARAM(T2)
+ , typename T3 = false_, typename T4 = false_, typename T5 = false_
+ >
+struct or_
+
+ : aux::or_impl<
+ BOOST_MPL_AUX_NESTED_TYPE_WKND(T1)::value
+ , T2, T3, T4, T5
+ >
+
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(
+ 5
+ , or_
+ , ( T1, T2, T3, T4, T5)
+ )
+};
+
+BOOST_MPL_AUX_NA_SPEC2(
+ 2
+ , 5
+ , or_
+ )
+
+}}
diff --git a/third_party/boost/boost/mpl/aux_/preprocessed/gcc/placeholders.hpp b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/placeholders.hpp
new file mode 100644
index 0000000..282a36a
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/placeholders.hpp
@@ -0,0 +1,105 @@
+
+// Copyright Aleksey Gurtovoy 2001-2004
+// Copyright Peter Dimov 2001-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)
+//
+
+// Preprocessed version of "boost/mpl/placeholders.hpp" header
+// -- DO NOT modify by hand!
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+typedef arg< -1 > _;
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+namespace boost { namespace mpl {
+
+BOOST_MPL_AUX_ARG_ADL_BARRIER_DECL(_)
+
+namespace placeholders {
+using BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE::_;
+}
+
+}}
+
+/// agurt, 17/mar/02: one more placeholder for the last 'apply#'
+/// specialization
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+typedef arg<1> _1;
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+namespace boost { namespace mpl {
+
+BOOST_MPL_AUX_ARG_ADL_BARRIER_DECL(_1)
+
+namespace placeholders {
+using BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE::_1;
+}
+
+}}
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+typedef arg<2> _2;
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+namespace boost { namespace mpl {
+
+BOOST_MPL_AUX_ARG_ADL_BARRIER_DECL(_2)
+
+namespace placeholders {
+using BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE::_2;
+}
+
+}}
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+typedef arg<3> _3;
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+namespace boost { namespace mpl {
+
+BOOST_MPL_AUX_ARG_ADL_BARRIER_DECL(_3)
+
+namespace placeholders {
+using BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE::_3;
+}
+
+}}
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+typedef arg<4> _4;
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+namespace boost { namespace mpl {
+
+BOOST_MPL_AUX_ARG_ADL_BARRIER_DECL(_4)
+
+namespace placeholders {
+using BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE::_4;
+}
+
+}}
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+typedef arg<5> _5;
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+namespace boost { namespace mpl {
+
+BOOST_MPL_AUX_ARG_ADL_BARRIER_DECL(_5)
+
+namespace placeholders {
+using BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE::_5;
+}
+
+}}
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+typedef arg<6> _6;
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+namespace boost { namespace mpl {
+
+BOOST_MPL_AUX_ARG_ADL_BARRIER_DECL(_6)
+
+namespace placeholders {
+using BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE::_6;
+}
+
+}}
diff --git a/third_party/boost/boost/mpl/aux_/preprocessed/gcc/quote.hpp b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/quote.hpp
new file mode 100644
index 0000000..c0c119d
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/quote.hpp
@@ -0,0 +1,122 @@
+
+// Copyright Aleksey Gurtovoy 2000-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)
+//
+
+// Preprocessed version of "boost/mpl/quote.hpp" header
+// -- DO NOT modify by hand!
+
+namespace boost { namespace mpl {
+
+template< typename T, bool has_type_ >
+struct quote_impl
+{
+ typedef typename T::type type;
+};
+
+template< typename T >
+struct quote_impl< T,false >
+{
+ typedef T type;
+};
+
+template<
+ template< typename P1 > class F
+ , typename Tag = void_
+ >
+struct quote1
+{
+ template< typename U1 > struct apply
+
+ : quote_impl<
+ F<U1>
+ , aux::has_type< F<U1> >::value
+ >
+
+ {
+ };
+};
+
+template<
+ template< typename P1, typename P2 > class F
+ , typename Tag = void_
+ >
+struct quote2
+{
+ template< typename U1, typename U2 > struct apply
+
+ : quote_impl<
+ F< U1,U2 >
+ , aux::has_type< F< U1,U2 > >::value
+ >
+
+ {
+ };
+};
+
+template<
+ template< typename P1, typename P2, typename P3 > class F
+ , typename Tag = void_
+ >
+struct quote3
+{
+ template< typename U1, typename U2, typename U3 > struct apply
+
+ : quote_impl<
+ F< U1,U2,U3 >
+ , aux::has_type< F< U1,U2,U3 > >::value
+ >
+
+ {
+ };
+};
+
+template<
+ template< typename P1, typename P2, typename P3, typename P4 > class F
+ , typename Tag = void_
+ >
+struct quote4
+{
+ template<
+ typename U1, typename U2, typename U3, typename U4
+ >
+ struct apply
+
+ : quote_impl<
+ F< U1,U2,U3,U4 >
+ , aux::has_type< F< U1,U2,U3,U4 > >::value
+ >
+
+ {
+ };
+};
+
+template<
+ template<
+ typename P1, typename P2, typename P3, typename P4
+ , typename P5
+ >
+ class F
+ , typename Tag = void_
+ >
+struct quote5
+{
+ template<
+ typename U1, typename U2, typename U3, typename U4
+ , typename U5
+ >
+ struct apply
+
+ : quote_impl<
+ F< U1,U2,U3,U4,U5 >
+ , aux::has_type< F< U1,U2,U3,U4,U5 > >::value
+ >
+
+ {
+ };
+};
+
+}}
diff --git a/third_party/boost/boost/mpl/aux_/preprocessed/gcc/reverse_fold_impl.hpp b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/reverse_fold_impl.hpp
new file mode 100644
index 0000000..3d43b7a
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/reverse_fold_impl.hpp
@@ -0,0 +1,231 @@
+
+// Copyright Aleksey Gurtovoy 2000-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)
+//
+
+// Preprocessed version of "boost/mpl/aux_/reverse_fold_impl.hpp" header
+// -- DO NOT modify by hand!
+
+namespace boost { namespace mpl { namespace aux {
+
+/// forward declaration
+
+template<
+ long N
+ , typename First
+ , typename Last
+ , typename State
+ , typename BackwardOp
+ , typename ForwardOp
+ >
+struct reverse_fold_impl;
+
+template<
+ typename First
+ , typename Last
+ , typename State
+ , typename BackwardOp
+ , typename ForwardOp
+ >
+struct reverse_fold_impl< 0,First,Last,State,BackwardOp,ForwardOp >
+{
+ typedef First iter0;
+ typedef State fwd_state0;
+ typedef fwd_state0 bkwd_state0;
+ typedef bkwd_state0 state;
+ typedef iter0 iterator;
+};
+
+template<
+ typename First
+ , typename Last
+ , typename State
+ , typename BackwardOp
+ , typename ForwardOp
+ >
+struct reverse_fold_impl< 1,First,Last,State,BackwardOp,ForwardOp >
+{
+ typedef First iter0;
+ typedef State fwd_state0;
+ typedef typename apply2< ForwardOp, fwd_state0, typename deref<iter0>::type >::type fwd_state1;
+ typedef typename mpl::next<iter0>::type iter1;
+
+
+ typedef fwd_state1 bkwd_state1;
+ typedef typename apply2< BackwardOp, bkwd_state1, typename deref<iter0>::type >::type bkwd_state0;
+ typedef bkwd_state0 state;
+ typedef iter1 iterator;
+};
+
+template<
+ typename First
+ , typename Last
+ , typename State
+ , typename BackwardOp
+ , typename ForwardOp
+ >
+struct reverse_fold_impl< 2,First,Last,State,BackwardOp,ForwardOp >
+{
+ typedef First iter0;
+ typedef State fwd_state0;
+ typedef typename apply2< ForwardOp, fwd_state0, typename deref<iter0>::type >::type fwd_state1;
+ typedef typename mpl::next<iter0>::type iter1;
+ typedef typename apply2< ForwardOp, fwd_state1, typename deref<iter1>::type >::type fwd_state2;
+ typedef typename mpl::next<iter1>::type iter2;
+
+
+ typedef fwd_state2 bkwd_state2;
+ typedef typename apply2< BackwardOp, bkwd_state2, typename deref<iter1>::type >::type bkwd_state1;
+ typedef typename apply2< BackwardOp, bkwd_state1, typename deref<iter0>::type >::type bkwd_state0;
+
+
+ typedef bkwd_state0 state;
+ typedef iter2 iterator;
+};
+
+template<
+ typename First
+ , typename Last
+ , typename State
+ , typename BackwardOp
+ , typename ForwardOp
+ >
+struct reverse_fold_impl< 3,First,Last,State,BackwardOp,ForwardOp >
+{
+ typedef First iter0;
+ typedef State fwd_state0;
+ typedef typename apply2< ForwardOp, fwd_state0, typename deref<iter0>::type >::type fwd_state1;
+ typedef typename mpl::next<iter0>::type iter1;
+ typedef typename apply2< ForwardOp, fwd_state1, typename deref<iter1>::type >::type fwd_state2;
+ typedef typename mpl::next<iter1>::type iter2;
+ typedef typename apply2< ForwardOp, fwd_state2, typename deref<iter2>::type >::type fwd_state3;
+ typedef typename mpl::next<iter2>::type iter3;
+
+
+ typedef fwd_state3 bkwd_state3;
+ typedef typename apply2< BackwardOp, bkwd_state3, typename deref<iter2>::type >::type bkwd_state2;
+ typedef typename apply2< BackwardOp, bkwd_state2, typename deref<iter1>::type >::type bkwd_state1;
+ typedef typename apply2< BackwardOp, bkwd_state1, typename deref<iter0>::type >::type bkwd_state0;
+
+
+ typedef bkwd_state0 state;
+ typedef iter3 iterator;
+};
+
+template<
+ typename First
+ , typename Last
+ , typename State
+ , typename BackwardOp
+ , typename ForwardOp
+ >
+struct reverse_fold_impl< 4,First,Last,State,BackwardOp,ForwardOp >
+{
+ typedef First iter0;
+ typedef State fwd_state0;
+ typedef typename apply2< ForwardOp, fwd_state0, typename deref<iter0>::type >::type fwd_state1;
+ typedef typename mpl::next<iter0>::type iter1;
+ typedef typename apply2< ForwardOp, fwd_state1, typename deref<iter1>::type >::type fwd_state2;
+ typedef typename mpl::next<iter1>::type iter2;
+ typedef typename apply2< ForwardOp, fwd_state2, typename deref<iter2>::type >::type fwd_state3;
+ typedef typename mpl::next<iter2>::type iter3;
+ typedef typename apply2< ForwardOp, fwd_state3, typename deref<iter3>::type >::type fwd_state4;
+ typedef typename mpl::next<iter3>::type iter4;
+
+
+ typedef fwd_state4 bkwd_state4;
+ typedef typename apply2< BackwardOp, bkwd_state4, typename deref<iter3>::type >::type bkwd_state3;
+ typedef typename apply2< BackwardOp, bkwd_state3, typename deref<iter2>::type >::type bkwd_state2;
+ typedef typename apply2< BackwardOp, bkwd_state2, typename deref<iter1>::type >::type bkwd_state1;
+ typedef typename apply2< BackwardOp, bkwd_state1, typename deref<iter0>::type >::type bkwd_state0;
+
+
+ typedef bkwd_state0 state;
+ typedef iter4 iterator;
+};
+
+template<
+ long N
+ , typename First
+ , typename Last
+ , typename State
+ , typename BackwardOp
+ , typename ForwardOp
+ >
+struct reverse_fold_impl
+{
+ typedef First iter0;
+ typedef State fwd_state0;
+ typedef typename apply2< ForwardOp, fwd_state0, typename deref<iter0>::type >::type fwd_state1;
+ typedef typename mpl::next<iter0>::type iter1;
+ typedef typename apply2< ForwardOp, fwd_state1, typename deref<iter1>::type >::type fwd_state2;
+ typedef typename mpl::next<iter1>::type iter2;
+ typedef typename apply2< ForwardOp, fwd_state2, typename deref<iter2>::type >::type fwd_state3;
+ typedef typename mpl::next<iter2>::type iter3;
+ typedef typename apply2< ForwardOp, fwd_state3, typename deref<iter3>::type >::type fwd_state4;
+ typedef typename mpl::next<iter3>::type iter4;
+
+
+ typedef reverse_fold_impl<
+ ( (N - 4) < 0 ? 0 : N - 4 )
+ , iter4
+ , Last
+ , fwd_state4
+ , BackwardOp
+ , ForwardOp
+ > nested_chunk;
+
+ typedef typename nested_chunk::state bkwd_state4;
+ typedef typename apply2< BackwardOp, bkwd_state4, typename deref<iter3>::type >::type bkwd_state3;
+ typedef typename apply2< BackwardOp, bkwd_state3, typename deref<iter2>::type >::type bkwd_state2;
+ typedef typename apply2< BackwardOp, bkwd_state2, typename deref<iter1>::type >::type bkwd_state1;
+ typedef typename apply2< BackwardOp, bkwd_state1, typename deref<iter0>::type >::type bkwd_state0;
+
+
+ typedef bkwd_state0 state;
+ typedef typename nested_chunk::iterator iterator;
+};
+
+template<
+ typename First
+ , typename Last
+ , typename State
+ , typename BackwardOp
+ , typename ForwardOp
+ >
+struct reverse_fold_impl< -1,First,Last,State,BackwardOp,ForwardOp >
+{
+ typedef reverse_fold_impl<
+ -1
+ , typename mpl::next<First>::type
+ , Last
+ , typename apply2<ForwardOp,State, typename deref<First>::type>::type
+ , BackwardOp
+ , ForwardOp
+ > nested_step;
+
+ typedef typename apply2<
+ BackwardOp
+ , typename nested_step::state
+ , typename deref<First>::type
+ >::type state;
+
+ typedef typename nested_step::iterator iterator;
+};
+
+template<
+ typename Last
+ , typename State
+ , typename BackwardOp
+ , typename ForwardOp
+ >
+struct reverse_fold_impl< -1,Last,Last,State,BackwardOp,ForwardOp >
+{
+ typedef State state;
+ typedef Last iterator;
+};
+
+}}}
diff --git a/third_party/boost/boost/mpl/aux_/preprocessed/gcc/template_arity.hpp b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/template_arity.hpp
new file mode 100644
index 0000000..28c8a90
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/preprocessed/gcc/template_arity.hpp
@@ -0,0 +1,97 @@
+
+// Copyright Aleksey Gurtovoy 2001-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)
+//
+
+// *Preprocessed* version of the main "template_arity.hpp" header
+// -- DO NOT modify by hand!
+
+namespace boost { namespace mpl { namespace aux {
+template< int N > struct arity_tag
+{
+ typedef char (&type)[N + 1];
+};
+
+template<
+ int C1, int C2, int C3, int C4, int C5, int C6
+ >
+struct max_arity
+{
+ BOOST_STATIC_CONSTANT(int, value =
+ ( C6 > 0 ? C6 : ( C5 > 0 ? C5 : ( C4 > 0 ? C4 : ( C3 > 0 ? C3 : ( C2 > 0 ? C2 : ( C1 > 0 ? C1 : -1 ) ) ) ) ) )
+ );
+};
+
+arity_tag<0>::type arity_helper(...);
+
+template<
+ template< typename P1 > class F
+ , typename T1
+ >
+typename arity_tag<1>::type
+arity_helper(type_wrapper< F<T1> >, arity_tag<1>);
+
+template<
+ template< typename P1, typename P2 > class F
+ , typename T1, typename T2
+ >
+typename arity_tag<2>::type
+arity_helper(type_wrapper< F< T1,T2 > >, arity_tag<2>);
+
+template<
+ template< typename P1, typename P2, typename P3 > class F
+ , typename T1, typename T2, typename T3
+ >
+typename arity_tag<3>::type
+arity_helper(type_wrapper< F< T1,T2,T3 > >, arity_tag<3>);
+
+template<
+ template< typename P1, typename P2, typename P3, typename P4 > class F
+ , typename T1, typename T2, typename T3, typename T4
+ >
+typename arity_tag<4>::type
+arity_helper(type_wrapper< F< T1,T2,T3,T4 > >, arity_tag<4>);
+
+template<
+ template<
+ typename P1, typename P2, typename P3, typename P4
+ , typename P5
+ >
+ class F
+ , typename T1, typename T2, typename T3, typename T4, typename T5
+ >
+typename arity_tag<5>::type
+arity_helper(type_wrapper< F< T1,T2,T3,T4,T5 > >, arity_tag<5>);
+
+template<
+ template<
+ typename P1, typename P2, typename P3, typename P4
+ , typename P5, typename P6
+ >
+ class F
+ , typename T1, typename T2, typename T3, typename T4, typename T5
+ , typename T6
+ >
+typename arity_tag<6>::type
+arity_helper(type_wrapper< F< T1,T2,T3,T4,T5,T6 > >, arity_tag<6>);
+template< typename F, int N >
+struct template_arity_impl
+{
+ BOOST_STATIC_CONSTANT(int, value =
+ sizeof(::boost::mpl::aux::arity_helper(type_wrapper<F>(), arity_tag<N>())) - 1
+ );
+};
+
+template< typename F >
+struct template_arity
+{
+ BOOST_STATIC_CONSTANT(int, value = (
+ max_arity< template_arity_impl< F,1 >::value, template_arity_impl< F,2 >::value, template_arity_impl< F,3 >::value, template_arity_impl< F,4 >::value, template_arity_impl< F,5 >::value, template_arity_impl< F,6 >::value >::value
+ ));
+ typedef mpl::int_<value> type;
+};
+
+}}}
diff --git a/third_party/boost/boost/mpl/aux_/preprocessor/def_params_tail.hpp b/third_party/boost/boost/mpl/aux_/preprocessor/def_params_tail.hpp
new file mode 100644
index 0000000..7b0188d
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/preprocessor/def_params_tail.hpp
@@ -0,0 +1,105 @@
+
+#ifndef BOOST_MPL_AUX_PREPROCESSOR_DEF_PARAMS_TAIL_HPP_INCLUDED
+#define BOOST_MPL_AUX_PREPROCESSOR_DEF_PARAMS_TAIL_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/limits/arity.hpp>
+#include <boost/mpl/aux_/config/dtp.hpp>
+#include <boost/mpl/aux_/config/preprocessor.hpp>
+
+#include <boost/preprocessor/comma_if.hpp>
+#include <boost/preprocessor/logical/and.hpp>
+#include <boost/preprocessor/identity.hpp>
+#include <boost/preprocessor/empty.hpp>
+
+// BOOST_MPL_PP_DEF_PARAMS_TAIL(1,T,value): , T1 = value, .., Tn = value
+// BOOST_MPL_PP_DEF_PARAMS_TAIL(2,T,value): , T2 = value, .., Tn = value
+// BOOST_MPL_PP_DEF_PARAMS_TAIL(n,T,value): <nothing>
+
+#if !defined(BOOST_MPL_CFG_NO_OWN_PP_PRIMITIVES)
+
+# include <boost/mpl/aux_/preprocessor/filter_params.hpp>
+# include <boost/mpl/aux_/preprocessor/sub.hpp>
+
+# define BOOST_MPL_PP_DEF_PARAMS_TAIL_IMPL(i, param, value_func) \
+ BOOST_MPL_PP_DEF_PARAMS_TAIL_DELAY_1( \
+ i \
+ , BOOST_MPL_PP_SUB(BOOST_MPL_LIMIT_METAFUNCTION_ARITY,i) \
+ , param \
+ , value_func \
+ ) \
+ /**/
+
+# define BOOST_MPL_PP_DEF_PARAMS_TAIL_DELAY_1(i, n, param, value_func) \
+ BOOST_MPL_PP_DEF_PARAMS_TAIL_DELAY_2(i,n,param,value_func) \
+ /**/
+
+# define BOOST_MPL_PP_DEF_PARAMS_TAIL_DELAY_2(i, n, param, value_func) \
+ BOOST_PP_COMMA_IF(BOOST_PP_AND(i,n)) \
+ BOOST_MPL_PP_DEF_PARAMS_TAIL_##i(n,param,value_func) \
+ /**/
+
+# define BOOST_MPL_PP_DEF_PARAMS_TAIL_0(i,p,v) BOOST_MPL_PP_FILTER_PARAMS_##i(p##1 v(),p##2 v(),p##3 v(),p##4 v(),p##5 v(),p##6 v(),p##7 v(),p##8 v(),p##9 v())
+# define BOOST_MPL_PP_DEF_PARAMS_TAIL_1(i,p,v) BOOST_MPL_PP_FILTER_PARAMS_##i(p##2 v(),p##3 v(),p##4 v(),p##5 v(),p##6 v(),p##7 v(),p##8 v(),p##9 v(),p1)
+# define BOOST_MPL_PP_DEF_PARAMS_TAIL_2(i,p,v) BOOST_MPL_PP_FILTER_PARAMS_##i(p##3 v(),p##4 v(),p##5 v(),p##6 v(),p##7 v(),p##8 v(),p##9 v(),p1,p2)
+# define BOOST_MPL_PP_DEF_PARAMS_TAIL_3(i,p,v) BOOST_MPL_PP_FILTER_PARAMS_##i(p##4 v(),p##5 v(),p##6 v(),p##7 v(),p##8 v(),p##9 v(),p1,p2,p3)
+# define BOOST_MPL_PP_DEF_PARAMS_TAIL_4(i,p,v) BOOST_MPL_PP_FILTER_PARAMS_##i(p##5 v(),p##6 v(),p##7 v(),p##8 v(),p##9 v(),p1,p2,p3,p4)
+# define BOOST_MPL_PP_DEF_PARAMS_TAIL_5(i,p,v) BOOST_MPL_PP_FILTER_PARAMS_##i(p##6 v(),p##7 v(),p##8 v(),p##9 v(),p1,p2,p3,p4,p5)
+# define BOOST_MPL_PP_DEF_PARAMS_TAIL_6(i,p,v) BOOST_MPL_PP_FILTER_PARAMS_##i(p##7 v(),p##8 v(),p##9 v(),p1,p2,p3,p4,p5,p6)
+# define BOOST_MPL_PP_DEF_PARAMS_TAIL_7(i,p,v) BOOST_MPL_PP_FILTER_PARAMS_##i(p##8 v(),p##9 v(),p1,p2,p3,p4,p5,p6,p7)
+# define BOOST_MPL_PP_DEF_PARAMS_TAIL_8(i,p,v) BOOST_MPL_PP_FILTER_PARAMS_##i(p##9 v(),p1,p2,p3,p4,p5,p6,p7,p8)
+# define BOOST_MPL_PP_DEF_PARAMS_TAIL_9(i,p,v) BOOST_MPL_PP_FILTER_PARAMS_##i(p1,p2,p3,p4,p5,p6,p7,p8,p9)
+
+#else
+
+# include <boost/preprocessor/arithmetic/add.hpp>
+# include <boost/preprocessor/arithmetic/sub.hpp>
+# include <boost/preprocessor/inc.hpp>
+# include <boost/preprocessor/tuple/elem.hpp>
+# include <boost/preprocessor/repeat.hpp>
+# include <boost/preprocessor/cat.hpp>
+
+# define BOOST_MPL_PP_AUX_TAIL_PARAM_FUNC(unused, i, op) \
+ , BOOST_PP_CAT( \
+ BOOST_PP_TUPLE_ELEM(3, 1, op) \
+ , BOOST_PP_ADD_D(1, i, BOOST_PP_INC(BOOST_PP_TUPLE_ELEM(3, 0, op))) \
+ ) BOOST_PP_TUPLE_ELEM(3, 2, op)() \
+ /**/
+
+# define BOOST_MPL_PP_DEF_PARAMS_TAIL_IMPL(i, param, value_func) \
+ BOOST_PP_REPEAT( \
+ BOOST_PP_SUB_D(1, BOOST_MPL_LIMIT_METAFUNCTION_ARITY, i) \
+ , BOOST_MPL_PP_AUX_TAIL_PARAM_FUNC \
+ , (i, param, value_func) \
+ ) \
+ /**/
+
+
+#endif // BOOST_MPL_CFG_NO_OWN_PP_PRIMITIVES
+
+#define BOOST_MPL_PP_DEF_PARAMS_TAIL(i, param, value) \
+ BOOST_MPL_PP_DEF_PARAMS_TAIL_IMPL(i, param, BOOST_PP_IDENTITY(=value)) \
+ /**/
+
+#if !defined(BOOST_MPL_CFG_NO_DEFAULT_PARAMETERS_IN_NESTED_TEMPLATES)
+# define BOOST_MPL_PP_NESTED_DEF_PARAMS_TAIL(i, param, value) \
+ BOOST_MPL_PP_DEF_PARAMS_TAIL_IMPL(i, param, BOOST_PP_IDENTITY(=value)) \
+ /**/
+#else
+# define BOOST_MPL_PP_NESTED_DEF_PARAMS_TAIL(i, param, value) \
+ BOOST_MPL_PP_DEF_PARAMS_TAIL_IMPL(i, param, BOOST_PP_EMPTY) \
+ /**/
+#endif
+
+#endif // BOOST_MPL_AUX_PREPROCESSOR_DEF_PARAMS_TAIL_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/preprocessor/default_params.hpp b/third_party/boost/boost/mpl/aux_/preprocessor/default_params.hpp
new file mode 100644
index 0000000..834d357
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/preprocessor/default_params.hpp
@@ -0,0 +1,67 @@
+
+#ifndef BOOST_MPL_AUX_PREPROCESSOR_DEFAULT_PARAMS_HPP_INCLUDED
+#define BOOST_MPL_AUX_PREPROCESSOR_DEFAULT_PARAMS_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 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/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/preprocessor.hpp>
+
+// BOOST_MPL_PP_DEFAULT_PARAMS(0,T,int): <nothing>
+// BOOST_MPL_PP_DEFAULT_PARAMS(1,T,int): T1 = int
+// BOOST_MPL_PP_DEFAULT_PARAMS(2,T,int): T1 = int, T2 = int
+// BOOST_MPL_PP_DEFAULT_PARAMS(n,T,int): T1 = int, T2 = int, .., Tn = int
+
+#if !defined(BOOST_MPL_CFG_NO_OWN_PP_PRIMITIVES)
+
+# include <boost/preprocessor/cat.hpp>
+
+# define BOOST_MPL_PP_DEFAULT_PARAMS(n,p,v) \
+ BOOST_PP_CAT(BOOST_MPL_PP_DEFAULT_PARAMS_,n)(p,v) \
+ /**/
+
+# define BOOST_MPL_PP_DEFAULT_PARAMS_0(p,v)
+# define BOOST_MPL_PP_DEFAULT_PARAMS_1(p,v) p##1=v
+# define BOOST_MPL_PP_DEFAULT_PARAMS_2(p,v) p##1=v,p##2=v
+# define BOOST_MPL_PP_DEFAULT_PARAMS_3(p,v) p##1=v,p##2=v,p##3=v
+# define BOOST_MPL_PP_DEFAULT_PARAMS_4(p,v) p##1=v,p##2=v,p##3=v,p##4=v
+# define BOOST_MPL_PP_DEFAULT_PARAMS_5(p,v) p##1=v,p##2=v,p##3=v,p##4=v,p##5=v
+# define BOOST_MPL_PP_DEFAULT_PARAMS_6(p,v) p##1=v,p##2=v,p##3=v,p##4=v,p##5=v,p##6=v
+# define BOOST_MPL_PP_DEFAULT_PARAMS_7(p,v) p##1=v,p##2=v,p##3=v,p##4=v,p##5=v,p##6=v,p##7=v
+# define BOOST_MPL_PP_DEFAULT_PARAMS_8(p,v) p##1=v,p##2=v,p##3=v,p##4=v,p##5=v,p##6=v,p##7=v,p##8=v
+# define BOOST_MPL_PP_DEFAULT_PARAMS_9(p,v) p##1=v,p##2=v,p##3=v,p##4=v,p##5=v,p##6=v,p##7=v,p##8=v,p##9=v
+
+#else
+
+# include <boost/preprocessor/tuple/elem.hpp>
+# include <boost/preprocessor/comma_if.hpp>
+# include <boost/preprocessor/repeat.hpp>
+# include <boost/preprocessor/inc.hpp>
+# include <boost/preprocessor/cat.hpp>
+
+# define BOOST_MPL_PP_AUX_DEFAULT_PARAM_FUNC(unused, i, pv) \
+ BOOST_PP_COMMA_IF(i) \
+ BOOST_PP_CAT( BOOST_PP_TUPLE_ELEM(2,0,pv), BOOST_PP_INC(i) ) \
+ = BOOST_PP_TUPLE_ELEM(2,1,pv) \
+ /**/
+
+# define BOOST_MPL_PP_DEFAULT_PARAMS(n, param, value) \
+ BOOST_PP_REPEAT( \
+ n \
+ , BOOST_MPL_PP_AUX_DEFAULT_PARAM_FUNC \
+ , (param,value) \
+ ) \
+ /**/
+
+#endif
+
+#endif // BOOST_MPL_AUX_PREPROCESSOR_DEFAULT_PARAMS_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/preprocessor/enum.hpp b/third_party/boost/boost/mpl/aux_/preprocessor/enum.hpp
new file mode 100644
index 0000000..b44f6e8
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/preprocessor/enum.hpp
@@ -0,0 +1,62 @@
+
+#ifndef BOOST_MPL_AUX_PREPROCESSOR_ENUM_HPP_INCLUDED
+#define BOOST_MPL_AUX_PREPROCESSOR_ENUM_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/preprocessor.hpp>
+
+// BOOST_MPL_PP_ENUM(0,int): <nothing>
+// BOOST_MPL_PP_ENUM(1,int): int
+// BOOST_MPL_PP_ENUM(2,int): int, int
+// BOOST_MPL_PP_ENUM(n,int): int, int, .., int
+
+#if !defined(BOOST_MPL_CFG_NO_OWN_PP_PRIMITIVES)
+
+# include <boost/preprocessor/cat.hpp>
+
+# define BOOST_MPL_PP_ENUM(n, param) \
+ BOOST_PP_CAT(BOOST_MPL_PP_ENUM_,n)(param) \
+ /**/
+
+# define BOOST_MPL_PP_ENUM_0(p)
+# define BOOST_MPL_PP_ENUM_1(p) p
+# define BOOST_MPL_PP_ENUM_2(p) p,p
+# define BOOST_MPL_PP_ENUM_3(p) p,p,p
+# define BOOST_MPL_PP_ENUM_4(p) p,p,p,p
+# define BOOST_MPL_PP_ENUM_5(p) p,p,p,p,p
+# define BOOST_MPL_PP_ENUM_6(p) p,p,p,p,p,p
+# define BOOST_MPL_PP_ENUM_7(p) p,p,p,p,p,p,p
+# define BOOST_MPL_PP_ENUM_8(p) p,p,p,p,p,p,p,p
+# define BOOST_MPL_PP_ENUM_9(p) p,p,p,p,p,p,p,p,p
+
+#else
+
+# include <boost/preprocessor/comma_if.hpp>
+# include <boost/preprocessor/repeat.hpp>
+
+# define BOOST_MPL_PP_AUX_ENUM_FUNC(unused, i, param) \
+ BOOST_PP_COMMA_IF(i) param \
+ /**/
+
+# define BOOST_MPL_PP_ENUM(n, param) \
+ BOOST_PP_REPEAT( \
+ n \
+ , BOOST_MPL_PP_AUX_ENUM_FUNC \
+ , param \
+ ) \
+ /**/
+
+#endif
+
+#endif // BOOST_MPL_AUX_PREPROCESSOR_ENUM_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/preprocessor/params.hpp b/third_party/boost/boost/mpl/aux_/preprocessor/params.hpp
new file mode 100644
index 0000000..2a5e2fe
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/preprocessor/params.hpp
@@ -0,0 +1,65 @@
+
+#ifndef BOOST_MPL_AUX_PREPROCESSOR_PARAMS_HPP_INCLUDED
+#define BOOST_MPL_AUX_PREPROCESSOR_PARAMS_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/preprocessor.hpp>
+
+// BOOST_MPL_PP_PARAMS(0,T): <nothing>
+// BOOST_MPL_PP_PARAMS(1,T): T1
+// BOOST_MPL_PP_PARAMS(2,T): T1, T2
+// BOOST_MPL_PP_PARAMS(n,T): T1, T2, .., Tn
+
+#if !defined(BOOST_MPL_CFG_NO_OWN_PP_PRIMITIVES)
+
+# include <boost/preprocessor/cat.hpp>
+
+# define BOOST_MPL_PP_PARAMS(n,p) \
+ BOOST_PP_CAT(BOOST_MPL_PP_PARAMS_,n)(p) \
+ /**/
+
+# define BOOST_MPL_PP_PARAMS_0(p)
+# define BOOST_MPL_PP_PARAMS_1(p) p##1
+# define BOOST_MPL_PP_PARAMS_2(p) p##1,p##2
+# define BOOST_MPL_PP_PARAMS_3(p) p##1,p##2,p##3
+# define BOOST_MPL_PP_PARAMS_4(p) p##1,p##2,p##3,p##4
+# define BOOST_MPL_PP_PARAMS_5(p) p##1,p##2,p##3,p##4,p##5
+# define BOOST_MPL_PP_PARAMS_6(p) p##1,p##2,p##3,p##4,p##5,p##6
+# define BOOST_MPL_PP_PARAMS_7(p) p##1,p##2,p##3,p##4,p##5,p##6,p##7
+# define BOOST_MPL_PP_PARAMS_8(p) p##1,p##2,p##3,p##4,p##5,p##6,p##7,p##8
+# define BOOST_MPL_PP_PARAMS_9(p) p##1,p##2,p##3,p##4,p##5,p##6,p##7,p##8,p##9
+
+#else
+
+# include <boost/preprocessor/comma_if.hpp>
+# include <boost/preprocessor/repeat.hpp>
+# include <boost/preprocessor/inc.hpp>
+# include <boost/preprocessor/cat.hpp>
+
+# define BOOST_MPL_PP_AUX_PARAM_FUNC(unused, i, param) \
+ BOOST_PP_COMMA_IF(i) \
+ BOOST_PP_CAT(param, BOOST_PP_INC(i)) \
+ /**/
+
+# define BOOST_MPL_PP_PARAMS(n, param) \
+ BOOST_PP_REPEAT( \
+ n \
+ , BOOST_MPL_PP_AUX_PARAM_FUNC \
+ , param \
+ ) \
+ /**/
+
+#endif
+
+#endif // BOOST_MPL_AUX_PREPROCESSOR_PARAMS_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/push_back_impl.hpp b/third_party/boost/boost/mpl/aux_/push_back_impl.hpp
new file mode 100644
index 0000000..cd9f7f2
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/push_back_impl.hpp
@@ -0,0 +1,70 @@
+
+#ifndef BOOST_MPL_AUX_PUSH_BACK_IMPL_HPP_INCLUDED
+#define BOOST_MPL_AUX_PUSH_BACK_IMPL_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2008
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/push_back_fwd.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/aux_/has_type.hpp>
+#include <boost/mpl/aux_/traits_lambda_spec.hpp>
+#include <boost/mpl/aux_/config/forwarding.hpp>
+#include <boost/mpl/aux_/config/static_constant.hpp>
+
+#include <boost/type_traits/is_same.hpp>
+
+namespace boost { namespace mpl {
+
+struct has_push_back_arg {};
+
+// agurt 05/feb/04: no default implementation; the stub definition is needed
+// to enable the default 'has_push_back' implementation below
+template< typename Tag >
+struct push_back_impl
+{
+ template< typename Sequence, typename T > struct apply
+ {
+ // should be instantiated only in the context of 'has_push_back_impl';
+ // if you've got an assert here, you are requesting a 'push_back'
+ // specialization that doesn't exist.
+ BOOST_MPL_ASSERT_MSG(
+ ( boost::is_same< T, has_push_back_arg >::value )
+ , REQUESTED_PUSH_BACK_SPECIALIZATION_FOR_SEQUENCE_DOES_NOT_EXIST
+ , ( Sequence )
+ );
+ };
+};
+
+template< typename Tag >
+struct has_push_back_impl
+{
+ template< typename Seq > struct apply
+#if !defined(BOOST_MPL_CFG_NO_NESTED_FORWARDING)
+ : aux::has_type< push_back< Seq, has_push_back_arg > >
+ {
+#else
+ {
+ typedef aux::has_type< push_back< Seq, has_push_back_arg > > type;
+ BOOST_STATIC_CONSTANT(bool, value =
+ (aux::has_type< push_back< Seq, has_push_back_arg > >::value)
+ );
+#endif
+ };
+};
+
+BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(2, push_back_impl)
+BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(1, has_push_back_impl)
+
+}}
+
+#endif // BOOST_MPL_AUX_PUSH_BACK_IMPL_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/push_front_impl.hpp b/third_party/boost/boost/mpl/aux_/push_front_impl.hpp
new file mode 100644
index 0000000..70159a1
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/push_front_impl.hpp
@@ -0,0 +1,71 @@
+
+#ifndef BOOST_MPL_AUX_PUSH_FRONT_IMPL_HPP_INCLUDED
+#define BOOST_MPL_AUX_PUSH_FRONT_IMPL_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2008
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/push_front_fwd.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/aux_/has_type.hpp>
+#include <boost/mpl/aux_/traits_lambda_spec.hpp>
+#include <boost/mpl/aux_/config/forwarding.hpp>
+#include <boost/mpl/aux_/config/static_constant.hpp>
+
+#include <boost/type_traits/is_same.hpp>
+
+namespace boost { namespace mpl {
+
+struct has_push_front_arg {};
+
+// agurt 05/feb/04: no default implementation; the stub definition is needed
+// to enable the default 'has_push_front' implementation below
+
+template< typename Tag >
+struct push_front_impl
+{
+ template< typename Sequence, typename T > struct apply
+ {
+ // should be instantiated only in the context of 'has_push_front_impl';
+ // if you've got an assert here, you are requesting a 'push_front'
+ // specialization that doesn't exist.
+ BOOST_MPL_ASSERT_MSG(
+ ( boost::is_same< T, has_push_front_arg >::value )
+ , REQUESTED_PUSH_FRONT_SPECIALIZATION_FOR_SEQUENCE_DOES_NOT_EXIST
+ , ( Sequence )
+ );
+ };
+};
+
+template< typename Tag >
+struct has_push_front_impl
+{
+ template< typename Seq > struct apply
+#if !defined(BOOST_MPL_CFG_NO_NESTED_FORWARDING)
+ : aux::has_type< push_front< Seq, has_push_front_arg > >
+ {
+#else
+ {
+ typedef aux::has_type< push_front< Seq, has_push_front_arg > > type;
+ BOOST_STATIC_CONSTANT(bool, value =
+ (aux::has_type< push_front< Seq, has_push_front_arg > >::value)
+ );
+#endif
+ };
+};
+
+BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(2, push_front_impl)
+BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(1, has_push_front_impl)
+
+}}
+
+#endif // BOOST_MPL_AUX_PUSH_FRONT_IMPL_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/reverse_fold_impl.hpp b/third_party/boost/boost/mpl/aux_/reverse_fold_impl.hpp
new file mode 100644
index 0000000..26ba383
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/reverse_fold_impl.hpp
@@ -0,0 +1,44 @@
+
+#ifndef BOOST_MPL_AUX_REVERSE_FOLD_IMPL_HPP_INCLUDED
+#define BOOST_MPL_AUX_REVERSE_FOLD_IMPL_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_PREPROCESSING_MODE)
+# include <boost/mpl/next_prior.hpp>
+# include <boost/mpl/deref.hpp>
+# include <boost/mpl/apply.hpp>
+# include <boost/mpl/aux_/config/ctps.hpp>
+# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
+ || defined(BOOST_MPL_CFG_NO_NONTYPE_TEMPLATE_PARTIAL_SPEC)
+# include <boost/mpl/if.hpp>
+# include <boost/type_traits/is_same.hpp>
+# endif
+#endif
+
+#include <boost/mpl/aux_/config/use_preprocessed.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE)
+
+# define BOOST_MPL_PREPROCESSED_HEADER reverse_fold_impl.hpp
+# include <boost/mpl/aux_/include_preprocessed.hpp>
+
+#else
+
+# define AUX778076_FOLD_IMPL_OP(iter) typename deref<iter>::type
+# define AUX778076_FOLD_IMPL_NAME_PREFIX reverse_fold
+# include <boost/mpl/aux_/reverse_fold_impl_body.hpp>
+
+#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#endif // BOOST_MPL_AUX_REVERSE_FOLD_IMPL_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/static_cast.hpp b/third_party/boost/boost/mpl/aux_/static_cast.hpp
new file mode 100644
index 0000000..d4dad17
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/static_cast.hpp
@@ -0,0 +1,27 @@
+
+#ifndef BOOST_MPL_AUX_STATIC_CAST_HPP_INCLUDED
+#define BOOST_MPL_AUX_STATIC_CAST_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x561)) \
+ || BOOST_WORKAROUND(__GNUC__, < 3) \
+ || BOOST_WORKAROUND(__MWERKS__, <= 0x3001)
+# define BOOST_MPL_AUX_STATIC_CAST(T, expr) (T)(expr)
+#else
+# define BOOST_MPL_AUX_STATIC_CAST(T, expr) static_cast<T>(expr)
+#endif
+
+#endif // BOOST_MPL_AUX_STATIC_CAST_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/template_arity.hpp b/third_party/boost/boost/mpl/aux_/template_arity.hpp
new file mode 100644
index 0000000..0edfba4
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/template_arity.hpp
@@ -0,0 +1,189 @@
+
+#if !defined(BOOST_PP_IS_ITERATING)
+
+///// header body
+
+#ifndef BOOST_MPL_AUX_TEMPLATE_ARITY_HPP_INCLUDED
+#define BOOST_MPL_AUX_TEMPLATE_ARITY_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/ttp.hpp>
+#include <boost/mpl/aux_/config/lambda.hpp>
+
+#if !defined(BOOST_MPL_PREPROCESSING_MODE)
+# include <boost/mpl/aux_/template_arity_fwd.hpp>
+# include <boost/mpl/int.hpp>
+# if !defined(BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT)
+# if defined(BOOST_MPL_CFG_EXTENDED_TEMPLATE_PARAMETERS_MATCHING)
+# include <boost/mpl/aux_/type_wrapper.hpp>
+# endif
+# else
+# include <boost/mpl/aux_/has_rebind.hpp>
+# endif
+#endif
+
+#include <boost/mpl/aux_/config/static_constant.hpp>
+#include <boost/mpl/aux_/config/use_preprocessed.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE)
+
+# define BOOST_MPL_PREPROCESSED_HEADER template_arity.hpp
+# include <boost/mpl/aux_/include_preprocessed.hpp>
+
+#else
+
+# if !defined(BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT)
+# if defined(BOOST_MPL_CFG_EXTENDED_TEMPLATE_PARAMETERS_MATCHING)
+
+# include <boost/mpl/limits/arity.hpp>
+# include <boost/mpl/aux_/preprocessor/range.hpp>
+# include <boost/mpl/aux_/preprocessor/repeat.hpp>
+# include <boost/mpl/aux_/preprocessor/params.hpp>
+# include <boost/mpl/aux_/nttp_decl.hpp>
+
+# include <boost/preprocessor/seq/fold_left.hpp>
+# include <boost/preprocessor/comma_if.hpp>
+# include <boost/preprocessor/iterate.hpp>
+# include <boost/preprocessor/inc.hpp>
+# include <boost/preprocessor/cat.hpp>
+
+# define AUX778076_ARITY BOOST_PP_INC(BOOST_MPL_LIMIT_METAFUNCTION_ARITY)
+
+namespace boost { namespace mpl { namespace aux {
+
+template< BOOST_MPL_AUX_NTTP_DECL(int, N) > struct arity_tag
+{
+ typedef char (&type)[N + 1];
+};
+
+# define AUX778076_MAX_ARITY_OP(unused, state, i_) \
+ ( BOOST_PP_CAT(C,i_) > 0 ? BOOST_PP_CAT(C,i_) : state ) \
+/**/
+
+template<
+ BOOST_MPL_PP_PARAMS(AUX778076_ARITY, BOOST_MPL_AUX_NTTP_DECL(int, C))
+ >
+struct max_arity
+{
+ BOOST_STATIC_CONSTANT(int, value =
+ BOOST_PP_SEQ_FOLD_LEFT(
+ AUX778076_MAX_ARITY_OP
+ , -1
+ , BOOST_MPL_PP_RANGE(1, AUX778076_ARITY)
+ )
+ );
+};
+
+# undef AUX778076_MAX_ARITY_OP
+
+arity_tag<0>::type arity_helper(...);
+
+# define BOOST_PP_ITERATION_LIMITS (1, AUX778076_ARITY)
+# define BOOST_PP_FILENAME_1 <boost/mpl/aux_/template_arity.hpp>
+# include BOOST_PP_ITERATE()
+
+template< typename F, BOOST_MPL_AUX_NTTP_DECL(int, N) >
+struct template_arity_impl
+{
+ BOOST_STATIC_CONSTANT(int, value =
+ sizeof(::boost::mpl::aux::arity_helper(type_wrapper<F>(),arity_tag<N>())) - 1
+ );
+};
+
+# define AUX778076_TEMPLATE_ARITY_IMPL_INVOCATION(unused, i_, F) \
+ BOOST_PP_COMMA_IF(i_) template_arity_impl<F,BOOST_PP_INC(i_)>::value \
+/**/
+
+template< typename F >
+struct template_arity
+{
+ BOOST_STATIC_CONSTANT(int, value = (
+ max_arity< BOOST_MPL_PP_REPEAT(
+ AUX778076_ARITY
+ , AUX778076_TEMPLATE_ARITY_IMPL_INVOCATION
+ , F
+ ) >::value
+ ));
+
+ typedef mpl::int_<value> type;
+};
+
+# undef AUX778076_TEMPLATE_ARITY_IMPL_INVOCATION
+
+# undef AUX778076_ARITY
+
+}}}
+
+# endif // BOOST_MPL_CFG_EXTENDED_TEMPLATE_PARAMETERS_MATCHING
+# else // BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT
+
+# include <boost/mpl/aux_/config/eti.hpp>
+
+namespace boost { namespace mpl { namespace aux {
+
+template< bool >
+struct template_arity_impl
+{
+ template< typename F > struct result_
+ : mpl::int_<-1>
+ {
+ };
+};
+
+template<>
+struct template_arity_impl<true>
+{
+ template< typename F > struct result_
+ : F::arity
+ {
+ };
+};
+
+template< typename F >
+struct template_arity
+ : template_arity_impl< ::boost::mpl::aux::has_rebind<F>::value >
+ ::template result_<F>
+{
+};
+
+#if defined(BOOST_MPL_CFG_MSVC_ETI_BUG)
+template<>
+struct template_arity<int>
+ : mpl::int_<-1>
+{
+};
+#endif
+
+}}}
+
+# endif // BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT
+
+#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#endif // BOOST_MPL_AUX_TEMPLATE_ARITY_HPP_INCLUDED
+
+///// iteration
+
+#else
+#define i_ BOOST_PP_FRAME_ITERATION(1)
+
+template<
+ template< BOOST_MPL_PP_PARAMS(i_, typename P) > class F
+ , BOOST_MPL_PP_PARAMS(i_, typename T)
+ >
+typename arity_tag<i_>::type
+arity_helper(type_wrapper< F<BOOST_MPL_PP_PARAMS(i_, T)> >, arity_tag<i_>);
+
+#undef i_
+#endif // BOOST_PP_IS_ITERATING
diff --git a/third_party/boost/boost/mpl/aux_/template_arity_fwd.hpp b/third_party/boost/boost/mpl/aux_/template_arity_fwd.hpp
new file mode 100644
index 0000000..0db5808
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/template_arity_fwd.hpp
@@ -0,0 +1,23 @@
+
+#ifndef BOOST_MPL_AUX_TEMPLATE_ARITY_FWD_HPP_INCLUDED
+#define BOOST_MPL_AUX_TEMPLATE_ARITY_FWD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+namespace boost { namespace mpl { namespace aux {
+
+template< typename F > struct template_arity;
+
+}}}
+
+#endif // BOOST_MPL_AUX_TEMPLATE_ARITY_FWD_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/traits_lambda_spec.hpp b/third_party/boost/boost/mpl/aux_/traits_lambda_spec.hpp
new file mode 100644
index 0000000..8923c7e
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/traits_lambda_spec.hpp
@@ -0,0 +1,63 @@
+
+#ifndef BOOST_MPL_AUX_TRAITS_LAMBDA_SPEC_HPP_INCLUDED
+#define BOOST_MPL_AUX_TRAITS_LAMBDA_SPEC_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2008
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/sequence_tag_fwd.hpp>
+#include <boost/mpl/void.hpp>
+#include <boost/mpl/aux_/preprocessor/params.hpp>
+#include <boost/mpl/aux_/config/lambda.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT)
+
+# define BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC_IMPL(i, trait) /**/
+
+#elif !defined(BOOST_MPL_CFG_MSVC_ETI_BUG)
+
+# define BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC_IMPL(i, trait) \
+template<> struct trait<void_> \
+{ \
+ template< BOOST_MPL_PP_PARAMS(i, typename T) > struct apply \
+ { \
+ }; \
+}; \
+/**/
+
+#else
+
+# define BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC_IMPL(i, trait) \
+template<> struct trait<void_> \
+{ \
+ template< BOOST_MPL_PP_PARAMS(i, typename T) > struct apply \
+ { \
+ }; \
+}; \
+template<> struct trait<int> \
+{ \
+ template< BOOST_MPL_PP_PARAMS(i, typename T) > struct apply \
+ { \
+ typedef int type; \
+ }; \
+}; \
+/**/
+
+#endif // BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT
+
+
+#define BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC(i, trait) \
+ BOOST_MPL_ALGORITM_TRAITS_LAMBDA_SPEC_IMPL(i, trait) \
+ template<> struct trait<non_sequence_tag> {}; \
+/**/
+
+#endif // BOOST_MPL_AUX_TRAITS_LAMBDA_SPEC_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/type_wrapper.hpp b/third_party/boost/boost/mpl/aux_/type_wrapper.hpp
new file mode 100644
index 0000000..6d950c5
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/type_wrapper.hpp
@@ -0,0 +1,47 @@
+
+#ifndef BOOST_MPL_AUX_TYPE_WRAPPER_HPP_INCLUDED
+#define BOOST_MPL_AUX_TYPE_WRAPPER_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+// Copyright Peter Dimov 2000-2003
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/ctps.hpp>
+
+namespace boost { namespace mpl { namespace aux {
+
+template< typename T > struct type_wrapper
+{
+ typedef T type;
+};
+
+#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+// agurt 08/may/03: a complicated way to extract the wrapped type; need it
+// mostly for the sake of GCC (3.2.x), which ICEs if you try to extract the
+// nested 'type' from 'type_wrapper<T>' when the latter was the result of a
+// 'typeof' expression
+template< typename T > struct wrapped_type;
+
+template< typename T > struct wrapped_type< type_wrapper<T> >
+{
+ typedef T type;
+};
+#else
+template< typename W > struct wrapped_type
+{
+ typedef typename W::type type;
+};
+#endif
+
+}}}
+
+#endif // BOOST_MPL_AUX_TYPE_WRAPPER_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/value_wknd.hpp b/third_party/boost/boost/mpl/aux_/value_wknd.hpp
new file mode 100644
index 0000000..9e1ad65
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/value_wknd.hpp
@@ -0,0 +1,89 @@
+
+#ifndef BOOST_MPL_AUX_VALUE_WKND_HPP_INCLUDED
+#define BOOST_MPL_AUX_VALUE_WKND_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/static_cast.hpp>
+#include <boost/mpl/aux_/config/integral.hpp>
+#include <boost/mpl/aux_/config/eti.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+#if defined(BOOST_MPL_CFG_BCC_INTEGRAL_CONSTANTS) \
+ || defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG)
+
+# include <boost/mpl/int.hpp>
+
+namespace boost { namespace mpl { namespace aux {
+template< typename C_ > struct value_wknd
+ : C_
+{
+};
+
+#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG)
+template<> struct value_wknd<int>
+ : int_<1>
+{
+ using int_<1>::value;
+};
+#endif
+}}}
+
+
+#if !defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG)
+# define BOOST_MPL_AUX_VALUE_WKND(C) \
+ ::BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE::aux::value_wknd< C > \
+/**/
+# define BOOST_MPL_AUX_MSVC_VALUE_WKND(C) BOOST_MPL_AUX_VALUE_WKND(C)
+#else
+# define BOOST_MPL_AUX_VALUE_WKND(C) C
+# define BOOST_MPL_AUX_MSVC_VALUE_WKND(C) \
+ ::boost::mpl::aux::value_wknd< C > \
+/**/
+#endif
+
+#else // BOOST_MPL_CFG_BCC_INTEGRAL_CONSTANTS
+
+# define BOOST_MPL_AUX_VALUE_WKND(C) C
+# define BOOST_MPL_AUX_MSVC_VALUE_WKND(C) C
+
+#endif
+
+#if BOOST_WORKAROUND(__EDG_VERSION__, <= 238)
+# define BOOST_MPL_AUX_NESTED_VALUE_WKND(T, C) \
+ BOOST_MPL_AUX_STATIC_CAST(T, C::value) \
+/**/
+#else
+# define BOOST_MPL_AUX_NESTED_VALUE_WKND(T, C) \
+ BOOST_MPL_AUX_VALUE_WKND(C)::value \
+/**/
+#endif
+
+
+namespace boost { namespace mpl { namespace aux {
+
+template< typename T > struct value_type_wknd
+{
+ typedef typename T::value_type type;
+};
+
+#if defined(BOOST_MPL_CFG_MSVC_ETI_BUG)
+template<> struct value_type_wknd<int>
+{
+ typedef int type;
+};
+#endif
+
+}}}
+
+#endif // BOOST_MPL_AUX_VALUE_WKND_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/aux_/yes_no.hpp b/third_party/boost/boost/mpl/aux_/yes_no.hpp
new file mode 100644
index 0000000..e1b65ed
--- /dev/null
+++ b/third_party/boost/boost/mpl/aux_/yes_no.hpp
@@ -0,0 +1,58 @@
+
+#ifndef BOOST_MPL_AUX_YES_NO_HPP_INCLUDED
+#define BOOST_MPL_AUX_YES_NO_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/nttp_decl.hpp>
+#include <boost/mpl/aux_/config/arrays.hpp>
+#include <boost/mpl/aux_/config/msvc.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+
+namespace boost { namespace mpl { namespace aux {
+
+typedef char (&no_tag)[1];
+typedef char (&yes_tag)[2];
+
+template< bool C_ > struct yes_no_tag
+{
+ typedef no_tag type;
+};
+
+template<> struct yes_no_tag<true>
+{
+ typedef yes_tag type;
+};
+
+
+template< BOOST_MPL_AUX_NTTP_DECL(long, n) > struct weighted_tag
+{
+#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+ typedef char (&type)[n];
+#else
+ char buf[n];
+ typedef weighted_tag type;
+#endif
+};
+
+#if defined(BOOST_MPL_CFG_NO_DEPENDENT_ARRAY_TYPES)
+template<> struct weighted_tag<0>
+{
+ typedef char (&type)[1];
+};
+#endif
+
+}}}
+
+#endif // BOOST_MPL_AUX_YES_NO_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/back_inserter.hpp b/third_party/boost/boost/mpl/back_inserter.hpp
new file mode 100644
index 0000000..b23b950
--- /dev/null
+++ b/third_party/boost/boost/mpl/back_inserter.hpp
@@ -0,0 +1,34 @@
+
+#ifndef BOOST_MPL_BACK_INSERTER_HPP_INCLUDED
+#define BOOST_MPL_BACK_INSERTER_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2003-2004
+// Copyright David Abrahams 2003-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/push_back.hpp>
+#include <boost/mpl/inserter.hpp>
+
+namespace boost {
+namespace mpl {
+
+template<
+ typename Sequence
+ >
+struct back_inserter
+ : inserter< Sequence,push_back<> >
+{
+};
+
+}}
+
+#endif // BOOST_MPL_BACK_INSERTER_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/begin_end.hpp b/third_party/boost/boost/mpl/begin_end.hpp
new file mode 100644
index 0000000..fe37ef1
--- /dev/null
+++ b/third_party/boost/boost/mpl/begin_end.hpp
@@ -0,0 +1,57 @@
+
+#ifndef BOOST_MPL_BEGIN_END_HPP_INCLUDED
+#define BOOST_MPL_BEGIN_END_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/begin_end_fwd.hpp>
+#include <boost/mpl/aux_/begin_end_impl.hpp>
+#include <boost/mpl/sequence_tag.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+
+namespace boost { namespace mpl {
+
+// agurt, 13/sep/02: switched from inheritance to typedef; MSVC is more
+// happy this way (less ETI-related errors), and it doesn't affect
+// anything else
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(Sequence)
+ >
+struct begin
+{
+ typedef typename sequence_tag<Sequence>::type tag_;
+ typedef typename begin_impl< tag_ >
+ ::template apply< Sequence >::type type;
+
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1,begin,(Sequence))
+};
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(Sequence)
+ >
+struct end
+{
+ typedef typename sequence_tag<Sequence>::type tag_;
+ typedef typename end_impl< tag_ >
+ ::template apply< Sequence >::type type;
+
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1,end,(Sequence))
+};
+
+BOOST_MPL_AUX_NA_SPEC(1, begin)
+BOOST_MPL_AUX_NA_SPEC(1, end)
+
+}}
+
+#endif // BOOST_MPL_BEGIN_END_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/begin_end_fwd.hpp b/third_party/boost/boost/mpl/begin_end_fwd.hpp
new file mode 100644
index 0000000..4c16cc2
--- /dev/null
+++ b/third_party/boost/boost/mpl/begin_end_fwd.hpp
@@ -0,0 +1,27 @@
+
+#ifndef BOOST_MPL_BEGIN_END_FWD_HPP_INCLUDED
+#define BOOST_MPL_BEGIN_END_FWD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+namespace boost { namespace mpl {
+
+template< typename Tag > struct begin_impl;
+template< typename Tag > struct end_impl;
+
+template< typename Sequence > struct begin;
+template< typename Sequence > struct end;
+
+}}
+
+#endif // BOOST_MPL_BEGIN_END_FWD_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/bind.hpp b/third_party/boost/boost/mpl/bind.hpp
new file mode 100644
index 0000000..5f73601
--- /dev/null
+++ b/third_party/boost/boost/mpl/bind.hpp
@@ -0,0 +1,551 @@
+
+#if !defined(BOOST_PP_IS_ITERATING)
+
+///// header body
+
+#ifndef BOOST_MPL_BIND_HPP_INCLUDED
+#define BOOST_MPL_BIND_HPP_INCLUDED
+
+// Copyright Peter Dimov 2001
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_PREPROCESSING_MODE)
+# include <boost/mpl/bind_fwd.hpp>
+# include <boost/mpl/placeholders.hpp>
+# include <boost/mpl/next.hpp>
+# include <boost/mpl/protect.hpp>
+# include <boost/mpl/apply_wrap.hpp>
+# include <boost/mpl/limits/arity.hpp>
+# include <boost/mpl/aux_/na.hpp>
+# include <boost/mpl/aux_/arity_spec.hpp>
+# include <boost/mpl/aux_/type_wrapper.hpp>
+# include <boost/mpl/aux_/yes_no.hpp>
+# if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+# include <boost/type_traits/is_reference.hpp>
+# endif
+#endif
+
+#include <boost/mpl/aux_/config/bind.hpp>
+#include <boost/mpl/aux_/config/static_constant.hpp>
+#include <boost/mpl/aux_/config/use_preprocessed.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE)
+
+# if defined(BOOST_MPL_CFG_NO_UNNAMED_PLACEHOLDER_SUPPORT)
+# define BOOST_MPL_PREPROCESSED_HEADER basic_bind.hpp
+# else
+# define BOOST_MPL_PREPROCESSED_HEADER bind.hpp
+# endif
+# include <boost/mpl/aux_/include_preprocessed.hpp>
+
+#else
+
+# include <boost/mpl/aux_/preprocessor/params.hpp>
+# include <boost/mpl/aux_/preprocessor/default_params.hpp>
+# include <boost/mpl/aux_/preprocessor/def_params_tail.hpp>
+# include <boost/mpl/aux_/preprocessor/partial_spec_params.hpp>
+# include <boost/mpl/aux_/preprocessor/ext_params.hpp>
+# include <boost/mpl/aux_/preprocessor/repeat.hpp>
+# include <boost/mpl/aux_/preprocessor/enum.hpp>
+# include <boost/mpl/aux_/preprocessor/add.hpp>
+# include <boost/mpl/aux_/config/dmc_ambiguous_ctps.hpp>
+# include <boost/mpl/aux_/config/ctps.hpp>
+# include <boost/mpl/aux_/config/ttp.hpp>
+# include <boost/mpl/aux_/config/dtp.hpp>
+# include <boost/mpl/aux_/nttp_decl.hpp>
+
+# include <boost/preprocessor/iterate.hpp>
+# include <boost/preprocessor/comma_if.hpp>
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/inc.hpp>
+
+namespace boost { namespace mpl {
+
+// local macros, #undef-ined at the end of the header
+# define AUX778076_APPLY \
+ BOOST_PP_CAT(apply_wrap,BOOST_MPL_LIMIT_METAFUNCTION_ARITY) \
+ /**/
+
+# if defined(BOOST_MPL_CFG_DMC_AMBIGUOUS_CTPS)
+# define AUX778076_DMC_PARAM() , int dummy_
+# else
+# define AUX778076_DMC_PARAM()
+# endif
+
+# define AUX778076_BIND_PARAMS(param) \
+ BOOST_MPL_PP_PARAMS( \
+ BOOST_MPL_LIMIT_METAFUNCTION_ARITY \
+ , param \
+ ) \
+ /**/
+
+# define AUX778076_BIND_DEFAULT_PARAMS(param, value) \
+ BOOST_MPL_PP_DEFAULT_PARAMS( \
+ BOOST_MPL_LIMIT_METAFUNCTION_ARITY \
+ , param \
+ , value \
+ ) \
+ /**/
+
+# define AUX778076_BIND_N_PARAMS(n, param) \
+ BOOST_PP_COMMA_IF(n) BOOST_MPL_PP_PARAMS(n, param) \
+ /**/
+
+# define AUX778076_BIND_N_SPEC_PARAMS(n, param, def) \
+ BOOST_PP_COMMA_IF(n) \
+ BOOST_MPL_PP_PARTIAL_SPEC_PARAMS(n, param, def) \
+ /**/
+
+#if !defined(BOOST_MPL_CFG_NO_DEFAULT_PARAMETERS_IN_NESTED_TEMPLATES)
+# define AUX778076_BIND_NESTED_DEFAULT_PARAMS(param, value) \
+ AUX778076_BIND_DEFAULT_PARAMS(param, value) \
+ /**/
+#else
+# define AUX778076_BIND_NESTED_DEFAULT_PARAMS(param, value) \
+ AUX778076_BIND_PARAMS(param) \
+ /**/
+#endif
+
+namespace aux {
+
+#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+
+template<
+ typename T, AUX778076_BIND_PARAMS(typename U)
+ >
+struct resolve_bind_arg
+{
+ typedef T type;
+};
+
+# if !defined(BOOST_MPL_CFG_NO_UNNAMED_PLACEHOLDER_SUPPORT)
+
+template<
+ typename T
+ , typename Arg
+ >
+struct replace_unnamed_arg
+{
+ typedef Arg next;
+ typedef T type;
+};
+
+template<
+ typename Arg
+ >
+struct replace_unnamed_arg< arg<-1>,Arg >
+{
+ typedef typename Arg::next next;
+ typedef Arg type;
+};
+
+# endif // BOOST_MPL_CFG_NO_UNNAMED_PLACEHOLDER_SUPPORT
+
+template<
+ BOOST_MPL_AUX_NTTP_DECL(int, N), AUX778076_BIND_PARAMS(typename U)
+ >
+struct resolve_bind_arg< arg<N>,AUX778076_BIND_PARAMS(U) >
+{
+ typedef typename AUX778076_APPLY<mpl::arg<N>, AUX778076_BIND_PARAMS(U)>::type type;
+};
+
+#if !defined(BOOST_MPL_CFG_NO_BIND_TEMPLATE)
+template<
+ typename F, AUX778076_BIND_PARAMS(typename T), AUX778076_BIND_PARAMS(typename U)
+ >
+struct resolve_bind_arg< bind<F,AUX778076_BIND_PARAMS(T)>,AUX778076_BIND_PARAMS(U) >
+{
+ typedef bind<F,AUX778076_BIND_PARAMS(T)> f_;
+ typedef typename AUX778076_APPLY<f_, AUX778076_BIND_PARAMS(U)>::type type;
+};
+#endif
+
+#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+
+// agurt, 15/jan/02: it's not a intended to be used as a function class, and
+// MSVC6.5 has problems with 'apply' name here (the code compiles, but doesn't
+// work), so I went with the 'result_' here, and in all other similar cases
+template< bool >
+struct resolve_arg_impl
+{
+ template< typename T, AUX778076_BIND_PARAMS(typename U) > struct result_
+ {
+ typedef T type;
+ };
+};
+
+template<>
+struct resolve_arg_impl<true>
+{
+ template< typename T, AUX778076_BIND_PARAMS(typename U) > struct result_
+ {
+ typedef typename AUX778076_APPLY<
+ T
+ , AUX778076_BIND_PARAMS(U)
+ >::type type;
+ };
+};
+
+// for 'resolve_bind_arg'
+template< typename T > struct is_bind_template;
+
+template<
+ typename T, AUX778076_BIND_PARAMS(typename U)
+ >
+struct resolve_bind_arg
+ : resolve_arg_impl< is_bind_template<T>::value >
+ ::template result_< T,AUX778076_BIND_PARAMS(U) >
+{
+};
+
+# if !defined(BOOST_MPL_CFG_NO_UNNAMED_PLACEHOLDER_SUPPORT)
+
+template< typename T >
+struct replace_unnamed_arg_impl
+{
+ template< typename Arg > struct result_
+ {
+ typedef Arg next;
+ typedef T type;
+ };
+};
+
+template<>
+struct replace_unnamed_arg_impl< arg<-1> >
+{
+ template< typename Arg > struct result_
+ {
+ typedef typename next<Arg>::type next;
+ typedef Arg type;
+ };
+};
+
+template< typename T, typename Arg >
+struct replace_unnamed_arg
+ : replace_unnamed_arg_impl<T>::template result_<Arg>
+{
+};
+
+# endif // BOOST_MPL_CFG_NO_UNNAMED_PLACEHOLDER_SUPPORT
+
+// agurt, 10/mar/02: the forward declaration has to appear before any of
+// 'is_bind_helper' overloads, otherwise MSVC6.5 issues an ICE on it
+template< BOOST_MPL_AUX_NTTP_DECL(int, arity_) > struct bind_chooser;
+
+aux::no_tag is_bind_helper(...);
+template< typename T > aux::no_tag is_bind_helper(protect<T>*);
+
+// overload for "main" form
+// agurt, 15/mar/02: MSVC 6.5 fails to properly resolve the overload
+// in case if we use 'aux::type_wrapper< bind<...> >' here, and all
+// 'bind' instantiations form a complete type anyway
+#if !defined(BOOST_MPL_CFG_NO_BIND_TEMPLATE)
+template<
+ typename F, AUX778076_BIND_PARAMS(typename T)
+ >
+aux::yes_tag is_bind_helper(bind<F,AUX778076_BIND_PARAMS(T)>*);
+#endif
+
+template< BOOST_MPL_AUX_NTTP_DECL(int, N) >
+aux::yes_tag is_bind_helper(arg<N>*);
+
+template< bool is_ref_ = true >
+struct is_bind_template_impl
+{
+ template< typename T > struct result_
+ {
+ BOOST_STATIC_CONSTANT(bool, value = false);
+ };
+};
+
+template<>
+struct is_bind_template_impl<false>
+{
+ template< typename T > struct result_
+ {
+ BOOST_STATIC_CONSTANT(bool, value =
+ sizeof(aux::is_bind_helper(static_cast<T*>(0)))
+ == sizeof(aux::yes_tag)
+ );
+ };
+};
+
+template< typename T > struct is_bind_template
+ : is_bind_template_impl< ::boost::detail::is_reference_impl<T>::value >
+ ::template result_<T>
+{
+};
+
+#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+
+} // namespace aux
+
+
+#define BOOST_PP_ITERATION_PARAMS_1 \
+ (3,(0, BOOST_MPL_LIMIT_METAFUNCTION_ARITY, <boost/mpl/bind.hpp>))
+#include BOOST_PP_ITERATE()
+
+#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
+ && !defined(BOOST_MPL_CFG_NO_TEMPLATE_TEMPLATE_PARAMETERS)
+/// if_/eval_if specializations
+# define AUX778076_SPEC_NAME if_
+# define BOOST_PP_ITERATION_PARAMS_1 (3,(3, 3, <boost/mpl/bind.hpp>))
+# include BOOST_PP_ITERATE()
+
+#if !defined(BOOST_MPL_CFG_DMC_AMBIGUOUS_CTPS)
+# define AUX778076_SPEC_NAME eval_if
+# define BOOST_PP_ITERATION_PARAMS_1 (3,(3, 3, <boost/mpl/bind.hpp>))
+# include BOOST_PP_ITERATE()
+#endif
+#endif
+
+// real C++ version is already taken care of
+#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
+ && !defined(BOOST_MPL_CFG_NO_BIND_TEMPLATE)
+
+namespace aux {
+// apply_count_args
+#define AUX778076_COUNT_ARGS_PREFIX bind
+#define AUX778076_COUNT_ARGS_DEFAULT na
+#define AUX778076_COUNT_ARGS_ARITY BOOST_MPL_LIMIT_METAFUNCTION_ARITY
+#include <boost/mpl/aux_/count_args.hpp>
+}
+
+// bind
+template<
+ typename F, AUX778076_BIND_PARAMS(typename T) AUX778076_DMC_PARAM()
+ >
+struct bind
+ : aux::bind_chooser<
+ aux::bind_count_args<AUX778076_BIND_PARAMS(T)>::value
+ >::template result_< F,AUX778076_BIND_PARAMS(T) >::type
+{
+};
+
+BOOST_MPL_AUX_ARITY_SPEC(
+ BOOST_PP_INC(BOOST_MPL_LIMIT_METAFUNCTION_ARITY)
+ , bind
+ )
+
+BOOST_MPL_AUX_TEMPLATE_ARITY_SPEC(
+ BOOST_PP_INC(BOOST_MPL_LIMIT_METAFUNCTION_ARITY)
+ , bind
+ )
+
+
+#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+
+# undef AUX778076_BIND_NESTED_DEFAULT_PARAMS
+# undef AUX778076_BIND_N_SPEC_PARAMS
+# undef AUX778076_BIND_N_PARAMS
+# undef AUX778076_BIND_DEFAULT_PARAMS
+# undef AUX778076_BIND_PARAMS
+# undef AUX778076_DMC_PARAM
+# undef AUX778076_APPLY
+
+}}
+
+#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#endif // BOOST_MPL_BIND_HPP_INCLUDED
+
+///// iteration, depth == 1
+
+// For gcc 4.4 compatability, we must include the
+// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
+#else // BOOST_PP_IS_ITERATING
+#if BOOST_PP_ITERATION_DEPTH() == 1
+
+# define i_ BOOST_PP_FRAME_ITERATION(1)
+
+#if defined(AUX778076_SPEC_NAME)
+
+// lazy metafunction specialization
+template< template< BOOST_MPL_PP_PARAMS(i_, typename T) > class F, typename Tag >
+struct BOOST_PP_CAT(quote,i_);
+
+template< BOOST_MPL_PP_PARAMS(i_, typename T) > struct AUX778076_SPEC_NAME;
+
+template<
+ typename Tag AUX778076_BIND_N_PARAMS(i_, typename T)
+ >
+struct BOOST_PP_CAT(bind,i_)<
+ BOOST_PP_CAT(quote,i_)<AUX778076_SPEC_NAME,Tag>
+ AUX778076_BIND_N_PARAMS(i_,T)
+ >
+{
+ template<
+ AUX778076_BIND_NESTED_DEFAULT_PARAMS(typename U, na)
+ >
+ struct apply
+ {
+ private:
+ typedef mpl::arg<1> n1;
+# define BOOST_PP_ITERATION_PARAMS_2 (3,(1, i_, <boost/mpl/bind.hpp>))
+# include BOOST_PP_ITERATE()
+
+ typedef typename AUX778076_SPEC_NAME<
+ typename t1::type
+ , BOOST_MPL_PP_EXT_PARAMS(2, BOOST_PP_INC(i_), t)
+ >::type f_;
+
+ public:
+ typedef typename f_::type type;
+ };
+};
+
+#undef AUX778076_SPEC_NAME
+
+#else // AUX778076_SPEC_NAME
+
+template<
+ typename F AUX778076_BIND_N_PARAMS(i_, typename T) AUX778076_DMC_PARAM()
+ >
+struct BOOST_PP_CAT(bind,i_)
+{
+ template<
+ AUX778076_BIND_NESTED_DEFAULT_PARAMS(typename U, na)
+ >
+ struct apply
+ {
+ private:
+# if !defined(BOOST_MPL_CFG_NO_UNNAMED_PLACEHOLDER_SUPPORT)
+
+ typedef aux::replace_unnamed_arg< F,mpl::arg<1> > r0;
+ typedef typename r0::type a0;
+ typedef typename r0::next n1;
+ typedef typename aux::resolve_bind_arg<a0,AUX778076_BIND_PARAMS(U)>::type f_;
+ ///
+# else
+ typedef typename aux::resolve_bind_arg<F,AUX778076_BIND_PARAMS(U)>::type f_;
+
+# endif // BOOST_MPL_CFG_NO_UNNAMED_PLACEHOLDER_SUPPORT
+
+# if i_ > 0
+# define BOOST_PP_ITERATION_PARAMS_2 (3,(1, i_, <boost/mpl/bind.hpp>))
+# include BOOST_PP_ITERATE()
+# endif
+
+ public:
+
+# define AUX778076_ARG(unused, i_, t) \
+ BOOST_PP_COMMA_IF(i_) \
+ typename BOOST_PP_CAT(t,BOOST_PP_INC(i_))::type \
+/**/
+
+ typedef typename BOOST_PP_CAT(apply_wrap,i_)<
+ f_
+ BOOST_PP_COMMA_IF(i_) BOOST_MPL_PP_REPEAT(i_, AUX778076_ARG, t)
+ >::type type;
+
+# undef AUX778076_ARG
+ };
+};
+
+namespace aux {
+
+#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+
+template<
+ typename F AUX778076_BIND_N_PARAMS(i_, typename T), AUX778076_BIND_PARAMS(typename U)
+ >
+struct resolve_bind_arg<
+ BOOST_PP_CAT(bind,i_)<F AUX778076_BIND_N_PARAMS(i_,T)>,AUX778076_BIND_PARAMS(U)
+ >
+{
+ typedef BOOST_PP_CAT(bind,i_)<F AUX778076_BIND_N_PARAMS(i_,T)> f_;
+ typedef typename AUX778076_APPLY<f_, AUX778076_BIND_PARAMS(U)>::type type;
+};
+
+#else
+
+template<
+ typename F AUX778076_BIND_N_PARAMS(i_, typename T)
+ >
+aux::yes_tag
+is_bind_helper(BOOST_PP_CAT(bind,i_)<F AUX778076_BIND_N_PARAMS(i_,T)>*);
+
+#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+
+} // namespace aux
+
+BOOST_MPL_AUX_ARITY_SPEC(BOOST_PP_INC(i_), BOOST_PP_CAT(bind,i_))
+BOOST_MPL_AUX_TEMPLATE_ARITY_SPEC(BOOST_PP_INC(i_), BOOST_PP_CAT(bind,i_))
+
+# if !defined(BOOST_MPL_CFG_NO_BIND_TEMPLATE)
+# if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+
+#if i_ == BOOST_MPL_LIMIT_METAFUNCTION_ARITY
+/// primary template (not a specialization!)
+template<
+ typename F AUX778076_BIND_N_PARAMS(i_, typename T) AUX778076_DMC_PARAM()
+ >
+struct bind
+ : BOOST_PP_CAT(bind,i_)<F AUX778076_BIND_N_PARAMS(i_,T) >
+{
+};
+#else
+template<
+ typename F AUX778076_BIND_N_PARAMS(i_, typename T) AUX778076_DMC_PARAM()
+ >
+struct bind< F AUX778076_BIND_N_SPEC_PARAMS(i_, T, na) >
+ : BOOST_PP_CAT(bind,i_)<F AUX778076_BIND_N_PARAMS(i_,T) >
+{
+};
+#endif
+
+# else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+
+namespace aux {
+
+template<>
+struct bind_chooser<i_>
+{
+ template<
+ typename F, AUX778076_BIND_PARAMS(typename T)
+ >
+ struct result_
+ {
+ typedef BOOST_PP_CAT(bind,i_)< F AUX778076_BIND_N_PARAMS(i_,T) > type;
+ };
+};
+
+} // namespace aux
+
+# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+# endif // BOOST_MPL_CFG_NO_BIND_TEMPLATE
+
+#endif // AUX778076_SPEC_NAME
+
+# undef i_
+
+///// iteration, depth == 2
+
+#elif BOOST_PP_ITERATION_DEPTH() == 2
+
+# define j_ BOOST_PP_FRAME_ITERATION(2)
+# if !defined(BOOST_MPL_CFG_NO_UNNAMED_PLACEHOLDER_SUPPORT)
+
+ typedef aux::replace_unnamed_arg< BOOST_PP_CAT(T,j_),BOOST_PP_CAT(n,j_) > BOOST_PP_CAT(r,j_);
+ typedef typename BOOST_PP_CAT(r,j_)::type BOOST_PP_CAT(a,j_);
+ typedef typename BOOST_PP_CAT(r,j_)::next BOOST_PP_CAT(n,BOOST_PP_INC(j_));
+ typedef aux::resolve_bind_arg<BOOST_PP_CAT(a,j_), AUX778076_BIND_PARAMS(U)> BOOST_PP_CAT(t,j_);
+ ///
+# else
+ typedef aux::resolve_bind_arg< BOOST_PP_CAT(T,j_),AUX778076_BIND_PARAMS(U)> BOOST_PP_CAT(t,j_);
+
+# endif
+# undef j_
+
+#endif // BOOST_PP_ITERATION_DEPTH()
+#endif // BOOST_PP_IS_ITERATING
diff --git a/third_party/boost/boost/mpl/bind_fwd.hpp b/third_party/boost/boost/mpl/bind_fwd.hpp
new file mode 100644
index 0000000..1fa8915
--- /dev/null
+++ b/third_party/boost/boost/mpl/bind_fwd.hpp
@@ -0,0 +1,99 @@
+
+#if !defined(BOOST_PP_IS_ITERATING)
+
+///// header body
+
+#ifndef BOOST_MPL_BIND_FWD_HPP_INCLUDED
+#define BOOST_MPL_BIND_FWD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_PREPROCESSING_MODE)
+# include <boost/mpl/aux_/na.hpp>
+#endif
+
+#include <boost/mpl/aux_/config/bind.hpp>
+#include <boost/mpl/aux_/config/use_preprocessed.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE)
+
+# define BOOST_MPL_PREPROCESSED_HEADER bind_fwd.hpp
+# include <boost/mpl/aux_/include_preprocessed.hpp>
+
+#else
+
+# include <boost/mpl/limits/arity.hpp>
+# include <boost/mpl/aux_/preprocessor/params.hpp>
+# include <boost/mpl/aux_/preprocessor/default_params.hpp>
+# include <boost/mpl/aux_/config/dmc_ambiguous_ctps.hpp>
+
+# include <boost/preprocessor/comma_if.hpp>
+# include <boost/preprocessor/iterate.hpp>
+# include <boost/preprocessor/cat.hpp>
+
+namespace boost { namespace mpl {
+
+// local macros, #undef-ined at the end of the header
+
+# if defined(BOOST_MPL_CFG_DMC_AMBIGUOUS_CTPS)
+# define AUX778076_DMC_PARAM() , int dummy_ = 0
+# else
+# define AUX778076_DMC_PARAM()
+# endif
+
+# define AUX778076_BIND_DEFAULT_PARAMS(param, value) \
+ BOOST_MPL_PP_DEFAULT_PARAMS( \
+ BOOST_MPL_LIMIT_METAFUNCTION_ARITY \
+ , param \
+ , value \
+ ) \
+ AUX778076_DMC_PARAM() \
+ /**/
+
+# define AUX778076_BIND_N_PARAMS(n, param) \
+ BOOST_PP_COMMA_IF(n) BOOST_MPL_PP_PARAMS(n, param) \
+ AUX778076_DMC_PARAM() \
+ /**/
+
+#if !defined(BOOST_MPL_CFG_NO_BIND_TEMPLATE)
+template<
+ typename F, AUX778076_BIND_DEFAULT_PARAMS(typename T, na)
+ >
+struct bind;
+#endif
+
+#define BOOST_PP_ITERATION_PARAMS_1 \
+ (3,(0, BOOST_MPL_LIMIT_METAFUNCTION_ARITY, <boost/mpl/bind_fwd.hpp>))
+#include BOOST_PP_ITERATE()
+
+# undef AUX778076_BIND_N_PARAMS
+# undef AUX778076_BIND_DEFAULT_PARAMS
+# undef AUX778076_DMC_PARAM
+}}
+
+#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#endif // BOOST_MPL_BIND_FWD_HPP_INCLUDED
+
+///// iteration
+
+#else
+#define i_ BOOST_PP_FRAME_ITERATION(1)
+
+template<
+ typename F AUX778076_BIND_N_PARAMS(i_, typename T)
+ >
+struct BOOST_PP_CAT(bind,i_);
+
+#undef i_
+#endif // BOOST_PP_IS_ITERATING
diff --git a/third_party/boost/boost/mpl/bool.hpp b/third_party/boost/boost/mpl/bool.hpp
new file mode 100644
index 0000000..4c336fb
--- /dev/null
+++ b/third_party/boost/boost/mpl/bool.hpp
@@ -0,0 +1,39 @@
+
+#ifndef BOOST_MPL_BOOL_HPP_INCLUDED
+#define BOOST_MPL_BOOL_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/bool_fwd.hpp>
+#include <boost/mpl/integral_c_tag.hpp>
+#include <boost/mpl/aux_/config/static_constant.hpp>
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+
+template< bool C_ > struct bool_
+{
+ BOOST_STATIC_CONSTANT(bool, value = C_);
+ typedef integral_c_tag tag;
+ typedef bool_ type;
+ typedef bool value_type;
+ BOOST_CONSTEXPR operator bool() const { return this->value; }
+};
+
+#if !defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION)
+template< bool C_ >
+bool const bool_<C_>::value;
+#endif
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+
+#endif // BOOST_MPL_BOOL_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/bool_fwd.hpp b/third_party/boost/boost/mpl/bool_fwd.hpp
new file mode 100644
index 0000000..780b280
--- /dev/null
+++ b/third_party/boost/boost/mpl/bool_fwd.hpp
@@ -0,0 +1,33 @@
+
+#ifndef BOOST_MPL_BOOL_FWD_HPP_INCLUDED
+#define BOOST_MPL_BOOL_FWD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/adl_barrier.hpp>
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+
+template< bool C_ > struct bool_;
+
+// shorcuts
+typedef bool_<true> true_;
+typedef bool_<false> false_;
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+
+BOOST_MPL_AUX_ADL_BARRIER_DECL(bool_)
+BOOST_MPL_AUX_ADL_BARRIER_DECL(true_)
+BOOST_MPL_AUX_ADL_BARRIER_DECL(false_)
+
+#endif // BOOST_MPL_BOOL_FWD_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/clear.hpp b/third_party/boost/boost/mpl/clear.hpp
new file mode 100644
index 0000000..91b8168
--- /dev/null
+++ b/third_party/boost/boost/mpl/clear.hpp
@@ -0,0 +1,39 @@
+
+#ifndef BOOST_MPL_CLEAR_HPP_INCLUDED
+#define BOOST_MPL_CLEAR_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/clear_fwd.hpp>
+#include <boost/mpl/aux_/clear_impl.hpp>
+#include <boost/mpl/sequence_tag.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+
+namespace boost { namespace mpl {
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(Sequence)
+ >
+struct clear
+ : clear_impl< typename sequence_tag<Sequence>::type >
+ ::template apply< Sequence >
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1,clear,(Sequence))
+};
+
+BOOST_MPL_AUX_NA_SPEC(1, clear)
+
+}}
+
+#endif // BOOST_MPL_CLEAR_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/clear_fwd.hpp b/third_party/boost/boost/mpl/clear_fwd.hpp
new file mode 100644
index 0000000..60dfedb
--- /dev/null
+++ b/third_party/boost/boost/mpl/clear_fwd.hpp
@@ -0,0 +1,24 @@
+
+#ifndef BOOST_MPL_CLEAR_FWD_HPP_INCLUDED
+#define BOOST_MPL_CLEAR_FWD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+namespace boost { namespace mpl {
+
+template< typename Tag > struct clear_impl;
+template< typename Sequence > struct clear;
+
+}}
+
+#endif // BOOST_MPL_CLEAR_FWD_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/deref.hpp b/third_party/boost/boost/mpl/deref.hpp
new file mode 100644
index 0000000..55f7cde
--- /dev/null
+++ b/third_party/boost/boost/mpl/deref.hpp
@@ -0,0 +1,41 @@
+
+#ifndef BOOST_MPL_DEREF_HPP_INCLUDED
+#define BOOST_MPL_DEREF_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 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/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/msvc_type.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+#include <boost/mpl/aux_/config/eti.hpp>
+
+namespace boost { namespace mpl {
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(Iterator)
+ >
+struct deref
+{
+#if !defined(BOOST_MPL_CFG_MSVC_70_ETI_BUG)
+ typedef typename Iterator::type type;
+#else
+ typedef typename aux::msvc_type<Iterator>::type type;
+#endif
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1,deref,(Iterator))
+};
+
+BOOST_MPL_AUX_NA_SPEC(1, deref)
+
+}}
+
+#endif // BOOST_MPL_DEREF_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/distance.hpp b/third_party/boost/boost/mpl/distance.hpp
new file mode 100644
index 0000000..18441a6
--- /dev/null
+++ b/third_party/boost/boost/mpl/distance.hpp
@@ -0,0 +1,78 @@
+
+#ifndef BOOST_MPL_DISTANCE_HPP_INCLUDED
+#define BOOST_MPL_DISTANCE_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/distance_fwd.hpp>
+#include <boost/mpl/iter_fold.hpp>
+#include <boost/mpl/iterator_range.hpp>
+#include <boost/mpl/long.hpp>
+#include <boost/mpl/next.hpp>
+#include <boost/mpl/tag.hpp>
+#include <boost/mpl/apply_wrap.hpp>
+#include <boost/mpl/aux_/msvc_eti_base.hpp>
+#include <boost/mpl/aux_/value_wknd.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/config/forwarding.hpp>
+#include <boost/mpl/aux_/config/static_constant.hpp>
+
+
+namespace boost { namespace mpl {
+
+// default implementation for forward/bidirectional iterators
+template< typename Tag > struct distance_impl
+{
+ template< typename First, typename Last > struct apply
+#if !defined(BOOST_MPL_CFG_NO_NESTED_FORWARDING)
+ : aux::msvc_eti_base< typename iter_fold<
+ iterator_range<First,Last>
+ , mpl::long_<0>
+ , next<>
+ >::type >
+ {
+#else
+ {
+ typedef typename iter_fold<
+ iterator_range<First,Last>
+ , mpl::long_<0>
+ , next<>
+ >::type type;
+
+ BOOST_STATIC_CONSTANT(long, value =
+ (iter_fold<
+ iterator_range<First,Last>
+ , mpl::long_<0>
+ , next<>
+ >::type::value)
+ );
+#endif
+ };
+};
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(First)
+ , typename BOOST_MPL_AUX_NA_PARAM(Last)
+ >
+struct distance
+ : distance_impl< typename tag<First>::type >
+ ::template apply<First, Last>
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(2, distance, (First, Last))
+};
+
+BOOST_MPL_AUX_NA_SPEC(2, distance)
+
+}}
+
+#endif // BOOST_MPL_DISTANCE_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/distance_fwd.hpp b/third_party/boost/boost/mpl/distance_fwd.hpp
new file mode 100644
index 0000000..efe8d12
--- /dev/null
+++ b/third_party/boost/boost/mpl/distance_fwd.hpp
@@ -0,0 +1,28 @@
+
+#ifndef BOOST_MPL_DISTANCE_FWD_HPP_INCLUDED
+#define BOOST_MPL_DISTANCE_FWD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/common_name_wknd.hpp>
+
+namespace boost { namespace mpl {
+
+BOOST_MPL_AUX_COMMON_NAME_WKND(distance)
+
+template< typename Tag > struct distance_impl;
+template< typename First, typename Last > struct distance;
+
+}}
+
+#endif // BOOST_MPL_DISTANCE_FWD_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/empty.hpp b/third_party/boost/boost/mpl/empty.hpp
new file mode 100644
index 0000000..f4f798f
--- /dev/null
+++ b/third_party/boost/boost/mpl/empty.hpp
@@ -0,0 +1,39 @@
+
+#ifndef BOOST_MPL_EMPTY_HPP_INCLUDED
+#define BOOST_MPL_EMPTY_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/empty_fwd.hpp>
+#include <boost/mpl/sequence_tag.hpp>
+#include <boost/mpl/aux_/empty_impl.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+
+namespace boost { namespace mpl {
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(Sequence)
+ >
+struct empty
+ : empty_impl< typename sequence_tag<Sequence>::type >
+ ::template apply< Sequence >
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1,empty,(Sequence))
+};
+
+BOOST_MPL_AUX_NA_SPEC(1, empty)
+
+}}
+
+#endif // BOOST_MPL_EMPTY_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/empty_fwd.hpp b/third_party/boost/boost/mpl/empty_fwd.hpp
new file mode 100644
index 0000000..910821b
--- /dev/null
+++ b/third_party/boost/boost/mpl/empty_fwd.hpp
@@ -0,0 +1,24 @@
+
+#ifndef BOOST_MPL_EMPTY_FWD_HPP_INCLUDED
+#define BOOST_MPL_EMPTY_FWD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+namespace boost { namespace mpl {
+
+template< typename Tag > struct empty_impl;
+template< typename Sequence > struct empty;
+
+}}
+
+#endif // BOOST_MPL_EMPTY_FWD_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/eval_if.hpp b/third_party/boost/boost/mpl/eval_if.hpp
new file mode 100644
index 0000000..e892703
--- /dev/null
+++ b/third_party/boost/boost/mpl/eval_if.hpp
@@ -0,0 +1,71 @@
+
+#ifndef BOOST_MPL_EVAL_IF_HPP_INCLUDED
+#define BOOST_MPL_EVAL_IF_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+#include <boost/mpl/aux_/config/msvc.hpp>
+#include <boost/mpl/aux_/config/gcc.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+namespace boost { namespace mpl {
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(C)
+ , typename BOOST_MPL_AUX_NA_PARAM(F1)
+ , typename BOOST_MPL_AUX_NA_PARAM(F2)
+ >
+struct eval_if
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \
+ || ( BOOST_WORKAROUND(BOOST_MPL_CFG_GCC, >= 0x0300) \
+ && BOOST_WORKAROUND(BOOST_MPL_CFG_GCC, BOOST_TESTED_AT(0x0304)) \
+ )
+{
+ typedef typename if_<C,F1,F2>::type f_;
+ typedef typename f_::type type;
+#else
+ : if_<C,F1,F2>::type
+{
+#endif
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(3,eval_if,(C,F1,F2))
+};
+
+// (almost) copy & paste in order to save one more
+// recursively nested template instantiation to user
+template<
+ bool C
+ , typename F1
+ , typename F2
+ >
+struct eval_if_c
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \
+ || ( BOOST_WORKAROUND(BOOST_MPL_CFG_GCC, >= 0x0300) \
+ && BOOST_WORKAROUND(BOOST_MPL_CFG_GCC, BOOST_TESTED_AT(0x0304)) \
+ )
+{
+ typedef typename if_c<C,F1,F2>::type f_;
+ typedef typename f_::type type;
+#else
+ : if_c<C,F1,F2>::type
+{
+#endif
+};
+
+BOOST_MPL_AUX_NA_SPEC(3, eval_if)
+
+}}
+
+#endif // BOOST_MPL_EVAL_IF_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/find_if.hpp b/third_party/boost/boost/mpl/find_if.hpp
new file mode 100644
index 0000000..d40da39
--- /dev/null
+++ b/third_party/boost/boost/mpl/find_if.hpp
@@ -0,0 +1,50 @@
+
+#ifndef BOOST_MPL_FIND_IF_HPP_INCLUDED
+#define BOOST_MPL_FIND_IF_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/find_if_pred.hpp>
+#include <boost/mpl/arg.hpp>
+#include <boost/mpl/iter_fold_if.hpp>
+#include <boost/mpl/aux_/common_name_wknd.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+
+namespace boost { namespace mpl {
+
+BOOST_MPL_AUX_COMMON_NAME_WKND(find_if)
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(Sequence)
+ , typename BOOST_MPL_AUX_NA_PARAM(Predicate)
+ >
+struct find_if
+{
+ typedef typename iter_fold_if<
+ Sequence
+ , void
+ , mpl::arg<1> // ignore
+ , protect< aux::find_if_pred<Predicate> >
+ >::type result_;
+
+ typedef typename second<result_>::type type;
+
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(2,find_if,(Sequence,Predicate))
+};
+
+BOOST_MPL_AUX_NA_SPEC(2,find_if)
+
+}}
+
+#endif // BOOST_MPL_FIND_IF_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/fold.hpp b/third_party/boost/boost/mpl/fold.hpp
new file mode 100644
index 0000000..8c06f76
--- /dev/null
+++ b/third_party/boost/boost/mpl/fold.hpp
@@ -0,0 +1,48 @@
+
+#ifndef BOOST_MPL_FOLD_HPP_INCLUDED
+#define BOOST_MPL_FOLD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+// Copyright David Abrahams 2001-2002
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/begin_end.hpp>
+#include <boost/mpl/O1_size.hpp>
+#include <boost/mpl/aux_/fold_impl.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+
+namespace boost { namespace mpl {
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(Sequence)
+ , typename BOOST_MPL_AUX_NA_PARAM(State)
+ , typename BOOST_MPL_AUX_NA_PARAM(ForwardOp)
+ >
+struct fold
+{
+ typedef typename aux::fold_impl<
+ ::boost::mpl::O1_size<Sequence>::value
+ , typename begin<Sequence>::type
+ , typename end<Sequence>::type
+ , State
+ , ForwardOp
+ >::state type;
+
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(3,fold,(Sequence,State,ForwardOp))
+};
+
+BOOST_MPL_AUX_NA_SPEC(3, fold)
+
+}}
+
+#endif // BOOST_MPL_FOLD_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/front.hpp b/third_party/boost/boost/mpl/front.hpp
new file mode 100644
index 0000000..6c30f02
--- /dev/null
+++ b/third_party/boost/boost/mpl/front.hpp
@@ -0,0 +1,39 @@
+
+#ifndef BOOST_MPL_FRONT_HPP_INCLUDED
+#define BOOST_MPL_FRONT_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/front_fwd.hpp>
+#include <boost/mpl/aux_/front_impl.hpp>
+#include <boost/mpl/sequence_tag.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+
+namespace boost { namespace mpl {
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(Sequence)
+ >
+struct front
+ : front_impl< typename sequence_tag<Sequence>::type >
+ ::template apply< Sequence >
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1,front,(Sequence))
+};
+
+BOOST_MPL_AUX_NA_SPEC(1, front)
+
+}}
+
+#endif // BOOST_MPL_FRONT_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/front_fwd.hpp b/third_party/boost/boost/mpl/front_fwd.hpp
new file mode 100644
index 0000000..0e181a5
--- /dev/null
+++ b/third_party/boost/boost/mpl/front_fwd.hpp
@@ -0,0 +1,24 @@
+
+#ifndef BOOST_MPL_FRONT_FWD_HPP_INCLUDED
+#define BOOST_MPL_FRONT_FWD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+namespace boost { namespace mpl {
+
+template< typename Tag > struct front_impl;
+template< typename Sequence > struct front;
+
+}}
+
+#endif // BOOST_MPL_FRONT_FWD_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/front_inserter.hpp b/third_party/boost/boost/mpl/front_inserter.hpp
new file mode 100644
index 0000000..b047233
--- /dev/null
+++ b/third_party/boost/boost/mpl/front_inserter.hpp
@@ -0,0 +1,33 @@
+
+#ifndef BOOST_MPL_FRONT_INSERTER_HPP_INCLUDED
+#define BOOST_MPL_FRONT_INSERTER_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2003-2004
+// Copyright David Abrahams 2003-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/push_front.hpp>
+#include <boost/mpl/inserter.hpp>
+
+namespace boost { namespace mpl {
+
+template<
+ typename Sequence
+ >
+struct front_inserter
+ : inserter< Sequence,push_front<> >
+{
+};
+
+}}
+
+#endif // BOOST_MPL_FRONT_INSERTER_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/has_xxx.hpp b/third_party/boost/boost/mpl/has_xxx.hpp
new file mode 100644
index 0000000..8df04cd
--- /dev/null
+++ b/third_party/boost/boost/mpl/has_xxx.hpp
@@ -0,0 +1,647 @@
+
+#ifndef BOOST_MPL_HAS_XXX_HPP_INCLUDED
+#define BOOST_MPL_HAS_XXX_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2002-2006
+// Copyright David Abrahams 2002-2003
+// Copyright Daniel Walker 2007
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/type_wrapper.hpp>
+#include <boost/mpl/aux_/yes_no.hpp>
+#include <boost/mpl/aux_/config/gcc.hpp>
+#include <boost/mpl/aux_/config/has_xxx.hpp>
+#include <boost/mpl/aux_/config/msvc_typename.hpp>
+#include <boost/mpl/aux_/config/msvc.hpp>
+#include <boost/mpl/aux_/config/static_constant.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+#include <boost/preprocessor/array/elem.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/control/if.hpp>
+#include <boost/preprocessor/repetition/enum_params.hpp>
+#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
+
+#if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x590) )
+# include <boost/type_traits/is_class.hpp>
+#endif
+
+#if !defined(BOOST_MPL_CFG_NO_HAS_XXX)
+
+# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
+
+// agurt, 11/sep/02: MSVC-specific version (< 7.1), based on a USENET
+// newsgroup's posting by John Madsen (comp.lang.c++.moderated,
+// 1999-11-12 19:17:06 GMT); the code is _not_ standard-conforming, but
+// it works way more reliably than the SFINAE-based implementation
+
+// Modified dwa 8/Oct/02 to handle reference types.
+
+# include <boost/mpl/if.hpp>
+# include <boost/mpl/bool.hpp>
+
+namespace boost { namespace mpl { namespace aux {
+
+struct has_xxx_tag;
+
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
+template< typename U > struct msvc_incomplete_array
+{
+ typedef char (&type)[sizeof(U) + 1];
+};
+#endif
+
+template< typename T >
+struct msvc_is_incomplete
+{
+ // MSVC is capable of some kinds of SFINAE. If U is an incomplete
+ // type, it won't pick the second overload
+ static char tester(...);
+
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
+ template< typename U >
+ static typename msvc_incomplete_array<U>::type tester(type_wrapper<U>);
+#else
+ template< typename U >
+ static char (& tester(type_wrapper<U>) )[sizeof(U)+1];
+#endif
+
+ BOOST_STATIC_CONSTANT(bool, value =
+ sizeof(tester(type_wrapper<T>())) == 1
+ );
+};
+
+template<>
+struct msvc_is_incomplete<int>
+{
+ BOOST_STATIC_CONSTANT(bool, value = false);
+};
+
+}}}
+
+# define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF_(trait, name, default_) \
+template< typename T, typename name = ::boost::mpl::aux::has_xxx_tag > \
+struct BOOST_PP_CAT(trait,_impl) : T \
+{ \
+ static boost::mpl::aux::no_tag \
+ test(void(*)(::boost::mpl::aux::has_xxx_tag)); \
+ \
+ static boost::mpl::aux::yes_tag test(...); \
+ \
+ BOOST_STATIC_CONSTANT(bool, value = \
+ sizeof(test(static_cast<void(*)(name)>(0))) \
+ != sizeof(boost::mpl::aux::no_tag) \
+ ); \
+ typedef boost::mpl::bool_<value> type; \
+}; \
+\
+template< typename T, typename fallback_ = boost::mpl::bool_<default_> > \
+struct trait \
+ : boost::mpl::if_c< \
+ boost::mpl::aux::msvc_is_incomplete<T>::value \
+ , boost::mpl::bool_<false> \
+ , BOOST_PP_CAT(trait,_impl)<T> \
+ >::type \
+{ \
+}; \
+\
+BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, void) \
+BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, bool) \
+BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, char) \
+BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, signed char) \
+BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, unsigned char) \
+BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, signed short) \
+BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, unsigned short) \
+BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, signed int) \
+BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, unsigned int) \
+BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, signed long) \
+BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, unsigned long) \
+BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, float) \
+BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, double) \
+BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, long double) \
+/**/
+
+# define BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, T) \
+template<> struct trait<T> \
+{ \
+ BOOST_STATIC_CONSTANT(bool, value = false); \
+ typedef boost::mpl::bool_<false> type; \
+}; \
+/**/
+
+#if !defined(BOOST_NO_INTRINSIC_WCHAR_T)
+# define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, unused) \
+ BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF_(trait, name, unused) \
+ BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, wchar_t) \
+/**/
+#else
+# define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, unused) \
+ BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF_(trait, name, unused) \
+/**/
+#endif
+
+
+// SFINAE-based implementations below are derived from a USENET newsgroup's
+// posting by Rani Sharoni (comp.lang.c++.moderated, 2002-03-17 07:45:09 PST)
+
+# elif BOOST_WORKAROUND(BOOST_MSVC, <= 1400) \
+ || (BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1800)) && defined(__CUDACC__)) \
+ || BOOST_WORKAROUND(__IBMCPP__, <= 700)
+
+// MSVC 7.1 & MSVC 8.0 & VACPP
+
+// agurt, 15/jun/05: replace overload-based SFINAE implementation with SFINAE
+// applied to partial specialization to fix some apparently random failures
+// (thanks to Daniel Wallin for researching this!)
+
+# define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, default_) \
+template< typename T > \
+struct BOOST_PP_CAT(trait, _msvc_sfinae_helper) \
+{ \
+ typedef void type; \
+};\
+\
+template< typename T, typename U = void > \
+struct BOOST_PP_CAT(trait,_impl_) \
+{ \
+ BOOST_STATIC_CONSTANT(bool, value = false); \
+ typedef boost::mpl::bool_<value> type; \
+}; \
+\
+template< typename T > \
+struct BOOST_PP_CAT(trait,_impl_)< \
+ T \
+ , typename BOOST_PP_CAT(trait, _msvc_sfinae_helper)< typename T::name >::type \
+ > \
+{ \
+ BOOST_STATIC_CONSTANT(bool, value = true); \
+ typedef boost::mpl::bool_<value> type; \
+}; \
+\
+template< typename T, typename fallback_ = boost::mpl::bool_<default_> > \
+struct trait \
+ : BOOST_PP_CAT(trait,_impl_)<T> \
+{ \
+}; \
+/**/
+
+# elif BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x590) )
+
+# define BOOST_MPL_HAS_XXX_TRAIT_NAMED_BCB_DEF(trait, trait_tester, name, default_) \
+template< typename T, bool IS_CLASS > \
+struct trait_tester \
+{ \
+ BOOST_STATIC_CONSTANT( bool, value = false ); \
+}; \
+template< typename T > \
+struct trait_tester< T, true > \
+{ \
+ struct trait_tester_impl \
+ { \
+ template < class U > \
+ static int resolve( boost::mpl::aux::type_wrapper<U> const volatile * \
+ , boost::mpl::aux::type_wrapper<typename U::name >* = 0 ); \
+ static char resolve( ... ); \
+ }; \
+ typedef boost::mpl::aux::type_wrapper<T> t_; \
+ BOOST_STATIC_CONSTANT( bool, value = ( sizeof( trait_tester_impl::resolve( static_cast< t_ * >(0) ) ) == sizeof(int) ) ); \
+}; \
+template< typename T, typename fallback_ = boost::mpl::bool_<default_> > \
+struct trait \
+{ \
+ BOOST_STATIC_CONSTANT( bool, value = (trait_tester< T, boost::is_class< T >::value >::value) ); \
+ typedef boost::mpl::bool_< trait< T, fallback_ >::value > type; \
+};
+
+# define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, default_) \
+ BOOST_MPL_HAS_XXX_TRAIT_NAMED_BCB_DEF( trait \
+ , BOOST_PP_CAT(trait,_tester) \
+ , name \
+ , default_ ) \
+/**/
+
+# else // other SFINAE-capable compilers
+
+# define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, default_) \
+template< typename T, typename fallback_ = boost::mpl::bool_<default_> > \
+struct trait \
+{ \
+ struct gcc_3_2_wknd \
+ { \
+ template< typename U > \
+ static boost::mpl::aux::yes_tag test( \
+ boost::mpl::aux::type_wrapper<U> const volatile* \
+ , boost::mpl::aux::type_wrapper<BOOST_MSVC_TYPENAME U::name>* = 0 \
+ ); \
+ \
+ static boost::mpl::aux::no_tag test(...); \
+ }; \
+ \
+ typedef boost::mpl::aux::type_wrapper<T> t_; \
+ BOOST_STATIC_CONSTANT(bool, value = \
+ sizeof(gcc_3_2_wknd::test(static_cast<t_*>(0))) \
+ == sizeof(boost::mpl::aux::yes_tag) \
+ ); \
+ typedef boost::mpl::bool_<value> type; \
+}; \
+/**/
+
+# endif // BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
+
+
+#else // BOOST_MPL_CFG_NO_HAS_XXX
+
+// placeholder implementation
+
+# define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, default_) \
+template< typename T, typename fallback_ = boost::mpl::bool_<default_> > \
+struct trait \
+{ \
+ BOOST_STATIC_CONSTANT(bool, value = fallback_::value); \
+ typedef fallback_ type; \
+}; \
+/**/
+
+#endif
+
+#define BOOST_MPL_HAS_XXX_TRAIT_DEF(name) \
+ BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(BOOST_PP_CAT(has_,name), name, false) \
+/**/
+
+
+#if !defined(BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE)
+
+// Create a boolean Metafunction to detect a nested template
+// member. This implementation is based on a USENET newsgroup's
+// posting by Aleksey Gurtovoy (comp.lang.c++.moderated, 2002-03-19),
+// Rani Sharoni's USENET posting cited above, the non-template has_xxx
+// implementations above, and discussion on the Boost mailing list.
+
+# if !defined(BOOST_MPL_HAS_XXX_NO_WRAPPED_TYPES)
+# if BOOST_WORKAROUND(BOOST_MSVC, <= 1400)
+# define BOOST_MPL_HAS_XXX_NO_WRAPPED_TYPES 1
+# else
+# define BOOST_MPL_HAS_XXX_NO_WRAPPED_TYPES 0
+# endif
+# endif
+
+# if !defined(BOOST_MPL_HAS_XXX_NO_EXPLICIT_TEST_FUNCTION)
+# if (defined(BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS))
+# define BOOST_MPL_HAS_XXX_NO_EXPLICIT_TEST_FUNCTION 1
+# else
+# define BOOST_MPL_HAS_XXX_NO_EXPLICIT_TEST_FUNCTION 0
+# endif
+# endif
+
+# if !defined(BOOST_MPL_HAS_XXX_NEEDS_TEMPLATE_SFINAE)
+# if BOOST_WORKAROUND(BOOST_MSVC, <= 1400)
+# define BOOST_MPL_HAS_XXX_NEEDS_TEMPLATE_SFINAE 1
+# else
+# define BOOST_MPL_HAS_XXX_NEEDS_TEMPLATE_SFINAE 0
+# endif
+# endif
+
+// NOTE: Many internal implementation macros take a Boost.Preprocessor
+// array argument called args which is of the following form.
+// ( 4, ( trait, name, max_arity, default_ ) )
+
+# define BOOST_MPL_HAS_MEMBER_INTROSPECTION_NAME(args) \
+ BOOST_PP_CAT(BOOST_PP_ARRAY_ELEM(0, args) , _introspect) \
+ /**/
+
+# define BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME(args, n) \
+ BOOST_PP_CAT(BOOST_PP_CAT(BOOST_PP_ARRAY_ELEM(0, args) , _substitute), n) \
+ /**/
+
+# define BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args) \
+ BOOST_PP_CAT(BOOST_PP_ARRAY_ELEM(0, args) , _test) \
+ /**/
+
+// Thanks to Guillaume Melquiond for pointing out the need for the
+// "substitute" template as an argument to the overloaded test
+// functions to get SFINAE to work for member templates with the
+// correct name but different number of arguments.
+# define BOOST_MPL_HAS_MEMBER_MULTI_SUBSTITUTE(z, n, args) \
+ template< \
+ template< BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n), typename V) > class V \
+ > \
+ struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME(args, n) { \
+ }; \
+ /**/
+
+# define BOOST_MPL_HAS_MEMBER_SUBSTITUTE(args, substitute_macro) \
+ BOOST_PP_REPEAT( \
+ BOOST_PP_ARRAY_ELEM(2, args) \
+ , BOOST_MPL_HAS_MEMBER_MULTI_SUBSTITUTE \
+ , args \
+ ) \
+ /**/
+
+# if !BOOST_MPL_HAS_XXX_NO_EXPLICIT_TEST_FUNCTION
+# define BOOST_MPL_HAS_MEMBER_REJECT(args, member_macro) \
+ template< typename V > \
+ static boost::mpl::aux::no_tag \
+ BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)(...); \
+ /**/
+# else
+# define BOOST_MPL_HAS_MEMBER_REJECT(args, member_macro) \
+ static boost::mpl::aux::no_tag \
+ BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)(...); \
+ /**/
+# endif
+
+# if !BOOST_MPL_HAS_XXX_NO_WRAPPED_TYPES
+# define BOOST_MPL_HAS_MEMBER_MULTI_ACCEPT(z, n, args) \
+ template< typename V > \
+ static boost::mpl::aux::yes_tag \
+ BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)( \
+ boost::mpl::aux::type_wrapper< V > const volatile* \
+ , BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME(args, n) < \
+ V::template BOOST_PP_ARRAY_ELEM(1, args) \
+ >* = 0 \
+ ); \
+ /**/
+# define BOOST_MPL_HAS_MEMBER_ACCEPT(args, member_macro) \
+ BOOST_PP_REPEAT( \
+ BOOST_PP_ARRAY_ELEM(2, args) \
+ , BOOST_MPL_HAS_MEMBER_MULTI_ACCEPT \
+ , args \
+ ) \
+ /**/
+# else
+# define BOOST_MPL_HAS_MEMBER_ACCEPT(args, member_macro) \
+ template< typename V > \
+ static boost::mpl::aux::yes_tag \
+ BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)( \
+ V const volatile* \
+ , member_macro(args, V, T)* = 0 \
+ ); \
+ /**/
+# endif
+
+# if !BOOST_MPL_HAS_XXX_NO_EXPLICIT_TEST_FUNCTION
+# define BOOST_MPL_HAS_MEMBER_TEST(args) \
+ sizeof(BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)< U >(0)) \
+ == sizeof(boost::mpl::aux::yes_tag) \
+ /**/
+# else
+# if !BOOST_MPL_HAS_XXX_NO_WRAPPED_TYPES
+# define BOOST_MPL_HAS_MEMBER_TEST(args) \
+ sizeof( \
+ BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)( \
+ static_cast< boost::mpl::aux::type_wrapper< U >* >(0) \
+ ) \
+ ) == sizeof(boost::mpl::aux::yes_tag) \
+ /**/
+# else
+# define BOOST_MPL_HAS_MEMBER_TEST(args) \
+ sizeof( \
+ BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)( \
+ static_cast< U* >(0) \
+ ) \
+ ) == sizeof(boost::mpl::aux::yes_tag) \
+ /**/
+# endif
+# endif
+
+# define BOOST_MPL_HAS_MEMBER_INTROSPECT( \
+ args, substitute_macro, member_macro \
+ ) \
+ template< typename U > \
+ struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_NAME(args) { \
+ BOOST_MPL_HAS_MEMBER_SUBSTITUTE(args, substitute_macro) \
+ BOOST_MPL_HAS_MEMBER_REJECT(args, member_macro) \
+ BOOST_MPL_HAS_MEMBER_ACCEPT(args, member_macro) \
+ BOOST_STATIC_CONSTANT( \
+ bool, value = BOOST_MPL_HAS_MEMBER_TEST(args) \
+ ); \
+ typedef boost::mpl::bool_< value > type; \
+ }; \
+ /**/
+
+# define BOOST_MPL_HAS_MEMBER_IMPLEMENTATION( \
+ args, introspect_macro, substitute_macro, member_macro \
+ ) \
+ template< \
+ typename T \
+ , typename fallback_ \
+ = boost::mpl::bool_< BOOST_PP_ARRAY_ELEM(3, args) > \
+ > \
+ class BOOST_PP_ARRAY_ELEM(0, args) { \
+ introspect_macro(args, substitute_macro, member_macro) \
+ public: \
+ static const bool value \
+ = BOOST_MPL_HAS_MEMBER_INTROSPECTION_NAME(args)< T >::value; \
+ typedef typename BOOST_MPL_HAS_MEMBER_INTROSPECTION_NAME(args)< \
+ T \
+ >::type type; \
+ }; \
+ /**/
+
+// BOOST_MPL_HAS_MEMBER_WITH_FUNCTION_SFINAE expands to the full
+// implementation of the function-based metafunction. Compile with -E
+// to see the preprocessor output for this macro.
+# define BOOST_MPL_HAS_MEMBER_WITH_FUNCTION_SFINAE( \
+ args, substitute_macro, member_macro \
+ ) \
+ BOOST_MPL_HAS_MEMBER_IMPLEMENTATION( \
+ args \
+ , BOOST_MPL_HAS_MEMBER_INTROSPECT \
+ , substitute_macro \
+ , member_macro \
+ ) \
+ /**/
+
+# if BOOST_MPL_HAS_XXX_NEEDS_TEMPLATE_SFINAE
+
+# if !defined(BOOST_MPL_HAS_XXX_NEEDS_NAMESPACE_LEVEL_SUBSTITUTE)
+# if BOOST_WORKAROUND(BOOST_MSVC, <= 1400)
+# define BOOST_MPL_HAS_XXX_NEEDS_NAMESPACE_LEVEL_SUBSTITUTE 1
+# endif
+# endif
+
+# if !BOOST_MPL_HAS_XXX_NEEDS_NAMESPACE_LEVEL_SUBSTITUTE
+# define BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME_WITH_TEMPLATE_SFINAE( \
+ args, n \
+ ) \
+ BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME(args, n) \
+ /**/
+# else
+# define BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME_WITH_TEMPLATE_SFINAE( \
+ args, n \
+ ) \
+ BOOST_PP_CAT( \
+ boost_mpl_has_xxx_ \
+ , BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME(args, n) \
+ ) \
+ /**/
+# endif
+
+# define BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_TAG_NAME( \
+ args \
+ ) \
+ BOOST_PP_CAT( \
+ BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME_WITH_TEMPLATE_SFINAE( \
+ args, 0 \
+ ) \
+ , _tag \
+ ) \
+ /**/
+
+# define BOOST_MPL_HAS_MEMBER_MULTI_SUBSTITUTE_WITH_TEMPLATE_SFINAE( \
+ z, n, args \
+ ) \
+ template< \
+ template< BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n), typename U) > class U \
+ > \
+ struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME_WITH_TEMPLATE_SFINAE( \
+ args, n \
+ ) { \
+ typedef \
+ BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_TAG_NAME(args) \
+ type; \
+ }; \
+ /**/
+
+# define BOOST_MPL_HAS_MEMBER_SUBSTITUTE_WITH_TEMPLATE_SFINAE( \
+ args, substitute_macro \
+ ) \
+ typedef void \
+ BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_TAG_NAME(args); \
+ BOOST_PP_REPEAT( \
+ BOOST_PP_ARRAY_ELEM(2, args) \
+ , BOOST_MPL_HAS_MEMBER_MULTI_SUBSTITUTE_WITH_TEMPLATE_SFINAE \
+ , args \
+ ) \
+ /**/
+
+# define BOOST_MPL_HAS_MEMBER_REJECT_WITH_TEMPLATE_SFINAE( \
+ args, member_macro \
+ ) \
+ template< \
+ typename U \
+ , typename V \
+ = BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_TAG_NAME(args) \
+ > \
+ struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args) { \
+ BOOST_STATIC_CONSTANT(bool, value = false); \
+ typedef boost::mpl::bool_< value > type; \
+ }; \
+ /**/
+
+# define BOOST_MPL_HAS_MEMBER_MULTI_ACCEPT_WITH_TEMPLATE_SFINAE( \
+ z, n, args \
+ ) \
+ template< typename U > \
+ struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)< \
+ U \
+ , typename \
+ BOOST_MPL_HAS_MEMBER_INTROSPECTION_SUBSTITUTE_NAME_WITH_TEMPLATE_SFINAE( \
+ args, n \
+ )< \
+ BOOST_MSVC_TYPENAME U::BOOST_PP_ARRAY_ELEM(1, args)< > \
+ >::type \
+ > { \
+ BOOST_STATIC_CONSTANT(bool, value = true); \
+ typedef boost::mpl::bool_< value > type; \
+ }; \
+ /**/
+
+# define BOOST_MPL_HAS_MEMBER_ACCEPT_WITH_TEMPLATE_SFINAE( \
+ args, member_macro \
+ ) \
+ BOOST_PP_REPEAT( \
+ BOOST_PP_ARRAY_ELEM(2, args) \
+ , BOOST_MPL_HAS_MEMBER_MULTI_ACCEPT_WITH_TEMPLATE_SFINAE \
+ , args \
+ ) \
+ /**/
+
+# define BOOST_MPL_HAS_MEMBER_INTROSPECT_WITH_TEMPLATE_SFINAE( \
+ args, substitute_macro, member_macro \
+ ) \
+ BOOST_MPL_HAS_MEMBER_REJECT_WITH_TEMPLATE_SFINAE(args, member_macro) \
+ BOOST_MPL_HAS_MEMBER_ACCEPT_WITH_TEMPLATE_SFINAE(args, member_macro) \
+ template< typename U > \
+ struct BOOST_MPL_HAS_MEMBER_INTROSPECTION_NAME(args) \
+ : BOOST_MPL_HAS_MEMBER_INTROSPECTION_TEST_NAME(args)< U > { \
+ }; \
+ /**/
+
+// BOOST_MPL_HAS_MEMBER_WITH_TEMPLATE_SFINAE expands to the full
+// implementation of the template-based metafunction. Compile with -E
+// to see the preprocessor output for this macro.
+//
+// Note that if BOOST_MPL_HAS_XXX_NEEDS_NAMESPACE_LEVEL_SUBSTITUTE is
+// defined BOOST_MPL_HAS_MEMBER_SUBSTITUTE_WITH_TEMPLATE_SFINAE needs
+// to be expanded at namespace level before
+// BOOST_MPL_HAS_MEMBER_WITH_TEMPLATE_SFINAE can be used.
+# define BOOST_MPL_HAS_MEMBER_WITH_TEMPLATE_SFINAE( \
+ args, substitute_macro, member_macro \
+ ) \
+ BOOST_MPL_HAS_MEMBER_SUBSTITUTE_WITH_TEMPLATE_SFINAE( \
+ args, substitute_macro \
+ ) \
+ BOOST_MPL_HAS_MEMBER_IMPLEMENTATION( \
+ args \
+ , BOOST_MPL_HAS_MEMBER_INTROSPECT_WITH_TEMPLATE_SFINAE \
+ , substitute_macro \
+ , member_macro \
+ ) \
+ /**/
+
+# endif // BOOST_MPL_HAS_XXX_NEEDS_TEMPLATE_SFINAE
+
+// Note: In the current implementation the parameter and access macros
+// are no longer expanded.
+# if !BOOST_WORKAROUND(BOOST_MSVC, <= 1400)
+# define BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF(trait, name, default_) \
+ BOOST_MPL_HAS_MEMBER_WITH_FUNCTION_SFINAE( \
+ ( 4, ( trait, name, BOOST_MPL_LIMIT_METAFUNCTION_ARITY, default_ ) ) \
+ , BOOST_MPL_HAS_MEMBER_TEMPLATE_SUBSTITUTE_PARAMETER \
+ , BOOST_MPL_HAS_MEMBER_TEMPLATE_ACCESS \
+ ) \
+ /**/
+# else
+# define BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF(trait, name, default_) \
+ BOOST_MPL_HAS_MEMBER_WITH_TEMPLATE_SFINAE( \
+ ( 4, ( trait, name, BOOST_MPL_LIMIT_METAFUNCTION_ARITY, default_ ) ) \
+ , BOOST_MPL_HAS_MEMBER_TEMPLATE_SUBSTITUTE_PARAMETER \
+ , BOOST_MPL_HAS_MEMBER_TEMPLATE_ACCESS \
+ ) \
+ /**/
+# endif
+
+#else // BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE
+
+// placeholder implementation
+
+# define BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF(trait, name, default_) \
+ template< typename T \
+ , typename fallback_ = boost::mpl::bool_< default_ > > \
+ struct trait { \
+ BOOST_STATIC_CONSTANT(bool, value = fallback_::value); \
+ typedef fallback_ type; \
+ }; \
+ /**/
+
+#endif // BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE
+
+# define BOOST_MPL_HAS_XXX_TEMPLATE_DEF(name) \
+ BOOST_MPL_HAS_XXX_TEMPLATE_NAMED_DEF( \
+ BOOST_PP_CAT(has_, name), name, false \
+ ) \
+ /**/
+
+#endif // BOOST_MPL_HAS_XXX_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/identity.hpp b/third_party/boost/boost/mpl/identity.hpp
new file mode 100644
index 0000000..021cbf4
--- /dev/null
+++ b/third_party/boost/boost/mpl/identity.hpp
@@ -0,0 +1,45 @@
+
+#ifndef BOOST_MPL_IDENTITY_HPP_INCLUDED
+#define BOOST_MPL_IDENTITY_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+
+namespace boost { namespace mpl {
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(T)
+ >
+struct identity
+{
+ typedef T type;
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1, identity, (T))
+};
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(T)
+ >
+struct make_identity
+{
+ typedef identity<T> type;
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1, make_identity, (T))
+};
+
+BOOST_MPL_AUX_NA_SPEC_NO_ETI(1, identity)
+BOOST_MPL_AUX_NA_SPEC_NO_ETI(1, make_identity)
+
+}}
+
+#endif // BOOST_MPL_IDENTITY_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/if.hpp b/third_party/boost/boost/mpl/if.hpp
new file mode 100644
index 0000000..d448c7f
--- /dev/null
+++ b/third_party/boost/boost/mpl/if.hpp
@@ -0,0 +1,135 @@
+
+#ifndef BOOST_MPL_IF_HPP_INCLUDED
+#define BOOST_MPL_IF_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/value_wknd.hpp>
+#include <boost/mpl/aux_/static_cast.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+#include <boost/mpl/aux_/config/integral.hpp>
+#include <boost/mpl/aux_/config/ctps.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+namespace boost { namespace mpl {
+
+#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+
+template<
+ bool C
+ , typename T1
+ , typename T2
+ >
+struct if_c
+{
+ typedef T1 type;
+};
+
+template<
+ typename T1
+ , typename T2
+ >
+struct if_c<false,T1,T2>
+{
+ typedef T2 type;
+};
+
+// agurt, 05/sep/04: nondescriptive parameter names for the sake of DigitalMars
+// (and possibly MWCW < 8.0); see http://article.gmane.org/gmane.comp.lib.boost.devel/108959
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(T1)
+ , typename BOOST_MPL_AUX_NA_PARAM(T2)
+ , typename BOOST_MPL_AUX_NA_PARAM(T3)
+ >
+struct if_
+{
+ private:
+ // agurt, 02/jan/03: two-step 'type' definition for the sake of aCC
+ typedef if_c<
+#if defined(BOOST_MPL_CFG_BCC_INTEGRAL_CONSTANTS)
+ BOOST_MPL_AUX_VALUE_WKND(T1)::value
+#else
+ BOOST_MPL_AUX_STATIC_CAST(bool, BOOST_MPL_AUX_VALUE_WKND(T1)::value)
+#endif
+ , T2
+ , T3
+ > almost_type_;
+
+ public:
+ typedef typename almost_type_::type type;
+
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(3,if_,(T1,T2,T3))
+};
+
+#else
+
+// no partial class template specialization
+
+namespace aux {
+
+template< bool C >
+struct if_impl
+{
+ template< typename T1, typename T2 > struct result_
+ {
+ typedef T1 type;
+ };
+};
+
+template<>
+struct if_impl<false>
+{
+ template< typename T1, typename T2 > struct result_
+ {
+ typedef T2 type;
+ };
+};
+
+} // namespace aux
+
+template<
+ bool C_
+ , typename T1
+ , typename T2
+ >
+struct if_c
+{
+ typedef typename aux::if_impl< C_ >
+ ::template result_<T1,T2>::type type;
+};
+
+// (almost) copy & paste in order to save one more
+// recursively nested template instantiation to user
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(C_)
+ , typename BOOST_MPL_AUX_NA_PARAM(T1)
+ , typename BOOST_MPL_AUX_NA_PARAM(T2)
+ >
+struct if_
+{
+ enum { msvc_wknd_ = BOOST_MPL_AUX_MSVC_VALUE_WKND(C_)::value };
+
+ typedef typename aux::if_impl< BOOST_MPL_AUX_STATIC_CAST(bool, msvc_wknd_) >
+ ::template result_<T1,T2>::type type;
+
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(3,if_,(C_,T1,T2))
+};
+
+#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+
+BOOST_MPL_AUX_NA_SPEC(3, if_)
+
+}}
+
+#endif // BOOST_MPL_IF_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/inserter.hpp b/third_party/boost/boost/mpl/inserter.hpp
new file mode 100644
index 0000000..44ffea6
--- /dev/null
+++ b/third_party/boost/boost/mpl/inserter.hpp
@@ -0,0 +1,32 @@
+
+#ifndef BOOST_MPL_INSERTER_HPP_INCLUDED
+#define BOOST_MPL_INSERTER_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2003-2004
+// Copyright David Abrahams 2003-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+namespace boost { namespace mpl {
+
+template<
+ typename Sequence
+ , typename Operation
+ >
+struct inserter
+{
+ typedef Sequence state;
+ typedef Operation operation;
+};
+
+}}
+
+#endif // BOOST_MPL_INSERTER_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/int.hpp b/third_party/boost/boost/mpl/int.hpp
new file mode 100644
index 0000000..08d6aa1
--- /dev/null
+++ b/third_party/boost/boost/mpl/int.hpp
@@ -0,0 +1,22 @@
+
+#ifndef BOOST_MPL_INT_HPP_INCLUDED
+#define BOOST_MPL_INT_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/int_fwd.hpp>
+
+#define AUX_WRAPPER_VALUE_TYPE int
+#include <boost/mpl/aux_/integral_wrapper.hpp>
+
+#endif // BOOST_MPL_INT_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/int_fwd.hpp b/third_party/boost/boost/mpl/int_fwd.hpp
new file mode 100644
index 0000000..2ae34d6
--- /dev/null
+++ b/third_party/boost/boost/mpl/int_fwd.hpp
@@ -0,0 +1,27 @@
+
+#ifndef BOOST_MPL_INT_FWD_HPP_INCLUDED
+#define BOOST_MPL_INT_FWD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/adl_barrier.hpp>
+#include <boost/mpl/aux_/nttp_decl.hpp>
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+
+template< BOOST_MPL_AUX_NTTP_DECL(int, N) > struct int_;
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+BOOST_MPL_AUX_ADL_BARRIER_DECL(int_)
+
+#endif // BOOST_MPL_INT_FWD_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/integral_c.hpp b/third_party/boost/boost/mpl/integral_c.hpp
new file mode 100644
index 0000000..f2a0132
--- /dev/null
+++ b/third_party/boost/boost/mpl/integral_c.hpp
@@ -0,0 +1,51 @@
+
+#ifndef BOOST_MPL_INTEGRAL_C_HPP_INCLUDED
+#define BOOST_MPL_INTEGRAL_C_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2006
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/integral_c_fwd.hpp>
+#include <boost/mpl/aux_/config/ctps.hpp>
+#include <boost/mpl/aux_/config/static_constant.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+#if BOOST_WORKAROUND(__HP_aCC, <= 53800)
+// the type of non-type template arguments may not depend on template arguments
+# define AUX_WRAPPER_PARAMS(N) typename T, long N
+#else
+# define AUX_WRAPPER_PARAMS(N) typename T, T N
+#endif
+
+#define AUX_WRAPPER_NAME integral_c
+#define AUX_WRAPPER_VALUE_TYPE T
+#define AUX_WRAPPER_INST(value) AUX_WRAPPER_NAME< T, value >
+#include <boost/mpl/aux_/integral_wrapper.hpp>
+
+
+#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
+ && !BOOST_WORKAROUND(__BORLANDC__, <= 0x551)
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+// 'bool' constant doesn't have 'next'/'prior' members
+template< bool C >
+struct integral_c<bool, C>
+{
+ BOOST_STATIC_CONSTANT(bool, value = C);
+ typedef integral_c_tag tag;
+ typedef integral_c type;
+ typedef bool value_type;
+ operator bool() const { return this->value; }
+};
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+#endif
+
+#endif // BOOST_MPL_INTEGRAL_C_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/integral_c_fwd.hpp b/third_party/boost/boost/mpl/integral_c_fwd.hpp
new file mode 100644
index 0000000..c0e286f
--- /dev/null
+++ b/third_party/boost/boost/mpl/integral_c_fwd.hpp
@@ -0,0 +1,32 @@
+
+#ifndef BOOST_MPL_INTEGRAL_C_FWD_HPP_INCLUDED
+#define BOOST_MPL_INTEGRAL_C_FWD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2006
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/workaround.hpp>
+#include <boost/mpl/aux_/adl_barrier.hpp>
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+
+#if BOOST_WORKAROUND(__HP_aCC, <= 53800)
+// the type of non-type template arguments may not depend on template arguments
+template< typename T, long N > struct integral_c;
+#else
+template< typename T, T N > struct integral_c;
+#endif
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+BOOST_MPL_AUX_ADL_BARRIER_DECL(integral_c)
+
+#endif // BOOST_MPL_INTEGRAL_C_FWD_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/integral_c_tag.hpp b/third_party/boost/boost/mpl/integral_c_tag.hpp
new file mode 100644
index 0000000..afef345
--- /dev/null
+++ b/third_party/boost/boost/mpl/integral_c_tag.hpp
@@ -0,0 +1,26 @@
+
+#ifndef BOOST_MPL_INTEGRAL_C_TAG_HPP_INCLUDED
+#define BOOST_MPL_INTEGRAL_C_TAG_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+
+#include <boost/mpl/aux_/adl_barrier.hpp>
+#include <boost/mpl/aux_/config/static_constant.hpp>
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+struct integral_c_tag { BOOST_STATIC_CONSTANT(int, value = 0); };
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+BOOST_MPL_AUX_ADL_BARRIER_DECL(integral_c_tag)
+
+#endif // BOOST_MPL_INTEGRAL_C_TAG_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/is_sequence.hpp b/third_party/boost/boost/mpl/is_sequence.hpp
new file mode 100644
index 0000000..65f6122
--- /dev/null
+++ b/third_party/boost/boost/mpl/is_sequence.hpp
@@ -0,0 +1,112 @@
+
+#ifndef BOOST_MPL_IS_SEQUENCE_HPP_INCLUDED
+#define BOOST_MPL_IS_SEQUENCE_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 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/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/not.hpp>
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/begin_end.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/sequence_tag_fwd.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/mpl/void.hpp>
+#include <boost/mpl/aux_/has_tag.hpp>
+#include <boost/mpl/aux_/has_begin.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+#include <boost/mpl/aux_/config/eti.hpp>
+#include <boost/mpl/aux_/config/msvc.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+# include <boost/mpl/aux_/msvc_is_class.hpp>
+#elif BOOST_WORKAROUND(BOOST_MSVC, == 1300)
+# include <boost/type_traits/is_class.hpp>
+#endif
+
+#include <boost/type_traits/is_same.hpp>
+
+namespace boost { namespace mpl {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
+
+namespace aux {
+
+// agurt, 11/jun/03:
+// MSVC 6.5/7.0 fails if 'has_begin' is instantiated on a class type that has a
+// 'begin' member that doesn't name a type; e.g. 'has_begin< std::vector<int> >'
+// would fail; requiring 'T' to have _both_ 'tag' and 'begin' members workarounds
+// the issue for most real-world cases
+template< typename T > struct is_sequence_impl
+ : and_<
+ identity< aux::has_tag<T> >
+ , identity< aux::has_begin<T> >
+ >
+{
+};
+
+} // namespace aux
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(T)
+ >
+struct is_sequence
+ : if_<
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+ aux::msvc_is_class<T>
+#else
+ boost::is_class<T>
+#endif
+ , aux::is_sequence_impl<T>
+ , bool_<false>
+ >::type
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1, is_sequence, (T))
+};
+
+#elif defined(BOOST_MPL_CFG_NO_HAS_XXX)
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(T)
+ >
+struct is_sequence
+ : bool_<false>
+{
+};
+
+#else
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(T)
+ >
+struct is_sequence
+ : not_< is_same< typename begin<T>::type, void_ > >
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1, is_sequence, (T))
+};
+
+#endif // BOOST_MSVC
+
+#if defined(BOOST_MPL_CFG_MSVC_60_ETI_BUG)
+template<> struct is_sequence<int>
+ : bool_<false>
+{
+};
+#endif
+
+BOOST_MPL_AUX_NA_SPEC_NO_ETI(1, is_sequence)
+
+}}
+
+#endif // BOOST_MPL_IS_SEQUENCE_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/iter_fold.hpp b/third_party/boost/boost/mpl/iter_fold.hpp
new file mode 100644
index 0000000..f09c00f
--- /dev/null
+++ b/third_party/boost/boost/mpl/iter_fold.hpp
@@ -0,0 +1,49 @@
+
+#ifndef BOOST_MPL_ITER_FOLD_HPP_INCLUDED
+#define BOOST_MPL_ITER_FOLD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+// Copyright David Abrahams 2001-2002
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/begin_end.hpp>
+#include <boost/mpl/O1_size.hpp>
+#include <boost/mpl/lambda.hpp>
+#include <boost/mpl/aux_/iter_fold_impl.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+
+namespace boost { namespace mpl {
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(Sequence)
+ , typename BOOST_MPL_AUX_NA_PARAM(State)
+ , typename BOOST_MPL_AUX_NA_PARAM(ForwardOp)
+ >
+struct iter_fold
+{
+ typedef typename aux::iter_fold_impl<
+ ::boost::mpl::O1_size<Sequence>::value
+ , typename begin<Sequence>::type
+ , typename end<Sequence>::type
+ , State
+ , typename lambda<ForwardOp>::type
+ >::state type;
+
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(3,iter_fold,(Sequence,State,ForwardOp))
+};
+
+BOOST_MPL_AUX_NA_SPEC(3, iter_fold)
+
+}}
+
+#endif // BOOST_MPL_ITER_FOLD_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/iter_fold_if.hpp b/third_party/boost/boost/mpl/iter_fold_if.hpp
new file mode 100644
index 0000000..0fa8165
--- /dev/null
+++ b/third_party/boost/boost/mpl/iter_fold_if.hpp
@@ -0,0 +1,117 @@
+
+#ifndef BOOST_MPL_ITER_FOLD_IF_HPP_INCLUDED
+#define BOOST_MPL_ITER_FOLD_IF_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2003-2004
+// Copyright Eric Friedman 2003
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/begin_end.hpp>
+#include <boost/mpl/logical.hpp>
+#include <boost/mpl/always.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/pair.hpp>
+#include <boost/mpl/apply.hpp>
+#include <boost/mpl/aux_/iter_fold_if_impl.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+#include <boost/mpl/aux_/config/forwarding.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+#include <boost/type_traits/is_same.hpp>
+
+namespace boost { namespace mpl {
+
+namespace aux {
+
+template< typename Predicate, typename LastIterator >
+struct iter_fold_if_pred
+{
+ template< typename State, typename Iterator > struct apply
+#if !defined(BOOST_MPL_CFG_NO_NESTED_FORWARDING)
+ : and_<
+ not_< is_same<Iterator,LastIterator> >
+ , apply1<Predicate,Iterator>
+ >
+ {
+#else
+ {
+ typedef and_<
+ not_< is_same<Iterator,LastIterator> >
+ , apply1<Predicate,Iterator>
+ > type;
+#endif
+ };
+};
+
+} // namespace aux
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(Sequence)
+ , typename BOOST_MPL_AUX_NA_PARAM(State)
+ , typename BOOST_MPL_AUX_NA_PARAM(ForwardOp)
+ , typename BOOST_MPL_AUX_NA_PARAM(ForwardPredicate)
+ , typename BOOST_MPL_AUX_NA_PARAM(BackwardOp)
+ , typename BOOST_MPL_AUX_NA_PARAM(BackwardPredicate)
+ >
+struct iter_fold_if
+{
+
+ typedef typename begin<Sequence>::type first_;
+ typedef typename end<Sequence>::type last_;
+
+ typedef typename eval_if<
+ is_na<BackwardPredicate>
+ , if_< is_na<BackwardOp>, always<false_>, always<true_> >
+ , identity<BackwardPredicate>
+ >::type backward_pred_;
+
+// cwpro8 doesn't like 'cut-off' type here (use typedef instead)
+#if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) && !BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600))
+ struct result_ :
+#else
+ typedef
+#endif
+ aux::iter_fold_if_impl<
+ first_
+ , State
+ , ForwardOp
+ , protect< aux::iter_fold_if_pred< ForwardPredicate,last_ > >
+ , BackwardOp
+ , backward_pred_
+ >
+#if !BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) && !BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600))
+ { };
+#else
+ result_;
+#endif
+
+public:
+
+ typedef pair<
+ typename result_::state
+ , typename result_::iterator
+ > type;
+
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(
+ 6
+ , iter_fold_if
+ , (Sequence,State,ForwardOp,ForwardPredicate,BackwardOp,BackwardPredicate)
+ )
+};
+
+BOOST_MPL_AUX_NA_SPEC(6, iter_fold_if)
+
+}}
+
+#endif // BOOST_MPL_ITER_FOLD_IF_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/iterator_category.hpp b/third_party/boost/boost/mpl/iterator_category.hpp
new file mode 100644
index 0000000..34a7cda
--- /dev/null
+++ b/third_party/boost/boost/mpl/iterator_category.hpp
@@ -0,0 +1,35 @@
+
+#ifndef BOOST_MPL_ITERATOR_CATEGORY_HPP_INCLUDED
+#define BOOST_MPL_ITERATOR_CATEGORY_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+
+namespace boost { namespace mpl {
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(Iterator)
+ >
+struct iterator_category
+{
+ typedef typename Iterator::category type;
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1,iterator_category,(Iterator))
+};
+
+BOOST_MPL_AUX_NA_SPEC(1, iterator_category)
+
+}}
+
+#endif // BOOST_MPL_ITERATOR_CATEGORY_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/iterator_range.hpp b/third_party/boost/boost/mpl/iterator_range.hpp
new file mode 100644
index 0000000..3ec1ab8
--- /dev/null
+++ b/third_party/boost/boost/mpl/iterator_range.hpp
@@ -0,0 +1,42 @@
+
+#ifndef BOOST_MPL_ITERATOR_RANGE_HPP_INCLUDED
+#define BOOST_MPL_ITERATOR_RANGE_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+
+namespace boost { namespace mpl {
+
+struct iterator_range_tag;
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(First)
+ , typename BOOST_MPL_AUX_NA_PARAM(Last)
+ >
+struct iterator_range
+{
+ typedef iterator_range_tag tag;
+ typedef iterator_range type;
+ typedef First begin;
+ typedef Last end;
+
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(2,iterator_range,(First,Last))
+};
+
+BOOST_MPL_AUX_NA_SPEC(2, iterator_range)
+
+}}
+
+#endif // BOOST_MPL_ITERATOR_RANGE_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/iterator_tags.hpp b/third_party/boost/boost/mpl/iterator_tags.hpp
new file mode 100644
index 0000000..a5e2f6b
--- /dev/null
+++ b/third_party/boost/boost/mpl/iterator_tags.hpp
@@ -0,0 +1,27 @@
+
+#ifndef BOOST_MPL_ITERATOR_TAG_HPP_INCLUDED
+#define BOOST_MPL_ITERATOR_TAG_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/int.hpp>
+
+namespace boost { namespace mpl {
+
+struct forward_iterator_tag : int_<0> { typedef forward_iterator_tag type; };
+struct bidirectional_iterator_tag : int_<1> { typedef bidirectional_iterator_tag type; };
+struct random_access_iterator_tag : int_<2> { typedef random_access_iterator_tag type; };
+
+}}
+
+#endif // BOOST_MPL_ITERATOR_TAG_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/lambda.hpp b/third_party/boost/boost/mpl/lambda.hpp
new file mode 100644
index 0000000..15e51e7
--- /dev/null
+++ b/third_party/boost/boost/mpl/lambda.hpp
@@ -0,0 +1,29 @@
+
+#ifndef BOOST_MPL_LAMBDA_HPP_INCLUDED
+#define BOOST_MPL_LAMBDA_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/lambda_fwd.hpp>
+#include <boost/mpl/bind.hpp>
+#include <boost/mpl/aux_/config/lambda.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT)
+# include <boost/mpl/aux_/full_lambda.hpp>
+#else
+# include <boost/mpl/aux_/lambda_no_ctps.hpp>
+# include <boost/mpl/aux_/lambda_support.hpp>
+# define BOOST_MPL_CFG_NO_IMPLICIT_METAFUNCTIONS
+#endif
+
+#endif // BOOST_MPL_LAMBDA_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/lambda_fwd.hpp b/third_party/boost/boost/mpl/lambda_fwd.hpp
new file mode 100644
index 0000000..e70d989
--- /dev/null
+++ b/third_party/boost/boost/mpl/lambda_fwd.hpp
@@ -0,0 +1,57 @@
+
+#ifndef BOOST_MPL_LAMBDA_FWD_HPP_INCLUDED
+#define BOOST_MPL_LAMBDA_FWD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/void_fwd.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/mpl/aux_/config/lambda.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT)
+
+# include <boost/mpl/int.hpp>
+# include <boost/mpl/aux_/lambda_arity_param.hpp>
+# include <boost/mpl/aux_/template_arity_fwd.hpp>
+
+namespace boost { namespace mpl {
+
+template<
+ typename T = na
+ , typename Tag = void_
+ BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(
+ typename Arity = int_< aux::template_arity<T>::value >
+ )
+ >
+struct lambda;
+
+}}
+
+#else // BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT
+
+# include <boost/mpl/bool.hpp>
+
+namespace boost { namespace mpl {
+
+template<
+ typename T = na
+ , typename Tag = void_
+ , typename Protect = true_
+ >
+struct lambda;
+
+}}
+
+#endif
+
+#endif // BOOST_MPL_LAMBDA_FWD_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/less.hpp b/third_party/boost/boost/mpl/less.hpp
new file mode 100644
index 0000000..3f76a38
--- /dev/null
+++ b/third_party/boost/boost/mpl/less.hpp
@@ -0,0 +1,21 @@
+
+#ifndef BOOST_MPL_LESS_HPP_INCLUDED
+#define BOOST_MPL_LESS_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#define AUX778076_OP_NAME less
+#define AUX778076_OP_TOKEN <
+#include <boost/mpl/aux_/comparison_op.hpp>
+
+#endif // BOOST_MPL_LESS_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/limits/arity.hpp b/third_party/boost/boost/mpl/limits/arity.hpp
new file mode 100644
index 0000000..b4a778e
--- /dev/null
+++ b/third_party/boost/boost/mpl/limits/arity.hpp
@@ -0,0 +1,21 @@
+
+#ifndef BOOST_MPL_LIMITS_ARITY_HPP_INCLUDED
+#define BOOST_MPL_LIMITS_ARITY_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_LIMIT_METAFUNCTION_ARITY)
+# define BOOST_MPL_LIMIT_METAFUNCTION_ARITY 5
+#endif
+
+#endif // BOOST_MPL_LIMITS_ARITY_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/limits/list.hpp b/third_party/boost/boost/mpl/limits/list.hpp
new file mode 100644
index 0000000..2ce1b34
--- /dev/null
+++ b/third_party/boost/boost/mpl/limits/list.hpp
@@ -0,0 +1,21 @@
+
+#ifndef BOOST_MPL_LIMITS_LIST_HPP_INCLUDED
+#define BOOST_MPL_LIMITS_LIST_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_LIMIT_LIST_SIZE)
+# define BOOST_MPL_LIMIT_LIST_SIZE 20
+#endif
+
+#endif // BOOST_MPL_LIMITS_LIST_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/list.hpp b/third_party/boost/boost/mpl/list.hpp
new file mode 100644
index 0000000..90940e2
--- /dev/null
+++ b/third_party/boost/boost/mpl/list.hpp
@@ -0,0 +1,57 @@
+
+#ifndef BOOST_MPL_LIST_HPP_INCLUDED
+#define BOOST_MPL_LIST_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_PREPROCESSING_MODE)
+# include <boost/mpl/limits/list.hpp>
+# include <boost/mpl/aux_/na.hpp>
+# include <boost/mpl/aux_/config/preprocessor.hpp>
+
+# include <boost/preprocessor/inc.hpp>
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/stringize.hpp>
+
+#if !defined(BOOST_NEEDS_TOKEN_PASTING_OP_FOR_TOKENS_JUXTAPOSING)
+# define AUX778076_LIST_HEADER \
+ BOOST_PP_CAT(list,BOOST_MPL_LIMIT_LIST_SIZE).hpp \
+ /**/
+#else
+# define AUX778076_LIST_HEADER \
+ BOOST_PP_CAT(list,BOOST_MPL_LIMIT_LIST_SIZE)##.hpp \
+ /**/
+#endif
+
+# include BOOST_PP_STRINGIZE(boost/mpl/list/AUX778076_LIST_HEADER)
+# undef AUX778076_LIST_HEADER
+#endif
+
+#include <boost/mpl/aux_/config/use_preprocessed.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE)
+
+# define BOOST_MPL_PREPROCESSED_HEADER list.hpp
+# include <boost/mpl/aux_/include_preprocessed.hpp>
+
+#else
+
+# include <boost/mpl/limits/list.hpp>
+
+# define AUX778076_SEQUENCE_NAME list
+# define AUX778076_SEQUENCE_LIMIT BOOST_MPL_LIMIT_LIST_SIZE
+# include <boost/mpl/aux_/sequence_wrapper.hpp>
+
+#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#endif // BOOST_MPL_LIST_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/list/aux_/O1_size.hpp b/third_party/boost/boost/mpl/list/aux_/O1_size.hpp
new file mode 100644
index 0000000..9924644
--- /dev/null
+++ b/third_party/boost/boost/mpl/list/aux_/O1_size.hpp
@@ -0,0 +1,33 @@
+
+#ifndef BOOST_MPL_LIST_AUX_O1_SIZE_HPP_INCLUDED
+#define BOOST_MPL_LIST_AUX_O1_SIZE_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/O1_size_fwd.hpp>
+#include <boost/mpl/list/aux_/tag.hpp>
+
+namespace boost { namespace mpl {
+
+template<>
+struct O1_size_impl< aux::list_tag >
+{
+ template< typename List > struct apply
+ : List::size
+ {
+ };
+};
+
+}}
+
+#endif // BOOST_MPL_LIST_AUX_O1_SIZE_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/list/aux_/begin_end.hpp b/third_party/boost/boost/mpl/list/aux_/begin_end.hpp
new file mode 100644
index 0000000..9e4a2e7
--- /dev/null
+++ b/third_party/boost/boost/mpl/list/aux_/begin_end.hpp
@@ -0,0 +1,44 @@
+
+#ifndef BOOST_MPL_LIST_AUX_BEGIN_END_HPP_INCLUDED
+#define BOOST_MPL_LIST_AUX_BEGIN_END_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/begin_end_fwd.hpp>
+#include <boost/mpl/list/aux_/iterator.hpp>
+#include <boost/mpl/list/aux_/tag.hpp>
+#include <boost/mpl/list/aux_/item.hpp>
+
+namespace boost { namespace mpl {
+
+template<>
+struct begin_impl< aux::list_tag >
+{
+ template< typename List > struct apply
+ {
+ typedef l_iter<typename List::type> type;
+ };
+};
+
+template<>
+struct end_impl< aux::list_tag >
+{
+ template< typename > struct apply
+ {
+ typedef l_iter<l_end> type;
+ };
+};
+
+}}
+
+#endif // BOOST_MPL_LIST_AUX_BEGIN_END_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/list/aux_/clear.hpp b/third_party/boost/boost/mpl/list/aux_/clear.hpp
new file mode 100644
index 0000000..563621f
--- /dev/null
+++ b/third_party/boost/boost/mpl/list/aux_/clear.hpp
@@ -0,0 +1,34 @@
+
+#ifndef BOOST_MPL_LIST_AUX_CLEAR_HPP_INCLUDED
+#define BOOST_MPL_LIST_AUX_CLEAR_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/clear_fwd.hpp>
+#include <boost/mpl/list/aux_/item.hpp>
+#include <boost/mpl/list/aux_/tag.hpp>
+
+namespace boost { namespace mpl {
+
+template<>
+struct clear_impl< aux::list_tag >
+{
+ template< typename List > struct apply
+ {
+ typedef l_end type;
+ };
+};
+
+}}
+
+#endif // BOOST_MPL_LIST_AUX_CLEAR_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/list/aux_/empty.hpp b/third_party/boost/boost/mpl/list/aux_/empty.hpp
new file mode 100644
index 0000000..4d4ffef
--- /dev/null
+++ b/third_party/boost/boost/mpl/list/aux_/empty.hpp
@@ -0,0 +1,34 @@
+
+#ifndef BOOST_MPL_LIST_AUX_EMPTY_HPP_INCLUDED
+#define BOOST_MPL_LIST_AUX_EMPTY_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/empty_fwd.hpp>
+#include <boost/mpl/not.hpp>
+#include <boost/mpl/list/aux_/tag.hpp>
+
+namespace boost { namespace mpl {
+
+template<>
+struct empty_impl< aux::list_tag >
+{
+ template< typename List > struct apply
+ : not_<typename List::size>
+ {
+ };
+};
+
+}}
+
+#endif // BOOST_MPL_LIST_AUX_EMPTY_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/list/aux_/front.hpp b/third_party/boost/boost/mpl/list/aux_/front.hpp
new file mode 100644
index 0000000..134a6fa
--- /dev/null
+++ b/third_party/boost/boost/mpl/list/aux_/front.hpp
@@ -0,0 +1,33 @@
+
+#ifndef BOOST_MPL_LIST_AUX_FRONT_HPP_INCLUDED
+#define BOOST_MPL_LIST_AUX_FRONT_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/front_fwd.hpp>
+#include <boost/mpl/list/aux_/tag.hpp>
+
+namespace boost { namespace mpl {
+
+template<>
+struct front_impl< aux::list_tag >
+{
+ template< typename List > struct apply
+ {
+ typedef typename List::item type;
+ };
+};
+
+}}
+
+#endif // BOOST_MPL_LIST_AUX_FRONT_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/list/aux_/include_preprocessed.hpp b/third_party/boost/boost/mpl/list/aux_/include_preprocessed.hpp
new file mode 100644
index 0000000..e95bff2
--- /dev/null
+++ b/third_party/boost/boost/mpl/list/aux_/include_preprocessed.hpp
@@ -0,0 +1,35 @@
+
+// Copyright Aleksey Gurtovoy 2001-2006
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+// NO INCLUDE GUARDS, THE HEADER IS INTENDED FOR MULTIPLE INCLUSION!
+
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/stringize.hpp>
+
+# define AUX778076_HEADER \
+ aux_/preprocessed/plain/BOOST_MPL_PREPROCESSED_HEADER \
+/**/
+
+#if BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(700))
+# define AUX778076_INCLUDE_STRING BOOST_PP_STRINGIZE(boost/mpl/list/AUX778076_HEADER)
+# include AUX778076_INCLUDE_STRING
+# undef AUX778076_INCLUDE_STRING
+#else
+# include BOOST_PP_STRINGIZE(boost/mpl/list/AUX778076_HEADER)
+#endif
+
+# undef AUX778076_HEADER
+
+#undef BOOST_MPL_PREPROCESSED_HEADER
diff --git a/third_party/boost/boost/mpl/list/aux_/item.hpp b/third_party/boost/boost/mpl/list/aux_/item.hpp
new file mode 100644
index 0000000..68e4295
--- /dev/null
+++ b/third_party/boost/boost/mpl/list/aux_/item.hpp
@@ -0,0 +1,55 @@
+
+#ifndef BOOST_MPL_LIST_AUX_NODE_HPP_INCLUDED
+#define BOOST_MPL_LIST_AUX_NODE_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/long.hpp>
+#include <boost/mpl/list/aux_/tag.hpp>
+#include <boost/mpl/aux_/config/msvc.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+namespace boost { namespace mpl {
+
+template<
+ typename Size
+ , typename T
+ , typename Next
+ >
+struct l_item
+{
+// agurt, 17/jul/03: to facilitate the deficient 'is_sequence' implementation
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
+ typedef int begin;
+#endif
+ typedef aux::list_tag tag;
+ typedef l_item type;
+
+ typedef Size size;
+ typedef T item;
+ typedef Next next;
+};
+
+struct l_end
+{
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
+ typedef int begin;
+#endif
+ typedef aux::list_tag tag;
+ typedef l_end type;
+ typedef long_<0> size;
+};
+
+}}
+
+#endif // BOOST_MPL_LIST_AUX_NODE_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/list/aux_/iterator.hpp b/third_party/boost/boost/mpl/list/aux_/iterator.hpp
new file mode 100644
index 0000000..5aaa1a1
--- /dev/null
+++ b/third_party/boost/boost/mpl/list/aux_/iterator.hpp
@@ -0,0 +1,76 @@
+
+#ifndef BOOST_MPL_LIST_AUX_ITERATOR_HPP_INCLUDED
+#define BOOST_MPL_LIST_AUX_ITERATOR_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/iterator_tags.hpp>
+#include <boost/mpl/next_prior.hpp>
+#include <boost/mpl/deref.hpp>
+#include <boost/mpl/list/aux_/item.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/mpl/aux_/lambda_spec.hpp>
+#include <boost/mpl/aux_/config/ctps.hpp>
+
+namespace boost { namespace mpl {
+
+#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+
+template< typename Node >
+struct l_iter
+{
+ typedef aux::l_iter_tag tag;
+ typedef forward_iterator_tag category;
+};
+
+template< typename Node >
+struct deref< l_iter<Node> >
+{
+ typedef typename Node::item type;
+};
+
+template< typename Node >
+struct next< l_iter<Node> >
+{
+ typedef l_iter< typename Node::next > type;
+};
+
+#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+
+template< typename Node >
+struct l_iter
+{
+ typedef aux::l_iter_tag tag;
+ typedef forward_iterator_tag category;
+ typedef typename Node::item type;
+ typedef l_iter< typename mpl::next<Node>::type > next;
+};
+
+#endif
+
+
+template<> struct l_iter<l_end>
+{
+ typedef aux::l_iter_tag tag;
+ typedef forward_iterator_tag category;
+#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+ typedef na type;
+ typedef l_iter next;
+#endif
+};
+
+BOOST_MPL_AUX_PASS_THROUGH_LAMBDA_SPEC(1, l_iter)
+
+}}
+
+#endif // BOOST_MPL_LIST_AUX_ITERATOR_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/list/aux_/pop_front.hpp b/third_party/boost/boost/mpl/list/aux_/pop_front.hpp
new file mode 100644
index 0000000..c01b26c
--- /dev/null
+++ b/third_party/boost/boost/mpl/list/aux_/pop_front.hpp
@@ -0,0 +1,34 @@
+
+#ifndef BOOST_MPL_LIST_AUX_POP_FRONT_HPP_INCLUDED
+#define BOOST_MPL_LIST_AUX_POP_FRONT_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/pop_front_fwd.hpp>
+#include <boost/mpl/next_prior.hpp>
+#include <boost/mpl/list/aux_/tag.hpp>
+
+namespace boost { namespace mpl {
+
+template<>
+struct pop_front_impl< aux::list_tag >
+{
+ template< typename List > struct apply
+ {
+ typedef typename mpl::next<List>::type type;
+ };
+};
+
+}}
+
+#endif // BOOST_MPL_LIST_AUX_POP_FRONT_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/list/aux_/preprocessed/plain/list10.hpp b/third_party/boost/boost/mpl/list/aux_/preprocessed/plain/list10.hpp
new file mode 100644
index 0000000..795a728
--- /dev/null
+++ b/third_party/boost/boost/mpl/list/aux_/preprocessed/plain/list10.hpp
@@ -0,0 +1,149 @@
+
+// Copyright Aleksey Gurtovoy 2000-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)
+//
+
+// Preprocessed version of "boost/mpl/list/list10.hpp" header
+// -- DO NOT modify by hand!
+
+namespace boost { namespace mpl {
+
+template<
+ typename T0
+ >
+struct list1
+ : l_item<
+ long_<1>
+ , T0
+ , l_end
+ >
+{
+ typedef list1 type;
+};
+
+template<
+ typename T0, typename T1
+ >
+struct list2
+ : l_item<
+ long_<2>
+ , T0
+ , list1<T1>
+ >
+{
+ typedef list2 type;
+};
+
+template<
+ typename T0, typename T1, typename T2
+ >
+struct list3
+ : l_item<
+ long_<3>
+ , T0
+ , list2< T1,T2 >
+ >
+{
+ typedef list3 type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3
+ >
+struct list4
+ : l_item<
+ long_<4>
+ , T0
+ , list3< T1,T2,T3 >
+ >
+{
+ typedef list4 type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ >
+struct list5
+ : l_item<
+ long_<5>
+ , T0
+ , list4< T1,T2,T3,T4 >
+ >
+{
+ typedef list5 type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5
+ >
+struct list6
+ : l_item<
+ long_<6>
+ , T0
+ , list5< T1,T2,T3,T4,T5 >
+ >
+{
+ typedef list6 type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6
+ >
+struct list7
+ : l_item<
+ long_<7>
+ , T0
+ , list6< T1,T2,T3,T4,T5,T6 >
+ >
+{
+ typedef list7 type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7
+ >
+struct list8
+ : l_item<
+ long_<8>
+ , T0
+ , list7< T1,T2,T3,T4,T5,T6,T7 >
+ >
+{
+ typedef list8 type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7, typename T8
+ >
+struct list9
+ : l_item<
+ long_<9>
+ , T0
+ , list8< T1,T2,T3,T4,T5,T6,T7,T8 >
+ >
+{
+ typedef list9 type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7, typename T8, typename T9
+ >
+struct list10
+ : l_item<
+ long_<10>
+ , T0
+ , list9< T1,T2,T3,T4,T5,T6,T7,T8,T9 >
+ >
+{
+ typedef list10 type;
+};
+
+}}
diff --git a/third_party/boost/boost/mpl/list/aux_/preprocessed/plain/list20.hpp b/third_party/boost/boost/mpl/list/aux_/preprocessed/plain/list20.hpp
new file mode 100644
index 0000000..b08ef07
--- /dev/null
+++ b/third_party/boost/boost/mpl/list/aux_/preprocessed/plain/list20.hpp
@@ -0,0 +1,169 @@
+
+// Copyright Aleksey Gurtovoy 2000-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)
+//
+
+// Preprocessed version of "boost/mpl/list/list20.hpp" header
+// -- DO NOT modify by hand!
+
+namespace boost { namespace mpl {
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7, typename T8, typename T9
+ , typename T10
+ >
+struct list11
+ : l_item<
+ long_<11>
+ , T0
+ , list10< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10 >
+ >
+{
+ typedef list11 type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7, typename T8, typename T9
+ , typename T10, typename T11
+ >
+struct list12
+ : l_item<
+ long_<12>
+ , T0
+ , list11< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11 >
+ >
+{
+ typedef list12 type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7, typename T8, typename T9
+ , typename T10, typename T11, typename T12
+ >
+struct list13
+ : l_item<
+ long_<13>
+ , T0
+ , list12< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12 >
+ >
+{
+ typedef list13 type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7, typename T8, typename T9
+ , typename T10, typename T11, typename T12, typename T13
+ >
+struct list14
+ : l_item<
+ long_<14>
+ , T0
+ , list13< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13 >
+ >
+{
+ typedef list14 type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7, typename T8, typename T9
+ , typename T10, typename T11, typename T12, typename T13, typename T14
+ >
+struct list15
+ : l_item<
+ long_<15>
+ , T0
+ , list14< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14 >
+ >
+{
+ typedef list15 type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7, typename T8, typename T9
+ , typename T10, typename T11, typename T12, typename T13, typename T14
+ , typename T15
+ >
+struct list16
+ : l_item<
+ long_<16>
+ , T0
+ , list15< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15 >
+ >
+{
+ typedef list16 type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7, typename T8, typename T9
+ , typename T10, typename T11, typename T12, typename T13, typename T14
+ , typename T15, typename T16
+ >
+struct list17
+ : l_item<
+ long_<17>
+ , T0
+ , list16< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16 >
+ >
+{
+ typedef list17 type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7, typename T8, typename T9
+ , typename T10, typename T11, typename T12, typename T13, typename T14
+ , typename T15, typename T16, typename T17
+ >
+struct list18
+ : l_item<
+ long_<18>
+ , T0
+ , list17< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17 >
+ >
+{
+ typedef list18 type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7, typename T8, typename T9
+ , typename T10, typename T11, typename T12, typename T13, typename T14
+ , typename T15, typename T16, typename T17, typename T18
+ >
+struct list19
+ : l_item<
+ long_<19>
+ , T0
+ , list18< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18 >
+ >
+{
+ typedef list19 type;
+};
+
+template<
+ typename T0, typename T1, typename T2, typename T3, typename T4
+ , typename T5, typename T6, typename T7, typename T8, typename T9
+ , typename T10, typename T11, typename T12, typename T13, typename T14
+ , typename T15, typename T16, typename T17, typename T18, typename T19
+ >
+struct list20
+ : l_item<
+ long_<20>
+ , T0
+ , list19< T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19 >
+ >
+{
+ typedef list20 type;
+};
+
+}}
diff --git a/third_party/boost/boost/mpl/list/aux_/push_back.hpp b/third_party/boost/boost/mpl/list/aux_/push_back.hpp
new file mode 100644
index 0000000..89610ca
--- /dev/null
+++ b/third_party/boost/boost/mpl/list/aux_/push_back.hpp
@@ -0,0 +1,36 @@
+
+#ifndef BOOST_MPL_LIST_AUX_PUSH_BACK_HPP_INCLUDED
+#define BOOST_MPL_LIST_AUX_PUSH_BACK_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/push_back_fwd.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/list/aux_/tag.hpp>
+
+namespace boost { namespace mpl {
+
+template< typename Tag > struct has_push_back_impl;
+
+template<>
+struct has_push_back_impl< aux::list_tag >
+{
+ template< typename Seq > struct apply
+ : false_
+ {
+ };
+};
+
+}}
+
+#endif // BOOST_MPL_LIST_AUX_PUSH_BACK_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/list/aux_/push_front.hpp b/third_party/boost/boost/mpl/list/aux_/push_front.hpp
new file mode 100644
index 0000000..f7d5088
--- /dev/null
+++ b/third_party/boost/boost/mpl/list/aux_/push_front.hpp
@@ -0,0 +1,39 @@
+
+#ifndef BOOST_MPL_LIST_AUX_PUSH_FRONT_HPP_INCLUDED
+#define BOOST_MPL_LIST_AUX_PUSH_FRONT_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/push_front_fwd.hpp>
+#include <boost/mpl/next.hpp>
+#include <boost/mpl/list/aux_/item.hpp>
+#include <boost/mpl/list/aux_/tag.hpp>
+
+namespace boost { namespace mpl {
+
+template<>
+struct push_front_impl< aux::list_tag >
+{
+ template< typename List, typename T > struct apply
+ {
+ typedef l_item<
+ typename next<typename List::size>::type
+ , T
+ , typename List::type
+ > type;
+ };
+};
+
+}}
+
+#endif // BOOST_MPL_LIST_AUX_PUSH_FRONT_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/list/aux_/size.hpp b/third_party/boost/boost/mpl/list/aux_/size.hpp
new file mode 100644
index 0000000..6a85379
--- /dev/null
+++ b/third_party/boost/boost/mpl/list/aux_/size.hpp
@@ -0,0 +1,33 @@
+
+#ifndef BOOST_MPL_LIST_AUX_SIZE_HPP_INCLUDED
+#define BOOST_MPL_LIST_AUX_SIZE_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/size_fwd.hpp>
+#include <boost/mpl/list/aux_/tag.hpp>
+
+namespace boost { namespace mpl {
+
+template<>
+struct size_impl< aux::list_tag >
+{
+ template< typename List > struct apply
+ : List::size
+ {
+ };
+};
+
+}}
+
+#endif // BOOST_MPL_LIST_AUX_SIZE_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/list/aux_/tag.hpp b/third_party/boost/boost/mpl/list/aux_/tag.hpp
new file mode 100644
index 0000000..09da2f2
--- /dev/null
+++ b/third_party/boost/boost/mpl/list/aux_/tag.hpp
@@ -0,0 +1,24 @@
+
+#ifndef BOOST_MPL_LIST_AUX_TAG_HPP_INCLUDED
+#define BOOST_MPL_LIST_AUX_TAG_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+namespace boost { namespace mpl { namespace aux {
+
+struct list_tag;
+struct l_iter_tag;
+
+}}}
+
+#endif // BOOST_MPL_LIST_AUX_TAG_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/list/list0.hpp b/third_party/boost/boost/mpl/list/list0.hpp
new file mode 100644
index 0000000..83432c3
--- /dev/null
+++ b/third_party/boost/boost/mpl/list/list0.hpp
@@ -0,0 +1,42 @@
+
+#ifndef BOOST_MPL_LIST_LIST0_HPP_INCLUDED
+#define BOOST_MPL_LIST_LIST0_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/long.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/mpl/list/aux_/push_front.hpp>
+#include <boost/mpl/list/aux_/pop_front.hpp>
+#include <boost/mpl/list/aux_/push_back.hpp>
+#include <boost/mpl/list/aux_/front.hpp>
+#include <boost/mpl/list/aux_/clear.hpp>
+#include <boost/mpl/list/aux_/O1_size.hpp>
+#include <boost/mpl/list/aux_/size.hpp>
+#include <boost/mpl/list/aux_/empty.hpp>
+#include <boost/mpl/list/aux_/begin_end.hpp>
+#include <boost/mpl/list/aux_/item.hpp>
+
+namespace boost { namespace mpl {
+
+template< typename Dummy = na > struct list0;
+
+template<> struct list0<na>
+ : l_end
+{
+ typedef l_end type;
+};
+
+}}
+
+#endif // BOOST_MPL_LIST_LIST0_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/list/list10.hpp b/third_party/boost/boost/mpl/list/list10.hpp
new file mode 100644
index 0000000..857a11c
--- /dev/null
+++ b/third_party/boost/boost/mpl/list/list10.hpp
@@ -0,0 +1,43 @@
+
+#ifndef BOOST_MPL_LIST_LIST10_HPP_INCLUDED
+#define BOOST_MPL_LIST_LIST10_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_PREPROCESSING_MODE)
+# include <boost/mpl/list/list0.hpp>
+#endif
+
+#include <boost/mpl/aux_/config/use_preprocessed.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE)
+
+# define BOOST_MPL_PREPROCESSED_HEADER list10.hpp
+# include <boost/mpl/list/aux_/include_preprocessed.hpp>
+
+#else
+
+# include <boost/preprocessor/iterate.hpp>
+
+namespace boost { namespace mpl {
+
+# define BOOST_PP_ITERATION_PARAMS_1 \
+ (3,(1, 10, <boost/mpl/list/aux_/numbered.hpp>))
+# include BOOST_PP_ITERATE()
+
+}}
+
+#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+
+#endif // BOOST_MPL_LIST_LIST10_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/list/list20.hpp b/third_party/boost/boost/mpl/list/list20.hpp
new file mode 100644
index 0000000..d8dc6b4
--- /dev/null
+++ b/third_party/boost/boost/mpl/list/list20.hpp
@@ -0,0 +1,43 @@
+
+#ifndef BOOST_MPL_LIST_LIST20_HPP_INCLUDED
+#define BOOST_MPL_LIST_LIST20_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_PREPROCESSING_MODE)
+# include <boost/mpl/list/list10.hpp>
+#endif
+
+#include <boost/mpl/aux_/config/use_preprocessed.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE)
+
+# define BOOST_MPL_PREPROCESSED_HEADER list20.hpp
+# include <boost/mpl/list/aux_/include_preprocessed.hpp>
+
+#else
+
+# include <boost/preprocessor/iterate.hpp>
+
+namespace boost { namespace mpl {
+
+# define BOOST_PP_ITERATION_PARAMS_1 \
+ (3,(11, 20, <boost/mpl/list/aux_/numbered.hpp>))
+# include BOOST_PP_ITERATE()
+
+}}
+
+#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+
+#endif // BOOST_MPL_LIST_LIST20_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/logical.hpp b/third_party/boost/boost/mpl/logical.hpp
new file mode 100644
index 0000000..6b48d41
--- /dev/null
+++ b/third_party/boost/boost/mpl/logical.hpp
@@ -0,0 +1,21 @@
+
+#ifndef BOOST_MPL_LOGICAL_HPP_INCLUDED
+#define BOOST_MPL_LOGICAL_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/not.hpp>
+
+#endif // BOOST_MPL_LOGICAL_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/long.hpp b/third_party/boost/boost/mpl/long.hpp
new file mode 100644
index 0000000..10d72da
--- /dev/null
+++ b/third_party/boost/boost/mpl/long.hpp
@@ -0,0 +1,22 @@
+
+#ifndef BOOST_MPL_LONG_HPP_INCLUDED
+#define BOOST_MPL_LONG_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/long_fwd.hpp>
+
+#define AUX_WRAPPER_VALUE_TYPE long
+#include <boost/mpl/aux_/integral_wrapper.hpp>
+
+#endif // BOOST_MPL_LONG_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/long_fwd.hpp b/third_party/boost/boost/mpl/long_fwd.hpp
new file mode 100644
index 0000000..90285c9
--- /dev/null
+++ b/third_party/boost/boost/mpl/long_fwd.hpp
@@ -0,0 +1,27 @@
+
+#ifndef BOOST_MPL_LONG_FWD_HPP_INCLUDED
+#define BOOST_MPL_LONG_FWD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/adl_barrier.hpp>
+#include <boost/mpl/aux_/nttp_decl.hpp>
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+
+template< BOOST_MPL_AUX_NTTP_DECL(long, N) > struct long_;
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+BOOST_MPL_AUX_ADL_BARRIER_DECL(long_)
+
+#endif // BOOST_MPL_LONG_FWD_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/max_element.hpp b/third_party/boost/boost/mpl/max_element.hpp
new file mode 100644
index 0000000..5531c5c
--- /dev/null
+++ b/third_party/boost/boost/mpl/max_element.hpp
@@ -0,0 +1,72 @@
+
+#ifndef BOOST_MPL_MAX_ELEMENT_HPP_INCLUDED
+#define BOOST_MPL_MAX_ELEMENT_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/less.hpp>
+#include <boost/mpl/iter_fold.hpp>
+#include <boost/mpl/begin_end.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/deref.hpp>
+#include <boost/mpl/apply.hpp>
+#include <boost/mpl/aux_/common_name_wknd.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+
+namespace boost { namespace mpl {
+
+BOOST_MPL_AUX_COMMON_NAME_WKND(max_element)
+
+namespace aux {
+
+template< typename Predicate >
+struct select_max
+{
+ template< typename OldIterator, typename Iterator >
+ struct apply
+ {
+ typedef typename apply2<
+ Predicate
+ , typename deref<OldIterator>::type
+ , typename deref<Iterator>::type
+ >::type condition_;
+
+ typedef typename if_<
+ condition_
+ , Iterator
+ , OldIterator
+ >::type type;
+ };
+};
+
+} // namespace aux
+
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(Sequence)
+ , typename Predicate = less<_,_>
+ >
+struct max_element
+ : iter_fold<
+ Sequence
+ , typename begin<Sequence>::type
+ , protect< aux::select_max<Predicate> >
+ >
+{
+};
+
+BOOST_MPL_AUX_NA_SPEC(1, max_element)
+
+}}
+
+#endif // BOOST_MPL_MAX_ELEMENT_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/min_max.hpp b/third_party/boost/boost/mpl/min_max.hpp
new file mode 100644
index 0000000..7b989da
--- /dev/null
+++ b/third_party/boost/boost/mpl/min_max.hpp
@@ -0,0 +1,46 @@
+
+#ifndef BOOST_MPL_MIN_MAX_HPP_INCLUDED
+#define BOOST_MPL_MIN_MAX_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2008
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/less.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+
+namespace boost { namespace mpl {
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(N1)
+ , typename BOOST_MPL_AUX_NA_PARAM(N2)
+ >
+struct min
+ : if_< less<N1,N2>,N1,N2 >
+{
+};
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(N1)
+ , typename BOOST_MPL_AUX_NA_PARAM(N2)
+ >
+struct max
+ : if_< less<N1,N2>,N2,N1 >
+{
+};
+
+BOOST_MPL_AUX_NA_SPEC(2, min)
+BOOST_MPL_AUX_NA_SPEC(2, max)
+
+}}
+
+#endif // BOOST_MPL_MIN_MAX_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/negate.hpp b/third_party/boost/boost/mpl/negate.hpp
new file mode 100644
index 0000000..319f221
--- /dev/null
+++ b/third_party/boost/boost/mpl/negate.hpp
@@ -0,0 +1,81 @@
+
+#ifndef BOOST_MPL_NEGATE_HPP_INCLUDED
+#define BOOST_MPL_NEGATE_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/integral_c.hpp>
+#include <boost/mpl/aux_/msvc_eti_base.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+#include <boost/mpl/aux_/config/eti.hpp>
+#include <boost/mpl/aux_/config/integral.hpp>
+#include <boost/mpl/aux_/config/static_constant.hpp>
+
+namespace boost { namespace mpl {
+
+template< typename Tag > struct negate_impl;
+
+template< typename T > struct negate_tag
+{
+ typedef typename T::tag type;
+};
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(N)
+ >
+struct negate
+#if !defined(BOOST_MPL_CFG_MSVC_ETI_BUG)
+ : negate_impl<
+ typename negate_tag<N>::type
+ >::template apply<N>::type
+#else
+ : aux::msvc_eti_base< typename apply_wrap1<
+ negate_impl< typename negate_tag<N>::type >
+ , N
+ >::type >::type
+#endif
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1, negate, (N))
+};
+
+BOOST_MPL_AUX_NA_SPEC(1, negate)
+
+
+#if defined(BOOST_MPL_CFG_NO_NESTED_VALUE_ARITHMETIC)
+namespace aux {
+template< typename T, T n > struct negate_wknd
+{
+ BOOST_STATIC_CONSTANT(T, value = -n);
+ typedef integral_c<T,value> type;
+};
+}
+#endif
+
+template<>
+struct negate_impl<integral_c_tag>
+{
+#if defined(BOOST_MPL_CFG_NO_NESTED_VALUE_ARITHMETIC)
+ template< typename N > struct apply
+ : aux::negate_wknd< typename N::value_type, N::value >
+#else
+ template< typename N > struct apply
+ : integral_c< typename N::value_type, (-N::value) >
+#endif
+ {
+ };
+};
+
+}}
+
+#endif // BOOST_MPL_NEGATE_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/next.hpp b/third_party/boost/boost/mpl/next.hpp
new file mode 100644
index 0000000..9f3300d
--- /dev/null
+++ b/third_party/boost/boost/mpl/next.hpp
@@ -0,0 +1,19 @@
+
+#ifndef BOOST_MPL_NEXT_HPP_INCLUDED
+#define BOOST_MPL_NEXT_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/next_prior.hpp>
+
+#endif // BOOST_MPL_NEXT_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/next_prior.hpp b/third_party/boost/boost/mpl/next_prior.hpp
new file mode 100644
index 0000000..552c26c
--- /dev/null
+++ b/third_party/boost/boost/mpl/next_prior.hpp
@@ -0,0 +1,49 @@
+
+#ifndef BOOST_MPL_NEXT_PRIOR_HPP_INCLUDED
+#define BOOST_MPL_NEXT_PRIOR_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/common_name_wknd.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+
+namespace boost { namespace mpl {
+
+BOOST_MPL_AUX_COMMON_NAME_WKND(next)
+BOOST_MPL_AUX_COMMON_NAME_WKND(prior)
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(T)
+ >
+struct next
+{
+ typedef typename T::next type;
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1,next,(T))
+};
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(T)
+ >
+struct prior
+{
+ typedef typename T::prior type;
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1,prior,(T))
+};
+
+BOOST_MPL_AUX_NA_SPEC(1, next)
+BOOST_MPL_AUX_NA_SPEC(1, prior)
+
+}}
+
+#endif // BOOST_MPL_NEXT_PRIOR_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/not.hpp b/third_party/boost/boost/mpl/not.hpp
new file mode 100644
index 0000000..8ef0a9e
--- /dev/null
+++ b/third_party/boost/boost/mpl/not.hpp
@@ -0,0 +1,51 @@
+
+#ifndef BOOST_MPL_NOT_HPP_INCLUDED
+#define BOOST_MPL_NOT_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/aux_/nttp_decl.hpp>
+#include <boost/mpl/aux_/nested_type_wknd.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+
+namespace boost { namespace mpl {
+
+namespace aux {
+
+template< BOOST_MPL_AUX_NTTP_DECL(long, C_) > // 'long' is intentional here
+struct not_impl
+ : bool_<!C_>
+{
+};
+
+} // namespace aux
+
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(T)
+ >
+struct not_
+ : aux::not_impl<
+ BOOST_MPL_AUX_NESTED_TYPE_WKND(T)::value
+ >
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1,not_,(T))
+};
+
+BOOST_MPL_AUX_NA_SPEC(1,not_)
+
+}}
+
+#endif // BOOST_MPL_NOT_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/numeric_cast.hpp b/third_party/boost/boost/mpl/numeric_cast.hpp
new file mode 100644
index 0000000..6541470
--- /dev/null
+++ b/third_party/boost/boost/mpl/numeric_cast.hpp
@@ -0,0 +1,41 @@
+
+#ifndef BOOST_MPL_NUMERIC_CAST_HPP_INCLUDED
+#define BOOST_MPL_NUMERIC_CAST_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2003-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/msvc.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+// agurt 21/sep/04: portability macro for the sake of MSVC 6.x-7.0;
+// resolves conflicts with 'boost::numeric_cast' function template.
+// use it in your own code _only_ if you care about compatibility with
+// these outdated compilers!
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570) )
+# define BOOST_MPL_AUX_NUMERIC_CAST numeric_cast_
+#else
+# define BOOST_MPL_AUX_NUMERIC_CAST numeric_cast
+#endif
+
+namespace boost { namespace mpl {
+
+// no default implementation; the definition is needed to make MSVC happy
+
+template< typename SourceTag, typename TargetTag > struct BOOST_MPL_AUX_NUMERIC_CAST
+{
+ template< typename N > struct apply;
+};
+
+}}
+
+#endif // BOOST_MPL_NUMERIC_CAST_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/or.hpp b/third_party/boost/boost/mpl/or.hpp
new file mode 100644
index 0000000..1f1ccba
--- /dev/null
+++ b/third_party/boost/boost/mpl/or.hpp
@@ -0,0 +1,61 @@
+
+#ifndef BOOST_MPL_OR_HPP_INCLUDED
+#define BOOST_MPL_OR_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/config/use_preprocessed.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE)
+
+# include <boost/mpl/bool.hpp>
+# include <boost/mpl/aux_/nested_type_wknd.hpp>
+# include <boost/mpl/aux_/na_spec.hpp>
+# include <boost/mpl/aux_/lambda_support.hpp>
+# include <boost/mpl/aux_/config/msvc.hpp>
+
+// agurt, 19/may/04: workaround a conflict with <iso646.h> header's
+// 'or' and 'and' macros, see http://tinyurl.com/3et69; 'defined(or)'
+// has to be checked in a separate condition, otherwise GCC complains
+// about 'or' being an alternative token
+#if defined(_MSC_VER) && !defined(__clang__)
+#ifndef __GCCXML__
+#if defined(or)
+# pragma push_macro("or")
+# undef or
+# define or(x)
+#endif
+#endif
+#endif
+
+# define BOOST_MPL_PREPROCESSED_HEADER or.hpp
+# include <boost/mpl/aux_/include_preprocessed.hpp>
+
+#if defined(_MSC_VER) && !defined(__clang__)
+#ifndef __GCCXML__
+#if defined(or)
+# pragma pop_macro("or")
+#endif
+#endif
+#endif
+
+#else
+
+# define AUX778076_OP_NAME or_
+# define AUX778076_OP_VALUE1 true
+# define AUX778076_OP_VALUE2 false
+# include <boost/mpl/aux_/logical_op.hpp>
+
+#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#endif // BOOST_MPL_OR_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/pair.hpp b/third_party/boost/boost/mpl/pair.hpp
new file mode 100644
index 0000000..18eca32
--- /dev/null
+++ b/third_party/boost/boost/mpl/pair.hpp
@@ -0,0 +1,70 @@
+
+#ifndef BOOST_MPL_PAIR_HPP_INCLUDED
+#define BOOST_MPL_PAIR_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/msvc_eti_base.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+#include <boost/mpl/aux_/config/eti.hpp>
+
+namespace boost { namespace mpl {
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(T1)
+ , typename BOOST_MPL_AUX_NA_PARAM(T2)
+ >
+struct pair
+{
+ typedef pair type;
+ typedef T1 first;
+ typedef T2 second;
+
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(2,pair,(T1,T2))
+};
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(P)
+ >
+struct first
+{
+#if !defined(BOOST_MPL_CFG_MSVC_70_ETI_BUG)
+ typedef typename P::first type;
+#else
+ typedef typename aux::msvc_eti_base<P>::first type;
+#endif
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1,first,(P))
+};
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(P)
+ >
+struct second
+{
+#if !defined(BOOST_MPL_CFG_MSVC_70_ETI_BUG)
+ typedef typename P::second type;
+#else
+ typedef typename aux::msvc_eti_base<P>::second type;
+#endif
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1,second,(P))
+};
+
+
+BOOST_MPL_AUX_NA_SPEC_NO_ETI(2, pair)
+BOOST_MPL_AUX_NA_SPEC(1, first)
+BOOST_MPL_AUX_NA_SPEC(1, second)
+
+}}
+
+#endif // BOOST_MPL_PAIR_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/pair_view.hpp b/third_party/boost/boost/mpl/pair_view.hpp
new file mode 100644
index 0000000..bf46ca1
--- /dev/null
+++ b/third_party/boost/boost/mpl/pair_view.hpp
@@ -0,0 +1,169 @@
+
+#ifndef BOOST_MPL_PAIR_VIEW_HPP_INCLUDED
+#define BOOST_MPL_PAIR_VIEW_HPP_INCLUDED
+
+// Copyright David Abrahams 2003-2004
+// Copyright Aleksey Gurtovoy 2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/begin_end.hpp>
+#include <boost/mpl/iterator_category.hpp>
+#include <boost/mpl/advance.hpp>
+#include <boost/mpl/distance.hpp>
+#include <boost/mpl/next_prior.hpp>
+#include <boost/mpl/deref.hpp>
+#include <boost/mpl/min_max.hpp>
+#include <boost/mpl/pair.hpp>
+#include <boost/mpl/iterator_tags.hpp>
+#include <boost/mpl/aux_/config/ctps.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+
+namespace boost { namespace mpl {
+
+namespace aux {
+struct pair_iter_tag;
+
+#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+
+template< typename Iter1, typename Iter2, typename Category >
+struct pair_iter;
+
+template< typename Category > struct prior_pair_iter
+{
+ template< typename Iter1, typename Iter2 > struct apply
+ {
+ typedef typename mpl::prior<Iter1>::type i1_;
+ typedef typename mpl::prior<Iter2>::type i2_;
+ typedef pair_iter<i1_,i2_,Category> type;
+ };
+};
+
+template<> struct prior_pair_iter<forward_iterator_tag>
+{
+ template< typename Iter1, typename Iter2 > struct apply
+ {
+ typedef pair_iter<Iter1,Iter2,forward_iterator_tag> type;
+ };
+};
+
+#endif
+}
+
+template<
+ typename Iter1
+ , typename Iter2
+ , typename Category
+ >
+struct pair_iter
+{
+ typedef aux::pair_iter_tag tag;
+ typedef Category category;
+ typedef Iter1 first;
+ typedef Iter2 second;
+
+#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+ typedef pair<
+ typename deref<Iter1>::type
+ , typename deref<Iter2>::type
+ > type;
+
+ typedef typename mpl::next<Iter1>::type i1_;
+ typedef typename mpl::next<Iter2>::type i2_;
+ typedef pair_iter<i1_,i2_,Category> next;
+
+ typedef apply_wrap2< aux::prior_pair_iter<Category>,Iter1,Iter2 >::type prior;
+#endif
+};
+
+
+#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+
+template< typename Iter1, typename Iter2, typename C >
+struct deref< pair_iter<Iter1,Iter2,C> >
+{
+ typedef pair<
+ typename deref<Iter1>::type
+ , typename deref<Iter2>::type
+ > type;
+};
+
+template< typename Iter1, typename Iter2, typename C >
+struct next< pair_iter<Iter1,Iter2,C> >
+{
+ typedef typename mpl::next<Iter1>::type i1_;
+ typedef typename mpl::next<Iter2>::type i2_;
+ typedef pair_iter<i1_,i2_,C> type;
+};
+
+template< typename Iter1, typename Iter2, typename C >
+struct prior< pair_iter<Iter1,Iter2,C> >
+{
+ typedef typename mpl::prior<Iter1>::type i1_;
+ typedef typename mpl::prior<Iter2>::type i2_;
+ typedef pair_iter<i1_,i2_,C> type;
+};
+
+#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+
+
+template<> struct advance_impl<aux::pair_iter_tag>
+{
+ template< typename Iter, typename D > struct apply
+ {
+ typedef typename mpl::advance< typename Iter::first,D >::type i1_;
+ typedef typename mpl::advance< typename Iter::second,D >::type i2_;
+ typedef pair_iter<i1_,i2_,typename Iter::category> type;
+ };
+};
+
+template<> struct distance_impl<aux::pair_iter_tag>
+{
+ template< typename Iter1, typename Iter2 > struct apply
+ {
+ // agurt, 10/nov/04: MSVC 6.5 ICE-s on forwarding
+ typedef typename mpl::distance<
+ typename first<Iter1>::type
+ , typename first<Iter2>::type
+ >::type type;
+ };
+};
+
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(Sequence1)
+ , typename BOOST_MPL_AUX_NA_PARAM(Sequence2)
+ >
+struct pair_view
+{
+ typedef nested_begin_end_tag tag;
+
+ typedef typename begin<Sequence1>::type iter1_;
+ typedef typename begin<Sequence2>::type iter2_;
+ typedef typename min<
+ typename iterator_category<iter1_>::type
+ , typename iterator_category<iter2_>::type
+ >::type category_;
+
+ typedef pair_iter<iter1_,iter2_,category_> begin;
+
+ typedef pair_iter<
+ typename end<Sequence1>::type
+ , typename end<Sequence2>::type
+ , category_
+ > end;
+};
+
+BOOST_MPL_AUX_NA_SPEC(2, pair_view)
+
+}}
+
+#endif // BOOST_MPL_PAIR_VIEW_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/placeholders.hpp b/third_party/boost/boost/mpl/placeholders.hpp
new file mode 100644
index 0000000..ba4acc0
--- /dev/null
+++ b/third_party/boost/boost/mpl/placeholders.hpp
@@ -0,0 +1,100 @@
+
+#if !defined(BOOST_PP_IS_ITERATING)
+
+///// header body
+
+#ifndef BOOST_MPL_PLACEHOLDERS_HPP_INCLUDED
+#define BOOST_MPL_PLACEHOLDERS_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+// Copyright Peter Dimov 2001-2003
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+
+#if !defined(BOOST_MPL_PREPROCESSING_MODE)
+# include <boost/mpl/arg.hpp>
+# include <boost/mpl/aux_/adl_barrier.hpp>
+
+# if !defined(BOOST_MPL_CFG_NO_ADL_BARRIER_NAMESPACE)
+# define BOOST_MPL_AUX_ARG_ADL_BARRIER_DECL(type) \
+ using ::BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE::type; \
+ /**/
+# else
+# define BOOST_MPL_AUX_ARG_ADL_BARRIER_DECL(type) /**/
+# endif
+
+#endif
+
+#include <boost/mpl/aux_/config/use_preprocessed.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE)
+
+# define BOOST_MPL_PREPROCESSED_HEADER placeholders.hpp
+# include <boost/mpl/aux_/include_preprocessed.hpp>
+
+#else
+
+# include <boost/mpl/aux_/nttp_decl.hpp>
+# include <boost/mpl/limits/arity.hpp>
+# include <boost/preprocessor/iterate.hpp>
+# include <boost/preprocessor/cat.hpp>
+
+// watch out for GNU gettext users, who #define _(x)
+#if !defined(_) || defined(BOOST_MPL_CFG_NO_UNNAMED_PLACEHOLDER_SUPPORT)
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+typedef arg<-1> _;
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+
+namespace boost { namespace mpl {
+
+BOOST_MPL_AUX_ARG_ADL_BARRIER_DECL(_)
+
+namespace placeholders {
+using BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE::_;
+}
+
+}}
+#endif
+
+/// agurt, 17/mar/02: one more placeholder for the last 'apply#'
+/// specialization
+#define BOOST_PP_ITERATION_PARAMS_1 \
+ (3,(1, BOOST_MPL_LIMIT_METAFUNCTION_ARITY + 1, <boost/mpl/placeholders.hpp>))
+#include BOOST_PP_ITERATE()
+
+#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#endif // BOOST_MPL_PLACEHOLDERS_HPP_INCLUDED
+
+///// iteration
+
+#else
+#define i_ BOOST_PP_FRAME_ITERATION(1)
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+
+typedef arg<i_> BOOST_PP_CAT(_,i_);
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+
+namespace boost { namespace mpl {
+
+BOOST_MPL_AUX_ARG_ADL_BARRIER_DECL(BOOST_PP_CAT(_,i_))
+
+namespace placeholders {
+using BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE::BOOST_PP_CAT(_,i_);
+}
+
+}}
+
+#undef i_
+#endif // BOOST_PP_IS_ITERATING
diff --git a/third_party/boost/boost/mpl/pop_front_fwd.hpp b/third_party/boost/boost/mpl/pop_front_fwd.hpp
new file mode 100644
index 0000000..ae2c518
--- /dev/null
+++ b/third_party/boost/boost/mpl/pop_front_fwd.hpp
@@ -0,0 +1,24 @@
+
+#ifndef BOOST_MPL_POP_FRONT_FWD_HPP_INCLUDED
+#define BOOST_MPL_POP_FRONT_FWD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+namespace boost { namespace mpl {
+
+template< typename Tag > struct pop_front_impl;
+template< typename Sequence > struct pop_front;
+
+}}
+
+#endif // BOOST_MPL_POP_FRONT_FWD_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/prior.hpp b/third_party/boost/boost/mpl/prior.hpp
new file mode 100644
index 0000000..16d120e
--- /dev/null
+++ b/third_party/boost/boost/mpl/prior.hpp
@@ -0,0 +1,19 @@
+
+#ifndef BOOST_MPL_PRIOR_HPP_INCLUDED
+#define BOOST_MPL_PRIOR_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/next_prior.hpp>
+
+#endif // BOOST_MPL_PRIOR_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/protect.hpp b/third_party/boost/boost/mpl/protect.hpp
new file mode 100644
index 0000000..ef585d7
--- /dev/null
+++ b/third_party/boost/boost/mpl/protect.hpp
@@ -0,0 +1,55 @@
+
+#ifndef BOOST_MPL_PROTECT_HPP_INCLUDED
+#define BOOST_MPL_PROTECT_HPP_INCLUDED
+
+// Copyright Peter Dimov 2001
+// Copyright Aleksey Gurtovoy 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/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/arity.hpp>
+#include <boost/mpl/aux_/config/dtp.hpp>
+#include <boost/mpl/aux_/nttp_decl.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+
+namespace boost { namespace mpl {
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(T)
+ , int not_le_ = 0
+ >
+struct protect : T
+{
+#if BOOST_WORKAROUND(__EDG_VERSION__, == 238)
+ typedef mpl::protect type;
+#else
+ typedef protect type;
+#endif
+};
+
+#if defined(BOOST_MPL_CFG_BROKEN_DEFAULT_PARAMETERS_IN_NESTED_TEMPLATES)
+namespace aux {
+template< BOOST_MPL_AUX_NTTP_DECL(int, N), typename T >
+struct arity< protect<T>, N >
+ : arity<T,N>
+{
+};
+} // namespace aux
+#endif
+
+BOOST_MPL_AUX_NA_SPEC_MAIN(1, protect)
+#if !defined(BOOST_MPL_CFG_NO_FULL_LAMBDA_SUPPORT)
+BOOST_MPL_AUX_NA_SPEC_TEMPLATE_ARITY(1, 1, protect)
+#endif
+
+}}
+
+#endif // BOOST_MPL_PROTECT_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/push_back.hpp b/third_party/boost/boost/mpl/push_back.hpp
new file mode 100644
index 0000000..f14bafa
--- /dev/null
+++ b/third_party/boost/boost/mpl/push_back.hpp
@@ -0,0 +1,53 @@
+
+#ifndef BOOST_MPL_PUSH_BACK_HPP_INCLUDED
+#define BOOST_MPL_PUSH_BACK_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/push_back_fwd.hpp>
+#include <boost/mpl/aux_/push_back_impl.hpp>
+#include <boost/mpl/sequence_tag.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+
+namespace boost { namespace mpl {
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(Sequence)
+ , typename BOOST_MPL_AUX_NA_PARAM(T)
+ >
+struct push_back
+ : push_back_impl< typename sequence_tag<Sequence>::type >
+ ::template apply< Sequence,T >
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(2,push_back,(Sequence,T))
+};
+
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(Sequence)
+ >
+struct has_push_back
+ : has_push_back_impl< typename sequence_tag<Sequence>::type >
+ ::template apply< Sequence >
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1,has_push_back,(Sequence))
+};
+
+
+BOOST_MPL_AUX_NA_SPEC(2, push_back)
+BOOST_MPL_AUX_NA_SPEC(1, has_push_back)
+
+}}
+
+#endif // BOOST_MPL_PUSH_BACK_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/push_back_fwd.hpp b/third_party/boost/boost/mpl/push_back_fwd.hpp
new file mode 100644
index 0000000..b2f7bcd
--- /dev/null
+++ b/third_party/boost/boost/mpl/push_back_fwd.hpp
@@ -0,0 +1,24 @@
+
+#ifndef BOOST_MPL_PUSH_BACK_FWD_HPP_INCLUDED
+#define BOOST_MPL_PUSH_BACK_FWD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+namespace boost { namespace mpl {
+
+template< typename Tag > struct push_back_impl;
+template< typename Sequence, typename T > struct push_back;
+
+}}
+
+#endif // BOOST_MPL_PUSH_BACK_FWD_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/push_front.hpp b/third_party/boost/boost/mpl/push_front.hpp
new file mode 100644
index 0000000..f5d6d44
--- /dev/null
+++ b/third_party/boost/boost/mpl/push_front.hpp
@@ -0,0 +1,52 @@
+
+#ifndef BOOST_MPL_PUSH_FRONT_HPP_INCLUDED
+#define BOOST_MPL_PUSH_FRONT_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/push_front_fwd.hpp>
+#include <boost/mpl/aux_/push_front_impl.hpp>
+#include <boost/mpl/sequence_tag.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+
+namespace boost { namespace mpl {
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(Sequence)
+ , typename BOOST_MPL_AUX_NA_PARAM(T)
+ >
+struct push_front
+ : push_front_impl< typename sequence_tag<Sequence>::type >
+ ::template apply< Sequence,T >
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(2,push_front,(Sequence,T))
+};
+
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(Sequence)
+ >
+struct has_push_front
+ : has_push_front_impl< typename sequence_tag<Sequence>::type >
+ ::template apply< Sequence >
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1,has_push_front,(Sequence))
+};
+
+BOOST_MPL_AUX_NA_SPEC(2, push_front)
+BOOST_MPL_AUX_NA_SPEC(1, has_push_front)
+
+}}
+
+#endif // BOOST_MPL_PUSH_FRONT_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/push_front_fwd.hpp b/third_party/boost/boost/mpl/push_front_fwd.hpp
new file mode 100644
index 0000000..ff1b055
--- /dev/null
+++ b/third_party/boost/boost/mpl/push_front_fwd.hpp
@@ -0,0 +1,24 @@
+
+#ifndef BOOST_MPL_PUSH_FRONT_FWD_HPP_INCLUDED
+#define BOOST_MPL_PUSH_FRONT_FWD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+namespace boost { namespace mpl {
+
+template< typename Tag > struct push_front_impl;
+template< typename Sequence, typename T > struct push_front;
+
+}}
+
+#endif // BOOST_MPL_PUSH_FRONT_FWD_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/quote.hpp b/third_party/boost/boost/mpl/quote.hpp
new file mode 100644
index 0000000..64e95b7
--- /dev/null
+++ b/third_party/boost/boost/mpl/quote.hpp
@@ -0,0 +1,151 @@
+
+#if !defined(BOOST_PP_IS_ITERATING)
+
+///// header body
+
+#ifndef BOOST_MPL_QUOTE_HPP_INCLUDED
+#define BOOST_MPL_QUOTE_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2008
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#if !defined(BOOST_MPL_PREPROCESSING_MODE)
+# include <boost/mpl/void.hpp>
+# include <boost/mpl/aux_/has_type.hpp>
+#endif
+
+#include <boost/mpl/aux_/config/bcc.hpp>
+#include <boost/mpl/aux_/config/ttp.hpp>
+
+#if defined(BOOST_MPL_CFG_NO_TEMPLATE_TEMPLATE_PARAMETERS) \
+ && !defined(BOOST_MPL_CFG_BCC590_WORKAROUNDS)
+# define BOOST_MPL_CFG_NO_QUOTE_TEMPLATE
+#endif
+
+#if !defined(BOOST_MPL_CFG_NO_IMPLICIT_METAFUNCTIONS) \
+ && defined(BOOST_MPL_CFG_NO_HAS_XXX)
+# define BOOST_MPL_CFG_NO_IMPLICIT_METAFUNCTIONS
+#endif
+
+#include <boost/mpl/aux_/config/use_preprocessed.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS) \
+ && !defined(BOOST_MPL_PREPROCESSING_MODE)
+
+# define BOOST_MPL_PREPROCESSED_HEADER quote.hpp
+# include <boost/mpl/aux_/include_preprocessed.hpp>
+
+#else
+
+# include <boost/mpl/limits/arity.hpp>
+# include <boost/mpl/aux_/preprocessor/params.hpp>
+# include <boost/mpl/aux_/config/ctps.hpp>
+# include <boost/mpl/aux_/config/workaround.hpp>
+
+# include <boost/preprocessor/iterate.hpp>
+# include <boost/preprocessor/cat.hpp>
+
+#if !defined(BOOST_MPL_CFG_NO_QUOTE_TEMPLATE)
+
+namespace boost { namespace mpl {
+
+#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+
+template< typename T, bool has_type_ >
+struct quote_impl
+// GCC has a problem with metafunction forwarding when T is a
+// specialization of a template called 'type'.
+# if BOOST_WORKAROUND(__GNUC__, BOOST_TESTED_AT(4)) \
+ && BOOST_WORKAROUND(__GNUC_MINOR__, BOOST_TESTED_AT(0)) \
+ && BOOST_WORKAROUND(__GNUC_PATCHLEVEL__, BOOST_TESTED_AT(2))
+{
+ typedef typename T::type type;
+};
+# else
+ : T
+{
+};
+# endif
+
+template< typename T >
+struct quote_impl<T,false>
+{
+ typedef T type;
+};
+
+#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+
+template< bool > struct quote_impl
+{
+ template< typename T > struct result_
+ : T
+ {
+ };
+};
+
+template<> struct quote_impl<false>
+{
+ template< typename T > struct result_
+ {
+ typedef T type;
+ };
+};
+
+#endif
+
+#define BOOST_PP_ITERATION_PARAMS_1 \
+ (3,(1, BOOST_MPL_LIMIT_METAFUNCTION_ARITY, <boost/mpl/quote.hpp>))
+#include BOOST_PP_ITERATE()
+
+}}
+
+#endif // BOOST_MPL_CFG_NO_QUOTE_TEMPLATE
+
+#endif // BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+#endif // BOOST_MPL_QUOTE_HPP_INCLUDED
+
+///// iteration
+
+#else
+#define i_ BOOST_PP_FRAME_ITERATION(1)
+
+template<
+ template< BOOST_MPL_PP_PARAMS(i_, typename P) > class F
+ , typename Tag = void_
+ >
+struct BOOST_PP_CAT(quote,i_)
+{
+ template< BOOST_MPL_PP_PARAMS(i_, typename U) > struct apply
+#if defined(BOOST_MPL_CFG_BCC590_WORKAROUNDS)
+ {
+ typedef typename quote_impl<
+ F< BOOST_MPL_PP_PARAMS(i_, U) >
+ , aux::has_type< F< BOOST_MPL_PP_PARAMS(i_, U) > >::value
+ >::type type;
+ };
+#elif !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
+ : quote_impl<
+ F< BOOST_MPL_PP_PARAMS(i_, U) >
+ , aux::has_type< F< BOOST_MPL_PP_PARAMS(i_, U) > >::value
+ >
+ {
+ };
+#else
+ : quote_impl< aux::has_type< F< BOOST_MPL_PP_PARAMS(i_, U) > >::value >
+ ::template result_< F< BOOST_MPL_PP_PARAMS(i_, U) > >
+ {
+ };
+#endif
+};
+
+#undef i_
+#endif // BOOST_PP_IS_ITERATING
diff --git a/third_party/boost/boost/mpl/reverse_fold.hpp b/third_party/boost/boost/mpl/reverse_fold.hpp
new file mode 100644
index 0000000..3d54b05
--- /dev/null
+++ b/third_party/boost/boost/mpl/reverse_fold.hpp
@@ -0,0 +1,50 @@
+
+#ifndef BOOST_MPL_REVERSE_FOLD_HPP_INCLUDED
+#define BOOST_MPL_REVERSE_FOLD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+// Copyright David Abrahams 2001-2002
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/begin_end.hpp>
+#include <boost/mpl/O1_size.hpp>
+#include <boost/mpl/arg.hpp>
+#include <boost/mpl/aux_/reverse_fold_impl.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+
+namespace boost { namespace mpl {
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(Sequence)
+ , typename BOOST_MPL_AUX_NA_PARAM(State)
+ , typename BOOST_MPL_AUX_NA_PARAM(BackwardOp)
+ , typename ForwardOp = arg<1>
+ >
+struct reverse_fold
+{
+ typedef typename aux::reverse_fold_impl<
+ ::boost::mpl::O1_size<Sequence>::value
+ , typename begin<Sequence>::type
+ , typename end<Sequence>::type
+ , State
+ , BackwardOp
+ , ForwardOp
+ >::state type;
+
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(3,reverse_fold,(Sequence,State,BackwardOp))
+};
+
+BOOST_MPL_AUX_NA_SPEC(3, reverse_fold)
+
+}}
+
+#endif // BOOST_MPL_REVERSE_FOLD_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/same_as.hpp b/third_party/boost/boost/mpl/same_as.hpp
new file mode 100644
index 0000000..c4b8e9f
--- /dev/null
+++ b/third_party/boost/boost/mpl/same_as.hpp
@@ -0,0 +1,55 @@
+
+#ifndef BOOST_MPL_SAME_AS_HPP_INCLUDED
+#define BOOST_MPL_SAME_AS_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/not.hpp>
+#include <boost/mpl/aux_/lambda_spec.hpp>
+#include <boost/mpl/aux_/config/forwarding.hpp>
+
+#include <boost/type_traits/is_same.hpp>
+
+namespace boost { namespace mpl {
+
+template< typename T1 >
+struct same_as
+{
+ template< typename T2 > struct apply
+#if !defined(BOOST_MPL_CFG_NO_NESTED_FORWARDING)
+ : is_same<T1,T2>
+ {
+#else
+ {
+ typedef typename is_same<T1,T2>::type type;
+#endif
+ };
+};
+
+template< typename T1 >
+struct not_same_as
+{
+ template< typename T2 > struct apply
+#if !defined(BOOST_MPL_CFG_NO_NESTED_FORWARDING)
+ : not_< is_same<T1,T2> >
+ {
+#else
+ {
+ typedef typename not_< is_same<T1,T2> >::type type;
+#endif
+ };
+};
+
+}}
+
+#endif // BOOST_MPL_SAME_AS_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/sequence_tag.hpp b/third_party/boost/boost/mpl/sequence_tag.hpp
new file mode 100644
index 0000000..cda8c87
--- /dev/null
+++ b/third_party/boost/boost/mpl/sequence_tag.hpp
@@ -0,0 +1,124 @@
+
+#ifndef BOOST_MPL_SEQUENCE_TAG_HPP_INCLUDED
+#define BOOST_MPL_SEQUENCE_TAG_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/sequence_tag_fwd.hpp>
+#include <boost/mpl/aux_/has_tag.hpp>
+#include <boost/mpl/aux_/has_begin.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/is_msvc_eti_arg.hpp>
+#include <boost/mpl/aux_/config/eti.hpp>
+#include <boost/mpl/aux_/yes_no.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+namespace boost { namespace mpl {
+
+// agurt, 27/nov/02: have to use a simplistic 'sequence_tag' implementation
+// on MSVC to avoid dreadful "internal structure overflow" error
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300) \
+ || defined(BOOST_MPL_CFG_NO_HAS_XXX)
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(Sequence)
+ >
+struct sequence_tag
+{
+ typedef typename Sequence::tag type;
+};
+
+#elif BOOST_WORKAROUND(BOOST_MSVC, == 1300)
+
+// agurt, 07/feb/03: workaround for what seems to be MSVC 7.0-specific ETI issue
+
+namespace aux {
+
+template< bool >
+struct sequence_tag_impl
+{
+ template< typename Sequence > struct result_
+ {
+ typedef typename Sequence::tag type;
+ };
+};
+
+template<>
+struct sequence_tag_impl<false>
+{
+ template< typename Sequence > struct result_
+ {
+ typedef int type;
+ };
+};
+
+} // namespace aux
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(Sequence)
+ >
+struct sequence_tag
+ : aux::sequence_tag_impl< !aux::is_msvc_eti_arg<Sequence>::value >
+ ::template result_<Sequence>
+{
+};
+
+#else
+
+namespace aux {
+
+template< bool has_tag_, bool has_begin_ >
+struct sequence_tag_impl
+{
+ // agurt 24/nov/02: MSVC 6.5 gets confused in 'sequence_tag_impl<true>'
+ // specialization below, if we name it 'result_' here
+ template< typename Sequence > struct result2_;
+};
+
+# define AUX_CLASS_SEQUENCE_TAG_SPEC(has_tag, has_begin, result_type) \
+template<> struct sequence_tag_impl<has_tag,has_begin> \
+{ \
+ template< typename Sequence > struct result2_ \
+ { \
+ typedef result_type type; \
+ }; \
+}; \
+/**/
+
+AUX_CLASS_SEQUENCE_TAG_SPEC(true, true, typename Sequence::tag)
+AUX_CLASS_SEQUENCE_TAG_SPEC(true, false, typename Sequence::tag)
+AUX_CLASS_SEQUENCE_TAG_SPEC(false, true, nested_begin_end_tag)
+AUX_CLASS_SEQUENCE_TAG_SPEC(false, false, non_sequence_tag)
+
+# undef AUX_CLASS_SEQUENCE_TAG_SPEC
+
+} // namespace aux
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(Sequence)
+ >
+struct sequence_tag
+ : aux::sequence_tag_impl<
+ ::boost::mpl::aux::has_tag<Sequence>::value
+ , ::boost::mpl::aux::has_begin<Sequence>::value
+ >::template result2_<Sequence>
+{
+};
+
+#endif // BOOST_MSVC
+
+BOOST_MPL_AUX_NA_SPEC(1, sequence_tag)
+
+}}
+
+#endif // BOOST_MPL_SEQUENCE_TAG_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/sequence_tag_fwd.hpp b/third_party/boost/boost/mpl/sequence_tag_fwd.hpp
new file mode 100644
index 0000000..4d4b628
--- /dev/null
+++ b/third_party/boost/boost/mpl/sequence_tag_fwd.hpp
@@ -0,0 +1,26 @@
+
+#ifndef BOOST_MPL_SEQUENCE_TAG_FWD_HPP_INCLUDED
+#define BOOST_MPL_SEQUENCE_TAG_FWD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+namespace boost { namespace mpl {
+
+struct nested_begin_end_tag;
+struct non_sequence_tag;
+
+template< typename Sequence > struct sequence_tag;
+
+}}
+
+#endif // BOOST_MPL_SEQUENCE_TAG_FWD_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/size_fwd.hpp b/third_party/boost/boost/mpl/size_fwd.hpp
new file mode 100644
index 0000000..f4d8ba0
--- /dev/null
+++ b/third_party/boost/boost/mpl/size_fwd.hpp
@@ -0,0 +1,24 @@
+
+#ifndef BOOST_MPL_SIZE_FWD_HPP_INCLUDED
+#define BOOST_MPL_SIZE_FWD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+namespace boost { namespace mpl {
+
+template< typename Tag > struct size_impl;
+template< typename Sequence > struct size;
+
+}}
+
+#endif // BOOST_MPL_SIZE_FWD_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/size_t.hpp b/third_party/boost/boost/mpl/size_t.hpp
new file mode 100644
index 0000000..d93964c
--- /dev/null
+++ b/third_party/boost/boost/mpl/size_t.hpp
@@ -0,0 +1,25 @@
+
+#ifndef BOOST_MPL_SIZE_T_HPP_INCLUDED
+#define BOOST_MPL_SIZE_T_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/size_t_fwd.hpp>
+
+#define AUX_WRAPPER_VALUE_TYPE std::size_t
+#define AUX_WRAPPER_NAME size_t
+#define AUX_WRAPPER_PARAMS(N) std::size_t N
+
+#include <boost/mpl/aux_/integral_wrapper.hpp>
+
+#endif // BOOST_MPL_SIZE_T_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/size_t_fwd.hpp b/third_party/boost/boost/mpl/size_t_fwd.hpp
new file mode 100644
index 0000000..b368ba2
--- /dev/null
+++ b/third_party/boost/boost/mpl/size_t_fwd.hpp
@@ -0,0 +1,28 @@
+
+#ifndef BOOST_MPL_SIZE_T_FWD_HPP_INCLUDED
+#define BOOST_MPL_SIZE_T_FWD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/adl_barrier.hpp>
+#include <boost/config.hpp> // make sure 'size_t' is placed into 'std'
+#include <cstddef>
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+
+template< std::size_t N > struct size_t;
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+BOOST_MPL_AUX_ADL_BARRIER_DECL(size_t)
+
+#endif // BOOST_MPL_SIZE_T_FWD_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/sizeof.hpp b/third_party/boost/boost/mpl/sizeof.hpp
new file mode 100644
index 0000000..21cfce2
--- /dev/null
+++ b/third_party/boost/boost/mpl/sizeof.hpp
@@ -0,0 +1,36 @@
+
+#ifndef BOOST_MPL_SIZEOF_HPP_INCLUDED
+#define BOOST_MPL_SIZEOF_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2003
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/size_t.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+
+namespace boost { namespace mpl {
+
+template<
+ typename BOOST_MPL_AUX_NA_PARAM(T)
+ >
+struct sizeof_
+ : mpl::size_t< sizeof(T) >
+{
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1,sizeof_,(T))
+};
+
+BOOST_MPL_AUX_NA_SPEC_NO_ETI(1, sizeof_)
+
+}}
+
+#endif // BOOST_MPL_SIZEOF_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/tag.hpp b/third_party/boost/boost/mpl/tag.hpp
new file mode 100644
index 0000000..423d038
--- /dev/null
+++ b/third_party/boost/boost/mpl/tag.hpp
@@ -0,0 +1,52 @@
+
+#ifndef BOOST_MPL_TAG_HPP_INCLUDED
+#define BOOST_MPL_TAG_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/void.hpp>
+#include <boost/mpl/aux_/has_tag.hpp>
+#include <boost/mpl/aux_/config/eti.hpp>
+
+namespace boost { namespace mpl {
+
+namespace aux {
+template< typename T > struct tag_impl
+{
+ typedef typename T::tag type;
+};
+}
+
+template< typename T, typename Default = void_ > struct tag
+#if !defined(BOOST_MPL_CFG_MSVC_ETI_BUG)
+ : if_<
+ aux::has_tag<T>
+ , aux::tag_impl<T>
+ , Default
+ >::type
+{
+#else
+{
+ typedef typename eval_if<
+ aux::has_tag<T>
+ , aux::tag_impl<T>
+ , Default
+ >::type type;
+
+#endif
+};
+
+}}
+
+#endif // BOOST_MPL_TAG_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/transform.hpp b/third_party/boost/boost/mpl/transform.hpp
new file mode 100644
index 0000000..f378cb0
--- /dev/null
+++ b/third_party/boost/boost/mpl/transform.hpp
@@ -0,0 +1,145 @@
+
+#ifndef BOOST_MPL_TRANSFORM_HPP_INCLUDED
+#define BOOST_MPL_TRANSFORM_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2000-2004
+// Copyright David Abrahams 2003-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/fold.hpp>
+#include <boost/mpl/reverse_fold.hpp>
+#include <boost/mpl/pair_view.hpp>
+#include <boost/mpl/is_sequence.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/lambda.hpp>
+#include <boost/mpl/bind.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/not.hpp>
+#include <boost/mpl/aux_/na.hpp>
+#include <boost/mpl/aux_/inserter_algorithm.hpp>
+
+namespace boost { namespace mpl {
+
+namespace aux {
+
+template<
+ typename Seq
+ , typename Op
+ , typename In
+ >
+struct transform1_impl
+ : fold<
+ Seq
+ , typename In::state
+ , bind2< typename lambda< typename In::operation >::type
+ , _1
+ , bind1< typename lambda<Op>::type, _2>
+ >
+ >
+{
+};
+
+template<
+ typename Seq
+ , typename Op
+ , typename In
+ >
+struct reverse_transform1_impl
+ : reverse_fold<
+ Seq
+ , typename In::state
+ , bind2< typename lambda< typename In::operation >::type
+ , _1
+ , bind1< typename lambda<Op>::type, _2>
+ >
+ >
+{
+};
+
+template<
+ typename Seq1
+ , typename Seq2
+ , typename Op
+ , typename In
+ >
+struct transform2_impl
+ : fold<
+ pair_view<Seq1,Seq2>
+ , typename In::state
+ , bind2< typename lambda< typename In::operation >::type
+ , _1
+ , bind2<
+ typename lambda<Op>::type
+ , bind1<first<>,_2>
+ , bind1<second<>,_2>
+ >
+ >
+ >
+{
+};
+
+template<
+ typename Seq1
+ , typename Seq2
+ , typename Op
+ , typename In
+ >
+struct reverse_transform2_impl
+ : reverse_fold<
+ pair_view<Seq1,Seq2>
+ , typename In::state
+ , bind2< typename lambda< typename In::operation >::type
+ , _1
+ , bind2< typename lambda< Op >::type
+ , bind1<first<>,_2>
+ , bind1<second<>,_2>
+ >
+ >
+ >
+{
+};
+
+} // namespace aux
+
+BOOST_MPL_AUX_INSERTER_ALGORITHM_DEF(3, transform1)
+BOOST_MPL_AUX_INSERTER_ALGORITHM_DEF(4, transform2)
+
+#define AUX778076_TRANSFORM_DEF(name) \
+template< \
+ typename BOOST_MPL_AUX_NA_PARAM(Seq1) \
+ , typename BOOST_MPL_AUX_NA_PARAM(Seq2OrOperation) \
+ , typename BOOST_MPL_AUX_NA_PARAM(OperationOrInserter) \
+ , typename BOOST_MPL_AUX_NA_PARAM(Inserter) \
+ > \
+struct name \
+{ \
+ typedef typename eval_if< \
+ or_< \
+ is_na<OperationOrInserter> \
+ , is_lambda_expression< Seq2OrOperation > \
+ , not_< is_sequence<Seq2OrOperation> > \
+ > \
+ , name##1<Seq1,Seq2OrOperation,OperationOrInserter> \
+ , name##2<Seq1,Seq2OrOperation,OperationOrInserter,Inserter> \
+ >::type type; \
+}; \
+BOOST_MPL_AUX_NA_SPEC(4, name) \
+/**/
+
+AUX778076_TRANSFORM_DEF(transform)
+AUX778076_TRANSFORM_DEF(reverse_transform)
+
+#undef AUX778076_TRANSFORM_DEF
+
+}}
+
+#endif // BOOST_MPL_TRANSFORM_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/void.hpp b/third_party/boost/boost/mpl/void.hpp
new file mode 100644
index 0000000..8ca99e3
--- /dev/null
+++ b/third_party/boost/boost/mpl/void.hpp
@@ -0,0 +1,76 @@
+
+#ifndef BOOST_MPL_VOID_HPP_INCLUDED
+#define BOOST_MPL_VOID_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/void_fwd.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/aux_/na_spec.hpp>
+#include <boost/mpl/aux_/config/msvc.hpp>
+#include <boost/mpl/aux_/config/workaround.hpp>
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+
+// [JDG Feb-4-2003] made void_ a complete type to allow it to be
+// instantiated so that it can be passed in as an object that can be
+// used to select an overloaded function. Possible use includes signaling
+// a zero arity functor evaluation call.
+struct void_ { typedef void_ type; };
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+
+namespace boost { namespace mpl {
+
+template< typename T >
+struct is_void_
+ : false_
+{
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+ using false_::value;
+#endif
+};
+
+template<>
+struct is_void_<void_>
+ : true_
+{
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+ using true_::value;
+#endif
+};
+
+template< typename T >
+struct is_not_void_
+ : true_
+{
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+ using true_::value;
+#endif
+};
+
+template<>
+struct is_not_void_<void_>
+ : false_
+{
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
+ using false_::value;
+#endif
+};
+
+BOOST_MPL_AUX_NA_SPEC(1, is_void_)
+BOOST_MPL_AUX_NA_SPEC(1, is_not_void_)
+
+}}
+
+#endif // BOOST_MPL_VOID_HPP_INCLUDED
diff --git a/third_party/boost/boost/mpl/void_fwd.hpp b/third_party/boost/boost/mpl/void_fwd.hpp
new file mode 100644
index 0000000..4838ff0
--- /dev/null
+++ b/third_party/boost/boost/mpl/void_fwd.hpp
@@ -0,0 +1,26 @@
+
+#ifndef BOOST_MPL_VOID_FWD_HPP_INCLUDED
+#define BOOST_MPL_VOID_FWD_HPP_INCLUDED
+
+// Copyright Aleksey Gurtovoy 2001-2004
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/mpl for documentation.
+
+// $Id$
+// $Date$
+// $Revision$
+
+#include <boost/mpl/aux_/adl_barrier.hpp>
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_OPEN
+
+struct void_;
+
+BOOST_MPL_AUX_ADL_BARRIER_NAMESPACE_CLOSE
+BOOST_MPL_AUX_ADL_BARRIER_DECL(void_)
+
+#endif // BOOST_MPL_VOID_FWD_HPP_INCLUDED
diff --git a/third_party/boost/boost/multi_index/detail/scope_guard.hpp b/third_party/boost/boost/multi_index/detail/scope_guard.hpp
new file mode 100644
index 0000000..2371091
--- /dev/null
+++ b/third_party/boost/boost/multi_index/detail/scope_guard.hpp
@@ -0,0 +1,453 @@
+/* Copyright 2003-2013 Joaquin M Lopez Munoz.
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * See http://www.boost.org/libs/multi_index for library home page.
+ */
+
+#ifndef BOOST_MULTI_INDEX_DETAIL_SCOPE_GUARD_HPP
+#define BOOST_MULTI_INDEX_DETAIL_SCOPE_GUARD_HPP
+
+#if defined(_MSC_VER)
+#pragma once
+#endif
+
+#include <boost/detail/no_exceptions_support.hpp>
+#include <boost/mpl/if.hpp>
+
+namespace boost{
+
+namespace multi_index{
+
+namespace detail{
+
+/* Until some official version of the ScopeGuard idiom makes it into Boost,
+ * we locally define our own. This is a merely reformated version of
+ * ScopeGuard.h as defined in:
+ * Alexandrescu, A., Marginean, P.:"Generic<Programming>: Change the Way You
+ * Write Exception-Safe Code - Forever", C/C++ Users Jornal, Dec 2000,
+ * http://www.drdobbs.com/184403758
+ * with the following modifications:
+ * - General pretty formatting (pretty to my taste at least.)
+ * - Naming style changed to standard C++ library requirements.
+ * - Added scope_guard_impl4 and obj_scope_guard_impl3, (Boost.MultiIndex
+ * needs them). A better design would provide guards for many more
+ * arguments through the Boost Preprocessor Library.
+ * - Added scope_guard_impl_base::touch (see below.)
+ * - Removed RefHolder and ByRef, whose functionality is provided
+ * already by Boost.Ref.
+ * - Removed static make_guard's and make_obj_guard's, so that the code
+ * will work even if BOOST_NO_MEMBER_TEMPLATES is defined. This forces
+ * us to move some private ctors to public, though.
+ *
+ * NB: CodeWarrior Pro 8 seems to have problems looking up safe_execute
+ * without an explicit qualification.
+ *
+ * We also define the following variants of the idiom:
+ *
+ * - make_guard_if_c<bool>( ... )
+ * - make_guard_if<IntegralConstant>( ... )
+ * - make_obj_guard_if_c<bool>( ... )
+ * - make_obj_guard_if<IntegralConstant>( ... )
+ * which may be used with a compile-time constant to yield
+ * a "null_guard" if the boolean compile-time parameter is false,
+ * or conversely, the guard is only constructed if the constant is true.
+ * This is useful to avoid extra tagging, because the returned
+ * null_guard can be optimzed comlpetely away by the compiler.
+ */
+
+class scope_guard_impl_base
+{
+public:
+ scope_guard_impl_base():dismissed_(false){}
+ void dismiss()const{dismissed_=true;}
+
+ /* This helps prevent some "unused variable" warnings under, for instance,
+ * GCC 3.2.
+ */
+ void touch()const{}
+
+protected:
+ ~scope_guard_impl_base(){}
+
+ scope_guard_impl_base(const scope_guard_impl_base& other):
+ dismissed_(other.dismissed_)
+ {
+ other.dismiss();
+ }
+
+ template<typename J>
+ static void safe_execute(J& j){
+ BOOST_TRY{
+ if(!j.dismissed_)j.execute();
+ }
+ BOOST_CATCH(...){}
+ BOOST_CATCH_END
+ }
+
+ mutable bool dismissed_;
+
+private:
+ scope_guard_impl_base& operator=(const scope_guard_impl_base&);
+};
+
+typedef const scope_guard_impl_base& scope_guard;
+
+struct null_guard : public scope_guard_impl_base
+{
+ template< class T1 >
+ null_guard( const T1& )
+ { }
+
+ template< class T1, class T2 >
+ null_guard( const T1&, const T2& )
+ { }
+
+ template< class T1, class T2, class T3 >
+ null_guard( const T1&, const T2&, const T3& )
+ { }
+
+ template< class T1, class T2, class T3, class T4 >
+ null_guard( const T1&, const T2&, const T3&, const T4& )
+ { }
+
+ template< class T1, class T2, class T3, class T4, class T5 >
+ null_guard( const T1&, const T2&, const T3&, const T4&, const T5& )
+ { }
+};
+
+template< bool cond, class T >
+struct null_guard_return
+{
+ typedef typename boost::mpl::if_c<cond,T,null_guard>::type type;
+};
+
+template<typename F>
+class scope_guard_impl0:public scope_guard_impl_base
+{
+public:
+ scope_guard_impl0(F fun):fun_(fun){}
+ ~scope_guard_impl0(){scope_guard_impl_base::safe_execute(*this);}
+ void execute(){fun_();}
+
+protected:
+
+ F fun_;
+};
+
+template<typename F>
+inline scope_guard_impl0<F> make_guard(F fun)
+{
+ return scope_guard_impl0<F>(fun);
+}
+
+template<bool cond, typename F>
+inline typename null_guard_return<cond,scope_guard_impl0<F> >::type
+make_guard_if_c(F fun)
+{
+ return typename null_guard_return<cond,scope_guard_impl0<F> >::type(fun);
+}
+
+template<typename C, typename F>
+inline typename null_guard_return<C::value,scope_guard_impl0<F> >::type
+make_guard_if(F fun)
+{
+ return make_guard_if<C::value>(fun);
+}
+
+template<typename F,typename P1>
+class scope_guard_impl1:public scope_guard_impl_base
+{
+public:
+ scope_guard_impl1(F fun,P1 p1):fun_(fun),p1_(p1){}
+ ~scope_guard_impl1(){scope_guard_impl_base::safe_execute(*this);}
+ void execute(){fun_(p1_);}
+
+protected:
+ F fun_;
+ const P1 p1_;
+};
+
+template<typename F,typename P1>
+inline scope_guard_impl1<F,P1> make_guard(F fun,P1 p1)
+{
+ return scope_guard_impl1<F,P1>(fun,p1);
+}
+
+template<bool cond, typename F,typename P1>
+inline typename null_guard_return<cond,scope_guard_impl1<F,P1> >::type
+make_guard_if_c(F fun,P1 p1)
+{
+ return typename null_guard_return<cond,scope_guard_impl1<F,P1> >::type(fun,p1);
+}
+
+template<typename C, typename F,typename P1>
+inline typename null_guard_return<C::value,scope_guard_impl1<F,P1> >::type
+make_guard_if(F fun,P1 p1)
+{
+ return make_guard_if_c<C::value>(fun,p1);
+}
+
+template<typename F,typename P1,typename P2>
+class scope_guard_impl2:public scope_guard_impl_base
+{
+public:
+ scope_guard_impl2(F fun,P1 p1,P2 p2):fun_(fun),p1_(p1),p2_(p2){}
+ ~scope_guard_impl2(){scope_guard_impl_base::safe_execute(*this);}
+ void execute(){fun_(p1_,p2_);}
+
+protected:
+ F fun_;
+ const P1 p1_;
+ const P2 p2_;
+};
+
+template<typename F,typename P1,typename P2>
+inline scope_guard_impl2<F,P1,P2> make_guard(F fun,P1 p1,P2 p2)
+{
+ return scope_guard_impl2<F,P1,P2>(fun,p1,p2);
+}
+
+template<bool cond, typename F,typename P1,typename P2>
+inline typename null_guard_return<cond,scope_guard_impl2<F,P1,P2> >::type
+make_guard_if_c(F fun,P1 p1,P2 p2)
+{
+ return typename null_guard_return<cond,scope_guard_impl2<F,P1,P2> >::type(fun,p1,p2);
+}
+
+template<typename C, typename F,typename P1,typename P2>
+inline typename null_guard_return<C::value,scope_guard_impl2<F,P1,P2> >::type
+make_guard_if(F fun,P1 p1,P2 p2)
+{
+ return make_guard_if_c<C::value>(fun,p1,p2);
+}
+
+template<typename F,typename P1,typename P2,typename P3>
+class scope_guard_impl3:public scope_guard_impl_base
+{
+public:
+ scope_guard_impl3(F fun,P1 p1,P2 p2,P3 p3):fun_(fun),p1_(p1),p2_(p2),p3_(p3){}
+ ~scope_guard_impl3(){scope_guard_impl_base::safe_execute(*this);}
+ void execute(){fun_(p1_,p2_,p3_);}
+
+protected:
+ F fun_;
+ const P1 p1_;
+ const P2 p2_;
+ const P3 p3_;
+};
+
+template<typename F,typename P1,typename P2,typename P3>
+inline scope_guard_impl3<F,P1,P2,P3> make_guard(F fun,P1 p1,P2 p2,P3 p3)
+{
+ return scope_guard_impl3<F,P1,P2,P3>(fun,p1,p2,p3);
+}
+
+template<bool cond,typename F,typename P1,typename P2,typename P3>
+inline typename null_guard_return<cond,scope_guard_impl3<F,P1,P2,P3> >::type
+make_guard_if_c(F fun,P1 p1,P2 p2,P3 p3)
+{
+ return typename null_guard_return<cond,scope_guard_impl3<F,P1,P2,P3> >::type(fun,p1,p2,p3);
+}
+
+template<typename C,typename F,typename P1,typename P2,typename P3>
+inline typename null_guard_return< C::value,scope_guard_impl3<F,P1,P2,P3> >::type
+make_guard_if(F fun,P1 p1,P2 p2,P3 p3)
+{
+ return make_guard_if_c<C::value>(fun,p1,p2,p3);
+}
+
+template<typename F,typename P1,typename P2,typename P3,typename P4>
+class scope_guard_impl4:public scope_guard_impl_base
+{
+public:
+ scope_guard_impl4(F fun,P1 p1,P2 p2,P3 p3,P4 p4):
+ fun_(fun),p1_(p1),p2_(p2),p3_(p3),p4_(p4){}
+ ~scope_guard_impl4(){scope_guard_impl_base::safe_execute(*this);}
+ void execute(){fun_(p1_,p2_,p3_,p4_);}
+
+protected:
+ F fun_;
+ const P1 p1_;
+ const P2 p2_;
+ const P3 p3_;
+ const P4 p4_;
+};
+
+template<typename F,typename P1,typename P2,typename P3,typename P4>
+inline scope_guard_impl4<F,P1,P2,P3,P4> make_guard(
+ F fun,P1 p1,P2 p2,P3 p3,P4 p4)
+{
+ return scope_guard_impl4<F,P1,P2,P3,P4>(fun,p1,p2,p3,p4);
+}
+
+template<bool cond, typename F,typename P1,typename P2,typename P3,typename P4>
+inline typename null_guard_return<cond,scope_guard_impl4<F,P1,P2,P3,P4> >::type
+make_guard_if_c(
+ F fun,P1 p1,P2 p2,P3 p3,P4 p4)
+{
+ return typename null_guard_return<cond,scope_guard_impl4<F,P1,P2,P3,P4> >::type(fun,p1,p2,p3,p4);
+}
+
+template<typename C, typename F,typename P1,typename P2,typename P3,typename P4>
+inline typename null_guard_return<C::value,scope_guard_impl4<F,P1,P2,P3,P4> >::type
+make_guard_if(
+ F fun,P1 p1,P2 p2,P3 p3,P4 p4)
+{
+ return make_guard_if_c<C::value>(fun,p1,p2,p3,p4);
+}
+
+template<class Obj,typename MemFun>
+class obj_scope_guard_impl0:public scope_guard_impl_base
+{
+public:
+ obj_scope_guard_impl0(Obj& obj,MemFun mem_fun):obj_(obj),mem_fun_(mem_fun){}
+ ~obj_scope_guard_impl0(){scope_guard_impl_base::safe_execute(*this);}
+ void execute(){(obj_.*mem_fun_)();}
+
+protected:
+ Obj& obj_;
+ MemFun mem_fun_;
+};
+
+template<class Obj,typename MemFun>
+inline obj_scope_guard_impl0<Obj,MemFun> make_obj_guard(Obj& obj,MemFun mem_fun)
+{
+ return obj_scope_guard_impl0<Obj,MemFun>(obj,mem_fun);
+}
+
+template<bool cond, class Obj,typename MemFun>
+inline typename null_guard_return<cond,obj_scope_guard_impl0<Obj,MemFun> >::type
+make_obj_guard_if_c(Obj& obj,MemFun mem_fun)
+{
+ return typename null_guard_return<cond,obj_scope_guard_impl0<Obj,MemFun> >::type(obj,mem_fun);
+}
+
+template<typename C, class Obj,typename MemFun>
+inline typename null_guard_return<C::value,obj_scope_guard_impl0<Obj,MemFun> >::type
+make_obj_guard_if(Obj& obj,MemFun mem_fun)
+{
+ return make_obj_guard_if_c<C::value>(obj,mem_fun);
+}
+
+template<class Obj,typename MemFun,typename P1>
+class obj_scope_guard_impl1:public scope_guard_impl_base
+{
+public:
+ obj_scope_guard_impl1(Obj& obj,MemFun mem_fun,P1 p1):
+ obj_(obj),mem_fun_(mem_fun),p1_(p1){}
+ ~obj_scope_guard_impl1(){scope_guard_impl_base::safe_execute(*this);}
+ void execute(){(obj_.*mem_fun_)(p1_);}
+
+protected:
+ Obj& obj_;
+ MemFun mem_fun_;
+ const P1 p1_;
+};
+
+template<class Obj,typename MemFun,typename P1>
+inline obj_scope_guard_impl1<Obj,MemFun,P1> make_obj_guard(
+ Obj& obj,MemFun mem_fun,P1 p1)
+{
+ return obj_scope_guard_impl1<Obj,MemFun,P1>(obj,mem_fun,p1);
+}
+
+template<bool cond, class Obj,typename MemFun,typename P1>
+inline typename null_guard_return<cond,obj_scope_guard_impl1<Obj,MemFun,P1> >::type
+make_obj_guard_if_c( Obj& obj,MemFun mem_fun,P1 p1)
+{
+ return typename null_guard_return<cond,obj_scope_guard_impl1<Obj,MemFun,P1> >::type(obj,mem_fun,p1);
+}
+
+template<typename C, class Obj,typename MemFun,typename P1>
+inline typename null_guard_return<C::value,obj_scope_guard_impl1<Obj,MemFun,P1> >::type
+make_obj_guard_if( Obj& obj,MemFun mem_fun,P1 p1)
+{
+ return make_obj_guard_if_c<C::value>(obj,mem_fun,p1);
+}
+
+template<class Obj,typename MemFun,typename P1,typename P2>
+class obj_scope_guard_impl2:public scope_guard_impl_base
+{
+public:
+ obj_scope_guard_impl2(Obj& obj,MemFun mem_fun,P1 p1,P2 p2):
+ obj_(obj),mem_fun_(mem_fun),p1_(p1),p2_(p2)
+ {}
+ ~obj_scope_guard_impl2(){scope_guard_impl_base::safe_execute(*this);}
+ void execute(){(obj_.*mem_fun_)(p1_,p2_);}
+
+protected:
+ Obj& obj_;
+ MemFun mem_fun_;
+ const P1 p1_;
+ const P2 p2_;
+};
+
+template<class Obj,typename MemFun,typename P1,typename P2>
+inline obj_scope_guard_impl2<Obj,MemFun,P1,P2>
+make_obj_guard(Obj& obj,MemFun mem_fun,P1 p1,P2 p2)
+{
+ return obj_scope_guard_impl2<Obj,MemFun,P1,P2>(obj,mem_fun,p1,p2);
+}
+
+template<bool cond, class Obj,typename MemFun,typename P1,typename P2>
+inline typename null_guard_return<cond,obj_scope_guard_impl2<Obj,MemFun,P1,P2> >::type
+make_obj_guard_if_c(Obj& obj,MemFun mem_fun,P1 p1,P2 p2)
+{
+ return typename null_guard_return<cond,obj_scope_guard_impl2<Obj,MemFun,P1,P2> >::type(obj,mem_fun,p1,p2);
+}
+
+template<typename C, class Obj,typename MemFun,typename P1,typename P2>
+inline typename null_guard_return<C::value,obj_scope_guard_impl2<Obj,MemFun,P1,P2> >::type
+make_obj_guard_if(Obj& obj,MemFun mem_fun,P1 p1,P2 p2)
+{
+ return make_obj_guard_if_c<C::value>(obj,mem_fun,p1,p2);
+}
+
+template<class Obj,typename MemFun,typename P1,typename P2,typename P3>
+class obj_scope_guard_impl3:public scope_guard_impl_base
+{
+public:
+ obj_scope_guard_impl3(Obj& obj,MemFun mem_fun,P1 p1,P2 p2,P3 p3):
+ obj_(obj),mem_fun_(mem_fun),p1_(p1),p2_(p2),p3_(p3)
+ {}
+ ~obj_scope_guard_impl3(){scope_guard_impl_base::safe_execute(*this);}
+ void execute(){(obj_.*mem_fun_)(p1_,p2_,p3_);}
+
+protected:
+ Obj& obj_;
+ MemFun mem_fun_;
+ const P1 p1_;
+ const P2 p2_;
+ const P3 p3_;
+};
+
+template<class Obj,typename MemFun,typename P1,typename P2,typename P3>
+inline obj_scope_guard_impl3<Obj,MemFun,P1,P2,P3>
+make_obj_guard(Obj& obj,MemFun mem_fun,P1 p1,P2 p2,P3 p3)
+{
+ return obj_scope_guard_impl3<Obj,MemFun,P1,P2,P3>(obj,mem_fun,p1,p2,p3);
+}
+
+template<bool cond, class Obj,typename MemFun,typename P1,typename P2,typename P3>
+inline typename null_guard_return<cond,obj_scope_guard_impl3<Obj,MemFun,P1,P2,P3> >::type
+make_obj_guard_if_c(Obj& obj,MemFun mem_fun,P1 p1,P2 p2,P3 p3)
+{
+ return typename null_guard_return<cond,obj_scope_guard_impl3<Obj,MemFun,P1,P2,P3> >::type(obj,mem_fun,p1,p2,p3);
+}
+
+template<typename C, class Obj,typename MemFun,typename P1,typename P2,typename P3>
+inline typename null_guard_return<C::value,obj_scope_guard_impl3<Obj,MemFun,P1,P2,P3> >::type
+make_obj_guard_if(Obj& obj,MemFun mem_fun,P1 p1,P2 p2,P3 p3)
+{
+ return make_obj_guard_if_c<C::value>(obj,mem_fun,p1,p2,p3);
+}
+
+} /* namespace multi_index::detail */
+
+} /* namespace multi_index */
+
+} /* namespace boost */
+
+#endif
diff --git a/third_party/boost/boost/next_prior.hpp b/third_party/boost/boost/next_prior.hpp
new file mode 100644
index 0000000..7854ec4
--- /dev/null
+++ b/third_party/boost/boost/next_prior.hpp
@@ -0,0 +1,165 @@
+// Boost next_prior.hpp header file ---------------------------------------//
+
+// (C) Copyright Dave Abrahams and Daniel Walker 1999-2003. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/utility for documentation.
+
+// Revision History
+// 13 Dec 2003 Added next(x, n) and prior(x, n) (Daniel Walker)
+
+#ifndef BOOST_NEXT_PRIOR_HPP_INCLUDED
+#define BOOST_NEXT_PRIOR_HPP_INCLUDED
+
+#include <iterator>
+#if defined(_MSC_VER) && _MSC_VER <= 1310
+#include <boost/mpl/and.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#endif
+#include <boost/type_traits/is_unsigned.hpp>
+#include <boost/type_traits/integral_promotion.hpp>
+#include <boost/type_traits/make_signed.hpp>
+#include <boost/type_traits/has_plus.hpp>
+#include <boost/type_traits/has_plus_assign.hpp>
+#include <boost/type_traits/has_minus.hpp>
+#include <boost/type_traits/has_minus_assign.hpp>
+
+namespace boost {
+
+// Helper functions for classes like bidirectional iterators not supporting
+// operator+ and operator-
+//
+// Usage:
+// const std::list<T>::iterator p = get_some_iterator();
+// const std::list<T>::iterator prev = boost::prior(p);
+// const std::list<T>::iterator next = boost::next(prev, 2);
+
+// Contributed by Dave Abrahams
+
+namespace next_prior_detail {
+
+template< typename T, typename Distance, bool HasPlus = has_plus< T, Distance >::value >
+struct next_impl2
+{
+ static T call(T x, Distance n)
+ {
+ std::advance(x, n);
+ return x;
+ }
+};
+
+template< typename T, typename Distance >
+struct next_impl2< T, Distance, true >
+{
+ static T call(T x, Distance n)
+ {
+ return x + n;
+ }
+};
+
+
+template< typename T, typename Distance, bool HasPlusAssign = has_plus_assign< T, Distance >::value >
+struct next_impl1 :
+ public next_impl2< T, Distance >
+{
+};
+
+template< typename T, typename Distance >
+struct next_impl1< T, Distance, true >
+{
+ static T call(T x, Distance n)
+ {
+ x += n;
+ return x;
+ }
+};
+
+
+template<
+ typename T,
+ typename Distance,
+ typename PromotedDistance = typename integral_promotion< Distance >::type,
+#if !defined(_MSC_VER) || _MSC_VER > 1310
+ bool IsUInt = is_unsigned< PromotedDistance >::value
+#else
+ // MSVC 7.1 has problems with applying is_unsigned to non-integral types
+ bool IsUInt = mpl::and_< is_integral< PromotedDistance >, is_unsigned< PromotedDistance > >::value
+#endif
+>
+struct prior_impl3
+{
+ static T call(T x, Distance n)
+ {
+ std::advance(x, -n);
+ return x;
+ }
+};
+
+template< typename T, typename Distance, typename PromotedDistance >
+struct prior_impl3< T, Distance, PromotedDistance, true >
+{
+ static T call(T x, Distance n)
+ {
+ typedef typename make_signed< PromotedDistance >::type signed_distance;
+ std::advance(x, -static_cast< signed_distance >(static_cast< PromotedDistance >(n)));
+ return x;
+ }
+};
+
+
+template< typename T, typename Distance, bool HasMinus = has_minus< T, Distance >::value >
+struct prior_impl2 :
+ public prior_impl3< T, Distance >
+{
+};
+
+template< typename T, typename Distance >
+struct prior_impl2< T, Distance, true >
+{
+ static T call(T x, Distance n)
+ {
+ return x - n;
+ }
+};
+
+
+template< typename T, typename Distance, bool HasMinusAssign = has_minus_assign< T, Distance >::value >
+struct prior_impl1 :
+ public prior_impl2< T, Distance >
+{
+};
+
+template< typename T, typename Distance >
+struct prior_impl1< T, Distance, true >
+{
+ static T call(T x, Distance n)
+ {
+ x -= n;
+ return x;
+ }
+};
+
+} // namespace next_prior_detail
+
+template <class T>
+inline T next(T x) { return ++x; }
+
+template <class T, class Distance>
+inline T next(T x, Distance n)
+{
+ return next_prior_detail::next_impl1< T, Distance >::call(x, n);
+}
+
+template <class T>
+inline T prior(T x) { return --x; }
+
+template <class T, class Distance>
+inline T prior(T x, Distance n)
+{
+ return next_prior_detail::prior_impl1< T, Distance >::call(x, n);
+}
+
+} // namespace boost
+
+#endif // BOOST_NEXT_PRIOR_HPP_INCLUDED
diff --git a/third_party/boost/boost/noncopyable.hpp b/third_party/boost/boost/noncopyable.hpp
new file mode 100644
index 0000000..e998ee8
--- /dev/null
+++ b/third_party/boost/boost/noncopyable.hpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2014 Glen Fernandes
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_NONCOPYABLE_HPP
+#define BOOST_NONCOPYABLE_HPP
+
+// The header file at this path is deprecated;
+// use boost/core/noncopyable.hpp instead.
+
+#include <boost/core/noncopyable.hpp>
+
+#endif
diff --git a/third_party/boost/boost/none.hpp b/third_party/boost/boost/none.hpp
new file mode 100644
index 0000000..811d4f2
--- /dev/null
+++ b/third_party/boost/boost/none.hpp
@@ -0,0 +1,58 @@
+// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
+// Copyright (C) 2014 Andrzej Krzemienski.
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/optional for documentation.
+//
+// You are welcome to contact the author at:
+// fernando_cacciola@hotmail.com
+//
+#ifndef BOOST_NONE_17SEP2003_HPP
+#define BOOST_NONE_17SEP2003_HPP
+
+#include "boost/none_t.hpp"
+
+// NOTE: Borland users have to include this header outside any precompiled headers
+// (bcc<=5.64 cannot include instance data in a precompiled header)
+// -- * To be verified, now that there's no unnamed namespace
+
+namespace boost {
+
+#ifdef BOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE
+
+none_t const none = (static_cast<none_t>(0)) ;
+
+#elif defined BOOST_OPTIONAL_USE_SINGLETON_DEFINITION_OF_NONE
+
+namespace detail { namespace optional_detail {
+
+ // the trick here is to make boost::none defined once as a global but in a header file
+ template <typename T>
+ struct none_instance
+ {
+ static const T instance;
+ };
+
+ template <typename T>
+ const T none_instance<T>::instance = T(); // global, but because 'tis a template, no cpp file required
+
+} } // namespace detail::optional_detail
+
+
+namespace {
+ // TU-local
+ const none_t& none = detail::optional_detail::none_instance<none_t>::instance;
+}
+
+#else
+
+const none_t none ((none_t::init_tag()));
+
+#endif // older definitions
+
+} // namespace boost
+
+#endif // header guard
diff --git a/third_party/boost/boost/none_t.hpp b/third_party/boost/boost/none_t.hpp
new file mode 100644
index 0000000..bc691ee
--- /dev/null
+++ b/third_party/boost/boost/none_t.hpp
@@ -0,0 +1,39 @@
+// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
+// Copyright (C) 2014 Andrzej Krzemienski.
+//
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/optional for documentation.
+//
+// You are welcome to contact the author at:
+// fernando_cacciola@hotmail.com
+//
+#ifndef BOOST_NONE_T_17SEP2003_HPP
+#define BOOST_NONE_T_17SEP2003_HPP
+
+namespace boost {
+
+#ifdef BOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE
+
+namespace detail { struct none_helper{}; }
+typedef int detail::none_helper::*none_t ;
+
+#elif defined BOOST_OPTIONAL_USE_SINGLETON_DEFINITION_OF_NONE
+
+class none_t {};
+
+#else
+
+struct none_t
+{
+ struct init_tag{};
+ explicit none_t(init_tag){} // to prevent default constructor
+};
+
+#endif // old implementation workarounds
+
+} // namespace boost
+
+#endif // header guard
diff --git a/third_party/boost/boost/optional.hpp b/third_party/boost/boost/optional.hpp
new file mode 100644
index 0000000..7a8b86f
--- /dev/null
+++ b/third_party/boost/boost/optional.hpp
@@ -0,0 +1,17 @@
+// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
+//
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/optional for documentation.
+//
+// You are welcome to contact the author at:
+// fernando_cacciola@hotmail.com
+//
+#ifndef BOOST_OPTIONAL_FLC_19NOV2002_HPP
+#define BOOST_OPTIONAL_FLC_19NOV2002_HPP
+
+#include "boost/optional/optional.hpp"
+
+#endif
diff --git a/third_party/boost/boost/optional/bad_optional_access.hpp b/third_party/boost/boost/optional/bad_optional_access.hpp
new file mode 100644
index 0000000..cabf43f
--- /dev/null
+++ b/third_party/boost/boost/optional/bad_optional_access.hpp
@@ -0,0 +1,32 @@
+// Copyright (C) 2014, Andrzej Krzemienski.
+//
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/optional for documentation.
+//
+// You are welcome to contact the author at:
+// akrzemi1@gmail.com
+//
+#ifndef BOOST_BAD_OPTIONAL_ACCESS_22MAY2014_HPP
+#define BOOST_BAD_OPTIONAL_ACCESS_22MAY2014_HPP
+
+#include <stdexcept>
+#if __cplusplus < 201103L
+#include <string> // to make converting-ctor std::string(char const*) visible
+#endif
+
+namespace boost {
+
+class bad_optional_access : public std::logic_error
+{
+public:
+ bad_optional_access()
+ : std::logic_error("Attempted to access the value of an uninitialized optional object.")
+ {}
+};
+
+} // namespace boost
+
+#endif
diff --git a/third_party/boost/boost/optional/optional.hpp b/third_party/boost/boost/optional/optional.hpp
new file mode 100644
index 0000000..8b0a9a6
--- /dev/null
+++ b/third_party/boost/boost/optional/optional.hpp
@@ -0,0 +1,1567 @@
+// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
+// Copyright (C) 2014, 2015 Andrzej Krzemienski.
+//
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/optional for documentation.
+//
+// You are welcome to contact the author at:
+// fernando_cacciola@hotmail.com
+//
+// Revisions:
+// 27 Apr 2008 (improved swap) Fernando Cacciola, Niels Dekker, Thorsten Ottosen
+// 05 May 2014 (Added move semantics) Andrzej Krzemienski
+//
+#ifndef BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
+#define BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
+
+#include <new>
+#include <iosfwd>
+
+#include <boost/config.hpp>
+#include <boost/assert.hpp>
+#include <boost/core/addressof.hpp>
+#include <boost/core/enable_if.hpp>
+#include <boost/core/explicit_operator_bool.hpp>
+#include <boost/core/swap.hpp>
+#include <boost/optional/bad_optional_access.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/type.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/type_traits/has_nothrow_constructor.hpp>
+#include <boost/type_traits/type_with_alignment.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/type_traits/decay.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/type_traits/is_lvalue_reference.hpp>
+#include <boost/type_traits/is_nothrow_move_assignable.hpp>
+#include <boost/type_traits/is_nothrow_move_constructible.hpp>
+#include <boost/type_traits/is_reference.hpp>
+#include <boost/type_traits/is_rvalue_reference.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/not.hpp>
+#include <boost/detail/reference_content.hpp>
+#include <boost/move/utility.hpp>
+#include <boost/none.hpp>
+#include <boost/utility/compare_pointees.hpp>
+
+#include <boost/optional/optional_fwd.hpp>
+
+#if (defined BOOST_NO_CXX11_RVALUE_REFERENCES) || (defined BOOST_OPTIONAL_CONFIG_NO_RVALUE_REFERENCES)
+#define BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+#endif
+
+#if BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION,<=700)
+// AFAICT only Intel 7 correctly resolves the overload set
+// that includes the in-place factory taking functions,
+// so for the other icc versions, in-place factory support
+// is disabled
+#define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
+#endif
+
+#if BOOST_WORKAROUND(__BORLANDC__, <= 0x551)
+// BCB (5.5.1) cannot parse the nested template struct in an inplace factory.
+#define BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
+#endif
+
+#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) \
+ && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581) )
+// BCB (up to 5.64) has the following bug:
+// If there is a member function/operator template of the form
+// template<class Expr> mfunc( Expr expr ) ;
+// some calls are resolved to this even if there are other better matches.
+// The effect of this bug is that calls to converting ctors and assignments
+// are incrorrectly sink to this general catch-all member function template as shown above.
+#define BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
+#endif
+
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+// GCC since 3.3 has may_alias attribute that helps to alleviate optimizer issues with
+// regard to violation of the strict aliasing rules. The optional< T > storage type is marked
+// with this attribute in order to let the compiler know that it will alias objects of type T
+// and silence compilation warnings.
+#define BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS
+#endif
+
+// Daniel Wallin discovered that bind/apply.hpp badly interacts with the apply<>
+// member template of a factory as used in the optional<> implementation.
+// He proposed this simple fix which is to move the call to apply<> outside
+// namespace boost.
+namespace boost_optional_detail
+{
+ template <class T, class Factory>
+ inline void construct(Factory const& factory, void* address)
+ {
+ factory.BOOST_NESTED_TEMPLATE apply<T>(address);
+ }
+}
+
+
+namespace boost {
+
+class in_place_factory_base ;
+class typed_in_place_factory_base ;
+
+// This forward is needed to refer to namespace scope swap from the member swap
+template<class T> void swap ( optional<T>& x, optional<T>& y );
+
+namespace optional_detail {
+// This local class is used instead of that in "aligned_storage.hpp"
+// because I've found the 'official' class to ICE BCB5.5
+// when some types are used with optional<>
+// (due to sizeof() passed down as a non-type template parameter)
+template <class T>
+class aligned_storage
+{
+ // Borland ICEs if unnamed unions are used for this!
+ union
+ // This works around GCC warnings about breaking strict aliasing rules when casting storage address to T*
+#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
+ __attribute__((__may_alias__))
+#endif
+ dummy_u
+ {
+ char data[ sizeof(T) ];
+ BOOST_DEDUCED_TYPENAME type_with_alignment<
+ ::boost::alignment_of<T>::value >::type aligner_;
+ } dummy_ ;
+
+ public:
+
+#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
+ void const* address() const { return &dummy_; }
+ void * address() { return &dummy_; }
+#else
+ void const* address() const { return dummy_.data; }
+ void * address() { return dummy_.data; }
+#endif
+} ;
+
+template<class T>
+struct types_when_isnt_ref
+{
+ typedef T const& reference_const_type ;
+ typedef T & reference_type ;
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ typedef T && rval_reference_type ;
+ typedef T && reference_type_of_temporary_wrapper;
+#ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
+ // GCC 4.4 has support for an early draft of rvalue references. The conforming version below
+ // causes warnings about returning references to a temporary.
+ static T&& move(T&& r) { return r; }
+#else
+ static rval_reference_type move(reference_type r) { return boost::move(r); }
+#endif
+#endif
+ typedef T const* pointer_const_type ;
+ typedef T * pointer_type ;
+ typedef T const& argument_type ;
+} ;
+
+template<class T>
+struct types_when_is_ref
+{
+ typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type raw_type ;
+
+ typedef raw_type& reference_const_type ;
+ typedef raw_type& reference_type ;
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ typedef BOOST_DEDUCED_TYPENAME remove_const<raw_type>::type&& rval_reference_type ;
+ typedef raw_type& reference_type_of_temporary_wrapper;
+ static reference_type move(reference_type r) { return r; }
+#endif
+ typedef raw_type* pointer_const_type ;
+ typedef raw_type* pointer_type ;
+ typedef raw_type& argument_type ;
+} ;
+
+template <class To, class From>
+void prevent_binding_rvalue_ref_to_optional_lvalue_ref()
+{
+#ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES
+ BOOST_STATIC_ASSERT_MSG(
+ !boost::is_lvalue_reference<To>::value || !boost::is_rvalue_reference<From>::value,
+ "binding rvalue references to optional lvalue references is disallowed");
+#endif
+}
+
+struct optional_tag {} ;
+
+template<class T>
+class optional_base : public optional_tag
+{
+ private :
+
+ typedef
+#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+ BOOST_DEDUCED_TYPENAME
+#endif
+ ::boost::detail::make_reference_content<T>::type internal_type ;
+
+ typedef aligned_storage<internal_type> storage_type ;
+
+ typedef types_when_isnt_ref<T> types_when_not_ref ;
+ typedef types_when_is_ref<T> types_when_ref ;
+
+ typedef optional_base<T> this_type ;
+
+ protected :
+
+ typedef T value_type ;
+
+ typedef mpl::true_ is_reference_tag ;
+ typedef mpl::false_ is_not_reference_tag ;
+
+ typedef BOOST_DEDUCED_TYPENAME is_reference<T>::type is_reference_predicate ;
+
+ public:
+ typedef BOOST_DEDUCED_TYPENAME mpl::if_<is_reference_predicate,types_when_ref,types_when_not_ref>::type types ;
+
+ protected:
+ typedef BOOST_DEDUCED_TYPENAME types::reference_type reference_type ;
+ typedef BOOST_DEDUCED_TYPENAME types::reference_const_type reference_const_type ;
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ typedef BOOST_DEDUCED_TYPENAME types::rval_reference_type rval_reference_type ;
+ typedef BOOST_DEDUCED_TYPENAME types::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ;
+#endif
+ typedef BOOST_DEDUCED_TYPENAME types::pointer_type pointer_type ;
+ typedef BOOST_DEDUCED_TYPENAME types::pointer_const_type pointer_const_type ;
+ typedef BOOST_DEDUCED_TYPENAME types::argument_type argument_type ;
+
+ // Creates an optional<T> uninitialized.
+ // No-throw
+ optional_base()
+ :
+ m_initialized(false) {}
+
+ // Creates an optional<T> uninitialized.
+ // No-throw
+ optional_base ( none_t )
+ :
+ m_initialized(false) {}
+
+ // Creates an optional<T> initialized with 'val'.
+ // Can throw if T::T(T const&) does
+ optional_base ( argument_type val )
+ :
+ m_initialized(false)
+ {
+ construct(val);
+ }
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // move-construct an optional<T> initialized from an rvalue-ref to 'val'.
+ // Can throw if T::T(T&&) does
+ optional_base ( rval_reference_type val )
+ :
+ m_initialized(false)
+ {
+ construct( boost::move(val) );
+ }
+#endif
+
+ // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialzed optional<T>.
+ // Can throw if T::T(T const&) does
+ optional_base ( bool cond, argument_type val )
+ :
+ m_initialized(false)
+ {
+ if ( cond )
+ construct(val);
+ }
+
+ // Creates a deep copy of another optional<T>
+ // Can throw if T::T(T const&) does
+ optional_base ( optional_base const& rhs )
+ :
+ m_initialized(false)
+ {
+ if ( rhs.is_initialized() )
+ construct(rhs.get_impl());
+ }
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Creates a deep move of another optional<T>
+ // Can throw if T::T(T&&) does
+ optional_base ( optional_base&& rhs )
+ :
+ m_initialized(false)
+ {
+ if ( rhs.is_initialized() )
+ construct( boost::move(rhs.get_impl()) );
+ }
+#endif
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+
+ template<class Expr, class PtrExpr>
+ explicit optional_base ( Expr&& expr, PtrExpr const* tag )
+ :
+ m_initialized(false)
+ {
+ construct(boost::forward<Expr>(expr),tag);
+ }
+
+#else
+ // This is used for both converting and in-place constructions.
+ // Derived classes use the 'tag' to select the appropriate
+ // implementation (the correct 'construct()' overload)
+ template<class Expr>
+ explicit optional_base ( Expr const& expr, Expr const* tag )
+ :
+ m_initialized(false)
+ {
+ construct(expr,tag);
+ }
+
+#endif
+
+
+ // No-throw (assuming T::~T() doesn't)
+ ~optional_base() { destroy() ; }
+
+ // Assigns from another optional<T> (deep-copies the rhs value)
+ void assign ( optional_base const& rhs )
+ {
+ if (is_initialized())
+ {
+ if ( rhs.is_initialized() )
+ assign_value(rhs.get_impl(), is_reference_predicate() );
+ else destroy();
+ }
+ else
+ {
+ if ( rhs.is_initialized() )
+ construct(rhs.get_impl());
+ }
+ }
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Assigns from another optional<T> (deep-moves the rhs value)
+ void assign ( optional_base&& rhs )
+ {
+ if (is_initialized())
+ {
+ if ( rhs.is_initialized() )
+ assign_value(boost::move(rhs.get_impl()), is_reference_predicate() );
+ else destroy();
+ }
+ else
+ {
+ if ( rhs.is_initialized() )
+ construct(boost::move(rhs.get_impl()));
+ }
+ }
+#endif
+
+ // Assigns from another _convertible_ optional<U> (deep-copies the rhs value)
+ template<class U>
+ void assign ( optional<U> const& rhs )
+ {
+ if (is_initialized())
+ {
+ if ( rhs.is_initialized() )
+#ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
+ assign_value(rhs.get(), is_reference_predicate() );
+#else
+ assign_value(static_cast<value_type>(rhs.get()), is_reference_predicate() );
+#endif
+
+ else destroy();
+ }
+ else
+ {
+ if ( rhs.is_initialized() )
+#ifndef BOOST_OPTIONAL_CONFIG_RESTORE_ASSIGNMENT_OF_NONCONVERTIBLE_TYPES
+ construct(rhs.get());
+#else
+ construct(static_cast<value_type>(rhs.get()));
+#endif
+ }
+ }
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // move-assigns from another _convertible_ optional<U> (deep-moves from the rhs value)
+ template<class U>
+ void assign ( optional<U>&& rhs )
+ {
+ typedef BOOST_DEDUCED_TYPENAME optional<U>::rval_reference_type ref_type;
+ if (is_initialized())
+ {
+ if ( rhs.is_initialized() )
+ assign_value(static_cast<ref_type>(rhs.get()), is_reference_predicate() );
+ else destroy();
+ }
+ else
+ {
+ if ( rhs.is_initialized() )
+ construct(static_cast<ref_type>(rhs.get()));
+ }
+ }
+#endif
+
+ // Assigns from a T (deep-copies the rhs value)
+ void assign ( argument_type val )
+ {
+ if (is_initialized())
+ assign_value(val, is_reference_predicate() );
+ else construct(val);
+ }
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Assigns from a T (deep-moves the rhs value)
+ void assign ( rval_reference_type val )
+ {
+ if (is_initialized())
+ assign_value( boost::move(val), is_reference_predicate() );
+ else construct( boost::move(val) );
+ }
+#endif
+
+ // Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
+ // No-throw (assuming T::~T() doesn't)
+ void assign ( none_t ) BOOST_NOEXCEPT { destroy(); }
+
+#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ template<class Expr, class ExprPtr>
+ void assign_expr ( Expr&& expr, ExprPtr const* tag )
+ {
+ if (is_initialized())
+ assign_expr_to_initialized(boost::forward<Expr>(expr),tag);
+ else construct(boost::forward<Expr>(expr),tag);
+ }
+#else
+ template<class Expr>
+ void assign_expr ( Expr const& expr, Expr const* tag )
+ {
+ if (is_initialized())
+ assign_expr_to_initialized(expr,tag);
+ else construct(expr,tag);
+ }
+#endif
+
+#endif
+
+ public :
+
+ // **DEPPRECATED** Destroys the current value, if any, leaving this UNINITIALIZED
+ // No-throw (assuming T::~T() doesn't)
+ void reset() BOOST_NOEXCEPT { destroy(); }
+
+ // **DEPPRECATED** Replaces the current value -if any- with 'val'
+ void reset ( argument_type val ) { assign(val); }
+
+ // Returns a pointer to the value if this is initialized, otherwise,
+ // returns NULL.
+ // No-throw
+ pointer_const_type get_ptr() const { return m_initialized ? get_ptr_impl() : 0 ; }
+ pointer_type get_ptr() { return m_initialized ? get_ptr_impl() : 0 ; }
+
+ bool is_initialized() const { return m_initialized ; }
+
+ protected :
+
+ void construct ( argument_type val )
+ {
+ ::new (m_storage.address()) internal_type(val) ;
+ m_initialized = true ;
+ }
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ void construct ( rval_reference_type val )
+ {
+ ::new (m_storage.address()) internal_type( types::move(val) ) ;
+ m_initialized = true ;
+ }
+#endif
+
+
+#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ // Constructs in-place
+ // upon exception *this is always uninitialized
+ template<class... Args>
+ void emplace_assign ( Args&&... args )
+ {
+ destroy();
+ ::new (m_storage.address()) internal_type( boost::forward<Args>(args)... );
+ m_initialized = true ;
+ }
+#elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
+ template<class Arg>
+ void emplace_assign ( Arg&& arg )
+ {
+ destroy();
+ ::new (m_storage.address()) internal_type( boost::forward<Arg>(arg) );
+ m_initialized = true ;
+ }
+
+ void emplace_assign ()
+ {
+ destroy();
+ ::new (m_storage.address()) internal_type();
+ m_initialized = true ;
+ }
+#else
+ template<class Arg>
+ void emplace_assign ( const Arg& arg )
+ {
+ destroy();
+ ::new (m_storage.address()) internal_type( arg );
+ m_initialized = true ;
+ }
+
+ template<class Arg>
+ void emplace_assign ( Arg& arg )
+ {
+ destroy();
+ ::new (m_storage.address()) internal_type( arg );
+ m_initialized = true ;
+ }
+
+ void emplace_assign ()
+ {
+ destroy();
+ ::new (m_storage.address()) internal_type();
+ m_initialized = true ;
+ }
+#endif
+
+#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Constructs in-place using the given factory
+ template<class Expr>
+ void construct ( Expr&& factory, in_place_factory_base const* )
+ {
+ BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
+ boost_optional_detail::construct<value_type>(factory, m_storage.address());
+ m_initialized = true ;
+ }
+
+ // Constructs in-place using the given typed factory
+ template<class Expr>
+ void construct ( Expr&& factory, typed_in_place_factory_base const* )
+ {
+ BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
+ factory.apply(m_storage.address()) ;
+ m_initialized = true ;
+ }
+
+ template<class Expr>
+ void assign_expr_to_initialized ( Expr&& factory, in_place_factory_base const* tag )
+ {
+ destroy();
+ construct(factory,tag);
+ }
+
+ // Constructs in-place using the given typed factory
+ template<class Expr>
+ void assign_expr_to_initialized ( Expr&& factory, typed_in_place_factory_base const* tag )
+ {
+ destroy();
+ construct(factory,tag);
+ }
+
+#else
+ // Constructs in-place using the given factory
+ template<class Expr>
+ void construct ( Expr const& factory, in_place_factory_base const* )
+ {
+ BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
+ boost_optional_detail::construct<value_type>(factory, m_storage.address());
+ m_initialized = true ;
+ }
+
+ // Constructs in-place using the given typed factory
+ template<class Expr>
+ void construct ( Expr const& factory, typed_in_place_factory_base const* )
+ {
+ BOOST_STATIC_ASSERT ( ::boost::mpl::not_<is_reference_predicate>::value ) ;
+ factory.apply(m_storage.address()) ;
+ m_initialized = true ;
+ }
+
+ template<class Expr>
+ void assign_expr_to_initialized ( Expr const& factory, in_place_factory_base const* tag )
+ {
+ destroy();
+ construct(factory,tag);
+ }
+
+ // Constructs in-place using the given typed factory
+ template<class Expr>
+ void assign_expr_to_initialized ( Expr const& factory, typed_in_place_factory_base const* tag )
+ {
+ destroy();
+ construct(factory,tag);
+ }
+#endif
+
+#endif
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Constructs using any expression implicitly convertible to the single argument
+ // of a one-argument T constructor.
+ // Converting constructions of optional<T> from optional<U> uses this function with
+ // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
+ template<class Expr>
+ void construct ( Expr&& expr, void const* )
+ {
+ new (m_storage.address()) internal_type(boost::forward<Expr>(expr)) ;
+ m_initialized = true ;
+ }
+
+ // Assigns using a form any expression implicitly convertible to the single argument
+ // of a T's assignment operator.
+ // Converting assignments of optional<T> from optional<U> uses this function with
+ // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
+ template<class Expr>
+ void assign_expr_to_initialized ( Expr&& expr, void const* )
+ {
+ assign_value(boost::forward<Expr>(expr), is_reference_predicate());
+ }
+#else
+ // Constructs using any expression implicitly convertible to the single argument
+ // of a one-argument T constructor.
+ // Converting constructions of optional<T> from optional<U> uses this function with
+ // 'Expr' being of type 'U' and relying on a converting constructor of T from U.
+ template<class Expr>
+ void construct ( Expr const& expr, void const* )
+ {
+ new (m_storage.address()) internal_type(expr) ;
+ m_initialized = true ;
+ }
+
+ // Assigns using a form any expression implicitly convertible to the single argument
+ // of a T's assignment operator.
+ // Converting assignments of optional<T> from optional<U> uses this function with
+ // 'Expr' being of type 'U' and relying on a converting assignment of T from U.
+ template<class Expr>
+ void assign_expr_to_initialized ( Expr const& expr, void const* )
+ {
+ assign_value(expr, is_reference_predicate());
+ }
+
+#endif
+
+#ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
+ // BCB5.64 (and probably lower versions) workaround.
+ // The in-place factories are supported by means of catch-all constructors
+ // and assignment operators (the functions are parameterized in terms of
+ // an arbitrary 'Expr' type)
+ // This compiler incorrectly resolves the overload set and sinks optional<T> and optional<U>
+ // to the 'Expr'-taking functions even though explicit overloads are present for them.
+ // Thus, the following overload is needed to properly handle the case when the 'lhs'
+ // is another optional.
+ //
+ // For VC<=70 compilers this workaround dosen't work becasue the comnpiler issues and error
+ // instead of choosing the wrong overload
+ //
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
+ template<class Expr>
+ void construct ( Expr&& expr, optional_tag const* )
+ {
+ if ( expr.is_initialized() )
+ {
+ // An exception can be thrown here.
+ // It it happens, THIS will be left uninitialized.
+ new (m_storage.address()) internal_type(types::move(expr.get())) ;
+ m_initialized = true ;
+ }
+ }
+#else
+ // Notice that 'Expr' will be optional<T> or optional<U> (but not optional_base<..>)
+ template<class Expr>
+ void construct ( Expr const& expr, optional_tag const* )
+ {
+ if ( expr.is_initialized() )
+ {
+ // An exception can be thrown here.
+ // It it happens, THIS will be left uninitialized.
+ new (m_storage.address()) internal_type(expr.get()) ;
+ m_initialized = true ;
+ }
+ }
+#endif
+#endif // defined BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
+
+ void assign_value ( argument_type val, is_not_reference_tag ) { get_impl() = val; }
+ void assign_value ( argument_type val, is_reference_tag ) { construct(val); }
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ void assign_value ( rval_reference_type val, is_not_reference_tag ) { get_impl() = static_cast<rval_reference_type>(val); }
+ void assign_value ( rval_reference_type val, is_reference_tag ) { construct( static_cast<rval_reference_type>(val) ); }
+#endif
+
+ void destroy()
+ {
+ if ( m_initialized )
+ destroy_impl(is_reference_predicate()) ;
+ }
+
+ reference_const_type get_impl() const { return dereference(get_object(), is_reference_predicate() ) ; }
+ reference_type get_impl() { return dereference(get_object(), is_reference_predicate() ) ; }
+
+ pointer_const_type get_ptr_impl() const { return cast_ptr(get_object(), is_reference_predicate() ) ; }
+ pointer_type get_ptr_impl() { return cast_ptr(get_object(), is_reference_predicate() ) ; }
+
+ private :
+
+ // internal_type can be either T or reference_content<T>
+#if defined(BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS)
+ // This workaround is supposed to silence GCC warnings about broken strict aliasing rules
+ internal_type const* get_object() const
+ {
+ union { void const* ap_pvoid; internal_type const* as_ptype; } caster = { m_storage.address() };
+ return caster.as_ptype;
+ }
+ internal_type * get_object()
+ {
+ union { void* ap_pvoid; internal_type* as_ptype; } caster = { m_storage.address() };
+ return caster.as_ptype;
+ }
+#else
+ internal_type const* get_object() const { return static_cast<internal_type const*>(m_storage.address()); }
+ internal_type * get_object() { return static_cast<internal_type *> (m_storage.address()); }
+#endif
+
+ // reference_content<T> lacks an implicit conversion to T&, so the following is needed to obtain a proper reference.
+ reference_const_type dereference( internal_type const* p, is_not_reference_tag ) const { return *p ; }
+ reference_type dereference( internal_type* p, is_not_reference_tag ) { return *p ; }
+ reference_const_type dereference( internal_type const* p, is_reference_tag ) const { return p->get() ; }
+ reference_type dereference( internal_type* p, is_reference_tag ) { return p->get() ; }
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))
+ void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->internal_type::~internal_type() ; m_initialized = false ; }
+#else
+ void destroy_impl ( is_not_reference_tag ) { get_ptr_impl()->~T() ; m_initialized = false ; }
+#endif
+
+ void destroy_impl ( is_reference_tag ) { m_initialized = false ; }
+
+ // If T is of reference type, trying to get a pointer to the held value must result in a compile-time error.
+ // Decent compilers should disallow conversions from reference_content<T>* to T*, but just in case,
+ // the following olverloads are used to filter out the case and guarantee an error in case of T being a reference.
+ pointer_const_type cast_ptr( internal_type const* p, is_not_reference_tag ) const { return p ; }
+ pointer_type cast_ptr( internal_type * p, is_not_reference_tag ) { return p ; }
+ pointer_const_type cast_ptr( internal_type const* p, is_reference_tag ) const { return &p->get() ; }
+ pointer_type cast_ptr( internal_type * p, is_reference_tag ) { return &p->get() ; }
+
+ bool m_initialized ;
+ storage_type m_storage ;
+} ;
+
+} // namespace optional_detail
+
+template<class T>
+class optional : public optional_detail::optional_base<T>
+{
+ typedef optional_detail::optional_base<T> base ;
+
+ public :
+
+ typedef optional<T> this_type ;
+
+ typedef BOOST_DEDUCED_TYPENAME base::value_type value_type ;
+ typedef BOOST_DEDUCED_TYPENAME base::reference_type reference_type ;
+ typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type ;
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ typedef BOOST_DEDUCED_TYPENAME base::rval_reference_type rval_reference_type ;
+ typedef BOOST_DEDUCED_TYPENAME base::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper ;
+#endif
+ typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type ;
+ typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type pointer_const_type ;
+ typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ;
+
+ // Creates an optional<T> uninitialized.
+ // No-throw
+ optional() BOOST_NOEXCEPT : base() {}
+
+ // Creates an optional<T> uninitialized.
+ // No-throw
+ optional( none_t none_ ) BOOST_NOEXCEPT : base(none_) {}
+
+ // Creates an optional<T> initialized with 'val'.
+ // Can throw if T::T(T const&) does
+ optional ( argument_type val ) : base(val) {}
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Creates an optional<T> initialized with 'move(val)'.
+ // Can throw if T::T(T &&) does
+ optional ( rval_reference_type val ) : base( boost::forward<T>(val) )
+ {optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, rval_reference_type>();}
+#endif
+
+ // Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
+ // Can throw if T::T(T const&) does
+ optional ( bool cond, argument_type val ) : base(cond,val) {}
+
+ // NOTE: MSVC needs templated versions first
+
+ // Creates a deep copy of another convertible optional<U>
+ // Requires a valid conversion from U to T.
+ // Can throw if T::T(U const&) does
+ template<class U>
+ explicit optional ( optional<U> const& rhs )
+ :
+ base()
+ {
+ if ( rhs.is_initialized() )
+ this->construct(rhs.get());
+ }
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Creates a deep move of another convertible optional<U>
+ // Requires a valid conversion from U to T.
+ // Can throw if T::T(U&&) does
+ template<class U>
+ explicit optional ( optional<U> && rhs )
+ :
+ base()
+ {
+ if ( rhs.is_initialized() )
+ this->construct( boost::move(rhs.get()) );
+ }
+#endif
+
+#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
+ // Creates an optional<T> with an expression which can be either
+ // (a) An instance of InPlaceFactory (i.e. in_place(a,b,...,n);
+ // (b) An instance of TypedInPlaceFactory ( i.e. in_place<T>(a,b,...,n);
+ // (c) Any expression implicitly convertible to the single type
+ // of a one-argument T's constructor.
+ // (d*) Weak compilers (BCB) might also resolved Expr as optional<T> and optional<U>
+ // even though explicit overloads are present for these.
+ // Depending on the above some T ctor is called.
+ // Can throw if the resolved T ctor throws.
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+
+
+ template<class Expr>
+ explicit optional ( Expr&& expr,
+ BOOST_DEDUCED_TYPENAME boost::disable_if_c<
+ (boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type>::value) ||
+ boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type, none_t>::value >::type* = 0
+ )
+ : base(boost::forward<Expr>(expr),boost::addressof(expr))
+ {optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, Expr&&>();}
+
+#else
+ template<class Expr>
+ explicit optional ( Expr const& expr ) : base(expr,boost::addressof(expr)) {}
+#endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+#endif // !defined BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
+
+ // Creates a deep copy of another optional<T>
+ // Can throw if T::T(T const&) does
+ optional ( optional const& rhs ) : base( static_cast<base const&>(rhs) ) {}
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Creates a deep move of another optional<T>
+ // Can throw if T::T(T&&) does
+ optional ( optional && rhs )
+ BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value)
+ : base( boost::move(rhs) )
+ {}
+
+#endif
+ // No-throw (assuming T::~T() doesn't)
+ ~optional() {}
+
+#if !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
+ // Assigns from an expression. See corresponding constructor.
+ // Basic Guarantee: If the resolved T ctor throws, this is left UNINITIALIZED
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+
+ template<class Expr>
+ BOOST_DEDUCED_TYPENAME boost::disable_if_c<
+ boost::is_base_of<optional_detail::optional_tag, BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type>::value ||
+ boost::is_same<BOOST_DEDUCED_TYPENAME boost::decay<Expr>::type, none_t>::value,
+ optional&
+ >::type
+ operator= ( Expr&& expr )
+ {
+ optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, Expr&&>();
+ this->assign_expr(boost::forward<Expr>(expr),boost::addressof(expr));
+ return *this ;
+ }
+
+#else
+ template<class Expr>
+ optional& operator= ( Expr const& expr )
+ {
+ this->assign_expr(expr,boost::addressof(expr));
+ return *this ;
+ }
+#endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+#endif // !defined(BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT) && !defined(BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION)
+
+ // Copy-assigns from another convertible optional<U> (converts && deep-copies the rhs value)
+ // Requires a valid conversion from U to T.
+ // Basic Guarantee: If T::T( U const& ) throws, this is left UNINITIALIZED
+ template<class U>
+ optional& operator= ( optional<U> const& rhs )
+ {
+ this->assign(rhs);
+ return *this ;
+ }
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Move-assigns from another convertible optional<U> (converts && deep-moves the rhs value)
+ // Requires a valid conversion from U to T.
+ // Basic Guarantee: If T::T( U && ) throws, this is left UNINITIALIZED
+ template<class U>
+ optional& operator= ( optional<U> && rhs )
+ {
+ this->assign(boost::move(rhs));
+ return *this ;
+ }
+#endif
+
+ // Assigns from another optional<T> (deep-copies the rhs value)
+ // Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED
+ // (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw)
+ optional& operator= ( optional const& rhs )
+ {
+ this->assign( static_cast<base const&>(rhs) ) ;
+ return *this ;
+ }
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Assigns from another optional<T> (deep-moves the rhs value)
+ optional& operator= ( optional && rhs )
+ BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
+ {
+ this->assign( static_cast<base &&>(rhs) ) ;
+ return *this ;
+ }
+#endif
+
+ // Assigns from a T (deep-copies the rhs value)
+ // Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED
+ optional& operator= ( argument_type val )
+ {
+ this->assign( val ) ;
+ return *this ;
+ }
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ // Assigns from a T (deep-moves the rhs value)
+ optional& operator= ( rval_reference_type val )
+ {
+ optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref<T, rval_reference_type>();
+ this->assign( boost::move(val) ) ;
+ return *this ;
+ }
+#endif
+
+ // Assigns from a "none"
+ // Which destroys the current value, if any, leaving this UNINITIALIZED
+ // No-throw (assuming T::~T() doesn't)
+ optional& operator= ( none_t none_ ) BOOST_NOEXCEPT
+ {
+ this->assign( none_ ) ;
+ return *this ;
+ }
+
+#if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ // Constructs in-place
+ // upon exception *this is always uninitialized
+ template<class... Args>
+ void emplace ( Args&&... args )
+ {
+ this->emplace_assign( boost::forward<Args>(args)... );
+ }
+#elif (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
+ template<class Arg>
+ void emplace ( Arg&& arg )
+ {
+ this->emplace_assign( boost::forward<Arg>(arg) );
+ }
+
+ void emplace ()
+ {
+ this->emplace_assign();
+ }
+#else
+ template<class Arg>
+ void emplace ( const Arg& arg )
+ {
+ this->emplace_assign( arg );
+ }
+
+ template<class Arg>
+ void emplace ( Arg& arg )
+ {
+ this->emplace_assign( arg );
+ }
+
+ void emplace ()
+ {
+ this->emplace_assign();
+ }
+#endif
+
+ void swap( optional & arg )
+ BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && ::boost::is_nothrow_move_assignable<T>::value)
+ {
+ // allow for Koenig lookup
+ boost::swap(*this, arg);
+ }
+
+
+ // Returns a reference to the value if this is initialized, otherwise,
+ // the behaviour is UNDEFINED
+ // No-throw
+ reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
+ reference_type get() { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
+
+ // Returns a copy of the value if this is initialized, 'v' otherwise
+ reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; }
+ reference_type get_value_or ( reference_type v ) { return this->is_initialized() ? get() : v ; }
+
+ // Returns a pointer to the value if this is initialized, otherwise,
+ // the behaviour is UNDEFINED
+ // No-throw
+ pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
+ pointer_type operator->() { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
+
+ // Returns a reference to the value if this is initialized, otherwise,
+ // the behaviour is UNDEFINED
+ // No-throw
+#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
+ reference_const_type operator *() const& { return this->get() ; }
+ reference_type operator *() & { return this->get() ; }
+ reference_type_of_temporary_wrapper operator *() && { return base::types::move(this->get()) ; }
+#else
+ reference_const_type operator *() const { return this->get() ; }
+ reference_type operator *() { return this->get() ; }
+#endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS
+
+#if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
+ reference_const_type value() const&
+ {
+ if (this->is_initialized())
+ return this->get() ;
+ else
+ throw_exception(bad_optional_access());
+ }
+
+ reference_type value() &
+ {
+ if (this->is_initialized())
+ return this->get() ;
+ else
+ throw_exception(bad_optional_access());
+ }
+
+ reference_type_of_temporary_wrapper value() &&
+ {
+ if (this->is_initialized())
+ return base::types::move(this->get()) ;
+ else
+ throw_exception(bad_optional_access());
+ }
+
+#else
+ reference_const_type value() const
+ {
+ if (this->is_initialized())
+ return this->get() ;
+ else
+ throw_exception(bad_optional_access());
+ }
+
+ reference_type value()
+ {
+ if (this->is_initialized())
+ return this->get() ;
+ else
+ throw_exception(bad_optional_access());
+ }
+#endif
+
+
+#ifndef BOOST_NO_CXX11_REF_QUALIFIERS
+ template <class U>
+ value_type value_or ( U&& v ) const&
+ {
+ if (this->is_initialized())
+ return get();
+ else
+ return boost::forward<U>(v);
+ }
+
+ template <class U>
+ value_type value_or ( U&& v ) &&
+ {
+ if (this->is_initialized())
+ return base::types::move(get());
+ else
+ return boost::forward<U>(v);
+ }
+#elif !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+ template <class U>
+ value_type value_or ( U&& v ) const
+ {
+ if (this->is_initialized())
+ return get();
+ else
+ return boost::forward<U>(v);
+ }
+#else
+ template <class U>
+ value_type value_or ( U const& v ) const
+ {
+ if (this->is_initialized())
+ return get();
+ else
+ return v;
+ }
+
+ template <class U>
+ value_type value_or ( U& v ) const
+ {
+ if (this->is_initialized())
+ return get();
+ else
+ return v;
+ }
+#endif
+
+
+#ifndef BOOST_NO_CXX11_REF_QUALIFIERS
+ template <typename F>
+ value_type value_or_eval ( F f ) const&
+ {
+ if (this->is_initialized())
+ return get();
+ else
+ return f();
+ }
+
+ template <typename F>
+ value_type value_or_eval ( F f ) &&
+ {
+ if (this->is_initialized())
+ return base::types::move(get());
+ else
+ return f();
+ }
+#else
+ template <typename F>
+ value_type value_or_eval ( F f ) const
+ {
+ if (this->is_initialized())
+ return get();
+ else
+ return f();
+ }
+#endif
+
+ bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; }
+
+ BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT()
+} ;
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+template<class T>
+class optional<T&&>
+{
+ BOOST_STATIC_ASSERT_MSG(sizeof(T) == 0, "Optional rvalue references are illegal.");
+} ;
+#endif
+
+// Returns optional<T>(v)
+template<class T>
+inline
+optional<T> make_optional ( T const& v )
+{
+ return optional<T>(v);
+}
+
+// Returns optional<T>(cond,v)
+template<class T>
+inline
+optional<T> make_optional ( bool cond, T const& v )
+{
+ return optional<T>(cond,v);
+}
+
+// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
+// No-throw
+template<class T>
+inline
+BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
+get ( optional<T> const& opt )
+{
+ return opt.get() ;
+}
+
+template<class T>
+inline
+BOOST_DEDUCED_TYPENAME optional<T>::reference_type
+get ( optional<T>& opt )
+{
+ return opt.get() ;
+}
+
+// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
+// No-throw
+template<class T>
+inline
+BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
+get ( optional<T> const* opt )
+{
+ return opt->get_ptr() ;
+}
+
+template<class T>
+inline
+BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
+get ( optional<T>* opt )
+{
+ return opt->get_ptr() ;
+}
+
+// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
+// No-throw
+template<class T>
+inline
+BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
+get_optional_value_or ( optional<T> const& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type v )
+{
+ return opt.get_value_or(v) ;
+}
+
+template<class T>
+inline
+BOOST_DEDUCED_TYPENAME optional<T>::reference_type
+get_optional_value_or ( optional<T>& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_type v )
+{
+ return opt.get_value_or(v) ;
+}
+
+// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
+// No-throw
+template<class T>
+inline
+BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
+get_pointer ( optional<T> const& opt )
+{
+ return opt.get_ptr() ;
+}
+
+template<class T>
+inline
+BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
+get_pointer ( optional<T>& opt )
+{
+ return opt.get_ptr() ;
+}
+
+// The following declaration prevents a bug where operator safe-bool is used upon streaming optional object if you forget the IO header.
+template<class CharType, class CharTrait>
+std::basic_ostream<CharType, CharTrait>&
+operator<<(std::basic_ostream<CharType, CharTrait>& os, optional_detail::optional_tag const&)
+{
+ BOOST_STATIC_ASSERT_MSG(sizeof(CharType) == 0, "If you want to output boost::optional, include header <boost/optional/optional_io.hpp>");
+ return os;
+}
+
+// optional's relational operators ( ==, !=, <, >, <=, >= ) have deep-semantics (compare values).
+// WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointess() in generic code instead.
+
+
+//
+// optional<T> vs optional<T> cases
+//
+
+template<class T>
+inline
+bool operator == ( optional<T> const& x, optional<T> const& y )
+{ return equal_pointees(x,y); }
+
+template<class T>
+inline
+bool operator < ( optional<T> const& x, optional<T> const& y )
+{ return less_pointees(x,y); }
+
+template<class T>
+inline
+bool operator != ( optional<T> const& x, optional<T> const& y )
+{ return !( x == y ) ; }
+
+template<class T>
+inline
+bool operator > ( optional<T> const& x, optional<T> const& y )
+{ return y < x ; }
+
+template<class T>
+inline
+bool operator <= ( optional<T> const& x, optional<T> const& y )
+{ return !( y < x ) ; }
+
+template<class T>
+inline
+bool operator >= ( optional<T> const& x, optional<T> const& y )
+{ return !( x < y ) ; }
+
+
+//
+// optional<T> vs T cases
+//
+template<class T>
+inline
+bool operator == ( optional<T> const& x, T const& y )
+{ return equal_pointees(x, optional<T>(y)); }
+
+template<class T>
+inline
+bool operator < ( optional<T> const& x, T const& y )
+{ return less_pointees(x, optional<T>(y)); }
+
+template<class T>
+inline
+bool operator != ( optional<T> const& x, T const& y )
+{ return !( x == y ) ; }
+
+template<class T>
+inline
+bool operator > ( optional<T> const& x, T const& y )
+{ return y < x ; }
+
+template<class T>
+inline
+bool operator <= ( optional<T> const& x, T const& y )
+{ return !( y < x ) ; }
+
+template<class T>
+inline
+bool operator >= ( optional<T> const& x, T const& y )
+{ return !( x < y ) ; }
+
+//
+// T vs optional<T> cases
+//
+
+template<class T>
+inline
+bool operator == ( T const& x, optional<T> const& y )
+{ return equal_pointees( optional<T>(x), y ); }
+
+template<class T>
+inline
+bool operator < ( T const& x, optional<T> const& y )
+{ return less_pointees( optional<T>(x), y ); }
+
+template<class T>
+inline
+bool operator != ( T const& x, optional<T> const& y )
+{ return !( x == y ) ; }
+
+template<class T>
+inline
+bool operator > ( T const& x, optional<T> const& y )
+{ return y < x ; }
+
+template<class T>
+inline
+bool operator <= ( T const& x, optional<T> const& y )
+{ return !( y < x ) ; }
+
+template<class T>
+inline
+bool operator >= ( T const& x, optional<T> const& y )
+{ return !( x < y ) ; }
+
+
+//
+// optional<T> vs none cases
+//
+
+template<class T>
+inline
+bool operator == ( optional<T> const& x, none_t ) BOOST_NOEXCEPT
+{ return !x; }
+
+template<class T>
+inline
+bool operator < ( optional<T> const& x, none_t )
+{ return less_pointees(x,optional<T>() ); }
+
+template<class T>
+inline
+bool operator != ( optional<T> const& x, none_t ) BOOST_NOEXCEPT
+{ return bool(x); }
+
+template<class T>
+inline
+bool operator > ( optional<T> const& x, none_t y )
+{ return y < x ; }
+
+template<class T>
+inline
+bool operator <= ( optional<T> const& x, none_t y )
+{ return !( y < x ) ; }
+
+template<class T>
+inline
+bool operator >= ( optional<T> const& x, none_t y )
+{ return !( x < y ) ; }
+
+//
+// none vs optional<T> cases
+//
+
+template<class T>
+inline
+bool operator == ( none_t , optional<T> const& y ) BOOST_NOEXCEPT
+{ return !y; }
+
+template<class T>
+inline
+bool operator < ( none_t , optional<T> const& y )
+{ return less_pointees(optional<T>() ,y); }
+
+template<class T>
+inline
+bool operator != ( none_t, optional<T> const& y ) BOOST_NOEXCEPT
+{ return bool(y); }
+
+template<class T>
+inline
+bool operator > ( none_t x, optional<T> const& y )
+{ return y < x ; }
+
+template<class T>
+inline
+bool operator <= ( none_t x, optional<T> const& y )
+{ return !( y < x ) ; }
+
+template<class T>
+inline
+bool operator >= ( none_t x, optional<T> const& y )
+{ return !( x < y ) ; }
+
+namespace optional_detail {
+
+template<bool use_default_constructor> struct swap_selector;
+
+template<>
+struct swap_selector<true>
+{
+ template<class T>
+ static void optional_swap ( optional<T>& x, optional<T>& y )
+ {
+ const bool hasX = !!x;
+ const bool hasY = !!y;
+
+ if ( !hasX && !hasY )
+ return;
+
+ if( !hasX )
+ x.emplace();
+ else if ( !hasY )
+ y.emplace();
+
+ // Boost.Utility.Swap will take care of ADL and workarounds for broken compilers
+ boost::swap(x.get(),y.get());
+
+ if( !hasX )
+ y = boost::none ;
+ else if( !hasY )
+ x = boost::none ;
+ }
+};
+
+#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+template<>
+struct swap_selector<false>
+{
+ template<class T>
+ static void optional_swap ( optional<T>& x, optional<T>& y )
+ //BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && BOOST_NOEXCEPT_EXPR(boost::swap(*x, *y)))
+ {
+ if(x)
+ {
+ if (y)
+ {
+ boost::swap(*x, *y);
+ }
+ else
+ {
+ y = boost::move(*x);
+ x = boost::none;
+ }
+ }
+ else
+ {
+ if (y)
+ {
+ x = boost::move(*y);
+ y = boost::none;
+ }
+ }
+ }
+};
+#else
+template<>
+struct swap_selector<false>
+{
+ template<class T>
+ static void optional_swap ( optional<T>& x, optional<T>& y )
+ {
+ const bool hasX = !!x;
+ const bool hasY = !!y;
+
+ if ( !hasX && hasY )
+ {
+ x = y.get();
+ y = boost::none ;
+ }
+ else if ( hasX && !hasY )
+ {
+ y = x.get();
+ x = boost::none ;
+ }
+ else if ( hasX && hasY )
+ {
+ // Boost.Utility.Swap will take care of ADL and workarounds for broken compilers
+ boost::swap(x.get(),y.get());
+ }
+ }
+};
+#endif // !defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
+
+} // namespace optional_detail
+
+#if (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) && (!defined BOOST_CONFIG_RESTORE_OBSOLETE_SWAP_IMPLEMENTATION)
+
+template<class T>
+struct optional_swap_should_use_default_constructor : boost::false_type {} ;
+
+#else
+
+template<class T>
+struct optional_swap_should_use_default_constructor : has_nothrow_default_constructor<T> {} ;
+
+#endif //BOOST_NO_CXX11_RVALUE_REFERENCES
+
+template<class T> inline void swap ( optional<T>& x, optional<T>& y )
+ //BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value && BOOST_NOEXCEPT_EXPR(boost::swap(*x, *y)))
+{
+ optional_detail::swap_selector<optional_swap_should_use_default_constructor<T>::value>::optional_swap(x, y);
+}
+
+} // namespace boost
+
+#endif
diff --git a/third_party/boost/boost/optional/optional_fwd.hpp b/third_party/boost/boost/optional/optional_fwd.hpp
new file mode 100644
index 0000000..162779a
--- /dev/null
+++ b/third_party/boost/boost/optional/optional_fwd.hpp
@@ -0,0 +1,29 @@
+// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
+//
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/optional for documentation.
+//
+// You are welcome to contact the author at:
+// fernando_cacciola@hotmail.com
+//
+// Revisions:
+// 10 May 2008 (added swap related forward declaration) Niels Dekker
+//
+#ifndef BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP
+#define BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP
+
+
+namespace boost {
+
+template<class T> class optional ;
+
+template<class T> void swap ( optional<T>& , optional<T>& );
+
+template<class T> struct optional_swap_should_use_default_constructor ;
+
+} // namespace boost
+
+#endif
diff --git a/third_party/boost/boost/predef.h b/third_party/boost/boost/predef.h
new file mode 100644
index 0000000..4965337
--- /dev/null
+++ b/third_party/boost/boost/predef.h
@@ -0,0 +1,24 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#if !defined(BOOST_PREDEF_H) || defined(BOOST_PREDEF_INTERNAL_GENERATE_TESTS)
+#ifndef BOOST_PREDEF_H
+#define BOOST_PREDEF_H
+#endif
+
+#include <boost/predef/language.h>
+#include <boost/predef/architecture.h>
+#include <boost/predef/compiler.h>
+#include <boost/predef/library.h>
+#include <boost/predef/os.h>
+#include <boost/predef/other.h>
+#include <boost/predef/platform.h>
+#include <boost/predef/hardware.h>
+
+#include <boost/predef/version.h>
+
+#endif
diff --git a/third_party/boost/boost/predef/architecture.h b/third_party/boost/boost/predef/architecture.h
new file mode 100644
index 0000000..c433d43
--- /dev/null
+++ b/third_party/boost/boost/predef/architecture.h
@@ -0,0 +1,32 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#if !defined(BOOST_PREDEF_ARCHITECTURE_H) || defined(BOOST_PREDEF_INTERNAL_GENERATE_TESTS)
+#ifndef BOOST_PREDEF_ARCHITECTURE_H
+#define BOOST_PREDEF_ARCHITECTURE_H
+#endif
+
+#include <boost/predef/architecture/alpha.h>
+#include <boost/predef/architecture/arm.h>
+#include <boost/predef/architecture/blackfin.h>
+#include <boost/predef/architecture/convex.h>
+#include <boost/predef/architecture/ia64.h>
+#include <boost/predef/architecture/m68k.h>
+#include <boost/predef/architecture/mips.h>
+#include <boost/predef/architecture/parisc.h>
+#include <boost/predef/architecture/ppc.h>
+#include <boost/predef/architecture/pyramid.h>
+#include <boost/predef/architecture/rs6k.h>
+#include <boost/predef/architecture/sparc.h>
+#include <boost/predef/architecture/superh.h>
+#include <boost/predef/architecture/sys370.h>
+#include <boost/predef/architecture/sys390.h>
+#include <boost/predef/architecture/x86.h>
+#include <boost/predef/architecture/z.h>
+/*#include <boost/predef/architecture/.h>*/
+
+#endif
diff --git a/third_party/boost/boost/predef/architecture/alpha.h b/third_party/boost/boost/predef/architecture/alpha.h
new file mode 100644
index 0000000..5bcade1
--- /dev/null
+++ b/third_party/boost/boost/predef/architecture/alpha.h
@@ -0,0 +1,59 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_ARCHITECTURE_ALPHA_H
+#define BOOST_PREDEF_ARCHITECTURE_ALPHA_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_ARCH_ALPHA`]
+
+[@http://en.wikipedia.org/wiki/DEC_Alpha DEC Alpha] architecture.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+ [[`__alpha__`] [__predef_detection__]]
+ [[`__alpha`] [__predef_detection__]]
+ [[`_M_ALPHA`] [__predef_detection__]]
+
+ [[`__alpha_ev4__`] [4.0.0]]
+ [[`__alpha_ev5__`] [5.0.0]]
+ [[`__alpha_ev6__`] [6.0.0]]
+ ]
+ */
+
+#define BOOST_ARCH_ALPHA BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__alpha__) || defined(__alpha) || \
+ defined(_M_ALPHA)
+# undef BOOST_ARCH_ALPHA
+# if !defined(BOOST_ARCH_ALPHA) && defined(__alpha_ev4__)
+# define BOOST_ARCH_ALPHA BOOST_VERSION_NUMBER(4,0,0)
+# endif
+# if !defined(BOOST_ARCH_ALPHA) && defined(__alpha_ev5__)
+# define BOOST_ARCH_ALPHA BOOST_VERSION_NUMBER(5,0,0)
+# endif
+# if !defined(BOOST_ARCH_ALPHA) && defined(__alpha_ev6__)
+# define BOOST_ARCH_ALPHA BOOST_VERSION_NUMBER(6,0,0)
+# endif
+# if !defined(BOOST_ARCH_ALPHA)
+# define BOOST_ARCH_ALPHA BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_ARCH_ALPHA
+# define BOOST_ARCH_ALPHA_AVAILABLE
+#endif
+
+#define BOOST_ARCH_ALPHA_NAME "DEC Alpha"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_ALPHA,BOOST_ARCH_ALPHA_NAME)
diff --git a/third_party/boost/boost/predef/architecture/arm.h b/third_party/boost/boost/predef/architecture/arm.h
new file mode 100644
index 0000000..b200c62
--- /dev/null
+++ b/third_party/boost/boost/predef/architecture/arm.h
@@ -0,0 +1,70 @@
+/*
+Copyright Rene Rivera 2008-2015
+Copyright Franz Detro 2014
+Copyright (c) Microsoft Corporation 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)
+*/
+
+#ifndef BOOST_PREDEF_ARCHITECTURE_ARM_H
+#define BOOST_PREDEF_ARCHITECTURE_ARM_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_ARCH_ARM`]
+
+[@http://en.wikipedia.org/wiki/ARM_architecture ARM] architecture.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__arm__`] [__predef_detection__]]
+ [[`__arm64`] [__predef_detection__]]
+ [[`__thumb__`] [__predef_detection__]]
+ [[`__TARGET_ARCH_ARM`] [__predef_detection__]]
+ [[`__TARGET_ARCH_THUMB`] [__predef_detection__]]
+ [[`_M_ARM`] [__predef_detection__]]
+
+ [[`__arm64`] [8.0.0]]
+ [[`__TARGET_ARCH_ARM`] [V.0.0]]
+ [[`__TARGET_ARCH_THUMB`] [V.0.0]]
+ [[`_M_ARM`] [V.0.0]]
+ ]
+ */
+
+#define BOOST_ARCH_ARM BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__arm__) || defined(__arm64) || defined(__thumb__) || \
+ defined(__TARGET_ARCH_ARM) || defined(__TARGET_ARCH_THUMB) || \
+ defined(_M_ARM)
+# undef BOOST_ARCH_ARM
+# if !defined(BOOST_ARCH_ARM) && defined(__arm64)
+# define BOOST_ARCH_ARM BOOST_VERSION_NUMBER(8,0,0)
+# endif
+# if !defined(BOOST_ARCH_ARM) && defined(__TARGET_ARCH_ARM)
+# define BOOST_ARCH_ARM BOOST_VERSION_NUMBER(__TARGET_ARCH_ARM,0,0)
+# endif
+# if !defined(BOOST_ARCH_ARM) && defined(__TARGET_ARCH_THUMB)
+# define BOOST_ARCH_ARM BOOST_VERSION_NUMBER(__TARGET_ARCH_THUMB,0,0)
+# endif
+# if !defined(BOOST_ARCH_ARM) && defined(_M_ARM)
+# define BOOST_ARCH_ARM BOOST_VERSION_NUMBER(_M_ARM,0,0)
+# endif
+# if !defined(BOOST_ARCH_ARM)
+# define BOOST_ARCH_ARM BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_ARCH_ARM
+# define BOOST_ARCH_ARM_AVAILABLE
+#endif
+
+#define BOOST_ARCH_ARM_NAME "ARM"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_ARM,BOOST_ARCH_ARM_NAME)
diff --git a/third_party/boost/boost/predef/architecture/blackfin.h b/third_party/boost/boost/predef/architecture/blackfin.h
new file mode 100644
index 0000000..84c58a2
--- /dev/null
+++ b/third_party/boost/boost/predef/architecture/blackfin.h
@@ -0,0 +1,46 @@
+/*
+Copyright Rene Rivera 2013-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_ARCHITECTURE_BLACKFIN_H
+#define BOOST_PREDEF_ARCHITECTURE_BLACKFIN_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_ARCH_BLACKFIN`]
+
+Blackfin Processors from Analog Devices.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__bfin__`] [__predef_detection__]]
+ [[`__BFIN__`] [__predef_detection__]]
+ [[`bfin`] [__predef_detection__]]
+ [[`BFIN`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_ARCH_BLACKFIN BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__bfin__) || defined(__BFIN__) || \
+ defined(bfin) || defined(BFIN)
+# undef BOOST_ARCH_BLACKFIN
+# define BOOST_ARCH_BLACKFIN BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_ARCH_BLACKFIN
+# define BOOST_ARCH_BLACKFIN_AVAILABLE
+#endif
+
+#define BOOST_ARCH_BLACKFIN_NAME "Blackfin"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_BLACKFIN,BOOST_ARCH_BLACKFIN_NAME)
diff --git a/third_party/boost/boost/predef/architecture/convex.h b/third_party/boost/boost/predef/architecture/convex.h
new file mode 100644
index 0000000..ac783a9
--- /dev/null
+++ b/third_party/boost/boost/predef/architecture/convex.h
@@ -0,0 +1,65 @@
+/*
+Copyright Rene Rivera 2011-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_ARCHITECTURE_CONVEX_H
+#define BOOST_PREDEF_ARCHITECTURE_CONVEX_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_ARCH_CONVEX`]
+
+[@http://en.wikipedia.org/wiki/Convex_Computer Convex Computer] architecture.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__convex__`] [__predef_detection__]]
+
+ [[`__convex_c1__`] [1.0.0]]
+ [[`__convex_c2__`] [2.0.0]]
+ [[`__convex_c32__`] [3.2.0]]
+ [[`__convex_c34__`] [3.4.0]]
+ [[`__convex_c38__`] [3.8.0]]
+ ]
+ */
+
+#define BOOST_ARCH_CONVEX BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__convex__)
+# undef BOOST_ARCH_CONVEX
+# if !defined(BOOST_ARCH_CONVEX) && defined(__convex_c1__)
+# define BOOST_ARCH_CONVEX BOOST_VERSION_NUMBER(1,0,0)
+# endif
+# if !defined(BOOST_ARCH_CONVEX) && defined(__convex_c2__)
+# define BOOST_ARCH_CONVEX BOOST_VERSION_NUMBER(2,0,0)
+# endif
+# if !defined(BOOST_ARCH_CONVEX) && defined(__convex_c32__)
+# define BOOST_ARCH_CONVEX BOOST_VERSION_NUMBER(3,2,0)
+# endif
+# if !defined(BOOST_ARCH_CONVEX) && defined(__convex_c34__)
+# define BOOST_ARCH_CONVEX BOOST_VERSION_NUMBER(3,4,0)
+# endif
+# if !defined(BOOST_ARCH_CONVEX) && defined(__convex_c38__)
+# define BOOST_ARCH_CONVEX BOOST_VERSION_NUMBER(3,8,0)
+# endif
+# if !defined(BOOST_ARCH_CONVEX)
+# define BOOST_ARCH_CONVEX BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_ARCH_CONVEX
+# define BOOST_ARCH_CONVEX_AVAILABLE
+#endif
+
+#define BOOST_ARCH_CONVEX_NAME "Convex Computer"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_CONVEX,BOOST_ARCH_CONVEX_NAME)
diff --git a/third_party/boost/boost/predef/architecture/ia64.h b/third_party/boost/boost/predef/architecture/ia64.h
new file mode 100644
index 0000000..9b1972b
--- /dev/null
+++ b/third_party/boost/boost/predef/architecture/ia64.h
@@ -0,0 +1,49 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_ARCHITECTURE_IA64_H
+#define BOOST_PREDEF_ARCHITECTURE_IA64_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_ARCH_IA64`]
+
+[@http://en.wikipedia.org/wiki/Ia64 Intel Itanium 64] architecture.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__ia64__`] [__predef_detection__]]
+ [[`_IA64`] [__predef_detection__]]
+ [[`__IA64__`] [__predef_detection__]]
+ [[`__ia64`] [__predef_detection__]]
+ [[`_M_IA64`] [__predef_detection__]]
+ [[`__itanium__`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_ARCH_IA64 BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__ia64__) || defined(_IA64) || \
+ defined(__IA64__) || defined(__ia64) || \
+ defined(_M_IA64) || defined(__itanium__)
+# undef BOOST_ARCH_IA64
+# define BOOST_ARCH_IA64 BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_ARCH_IA64
+# define BOOST_ARCH_IA64_AVAILABLE
+#endif
+
+#define BOOST_ARCH_IA64_NAME "Intel Itanium 64"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_IA64,BOOST_ARCH_IA64_NAME)
diff --git a/third_party/boost/boost/predef/architecture/m68k.h b/third_party/boost/boost/predef/architecture/m68k.h
new file mode 100644
index 0000000..63ed5f8
--- /dev/null
+++ b/third_party/boost/boost/predef/architecture/m68k.h
@@ -0,0 +1,82 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_ARCHITECTURE_M68K_H
+#define BOOST_PREDEF_ARCHITECTURE_M68K_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_ARCH_M68K`]
+
+[@http://en.wikipedia.org/wiki/M68k Motorola 68k] architecture.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__m68k__`] [__predef_detection__]]
+ [[`M68000`] [__predef_detection__]]
+
+ [[`__mc68060__`] [6.0.0]]
+ [[`mc68060`] [6.0.0]]
+ [[`__mc68060`] [6.0.0]]
+ [[`__mc68040__`] [4.0.0]]
+ [[`mc68040`] [4.0.0]]
+ [[`__mc68040`] [4.0.0]]
+ [[`__mc68030__`] [3.0.0]]
+ [[`mc68030`] [3.0.0]]
+ [[`__mc68030`] [3.0.0]]
+ [[`__mc68020__`] [2.0.0]]
+ [[`mc68020`] [2.0.0]]
+ [[`__mc68020`] [2.0.0]]
+ [[`__mc68010__`] [1.0.0]]
+ [[`mc68010`] [1.0.0]]
+ [[`__mc68010`] [1.0.0]]
+ [[`__mc68000__`] [0.0.1]]
+ [[`mc68000`] [0.0.1]]
+ [[`__mc68000`] [0.0.1]]
+ ]
+ */
+
+#define BOOST_ARCH_M68K BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__m68k__) || defined(M68000)
+# undef BOOST_ARCH_M68K
+# if !defined(BOOST_ARCH_M68K) && (defined(__mc68060__) || defined(mc68060) || defined(__mc68060))
+# define BOOST_ARCH_M68K BOOST_VERSION_NUMBER(6,0,0)
+# endif
+# if !defined(BOOST_ARCH_M68K) && (defined(__mc68040__) || defined(mc68040) || defined(__mc68040))
+# define BOOST_ARCH_M68K BOOST_VERSION_NUMBER(4,0,0)
+# endif
+# if !defined(BOOST_ARCH_M68K) && (defined(__mc68030__) || defined(mc68030) || defined(__mc68030))
+# define BOOST_ARCH_M68K BOOST_VERSION_NUMBER(3,0,0)
+# endif
+# if !defined(BOOST_ARCH_M68K) && (defined(__mc68020__) || defined(mc68020) || defined(__mc68020))
+# define BOOST_ARCH_M68K BOOST_VERSION_NUMBER(2,0,0)
+# endif
+# if !defined(BOOST_ARCH_M68K) && (defined(__mc68010__) || defined(mc68010) || defined(__mc68010))
+# define BOOST_ARCH_M68K BOOST_VERSION_NUMBER(1,0,0)
+# endif
+# if !defined(BOOST_ARCH_M68K) && (defined(__mc68000__) || defined(mc68000) || defined(__mc68000))
+# define BOOST_ARCH_M68K BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+# if !defined(BOOST_ARCH_M68K)
+# define BOOST_ARCH_M68K BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_ARCH_M68K
+# define BOOST_ARCH_M68K_AVAILABLE
+#endif
+
+#define BOOST_ARCH_M68K_NAME "Motorola 68k"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_M68K,BOOST_ARCH_M68K_NAME)
diff --git a/third_party/boost/boost/predef/architecture/mips.h b/third_party/boost/boost/predef/architecture/mips.h
new file mode 100644
index 0000000..0189d7d
--- /dev/null
+++ b/third_party/boost/boost/predef/architecture/mips.h
@@ -0,0 +1,73 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_ARCHITECTURE_MIPS_H
+#define BOOST_PREDEF_ARCHITECTURE_MIPS_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_ARCH_MIPS`]
+
+[@http://en.wikipedia.org/wiki/MIPS_architecture MIPS] architecture.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__mips__`] [__predef_detection__]]
+ [[`__mips`] [__predef_detection__]]
+ [[`__MIPS__`] [__predef_detection__]]
+
+ [[`__mips`] [V.0.0]]
+ [[`_MIPS_ISA_MIPS1`] [1.0.0]]
+ [[`_R3000`] [1.0.0]]
+ [[`_MIPS_ISA_MIPS2`] [2.0.0]]
+ [[`__MIPS_ISA2__`] [2.0.0]]
+ [[`_R4000`] [2.0.0]]
+ [[`_MIPS_ISA_MIPS3`] [3.0.0]]
+ [[`__MIPS_ISA3__`] [3.0.0]]
+ [[`_MIPS_ISA_MIPS4`] [4.0.0]]
+ [[`__MIPS_ISA4__`] [4.0.0]]
+ ]
+ */
+
+#define BOOST_ARCH_MIPS BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__mips__) || defined(__mips) || \
+ defined(__MIPS__)
+# undef BOOST_ARCH_MIPS
+# if !defined(BOOST_ARCH_MIPS) && (defined(__mips))
+# define BOOST_ARCH_MIPS BOOST_VERSION_NUMBER(__mips,0,0)
+# endif
+# if !defined(BOOST_ARCH_MIPS) && (defined(_MIPS_ISA_MIPS1) || defined(_R3000))
+# define BOOST_ARCH_MIPS BOOST_VERSION_NUMBER(1,0,0)
+# endif
+# if !defined(BOOST_ARCH_MIPS) && (defined(_MIPS_ISA_MIPS2) || defined(__MIPS_ISA2__) || defined(_R4000))
+# define BOOST_ARCH_MIPS BOOST_VERSION_NUMBER(2,0,0)
+# endif
+# if !defined(BOOST_ARCH_MIPS) && (defined(_MIPS_ISA_MIPS3) || defined(__MIPS_ISA3__))
+# define BOOST_ARCH_MIPS BOOST_VERSION_NUMBER(3,0,0)
+# endif
+# if !defined(BOOST_ARCH_MIPS) && (defined(_MIPS_ISA_MIPS4) || defined(__MIPS_ISA4__))
+# define BOOST_ARCH_MIPS BOOST_VERSION_NUMBER(4,0,0)
+# endif
+# if !defined(BOOST_ARCH_MIPS)
+# define BOOST_ARCH_MIPS BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_ARCH_MIPS
+# define BOOST_ARCH_MIPS_AVAILABLE
+#endif
+
+#define BOOST_ARCH_MIPS_NAME "MIPS"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_MIPS,BOOST_ARCH_MIPS_NAME)
diff --git a/third_party/boost/boost/predef/architecture/parisc.h b/third_party/boost/boost/predef/architecture/parisc.h
new file mode 100644
index 0000000..7c7625f
--- /dev/null
+++ b/third_party/boost/boost/predef/architecture/parisc.h
@@ -0,0 +1,64 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_ARCHITECTURE_PARISC_H
+#define BOOST_PREDEF_ARCHITECTURE_PARISC_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_ARCH_PARISK`]
+
+[@http://en.wikipedia.org/wiki/PA-RISC_family HP/PA RISC] architecture.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__hppa__`] [__predef_detection__]]
+ [[`__hppa`] [__predef_detection__]]
+ [[`__HPPA__`] [__predef_detection__]]
+
+ [[`_PA_RISC1_0`] [1.0.0]]
+ [[`_PA_RISC1_1`] [1.1.0]]
+ [[`__HPPA11__`] [1.1.0]]
+ [[`__PA7100__`] [1.1.0]]
+ [[`_PA_RISC2_0`] [2.0.0]]
+ [[`__RISC2_0__`] [2.0.0]]
+ [[`__HPPA20__`] [2.0.0]]
+ [[`__PA8000__`] [2.0.0]]
+ ]
+ */
+
+#define BOOST_ARCH_PARISC BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__hppa__) || defined(__hppa) || defined(__HPPA__)
+# undef BOOST_ARCH_PARISC
+# if !defined(BOOST_ARCH_PARISC) && (defined(_PA_RISC1_0))
+# define BOOST_ARCH_PARISC BOOST_VERSION_NUMBER(1,0,0)
+# endif
+# if !defined(BOOST_ARCH_PARISC) && (defined(_PA_RISC1_1) || defined(__HPPA11__) || defined(__PA7100__))
+# define BOOST_ARCH_PARISC BOOST_VERSION_NUMBER(1,1,0)
+# endif
+# if !defined(BOOST_ARCH_PARISC) && (defined(_PA_RISC2_0) || defined(__RISC2_0__) || defined(__HPPA20__) || defined(__PA8000__))
+# define BOOST_ARCH_PARISC BOOST_VERSION_NUMBER(2,0,0)
+# endif
+# if !defined(BOOST_ARCH_PARISC)
+# define BOOST_ARCH_PARISC BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_ARCH_PARISC
+# define BOOST_ARCH_PARISC_AVAILABLE
+#endif
+
+#define BOOST_ARCH_PARISC_NAME "HP/PA RISC"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_PARISC,BOOST_ARCH_PARISC_NAME)
diff --git a/third_party/boost/boost/predef/architecture/ppc.h b/third_party/boost/boost/predef/architecture/ppc.h
new file mode 100644
index 0000000..e8c57c9
--- /dev/null
+++ b/third_party/boost/boost/predef/architecture/ppc.h
@@ -0,0 +1,72 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_ARCHITECTURE_PPC_H
+#define BOOST_PREDEF_ARCHITECTURE_PPC_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_ARCH_PPC`]
+
+[@http://en.wikipedia.org/wiki/PowerPC PowerPC] architecture.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__powerpc`] [__predef_detection__]]
+ [[`__powerpc__`] [__predef_detection__]]
+ [[`__POWERPC__`] [__predef_detection__]]
+ [[`__ppc__`] [__predef_detection__]]
+ [[`_M_PPC`] [__predef_detection__]]
+ [[`_ARCH_PPC`] [__predef_detection__]]
+ [[`__PPCGECKO__`] [__predef_detection__]]
+ [[`__PPCBROADWAY__`] [__predef_detection__]]
+ [[`_XENON`] [__predef_detection__]]
+
+ [[`__ppc601__`] [6.1.0]]
+ [[`_ARCH_601`] [6.1.0]]
+ [[`__ppc603__`] [6.3.0]]
+ [[`_ARCH_603`] [6.3.0]]
+ [[`__ppc604__`] [6.4.0]]
+ [[`__ppc604__`] [6.4.0]]
+ ]
+ */
+
+#define BOOST_ARCH_PPC BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__powerpc) || defined(__powerpc__) || \
+ defined(__POWERPC__) || defined(__ppc__) || \
+ defined(_M_PPC) || defined(_ARCH_PPC) || \
+ defined(__PPCGECKO__) || defined(__PPCBROADWAY__) || \
+ defined(_XENON)
+# undef BOOST_ARCH_PPC
+# if !defined (BOOST_ARCH_PPC) && (defined(__ppc601__) || defined(_ARCH_601))
+# define BOOST_ARCH_PPC BOOST_VERSION_NUMBER(6,1,0)
+# endif
+# if !defined (BOOST_ARCH_PPC) && (defined(__ppc603__) || defined(_ARCH_603))
+# define BOOST_ARCH_PPC BOOST_VERSION_NUMBER(6,3,0)
+# endif
+# if !defined (BOOST_ARCH_PPC) && (defined(__ppc604__) || defined(__ppc604__))
+# define BOOST_ARCH_PPC BOOST_VERSION_NUMBER(6,4,0)
+# endif
+# if !defined (BOOST_ARCH_PPC)
+# define BOOST_ARCH_PPC BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_ARCH_PPC
+# define BOOST_ARCH_PPC_AVAILABLE
+#endif
+
+#define BOOST_ARCH_PPC_NAME "PowerPC"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_PPC,BOOST_ARCH_PPC_NAME)
diff --git a/third_party/boost/boost/predef/architecture/pyramid.h b/third_party/boost/boost/predef/architecture/pyramid.h
new file mode 100644
index 0000000..4f13253
--- /dev/null
+++ b/third_party/boost/boost/predef/architecture/pyramid.h
@@ -0,0 +1,42 @@
+/*
+Copyright Rene Rivera 2011-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_ARCHITECTURE_PYRAMID_H
+#define BOOST_PREDEF_ARCHITECTURE_PYRAMID_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_ARCH_PYRAMID`]
+
+Pyramid 9810 architecture.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`pyr`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_ARCH_PYRAMID BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(pyr)
+# undef BOOST_ARCH_PYRAMID
+# define BOOST_ARCH_PYRAMID BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_ARCH_PYRAMID
+# define BOOST_ARCH_PYRAMID_AVAILABLE
+#endif
+
+#define BOOST_ARCH_PYRAMID_NAME "Pyramid 9810"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_PYRAMID,BOOST_ARCH_PYRAMID_NAME)
diff --git a/third_party/boost/boost/predef/architecture/rs6k.h b/third_party/boost/boost/predef/architecture/rs6k.h
new file mode 100644
index 0000000..8a6e9b6
--- /dev/null
+++ b/third_party/boost/boost/predef/architecture/rs6k.h
@@ -0,0 +1,56 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_ARCHITECTURE_RS6K_H
+#define BOOST_PREDEF_ARCHITECTURE_RS6K_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_ARCH_RS6000`]
+
+[@http://en.wikipedia.org/wiki/RS/6000 RS/6000] architecture.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__THW_RS6000`] [__predef_detection__]]
+ [[`_IBMR2`] [__predef_detection__]]
+ [[`_POWER`] [__predef_detection__]]
+ [[`_ARCH_PWR`] [__predef_detection__]]
+ [[`_ARCH_PWR2`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_ARCH_RS6000 BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__THW_RS6000) || defined(_IBMR2) || \
+ defined(_POWER) || defined(_ARCH_PWR) || \
+ defined(_ARCH_PWR2)
+# undef BOOST_ARCH_RS6000
+# define BOOST_ARCH_RS6000 BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_ARCH_RS6000
+# define BOOST_ARCH_RS6000_AVAILABLE
+#endif
+
+#define BOOST_ARCH_RS6000_NAME "RS/6000"
+
+#define BOOST_ARCH_PWR BOOST_ARCH_RS6000
+
+#if BOOST_ARCH_PWR
+# define BOOST_ARCH_PWR_AVAILABLE
+#endif
+
+#define BOOST_ARCH_PWR_NAME BOOST_ARCH_RS6000_NAME
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_RS6000,BOOST_ARCH_RS6000_NAME)
diff --git a/third_party/boost/boost/predef/architecture/sparc.h b/third_party/boost/boost/predef/architecture/sparc.h
new file mode 100644
index 0000000..a89a510
--- /dev/null
+++ b/third_party/boost/boost/predef/architecture/sparc.h
@@ -0,0 +1,54 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_ARCHITECTURE_SPARC_H
+#define BOOST_PREDEF_ARCHITECTURE_SPARC_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_ARCH_SPARC`]
+
+[@http://en.wikipedia.org/wiki/SPARC SPARC] architecture.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__sparc__`] [__predef_detection__]]
+ [[`__sparc`] [__predef_detection__]]
+
+ [[`__sparcv9`] [9.0.0]]
+ [[`__sparcv8`] [8.0.0]]
+ ]
+ */
+
+#define BOOST_ARCH_SPARC BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__sparc__) || defined(__sparc)
+# undef BOOST_ARCH_SPARC
+# if !defined(BOOST_ARCH_SPARC) && defined(__sparcv9)
+# define BOOST_ARCH_SPARC BOOST_VERSION_NUMBER(9,0,0)
+# endif
+# if !defined(BOOST_ARCH_SPARC) && defined(__sparcv8)
+# define BOOST_ARCH_SPARC BOOST_VERSION_NUMBER(8,0,0)
+# endif
+# if !defined(BOOST_ARCH_SPARC)
+# define BOOST_ARCH_SPARC BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_ARCH_SPARC
+# define BOOST_ARCH_SPARC_AVAILABLE
+#endif
+
+#define BOOST_ARCH_SPARC_NAME "SPARC"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_SPARC,BOOST_ARCH_SPARC_NAME)
diff --git a/third_party/boost/boost/predef/architecture/superh.h b/third_party/boost/boost/predef/architecture/superh.h
new file mode 100644
index 0000000..da0529e
--- /dev/null
+++ b/third_party/boost/boost/predef/architecture/superh.h
@@ -0,0 +1,67 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_ARCHITECTURE_SUPERH_H
+#define BOOST_PREDEF_ARCHITECTURE_SUPERH_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_ARCH_SH`]
+
+[@http://en.wikipedia.org/wiki/SuperH SuperH] architecture:
+If available versions \[1-5\] are specifically detected.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__sh__`] [__predef_detection__]]
+
+ [[`__SH5__`] [5.0.0]]
+ [[`__SH4__`] [4.0.0]]
+ [[`__sh3__`] [3.0.0]]
+ [[`__SH3__`] [3.0.0]]
+ [[`__sh2__`] [2.0.0]]
+ [[`__sh1__`] [1.0.0]]
+ ]
+ */
+
+#define BOOST_ARCH_SH BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__sh__)
+# undef BOOST_ARCH_SH
+# if !defined(BOOST_ARCH_SH) && (defined(__SH5__))
+# define BOOST_ARCH_SH BOOST_VERSION_NUMBER(5,0,0)
+# endif
+# if !defined(BOOST_ARCH_SH) && (defined(__SH4__))
+# define BOOST_ARCH_SH BOOST_VERSION_NUMBER(4,0,0)
+# endif
+# if !defined(BOOST_ARCH_SH) && (defined(__sh3__) || defined(__SH3__))
+# define BOOST_ARCH_SH BOOST_VERSION_NUMBER(3,0,0)
+# endif
+# if !defined(BOOST_ARCH_SH) && (defined(__sh2__))
+# define BOOST_ARCH_SH BOOST_VERSION_NUMBER(2,0,0)
+# endif
+# if !defined(BOOST_ARCH_SH) && (defined(__sh1__))
+# define BOOST_ARCH_SH BOOST_VERSION_NUMBER(1,0,0)
+# endif
+# if !defined(BOOST_ARCH_SH)
+# define BOOST_ARCH_SH BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_ARCH_SH
+# define BOOST_ARCH_SH_AVAILABLE
+#endif
+
+#define BOOST_ARCH_SH_NAME "SuperH"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_SH,BOOST_ARCH_SH_NAME)
diff --git a/third_party/boost/boost/predef/architecture/sys370.h b/third_party/boost/boost/predef/architecture/sys370.h
new file mode 100644
index 0000000..cfd85dc
--- /dev/null
+++ b/third_party/boost/boost/predef/architecture/sys370.h
@@ -0,0 +1,43 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_ARCHITECTURE_SYS370_H
+#define BOOST_PREDEF_ARCHITECTURE_SYS370_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_ARCH_SYS370`]
+
+[@http://en.wikipedia.org/wiki/System/370 System/370] architecture.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__370__`] [__predef_detection__]]
+ [[`__THW_370__`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_ARCH_SYS370 BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__370__) || defined(__THW_370__)
+# undef BOOST_ARCH_SYS370
+# define BOOST_ARCH_SYS370 BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_ARCH_SYS370
+# define BOOST_ARCH_SYS370_AVAILABLE
+#endif
+
+#define BOOST_ARCH_SYS370_NAME "System/370"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_SYS370,BOOST_ARCH_SYS370_NAME)
diff --git a/third_party/boost/boost/predef/architecture/sys390.h b/third_party/boost/boost/predef/architecture/sys390.h
new file mode 100644
index 0000000..47aff6a
--- /dev/null
+++ b/third_party/boost/boost/predef/architecture/sys390.h
@@ -0,0 +1,43 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_ARCHITECTURE_SYS390_H
+#define BOOST_PREDEF_ARCHITECTURE_SYS390_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_ARCH_SYS390`]
+
+[@http://en.wikipedia.org/wiki/System/390 System/390] architecture.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__s390__`] [__predef_detection__]]
+ [[`__s390x__`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_ARCH_SYS390 BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__s390__) || defined(__s390x__)
+# undef BOOST_ARCH_SYS390
+# define BOOST_ARCH_SYS390 BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_ARCH_SYS390
+# define BOOST_ARCH_SYS390_AVAILABLE
+#endif
+
+#define BOOST_ARCH_SYS390_NAME "System/390"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_SYS390,BOOST_ARCH_SYS390_NAME)
diff --git a/third_party/boost/boost/predef/architecture/x86.h b/third_party/boost/boost/predef/architecture/x86.h
new file mode 100644
index 0000000..0ef3ef4
--- /dev/null
+++ b/third_party/boost/boost/predef/architecture/x86.h
@@ -0,0 +1,38 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the 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/predef/architecture/x86/32.h>
+#include <boost/predef/architecture/x86/64.h>
+
+#ifndef BOOST_PREDEF_ARCHITECTURE_X86_H
+#define BOOST_PREDEF_ARCHITECTURE_X86_H
+
+/*`
+[heading `BOOST_ARCH_X86`]
+
+[@http://en.wikipedia.org/wiki/X86 Intel x86] architecture. This is
+a category to indicate that either `BOOST_ARCH_X86_32` or
+`BOOST_ARCH_X86_64` is detected.
+ */
+
+#define BOOST_ARCH_X86 BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if BOOST_ARCH_X86_32 || BOOST_ARCH_X86_64
+# undef BOOST_ARCH_X86
+# define BOOST_ARCH_X86 BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_ARCH_X86
+# define BOOST_ARCH_X86_AVAILABLE
+#endif
+
+#define BOOST_ARCH_X86_NAME "Intel x86"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_X86,BOOST_ARCH_X86_NAME)
diff --git a/third_party/boost/boost/predef/architecture/x86/32.h b/third_party/boost/boost/predef/architecture/x86/32.h
new file mode 100644
index 0000000..17fbff5
--- /dev/null
+++ b/third_party/boost/boost/predef/architecture/x86/32.h
@@ -0,0 +1,87 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_ARCHITECTURE_X86_32_H
+#define BOOST_PREDEF_ARCHITECTURE_X86_32_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_ARCH_X86_32`]
+
+[@http://en.wikipedia.org/wiki/X86 Intel x86] architecture:
+If available versions \[3-6\] are specifically detected.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`i386`] [__predef_detection__]]
+ [[`__i386__`] [__predef_detection__]]
+ [[`__i486__`] [__predef_detection__]]
+ [[`__i586__`] [__predef_detection__]]
+ [[`__i686__`] [__predef_detection__]]
+ [[`__i386`] [__predef_detection__]]
+ [[`_M_IX86`] [__predef_detection__]]
+ [[`_X86_`] [__predef_detection__]]
+ [[`__THW_INTEL__`] [__predef_detection__]]
+ [[`__I86__`] [__predef_detection__]]
+ [[`__INTEL__`] [__predef_detection__]]
+
+ [[`__I86__`] [V.0.0]]
+ [[`_M_IX86`] [V.0.0]]
+ [[`__i686__`] [6.0.0]]
+ [[`__i586__`] [5.0.0]]
+ [[`__i486__`] [4.0.0]]
+ [[`__i386__`] [3.0.0]]
+ ]
+ */
+
+#define BOOST_ARCH_X86_32 BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(i386) || defined(__i386__) || \
+ defined(__i486__) || defined(__i586__) || \
+ defined(__i686__) || defined(__i386) || \
+ defined(_M_IX86) || defined(_X86_) || \
+ defined(__THW_INTEL__) || defined(__I86__) || \
+ defined(__INTEL__)
+# undef BOOST_ARCH_X86_32
+# if !defined(BOOST_ARCH_X86_32) && defined(__I86__)
+# define BOOST_ARCH_X86_32 BOOST_VERSION_NUMBER(__I86__,0,0)
+# endif
+# if !defined(BOOST_ARCH_X86_32) && defined(_M_IX86)
+# define BOOST_ARCH_X86_32 BOOST_PREDEF_MAKE_10_VV00(_M_IX86)
+# endif
+# if !defined(BOOST_ARCH_X86_32) && defined(__i686__)
+# define BOOST_ARCH_X86_32 BOOST_VERSION_NUMBER(6,0,0)
+# endif
+# if !defined(BOOST_ARCH_X86_32) && defined(__i586__)
+# define BOOST_ARCH_X86_32 BOOST_VERSION_NUMBER(5,0,0)
+# endif
+# if !defined(BOOST_ARCH_X86_32) && defined(__i486__)
+# define BOOST_ARCH_X86_32 BOOST_VERSION_NUMBER(4,0,0)
+# endif
+# if !defined(BOOST_ARCH_X86_32) && defined(__i386__)
+# define BOOST_ARCH_X86_32 BOOST_VERSION_NUMBER(3,0,0)
+# endif
+# if !defined(BOOST_ARCH_X86_32)
+# define BOOST_ARCH_X86_32 BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_ARCH_X86_32
+# define BOOST_ARCH_X86_32_AVAILABLE
+#endif
+
+#define BOOST_ARCH_X86_32_NAME "Intel x86-32"
+
+#include <boost/predef/architecture/x86.h>
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_X86_32,BOOST_ARCH_X86_32_NAME)
diff --git a/third_party/boost/boost/predef/architecture/x86/64.h b/third_party/boost/boost/predef/architecture/x86/64.h
new file mode 100644
index 0000000..f761c92
--- /dev/null
+++ b/third_party/boost/boost/predef/architecture/x86/64.h
@@ -0,0 +1,50 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_ARCHITECTURE_X86_64_H
+#define BOOST_PREDEF_ARCHITECTURE_X86_64_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_ARCH_X86_64`]
+
+[@http://en.wikipedia.org/wiki/Ia64 Intel IA-64] architecture.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__x86_64`] [__predef_detection__]]
+ [[`__x86_64__`] [__predef_detection__]]
+ [[`__amd64__`] [__predef_detection__]]
+ [[`__amd64`] [__predef_detection__]]
+ [[`_M_X64`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_ARCH_X86_64 BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__x86_64) || defined(__x86_64__) || \
+ defined(__amd64__) || defined(__amd64) || \
+ defined(_M_X64)
+# undef BOOST_ARCH_X86_64
+# define BOOST_ARCH_X86_64 BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_ARCH_X86_64
+# define BOOST_ARCH_X86_64_AVAILABLE
+#endif
+
+#define BOOST_ARCH_X86_64_NAME "Intel x86-64"
+
+#include <boost/predef/architecture/x86.h>
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_X86_64,BOOST_ARCH_X86_64_NAME)
diff --git a/third_party/boost/boost/predef/architecture/z.h b/third_party/boost/boost/predef/architecture/z.h
new file mode 100644
index 0000000..3d218aa
--- /dev/null
+++ b/third_party/boost/boost/predef/architecture/z.h
@@ -0,0 +1,42 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_ARCHITECTURE_Z_H
+#define BOOST_PREDEF_ARCHITECTURE_Z_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_ARCH_Z`]
+
+[@http://en.wikipedia.org/wiki/Z/Architecture z/Architecture] architecture.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__SYSC_ZARCH__`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_ARCH_Z BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__SYSC_ZARCH__)
+# undef BOOST_ARCH_Z
+# define BOOST_ARCH_Z BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_ARCH_Z
+# define BOOST_ARCH_Z_AVAILABLE
+#endif
+
+#define BOOST_ARCH_Z_NAME "z/Architecture"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_ARCH_Z,BOOST_ARCH_Z_NAME)
diff --git a/third_party/boost/boost/predef/compiler.h b/third_party/boost/boost/predef/compiler.h
new file mode 100644
index 0000000..61a4c52
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler.h
@@ -0,0 +1,43 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#if !defined(BOOST_PREDEF_COMPILER_H) || defined(BOOST_PREDEF_INTERNAL_GENERATE_TESTS)
+#ifndef BOOST_PREDEF_COMPILER_H
+#define BOOST_PREDEF_COMPILER_H
+#endif
+
+#include <boost/predef/compiler/borland.h>
+#include <boost/predef/compiler/clang.h>
+#include <boost/predef/compiler/comeau.h>
+#include <boost/predef/compiler/compaq.h>
+#include <boost/predef/compiler/diab.h>
+#include <boost/predef/compiler/digitalmars.h>
+#include <boost/predef/compiler/dignus.h>
+#include <boost/predef/compiler/edg.h>
+#include <boost/predef/compiler/ekopath.h>
+#include <boost/predef/compiler/gcc_xml.h>
+#include <boost/predef/compiler/gcc.h>
+#include <boost/predef/compiler/greenhills.h>
+#include <boost/predef/compiler/hp_acc.h>
+#include <boost/predef/compiler/iar.h>
+#include <boost/predef/compiler/ibm.h>
+#include <boost/predef/compiler/intel.h>
+#include <boost/predef/compiler/kai.h>
+#include <boost/predef/compiler/llvm.h>
+#include <boost/predef/compiler/metaware.h>
+#include <boost/predef/compiler/metrowerks.h>
+#include <boost/predef/compiler/microtec.h>
+#include <boost/predef/compiler/mpw.h>
+#include <boost/predef/compiler/palm.h>
+#include <boost/predef/compiler/pgi.h>
+#include <boost/predef/compiler/sgi_mipspro.h>
+#include <boost/predef/compiler/sunpro.h>
+#include <boost/predef/compiler/tendra.h>
+#include <boost/predef/compiler/visualc.h>
+#include <boost/predef/compiler/watcom.h>
+
+#endif
diff --git a/third_party/boost/boost/predef/compiler/borland.h b/third_party/boost/boost/predef/compiler/borland.h
new file mode 100644
index 0000000..3677cca
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/borland.h
@@ -0,0 +1,63 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_BORLAND_H
+#define BOOST_PREDEF_COMPILER_BORLAND_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_BORLAND`]
+
+[@http://en.wikipedia.org/wiki/C_plus_plus_builder Borland C++] compiler.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__BORLANDC__`] [__predef_detection__]]
+ [[`__CODEGEARC__`] [__predef_detection__]]
+
+ [[`__BORLANDC__`] [V.R.P]]
+ [[`__CODEGEARC__`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_COMP_BORLAND BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__BORLANDC__) || defined(__CODEGEARC__)
+# if !defined(BOOST_COMP_BORLAND_DETECTION) && (defined(__CODEGEARC__))
+# define BOOST_COMP_BORLAND_DETECTION BOOST_PREDEF_MAKE_0X_VVRP(__CODEGEARC__)
+# endif
+# if !defined(BOOST_COMP_BORLAND_DETECTION)
+# define BOOST_COMP_BORLAND_DETECTION BOOST_PREDEF_MAKE_0X_VVRP(__BORLANDC__)
+# endif
+#endif
+
+#ifdef BOOST_COMP_BORLAND_DETECTION
+# define BOOST_COMP_BORLAND_AVAILABLE
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_BORLAND_EMULATED BOOST_COMP_BORLAND_DETECTION
+# else
+# undef BOOST_COMP_BORLAND
+# define BOOST_COMP_BORLAND BOOST_COMP_BORLAND_DETECTION
+# endif
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_BORLAND_NAME "Borland C++"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_BORLAND,BOOST_COMP_BORLAND_NAME)
+
+#ifdef BOOST_COMP_BORLAND_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_BORLAND_EMULATED,BOOST_COMP_BORLAND_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/clang.h b/third_party/boost/boost/predef/compiler/clang.h
new file mode 100644
index 0000000..56678fe
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/clang.h
@@ -0,0 +1,56 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_CLANG_H
+#define BOOST_PREDEF_COMPILER_CLANG_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_CLANG`]
+
+[@http://en.wikipedia.org/wiki/Clang Clang] compiler.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__clang__`] [__predef_detection__]]
+
+ [[`__clang_major__`, `__clang_minor__`, `__clang_patchlevel__`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_COMP_CLANG BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__clang__)
+# define BOOST_COMP_CLANG_DETECTION BOOST_VERSION_NUMBER(__clang_major__,__clang_minor__,__clang_patchlevel__)
+#endif
+
+#ifdef BOOST_COMP_CLANG_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_CLANG_EMULATED BOOST_COMP_CLANG_DETECTION
+# else
+# undef BOOST_COMP_CLANG
+# define BOOST_COMP_CLANG BOOST_COMP_CLANG_DETECTION
+# endif
+# define BOOST_COMP_CLANG_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_CLANG_NAME "Clang"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_CLANG,BOOST_COMP_CLANG_NAME)
+
+#ifdef BOOST_COMP_CLANG_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_CLANG_EMULATED,BOOST_COMP_CLANG_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/comeau.h b/third_party/boost/boost/predef/compiler/comeau.h
new file mode 100644
index 0000000..15a4564
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/comeau.h
@@ -0,0 +1,61 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_COMEAU_H
+#define BOOST_PREDEF_COMPILER_COMEAU_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+#define BOOST_COMP_COMO BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+/*`
+[heading `BOOST_COMP_COMO`]
+
+[@http://en.wikipedia.org/wiki/Comeau_C/C%2B%2B Comeau C++] compiler.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__COMO__`] [__predef_detection__]]
+
+ [[`__COMO_VERSION__`] [V.R.P]]
+ ]
+ */
+
+#if defined(__COMO__)
+# if !defined(BOOST_COMP_COMO_DETECTION) && defined(__COMO_VERSION__)
+# define BOOST_COMP_COMO_DETECTION BOOST_PREDEF_MAKE_0X_VRP(__COMO_VERSION__)
+# endif
+# if !defined(BOOST_COMP_COMO_DETECTION)
+# define BOOST_COMP_COMO_DETECTION BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#ifdef BOOST_COMP_COMO_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_COMO_EMULATED BOOST_COMP_COMO_DETECTION
+# else
+# undef BOOST_COMP_COMO
+# define BOOST_COMP_COMO BOOST_COMP_COMO_DETECTION
+# endif
+# define BOOST_COMP_COMO_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_COMO_NAME "Comeau C++"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_COMO,BOOST_COMP_COMO_NAME)
+
+#ifdef BOOST_COMP_COMO_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_COMO_EMULATED,BOOST_COMP_COMO_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/compaq.h b/third_party/boost/boost/predef/compiler/compaq.h
new file mode 100644
index 0000000..96a79e6
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/compaq.h
@@ -0,0 +1,66 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_COMPAQ_H
+#define BOOST_PREDEF_COMPILER_COMPAQ_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_DEC`]
+
+[@http://www.openvms.compaq.com/openvms/brochures/deccplus/ Compaq C/C++] compiler.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__DECCXX`] [__predef_detection__]]
+ [[`__DECC`] [__predef_detection__]]
+
+ [[`__DECCXX_VER`] [V.R.P]]
+ [[`__DECC_VER`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_COMP_DEC BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__DECC) || defined(__DECCXX)
+# if !defined(BOOST_COMP_DEC_DETECTION) && defined(__DECCXX_VER)
+# define BOOST_COMP_DEC_DETECTION BOOST_PREDEF_MAKE_10_VVRR0PP00(__DECCXX_VER)
+# endif
+# if !defined(BOOST_COMP_DEC_DETECTION) && defined(__DECC_VER)
+# define BOOST_COMP_DEC_DETECTION BOOST_PREDEF_MAKE_10_VVRR0PP00(__DECC_VER)
+# endif
+# if !defined(BOOST_COMP_DEC_DETECTION)
+# define BOOST_COM_DEC_DETECTION BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#ifdef BOOST_COMP_DEC_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_DEC_EMULATED BOOST_COMP_DEC_DETECTION
+# else
+# undef BOOST_COMP_DEC
+# define BOOST_COMP_DEC BOOST_COMP_DEC_DETECTION
+# endif
+# define BOOST_COMP_DEC_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_DEC_NAME "Compaq C/C++"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_DEC,BOOST_COMP_DEC_NAME)
+
+#ifdef BOOST_COMP_DEC_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_DEC_EMULATED,BOOST_COMP_DEC_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/diab.h b/third_party/boost/boost/predef/compiler/diab.h
new file mode 100644
index 0000000..f5a37de
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/diab.h
@@ -0,0 +1,56 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_DIAB_H
+#define BOOST_PREDEF_COMPILER_DIAB_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_DIAB`]
+
+[@http://www.windriver.com/products/development_suite/wind_river_compiler/ Diab C/C++] compiler.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__DCC__`] [__predef_detection__]]
+
+ [[`__VERSION_NUMBER__`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_COMP_DIAB BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__DCC__)
+# define BOOST_COMP_DIAB_DETECTION BOOST_PREDEF_MAKE_10_VRPP(__VERSION_NUMBER__)
+#endif
+
+#ifdef BOOST_COMP_DIAB_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_DIAB_EMULATED BOOST_COMP_DIAB_DETECTION
+# else
+# undef BOOST_COMP_DIAB
+# define BOOST_COMP_DIAB BOOST_COMP_DIAB_DETECTION
+# endif
+# define BOOST_COMP_DIAB_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_DIAB_NAME "Diab C/C++"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_DIAB,BOOST_COMP_DIAB_NAME)
+
+#ifdef BOOST_COMP_DIAB_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_DIAB_EMULATED,BOOST_COMP_DIAB_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/digitalmars.h b/third_party/boost/boost/predef/compiler/digitalmars.h
new file mode 100644
index 0000000..9bd5850
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/digitalmars.h
@@ -0,0 +1,56 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_DIGITALMARS_H
+#define BOOST_PREDEF_COMPILER_DIGITALMARS_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_DMC`]
+
+[@http://en.wikipedia.org/wiki/Digital_Mars Digital Mars] compiler.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__DMC__`] [__predef_detection__]]
+
+ [[`__DMC__`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_COMP_DMC BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__DMC__)
+# define BOOST_COMP_DMC_DETECTION BOOST_PREDEF_MAKE_0X_VRP(__DMC__)
+#endif
+
+#ifdef BOOST_COMP_DMC_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_DMC_EMULATED BOOST_COMP_DMC_DETECTION
+# else
+# undef BOOST_COMP_DMC
+# define BOOST_COMP_DMC BOOST_COMP_DMC_DETECTION
+# endif
+# define BOOST_COMP_DMC_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_DMC_NAME "Digital Mars"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_DMC,BOOST_COMP_DMC_NAME)
+
+#ifdef BOOST_COMP_DMC_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_DMC_EMULATED,BOOST_COMP_DMC_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/dignus.h b/third_party/boost/boost/predef/compiler/dignus.h
new file mode 100644
index 0000000..c65d3dc
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/dignus.h
@@ -0,0 +1,56 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_DIGNUS_H
+#define BOOST_PREDEF_COMPILER_DIGNUS_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_SYSC`]
+
+[@http://www.dignus.com/dcxx/ Dignus Systems/C++] compiler.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__SYSC__`] [__predef_detection__]]
+
+ [[`__SYSC_VER__`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_COMP_SYSC BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__SYSC__)
+# define BOOST_COMP_SYSC_DETECTION BOOST_PREDEF_MAKE_10_VRRPP(__SYSC_VER__)
+#endif
+
+#ifdef BOOST_COMP_SYSC_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_SYSC_EMULATED BOOST_COMP_SYSC_DETECTION
+# else
+# undef BOOST_COMP_SYSC
+# define BOOST_COMP_SYSC BOOST_COMP_SYSC_DETECTION
+# endif
+# define BOOST_COMP_SYSC_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_SYSC_NAME "Dignus Systems/C++"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_SYSC,BOOST_COMP_SYSC_NAME)
+
+#ifdef BOOST_COMP_SYSC_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_SYSC_EMULATED,BOOST_COMP_SYSC_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/edg.h b/third_party/boost/boost/predef/compiler/edg.h
new file mode 100644
index 0000000..2ffb9b0
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/edg.h
@@ -0,0 +1,56 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_EDG_H
+#define BOOST_PREDEF_COMPILER_EDG_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_EDG`]
+
+[@http://en.wikipedia.org/wiki/Edison_Design_Group EDG C++ Frontend] compiler.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__EDG__`] [__predef_detection__]]
+
+ [[`__EDG_VERSION__`] [V.R.0]]
+ ]
+ */
+
+#define BOOST_COMP_EDG BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__EDG__)
+# define BOOST_COMP_EDG_DETECTION BOOST_PREDEF_MAKE_10_VRR(__EDG_VERSION__)
+#endif
+
+#ifdef BOOST_COMP_EDG_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_EDG_EMULATED BOOST_COMP_EDG_DETECTION
+# else
+# undef BOOST_COMP_EDG
+# define BOOST_COMP_EDG BOOST_COMP_EDG_DETECTION
+# endif
+# define BOOST_COMP_EDG_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_EDG_NAME "EDG C++ Frontend"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_EDG,BOOST_COMP_EDG_NAME)
+
+#ifdef BOOST_COMP_EDG_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_EDG_EMULATED,BOOST_COMP_EDG_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/ekopath.h b/third_party/boost/boost/predef/compiler/ekopath.h
new file mode 100644
index 0000000..e5cde36
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/ekopath.h
@@ -0,0 +1,57 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_EKOPATH_H
+#define BOOST_PREDEF_COMPILER_EKOPATH_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_PATH`]
+
+[@http://en.wikipedia.org/wiki/PathScale EKOpath] compiler.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__PATHCC__`] [__predef_detection__]]
+
+ [[`__PATHCC__`, `__PATHCC_MINOR__`, `__PATHCC_PATCHLEVEL__`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_COMP_PATH BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__PATHCC__)
+# define BOOST_COMP_PATH_DETECTION \
+ BOOST_VERSION_NUMBER(__PATHCC__,__PATHCC_MINOR__,__PATHCC_PATCHLEVEL__)
+#endif
+
+#ifdef BOOST_COMP_PATH_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_PATH_EMULATED BOOST_COMP_PATH_DETECTION
+# else
+# undef BOOST_COMP_PATH
+# define BOOST_COMP_PATH BOOST_COMP_PATH_DETECTION
+# endif
+# define BOOST_COMP_PATH_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_PATH_NAME "EKOpath"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_PATH,BOOST_COMP_PATH_NAME)
+
+#ifdef BOOST_COMP_PATH_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_PATH_EMULATED,BOOST_COMP_PATH_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/gcc.h b/third_party/boost/boost/predef/compiler/gcc.h
new file mode 100644
index 0000000..c2d7fff
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/gcc.h
@@ -0,0 +1,68 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_GCC_H
+#define BOOST_PREDEF_COMPILER_GCC_H
+
+/* Other compilers that emulate this one need to be detected first. */
+
+#include <boost/predef/compiler/clang.h>
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_GNUC`]
+
+[@http://en.wikipedia.org/wiki/GNU_Compiler_Collection Gnu GCC C/C++] compiler.
+Version number available as major, minor, and patch (if available).
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__GNUC__`] [__predef_detection__]]
+
+ [[`__GNUC__`, `__GNUC_MINOR__`, `__GNUC_PATCHLEVEL__`] [V.R.P]]
+ [[`__GNUC__`, `__GNUC_MINOR__`] [V.R.0]]
+ ]
+ */
+
+#define BOOST_COMP_GNUC BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__GNUC__)
+# if !defined(BOOST_COMP_GNUC_DETECTION) && defined(__GNUC_PATCHLEVEL__)
+# define BOOST_COMP_GNUC_DETECTION \
+ BOOST_VERSION_NUMBER(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__)
+# endif
+# if !defined(BOOST_COMP_GNUC_DETECTION)
+# define BOOST_COMP_GNUC_DETECTION \
+ BOOST_VERSION_NUMBER(__GNUC__,__GNUC_MINOR__,0)
+# endif
+#endif
+
+#ifdef BOOST_COMP_GNUC_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_GNUC_EMULATED BOOST_COMP_GNUC_DETECTION
+# else
+# undef BOOST_COMP_GNUC
+# define BOOST_COMP_GNUC BOOST_COMP_GNUC_DETECTION
+# endif
+# define BOOST_COMP_GNUC_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_GNUC_NAME "Gnu GCC C/C++"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_GNUC,BOOST_COMP_GNUC_NAME)
+
+#ifdef BOOST_COMP_GNUC_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_GNUC_EMULATED,BOOST_COMP_GNUC_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/gcc_xml.h b/third_party/boost/boost/predef/compiler/gcc_xml.h
new file mode 100644
index 0000000..acae600
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/gcc_xml.h
@@ -0,0 +1,53 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_GCC_XML_H
+#define BOOST_PREDEF_COMPILER_GCC_XML_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_GCCXML`]
+
+[@http://www.gccxml.org/ GCC XML] compiler.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__GCCXML__`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_COMP_GCCXML BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__GCCXML__)
+# define BOOST_COMP_GCCXML_DETECTION BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#ifdef BOOST_COMP_GCCXML_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_GCCXML_EMULATED BOOST_COMP_GCCXML_DETECTION
+# else
+# undef BOOST_COMP_GCCXML
+# define BOOST_COMP_GCCXML BOOST_COMP_GCCXML_DETECTION
+# endif
+# define BOOST_COMP_GCCXML_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_GCCXML_NAME "GCC XML"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_GCCXML,BOOST_COMP_GCCXML_NAME)
+
+#ifdef BOOST_COMP_GCCXML_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_GCCXML_EMULATED,BOOST_COMP_GCCXML_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/greenhills.h b/third_party/boost/boost/predef/compiler/greenhills.h
new file mode 100644
index 0000000..23b8f01
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/greenhills.h
@@ -0,0 +1,66 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_GREENHILLS_H
+#define BOOST_PREDEF_COMPILER_GREENHILLS_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_GHS`]
+
+[@http://en.wikipedia.org/wiki/Green_Hills_Software Green Hills C/C++] compiler.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__ghs`] [__predef_detection__]]
+ [[`__ghs__`] [__predef_detection__]]
+
+ [[`__GHS_VERSION_NUMBER__`] [V.R.P]]
+ [[`__ghs`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_COMP_GHS BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__ghs) || defined(__ghs__)
+# if !defined(BOOST_COMP_GHS_DETECTION) && defined(__GHS_VERSION_NUMBER__)
+# define BOOST_COMP_GHS_DETECTION BOOST_PREDEF_MAKE_10_VRP(__GHS_VERSION_NUMBER__)
+# endif
+# if !defined(BOOST_COMP_GHS_DETECTION) && defined(__ghs)
+# define BOOST_COMP_GHS_DETECTION BOOST_PREDEF_MAKE_10_VRP(__ghs)
+# endif
+# if !defined(BOOST_COMP_GHS_DETECTION)
+# define BOOST_COMP_GHS_DETECTION BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#ifdef BOOST_COMP_GHS_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_GHS_EMULATED BOOST_COMP_GHS_DETECTION
+# else
+# undef BOOST_COMP_GHS
+# define BOOST_COMP_GHS BOOST_COMP_GHS_DETECTION
+# endif
+# define BOOST_COMP_GHS_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_GHS_NAME "Green Hills C/C++"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_GHS,BOOST_COMP_GHS_NAME)
+
+#ifdef BOOST_COMP_GHS_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_GHS_EMULATED,BOOST_COMP_GHS_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/hp_acc.h b/third_party/boost/boost/predef/compiler/hp_acc.h
new file mode 100644
index 0000000..7b3ffe9
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/hp_acc.h
@@ -0,0 +1,61 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_HP_ACC_H
+#define BOOST_PREDEF_COMPILER_HP_ACC_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_HPACC`]
+
+HP aC++ compiler.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__HP_aCC`] [__predef_detection__]]
+
+ [[`__HP_aCC`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_COMP_HPACC BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__HP_aCC)
+# if !defined(BOOST_COMP_HPACC_DETECTION) && (__HP_aCC > 1)
+# define BOOST_COMP_HPACC_DETECTION BOOST_PREDEF_MAKE_10_VVRRPP(__HP_aCC)
+# endif
+# if !defined(BOOST_COMP_HPACC_DETECTION)
+# define BOOST_COMP_HPACC_DETECTION BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#ifdef BOOST_COMP_HPACC_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_HPACC_EMULATED BOOST_COMP_HPACC_DETECTION
+# else
+# undef BOOST_COMP_HPACC
+# define BOOST_COMP_HPACC BOOST_COMP_HPACC_DETECTION
+# endif
+# define BOOST_COMP_HPACC_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_HPACC_NAME "HP aC++"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_HPACC,BOOST_COMP_HPACC_NAME)
+
+#ifdef BOOST_COMP_HPACC_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_HPACC_EMULATED,BOOST_COMP_HPACC_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/iar.h b/third_party/boost/boost/predef/compiler/iar.h
new file mode 100644
index 0000000..237f492
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/iar.h
@@ -0,0 +1,56 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_IAR_H
+#define BOOST_PREDEF_COMPILER_IAR_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_IAR`]
+
+IAR C/C++ compiler.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__IAR_SYSTEMS_ICC__`] [__predef_detection__]]
+
+ [[`__VER__`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_COMP_IAR BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__IAR_SYSTEMS_ICC__)
+# define BOOST_COMP_IAR_DETECTION BOOST_PREDEF_MAKE_10_VVRR(__VER__)
+#endif
+
+#ifdef BOOST_COMP_IAR_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_IAR_EMULATED BOOST_COMP_IAR_DETECTION
+# else
+# undef BOOST_COMP_IAR
+# define BOOST_COMP_IAR BOOST_COMP_IAR_DETECTION
+# endif
+# define BOOST_COMP_IAR_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_IAR_NAME "IAR C/C++"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_IAR,BOOST_COMP_IAR_NAME)
+
+#ifdef BOOST_COMP_IAR_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_IAR_EMULATED,BOOST_COMP_IAR_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/ibm.h b/third_party/boost/boost/predef/compiler/ibm.h
new file mode 100644
index 0000000..6931ebd
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/ibm.h
@@ -0,0 +1,72 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_IBM_H
+#define BOOST_PREDEF_COMPILER_IBM_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_IBM`]
+
+[@http://en.wikipedia.org/wiki/VisualAge IBM XL C/C++] compiler.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__IBMCPP__`] [__predef_detection__]]
+ [[`__xlC__`] [__predef_detection__]]
+ [[`__xlc__`] [__predef_detection__]]
+
+ [[`__COMPILER_VER__`] [V.R.P]]
+ [[`__xlC__`] [V.R.P]]
+ [[`__xlc__`] [V.R.P]]
+ [[`__IBMCPP__`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_COMP_IBM BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__IBMCPP__) || defined(__xlC__) || defined(__xlc__)
+# if !defined(BOOST_COMP_IBM_DETECTION) && defined(__COMPILER_VER__)
+# define BOOST_COMP_IBM_DETECTION BOOST_PREDEF_MAKE_0X_VRRPPPP(__COMPILER_VER__)
+# endif
+# if !defined(BOOST_COMP_IBM_DETECTION) && defined(__xlC__)
+# define BOOST_COMP_IBM_DETECTION BOOST_PREDEF_MAKE_0X_VVRR(__xlC__)
+# endif
+# if !defined(BOOST_COMP_IBM_DETECTION) && defined(__xlc__)
+# define BOOST_COMP_IBM_DETECTION BOOST_PREDEF_MAKE_0X_VVRR(__xlc__)
+# endif
+# if !defined(BOOST_COMP_IBM_DETECTION)
+# define BOOST_COMP_IBM_DETECTION BOOST_PREDEF_MAKE_10_VRP(__IBMCPP__)
+# endif
+#endif
+
+#ifdef BOOST_COMP_IBM_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_IBM_EMULATED BOOST_COMP_IBM_DETECTION
+# else
+# undef BOOST_COMP_IBM
+# define BOOST_COMP_IBM BOOST_COMP_IBM_DETECTION
+# endif
+# define BOOST_COMP_IBM_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_IBM_NAME "IBM XL C/C++"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_IBM,BOOST_COMP_IBM_NAME)
+
+#ifdef BOOST_COMP_IBM_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_IBM_EMULATED,BOOST_COMP_IBM_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/intel.h b/third_party/boost/boost/predef/compiler/intel.h
new file mode 100644
index 0000000..65bde67
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/intel.h
@@ -0,0 +1,65 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_INTEL_H
+#define BOOST_PREDEF_COMPILER_INTEL_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_INTEL`]
+
+[@http://en.wikipedia.org/wiki/Intel_C%2B%2B Intel C/C++] compiler.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__INTEL_COMPILER`] [__predef_detection__]]
+ [[`__ICL`] [__predef_detection__]]
+ [[`__ICC`] [__predef_detection__]]
+ [[`__ECC`] [__predef_detection__]]
+
+ [[`__INTEL_COMPILER`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_COMP_INTEL BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || \
+ defined(__ECC)
+# if !defined(BOOST_COMP_INTEL_DETECTION) && defined(__INTEL_COMPILER)
+# define BOOST_COMP_INTEL_DETECTION BOOST_PREDEF_MAKE_10_VRP(__INTEL_COMPILER)
+# endif
+# if !defined(BOOST_COMP_INTEL_DETECTION)
+# define BOOST_COMP_INTEL_DETECTION BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#ifdef BOOST_COMP_INTEL_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_INTEL_EMULATED BOOST_COMP_INTEL_DETECTION
+# else
+# undef BOOST_COMP_INTEL
+# define BOOST_COMP_INTEL BOOST_COMP_INTEL_DETECTION
+# endif
+# define BOOST_COMP_INTEL_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_INTEL_NAME "Intel C/C++"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_INTEL,BOOST_COMP_INTEL_NAME)
+
+#ifdef BOOST_COMP_INTEL_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_INTEL_EMULATED,BOOST_COMP_INTEL_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/kai.h b/third_party/boost/boost/predef/compiler/kai.h
new file mode 100644
index 0000000..68ce84e
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/kai.h
@@ -0,0 +1,56 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_KAI_H
+#define BOOST_PREDEF_COMPILER_KAI_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_KCC`]
+
+Kai C++ compiler.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__KCC`] [__predef_detection__]]
+
+ [[`__KCC_VERSION`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_COMP_KCC BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__KCC)
+# define BOOST_COMP_KCC_DETECTION BOOST_PREDEF_MAKE_0X_VRPP(__KCC_VERSION)
+#endif
+
+#ifdef BOOST_COMP_KCC_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_KCC_EMULATED BOOST_COMP_KCC_DETECTION
+# else
+# undef BOOST_COMP_KCC
+# define BOOST_COMP_KCC BOOST_COMP_KCC_DETECTION
+# endif
+# define BOOST_COMP_KCC_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_KCC_NAME "Kai C++"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_KCC,BOOST_COMP_KCC_NAME)
+
+#ifdef BOOST_COMP_KCC_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_KCC_EMULATED,BOOST_COMP_KCC_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/llvm.h b/third_party/boost/boost/predef/compiler/llvm.h
new file mode 100644
index 0000000..de654eb
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/llvm.h
@@ -0,0 +1,57 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_LLVM_H
+#define BOOST_PREDEF_COMPILER_LLVM_H
+
+/* Other compilers that emulate this one need to be detected first. */
+
+#include <boost/predef/compiler/clang.h>
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_LLVM`]
+
+[@http://en.wikipedia.org/wiki/LLVM LLVM] compiler.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__llvm__`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_COMP_LLVM BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__llvm__)
+# define BOOST_COMP_LLVM_DETECTION BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#ifdef BOOST_COMP_LLVM_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_LLVM_EMULATED BOOST_COMP_LLVM_DETECTION
+# else
+# undef BOOST_COMP_LLVM
+# define BOOST_COMP_LLVM BOOST_COMP_LLVM_DETECTION
+# endif
+# define BOOST_COMP_LLVM_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_LLVM_NAME "LLVM"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_LLVM,BOOST_COMP_LLVM_NAME)
+
+#ifdef BOOST_COMP_LLVM_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_LLVM_EMULATED,BOOST_COMP_LLVM_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/metaware.h b/third_party/boost/boost/predef/compiler/metaware.h
new file mode 100644
index 0000000..1a32039
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/metaware.h
@@ -0,0 +1,53 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_METAWARE_H
+#define BOOST_PREDEF_COMPILER_METAWARE_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_HIGHC`]
+
+MetaWare High C/C++ compiler.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__HIGHC__`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_COMP_HIGHC BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__HIGHC__)
+# define BOOST_COMP_HIGHC_DETECTION BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#ifdef BOOST_COMP_HIGHC_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_HIGHC_EMULATED BOOST_COMP_HIGHC_DETECTION
+# else
+# undef BOOST_COMP_HIGHC
+# define BOOST_COMP_HIGHC BOOST_COMP_HIGHC_DETECTION
+# endif
+# define BOOST_COMP_HIGHC_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_HIGHC_NAME "MetaWare High C/C++"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_HIGHC,BOOST_COMP_HIGHC_NAME)
+
+#ifdef BOOST_COMP_HIGHC_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_HIGHC_EMULATED,BOOST_COMP_HIGHC_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/metrowerks.h b/third_party/boost/boost/predef/compiler/metrowerks.h
new file mode 100644
index 0000000..f2d739b
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/metrowerks.h
@@ -0,0 +1,77 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_METROWERKS_H
+#define BOOST_PREDEF_COMPILER_METROWERKS_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_MWERKS`]
+
+[@http://en.wikipedia.org/wiki/CodeWarrior Metrowerks CodeWarrior] compiler.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__MWERKS__`] [__predef_detection__]]
+ [[`__CWCC__`] [__predef_detection__]]
+
+ [[`__CWCC__`] [V.R.P]]
+ [[`__MWERKS__`] [V.R.P >= 4.2.0]]
+ [[`__MWERKS__`] [9.R.0]]
+ [[`__MWERKS__`] [8.R.0]]
+ ]
+ */
+
+#define BOOST_COMP_MWERKS BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__MWERKS__) || defined(__CWCC__)
+# if !defined(BOOST_COMP_MWERKS_DETECTION) && defined(__CWCC__)
+# define BOOST_COMP_MWERKS_DETECTION BOOST_PREDEF_MAKE_0X_VRPP(__CWCC__)
+# endif
+# if !defined(BOOST_COMP_MWERKS_DETECTION) && (__MWERKS__ >= 0x4200)
+# define BOOST_COMP_MWERKS_DETECTION BOOST_PREDEF_MAKE_0X_VRPP(__MWERKS__)
+# endif
+# if !defined(BOOST_COMP_MWERKS_DETECTION) && (__MWERKS__ >= 0x3204) // note the "skip": 04->9.3
+# define BOOST_COMP_MWERKS_DETECTION BOOST_VERSION_NUMBER(9,(__MWERKS__)%100-1,0)
+# endif
+# if !defined(BOOST_COMP_MWERKS_DETECTION) && (__MWERKS__ >= 0x3200)
+# define BOOST_COMP_MWERKS_DETECTION BOOST_VERSION_NUMBER(9,(__MWERKS__)%100,0)
+# endif
+# if !defined(BOOST_COMP_MWERKS_DETECTION) && (__MWERKS__ >= 0x3000)
+# define BOOST_COMP_MWERKS_DETECTION BOOST_VERSION_NUMBER(8,(__MWERKS__)%100,0)
+# endif
+# if !defined(BOOST_COMP_MWERKS_DETECTION)
+# define BOOST_COMP_MWERKS_DETECTION BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#ifdef BOOST_COMP_MWERKS_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_MWERKS_EMULATED BOOST_COMP_MWERKS_DETECTION
+# else
+# undef BOOST_COMP_MWERKS
+# define BOOST_COMP_MWERKS BOOST_COMP_MWERKS_DETECTION
+# endif
+# define BOOST_COMP_MWERKS_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_MWERKS_NAME "Metrowerks CodeWarrior"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_MWERKS,BOOST_COMP_MWERKS_NAME)
+
+#ifdef BOOST_COMP_MWERKS_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_MWERKS_EMULATED,BOOST_COMP_MWERKS_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/microtec.h b/third_party/boost/boost/predef/compiler/microtec.h
new file mode 100644
index 0000000..066a6d2
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/microtec.h
@@ -0,0 +1,53 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_MICROTEC_H
+#define BOOST_PREDEF_COMPILER_MICROTEC_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_MRI`]
+
+[@http://www.mentor.com/microtec/ Microtec C/C++] compiler.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`_MRI`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_COMP_MRI BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(_MRI)
+# define BOOST_COMP_MRI_DETECTION BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#ifdef BOOST_COMP_MRI_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_MRI_EMULATED BOOST_COMP_MRI_DETECTION
+# else
+# undef BOOST_COMP_MRI
+# define BOOST_COMP_MRI BOOST_COMP_MRI_DETECTION
+# endif
+# define BOOST_COMP_MRI_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_MRI_NAME "Microtec C/C++"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_MRI,BOOST_COMP_MRI_NAME)
+
+#ifdef BOOST_COMP_MRI_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_MRI_EMULATED,BOOST_COMP_MRI_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/mpw.h b/third_party/boost/boost/predef/compiler/mpw.h
new file mode 100644
index 0000000..1183306
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/mpw.h
@@ -0,0 +1,63 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_MPW_H
+#define BOOST_PREDEF_COMPILER_MPW_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_MPW`]
+
+[@http://en.wikipedia.org/wiki/Macintosh_Programmer%27s_Workshop MPW C++] compiler.
+Version number available as major, and minor.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__MRC__`] [__predef_detection__]]
+ [[`MPW_C`] [__predef_detection__]]
+ [[`MPW_CPLUS`] [__predef_detection__]]
+
+ [[`__MRC__`] [V.R.0]]
+ ]
+ */
+
+#define BOOST_COMP_MPW BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__MRC__) || defined(MPW_C) || defined(MPW_CPLUS)
+# if !defined(BOOST_COMP_MPW_DETECTION) && defined(__MRC__)
+# define BOOST_COMP_MPW_DETECTION BOOST_PREDEF_MAKE_0X_VVRR(__MRC__)
+# endif
+# if !defined(BOOST_COMP_MPW_DETECTION)
+# define BOOST_COMP_MPW_DETECTION BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#ifdef BOOST_COMP_MPW_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_MPW_EMULATED BOOST_COMP_MPW_DETECTION
+# else
+# undef BOOST_COMP_MPW
+# define BOOST_COMP_MPW BOOST_COMP_MPW_DETECTION
+# endif
+# define BOOST_COMP_MPW_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_MPW_NAME "MPW C++"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_MPW,BOOST_COMP_MPW_NAME)
+
+#ifdef BOOST_COMP_MPW_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_MPW_EMULATED,BOOST_COMP_MPW_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/palm.h b/third_party/boost/boost/predef/compiler/palm.h
new file mode 100644
index 0000000..707925a
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/palm.h
@@ -0,0 +1,56 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_PALM_H
+#define BOOST_PREDEF_COMPILER_PALM_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_PALM`]
+
+Palm C/C++ compiler.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`_PACC_VER`] [__predef_detection__]]
+
+ [[`_PACC_VER`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_COMP_PALM BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(_PACC_VER)
+# define BOOST_COMP_PALM_DETECTION BOOST_PREDEF_MAKE_0X_VRRPP000(_PACC_VER)
+#endif
+
+#ifdef BOOST_COMP_PALM_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_PALM_EMULATED BOOST_COMP_PALM_DETECTION
+# else
+# undef BOOST_COMP_PALM
+# define BOOST_COMP_PALM BOOST_COMP_PALM_DETECTION
+# endif
+# define BOOST_COMP_PALM_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_PALM_NAME "Palm C/C++"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_PALM,BOOST_COMP_PALM_NAME)
+
+#ifdef BOOST_COMP_PALM_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_PALM_EMULATED,BOOST_COMP_PALM_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/pgi.h b/third_party/boost/boost/predef/compiler/pgi.h
new file mode 100644
index 0000000..e016aeb
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/pgi.h
@@ -0,0 +1,60 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_PGI_H
+#define BOOST_PREDEF_COMPILER_PGI_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_PGI`]
+
+[@http://en.wikipedia.org/wiki/The_Portland_Group Portland Group C/C++] compiler.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__PGI`] [__predef_detection__]]
+
+ [[`__PGIC__`, `__PGIC_MINOR__`, `__PGIC_PATCHLEVEL__`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_COMP_PGI BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__PGI)
+# if !defined(BOOST_COMP_PGI_DETECTION) && (defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__))
+# define BOOST_COMP_PGI_DETECTION BOOST_VERSION_NUMBER(__PGIC__,__PGIC_MINOR__,__PGIC_PATCHLEVEL__)
+# endif
+# if !defined(BOOST_COMP_PGI_DETECTION)
+# define BOOST_COMP_PGI_DETECTION BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#ifdef BOOST_COMP_PGI_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_PGI_EMULATED BOOST_COMP_PGI_DETECTION
+# else
+# undef BOOST_COMP_PGI
+# define BOOST_COMP_PGI BOOST_COMP_PGI_DETECTION
+# endif
+# define BOOST_COMP_PGI_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_PGI_NAME "Portland Group C/C++"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_PGI,BOOST_COMP_PGI_NAME)
+
+#ifdef BOOST_COMP_PGI_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_PGI_EMULATED,BOOST_COMP_PGI_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/sgi_mipspro.h b/third_party/boost/boost/predef/compiler/sgi_mipspro.h
new file mode 100644
index 0000000..00739f0
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/sgi_mipspro.h
@@ -0,0 +1,66 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_SGI_MIPSPRO_H
+#define BOOST_PREDEF_COMPILER_SGI_MIPSPRO_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_SGI`]
+
+[@http://en.wikipedia.org/wiki/MIPSpro SGI MIPSpro] compiler.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__sgi`] [__predef_detection__]]
+ [[`sgi`] [__predef_detection__]]
+
+ [[`_SGI_COMPILER_VERSION`] [V.R.P]]
+ [[`_COMPILER_VERSION`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_COMP_SGI BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__sgi) || defined(sgi)
+# if !defined(BOOST_COMP_SGI_DETECTION) && defined(_SGI_COMPILER_VERSION)
+# define BOOST_COMP_SGI_DETECTION BOOST_PREDEF_MAKE_10_VRP(_SGI_COMPILER_VERSION)
+# endif
+# if !defined(BOOST_COMP_SGI_DETECTION) && defined(_COMPILER_VERSION)
+# define BOOST_COMP_SGI_DETECTION BOOST_PREDEF_MAKE_10_VRP(_COMPILER_VERSION)
+# endif
+# if !defined(BOOST_COMP_SGI_DETECTION)
+# define BOOST_COMP_SGI_DETECTION BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#ifdef BOOST_COMP_SGI_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_SGI_EMULATED BOOST_COMP_SGI_DETECTION
+# else
+# undef BOOST_COMP_SGI
+# define BOOST_COMP_SGI BOOST_COMP_SGI_DETECTION
+# endif
+# define BOOST_COMP_SGI_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_SGI_NAME "SGI MIPSpro"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_SGI,BOOST_COMP_SGI_NAME)
+
+#ifdef BOOST_COMP_SGI_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_SGI_EMULATED,BOOST_COMP_SGI_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/sunpro.h b/third_party/boost/boost/predef/compiler/sunpro.h
new file mode 100644
index 0000000..92c3926
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/sunpro.h
@@ -0,0 +1,76 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_SUNPRO_H
+#define BOOST_PREDEF_COMPILER_SUNPRO_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_SUNPRO`]
+
+[@http://en.wikipedia.org/wiki/Oracle_Solaris_Studio Oracle Solaris Studio] compiler.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__SUNPRO_CC`] [__predef_detection__]]
+ [[`__SUNPRO_C`] [__predef_detection__]]
+
+ [[`__SUNPRO_CC`] [V.R.P]]
+ [[`__SUNPRO_C`] [V.R.P]]
+ [[`__SUNPRO_CC`] [VV.RR.P]]
+ [[`__SUNPRO_C`] [VV.RR.P]]
+ ]
+ */
+
+#define BOOST_COMP_SUNPRO BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__SUNPRO_CC) || defined(__SUNPRO_C)
+# if !defined(BOOST_COMP_SUNPRO_DETECTION) && defined(__SUNPRO_CC)
+# if (__SUNPRO_CC < 0x5100)
+# define BOOST_COMP_SUNPRO_DETECTION BOOST_PREDEF_MAKE_0X_VRP(__SUNPRO_CC)
+# else
+# define BOOST_COMP_SUNPRO_DETECTION BOOST_PREDEF_MAKE_0X_VVRRP(__SUNPRO_CC)
+# endif
+# endif
+# if !defined(BOOST_COMP_SUNPRO_DETECTION) && defined(__SUNPRO_C)
+# if (__SUNPRO_C < 0x5100)
+# define BOOST_COMP_SUNPRO_DETECTION BOOST_PREDEF_MAKE_0X_VRP(__SUNPRO_C)
+# else
+# define BOOST_COMP_SUNPRO_DETECTION BOOST_PREDEF_MAKE_0X_VVRRP(__SUNPRO_C)
+# endif
+# endif
+# if !defined(BOOST_COMP_SUNPRO_DETECTION)
+# define BOOST_COMP_SUNPRO_DETECTION BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#ifdef BOOST_COMP_SUNPRO_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_SUNPRO_EMULATED BOOST_COMP_SUNPRO_DETECTION
+# else
+# undef BOOST_COMP_SUNPRO
+# define BOOST_COMP_SUNPRO BOOST_COMP_SUNPRO_DETECTION
+# endif
+# define BOOST_COMP_SUNPRO_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_SUNPRO_NAME "Oracle Solaris Studio"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_SUNPRO,BOOST_COMP_SUNPRO_NAME)
+
+#ifdef BOOST_COMP_SUNPRO_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_SUNPRO_EMULATED,BOOST_COMP_SUNPRO_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/tendra.h b/third_party/boost/boost/predef/compiler/tendra.h
new file mode 100644
index 0000000..c2bc5e4
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/tendra.h
@@ -0,0 +1,53 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_TENDRA_H
+#define BOOST_PREDEF_COMPILER_TENDRA_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_TENDRA`]
+
+[@http://en.wikipedia.org/wiki/TenDRA_Compiler TenDRA C/C++] compiler.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__TenDRA__`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_COMP_TENDRA BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__TenDRA__)
+# define BOOST_COMP_TENDRA_DETECTION BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#ifdef BOOST_COMP_TENDRA_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_TENDRA_EMULATED BOOST_COMP_TENDRA_DETECTION
+# else
+# undef BOOST_COMP_TENDRA
+# define BOOST_COMP_TENDRA BOOST_COMP_TENDRA_DETECTION
+# endif
+# define BOOST_COMP_TENDRA_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_TENDRA_NAME "TenDRA C/C++"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_TENDRA,BOOST_COMP_TENDRA_NAME)
+
+#ifdef BOOST_COMP_TENDRA_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_TENDRA_EMULATED,BOOST_COMP_TENDRA_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/visualc.h b/third_party/boost/boost/predef/compiler/visualc.h
new file mode 100644
index 0000000..9481d9d
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/visualc.h
@@ -0,0 +1,91 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_VISUALC_H
+#define BOOST_PREDEF_COMPILER_VISUALC_H
+
+/* Other compilers that emulate this one need to be detected first. */
+
+#include <boost/predef/compiler/clang.h>
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_MSVC`]
+
+[@http://en.wikipedia.org/wiki/Visual_studio Microsoft Visual C/C++] compiler.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`_MSC_VER`] [__predef_detection__]]
+
+ [[`_MSC_FULL_VER`] [V.R.P]]
+ [[`_MSC_VER`] [V.R.0]]
+ ]
+ */
+
+#define BOOST_COMP_MSVC BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(_MSC_VER)
+# if !defined (_MSC_FULL_VER)
+# define BOOST_COMP_MSVC_BUILD 0
+# else
+ /* how many digits does the build number have? */
+# if _MSC_FULL_VER / 10000 == _MSC_VER
+ /* four digits */
+# define BOOST_COMP_MSVC_BUILD (_MSC_FULL_VER % 10000)
+# elif _MSC_FULL_VER / 100000 == _MSC_VER
+ /* five digits */
+# define BOOST_COMP_MSVC_BUILD (_MSC_FULL_VER % 100000)
+# else
+# error "Cannot determine build number from _MSC_FULL_VER"
+# endif
+# endif
+ /*
+ VS2014 was skipped in the release sequence for MS. Which
+ means that the compiler and VS product versions are no longer
+ in sync. Hence we need to use different formulas for
+ mapping from MSC version to VS product version.
+ */
+# if (_MSC_VER >= 1900)
+# define BOOST_COMP_MSVC_DETECTION BOOST_VERSION_NUMBER(\
+ _MSC_VER/100-5,\
+ _MSC_VER%100,\
+ BOOST_COMP_MSVC_BUILD)
+# else
+# define BOOST_COMP_MSVC_DETECTION BOOST_VERSION_NUMBER(\
+ _MSC_VER/100-6,\
+ _MSC_VER%100,\
+ BOOST_COMP_MSVC_BUILD)
+# endif
+#endif
+
+#ifdef BOOST_COMP_MSVC_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_MSVC_EMULATED BOOST_COMP_MSVC_DETECTION
+# else
+# undef BOOST_COMP_MSVC
+# define BOOST_COMP_MSVC BOOST_COMP_MSVC_DETECTION
+# endif
+# define BOOST_COMP_MSVC_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_MSVC_NAME "Microsoft Visual C/C++"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_MSVC,BOOST_COMP_MSVC_NAME)
+
+#ifdef BOOST_COMP_MSVC_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_MSVC_EMULATED,BOOST_COMP_MSVC_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/compiler/watcom.h b/third_party/boost/boost/predef/compiler/watcom.h
new file mode 100644
index 0000000..b0e7776
--- /dev/null
+++ b/third_party/boost/boost/predef/compiler/watcom.h
@@ -0,0 +1,56 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_WATCOM_H
+#define BOOST_PREDEF_COMPILER_WATCOM_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_COMP_WATCOM`]
+
+[@http://en.wikipedia.org/wiki/Watcom Watcom C++] compiler.
+Version number available as major, and minor.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__WATCOMC__`] [__predef_detection__]]
+
+ [[`__WATCOMC__`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_COMP_WATCOM BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__WATCOMC__)
+# define BOOST_COMP_WATCOM_DETECTION BOOST_PREDEF_MAKE_10_VVRR(__WATCOMC__)
+#endif
+
+#ifdef BOOST_COMP_WATCOM_DETECTION
+# if defined(BOOST_PREDEF_DETAIL_COMP_DETECTED)
+# define BOOST_COMP_WATCOM_EMULATED BOOST_COMP_WATCOM_DETECTION
+# else
+# undef BOOST_COMP_WATCOM
+# define BOOST_COMP_WATCOM BOOST_COMP_WATCOM_DETECTION
+# endif
+# define BOOST_COMP_WATCOM_AVAILABLE
+# include <boost/predef/detail/comp_detected.h>
+#endif
+
+#define BOOST_COMP_WATCOM_NAME "Watcom C++"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_WATCOM,BOOST_COMP_WATCOM_NAME)
+
+#ifdef BOOST_COMP_WATCOM_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_COMP_WATCOM_EMULATED,BOOST_COMP_WATCOM_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/detail/_cassert.h b/third_party/boost/boost/predef/detail/_cassert.h
new file mode 100644
index 0000000..940e944
--- /dev/null
+++ b/third_party/boost/boost/predef/detail/_cassert.h
@@ -0,0 +1,17 @@
+/*
+Copyright Rene Rivera 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)
+*/
+
+#ifndef BOOST_PREDEF_DETAIL__CASSERT_H
+#define BOOST_PREDEF_DETAIL__CASSERT_H
+
+#if defined(__cplusplus)
+#include <cassert>
+#else
+#include <assert.h>
+#endif
+
+#endif
diff --git a/third_party/boost/boost/predef/detail/_exception.h b/third_party/boost/boost/predef/detail/_exception.h
new file mode 100644
index 0000000..f5a6687
--- /dev/null
+++ b/third_party/boost/boost/predef/detail/_exception.h
@@ -0,0 +1,15 @@
+/*
+Copyright Rene Rivera 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)
+*/
+
+#ifndef BOOST_PREDEF_DETAIL__EXCEPTION_H
+#define BOOST_PREDEF_DETAIL__EXCEPTION_H
+
+#if defined(__cplusplus)
+#include <exception>
+#endif
+
+#endif
diff --git a/third_party/boost/boost/predef/detail/comp_detected.h b/third_party/boost/boost/predef/detail/comp_detected.h
new file mode 100644
index 0000000..fda1801
--- /dev/null
+++ b/third_party/boost/boost/predef/detail/comp_detected.h
@@ -0,0 +1,10 @@
+/*
+Copyright Rene Rivera 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)
+*/
+
+#ifndef BOOST_PREDEF_DETAIL_COMP_DETECTED
+#define BOOST_PREDEF_DETAIL_COMP_DETECTED 1
+#endif
diff --git a/third_party/boost/boost/predef/detail/os_detected.h b/third_party/boost/boost/predef/detail/os_detected.h
new file mode 100644
index 0000000..08e10f9
--- /dev/null
+++ b/third_party/boost/boost/predef/detail/os_detected.h
@@ -0,0 +1,10 @@
+/*
+Copyright Rene Rivera 2013
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_DETAIL_OS_DETECTED
+#define BOOST_PREDEF_DETAIL_OS_DETECTED 1
+#endif
diff --git a/third_party/boost/boost/predef/detail/test.h b/third_party/boost/boost/predef/detail/test.h
new file mode 100644
index 0000000..546a9e4
--- /dev/null
+++ b/third_party/boost/boost/predef/detail/test.h
@@ -0,0 +1,17 @@
+/*
+Copyright Rene Rivera 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)
+*/
+
+#ifndef BOOST_PREDEF_DETAIL_TEST_H
+#define BOOST_PREDEF_DETAIL_TEST_H
+
+#if !defined(BOOST_PREDEF_INTERNAL_GENERATE_TESTS)
+
+#define BOOST_PREDEF_DECLARE_TEST(x,s)
+
+#endif
+
+#endif
diff --git a/third_party/boost/boost/predef/hardware.h b/third_party/boost/boost/predef/hardware.h
new file mode 100644
index 0000000..972b73a
--- /dev/null
+++ b/third_party/boost/boost/predef/hardware.h
@@ -0,0 +1,16 @@
+/*
+Copyright Charly Chevalier 2015
+Copyright Joel Falcou 2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#if !defined(BOOST_PREDEF_HARDWARE_H) || defined(BOOST_PREDEF_INTERNAL_GENERATE_TESTS)
+#ifndef BOOST_PREDEF_HARDWARE_H
+#define BOOST_PREDEF_HARDWARE_H
+#endif
+
+#include <boost/predef/hardware/simd.h>
+
+#endif
diff --git a/third_party/boost/boost/predef/hardware/simd.h b/third_party/boost/boost/predef/hardware/simd.h
new file mode 100644
index 0000000..4de1e70
--- /dev/null
+++ b/third_party/boost/boost/predef/hardware/simd.h
@@ -0,0 +1,107 @@
+/*
+Copyright Charly Chevalier 2015
+Copyright Joel Falcou 2015
+Distributed under the 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/predef/hardware/simd/x86.h>
+#include <boost/predef/hardware/simd/x86_amd.h>
+#include <boost/predef/hardware/simd/arm.h>
+#include <boost/predef/hardware/simd/ppc.h>
+
+#ifndef BOOST_PREDEF_HARDWARE_SIMD_H
+#define BOOST_PREDEF_HARDWARE_SIMD_H
+
+#include <boost/predef/version_number.h>
+
+/*`
+ [section Using the `BOOST_HW_SIMD_*` predefs]
+ [include ../doc/hardware_simd.qbk]
+ [endsect]
+
+ [/ --------------------------- ]
+
+ [section `BOOST_HW_SIMD_*`]
+
+ [heading `BOOST_HW_SIMD`]
+
+ The SIMD extension detected for a specific architectures.
+ Version number depends on the detected extension.
+
+ [table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`BOOST_HW_SIMD_X86_AVAILABLE`] [__predef_detection__]]
+ [[`BOOST_HW_SIMD_X86_AMD_AVAILABLE`] [__predef_detection__]]
+ [[`BOOST_HW_SIMD_ARM_AVAILABLE`] [__predef_detection__]]
+ [[`BOOST_HW_SIMD_PPC_AVAILABLE`] [__predef_detection__]]
+ ]
+
+ [include ../include/boost/predef/hardware/simd/x86.h]
+ [include ../include/boost/predef/hardware/simd/x86_amd.h]
+ [include ../include/boost/predef/hardware/simd/arm.h]
+ [include ../include/boost/predef/hardware/simd/ppc.h]
+
+ [endsect]
+
+ [/ --------------------------- ]
+
+ [section `BOOST_HW_SIMD_X86_*_VERSION`]
+ [include ../include/boost/predef/hardware/simd/x86/versions.h]
+ [endsect]
+
+ [section `BOOST_HW_SIMD_X86_AMD_*_VERSION`]
+ [include ../include/boost/predef/hardware/simd/x86_amd/versions.h]
+ [endsect]
+
+ [section `BOOST_HW_SIMD_ARM_*_VERSION`]
+ [include ../include/boost/predef/hardware/simd/arm/versions.h]
+ [endsect]
+
+ [section `BOOST_HW_SIMD_PPC_*_VERSION`]
+ [include ../include/boost/predef/hardware/simd/ppc/versions.h]
+ [endsect]
+
+ */
+
+// We check if SIMD extension of multiples architectures have been detected,
+// if yes, then this is an error!
+//
+// NOTE: _X86_AMD implies _X86, so there is no need to check for it here!
+//
+#if defined(BOOST_HW_SIMD_ARM_AVAILABLE) && defined(BOOST_HW_SIMD_PPC_AVAILABLE) ||\
+ defined(BOOST_HW_SIMD_ARM_AVAILABLE) && defined(BOOST_HW_SIMD_X86_AVAILABLE) ||\
+ defined(BOOST_HW_SIMD_PPC_AVAILABLE) && defined(BOOST_HW_SIMD_X86_AVAILABLE)
+# error "Multiple SIMD architectures detected, this cannot happen!"
+#endif
+
+#if defined(BOOST_HW_SIMD_X86_AVAILABLE)
+# define BOOST_HW_SIMD BOOST_HW_SIMD_X86
+#endif
+
+#if defined(BOOST_HW_SIMD_X86_AMD_AVAILABLE)
+# define BOOST_HW_SIMD BOOST_HW_SIMD_X86_AMD
+#endif
+
+#if defined(BOOST_HW_SIMD_ARM_AVAILABLE)
+# define BOOST_HW_SIMD BOOST_HW_SIMD_ARM
+#endif
+
+#if defined(BOOST_HW_SIMD_PPC_AVAILABLE)
+# define BOOST_HW_SIMD BOOST_HW_SIMD_PPC
+#endif
+
+#if defined(BOOST_HW_SIMD)
+# define BOOST_HW_SIMD_AVAILABLE
+#else
+# define BOOST_HW_SIMD BOOST_VERSION_NUMBER_NOT_AVAILABLE
+#endif
+
+#define BOOST_HW_SIMD_NAME "Hardware SIMD"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_HW_SIMD, BOOST_HW_SIMD_NAME)
diff --git a/third_party/boost/boost/predef/hardware/simd/arm.h b/third_party/boost/boost/predef/hardware/simd/arm.h
new file mode 100644
index 0000000..d067c93
--- /dev/null
+++ b/third_party/boost/boost/predef/hardware/simd/arm.h
@@ -0,0 +1,57 @@
+/*
+Copyright Charly Chevalier 2015
+Copyright Joel Falcou 2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_HARDWARE_SIMD_ARM_H
+#define BOOST_PREDEF_HARDWARE_SIMD_ARM_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/hardware/simd/arm/versions.h>
+
+/*`
+ [heading `BOOST_HW_SIMD_ARM`]
+
+ The SIMD extension for ARM (*if detected*).
+ Version number depends on the most recent detected extension.
+
+ [table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__ARM_NEON__`] [__predef_detection__]]
+ [[`__aarch64__`] [__predef_detection__]]
+ [[`_M_ARM`] [__predef_detection__]]
+ ]
+
+ [table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__ARM_NEON__`] [BOOST_HW_SIMD_ARM_NEON_VERSION]]
+ [[`__aarch64__`] [BOOST_HW_SIMD_ARM_NEON_VERSION]]
+ [[`_M_ARM`] [BOOST_HW_SIMD_ARM_NEON_VERSION]]
+ ]
+
+ */
+
+#define BOOST_HW_SIMD_ARM BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#undef BOOST_HW_SIMD_ARM
+#if !defined(BOOST_HW_SIMD_ARM) && (defined(__ARM_NEON__) || defined(__aarch64__) || defined (_M_ARM))
+# define BOOST_HW_SIMD_ARM BOOST_HW_SIMD_ARM_NEON_VERSION
+#endif
+
+#if !defined(BOOST_HW_SIMD_ARM)
+# define BOOST_HW_SIMD_ARM BOOST_VERSION_NUMBER_NOT_AVAILABLE
+#else
+# define BOOST_HW_SIMD_ARM_AVAILABLE
+#endif
+
+#define BOOST_HW_SIMD_ARM_NAME "ARM SIMD"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_HW_SIMD_ARM, BOOST_HW_SIMD_ARM_NAME)
diff --git a/third_party/boost/boost/predef/hardware/simd/arm/versions.h b/third_party/boost/boost/predef/hardware/simd/arm/versions.h
new file mode 100644
index 0000000..8425b31
--- /dev/null
+++ b/third_party/boost/boost/predef/hardware/simd/arm/versions.h
@@ -0,0 +1,32 @@
+/*
+Copyright Charly Chevalier 2015
+Copyright Joel Falcou 2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_HARDWARE_SIMD_ARM_VERSIONS_H
+#define BOOST_PREDEF_HARDWARE_SIMD_ARM_VERSIONS_H
+
+#include <boost/predef/version_number.h>
+
+/*`
+ Those defines represent ARM SIMD extensions versions.
+
+ [note You *MUST* compare them with the predef `BOOST_HW_SIMD_ARM`.]
+ */
+
+// ---------------------------------
+
+/*`
+ [heading `BOOST_HW_SIMD_ARM_NEON_VERSION`]
+
+ The [@https://en.wikipedia.org/wiki/ARM_architecture#Advanced_SIMD_.28NEON.29 NEON]
+ ARM extension version number.
+
+ Version number is: *1.0.0*.
+ */
+#define BOOST_HW_SIMD_ARM_NEON_VERSION BOOST_VERSION_NUMBER(1, 0, 0)
+
+#endif
diff --git a/third_party/boost/boost/predef/hardware/simd/ppc.h b/third_party/boost/boost/predef/hardware/simd/ppc.h
new file mode 100644
index 0000000..eef25c2
--- /dev/null
+++ b/third_party/boost/boost/predef/hardware/simd/ppc.h
@@ -0,0 +1,69 @@
+/*
+Copyright Charly Chevalier 2015
+Copyright Joel Falcou 2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_HARDWARE_SIMD_PPC_H
+#define BOOST_PREDEF_HARDWARE_SIMD_PPC_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/hardware/simd/ppc/versions.h>
+
+/*`
+ [heading `BOOST_HW_SIMD_PPC`]
+
+ The SIMD extension for PowerPC (*if detected*).
+ Version number depends on the most recent detected extension.
+
+ [table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__VECTOR4DOUBLE__`] [__predef_detection__]]
+
+ [[`__ALTIVEC__`] [__predef_detection__]]
+ [[`__VEC__`] [__predef_detection__]]
+
+ [[`__VSX__`] [__predef_detection__]]
+ ]
+
+ [table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__VECTOR4DOUBLE__`] [BOOST_HW_SIMD_PPC_QPX_VERSION]]
+
+ [[`__ALTIVEC__`] [BOOST_HW_SIMD_PPC_VMX_VERSION]]
+ [[`__VEC__`] [BOOST_HW_SIMD_PPC_VMX_VERSION]]
+
+ [[`__VSX__`] [BOOST_HW_SIMD_PPC_VSX_VERSION]]
+ ]
+
+ */
+
+#define BOOST_HW_SIMD_PPC BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#undef BOOST_HW_SIMD_PPC
+#if !defined(BOOST_HW_SIMD_PPC) && defined(__VECTOR4DOUBLE__)
+# define BOOST_HW_SIMD_PPC BOOST_HW_SIMD_PPC_QPX_VERSION
+#endif
+#if !defined(BOOST_HW_SIMD_PPC) && defined(__VSX__)
+# define BOOST_HW_SIMD_PPC BOOST_HW_SIMD_PPC_VSX_VERSION
+#endif
+#if !defined(BOOST_HW_SIMD_PPC) && (defined(__ALTIVEC__) || defined(__VEC__))
+# define BOOST_HW_SIMD_PPC BOOST_HW_SIMD_PPC_VMX_VERSION
+#endif
+
+#if !defined(BOOST_HW_SIMD_PPC)
+# define BOOST_HW_SIMD_PPC BOOST_VERSION_NUMBER_NOT_AVAILABLE
+#else
+# define BOOST_HW_SIMD_PPC_AVAILABLE
+#endif
+
+#define BOOST_HW_SIMD_PPC_NAME "PPC SIMD"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_HW_SIMD_PPC, BOOST_HW_SIMD_PPC_NAME)
diff --git a/third_party/boost/boost/predef/hardware/simd/ppc/versions.h b/third_party/boost/boost/predef/hardware/simd/ppc/versions.h
new file mode 100644
index 0000000..ffe3f0b
--- /dev/null
+++ b/third_party/boost/boost/predef/hardware/simd/ppc/versions.h
@@ -0,0 +1,51 @@
+/*
+Copyright Charly Chevalier 2015
+Copyright Joel Falcou 2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_HARDWARE_SIMD_PPC_VERSIONS_H
+#define BOOST_PREDEF_HARDWARE_SIMD_PPC_VERSIONS_H
+
+#include <boost/predef/version_number.h>
+
+/*`
+ Those defines represent Power PC SIMD extensions versions.
+
+ [note You *MUST* compare them with the predef `BOOST_HW_SIMD_PPC`.]
+ */
+
+// ---------------------------------
+
+/*`
+ [heading `BOOST_HW_SIMD_PPC_VMX_VERSION`]
+
+ The [@https://en.wikipedia.org/wiki/AltiVec#VMX128 VMX] powerpc extension
+ version number.
+
+ Version number is: *1.0.0*.
+ */
+#define BOOST_HW_SIMD_PPC_VMX_VERSION BOOST_VERSION_NUMBER(1, 0, 0)
+
+/*`
+ [heading `BOOST_HW_SIMD_PPC_VSX_VERSION`]
+
+ The [@https://en.wikipedia.org/wiki/AltiVec#VSX VSX] powerpc extension version
+ number.
+
+ Version number is: *1.1.0*.
+ */
+#define BOOST_HW_SIMD_PPC_VSX_VERSION BOOST_VERSION_NUMBER(1, 1, 0)
+
+/*`
+ [heading `BOOST_HW_SIMD_PPC_QPX_VERSION`]
+
+ The QPX powerpc extension version number.
+
+ Version number is: *2.0.0*.
+ */
+#define BOOST_HW_SIMD_PPC_QPX_VERSION BOOST_VERSION_NUMBER(2, 0, 0)
+
+#endif
diff --git a/third_party/boost/boost/predef/hardware/simd/x86.h b/third_party/boost/boost/predef/hardware/simd/x86.h
new file mode 100644
index 0000000..0874bc4
--- /dev/null
+++ b/third_party/boost/boost/predef/hardware/simd/x86.h
@@ -0,0 +1,123 @@
+/*
+Copyright Charly Chevalier 2015
+Copyright Joel Falcou 2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_HARDWARE_SIMD_X86_H
+#define BOOST_PREDEF_HARDWARE_SIMD_X86_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/hardware/simd/x86/versions.h>
+
+/*`
+ [heading `BOOST_HW_SIMD_X86`]
+
+ The SIMD extension for x86 (*if detected*).
+ Version number depends on the most recent detected extension.
+
+ [table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__SSE__`] [__predef_detection__]]
+ [[`_M_X64`] [__predef_detection__]]
+ [[`_M_IX86_FP >= 1`] [__predef_detection__]]
+
+ [[`__SSE2__`] [__predef_detection__]]
+ [[`_M_X64`] [__predef_detection__]]
+ [[`_M_IX86_FP >= 2`] [__predef_detection__]]
+
+ [[`__SSE3__`] [__predef_detection__]]
+
+ [[`__SSSE3__`] [__predef_detection__]]
+
+ [[`__SSE4_1__`] [__predef_detection__]]
+
+ [[`__SSE4_2__`] [__predef_detection__]]
+
+ [[`__AVX__`] [__predef_detection__]]
+
+ [[`__FMA__`] [__predef_detection__]]
+
+ [[`__AVX2__`] [__predef_detection__]]
+ ]
+
+ [table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__SSE__`] [BOOST_HW_SIMD_X86_SSE_VERSION]]
+ [[`_M_X64`] [BOOST_HW_SIMD_X86_SSE_VERSION]]
+ [[`_M_IX86_FP >= 1`] [BOOST_HW_SIMD_X86_SSE_VERSION]]
+
+ [[`__SSE2__`] [BOOST_HW_SIMD_X86_SSE2_VERSION]]
+ [[`_M_X64`] [BOOST_HW_SIMD_X86_SSE2_VERSION]]
+ [[`_M_IX86_FP >= 2`] [BOOST_HW_SIMD_X86_SSE2_VERSION]]
+
+ [[`__SSE3__`] [BOOST_HW_SIMD_X86_SSE3_VERSION]]
+
+ [[`__SSSE3__`] [BOOST_HW_SIMD_X86_SSSE3_VERSION]]
+
+ [[`__SSE4_1__`] [BOOST_HW_SIMD_X86_SSE4_1_VERSION]]
+
+ [[`__SSE4_2__`] [BOOST_HW_SIMD_X86_SSE4_2_VERSION]]
+
+ [[`__AVX__`] [BOOST_HW_SIMD_X86_AVX_VERSION]]
+
+ [[`__FMA__`] [BOOST_HW_SIMD_X86_FMA3_VERSION]]
+
+ [[`__AVX2__`] [BOOST_HW_SIMD_x86_AVX2_VERSION]]
+ ]
+
+ */
+
+#define BOOST_HW_SIMD_X86 BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#undef BOOST_HW_SIMD_X86
+#if !defined(BOOST_HW_SIMD_X86) && defined(__MIC__)
+# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_MIC_VERSION
+#endif
+#if !defined(BOOST_HW_SIMD_X86) && defined(__AVX2__)
+# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_AVX2_VERSION
+#endif
+#if !defined(BOOST_HW_SIMD_X86) && defined(__AVX__)
+# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_AVX_VERSION
+#endif
+#if !defined(BOOST_HW_SIMD_X86) && defined(__FMA__)
+# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_FMA_VERSION
+#endif
+#if !defined(BOOST_HW_SIMD_X86) && defined(__SSE4_2__)
+# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_SSE4_2_VERSION
+#endif
+#if !defined(BOOST_HW_SIMD_X86) && defined(__SSE4_1__)
+# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_SSE4_1_VERSION
+#endif
+#if !defined(BOOST_HW_SIMD_X86) && defined(__SSSE3__)
+# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_SSSE3_VERSION
+#endif
+#if !defined(BOOST_HW_SIMD_X86) && defined(__SSE3__)
+# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_SSE3_VERSION
+#endif
+#if !defined(BOOST_HW_SIMD_X86) && (defined(__SSE2__) || defined(_M_X64) || _M_IX86_FP >= 2)
+# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_SSE2_VERSION
+#endif
+#if !defined(BOOST_HW_SIMD_X86) && (defined(__SSE__) || defined(_M_X64) || _M_IX86_FP >= 1)
+# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_SSE_VERSION
+#endif
+#if !defined(BOOST_HW_SIMD_X86) && defined(__MMX__)
+# define BOOST_HW_SIMD_X86 BOOST_HW_SIMD_X86_MMX_VERSION
+#endif
+
+#if !defined(BOOST_HW_SIMD_X86)
+# define BOOST_HW_SIMD_X86 BOOST_VERSION_NUMBER_NOT_AVAILABLE
+#else
+# define BOOST_HW_SIMD_X86_AVAILABLE
+#endif
+
+#define BOOST_HW_SIMD_X86_NAME "x86 SIMD"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_HW_SIMD_X86, BOOST_HW_SIMD_X86_NAME)
diff --git a/third_party/boost/boost/predef/hardware/simd/x86/versions.h b/third_party/boost/boost/predef/hardware/simd/x86/versions.h
new file mode 100644
index 0000000..0c7a4d3
--- /dev/null
+++ b/third_party/boost/boost/predef/hardware/simd/x86/versions.h
@@ -0,0 +1,129 @@
+/*
+Copyright Charly Chevalier 2015
+Copyright Joel Falcou 2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_HARDWARE_SIMD_X86_VERSIONS_H
+#define BOOST_PREDEF_HARDWARE_SIMD_X86_VERSIONS_H
+
+#include <boost/predef/version_number.h>
+
+/*`
+ Those defines represent x86 SIMD extensions versions.
+
+ [note You *MUST* compare them with the predef `BOOST_HW_SIMD_X86`.]
+ */
+
+// ---------------------------------
+
+/*`
+ [heading `BOOST_HW_SIMD_X86_MMX_VERSION`]
+
+ The [@https://en.wikipedia.org/wiki/MMX_(instruction_set) MMX] x86 extension
+ version number.
+
+ Version number is: *0.99.0*.
+ */
+#define BOOST_HW_SIMD_X86_MMX_VERSION BOOST_VERSION_NUMBER(0, 99, 0)
+
+/*`
+ [heading `BOOST_HW_SIMD_X86_SSE_VERSION`]
+
+ The [@https://en.wikipedia.org/wiki/Streaming_SIMD_Extensions SSE] x86 extension
+ version number.
+
+ Version number is: *1.0.0*.
+ */
+#define BOOST_HW_SIMD_X86_SSE_VERSION BOOST_VERSION_NUMBER(1, 0, 0)
+
+/*`
+ [heading `BOOST_HW_SIMD_X86_SSE2_VERSION`]
+
+ The [@https://en.wikipedia.org/wiki/SSE2 SSE2] x86 extension version number.
+
+ Version number is: *2.0.0*.
+ */
+#define BOOST_HW_SIMD_X86_SSE2_VERSION BOOST_VERSION_NUMBER(2, 0, 0)
+
+/*`
+ [heading `BOOST_HW_SIMD_X86_SSE3_VERSION`]
+
+ The [@https://en.wikipedia.org/wiki/SSE3 SSE3] x86 extension version number.
+
+ Version number is: *3.0.0*.
+ */
+#define BOOST_HW_SIMD_X86_SSE3_VERSION BOOST_VERSION_NUMBER(3, 0, 0)
+
+/*`
+ [heading `BOOST_HW_SIMD_X86_SSSE3_VERSION`]
+
+ The [@https://en.wikipedia.org/wiki/SSSE3 SSSE3] x86 extension version number.
+
+ Version number is: *3.1.0*.
+ */
+#define BOOST_HW_SIMD_X86_SSSE3_VERSION BOOST_VERSION_NUMBER(3, 1, 0)
+
+/*`
+ [heading `BOOST_HW_SIMD_X86_SSE4_1_VERSION`]
+
+ The [@https://en.wikipedia.org/wiki/SSE4#SSE4.1 SSE4_1] x86 extension version
+ number.
+
+ Version number is: *4.1.0*.
+ */
+#define BOOST_HW_SIMD_X86_SSE4_1_VERSION BOOST_VERSION_NUMBER(4, 1, 0)
+
+/*`
+ [heading `BOOST_HW_SIMD_X86_SSE4_2_VERSION`]
+
+ The [@https://en.wikipedia.org/wiki/SSE4##SSE4.2 SSE4_2] x86 extension version
+ number.
+
+ Version number is: *4.2.0*.
+ */
+#define BOOST_HW_SIMD_X86_SSE4_2_VERSION BOOST_VERSION_NUMBER(4, 2, 0)
+
+/*`
+ [heading `BOOST_HW_SIMD_X86_AVX_VERSION`]
+
+ The [@https://en.wikipedia.org/wiki/Advanced_Vector_Extensions AVX] x86
+ extension version number.
+
+ Version number is: *5.0.0*.
+ */
+#define BOOST_HW_SIMD_X86_AVX_VERSION BOOST_VERSION_NUMBER(5, 0, 0)
+
+/*`
+ [heading `BOOST_HW_SIMD_X86_FMA3_VERSION`]
+
+ The [@https://en.wikipedia.org/wiki/FMA_instruction_set FMA3] x86 extension
+ version number.
+
+ Version number is: *5.2.0*.
+ */
+#define BOOST_HW_SIMD_X86_FMA3_VERSION BOOST_VERSION_NUMBER(5, 2, 0)
+
+/*`
+ [heading `BOOST_HW_SIMD_X86_AVX2_VERSION`]
+
+ The [@https://en.wikipedia.org/wiki/Advanced_Vector_Extensions#Advanced_Vector_Extensions_2 AVX2]
+ x86 extension version number.
+
+ Version number is: *5.3.0*.
+ */
+#define BOOST_HW_SIMD_X86_AVX2_VERSION BOOST_VERSION_NUMBER(5, 3, 0)
+
+/*`
+ [heading `BOOST_HW_SIMD_X86_MIC_VERSION`]
+
+ The [@https://en.wikipedia.org/wiki/Xeon_Phi MIC] (Xeon Phi) x86 extension
+ version number.
+
+ Version number is: *9.0.0*.
+ */
+#define BOOST_HW_SIMD_X86_MIC_VERSION BOOST_VERSION_NUMBER(9, 0, 0)
+
+#endif
diff --git a/third_party/boost/boost/predef/hardware/simd/x86_amd.h b/third_party/boost/boost/predef/hardware/simd/x86_amd.h
new file mode 100644
index 0000000..60fd448
--- /dev/null
+++ b/third_party/boost/boost/predef/hardware/simd/x86_amd.h
@@ -0,0 +1,87 @@
+/*
+Copyright Charly Chevalier 2015
+Copyright Joel Falcou 2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_HARDWARE_SIMD_X86_AMD_H
+#define BOOST_PREDEF_HARDWARE_SIMD_X86_AMD_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/hardware/simd/x86_amd/versions.h>
+
+/*`
+ [heading `BOOST_HW_SIMD_X86_AMD`]
+
+ The SIMD extension for x86 (AMD) (*if detected*).
+ Version number depends on the most recent detected extension.
+
+ [table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__SSE4A__`] [__predef_detection__]]
+
+ [[`__FMA4__`] [__predef_detection__]]
+
+ [[`__XOP__`] [__predef_detection__]]
+
+ [[`BOOST_HW_SIMD_X86`] [__predef_detection__]]
+ ]
+
+ [table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__SSE4A__`] [BOOST_HW_SIMD_x86_SSE4A_VERSION]]
+
+ [[`__FMA4__`] [BOOST_HW_SIMD_x86_FMA4_VERSION]]
+
+ [[`__XOP__`] [BOOST_HW_SIMD_x86_XOP_VERSION]]
+
+ [[`BOOST_HW_SIMD_X86`] [BOOST_HW_SIMD_x86]]
+ ]
+
+ [note This predef includes every other x86 SIMD extensions and also has other
+ more specific extensions (FMA4, XOP, SSE4a). You should use this predef
+ instead of `BOOST_HW_SIMD_X86` to test if those specific extensions have
+ been detected.]
+
+ */
+
+#define BOOST_HW_SIMD_X86_AMD BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+// AMD CPUs also use x86 architecture. We first try to detect if any AMD
+// specific extension are detected, if yes, then try to detect more recent x86
+// common extensions.
+
+#undef BOOST_HW_SIMD_X86_AMD
+#if !defined(BOOST_HW_SIMD_X86_AMD) && defined(__XOP__)
+# define BOOST_HW_SIMD_X86_AMD BOOST_HW_SIMD_X86_AMD_XOP_VERSION
+#endif
+#if !defined(BOOST_HW_SIMD_X86_AMD) && defined(__FMA4__)
+# define BOOST_HW_SIMD_X86_AMD BOOST_HW_SIMD_X86_AMD_FMA4_VERSION
+#endif
+#if !defined(BOOST_HW_SIMD_X86_AMD) && defined(__SSE4A__)
+# define BOOST_HW_SIMD_X86_AMD BOOST_HW_SIMD_X86_AMD_SSE4A_VERSION
+#endif
+
+#if !defined(BOOST_HW_SIMD_X86_AMD)
+# define BOOST_HW_SIMD_X86_AMD BOOST_VERSION_NUMBER_NOT_AVAILABLE
+#else
+ // At this point, we know that we have an AMD CPU, we do need to check for
+ // other x86 extensions to determine the final version number.
+# include <boost/predef/hardware/simd/x86.h>
+# if BOOST_HW_SIMD_X86 > BOOST_HW_SIMD_X86_AMD
+# undef BOOST_HW_SIMD_X86_AMD
+# define BOOST_HW_SIMD_X86_AMD BOOST_HW_SIMD_X86
+# endif
+# define BOOST_HW_SIMD_X86_AMD_AVAILABLE
+#endif
+
+#define BOOST_HW_SIMD_X86_AMD_NAME "x86 (AMD) SIMD"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_HW_SIMD_X86_AMD, BOOST_HW_SIMD_X86_AMD_NAME)
diff --git a/third_party/boost/boost/predef/hardware/simd/x86_amd/versions.h b/third_party/boost/boost/predef/hardware/simd/x86_amd/versions.h
new file mode 100644
index 0000000..a0a9e91
--- /dev/null
+++ b/third_party/boost/boost/predef/hardware/simd/x86_amd/versions.h
@@ -0,0 +1,51 @@
+/*
+Copyright Charly Chevalier 2015
+Copyright Joel Falcou 2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_HARDWARE_SIMD_X86_AMD_VERSIONS_H
+#define BOOST_PREDEF_HARDWARE_SIMD_X86_AMD_VERSIONS_H
+
+#include <boost/predef/version_number.h>
+
+/*`
+ Those defines represent x86 (AMD specific) SIMD extensions versions.
+
+ [note You *MUST* compare them with the predef `BOOST_HW_SIMD_X86_AMD`.]
+ */
+
+
+// ---------------------------------
+
+/*`
+ [heading `BOOST_HW_SIMD_X86_SSE4A_VERSION`]
+
+ [@https://en.wikipedia.org/wiki/SSE4##SSE4A SSE4A] x86 extension (AMD specific).
+
+ Version number is: *4.0.0*.
+ */
+#define BOOST_HW_SIMD_X86_AMD_SSE4A_VERSION BOOST_VERSION_NUMBER(4, 0, 0)
+
+/*`
+ [heading `BOOST_HW_SIMD_X86_XOP_VERSION`]
+
+ [@https://en.wikipedia.org/wiki/XOP_instruction_set XOP] x86 extension (AMD specific).
+
+ Version number is: *5.1.0*.
+ */
+#define BOOST_HW_SIMD_X86_AMD_FMA4_VERSION BOOST_VERSION_NUMBER(5, 1, 0)
+
+/*`
+ [heading `BOOST_HW_SIMD_X86_XOP_VERSION`]
+
+ [@https://en.wikipedia.org/wiki/XOP_instruction_set XOP] x86 extension (AMD specific).
+
+ Version number is: *5.1.1*.
+ */
+#define BOOST_HW_SIMD_X86_AMD_XOP_VERSION BOOST_VERSION_NUMBER(5, 1, 1)
+
+
+#endif
diff --git a/third_party/boost/boost/predef/language.h b/third_party/boost/boost/predef/language.h
new file mode 100644
index 0000000..0a317d5
--- /dev/null
+++ b/third_party/boost/boost/predef/language.h
@@ -0,0 +1,17 @@
+/*
+Copyright Rene Rivera 2011-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#if !defined(BOOST_PREDEF_LANGUAGE_H) || defined(BOOST_PREDEF_INTERNAL_GENERATE_TESTS)
+#ifndef BOOST_PREDEF_LANGUAGE_H
+#define BOOST_PREDEF_LANGUAGE_H
+#endif
+
+#include <boost/predef/language/stdc.h>
+#include <boost/predef/language/stdcpp.h>
+#include <boost/predef/language/objc.h>
+
+#endif
diff --git a/third_party/boost/boost/predef/language/objc.h b/third_party/boost/boost/predef/language/objc.h
new file mode 100644
index 0000000..24e3ad3
--- /dev/null
+++ b/third_party/boost/boost/predef/language/objc.h
@@ -0,0 +1,42 @@
+/*
+Copyright Rene Rivera 2011-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_LANGUAGE_OBJC_H
+#define BOOST_PREDEF_LANGUAGE_OBJC_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_LANG_OBJC`]
+
+[@http://en.wikipedia.org/wiki/Objective-C Objective-C] language.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__OBJC__`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_LANG_OBJC BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__OBJC__)
+# undef BOOST_LANG_OBJC
+# define BOOST_LANG_OBJC BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_LANG_OBJC
+# define BOOST_LANG_OBJC_AVAILABLE
+#endif
+
+#define BOOST_LANG_OBJC_NAME "Objective-C"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_LANG_OBJC,BOOST_LANG_OBJC_NAME)
diff --git a/third_party/boost/boost/predef/language/stdc.h b/third_party/boost/boost/predef/language/stdc.h
new file mode 100644
index 0000000..db25c12
--- /dev/null
+++ b/third_party/boost/boost/predef/language/stdc.h
@@ -0,0 +1,53 @@
+/*
+Copyright Rene Rivera 2011-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_LANGUAGE_STDC_H
+#define BOOST_PREDEF_LANGUAGE_STDC_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_LANG_STDC`]
+
+[@http://en.wikipedia.org/wiki/C_(programming_language) Standard C] language.
+If available, the year of the standard is detected as YYYY.MM.1 from the Epoc date.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__STDC__`] [__predef_detection__]]
+
+ [[`__STDC_VERSION__`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_LANG_STDC BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__STDC__)
+# undef BOOST_LANG_STDC
+# if defined(__STDC_VERSION__)
+# if (__STDC_VERSION__ > 100)
+# define BOOST_LANG_STDC BOOST_PREDEF_MAKE_YYYYMM(__STDC_VERSION__)
+# else
+# define BOOST_LANG_STDC BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+# else
+# define BOOST_LANG_STDC BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_LANG_STDC
+# define BOOST_LANG_STDC_AVAILABLE
+#endif
+
+#define BOOST_LANG_STDC_NAME "Standard C"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_LANG_STDC,BOOST_LANG_STDC_NAME)
diff --git a/third_party/boost/boost/predef/language/stdcpp.h b/third_party/boost/boost/predef/language/stdcpp.h
new file mode 100644
index 0000000..34dc8c7
--- /dev/null
+++ b/third_party/boost/boost/predef/language/stdcpp.h
@@ -0,0 +1,121 @@
+/*
+Copyright Rene Rivera 2011-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_LANGUAGE_STDCPP_H
+#define BOOST_PREDEF_LANGUAGE_STDCPP_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_LANG_STDCPP`]
+
+[@http://en.wikipedia.org/wiki/C%2B%2B Standard C++] language.
+If available, the year of the standard is detected as YYYY.MM.1 from the Epoc date.
+Because of the way the C++ standardization process works the
+defined version year will not be the commonly known year of the standard.
+Specifically the defined versions are:
+
+[table Detected Version Number vs. C++ Standard Year
+ [[Detected Version Number] [Standard Year] [C++ Standard]]
+ [[27.11.1] [1998] [ISO/IEC 14882:1998]]
+ [[41.12.1] [2011] [ISO/IEC 14882:2011]]
+]
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__cplusplus`] [__predef_detection__]]
+
+ [[`__cplusplus`] [YYYY.MM.1]]
+ ]
+ */
+
+#define BOOST_LANG_STDCPP BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__cplusplus)
+# undef BOOST_LANG_STDCPP
+# if (__cplusplus > 100)
+# define BOOST_LANG_STDCPP BOOST_PREDEF_MAKE_YYYYMM(__cplusplus)
+# else
+# define BOOST_LANG_STDCPP BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_LANG_STDCPP
+# define BOOST_LANG_STDCPP_AVAILABLE
+#endif
+
+#define BOOST_LANG_STDCPP_NAME "Standard C++"
+
+/*`
+[heading `BOOST_LANG_STDCPPCLI`]
+
+[@http://en.wikipedia.org/wiki/C%2B%2B/CLI Standard C++/CLI] language.
+If available, the year of the standard is detected as YYYY.MM.1 from the Epoc date.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__cplusplus_cli`] [__predef_detection__]]
+
+ [[`__cplusplus_cli`] [YYYY.MM.1]]
+ ]
+ */
+
+#define BOOST_LANG_STDCPPCLI BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__cplusplus_cli)
+# undef BOOST_LANG_STDCPPCLI
+# if (__cplusplus_cli > 100)
+# define BOOST_LANG_STDCPPCLI BOOST_PREDEF_MAKE_YYYYMM(__cplusplus_cli)
+# else
+# define BOOST_LANG_STDCPPCLI BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_LANG_STDCPPCLI
+# define BOOST_LANG_STDCPPCLI_AVAILABLE
+#endif
+
+#define BOOST_LANG_STDCPPCLI_NAME "Standard C++/CLI"
+
+/*`
+[heading `BOOST_LANG_STDECPP`]
+
+[@http://en.wikipedia.org/wiki/Embedded_C%2B%2B Standard Embedded C++] language.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__embedded_cplusplus`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_LANG_STDECPP BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__embedded_cplusplus)
+# undef BOOST_LANG_STDECPP
+# define BOOST_LANG_STDECPP BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_LANG_STDECPP
+# define BOOST_LANG_STDECPP_AVAILABLE
+#endif
+
+#define BOOST_LANG_STDECPP_NAME "Standard Embedded C++"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_LANG_STDCPP,BOOST_LANG_STDCPP_NAME)
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_LANG_STDCPPCLI,BOOST_LANG_STDCPPCLI_NAME)
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_LANG_STDECPP,BOOST_LANG_STDECPP_NAME)
diff --git a/third_party/boost/boost/predef/library.h b/third_party/boost/boost/predef/library.h
new file mode 100644
index 0000000..40518a9
--- /dev/null
+++ b/third_party/boost/boost/predef/library.h
@@ -0,0 +1,16 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#if !defined(BOOST_PREDEF_LIBRARY_H) || defined(BOOST_PREDEF_INTERNAL_GENERATE_TESTS)
+#ifndef BOOST_PREDEF_LIBRARY_H
+#define BOOST_PREDEF_LIBRARY_H
+#endif
+
+#include <boost/predef/library/c.h>
+#include <boost/predef/library/std.h>
+
+#endif
diff --git a/third_party/boost/boost/predef/library/c.h b/third_party/boost/boost/predef/library/c.h
new file mode 100644
index 0000000..fa8841e
--- /dev/null
+++ b/third_party/boost/boost/predef/library/c.h
@@ -0,0 +1,20 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#if !defined(BOOST_PREDEF_LIBRARY_C_H) || defined(BOOST_PREDEF_INTERNAL_GENERATE_TESTS)
+#ifndef BOOST_PREDEF_LIBRARY_C_H
+#define BOOST_PREDEF_LIBRARY_C_H
+#endif
+
+#include <boost/predef/library/c/_prefix.h>
+
+#include <boost/predef/library/c/gnu.h>
+#include <boost/predef/library/c/uc.h>
+#include <boost/predef/library/c/vms.h>
+#include <boost/predef/library/c/zos.h>
+
+#endif
diff --git a/third_party/boost/boost/predef/library/c/_prefix.h b/third_party/boost/boost/predef/library/c/_prefix.h
new file mode 100644
index 0000000..12bcb0f
--- /dev/null
+++ b/third_party/boost/boost/predef/library/c/_prefix.h
@@ -0,0 +1,13 @@
+/*
+Copyright Rene Rivera 2008-2013
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_LIBRARY_C__PREFIX_H
+#define BOOST_PREDEF_LIBRARY_C__PREFIX_H
+
+#include <boost/predef/detail/_cassert.h>
+
+#endif
diff --git a/third_party/boost/boost/predef/library/c/gnu.h b/third_party/boost/boost/predef/library/c/gnu.h
new file mode 100644
index 0000000..9e4ca89
--- /dev/null
+++ b/third_party/boost/boost/predef/library/c/gnu.h
@@ -0,0 +1,61 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_LIBRARY_C_GNU_H
+#define BOOST_PREDEF_LIBRARY_C_GNU_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+#include <boost/predef/library/c/_prefix.h>
+
+#if defined(__STDC__)
+#include <stddef.h>
+#elif defined(__cplusplus)
+#include <cstddef>
+#endif
+
+/*`
+[heading `BOOST_LIB_C_GNU`]
+
+[@http://en.wikipedia.org/wiki/Glibc GNU glibc] Standard C library.
+Version number available as major, and minor.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__GLIBC__`] [__predef_detection__]]
+ [[`__GNU_LIBRARY__`] [__predef_detection__]]
+
+ [[`__GLIBC__`, `__GLIBC_MINOR__`] [V.R.0]]
+ [[`__GNU_LIBRARY__`, `__GNU_LIBRARY_MINOR__`] [V.R.0]]
+ ]
+ */
+
+#define BOOST_LIB_C_GNU BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__GLIBC__) || defined(__GNU_LIBRARY__)
+# undef BOOST_LIB_C_GNU
+# if defined(__GLIBC__)
+# define BOOST_LIB_C_GNU \
+ BOOST_VERSION_NUMBER(__GLIBC__,__GLIBC_MINOR__,0)
+# else
+# define BOOST_LIB_C_GNU \
+ BOOST_VERSION_NUMBER(__GNU_LIBRARY__,__GNU_LIBRARY_MINOR__,0)
+# endif
+#endif
+
+#if BOOST_LIB_C_GNU
+# define BOOST_LIB_C_GNU_AVAILABLE
+#endif
+
+#define BOOST_LIB_C_GNU_NAME "GNU"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_C_GNU,BOOST_LIB_C_GNU_NAME)
diff --git a/third_party/boost/boost/predef/library/c/uc.h b/third_party/boost/boost/predef/library/c/uc.h
new file mode 100644
index 0000000..03081e9
--- /dev/null
+++ b/third_party/boost/boost/predef/library/c/uc.h
@@ -0,0 +1,47 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_LIBRARY_C_UC_H
+#define BOOST_PREDEF_LIBRARY_C_UC_H
+
+#include <boost/predef/library/c/_prefix.h>
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_LIB_C_UC`]
+
+[@http://en.wikipedia.org/wiki/Uclibc uClibc] Standard C library.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__UCLIBC__`] [__predef_detection__]]
+
+ [[`__UCLIBC_MAJOR__`, `__UCLIBC_MINOR__`, `__UCLIBC_SUBLEVEL__`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_LIB_C_UC BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__UCLIBC__)
+# undef BOOST_LIB_C_UC
+# define BOOST_LIB_C_UC BOOST_VERSION_NUMBER(\
+ __UCLIBC_MAJOR__,__UCLIBC_MINOR__,__UCLIBC_SUBLEVEL__)
+#endif
+
+#if BOOST_LIB_C_UC
+# define BOOST_LIB_C_UC_AVAILABLE
+#endif
+
+#define BOOST_LIB_C_UC_NAME "uClibc"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_C_UC,BOOST_LIB_C_UC_NAME)
diff --git a/third_party/boost/boost/predef/library/c/vms.h b/third_party/boost/boost/predef/library/c/vms.h
new file mode 100644
index 0000000..685f1a7
--- /dev/null
+++ b/third_party/boost/boost/predef/library/c/vms.h
@@ -0,0 +1,47 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_LIBRARY_C_VMS_H
+#define BOOST_PREDEF_LIBRARY_C_VMS_H
+
+#include <boost/predef/library/c/_prefix.h>
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_LIB_C_VMS`]
+
+VMS libc Standard C library.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__CRTL_VER`] [__predef_detection__]]
+
+ [[`__CRTL_VER`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_LIB_C_VMS BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__CRTL_VER)
+# undef BOOST_LIB_C_VMS
+# define BOOST_LIB_C_VMS BOOST_PREDEF_MAKE_10_VVRR0PP00(__CRTL_VER)
+#endif
+
+#if BOOST_LIB_C_VMS
+# define BOOST_LIB_C_VMS_AVAILABLE
+#endif
+
+#define BOOST_LIB_C_VMS_NAME "VMS"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_C_VMS,BOOST_LIB_C_VMS_NAME)
diff --git a/third_party/boost/boost/predef/library/c/zos.h b/third_party/boost/boost/predef/library/c/zos.h
new file mode 100644
index 0000000..222d355
--- /dev/null
+++ b/third_party/boost/boost/predef/library/c/zos.h
@@ -0,0 +1,56 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_LIBRARY_C_ZOS_H
+#define BOOST_PREDEF_LIBRARY_C_ZOS_H
+
+#include <boost/predef/library/c/_prefix.h>
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_LIB_C_ZOS`]
+
+z/OS libc Standard C library.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__LIBREL__`] [__predef_detection__]]
+
+ [[`__LIBREL__`] [V.R.P]]
+ [[`__TARGET_LIB__`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_LIB_C_ZOS BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__LIBREL__)
+# undef BOOST_LIB_C_ZOS
+# if !defined(BOOST_LIB_C_ZOS) && defined(__LIBREL__)
+# define BOOST_LIB_C_ZOS BOOST_PREDEF_MAKE_0X_VRRPPPP(__LIBREL__)
+# endif
+# if !defined(BOOST_LIB_C_ZOS) && defined(__TARGET_LIB__)
+# define BOOST_LIB_C_ZOS BOOST_PREDEF_MAKE_0X_VRRPPPP(__TARGET_LIB__)
+# endif
+# if !defined(BOOST_LIB_C_ZOS)
+# define BOOST_LIB_C_ZOS BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_LIB_C_ZOS
+# define BOOST_LIB_C_ZOS_AVAILABLE
+#endif
+
+#define BOOST_LIB_C_ZOS_NAME "z/OS"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_C_ZOS,BOOST_LIB_C_ZOS_NAME)
diff --git a/third_party/boost/boost/predef/library/std.h b/third_party/boost/boost/predef/library/std.h
new file mode 100644
index 0000000..403b6ff
--- /dev/null
+++ b/third_party/boost/boost/predef/library/std.h
@@ -0,0 +1,25 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+#if !defined(BOOST_PREDEF_LIBRARY_STD_H) || defined(BOOST_PREDEF_INTERNAL_GENERATE_TESTS)
+#ifndef BOOST_PREDEF_LIBRARY_STD_H
+#define BOOST_PREDEF_LIBRARY_STD_H
+#endif
+
+#include <boost/predef/library/std/_prefix.h>
+
+#include <boost/predef/library/std/cxx.h>
+#include <boost/predef/library/std/dinkumware.h>
+#include <boost/predef/library/std/libcomo.h>
+#include <boost/predef/library/std/modena.h>
+#include <boost/predef/library/std/msl.h>
+#include <boost/predef/library/std/roguewave.h>
+#include <boost/predef/library/std/sgi.h>
+#include <boost/predef/library/std/stdcpp3.h>
+#include <boost/predef/library/std/stlport.h>
+#include <boost/predef/library/std/vacpp.h>
+
+#endif
diff --git a/third_party/boost/boost/predef/library/std/_prefix.h b/third_party/boost/boost/predef/library/std/_prefix.h
new file mode 100644
index 0000000..932b855
--- /dev/null
+++ b/third_party/boost/boost/predef/library/std/_prefix.h
@@ -0,0 +1,23 @@
+/*
+Copyright Rene Rivera 2008-2013
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+#ifndef BOOST_PREDEF_LIBRARY_STD__PREFIX_H
+#define BOOST_PREDEF_LIBRARY_STD__PREFIX_H
+
+/*
+We need to include an STD header to gives us the context
+of which library we are using. The "smallest" code-wise header
+seems to be <exception>. Boost uses <utility> but as far
+as I can tell (RR) it's not a stand-alone header in most
+implementations. Using <exception> also has the benefit of
+being available in EC++, so we get a chance to make this work
+for embedded users. And since it's not a header impacted by TR1
+there's no magic needed for inclusion in the face of the
+Boost.TR1 library.
+*/
+#include <boost/predef/detail/_exception.h>
+
+#endif
diff --git a/third_party/boost/boost/predef/library/std/cxx.h b/third_party/boost/boost/predef/library/std/cxx.h
new file mode 100644
index 0000000..07b52cd
--- /dev/null
+++ b/third_party/boost/boost/predef/library/std/cxx.h
@@ -0,0 +1,46 @@
+/*
+Copyright Rene Rivera 2011-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_LIBRARY_STD_CXX_H
+#define BOOST_PREDEF_LIBRARY_STD_CXX_H
+
+#include <boost/predef/library/std/_prefix.h>
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_LIB_STD_CXX`]
+
+[@http://libcxx.llvm.org/ libc++] C++ Standard Library.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`_LIBCPP_VERSION`] [__predef_detection__]]
+
+ [[`_LIBCPP_VERSION`] [V.0.P]]
+ ]
+ */
+
+#define BOOST_LIB_STD_CXX BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(_LIBCPP_VERSION)
+# undef BOOST_LIB_STD_CXX
+# define BOOST_LIB_STD_CXX BOOST_PREDEF_MAKE_10_VPPP(_LIBCPP_VERSION)
+#endif
+
+#if BOOST_LIB_STD_CXX
+# define BOOST_LIB_STD_CXX_AVAILABLE
+#endif
+
+#define BOOST_LIB_STD_CXX_NAME "libc++"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_STD_CXX,BOOST_LIB_STD_CXX_NAME)
diff --git a/third_party/boost/boost/predef/library/std/dinkumware.h b/third_party/boost/boost/predef/library/std/dinkumware.h
new file mode 100644
index 0000000..0fc0776
--- /dev/null
+++ b/third_party/boost/boost/predef/library/std/dinkumware.h
@@ -0,0 +1,52 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_LIBRARY_STD_DINKUMWARE_H
+#define BOOST_PREDEF_LIBRARY_STD_DINKUMWARE_H
+
+#include <boost/predef/library/std/_prefix.h>
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_LIB_STD_DINKUMWARE`]
+
+[@http://en.wikipedia.org/wiki/Dinkumware Dinkumware] Standard C++ Library.
+If available version number as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`_YVALS`, `__IBMCPP__`] [__predef_detection__]]
+ [[`_CPPLIB_VER`] [__predef_detection__]]
+
+ [[`_CPPLIB_VER`] [V.R.0]]
+ ]
+ */
+
+#define BOOST_LIB_STD_DINKUMWARE BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if (defined(_YVALS) && !defined(__IBMCPP__)) || defined(_CPPLIB_VER)
+# undef BOOST_LIB_STD_DINKUMWARE
+# if defined(_CPPLIB_VER)
+# define BOOST_LIB_STD_DINKUMWARE BOOST_PREDEF_MAKE_10_VVRR(_CPPLIB_VER)
+# else
+# define BOOST_LIB_STD_DINKUMWARE BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_LIB_STD_DINKUMWARE
+# define BOOST_LIB_STD_DINKUMWARE_AVAILABLE
+#endif
+
+#define BOOST_LIB_STD_DINKUMWARE_NAME "Dinkumware"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_STD_DINKUMWARE,BOOST_LIB_STD_DINKUMWARE_NAME)
diff --git a/third_party/boost/boost/predef/library/std/libcomo.h b/third_party/boost/boost/predef/library/std/libcomo.h
new file mode 100644
index 0000000..97d4a53
--- /dev/null
+++ b/third_party/boost/boost/predef/library/std/libcomo.h
@@ -0,0 +1,47 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_LIBRARY_STD_LIBCOMO_H
+#define BOOST_PREDEF_LIBRARY_STD_LIBCOMO_H
+
+#include <boost/predef/library/std/_prefix.h>
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_LIB_STD_COMO`]
+
+[@http://www.comeaucomputing.com/libcomo/ Comeau Computing] Standard C++ Library.
+Version number available as major.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__LIBCOMO__`] [__predef_detection__]]
+
+ [[`__LIBCOMO_VERSION__`] [V.0.0]]
+ ]
+ */
+
+#define BOOST_LIB_STD_COMO BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__LIBCOMO__)
+# undef BOOST_LIB_STD_COMO
+# define BOOST_LIB_STD_COMO BOOST_VERSION_NUMBER(__LIBCOMO_VERSION__,0,0)
+#endif
+
+#if BOOST_LIB_STD_COMO
+# define BOOST_LIB_STD_COMO_AVAILABLE
+#endif
+
+#define BOOST_LIB_STD_COMO_NAME "Comeau Computing"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_STD_COMO,BOOST_LIB_STD_COMO_NAME)
diff --git a/third_party/boost/boost/predef/library/std/modena.h b/third_party/boost/boost/predef/library/std/modena.h
new file mode 100644
index 0000000..b67ac62
--- /dev/null
+++ b/third_party/boost/boost/predef/library/std/modena.h
@@ -0,0 +1,45 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_LIBRARY_STD_MODENA_H
+#define BOOST_PREDEF_LIBRARY_STD_MODENA_H
+
+#include <boost/predef/library/std/_prefix.h>
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_LIB_STD_MSIPL`]
+
+[@http://modena.us/ Modena Software Lib++] Standard C++ Library.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`MSIPL_COMPILE_H`] [__predef_detection__]]
+ [[`__MSIPL_COMPILE_H`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_LIB_STD_MSIPL BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(MSIPL_COMPILE_H) || defined(__MSIPL_COMPILE_H)
+# undef BOOST_LIB_STD_MSIPL
+# define BOOST_LIB_STD_MSIPL BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_LIB_STD_MSIPL
+# define BOOST_LIB_STD_MSIPL_AVAILABLE
+#endif
+
+#define BOOST_LIB_STD_MSIPL_NAME "Modena Software Lib++"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_STD_MSIPL,BOOST_LIB_STD_MSIPL_NAME)
diff --git a/third_party/boost/boost/predef/library/std/msl.h b/third_party/boost/boost/predef/library/std/msl.h
new file mode 100644
index 0000000..d73c74c
--- /dev/null
+++ b/third_party/boost/boost/predef/library/std/msl.h
@@ -0,0 +1,53 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_LIBRARY_STD_MSL_H
+#define BOOST_PREDEF_LIBRARY_STD_MSL_H
+
+#include <boost/predef/library/std/_prefix.h>
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_LIB_STD_MSL`]
+
+[@http://www.freescale.com/ Metrowerks] Standard C++ Library.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__MSL_CPP__`] [__predef_detection__]]
+ [[`__MSL__`] [__predef_detection__]]
+
+ [[`__MSL_CPP__`] [V.R.P]]
+ [[`__MSL__`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_LIB_STD_MSL BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__MSL_CPP__) || defined(__MSL__)
+# undef BOOST_LIB_STD_MSL
+# if defined(__MSL_CPP__)
+# define BOOST_LIB_STD_MSL BOOST_PREDEF_MAKE_0X_VRPP(__MSL_CPP__)
+# else
+# define BOOST_LIB_STD_MSL BOOST_PREDEF_MAKE_0X_VRPP(__MSL__)
+# endif
+#endif
+
+#if BOOST_LIB_STD_MSL
+# define BOOST_LIB_STD_MSL_AVAILABLE
+#endif
+
+#define BOOST_LIB_STD_MSL_NAME "Metrowerks"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_STD_MSL,BOOST_LIB_STD_MSL_NAME)
diff --git a/third_party/boost/boost/predef/library/std/roguewave.h b/third_party/boost/boost/predef/library/std/roguewave.h
new file mode 100644
index 0000000..9c3f288
--- /dev/null
+++ b/third_party/boost/boost/predef/library/std/roguewave.h
@@ -0,0 +1,56 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_LIBRARY_STD_ROGUEWAVE_H
+#define BOOST_PREDEF_LIBRARY_STD_ROGUEWAVE_H
+
+#include <boost/predef/library/std/_prefix.h>
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_LIB_STD_RW`]
+
+[@http://stdcxx.apache.org/ Roguewave] Standard C++ library.
+If available version number as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__STD_RWCOMPILER_H__`] [__predef_detection__]]
+ [[`_RWSTD_VER`] [__predef_detection__]]
+
+ [[`_RWSTD_VER`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_LIB_STD_RW BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER)
+# undef BOOST_LIB_STD_RW
+# if defined(_RWSTD_VER)
+# if _RWSTD_VER < 0x010000
+# define BOOST_LIB_STD_RW BOOST_PREDEF_MAKE_0X_VVRRP(_RWSTD_VER)
+# else
+# define BOOST_LIB_STD_RW BOOST_PREDEF_MAKE_0X_VVRRPP(_RWSTD_VER)
+# endif
+# else
+# define BOOST_LIB_STD_RW BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_LIB_STD_RW
+# define BOOST_LIB_STD_RW_AVAILABLE
+#endif
+
+#define BOOST_LIB_STD_RW_NAME "Roguewave"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_STD_RW,BOOST_LIB_STD_RW_NAME)
diff --git a/third_party/boost/boost/predef/library/std/sgi.h b/third_party/boost/boost/predef/library/std/sgi.h
new file mode 100644
index 0000000..5d19bba
--- /dev/null
+++ b/third_party/boost/boost/predef/library/std/sgi.h
@@ -0,0 +1,51 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_LIBRARY_STD_SGI_H
+#define BOOST_PREDEF_LIBRARY_STD_SGI_H
+
+#include <boost/predef/library/std/_prefix.h>
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_LIB_STD_SGI`]
+
+[@http://www.sgi.com/tech/stl/ SGI] Standard C++ library.
+If available version number as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__STL_CONFIG_H`] [__predef_detection__]]
+
+ [[`__SGI_STL`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_LIB_STD_SGI BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__STL_CONFIG_H)
+# undef BOOST_LIB_STD_SGI
+# if defined(__SGI_STL)
+# define BOOST_LIB_STD_SGI BOOST_PREDEF_MAKE_0X_VRP(__SGI_STL)
+# else
+# define BOOST_LIB_STD_SGI BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_LIB_STD_SGI
+# define BOOST_LIB_STD_SGI_AVAILABLE
+#endif
+
+#define BOOST_LIB_STD_SGI_NAME "SGI"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_STD_SGI,BOOST_LIB_STD_SGI_NAME)
diff --git a/third_party/boost/boost/predef/library/std/stdcpp3.h b/third_party/boost/boost/predef/library/std/stdcpp3.h
new file mode 100644
index 0000000..c980292
--- /dev/null
+++ b/third_party/boost/boost/predef/library/std/stdcpp3.h
@@ -0,0 +1,53 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_LIBRARY_STD_STDCPP3_H
+#define BOOST_PREDEF_LIBRARY_STD_STDCPP3_H
+
+#include <boost/predef/library/std/_prefix.h>
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_LIB_STD_GNU`]
+
+[@http://gcc.gnu.org/libstdc++/ GNU libstdc++] Standard C++ library.
+Version number available as year (from 1970), month, and day.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__GLIBCXX__`] [__predef_detection__]]
+ [[`__GLIBCPP__`] [__predef_detection__]]
+
+ [[`__GLIBCXX__`] [V.R.P]]
+ [[`__GLIBCPP__`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_LIB_STD_GNU BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__GLIBCPP__) || defined(__GLIBCXX__)
+# undef BOOST_LIB_STD_GNU
+# if defined(__GLIBCXX__)
+# define BOOST_LIB_STD_GNU BOOST_PREDEF_MAKE_YYYYMMDD(__GLIBCXX__)
+# else
+# define BOOST_LIB_STD_GNU BOOST_PREDEF_MAKE_YYYYMMDD(__GLIBCPP__)
+# endif
+#endif
+
+#if BOOST_LIB_STD_GNU
+# define BOOST_LIB_STD_GNU_AVAILABLE
+#endif
+
+#define BOOST_LIB_STD_GNU_NAME "GNU"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_STD_GNU,BOOST_LIB_STD_GNU_NAME)
diff --git a/third_party/boost/boost/predef/library/std/stlport.h b/third_party/boost/boost/predef/library/std/stlport.h
new file mode 100644
index 0000000..c09483b
--- /dev/null
+++ b/third_party/boost/boost/predef/library/std/stlport.h
@@ -0,0 +1,59 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_LIBRARY_STD_STLPORT_H
+#define BOOST_PREDEF_LIBRARY_STD_STLPORT_H
+
+#include <boost/predef/library/std/_prefix.h>
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_LIB_STD_STLPORT`]
+
+[@http://sourceforge.net/projects/stlport/ STLport Standard C++] library.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__SGI_STL_PORT`] [__predef_detection__]]
+ [[`_STLPORT_VERSION`] [__predef_detection__]]
+
+ [[`_STLPORT_MAJOR`, `_STLPORT_MINOR`, `_STLPORT_PATCHLEVEL`] [V.R.P]]
+ [[`_STLPORT_VERSION`] [V.R.P]]
+ [[`__SGI_STL_PORT`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_LIB_STD_STLPORT BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
+# undef BOOST_LIB_STD_STLPORT
+# if !defined(BOOST_LIB_STD_STLPORT) && defined(_STLPORT_MAJOR)
+# define BOOST_LIB_STD_STLPORT \
+ BOOST_VERSION_NUMBER(_STLPORT_MAJOR,_STLPORT_MINOR,_STLPORT_PATCHLEVEL)
+# endif
+# if !defined(BOOST_LIB_STD_STLPORT) && defined(_STLPORT_VERSION)
+# define BOOST_LIB_STD_STLPORT BOOST_PREDEF_MAKE_0X_VRP(_STLPORT_VERSION)
+# endif
+# if !defined(BOOST_LIB_STD_STLPORT)
+# define BOOST_LIB_STD_STLPORT BOOST_PREDEF_MAKE_0X_VRP(__SGI_STL_PORT)
+# endif
+#endif
+
+#if BOOST_LIB_STD_STLPORT
+# define BOOST_LIB_STD_STLPORT_AVAILABLE
+#endif
+
+#define BOOST_LIB_STD_STLPORT_NAME "STLport"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_STD_STLPORT,BOOST_LIB_STD_STLPORT_NAME)
diff --git a/third_party/boost/boost/predef/library/std/vacpp.h b/third_party/boost/boost/predef/library/std/vacpp.h
new file mode 100644
index 0000000..632f846
--- /dev/null
+++ b/third_party/boost/boost/predef/library/std/vacpp.h
@@ -0,0 +1,44 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_LIBRARY_STD_VACPP_H
+#define BOOST_PREDEF_LIBRARY_STD_VACPP_H
+
+#include <boost/predef/library/std/_prefix.h>
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_LIB_STD_IBM`]
+
+[@http://www.ibm.com/software/awdtools/xlcpp/ IBM VACPP Standard C++] library.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__IBMCPP__`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_LIB_STD_IBM BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__IBMCPP__)
+# undef BOOST_LIB_STD_IBM
+# define BOOST_LIB_STD_IBM BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_LIB_STD_IBM
+# define BOOST_LIB_STD_IBM_AVAILABLE
+#endif
+
+#define BOOST_LIB_STD_IBM_NAME "IBM VACPP"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_LIB_STD_IBM,BOOST_LIB_STD_IBM_NAME)
diff --git a/third_party/boost/boost/predef/make.h b/third_party/boost/boost/predef/make.h
new file mode 100644
index 0000000..4f2f9ee
--- /dev/null
+++ b/third_party/boost/boost/predef/make.h
@@ -0,0 +1,89 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the 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/predef/detail/test.h>
+
+#ifndef BOOST_PREDEF_MAKE_H
+#define BOOST_PREDEF_MAKE_H
+
+/*
+Shorthands for the common version number formats used by vendors...
+*/
+
+/*`
+[heading `BOOST_PREDEF_MAKE_..` macros]
+
+These set of macros decompose common vendor version number
+macros which are composed version, revision, and patch digits.
+The naming convention indicates:
+
+* The base of the specified version number. "`BOOST_PREDEF_MAKE_0X`" for
+ hexadecimal digits, and "`BOOST_PREDEF_MAKE_10`" for decimal digits.
+* The format of the vendor version number. Where "`V`" indicates the version digits,
+ "`R`" indicates the revision digits, "`P`" indicates the patch digits, and "`0`"
+ indicates an ignored digit.
+
+Macros are:
+*/
+/*` `BOOST_PREDEF_MAKE_0X_VRP(V)` */
+#define BOOST_PREDEF_MAKE_0X_VRP(V) BOOST_VERSION_NUMBER((V&0xF00)>>8,(V&0xF0)>>4,(V&0xF))
+/*` `BOOST_PREDEF_MAKE_0X_VVRP(V)` */
+#define BOOST_PREDEF_MAKE_0X_VVRP(V) BOOST_VERSION_NUMBER((V&0xFF00)>>8,(V&0xF0)>>4,(V&0xF))
+/*` `BOOST_PREDEF_MAKE_0X_VRPP(V)` */
+#define BOOST_PREDEF_MAKE_0X_VRPP(V) BOOST_VERSION_NUMBER((V&0xF000)>>12,(V&0xF00)>>8,(V&0xFF))
+/*` `BOOST_PREDEF_MAKE_0X_VVRR(V)` */
+#define BOOST_PREDEF_MAKE_0X_VVRR(V) BOOST_VERSION_NUMBER((V&0xFF00)>>8,(V&0xFF),0)
+/*` `BOOST_PREDEF_MAKE_0X_VRRPPPP(V)` */
+#define BOOST_PREDEF_MAKE_0X_VRRPPPP(V) BOOST_VERSION_NUMBER((V&0xF000000)>>24,(V&0xFF0000)>>16,(V&0xFFFF))
+/*` `BOOST_PREDEF_MAKE_0X_VVRRP(V)` */
+#define BOOST_PREDEF_MAKE_0X_VVRRP(V) BOOST_VERSION_NUMBER((V&0xFF000)>>12,(V&0xFF0)>>4,(V&0xF))
+/*` `BOOST_PREDEF_MAKE_0X_VRRPP000(V)` */
+#define BOOST_PREDEF_MAKE_0X_VRRPP000(V) BOOST_VERSION_NUMBER((V&0xF0000000)>>28,(V&0xFF00000)>>20,(V&0xFF000)>>12)
+/*` `BOOST_PREDEF_MAKE_0X_VVRRPP(V)` */
+#define BOOST_PREDEF_MAKE_0X_VVRRPP(V) BOOST_VERSION_NUMBER((V&0xFF0000)>>16,(V&0xFF00)>>8,(V&0xFF))
+/*` `BOOST_PREDEF_MAKE_10_VPPP(V)` */
+#define BOOST_PREDEF_MAKE_10_VPPP(V) BOOST_VERSION_NUMBER(((V)/1000)%10,0,(V)%1000)
+/*` `BOOST_PREDEF_MAKE_10_VRP(V)` */
+#define BOOST_PREDEF_MAKE_10_VRP(V) BOOST_VERSION_NUMBER(((V)/100)%10,((V)/10)%10,(V)%10)
+/*` `BOOST_PREDEF_MAKE_10_VRP000(V)` */
+#define BOOST_PREDEF_MAKE_10_VRP000(V) BOOST_VERSION_NUMBER(((V)/100000)%10,((V)/10000)%10,((V)/1000)%10)
+/*` `BOOST_PREDEF_MAKE_10_VRPP(V)` */
+#define BOOST_PREDEF_MAKE_10_VRPP(V) BOOST_VERSION_NUMBER(((V)/1000)%10,((V)/100)%10,(V)%100)
+/*` `BOOST_PREDEF_MAKE_10_VRR(V)` */
+#define BOOST_PREDEF_MAKE_10_VRR(V) BOOST_VERSION_NUMBER(((V)/100)%10,(V)%100,0)
+/*` `BOOST_PREDEF_MAKE_10_VRRPP(V)` */
+#define BOOST_PREDEF_MAKE_10_VRRPP(V) BOOST_VERSION_NUMBER(((V)/10000)%10,((V)/100)%100,(V)%100)
+/*` `BOOST_PREDEF_MAKE_10_VRR000(V)` */
+#define BOOST_PREDEF_MAKE_10_VRR000(V) BOOST_VERSION_NUMBER(((V)/100000)%10,((V)/1000)%100,0)
+/*` `BOOST_PREDEF_MAKE_10_VV00(V)` */
+#define BOOST_PREDEF_MAKE_10_VV00(V) BOOST_VERSION_NUMBER(((V)/100)%100,0,0)
+/*` `BOOST_PREDEF_MAKE_10_VVRR(V)` */
+#define BOOST_PREDEF_MAKE_10_VVRR(V) BOOST_VERSION_NUMBER(((V)/100)%100,(V)%100,0)
+/*` `BOOST_PREDEF_MAKE_10_VVRRPP(V)` */
+#define BOOST_PREDEF_MAKE_10_VVRRPP(V) BOOST_VERSION_NUMBER(((V)/10000)%100,((V)/100)%100,(V)%100)
+/*` `BOOST_PREDEF_MAKE_10_VVRR0PP00(V)` */
+#define BOOST_PREDEF_MAKE_10_VVRR0PP00(V) BOOST_VERSION_NUMBER(((V)/10000000)%100,((V)/100000)%100,((V)/100)%100)
+/*` `BOOST_PREDEF_MAKE_10_VVRR0PPPP(V)` */
+#define BOOST_PREDEF_MAKE_10_VVRR0PPPP(V) BOOST_VERSION_NUMBER(((V)/10000000)%100,((V)/100000)%100,(V)%10000)
+/*` `BOOST_PREDEF_MAKE_10_VVRR00PP00(V)` */
+#define BOOST_PREDEF_MAKE_10_VVRR00PP00(V) BOOST_VERSION_NUMBER(((V)/100000000)%100,((V)/1000000)%100,((V)/100)%100)
+/*`
+[heading `BOOST_PREDEF_MAKE_*..` date macros]
+
+Date decomposition macros return a date in the relative to the 1970
+Epoch date. If the month is not available, January 1st is used as the month and day.
+If the day is not available, but the month is, the 1st of the month is used as the day.
+*/
+/*` `BOOST_PREDEF_MAKE_DATE(Y,M,D)` */
+#define BOOST_PREDEF_MAKE_DATE(Y,M,D) BOOST_VERSION_NUMBER((Y)%10000-1970,(M)%100,(D)%100)
+/*` `BOOST_PREDEF_MAKE_YYYYMMDD(V)` */
+#define BOOST_PREDEF_MAKE_YYYYMMDD(V) BOOST_PREDEF_MAKE_DATE(((V)/10000)%10000,((V)/100)%100,(V)%100)
+/*` `BOOST_PREDEF_MAKE_YYYY(V)` */
+#define BOOST_PREDEF_MAKE_YYYY(V) BOOST_PREDEF_MAKE_DATE(V,1,1)
+/*` `BOOST_PREDEF_MAKE_YYYYMM(V)` */
+#define BOOST_PREDEF_MAKE_YYYYMM(V) BOOST_PREDEF_MAKE_DATE((V)/100,(V)%100,1)
+
+#endif
diff --git a/third_party/boost/boost/predef/os.h b/third_party/boost/boost/predef/os.h
new file mode 100644
index 0000000..bedf99e
--- /dev/null
+++ b/third_party/boost/boost/predef/os.h
@@ -0,0 +1,33 @@
+/*
+Copyright Rene Rivera 2008-2015
+Copyright Franz Detro 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)
+*/
+
+#if !defined(BOOST_PREDEF_OS_H) || defined(BOOST_PREDEF_INTERNAL_GENERATE_TESTS)
+#ifndef BOOST_PREDEF_OS_H
+#define BOOST_PREDEF_OS_H
+#endif
+
+#include <boost/predef/os/aix.h>
+#include <boost/predef/os/amigaos.h>
+#include <boost/predef/os/android.h>
+#include <boost/predef/os/beos.h>
+#include <boost/predef/os/bsd.h>
+#include <boost/predef/os/cygwin.h>
+#include <boost/predef/os/haiku.h>
+#include <boost/predef/os/hpux.h>
+#include <boost/predef/os/irix.h>
+#include <boost/predef/os/ios.h>
+#include <boost/predef/os/linux.h>
+#include <boost/predef/os/macos.h>
+#include <boost/predef/os/os400.h>
+#include <boost/predef/os/qnxnto.h>
+#include <boost/predef/os/solaris.h>
+#include <boost/predef/os/unix.h>
+#include <boost/predef/os/vms.h>
+#include <boost/predef/os/windows.h>
+
+#endif
diff --git a/third_party/boost/boost/predef/os/aix.h b/third_party/boost/boost/predef/os/aix.h
new file mode 100644
index 0000000..3e5a953
--- /dev/null
+++ b/third_party/boost/boost/predef/os/aix.h
@@ -0,0 +1,66 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_OS_AIX_H
+#define BOOST_PREDEF_OS_AIX_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_OS_AIX`]
+
+[@http://en.wikipedia.org/wiki/AIX_operating_system IBM AIX] operating system.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`_AIX`] [__predef_detection__]]
+ [[`__TOS_AIX__`] [__predef_detection__]]
+
+ [[`_AIX43`] [4.3.0]]
+ [[`_AIX41`] [4.1.0]]
+ [[`_AIX32`] [3.2.0]]
+ [[`_AIX3`] [3.0.0]]
+ ]
+ */
+
+#define BOOST_OS_AIX BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \
+ defined(_AIX) || defined(__TOS_AIX__) \
+ )
+# undef BOOST_OS_AIX
+# if !defined(BOOST_OS_AIX) && defined(_AIX43)
+# define BOOST_OS_AIX BOOST_VERSION_NUMBER(4,3,0)
+# endif
+# if !defined(BOOST_OS_AIX) && defined(_AIX41)
+# define BOOST_OS_AIX BOOST_VERSION_NUMBER(4,1,0)
+# endif
+# if !defined(BOOST_OS_AIX) && defined(_AIX32)
+# define BOOST_OS_AIX BOOST_VERSION_NUMBER(3,2,0)
+# endif
+# if !defined(BOOST_OS_AIX) && defined(_AIX3)
+# define BOOST_OS_AIX BOOST_VERSION_NUMBER(3,0,0)
+# endif
+# if !defined(BOOST_OS_AIX)
+# define BOOST_OS_AIX BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_OS_AIX
+# define BOOST_OS_AIX_AVAILABLE
+# include <boost/predef/detail/os_detected.h>
+#endif
+
+#define BOOST_OS_AIX_NAME "IBM AIX"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_OS_AIX,BOOST_OS_AIX_NAME)
diff --git a/third_party/boost/boost/predef/os/amigaos.h b/third_party/boost/boost/predef/os/amigaos.h
new file mode 100644
index 0000000..7b32ddf
--- /dev/null
+++ b/third_party/boost/boost/predef/os/amigaos.h
@@ -0,0 +1,46 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_OS_AMIGAOS_H
+#define BOOST_PREDEF_OS_AMIGAOS_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_OS_AMIGAOS`]
+
+[@http://en.wikipedia.org/wiki/AmigaOS AmigaOS] operating system.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`AMIGA`] [__predef_detection__]]
+ [[`__amigaos__`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_OS_AMIGAOS BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \
+ defined(AMIGA) || defined(__amigaos__) \
+ )
+# undef BOOST_OS_AMIGAOS
+# define BOOST_OS_AMIGAOS BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_OS_AMIGAOS
+# define BOOST_OS_AMIGAOS_AVAILABLE
+# include <boost/predef/detail/os_detected.h>
+#endif
+
+#define BOOST_OS_AMIGAOS_NAME "AmigaOS"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_OS_AMIGAOS,BOOST_OS_AMIGAOS_NAME)
diff --git a/third_party/boost/boost/predef/os/android.h b/third_party/boost/boost/predef/os/android.h
new file mode 100644
index 0000000..00836e7
--- /dev/null
+++ b/third_party/boost/boost/predef/os/android.h
@@ -0,0 +1,45 @@
+/*
+Copyright Rene Rivera 2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_OS_ADROID_H
+#define BOOST_PREDEF_OS_ADROID_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_OS_ANDROID`]
+
+[@http://en.wikipedia.org/wiki/Android_%28operating_system%29 Android] operating system.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__ANDROID__`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_OS_ANDROID BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \
+ defined(__ANDROID__) \
+ )
+# undef BOOST_OS_ANDROID
+# define BOOST_OS_ANDROID BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_OS_ANDROID
+# define BOOST_OS_ANDROID_AVAILABLE
+# include <boost/predef/detail/os_detected.h>
+#endif
+
+#define BOOST_OS_ANDROID_NAME "Android"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_OS_ANDROID,BOOST_OS_ANDROID_NAME)
diff --git a/third_party/boost/boost/predef/os/beos.h b/third_party/boost/boost/predef/os/beos.h
new file mode 100644
index 0000000..19f4cb7
--- /dev/null
+++ b/third_party/boost/boost/predef/os/beos.h
@@ -0,0 +1,45 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_OS_BEOS_H
+#define BOOST_PREDEF_OS_BEOS_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_OS_BEOS`]
+
+[@http://en.wikipedia.org/wiki/BeOS BeOS] operating system.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__BEOS__`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_OS_BEOS BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \
+ defined(__BEOS__) \
+ )
+# undef BOOST_OS_BEOS
+# define BOOST_OS_BEOS BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_OS_BEOS
+# define BOOST_OS_BEOS_AVAILABLE
+# include <boost/predef/detail/os_detected.h>
+#endif
+
+#define BOOST_OS_BEOS_NAME "BeOS"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_OS_BEOS,BOOST_OS_BEOS_NAME)
diff --git a/third_party/boost/boost/predef/os/bsd.h b/third_party/boost/boost/predef/os/bsd.h
new file mode 100644
index 0000000..fad9aed
--- /dev/null
+++ b/third_party/boost/boost/predef/os/bsd.h
@@ -0,0 +1,103 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_OS_BSD_H
+#define BOOST_PREDEF_OS_BSD_H
+
+/* Special case: OSX will define BSD predefs if the sys/param.h
+ * header is included. We can guard against that, but only if we
+ * detect OSX first. Hence we will force include OSX detection
+ * before doing any BSD detection.
+ */
+#include <boost/predef/os/macos.h>
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_OS_BSD`]
+
+[@http://en.wikipedia.org/wiki/Berkeley_Software_Distribution BSD] operating system.
+
+BSD has various branch operating systems possible and each detected
+individually. This detects the following variations and sets a specific
+version number macro to match:
+
+* `BOOST_OS_BSD_DRAGONFLY` [@http://en.wikipedia.org/wiki/DragonFly_BSD DragonFly BSD]
+* `BOOST_OS_BSD_FREE` [@http://en.wikipedia.org/wiki/Freebsd FreeBSD]
+* `BOOST_OS_BSD_BSDI` [@http://en.wikipedia.org/wiki/BSD/OS BSDi BSD/OS]
+* `BOOST_OS_BSD_NET` [@http://en.wikipedia.org/wiki/Netbsd NetBSD]
+* `BOOST_OS_BSD_OPEN` [@http://en.wikipedia.org/wiki/Openbsd OpenBSD]
+
+[note The general `BOOST_OS_BSD` is set in all cases to indicate some form
+of BSD. If the above variants is detected the corresponding macro is also set.]
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`BSD`] [__predef_detection__]]
+ [[`_SYSTYPE_BSD`] [__predef_detection__]]
+
+ [[`BSD4_2`] [4.2.0]]
+ [[`BSD4_3`] [4.3.0]]
+ [[`BSD4_4`] [4.4.0]]
+ [[`BSD`] [V.R.0]]
+ ]
+ */
+
+#include <boost/predef/os/bsd/bsdi.h>
+#include <boost/predef/os/bsd/dragonfly.h>
+#include <boost/predef/os/bsd/free.h>
+#include <boost/predef/os/bsd/open.h>
+#include <boost/predef/os/bsd/net.h>
+
+#ifndef BOOST_OS_BSD
+#define BOOST_OS_BSD BOOST_VERSION_NUMBER_NOT_AVAILABLE
+#endif
+
+#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \
+ defined(BSD) || \
+ defined(_SYSTYPE_BSD) \
+ )
+# undef BOOST_OS_BSD
+# include <sys/param.h>
+# if !defined(BOOST_OS_BSD) && defined(BSD4_4)
+# define BOOST_OS_BSD BOOST_VERSION_NUMBER(4,4,0)
+# endif
+# if !defined(BOOST_OS_BSD) && defined(BSD4_3)
+# define BOOST_OS_BSD BOOST_VERSION_NUMBER(4,3,0)
+# endif
+# if !defined(BOOST_OS_BSD) && defined(BSD4_2)
+# define BOOST_OS_BSD BOOST_VERSION_NUMBER(4,2,0)
+# endif
+# if !defined(BOOST_OS_BSD) && defined(BSD)
+# define BOOST_OS_BSD BOOST_PREDEF_MAKE_10_VVRR(BSD)
+# endif
+# if !defined(BOOST_OS_BSD)
+# define BOOST_OS_BSD BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_OS_BSD
+# define BOOST_OS_BSD_AVAILABLE
+# include <boost/predef/detail/os_detected.h>
+#endif
+
+#define BOOST_OS_BSD_NAME "BSD"
+
+#else
+
+#include <boost/predef/os/bsd/bsdi.h>
+#include <boost/predef/os/bsd/dragonfly.h>
+#include <boost/predef/os/bsd/free.h>
+#include <boost/predef/os/bsd/open.h>
+#include <boost/predef/os/bsd/net.h>
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_OS_BSD,BOOST_OS_BSD_NAME)
diff --git a/third_party/boost/boost/predef/os/bsd/bsdi.h b/third_party/boost/boost/predef/os/bsd/bsdi.h
new file mode 100644
index 0000000..afdcd3e
--- /dev/null
+++ b/third_party/boost/boost/predef/os/bsd/bsdi.h
@@ -0,0 +1,48 @@
+/*
+Copyright Rene Rivera 2012-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_OS_BSD_BSDI_H
+#define BOOST_PREDEF_OS_BSD_BSDI_H
+
+#include <boost/predef/os/bsd.h>
+
+/*`
+[heading `BOOST_OS_BSD_BSDI`]
+
+[@http://en.wikipedia.org/wiki/BSD/OS BSDi BSD/OS] operating system.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__bsdi__`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_OS_BSD_BSDI BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \
+ defined(__bsdi__) \
+ )
+# ifndef BOOST_OS_BSD_AVAILABLE
+# define BOOST_OS_BSD BOOST_VERSION_NUMBER_AVAILABLE
+# define BOOST_OS_BSD_AVAILABLE
+# endif
+# undef BOOST_OS_BSD_BSDI
+# define BOOST_OS_BSD_BSDI BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_OS_BSD_BSDI
+# define BOOST_OS_BSD_BSDI_AVAILABLE
+# include <boost/predef/detail/os_detected.h>
+#endif
+
+#define BOOST_OS_BSD_BSDI_NAME "BSDi BSD/OS"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_OS_BSD_BSDI,BOOST_OS_BSD_BSDI_NAME)
diff --git a/third_party/boost/boost/predef/os/bsd/dragonfly.h b/third_party/boost/boost/predef/os/bsd/dragonfly.h
new file mode 100644
index 0000000..1d07579
--- /dev/null
+++ b/third_party/boost/boost/predef/os/bsd/dragonfly.h
@@ -0,0 +1,50 @@
+/*
+Copyright Rene Rivera 2012-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_OS_BSD_DRAGONFLY_H
+#define BOOST_PREDEF_OS_BSD_DRAGONFLY_H
+
+#include <boost/predef/os/bsd.h>
+
+/*`
+[heading `BOOST_OS_BSD_DRAGONFLY`]
+
+[@http://en.wikipedia.org/wiki/DragonFly_BSD DragonFly BSD] operating system.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__DragonFly__`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_OS_BSD_DRAGONFLY BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \
+ defined(__DragonFly__) \
+ )
+# ifndef BOOST_OS_BSD_AVAILABLE
+# define BOOST_OS_BSD BOOST_VERSION_NUMBER_AVAILABLE
+# define BOOST_OS_BSD_AVAILABLE
+# endif
+# undef BOOST_OS_BSD_DRAGONFLY
+# if defined(__DragonFly__)
+# define BOOST_OS_DRAGONFLY_BSD BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_OS_BSD_DRAGONFLY
+# define BOOST_OS_BSD_DRAGONFLY_AVAILABLE
+# include <boost/predef/detail/os_detected.h>
+#endif
+
+#define BOOST_OS_BSD_DRAGONFLY_NAME "DragonFly BSD"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_OS_BSD_DRAGONFLY,BOOST_OS_BSD_DRAGONFLY_NAME)
diff --git a/third_party/boost/boost/predef/os/bsd/free.h b/third_party/boost/boost/predef/os/bsd/free.h
new file mode 100644
index 0000000..248011a
--- /dev/null
+++ b/third_party/boost/boost/predef/os/bsd/free.h
@@ -0,0 +1,60 @@
+/*
+Copyright Rene Rivera 2012-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_OS_BSD_FREE_H
+#define BOOST_PREDEF_OS_BSD_FREE_H
+
+#include <boost/predef/os/bsd.h>
+
+/*`
+[heading `BOOST_OS_BSD_FREE`]
+
+[@http://en.wikipedia.org/wiki/Freebsd FreeBSD] operating system.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__FreeBSD__`] [__predef_detection__]]
+
+ [[`__FreeBSD_version`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_OS_BSD_FREE BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \
+ defined(__FreeBSD__) \
+ )
+# ifndef BOOST_OS_BSD_AVAILABLE
+# define BOOST_OS_BSD BOOST_VERSION_NUMBER_AVAILABLE
+# define BOOST_OS_BSD_AVAILABLE
+# endif
+# undef BOOST_OS_BSD_FREE
+# if defined(__FreeBSD_version)
+# if __FreeBSD_version < 500000
+# define BOOST_OS_BSD_FREE \
+ BOOST_PREDEF_MAKE_10_VRP000(__FreeBSD_version)
+# else
+# define BOOST_OS_BSD_FREE \
+ BOOST_PREDEF_MAKE_10_VRR000(__FreeBSD_version)
+# endif
+# else
+# define BOOST_OS_BSD_FREE BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_OS_BSD_FREE
+# define BOOST_OS_BSD_FREE_AVAILABLE
+# include <boost/predef/detail/os_detected.h>
+#endif
+
+#define BOOST_OS_BSD_FREE_NAME "Free BSD"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_OS_BSD_FREE,BOOST_OS_BSD_FREE_NAME)
diff --git a/third_party/boost/boost/predef/os/bsd/net.h b/third_party/boost/boost/predef/os/bsd/net.h
new file mode 100644
index 0000000..387cbde
--- /dev/null
+++ b/third_party/boost/boost/predef/os/bsd/net.h
@@ -0,0 +1,84 @@
+/*
+Copyright Rene Rivera 2012-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_OS_BSD_NET_H
+#define BOOST_PREDEF_OS_BSD_NET_H
+
+#include <boost/predef/os/bsd.h>
+
+/*`
+[heading `BOOST_OS_BSD_NET`]
+
+[@http://en.wikipedia.org/wiki/Netbsd NetBSD] operating system.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__NETBSD__`] [__predef_detection__]]
+ [[`__NetBSD__`] [__predef_detection__]]
+
+ [[`__NETBSD_version`] [V.R.P]]
+ [[`NetBSD0_8`] [0.8.0]]
+ [[`NetBSD0_9`] [0.9.0]]
+ [[`NetBSD1_0`] [1.0.0]]
+ [[`__NetBSD_Version`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_OS_BSD_NET BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \
+ defined(__NETBSD__) || defined(__NetBSD__) \
+ )
+# ifndef BOOST_OS_BSD_AVAILABLE
+# define BOOST_OS_BSD BOOST_VERSION_NUMBER_AVAILABLE
+# define BOOST_OS_BSD_AVAILABLE
+# endif
+# undef BOOST_OS_BSD_NET
+# if defined(__NETBSD__)
+# if defined(__NETBSD_version)
+# if __NETBSD_version < 500000
+# define BOOST_OS_BSD_NET \
+ BOOST_PREDEF_MAKE_10_VRP000(__NETBSD_version)
+# else
+# define BOOST_OS_BSD_NET \
+ BOOST_PREDEF_MAKE_10_VRR000(__NETBSD_version)
+# endif
+# else
+# define BOOST_OS_BSD_NET BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+# elif defined(__NetBSD__)
+# if !defined(BOOST_OS_BSD_NET) && defined(NetBSD0_8)
+# define BOOST_OS_BSD_NET BOOST_VERSION_NUMBER(0,8,0)
+# endif
+# if !defined(BOOST_OS_BSD_NET) && defined(NetBSD0_9)
+# define BOOST_OS_BSD_NET BOOST_VERSION_NUMBER(0,9,0)
+# endif
+# if !defined(BOOST_OS_BSD_NET) && defined(NetBSD1_0)
+# define BOOST_OS_BSD_NET BOOST_VERSION_NUMBER(1,0,0)
+# endif
+# if !defined(BOOST_OS_BSD_NET) && defined(__NetBSD_Version)
+# define BOOST_OS_BSD_NET \
+ BOOST_PREDEF_MAKE_10_VVRR00PP00(__NetBSD_Version)
+# endif
+# if !defined(BOOST_OS_BSD_NET)
+# define BOOST_OS_BSD_NET BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+# endif
+#endif
+
+#if BOOST_OS_BSD_NET
+# define BOOST_OS_BSD_NET_AVAILABLE
+# include <boost/predef/detail/os_detected.h>
+#endif
+
+#define BOOST_OS_BSD_NET_NAME "DragonFly BSD"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_OS_BSD_NET,BOOST_OS_BSD_NET_NAME)
diff --git a/third_party/boost/boost/predef/os/bsd/open.h b/third_party/boost/boost/predef/os/bsd/open.h
new file mode 100644
index 0000000..423103a
--- /dev/null
+++ b/third_party/boost/boost/predef/os/bsd/open.h
@@ -0,0 +1,171 @@
+/*
+Copyright Rene Rivera 2012-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_OS_BSD_OPEN_H
+#define BOOST_PREDEF_OS_BSD_OPEN_H
+
+#include <boost/predef/os/bsd.h>
+
+/*`
+[heading `BOOST_OS_BSD_OPEN`]
+
+[@http://en.wikipedia.org/wiki/Openbsd OpenBSD] operating system.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__OpenBSD__`] [__predef_detection__]]
+
+ [[`OpenBSD2_0`] [2.0.0]]
+ [[`OpenBSD2_1`] [2.1.0]]
+ [[`OpenBSD2_2`] [2.2.0]]
+ [[`OpenBSD2_3`] [2.3.0]]
+ [[`OpenBSD2_4`] [2.4.0]]
+ [[`OpenBSD2_5`] [2.5.0]]
+ [[`OpenBSD2_6`] [2.6.0]]
+ [[`OpenBSD2_7`] [2.7.0]]
+ [[`OpenBSD2_8`] [2.8.0]]
+ [[`OpenBSD2_9`] [2.9.0]]
+ [[`OpenBSD3_0`] [3.0.0]]
+ [[`OpenBSD3_1`] [3.1.0]]
+ [[`OpenBSD3_2`] [3.2.0]]
+ [[`OpenBSD3_3`] [3.3.0]]
+ [[`OpenBSD3_4`] [3.4.0]]
+ [[`OpenBSD3_5`] [3.5.0]]
+ [[`OpenBSD3_6`] [3.6.0]]
+ [[`OpenBSD3_7`] [3.7.0]]
+ [[`OpenBSD3_8`] [3.8.0]]
+ [[`OpenBSD3_9`] [3.9.0]]
+ [[`OpenBSD4_0`] [4.0.0]]
+ [[`OpenBSD4_1`] [4.1.0]]
+ [[`OpenBSD4_2`] [4.2.0]]
+ [[`OpenBSD4_3`] [4.3.0]]
+ [[`OpenBSD4_4`] [4.4.0]]
+ [[`OpenBSD4_5`] [4.5.0]]
+ [[`OpenBSD4_6`] [4.6.0]]
+ [[`OpenBSD4_7`] [4.7.0]]
+ [[`OpenBSD4_8`] [4.8.0]]
+ [[`OpenBSD4_9`] [4.9.0]]
+ ]
+ */
+
+#define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \
+ defined(__OpenBSD__) \
+ )
+# ifndef BOOST_OS_BSD_AVAILABLE
+# define BOOST_OS_BSD BOOST_VERSION_NUMBER_AVAILABLE
+# define BOOST_OS_BSD_AVAILABLE
+# endif
+# undef BOOST_OS_BSD_OPEN
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD2_0)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(2,0,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD2_1)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(2,1,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD2_2)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(2,2,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD2_3)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(2,3,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD2_4)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(2,4,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD2_5)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(2,5,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD2_6)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(2,6,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD2_7)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(2,7,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD2_8)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(2,8,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD2_9)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(2,9,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD3_0)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(3,0,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD3_1)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(3,1,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD3_2)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(3,2,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD3_3)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(3,3,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD3_4)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(3,4,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD3_5)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(3,5,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD3_6)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(3,6,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD3_7)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(3,7,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD3_8)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(3,8,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD3_9)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(3,9,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD4_0)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(4,0,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD4_1)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(4,1,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD4_2)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(4,2,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD4_3)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(4,3,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD4_4)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(4,4,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD4_5)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(4,5,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD4_6)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(4,6,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD4_7)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(4,7,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD4_8)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(4,8,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN) && defined(OpenBSD4_9)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER(4,9,0)
+# endif
+# if !defined(BOOST_OS_BSD_OPEN)
+# define BOOST_OS_BSD_OPEN BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_OS_BSD_OPEN
+# define BOOST_OS_BSD_OPEN_AVAILABLE
+# include <boost/predef/detail/os_detected.h>
+#endif
+
+#define BOOST_OS_BSD_OPEN_NAME "OpenBSD"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_OS_BSD_OPEN,BOOST_OS_BSD_OPEN_NAME)
diff --git a/third_party/boost/boost/predef/os/cygwin.h b/third_party/boost/boost/predef/os/cygwin.h
new file mode 100644
index 0000000..1985c97
--- /dev/null
+++ b/third_party/boost/boost/predef/os/cygwin.h
@@ -0,0 +1,45 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_OS_CYGWIN_H
+#define BOOST_PREDEF_OS_CYGWIN_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_OS_CYGWIN`]
+
+[@http://en.wikipedia.org/wiki/Cygwin Cygwin] evironment.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__CYGWIN__`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_OS_CYGWIN BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \
+ defined(__CYGWIN__) \
+ )
+# undef BOOST_OS_CYGWIN
+# define BOOST_OS_CGYWIN BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_OS_CYGWIN
+# define BOOST_OS_CYGWIN_AVAILABLE
+# include <boost/predef/detail/os_detected.h>
+#endif
+
+#define BOOST_OS_CYGWIN_NAME "Cygwin"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_OS_CYGWIN,BOOST_OS_CYGWIN_NAME)
diff --git a/third_party/boost/boost/predef/os/haiku.h b/third_party/boost/boost/predef/os/haiku.h
new file mode 100644
index 0000000..d79dbea
--- /dev/null
+++ b/third_party/boost/boost/predef/os/haiku.h
@@ -0,0 +1,46 @@
+/*
+Copyright Jessica Hamilton 2014
+Copyright Rene Rivera 2014-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_OS_HAIKU_H
+#define BOOST_PREDEF_OS_HAIKU_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_OS_HAIKU`]
+
+[@http://en.wikipedia.org/wiki/Haiku_(operating_system) Haiku] operating system.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__HAIKU__`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_OS_HAIKU BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \
+ defined(__HAIKU__) \
+ )
+# undef BOOST_OS_HAIKU
+# define BOOST_OS_HAIKU BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_OS_HAIKU
+# define BOOST_OS_HAIKU_AVAILABLE
+# include <boost/predef/detail/os_detected.h>
+#endif
+
+#define BOOST_OS_HAIKU_NAME "Haiku"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_OS_HAIKU,BOOST_OS_HAIKU_NAME)
diff --git a/third_party/boost/boost/predef/os/hpux.h b/third_party/boost/boost/predef/os/hpux.h
new file mode 100644
index 0000000..29243f4
--- /dev/null
+++ b/third_party/boost/boost/predef/os/hpux.h
@@ -0,0 +1,47 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_OS_HPUX_H
+#define BOOST_PREDEF_OS_HPUX_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_OS_HPUX`]
+
+[@http://en.wikipedia.org/wiki/HP-UX HP-UX] operating system.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`hpux`] [__predef_detection__]]
+ [[`_hpux`] [__predef_detection__]]
+ [[`__hpux`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_OS_HPUX BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \
+ defined(hpux) || defined(_hpux) || defined(__hpux) \
+ )
+# undef BOOST_OS_HPUX
+# define BOOST_OS_HPUX BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_OS_HPUX
+# define BOOST_OS_HPUX_AVAILABLE
+# include <boost/predef/detail/os_detected.h>
+#endif
+
+#define BOOST_OS_HPUX_NAME "HP-UX"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_OS_HPUX,BOOST_OS_HPUX_NAME)
diff --git a/third_party/boost/boost/predef/os/ios.h b/third_party/boost/boost/predef/os/ios.h
new file mode 100644
index 0000000..f853815
--- /dev/null
+++ b/third_party/boost/boost/predef/os/ios.h
@@ -0,0 +1,51 @@
+/*
+Copyright Franz Detro 2014
+Copyright Rene Rivera 2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_OS_IOS_H
+#define BOOST_PREDEF_OS_IOS_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_OS_IOS`]
+
+[@http://en.wikipedia.org/wiki/iOS iOS] operating system.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__APPLE__`] [__predef_detection__]]
+ [[`__MACH__`] [__predef_detection__]]
+ [[`__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__`] [__predef_detection__]]
+
+ [[`__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__`] [__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__*1000]]
+ ]
+ */
+
+#define BOOST_OS_IOS BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \
+ defined(__APPLE__) && defined(__MACH__) && \
+ defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) \
+ )
+# undef BOOST_OS_IOS
+# define BOOST_OS_IOS (__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__*1000)
+#endif
+
+#if BOOST_OS_IOS
+# define BOOST_OS_IOS_AVAILABLE
+# include <boost/predef/detail/os_detected.h>
+#endif
+
+#define BOOST_OS_IOS_NAME "iOS"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_OS_IOS,BOOST_OS_IOS_NAME)
diff --git a/third_party/boost/boost/predef/os/irix.h b/third_party/boost/boost/predef/os/irix.h
new file mode 100644
index 0000000..fa6ac41
--- /dev/null
+++ b/third_party/boost/boost/predef/os/irix.h
@@ -0,0 +1,46 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_OS_IRIX_H
+#define BOOST_PREDEF_OS_IRIX_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_OS_IRIX`]
+
+[@http://en.wikipedia.org/wiki/Irix IRIX] operating system.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`sgi`] [__predef_detection__]]
+ [[`__sgi`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_OS_IRIX BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \
+ defined(sgi) || defined(__sgi) \
+ )
+# undef BOOST_OS_IRIX
+# define BOOST_OS_IRIX BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_OS_IRIX
+# define BOOST_OS_IRIX_AVAILABLE
+# include <boost/predef/detail/os_detected.h>
+#endif
+
+#define BOOST_OS_IRIX_NAME "IRIX"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_OS_IRIX,BOOST_OS_IRIX_NAME)
diff --git a/third_party/boost/boost/predef/os/linux.h b/third_party/boost/boost/predef/os/linux.h
new file mode 100644
index 0000000..a297d08
--- /dev/null
+++ b/third_party/boost/boost/predef/os/linux.h
@@ -0,0 +1,46 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_OS_LINUX_H
+#define BOOST_PREDEF_OS_LINUX_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_OS_LINUX`]
+
+[@http://en.wikipedia.org/wiki/Linux Linux] operating system.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`linux`] [__predef_detection__]]
+ [[`__linux`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_OS_LINUX BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \
+ defined(linux) || defined(__linux) \
+ )
+# undef BOOST_OS_LINUX
+# define BOOST_OS_LINUX BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_OS_LINUX
+# define BOOST_OS_LINUX_AVAILABLE
+# include <boost/predef/detail/os_detected.h>
+#endif
+
+#define BOOST_OS_LINUX_NAME "Linux"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_OS_LINUX,BOOST_OS_LINUX_NAME)
diff --git a/third_party/boost/boost/predef/os/macos.h b/third_party/boost/boost/predef/os/macos.h
new file mode 100644
index 0000000..4afb30d
--- /dev/null
+++ b/third_party/boost/boost/predef/os/macos.h
@@ -0,0 +1,65 @@
+/*
+Copyright Rene Rivera 2008-2015
+Copyright Franz Detro 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)
+*/
+
+#ifndef BOOST_PREDEF_OS_MACOS_H
+#define BOOST_PREDEF_OS_MACOS_H
+
+/* Special case: iOS will define the same predefs as MacOS, and additionally
+ '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__'. We can guard against that,
+ but only if we detect iOS first. Hence we will force include iOS detection
+ * before doing any MacOS detection.
+ */
+#include <boost/predef/os/ios.h>
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_OS_MACOS`]
+
+[@http://en.wikipedia.org/wiki/Mac_OS Mac OS] operating system.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`macintosh`] [__predef_detection__]]
+ [[`Macintosh`] [__predef_detection__]]
+ [[`__APPLE__`] [__predef_detection__]]
+ [[`__MACH__`] [__predef_detection__]]
+
+ [[`__APPLE__`, `__MACH__`] [10.0.0]]
+ [[ /otherwise/ ] [9.0.0]]
+ ]
+ */
+
+#define BOOST_OS_MACOS BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \
+ defined(macintosh) || defined(Macintosh) || \
+ (defined(__APPLE__) && defined(__MACH__)) \
+ )
+# undef BOOST_OS_MACOS
+# if !defined(BOOST_OS_MACOS) && defined(__APPLE__) && defined(__MACH__)
+# define BOOST_OS_MACOS BOOST_VERSION_NUMBER(10,0,0)
+# endif
+# if !defined(BOOST_OS_MACOS)
+# define BOOST_OS_MACOS BOOST_VERSION_NUMBER(9,0,0)
+# endif
+#endif
+
+#if BOOST_OS_MACOS
+# define BOOST_OS_MACOS_AVAILABLE
+# include <boost/predef/detail/os_detected.h>
+#endif
+
+#define BOOST_OS_MACOS_NAME "Mac OS"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_OS_MACOS,BOOST_OS_MACOS_NAME)
diff --git a/third_party/boost/boost/predef/os/os400.h b/third_party/boost/boost/predef/os/os400.h
new file mode 100644
index 0000000..b3446c2
--- /dev/null
+++ b/third_party/boost/boost/predef/os/os400.h
@@ -0,0 +1,45 @@
+/*
+Copyright Rene Rivera 2011-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_OS_OS400_H
+#define BOOST_PREDEF_OS_OS400_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_OS_OS400`]
+
+[@http://en.wikipedia.org/wiki/IBM_i IBM OS/400] operating system.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__OS400__`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_OS_OS400 BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \
+ defined(__OS400__) \
+ )
+# undef BOOST_OS_OS400
+# define BOOST_OS_OS400 BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_OS_OS400
+# define BOOST_OS_OS400_AVAILABLE
+# include <boost/predef/detail/os_detected.h>
+#endif
+
+#define BOOST_OS_OS400_NAME "IBM OS/400"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_OS_OS400,BOOST_OS_OS400_NAME)
diff --git a/third_party/boost/boost/predef/os/qnxnto.h b/third_party/boost/boost/predef/os/qnxnto.h
new file mode 100644
index 0000000..e76fbf2
--- /dev/null
+++ b/third_party/boost/boost/predef/os/qnxnto.h
@@ -0,0 +1,59 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_OS_QNXNTO_H
+#define BOOST_PREDEF_OS_QNXNTO_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_OS_QNX`]
+
+[@http://en.wikipedia.org/wiki/QNX QNX] operating system.
+Version number available as major, and minor if possible. And
+version 4 is specifically detected.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__QNX__`] [__predef_detection__]]
+ [[`__QNXNTO__`] [__predef_detection__]]
+
+ [[`_NTO_VERSION`] [V.R.0]]
+ [[`__QNX__`] [4.0.0]]
+ ]
+ */
+
+#define BOOST_OS_QNX BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \
+ defined(__QNX__) || defined(__QNXNTO__) \
+ )
+# undef BOOST_OS_QNX
+# if !defined(BOOST_OS_QNX) && defined(_NTO_VERSION)
+# define BOOST_OS_QNX BOOST_PREDEF_MAKE_10_VVRR(_NTO_VERSION)
+# endif
+# if !defined(BOOST_OS_QNX) && defined(__QNX__)
+# define BOOST_OS_QNX BOOST_VERSION_NUMBER(4,0,0)
+# endif
+# if !defined(BOOST_OS_QNX)
+# define BOOST_OS_QNX BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_OS_QNX
+# define BOOST_OS_QNX_AVAILABLE
+# include <boost/predef/detail/os_detected.h>
+#endif
+
+#define BOOST_OS_QNX_NAME "QNX"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_OS_QNX,BOOST_OS_QNX_NAME)
diff --git a/third_party/boost/boost/predef/os/solaris.h b/third_party/boost/boost/predef/os/solaris.h
new file mode 100644
index 0000000..75ddc91
--- /dev/null
+++ b/third_party/boost/boost/predef/os/solaris.h
@@ -0,0 +1,46 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_OS_SOLARIS_H
+#define BOOST_PREDEF_OS_SOLARIS_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_OS_SOLARIS`]
+
+[@http://en.wikipedia.org/wiki/Solaris_Operating_Environment Solaris] operating system.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`sun`] [__predef_detection__]]
+ [[`__sun`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_OS_SOLARIS BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \
+ defined(sun) || defined(__sun) \
+ )
+# undef BOOST_OS_SOLARIS
+# define BOOST_OS_SOLARIS BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_OS_SOLARIS
+# define BOOST_OS_SOLARIS_AVAILABLE
+# include <boost/predef/detail/os_detected.h>
+#endif
+
+#define BOOST_OS_SOLARIS_NAME "Solaris"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_OS_SOLARIS,BOOST_OS_SOLARIS_NAME)
diff --git a/third_party/boost/boost/predef/os/unix.h b/third_party/boost/boost/predef/os/unix.h
new file mode 100644
index 0000000..a607104
--- /dev/null
+++ b/third_party/boost/boost/predef/os/unix.h
@@ -0,0 +1,76 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_OS_UNIX_H
+#define BOOST_PREDEF_OS_UNIX_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_OS_UNIX`]
+
+[@http://en.wikipedia.org/wiki/Unix Unix Environment] operating system.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`unix`] [__predef_detection__]]
+ [[`__unix`] [__predef_detection__]]
+ [[`_XOPEN_SOURCE`] [__predef_detection__]]
+ [[`_POSIX_SOURCE`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_OS_UNIX BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(unix) || defined(__unix) || \
+ defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE)
+# undef BOOST_OS_UNIX
+# define BOOST_OS_UNIX BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_OS_UNIX
+# define BOOST_OS_UNIX_AVAILABLE
+#endif
+
+#define BOOST_OS_UNIX_NAME "Unix Environment"
+
+/*`
+[heading `BOOST_OS_SVR4`]
+
+[@http://en.wikipedia.org/wiki/UNIX_System_V SVR4 Environment] operating system.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__sysv__`] [__predef_detection__]]
+ [[`__SVR4`] [__predef_detection__]]
+ [[`__svr4__`] [__predef_detection__]]
+ [[`_SYSTYPE_SVR4`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_OS_SVR4 BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__sysv__) || defined(__SVR4) || \
+ defined(__svr4__) || defined(_SYSTYPE_SVR4)
+# undef BOOST_OS_SVR4
+# define BOOST_OS_SVR4 BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_OS_SVR4
+# define BOOST_OS_SVR4_AVAILABLE
+#endif
+
+#define BOOST_OS_SVR4_NAME "SVR4 Environment"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_OS_UNIX,BOOST_OS_UNIX_NAME)
+BOOST_PREDEF_DECLARE_TEST(BOOST_OS_SVR4,BOOST_OS_SVR4_NAME)
diff --git a/third_party/boost/boost/predef/os/vms.h b/third_party/boost/boost/predef/os/vms.h
new file mode 100644
index 0000000..2f8f786
--- /dev/null
+++ b/third_party/boost/boost/predef/os/vms.h
@@ -0,0 +1,52 @@
+/*
+Copyright Rene Rivera 2011-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_OS_VMS_H
+#define BOOST_PREDEF_OS_VMS_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_OS_VMS`]
+
+[@http://en.wikipedia.org/wiki/Vms VMS] operating system.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`VMS`] [__predef_detection__]]
+ [[`__VMS`] [__predef_detection__]]
+
+ [[`__VMS_VER`] [V.R.P]]
+ ]
+ */
+
+#define BOOST_OS_VMS BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \
+ defined(VMS) || defined(__VMS) \
+ )
+# undef BOOST_OS_VMS
+# if defined(__VMS_VER)
+# define BOOST_OS_VMS BOOST_PREDEF_MAKE_10_VVRR00PP00(__VMS_VER)
+# else
+# define BOOST_OS_VMS BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#if BOOST_OS_VMS
+# define BOOST_OS_VMS_AVAILABLE
+# include <boost/predef/detail/os_detected.h>
+#endif
+
+#define BOOST_OS_VMS_NAME "VMS"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_OS_VMS,BOOST_OS_VMS_NAME)
diff --git a/third_party/boost/boost/predef/os/windows.h b/third_party/boost/boost/predef/os/windows.h
new file mode 100644
index 0000000..9db4390
--- /dev/null
+++ b/third_party/boost/boost/predef/os/windows.h
@@ -0,0 +1,51 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_OS_WINDOWS_H
+#define BOOST_PREDEF_OS_WINDOWS_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_OS_WINDOWS`]
+
+[@http://en.wikipedia.org/wiki/Category:Microsoft_Windows Microsoft Windows] operating system.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`_WIN32`] [__predef_detection__]]
+ [[`_WIN64`] [__predef_detection__]]
+ [[`__WIN32__`] [__predef_detection__]]
+ [[`__TOS_WIN__`] [__predef_detection__]]
+ [[`__WINDOWS__`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_OS_WINDOWS BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if !defined(BOOST_PREDEF_DETAIL_OS_DETECTED) && ( \
+ defined(_WIN32) || defined(_WIN64) || \
+ defined(__WIN32__) || defined(__TOS_WIN__) || \
+ defined(__WINDOWS__) \
+ )
+# undef BOOST_OS_WINDOWS
+# define BOOST_OS_WINDOWS BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_OS_WINDOWS
+# define BOOST_OS_WINDOWS_AVAILABLE
+# include <boost/predef/detail/os_detected.h>
+#endif
+
+#define BOOST_OS_WINDOWS_NAME "Microsoft Windows"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_OS_WINDOWS,BOOST_OS_WINDOWS_NAME)
diff --git a/third_party/boost/boost/predef/other.h b/third_party/boost/boost/predef/other.h
new file mode 100644
index 0000000..c09ad49
--- /dev/null
+++ b/third_party/boost/boost/predef/other.h
@@ -0,0 +1,16 @@
+/*
+Copyright Rene Rivera 2013-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#if !defined(BOOST_PREDEF_OTHER_H) || defined(BOOST_PREDEF_INTERNAL_GENERATE_TESTS)
+#ifndef BOOST_PREDEF_OTHER_H
+#define BOOST_PREDEF_OTHER_H
+#endif
+
+#include <boost/predef/other/endian.h>
+/*#include <boost/predef/other/.h>*/
+
+#endif
diff --git a/third_party/boost/boost/predef/other/endian.h b/third_party/boost/boost/predef/other/endian.h
new file mode 100644
index 0000000..6d1f43f
--- /dev/null
+++ b/third_party/boost/boost/predef/other/endian.h
@@ -0,0 +1,204 @@
+/*
+Copyright Rene Rivera 2013-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_ENDIAN_H
+#define BOOST_PREDEF_ENDIAN_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+#include <boost/predef/library/c/gnu.h>
+#include <boost/predef/os/macos.h>
+#include <boost/predef/os/bsd.h>
+#include <boost/predef/os/android.h>
+
+/*`
+[heading `BOOST_ENDIAN_*`]
+
+Detection of endian memory ordering. There are four defined macros
+in this header that define the various generally possible endian
+memory orderings:
+
+* `BOOST_ENDIAN_BIG_BYTE`, byte-swapped big-endian.
+* `BOOST_ENDIAN_BIG_WORD`, word-swapped big-endian.
+* `BOOST_ENDIAN_LITTLE_BYTE`, byte-swapped little-endian.
+* `BOOST_ENDIAN_LITTLE_WORD`, word-swapped little-endian.
+
+The detection is conservative in that it only identifies endianness
+that it knows for certain. In particular bi-endianness is not
+indicated as is it not practically possible to determine the
+endianness from anything but an operating system provided
+header. And the currently known headers do not define that
+programatic bi-endianness is available.
+
+This implementation is a compilation of various publicly available
+information and acquired knowledge:
+
+# The indispensable documentation of "Pre-defined Compiler Macros"
+ [@http://sourceforge.net/p/predef/wiki/Endianness Endianness].
+# The various endian specifications available in the
+ [@http://wikipedia.org/ Wikipedia] computer architecture pages.
+# Generally available searches for headers that define endianness.
+ */
+
+#define BOOST_ENDIAN_BIG_BYTE BOOST_VERSION_NUMBER_NOT_AVAILABLE
+#define BOOST_ENDIAN_BIG_WORD BOOST_VERSION_NUMBER_NOT_AVAILABLE
+#define BOOST_ENDIAN_LITTLE_BYTE BOOST_VERSION_NUMBER_NOT_AVAILABLE
+#define BOOST_ENDIAN_LITTLE_WORD BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+/* GNU libc provides a header defining __BYTE_ORDER, or _BYTE_ORDER.
+ * And some OSs provide some for of endian header also.
+ */
+#if !BOOST_ENDIAN_BIG_BYTE && !BOOST_ENDIAN_BIG_WORD && \
+ !BOOST_ENDIAN_LITTLE_BYTE && !BOOST_ENDIAN_LITTLE_WORD
+# if BOOST_LIB_C_GNU || BOOST_OS_ANDROID
+# include <endian.h>
+# else
+# if BOOST_OS_MACOS
+# include <machine/endian.h>
+# else
+# if BOOST_OS_BSD
+# if BOOST_OS_BSD_OPEN
+# include <machine/endian.h>
+# else
+# include <sys/endian.h>
+# endif
+# endif
+# endif
+# endif
+# if defined(__BYTE_ORDER)
+# if defined(__BIG_ENDIAN) && (__BYTE_ORDER == __BIG_ENDIAN)
+# undef BOOST_ENDIAN_BIG_BYTE
+# define BOOST_ENDIAN_BIG_BYTE BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+# if defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN)
+# undef BOOST_ENDIAN_LITTLE_BYTE
+# define BOOST_ENDIAN_LITTLE_BYTE BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+# if defined(__PDP_ENDIAN) && (__BYTE_ORDER == __PDP_ENDIAN)
+# undef BOOST_ENDIAN_LITTLE_WORD
+# define BOOST_ENDIAN_LITTLE_WORD BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+# endif
+# if !defined(__BYTE_ORDER) && defined(_BYTE_ORDER)
+# if defined(_BIG_ENDIAN) && (_BYTE_ORDER == _BIG_ENDIAN)
+# undef BOOST_ENDIAN_BIG_BYTE
+# define BOOST_ENDIAN_BIG_BYTE BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+# if defined(_LITTLE_ENDIAN) && (_BYTE_ORDER == _LITTLE_ENDIAN)
+# undef BOOST_ENDIAN_LITTLE_BYTE
+# define BOOST_ENDIAN_LITTLE_BYTE BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+# if defined(_PDP_ENDIAN) && (_BYTE_ORDER == _PDP_ENDIAN)
+# undef BOOST_ENDIAN_LITTLE_WORD
+# define BOOST_ENDIAN_LITTLE_WORD BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+# endif
+#endif
+
+/* Built-in byte-swpped big-endian macros.
+ */
+#if !BOOST_ENDIAN_BIG_BYTE && !BOOST_ENDIAN_BIG_WORD && \
+ !BOOST_ENDIAN_LITTLE_BYTE && !BOOST_ENDIAN_LITTLE_WORD
+# if (defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)) || \
+ (defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)) || \
+ defined(__ARMEB__) || \
+ defined(__THUMBEB__) || \
+ defined(__AARCH64EB__) || \
+ defined(_MIPSEB) || \
+ defined(__MIPSEB) || \
+ defined(__MIPSEB__)
+# undef BOOST_ENDIAN_BIG_BYTE
+# define BOOST_ENDIAN_BIG_BYTE BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+/* Built-in byte-swpped little-endian macros.
+ */
+#if !BOOST_ENDIAN_BIG_BYTE && !BOOST_ENDIAN_BIG_WORD && \
+ !BOOST_ENDIAN_LITTLE_BYTE && !BOOST_ENDIAN_LITTLE_WORD
+# if (defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \
+ (defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)) || \
+ defined(__ARMEL__) || \
+ defined(__THUMBEL__) || \
+ defined(__AARCH64EL__) || \
+ defined(_MIPSEL) || \
+ defined(__MIPSEL) || \
+ defined(__MIPSEL__)
+# undef BOOST_ENDIAN_LITTLE_BYTE
+# define BOOST_ENDIAN_LITTLE_BYTE BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+/* Some architectures are strictly one endianess (as opposed
+ * the current common bi-endianess).
+ */
+#if !BOOST_ENDIAN_BIG_BYTE && !BOOST_ENDIAN_BIG_WORD && \
+ !BOOST_ENDIAN_LITTLE_BYTE && !BOOST_ENDIAN_LITTLE_WORD
+# include <boost/predef/architecture.h>
+# if BOOST_ARCH_M68K || \
+ BOOST_ARCH_PARISC || \
+ BOOST_ARCH_SPARC || \
+ BOOST_ARCH_SYS370 || \
+ BOOST_ARCH_SYS390 || \
+ BOOST_ARCH_Z
+# undef BOOST_ENDIAN_BIG_BYTE
+# define BOOST_ENDIAN_BIG_BYTE BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+# if BOOST_ARCH_AMD64 || \
+ BOOST_ARCH_IA64 || \
+ BOOST_ARCH_X86 || \
+ BOOST_ARCH_BLACKFIN
+# undef BOOST_ENDIAN_LITTLE_BYTE
+# define BOOST_ENDIAN_LITTLE_BYTE BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+/* Windows on ARM, if not otherwise detected/specified, is always
+ * byte-swaped little-endian.
+ */
+#if !BOOST_ENDIAN_BIG_BYTE && !BOOST_ENDIAN_BIG_WORD && \
+ !BOOST_ENDIAN_LITTLE_BYTE && !BOOST_ENDIAN_LITTLE_WORD
+# if BOOST_ARCH_ARM
+# include <boost/predef/os/windows.h>
+# if BOOST_OS_WINDOWS
+# undef BOOST_ENDIAN_LITTLE_BYTE
+# define BOOST_ENDIAN_LITTLE_BYTE BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+# endif
+#endif
+
+#if BOOST_ENDIAN_BIG_BYTE
+# define BOOST_ENDIAN_BIG_BYTE_AVAILABLE
+#endif
+#if BOOST_ENDIAN_BIG_WORD
+# define BOOST_ENDIAN_BIG_WORD_BYTE_AVAILABLE
+#endif
+#if BOOST_ENDIAN_LITTLE_BYTE
+# define BOOST_ENDIAN_LITTLE_BYTE_AVAILABLE
+#endif
+#if BOOST_ENDIAN_LITTLE_WORD
+# define BOOST_ENDIAN_LITTLE_WORD_BYTE_AVAILABLE
+#endif
+
+#define BOOST_ENDIAN_BIG_BYTE_NAME "Byte-Swapped Big-Endian"
+#define BOOST_ENDIAN_BIG_WORD_NAME "Word-Swapped Big-Endian"
+#define BOOST_ENDIAN_LITTLE_BYTE_NAME "Byte-Swapped Little-Endian"
+#define BOOST_ENDIAN_LITTLE_WORD_NAME "Word-Swapped Little-Endian"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_ENDIAN_BIG_BYTE,BOOST_ENDIAN_BIG_BYTE_NAME)
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_ENDIAN_BIG_WORD,BOOST_ENDIAN_BIG_WORD_NAME)
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_ENDIAN_LITTLE_BYTE,BOOST_ENDIAN_LITTLE_BYTE_NAME)
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_ENDIAN_LITTLE_WORD,BOOST_ENDIAN_LITTLE_WORD_NAME)
diff --git a/third_party/boost/boost/predef/platform.h b/third_party/boost/boost/predef/platform.h
new file mode 100644
index 0000000..c0c8706
--- /dev/null
+++ b/third_party/boost/boost/predef/platform.h
@@ -0,0 +1,21 @@
+/*
+Copyright Rene Rivera 2013-2015
+Copyright (c) Microsoft Corporation 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)
+*/
+
+#if !defined(BOOST_PREDEF_PLATFORM_H) || defined(BOOST_PREDEF_INTERNAL_GENERATE_TESTS)
+#ifndef BOOST_PREDEF_PLATFORM_H
+#define BOOST_PREDEF_PLATFORM_H
+#endif
+
+#include <boost/predef/platform/mingw.h>
+#include <boost/predef/platform/windows_desktop.h>
+#include <boost/predef/platform/windows_store.h>
+#include <boost/predef/platform/windows_phone.h>
+#include <boost/predef/platform/windows_runtime.h>
+/*#include <boost/predef/platform/.h>*/
+
+#endif
diff --git a/third_party/boost/boost/predef/platform/mingw.h b/third_party/boost/boost/predef/platform/mingw.h
new file mode 100644
index 0000000..64c5837
--- /dev/null
+++ b/third_party/boost/boost/predef/platform/mingw.h
@@ -0,0 +1,69 @@
+/*
+Copyright Rene Rivera 2008-2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_COMPILER_MINGW_H
+#define BOOST_PREDEF_COMPILER_MINGW_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+
+/*`
+[heading `BOOST_PLAT_MINGW`]
+
+[@http://en.wikipedia.org/wiki/MinGW MinGW] platform.
+Version number available as major, minor, and patch.
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`__MINGW32__`] [__predef_detection__]]
+ [[`__MINGW64__`] [__predef_detection__]]
+
+ [[`__MINGW64_VERSION_MAJOR`, `__MINGW64_VERSION_MINOR`] [V.R.0]]
+ [[`__MINGW32_VERSION_MAJOR`, `__MINGW32_VERSION_MINOR`] [V.R.0]]
+ ]
+ */
+
+#define BOOST_PLAT_MINGW BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if defined(__MINGW32__) || defined(__MINGW64__)
+# include <_mingw.h>
+# if !defined(BOOST_PLAT_MINGW_DETECTION) && (defined(__MINGW64_VERSION_MAJOR) && defined(__MINGW64_VERSION_MINOR))
+# define BOOST_PLAT_MINGW_DETECTION \
+ BOOST_VERSION_NUMBER(__MINGW64_VERSION_MAJOR,__MINGW64_VERSION_MINOR,0)
+# endif
+# if !defined(BOOST_PLAT_MINGW_DETECTION) && (defined(__MINGW32_VERSION_MAJOR) && defined(__MINGW32_VERSION_MINOR))
+# define BOOST_PLAT_MINGW_DETECTION \
+ BOOST_VERSION_NUMBER(__MINGW32_MAJOR_VERSION,__MINGW32_MINOR_VERSION,0)
+# endif
+# if !defined(BOOST_PLAT_MINGW_DETECTION)
+# define BOOST_PLAT_MINGW_DETECTION BOOST_VERSION_NUMBER_AVAILABLE
+# endif
+#endif
+
+#ifdef BOOST_PLAT_MINGW_DETECTION
+# define BOOST_PLAT_MINGW_AVAILABLE
+# if defined(BOOST_PREDEF_DETAIL_PLAT_DETECTED)
+# define BOOST_PLAT_MINGW_EMULATED BOOST_PLAT_MINGW_DETECTION
+# else
+# undef BOOST_PLAT_MINGW
+# define BOOST_PLAT_MINGW BOOST_PLAT_MINGW_DETECTION
+# endif
+# include <boost/predef/detail/platform_detected.h>
+#endif
+
+#define BOOST_PLAT_MINGW_NAME "MinGW"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_PLAT_MINGW,BOOST_PLAT_MINGW_NAME)
+
+#ifdef BOOST_PLAT_MINGW_EMULATED
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_PLAT_MINGW_EMULATED,BOOST_PLAT_MINGW_NAME)
+#endif
diff --git a/third_party/boost/boost/predef/platform/windows_desktop.h b/third_party/boost/boost/predef/platform/windows_desktop.h
new file mode 100644
index 0000000..41485e9
--- /dev/null
+++ b/third_party/boost/boost/predef/platform/windows_desktop.h
@@ -0,0 +1,45 @@
+/*
+Copyright (c) Microsoft Corporation 2014
+Copyright Rene Rivera 2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_PLAT_WINDOWS_DESKTOP_H
+#define BOOST_PREDEF_PLAT_WINDOWS_DESKTOP_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+#include <boost/predef/os/windows.h>
+
+/*`
+[heading `BOOST_PLAT_WINDOWS_DESKTOP`]
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`!WINAPI_FAMILY`] [__predef_detection__]]
+ [[`WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_PLAT_WINDOWS_DESKTOP BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if BOOST_OS_WINDOWS && \
+ ( !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP) )
+# undef BOOST_PLAT_WINDOWS_DESKTOP
+# define BOOST_PLAT_WINDOWS_DESKTOP BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_PLAT_WINDOWS_DESKTOP
+# define BOOST_PLAT_WINDOWS_DESKTOP_AVAILABLE
+# include <boost/predef/detail/platform_detected.h>
+#endif
+
+#define BOOST_PLAT_WINDOWS_DESKTOP_NAME "Windows Desktop"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_PLAT_WINDOWS_DESKTOP,BOOST_PLAT_WINDOWS_DESKTOP_NAME)
diff --git a/third_party/boost/boost/predef/platform/windows_phone.h b/third_party/boost/boost/predef/platform/windows_phone.h
new file mode 100644
index 0000000..5ed6410
--- /dev/null
+++ b/third_party/boost/boost/predef/platform/windows_phone.h
@@ -0,0 +1,43 @@
+/*
+Copyright (c) Microsoft Corporation 2014
+Copyright Rene Rivera 2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_PLAT_WINDOWS_PHONE_H
+#define BOOST_PREDEF_PLAT_WINDOWS_PHONE_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+#include <boost/predef/os/windows.h>
+
+/*`
+[heading `BOOST_PLAT_WINDOWS_PHONE`]
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_PLAT_WINDOWS_PHONE BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if BOOST_OS_WINDOWS && defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
+# undef BOOST_PLAT_WINDOWS_PHONE
+# define BOOST_PLAT_WINDOWS_PHONE BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_PLAT_WINDOWS_PHONE
+# define BOOST_PLAT_WINDOWS_PHONE_AVAILABLE
+# include <boost/predef/detail/platform_detected.h>
+#endif
+
+#define BOOST_PLAT_WINDOWS_PHONE_NAME "Windows Phone"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_PLAT_WINDOWS_PHONE,BOOST_PLAT_WINDOWS_PHONE_NAME)
diff --git a/third_party/boost/boost/predef/platform/windows_runtime.h b/third_party/boost/boost/predef/platform/windows_runtime.h
new file mode 100644
index 0000000..bffab75
--- /dev/null
+++ b/third_party/boost/boost/predef/platform/windows_runtime.h
@@ -0,0 +1,45 @@
+/*
+Copyright (c) Microsoft Corporation 2014
+Copyright Rene Rivera 2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_PLAT_WINDOWS_RUNTIME_H
+#define BOOST_PREDEF_PLAT_WINDOWS_RUNTIME_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+#include <boost/predef/os/windows.h>
+
+/*`
+[heading `BOOST_PLAT_WINDOWS_RUNTIME`]
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`WINAPI_FAMILY == WINAPI_FAMILY_APP`] [__predef_detection__]]
+ [[`WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_PLAT_WINDOWS_RUNTIME BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if BOOST_OS_WINDOWS && defined(WINAPI_FAMILY) && \
+ ( WINAPI_FAMILY == WINAPI_FAMILY_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP )
+# undef BOOST_PLAT_WINDOWS_RUNTIME
+# define BOOST_PLAT_WINDOWS_RUNTIME BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_PLAT_WINDOWS_RUNTIME
+# define BOOST_PLAT_WINDOWS_RUNTIME_AVAILABLE
+# include <boost/predef/detail/platform_detected.h>
+#endif
+
+#define BOOST_PLAT_WINDOWS_RUNTIME_NAME "Windows Runtime"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_PLAT_WINDOWS_RUNTIME,BOOST_PLAT_WINDOWS_RUNTIME_NAME)
diff --git a/third_party/boost/boost/predef/platform/windows_store.h b/third_party/boost/boost/predef/platform/windows_store.h
new file mode 100644
index 0000000..86e7116
--- /dev/null
+++ b/third_party/boost/boost/predef/platform/windows_store.h
@@ -0,0 +1,43 @@
+/*
+Copyright (c) Microsoft Corporation 2014
+Copyright Rene Rivera 2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_PLAT_WINDOWS_STORE_H
+#define BOOST_PREDEF_PLAT_WINDOWS_STORE_H
+
+#include <boost/predef/version_number.h>
+#include <boost/predef/make.h>
+#include <boost/predef/os/windows.h>
+
+/*`
+[heading `BOOST_PLAT_WINDOWS_STORE`]
+
+[table
+ [[__predef_symbol__] [__predef_version__]]
+
+ [[`WINAPI_FAMILY == WINAPI_FAMILY_APP`] [__predef_detection__]]
+ ]
+ */
+
+#define BOOST_PLAT_WINDOWS_STORE BOOST_VERSION_NUMBER_NOT_AVAILABLE
+
+#if BOOST_OS_WINDOWS && defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_APP
+# undef BOOST_PLAT_WINDOWS_STORE
+# define BOOST_PLAT_WINDOWS_STORE BOOST_VERSION_NUMBER_AVAILABLE
+#endif
+
+#if BOOST_PLAT_WINDOWS_STORE
+# define BOOST_PLAT_WINDOWS_STORE_AVAILABLE
+# include <boost/predef/detail/platform_detected.h>
+#endif
+
+#define BOOST_PLAT_WINDOWS_STORE_NAME "Windows Store"
+
+#endif
+
+#include <boost/predef/detail/test.h>
+BOOST_PREDEF_DECLARE_TEST(BOOST_PLAT_WINDOWS_STORE,BOOST_PLAT_WINDOWS_STORE_NAME)
diff --git a/third_party/boost/boost/predef/version.h b/third_party/boost/boost/predef/version.h
new file mode 100644
index 0000000..2fcdefa
--- /dev/null
+++ b/third_party/boost/boost/predef/version.h
@@ -0,0 +1,15 @@
+/*
+Copyright Rene Rivera 2015
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_VERSION_H
+#define BOOST_PREDEF_VERSION_H
+
+#include <boost/predef/version_number.h>
+
+#define BOOST_PREDEF_VERSION BOOST_VERSION_NUMBER(1,4,0)
+
+#endif
diff --git a/third_party/boost/boost/predef/version_number.h b/third_party/boost/boost/predef/version_number.h
new file mode 100644
index 0000000..3903a36
--- /dev/null
+++ b/third_party/boost/boost/predef/version_number.h
@@ -0,0 +1,53 @@
+/*
+Copyright Rene Rivera 2005, 2008-2013
+Distributed under the Boost Software License, Version 1.0.
+(See accompanying file LICENSE_1_0.txt or copy at
+http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+#ifndef BOOST_PREDEF_VERSION_NUMBER_H
+#define BOOST_PREDEF_VERSION_NUMBER_H
+
+/*`
+[heading `BOOST_VERSION_NUMBER`]
+
+``
+BOOST_VERSION_NUMBER(major,minor,patch)
+``
+
+Defines standard version numbers, with these properties:
+
+* Decimal base whole numbers in the range \[0,1000000000).
+ The number range is designed to allow for a (2,2,5) triplet.
+ Which fits within a 32 bit value.
+* The `major` number can be in the \[0,99\] range.
+* The `minor` number can be in the \[0,99\] range.
+* The `patch` number can be in the \[0,99999\] range.
+* Values can be specified in any base. As the defined value
+ is an constant expression.
+* Value can be directly used in both preprocessor and compiler
+ expressions for comparison to other similarly defined values.
+* The implementation enforces the individual ranges for the
+ major, minor, and patch numbers. And values over the ranges
+ are truncated (modulo).
+
+*/
+#define BOOST_VERSION_NUMBER(major,minor,patch) \
+ ( (((major)%100)*10000000) + (((minor)%100)*100000) + ((patch)%100000) )
+
+#define BOOST_VERSION_NUMBER_MAX \
+ BOOST_VERSION_NUMBER(99,99,99999)
+
+#define BOOST_VERSION_NUMBER_ZERO \
+ BOOST_VERSION_NUMBER(0,0,0)
+
+#define BOOST_VERSION_NUMBER_MIN \
+ BOOST_VERSION_NUMBER(0,0,1)
+
+#define BOOST_VERSION_NUMBER_AVAILABLE \
+ BOOST_VERSION_NUMBER_MIN
+
+#define BOOST_VERSION_NUMBER_NOT_AVAILABLE \
+ BOOST_VERSION_NUMBER_ZERO
+
+#endif
diff --git a/third_party/boost/boost/preprocessor/arithmetic.hpp b/third_party/boost/boost/preprocessor/arithmetic.hpp
new file mode 100644
index 0000000..b1be781
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/arithmetic.hpp
@@ -0,0 +1,25 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_ARITHMETIC_HPP
+# define BOOST_PREPROCESSOR_ARITHMETIC_HPP
+#
+# include <boost/preprocessor/arithmetic/add.hpp>
+# include <boost/preprocessor/arithmetic/dec.hpp>
+# include <boost/preprocessor/arithmetic/div.hpp>
+# include <boost/preprocessor/arithmetic/inc.hpp>
+# include <boost/preprocessor/arithmetic/mod.hpp>
+# include <boost/preprocessor/arithmetic/mul.hpp>
+# include <boost/preprocessor/arithmetic/sub.hpp>
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/arithmetic/add.hpp b/third_party/boost/boost/preprocessor/arithmetic/add.hpp
new file mode 100644
index 0000000..5a29f55
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/arithmetic/add.hpp
@@ -0,0 +1,51 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_ARITHMETIC_ADD_HPP
+# define BOOST_PREPROCESSOR_ARITHMETIC_ADD_HPP
+#
+# include <boost/preprocessor/arithmetic/dec.hpp>
+# include <boost/preprocessor/arithmetic/inc.hpp>
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/control/while.hpp>
+# include <boost/preprocessor/tuple/elem.hpp>
+#
+# /* BOOST_PP_ADD */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_ADD(x, y) BOOST_PP_TUPLE_ELEM(2, 0, BOOST_PP_WHILE(BOOST_PP_ADD_P, BOOST_PP_ADD_O, (x, y)))
+# else
+# define BOOST_PP_ADD(x, y) BOOST_PP_ADD_I(x, y)
+# define BOOST_PP_ADD_I(x, y) BOOST_PP_TUPLE_ELEM(2, 0, BOOST_PP_WHILE(BOOST_PP_ADD_P, BOOST_PP_ADD_O, (x, y)))
+# endif
+#
+# define BOOST_PP_ADD_P(d, xy) BOOST_PP_TUPLE_ELEM(2, 1, xy)
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MWCC()
+# define BOOST_PP_ADD_O(d, xy) BOOST_PP_ADD_O_I xy
+# else
+# define BOOST_PP_ADD_O(d, xy) BOOST_PP_ADD_O_I(BOOST_PP_TUPLE_ELEM(2, 0, xy), BOOST_PP_TUPLE_ELEM(2, 1, xy))
+# endif
+#
+# define BOOST_PP_ADD_O_I(x, y) (BOOST_PP_INC(x), BOOST_PP_DEC(y))
+#
+# /* BOOST_PP_ADD_D */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_ADD_D(d, x, y) BOOST_PP_TUPLE_ELEM(2, 0, BOOST_PP_WHILE_ ## d(BOOST_PP_ADD_P, BOOST_PP_ADD_O, (x, y)))
+# else
+# define BOOST_PP_ADD_D(d, x, y) BOOST_PP_ADD_D_I(d, x, y)
+# define BOOST_PP_ADD_D_I(d, x, y) BOOST_PP_TUPLE_ELEM(2, 0, BOOST_PP_WHILE_ ## d(BOOST_PP_ADD_P, BOOST_PP_ADD_O, (x, y)))
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/arithmetic/dec.hpp b/third_party/boost/boost/preprocessor/arithmetic/dec.hpp
new file mode 100644
index 0000000..23dd0a3
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/arithmetic/dec.hpp
@@ -0,0 +1,289 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_ARITHMETIC_DEC_HPP
+# define BOOST_PREPROCESSOR_ARITHMETIC_DEC_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+#
+# /* BOOST_PP_DEC */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MWCC()
+# define BOOST_PP_DEC(x) BOOST_PP_DEC_I(x)
+# else
+# define BOOST_PP_DEC(x) BOOST_PP_DEC_OO((x))
+# define BOOST_PP_DEC_OO(par) BOOST_PP_DEC_I ## par
+# endif
+#
+# define BOOST_PP_DEC_I(x) BOOST_PP_DEC_ ## x
+#
+# define BOOST_PP_DEC_0 0
+# define BOOST_PP_DEC_1 0
+# define BOOST_PP_DEC_2 1
+# define BOOST_PP_DEC_3 2
+# define BOOST_PP_DEC_4 3
+# define BOOST_PP_DEC_5 4
+# define BOOST_PP_DEC_6 5
+# define BOOST_PP_DEC_7 6
+# define BOOST_PP_DEC_8 7
+# define BOOST_PP_DEC_9 8
+# define BOOST_PP_DEC_10 9
+# define BOOST_PP_DEC_11 10
+# define BOOST_PP_DEC_12 11
+# define BOOST_PP_DEC_13 12
+# define BOOST_PP_DEC_14 13
+# define BOOST_PP_DEC_15 14
+# define BOOST_PP_DEC_16 15
+# define BOOST_PP_DEC_17 16
+# define BOOST_PP_DEC_18 17
+# define BOOST_PP_DEC_19 18
+# define BOOST_PP_DEC_20 19
+# define BOOST_PP_DEC_21 20
+# define BOOST_PP_DEC_22 21
+# define BOOST_PP_DEC_23 22
+# define BOOST_PP_DEC_24 23
+# define BOOST_PP_DEC_25 24
+# define BOOST_PP_DEC_26 25
+# define BOOST_PP_DEC_27 26
+# define BOOST_PP_DEC_28 27
+# define BOOST_PP_DEC_29 28
+# define BOOST_PP_DEC_30 29
+# define BOOST_PP_DEC_31 30
+# define BOOST_PP_DEC_32 31
+# define BOOST_PP_DEC_33 32
+# define BOOST_PP_DEC_34 33
+# define BOOST_PP_DEC_35 34
+# define BOOST_PP_DEC_36 35
+# define BOOST_PP_DEC_37 36
+# define BOOST_PP_DEC_38 37
+# define BOOST_PP_DEC_39 38
+# define BOOST_PP_DEC_40 39
+# define BOOST_PP_DEC_41 40
+# define BOOST_PP_DEC_42 41
+# define BOOST_PP_DEC_43 42
+# define BOOST_PP_DEC_44 43
+# define BOOST_PP_DEC_45 44
+# define BOOST_PP_DEC_46 45
+# define BOOST_PP_DEC_47 46
+# define BOOST_PP_DEC_48 47
+# define BOOST_PP_DEC_49 48
+# define BOOST_PP_DEC_50 49
+# define BOOST_PP_DEC_51 50
+# define BOOST_PP_DEC_52 51
+# define BOOST_PP_DEC_53 52
+# define BOOST_PP_DEC_54 53
+# define BOOST_PP_DEC_55 54
+# define BOOST_PP_DEC_56 55
+# define BOOST_PP_DEC_57 56
+# define BOOST_PP_DEC_58 57
+# define BOOST_PP_DEC_59 58
+# define BOOST_PP_DEC_60 59
+# define BOOST_PP_DEC_61 60
+# define BOOST_PP_DEC_62 61
+# define BOOST_PP_DEC_63 62
+# define BOOST_PP_DEC_64 63
+# define BOOST_PP_DEC_65 64
+# define BOOST_PP_DEC_66 65
+# define BOOST_PP_DEC_67 66
+# define BOOST_PP_DEC_68 67
+# define BOOST_PP_DEC_69 68
+# define BOOST_PP_DEC_70 69
+# define BOOST_PP_DEC_71 70
+# define BOOST_PP_DEC_72 71
+# define BOOST_PP_DEC_73 72
+# define BOOST_PP_DEC_74 73
+# define BOOST_PP_DEC_75 74
+# define BOOST_PP_DEC_76 75
+# define BOOST_PP_DEC_77 76
+# define BOOST_PP_DEC_78 77
+# define BOOST_PP_DEC_79 78
+# define BOOST_PP_DEC_80 79
+# define BOOST_PP_DEC_81 80
+# define BOOST_PP_DEC_82 81
+# define BOOST_PP_DEC_83 82
+# define BOOST_PP_DEC_84 83
+# define BOOST_PP_DEC_85 84
+# define BOOST_PP_DEC_86 85
+# define BOOST_PP_DEC_87 86
+# define BOOST_PP_DEC_88 87
+# define BOOST_PP_DEC_89 88
+# define BOOST_PP_DEC_90 89
+# define BOOST_PP_DEC_91 90
+# define BOOST_PP_DEC_92 91
+# define BOOST_PP_DEC_93 92
+# define BOOST_PP_DEC_94 93
+# define BOOST_PP_DEC_95 94
+# define BOOST_PP_DEC_96 95
+# define BOOST_PP_DEC_97 96
+# define BOOST_PP_DEC_98 97
+# define BOOST_PP_DEC_99 98
+# define BOOST_PP_DEC_100 99
+# define BOOST_PP_DEC_101 100
+# define BOOST_PP_DEC_102 101
+# define BOOST_PP_DEC_103 102
+# define BOOST_PP_DEC_104 103
+# define BOOST_PP_DEC_105 104
+# define BOOST_PP_DEC_106 105
+# define BOOST_PP_DEC_107 106
+# define BOOST_PP_DEC_108 107
+# define BOOST_PP_DEC_109 108
+# define BOOST_PP_DEC_110 109
+# define BOOST_PP_DEC_111 110
+# define BOOST_PP_DEC_112 111
+# define BOOST_PP_DEC_113 112
+# define BOOST_PP_DEC_114 113
+# define BOOST_PP_DEC_115 114
+# define BOOST_PP_DEC_116 115
+# define BOOST_PP_DEC_117 116
+# define BOOST_PP_DEC_118 117
+# define BOOST_PP_DEC_119 118
+# define BOOST_PP_DEC_120 119
+# define BOOST_PP_DEC_121 120
+# define BOOST_PP_DEC_122 121
+# define BOOST_PP_DEC_123 122
+# define BOOST_PP_DEC_124 123
+# define BOOST_PP_DEC_125 124
+# define BOOST_PP_DEC_126 125
+# define BOOST_PP_DEC_127 126
+# define BOOST_PP_DEC_128 127
+# define BOOST_PP_DEC_129 128
+# define BOOST_PP_DEC_130 129
+# define BOOST_PP_DEC_131 130
+# define BOOST_PP_DEC_132 131
+# define BOOST_PP_DEC_133 132
+# define BOOST_PP_DEC_134 133
+# define BOOST_PP_DEC_135 134
+# define BOOST_PP_DEC_136 135
+# define BOOST_PP_DEC_137 136
+# define BOOST_PP_DEC_138 137
+# define BOOST_PP_DEC_139 138
+# define BOOST_PP_DEC_140 139
+# define BOOST_PP_DEC_141 140
+# define BOOST_PP_DEC_142 141
+# define BOOST_PP_DEC_143 142
+# define BOOST_PP_DEC_144 143
+# define BOOST_PP_DEC_145 144
+# define BOOST_PP_DEC_146 145
+# define BOOST_PP_DEC_147 146
+# define BOOST_PP_DEC_148 147
+# define BOOST_PP_DEC_149 148
+# define BOOST_PP_DEC_150 149
+# define BOOST_PP_DEC_151 150
+# define BOOST_PP_DEC_152 151
+# define BOOST_PP_DEC_153 152
+# define BOOST_PP_DEC_154 153
+# define BOOST_PP_DEC_155 154
+# define BOOST_PP_DEC_156 155
+# define BOOST_PP_DEC_157 156
+# define BOOST_PP_DEC_158 157
+# define BOOST_PP_DEC_159 158
+# define BOOST_PP_DEC_160 159
+# define BOOST_PP_DEC_161 160
+# define BOOST_PP_DEC_162 161
+# define BOOST_PP_DEC_163 162
+# define BOOST_PP_DEC_164 163
+# define BOOST_PP_DEC_165 164
+# define BOOST_PP_DEC_166 165
+# define BOOST_PP_DEC_167 166
+# define BOOST_PP_DEC_168 167
+# define BOOST_PP_DEC_169 168
+# define BOOST_PP_DEC_170 169
+# define BOOST_PP_DEC_171 170
+# define BOOST_PP_DEC_172 171
+# define BOOST_PP_DEC_173 172
+# define BOOST_PP_DEC_174 173
+# define BOOST_PP_DEC_175 174
+# define BOOST_PP_DEC_176 175
+# define BOOST_PP_DEC_177 176
+# define BOOST_PP_DEC_178 177
+# define BOOST_PP_DEC_179 178
+# define BOOST_PP_DEC_180 179
+# define BOOST_PP_DEC_181 180
+# define BOOST_PP_DEC_182 181
+# define BOOST_PP_DEC_183 182
+# define BOOST_PP_DEC_184 183
+# define BOOST_PP_DEC_185 184
+# define BOOST_PP_DEC_186 185
+# define BOOST_PP_DEC_187 186
+# define BOOST_PP_DEC_188 187
+# define BOOST_PP_DEC_189 188
+# define BOOST_PP_DEC_190 189
+# define BOOST_PP_DEC_191 190
+# define BOOST_PP_DEC_192 191
+# define BOOST_PP_DEC_193 192
+# define BOOST_PP_DEC_194 193
+# define BOOST_PP_DEC_195 194
+# define BOOST_PP_DEC_196 195
+# define BOOST_PP_DEC_197 196
+# define BOOST_PP_DEC_198 197
+# define BOOST_PP_DEC_199 198
+# define BOOST_PP_DEC_200 199
+# define BOOST_PP_DEC_201 200
+# define BOOST_PP_DEC_202 201
+# define BOOST_PP_DEC_203 202
+# define BOOST_PP_DEC_204 203
+# define BOOST_PP_DEC_205 204
+# define BOOST_PP_DEC_206 205
+# define BOOST_PP_DEC_207 206
+# define BOOST_PP_DEC_208 207
+# define BOOST_PP_DEC_209 208
+# define BOOST_PP_DEC_210 209
+# define BOOST_PP_DEC_211 210
+# define BOOST_PP_DEC_212 211
+# define BOOST_PP_DEC_213 212
+# define BOOST_PP_DEC_214 213
+# define BOOST_PP_DEC_215 214
+# define BOOST_PP_DEC_216 215
+# define BOOST_PP_DEC_217 216
+# define BOOST_PP_DEC_218 217
+# define BOOST_PP_DEC_219 218
+# define BOOST_PP_DEC_220 219
+# define BOOST_PP_DEC_221 220
+# define BOOST_PP_DEC_222 221
+# define BOOST_PP_DEC_223 222
+# define BOOST_PP_DEC_224 223
+# define BOOST_PP_DEC_225 224
+# define BOOST_PP_DEC_226 225
+# define BOOST_PP_DEC_227 226
+# define BOOST_PP_DEC_228 227
+# define BOOST_PP_DEC_229 228
+# define BOOST_PP_DEC_230 229
+# define BOOST_PP_DEC_231 230
+# define BOOST_PP_DEC_232 231
+# define BOOST_PP_DEC_233 232
+# define BOOST_PP_DEC_234 233
+# define BOOST_PP_DEC_235 234
+# define BOOST_PP_DEC_236 235
+# define BOOST_PP_DEC_237 236
+# define BOOST_PP_DEC_238 237
+# define BOOST_PP_DEC_239 238
+# define BOOST_PP_DEC_240 239
+# define BOOST_PP_DEC_241 240
+# define BOOST_PP_DEC_242 241
+# define BOOST_PP_DEC_243 242
+# define BOOST_PP_DEC_244 243
+# define BOOST_PP_DEC_245 244
+# define BOOST_PP_DEC_246 245
+# define BOOST_PP_DEC_247 246
+# define BOOST_PP_DEC_248 247
+# define BOOST_PP_DEC_249 248
+# define BOOST_PP_DEC_250 249
+# define BOOST_PP_DEC_251 250
+# define BOOST_PP_DEC_252 251
+# define BOOST_PP_DEC_253 252
+# define BOOST_PP_DEC_254 253
+# define BOOST_PP_DEC_255 254
+# define BOOST_PP_DEC_256 255
+# define BOOST_PP_DEC_257 256
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/arithmetic/detail/div_base.hpp b/third_party/boost/boost/preprocessor/arithmetic/detail/div_base.hpp
new file mode 100644
index 0000000..106632a
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/arithmetic/detail/div_base.hpp
@@ -0,0 +1,61 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_ARITHMETIC_DETAIL_DIV_BASE_HPP
+# define BOOST_PREPROCESSOR_ARITHMETIC_DETAIL_DIV_BASE_HPP
+#
+# include <boost/preprocessor/arithmetic/inc.hpp>
+# include <boost/preprocessor/arithmetic/sub.hpp>
+# include <boost/preprocessor/comparison/less_equal.hpp>
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/control/while.hpp>
+# include <boost/preprocessor/tuple/elem.hpp>
+# include <boost/preprocessor/tuple/rem.hpp>
+#
+# /* BOOST_PP_DIV_BASE */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_DIV_BASE(x, y) BOOST_PP_WHILE(BOOST_PP_DIV_BASE_P, BOOST_PP_DIV_BASE_O, (0, x, y))
+# else
+# define BOOST_PP_DIV_BASE(x, y) BOOST_PP_DIV_BASE_I(x, y)
+# define BOOST_PP_DIV_BASE_I(x, y) BOOST_PP_WHILE(BOOST_PP_DIV_BASE_P, BOOST_PP_DIV_BASE_O, (0, x, y))
+# endif
+#
+# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT()
+# define BOOST_PP_DIV_BASE_P(d, rxy) BOOST_PP_DIV_BASE_P_IM(d, BOOST_PP_TUPLE_REM_3 rxy)
+# define BOOST_PP_DIV_BASE_P_IM(d, im) BOOST_PP_DIV_BASE_P_I(d, im)
+# else
+# define BOOST_PP_DIV_BASE_P(d, rxy) BOOST_PP_DIV_BASE_P_I(d, BOOST_PP_TUPLE_ELEM(3, 0, rxy), BOOST_PP_TUPLE_ELEM(3, 1, rxy), BOOST_PP_TUPLE_ELEM(3, 2, rxy))
+# endif
+#
+# define BOOST_PP_DIV_BASE_P_I(d, r, x, y) BOOST_PP_LESS_EQUAL_D(d, y, x)
+#
+# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT()
+# define BOOST_PP_DIV_BASE_O(d, rxy) BOOST_PP_DIV_BASE_O_IM(d, BOOST_PP_TUPLE_REM_3 rxy)
+# define BOOST_PP_DIV_BASE_O_IM(d, im) BOOST_PP_DIV_BASE_O_I(d, im)
+# else
+# define BOOST_PP_DIV_BASE_O(d, rxy) BOOST_PP_DIV_BASE_O_I(d, BOOST_PP_TUPLE_ELEM(3, 0, rxy), BOOST_PP_TUPLE_ELEM(3, 1, rxy), BOOST_PP_TUPLE_ELEM(3, 2, rxy))
+# endif
+#
+# define BOOST_PP_DIV_BASE_O_I(d, r, x, y) (BOOST_PP_INC(r), BOOST_PP_SUB_D(d, x, y), y)
+#
+# /* BOOST_PP_DIV_BASE_D */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_DIV_BASE_D(d, x, y) BOOST_PP_WHILE_ ## d(BOOST_PP_DIV_BASE_P, BOOST_PP_DIV_BASE_O, (0, x, y))
+# else
+# define BOOST_PP_DIV_BASE_D(d, x, y) BOOST_PP_DIV_BASE_D_I(d, x, y)
+# define BOOST_PP_DIV_BASE_D_I(d, x, y) BOOST_PP_WHILE_ ## d(BOOST_PP_DIV_BASE_P, BOOST_PP_DIV_BASE_O, (0, x, y))
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/arithmetic/div.hpp b/third_party/boost/boost/preprocessor/arithmetic/div.hpp
new file mode 100644
index 0000000..277596c
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/arithmetic/div.hpp
@@ -0,0 +1,39 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_ARITHMETIC_DIV_HPP
+# define BOOST_PREPROCESSOR_ARITHMETIC_DIV_HPP
+#
+# include <boost/preprocessor/arithmetic/detail/div_base.hpp>
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/tuple/elem.hpp>
+#
+# /* BOOST_PP_DIV */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_DIV(x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_DIV_BASE(x, y))
+# else
+# define BOOST_PP_DIV(x, y) BOOST_PP_DIV_I(x, y)
+# define BOOST_PP_DIV_I(x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_DIV_BASE(x, y))
+# endif
+#
+# /* BOOST_PP_DIV_D */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_DIV_D(d, x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_DIV_BASE_D(d, x, y))
+# else
+# define BOOST_PP_DIV_D(d, x, y) BOOST_PP_DIV_D_I(d, x, y)
+# define BOOST_PP_DIV_D_I(d, x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_DIV_BASE_D(d, x, y))
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/arithmetic/inc.hpp b/third_party/boost/boost/preprocessor/arithmetic/inc.hpp
new file mode 100644
index 0000000..1597ab8
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/arithmetic/inc.hpp
@@ -0,0 +1,288 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_ARITHMETIC_INC_HPP
+# define BOOST_PREPROCESSOR_ARITHMETIC_INC_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+#
+# /* BOOST_PP_INC */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MWCC()
+# define BOOST_PP_INC(x) BOOST_PP_INC_I(x)
+# else
+# define BOOST_PP_INC(x) BOOST_PP_INC_OO((x))
+# define BOOST_PP_INC_OO(par) BOOST_PP_INC_I ## par
+# endif
+#
+# define BOOST_PP_INC_I(x) BOOST_PP_INC_ ## x
+#
+# define BOOST_PP_INC_0 1
+# define BOOST_PP_INC_1 2
+# define BOOST_PP_INC_2 3
+# define BOOST_PP_INC_3 4
+# define BOOST_PP_INC_4 5
+# define BOOST_PP_INC_5 6
+# define BOOST_PP_INC_6 7
+# define BOOST_PP_INC_7 8
+# define BOOST_PP_INC_8 9
+# define BOOST_PP_INC_9 10
+# define BOOST_PP_INC_10 11
+# define BOOST_PP_INC_11 12
+# define BOOST_PP_INC_12 13
+# define BOOST_PP_INC_13 14
+# define BOOST_PP_INC_14 15
+# define BOOST_PP_INC_15 16
+# define BOOST_PP_INC_16 17
+# define BOOST_PP_INC_17 18
+# define BOOST_PP_INC_18 19
+# define BOOST_PP_INC_19 20
+# define BOOST_PP_INC_20 21
+# define BOOST_PP_INC_21 22
+# define BOOST_PP_INC_22 23
+# define BOOST_PP_INC_23 24
+# define BOOST_PP_INC_24 25
+# define BOOST_PP_INC_25 26
+# define BOOST_PP_INC_26 27
+# define BOOST_PP_INC_27 28
+# define BOOST_PP_INC_28 29
+# define BOOST_PP_INC_29 30
+# define BOOST_PP_INC_30 31
+# define BOOST_PP_INC_31 32
+# define BOOST_PP_INC_32 33
+# define BOOST_PP_INC_33 34
+# define BOOST_PP_INC_34 35
+# define BOOST_PP_INC_35 36
+# define BOOST_PP_INC_36 37
+# define BOOST_PP_INC_37 38
+# define BOOST_PP_INC_38 39
+# define BOOST_PP_INC_39 40
+# define BOOST_PP_INC_40 41
+# define BOOST_PP_INC_41 42
+# define BOOST_PP_INC_42 43
+# define BOOST_PP_INC_43 44
+# define BOOST_PP_INC_44 45
+# define BOOST_PP_INC_45 46
+# define BOOST_PP_INC_46 47
+# define BOOST_PP_INC_47 48
+# define BOOST_PP_INC_48 49
+# define BOOST_PP_INC_49 50
+# define BOOST_PP_INC_50 51
+# define BOOST_PP_INC_51 52
+# define BOOST_PP_INC_52 53
+# define BOOST_PP_INC_53 54
+# define BOOST_PP_INC_54 55
+# define BOOST_PP_INC_55 56
+# define BOOST_PP_INC_56 57
+# define BOOST_PP_INC_57 58
+# define BOOST_PP_INC_58 59
+# define BOOST_PP_INC_59 60
+# define BOOST_PP_INC_60 61
+# define BOOST_PP_INC_61 62
+# define BOOST_PP_INC_62 63
+# define BOOST_PP_INC_63 64
+# define BOOST_PP_INC_64 65
+# define BOOST_PP_INC_65 66
+# define BOOST_PP_INC_66 67
+# define BOOST_PP_INC_67 68
+# define BOOST_PP_INC_68 69
+# define BOOST_PP_INC_69 70
+# define BOOST_PP_INC_70 71
+# define BOOST_PP_INC_71 72
+# define BOOST_PP_INC_72 73
+# define BOOST_PP_INC_73 74
+# define BOOST_PP_INC_74 75
+# define BOOST_PP_INC_75 76
+# define BOOST_PP_INC_76 77
+# define BOOST_PP_INC_77 78
+# define BOOST_PP_INC_78 79
+# define BOOST_PP_INC_79 80
+# define BOOST_PP_INC_80 81
+# define BOOST_PP_INC_81 82
+# define BOOST_PP_INC_82 83
+# define BOOST_PP_INC_83 84
+# define BOOST_PP_INC_84 85
+# define BOOST_PP_INC_85 86
+# define BOOST_PP_INC_86 87
+# define BOOST_PP_INC_87 88
+# define BOOST_PP_INC_88 89
+# define BOOST_PP_INC_89 90
+# define BOOST_PP_INC_90 91
+# define BOOST_PP_INC_91 92
+# define BOOST_PP_INC_92 93
+# define BOOST_PP_INC_93 94
+# define BOOST_PP_INC_94 95
+# define BOOST_PP_INC_95 96
+# define BOOST_PP_INC_96 97
+# define BOOST_PP_INC_97 98
+# define BOOST_PP_INC_98 99
+# define BOOST_PP_INC_99 100
+# define BOOST_PP_INC_100 101
+# define BOOST_PP_INC_101 102
+# define BOOST_PP_INC_102 103
+# define BOOST_PP_INC_103 104
+# define BOOST_PP_INC_104 105
+# define BOOST_PP_INC_105 106
+# define BOOST_PP_INC_106 107
+# define BOOST_PP_INC_107 108
+# define BOOST_PP_INC_108 109
+# define BOOST_PP_INC_109 110
+# define BOOST_PP_INC_110 111
+# define BOOST_PP_INC_111 112
+# define BOOST_PP_INC_112 113
+# define BOOST_PP_INC_113 114
+# define BOOST_PP_INC_114 115
+# define BOOST_PP_INC_115 116
+# define BOOST_PP_INC_116 117
+# define BOOST_PP_INC_117 118
+# define BOOST_PP_INC_118 119
+# define BOOST_PP_INC_119 120
+# define BOOST_PP_INC_120 121
+# define BOOST_PP_INC_121 122
+# define BOOST_PP_INC_122 123
+# define BOOST_PP_INC_123 124
+# define BOOST_PP_INC_124 125
+# define BOOST_PP_INC_125 126
+# define BOOST_PP_INC_126 127
+# define BOOST_PP_INC_127 128
+# define BOOST_PP_INC_128 129
+# define BOOST_PP_INC_129 130
+# define BOOST_PP_INC_130 131
+# define BOOST_PP_INC_131 132
+# define BOOST_PP_INC_132 133
+# define BOOST_PP_INC_133 134
+# define BOOST_PP_INC_134 135
+# define BOOST_PP_INC_135 136
+# define BOOST_PP_INC_136 137
+# define BOOST_PP_INC_137 138
+# define BOOST_PP_INC_138 139
+# define BOOST_PP_INC_139 140
+# define BOOST_PP_INC_140 141
+# define BOOST_PP_INC_141 142
+# define BOOST_PP_INC_142 143
+# define BOOST_PP_INC_143 144
+# define BOOST_PP_INC_144 145
+# define BOOST_PP_INC_145 146
+# define BOOST_PP_INC_146 147
+# define BOOST_PP_INC_147 148
+# define BOOST_PP_INC_148 149
+# define BOOST_PP_INC_149 150
+# define BOOST_PP_INC_150 151
+# define BOOST_PP_INC_151 152
+# define BOOST_PP_INC_152 153
+# define BOOST_PP_INC_153 154
+# define BOOST_PP_INC_154 155
+# define BOOST_PP_INC_155 156
+# define BOOST_PP_INC_156 157
+# define BOOST_PP_INC_157 158
+# define BOOST_PP_INC_158 159
+# define BOOST_PP_INC_159 160
+# define BOOST_PP_INC_160 161
+# define BOOST_PP_INC_161 162
+# define BOOST_PP_INC_162 163
+# define BOOST_PP_INC_163 164
+# define BOOST_PP_INC_164 165
+# define BOOST_PP_INC_165 166
+# define BOOST_PP_INC_166 167
+# define BOOST_PP_INC_167 168
+# define BOOST_PP_INC_168 169
+# define BOOST_PP_INC_169 170
+# define BOOST_PP_INC_170 171
+# define BOOST_PP_INC_171 172
+# define BOOST_PP_INC_172 173
+# define BOOST_PP_INC_173 174
+# define BOOST_PP_INC_174 175
+# define BOOST_PP_INC_175 176
+# define BOOST_PP_INC_176 177
+# define BOOST_PP_INC_177 178
+# define BOOST_PP_INC_178 179
+# define BOOST_PP_INC_179 180
+# define BOOST_PP_INC_180 181
+# define BOOST_PP_INC_181 182
+# define BOOST_PP_INC_182 183
+# define BOOST_PP_INC_183 184
+# define BOOST_PP_INC_184 185
+# define BOOST_PP_INC_185 186
+# define BOOST_PP_INC_186 187
+# define BOOST_PP_INC_187 188
+# define BOOST_PP_INC_188 189
+# define BOOST_PP_INC_189 190
+# define BOOST_PP_INC_190 191
+# define BOOST_PP_INC_191 192
+# define BOOST_PP_INC_192 193
+# define BOOST_PP_INC_193 194
+# define BOOST_PP_INC_194 195
+# define BOOST_PP_INC_195 196
+# define BOOST_PP_INC_196 197
+# define BOOST_PP_INC_197 198
+# define BOOST_PP_INC_198 199
+# define BOOST_PP_INC_199 200
+# define BOOST_PP_INC_200 201
+# define BOOST_PP_INC_201 202
+# define BOOST_PP_INC_202 203
+# define BOOST_PP_INC_203 204
+# define BOOST_PP_INC_204 205
+# define BOOST_PP_INC_205 206
+# define BOOST_PP_INC_206 207
+# define BOOST_PP_INC_207 208
+# define BOOST_PP_INC_208 209
+# define BOOST_PP_INC_209 210
+# define BOOST_PP_INC_210 211
+# define BOOST_PP_INC_211 212
+# define BOOST_PP_INC_212 213
+# define BOOST_PP_INC_213 214
+# define BOOST_PP_INC_214 215
+# define BOOST_PP_INC_215 216
+# define BOOST_PP_INC_216 217
+# define BOOST_PP_INC_217 218
+# define BOOST_PP_INC_218 219
+# define BOOST_PP_INC_219 220
+# define BOOST_PP_INC_220 221
+# define BOOST_PP_INC_221 222
+# define BOOST_PP_INC_222 223
+# define BOOST_PP_INC_223 224
+# define BOOST_PP_INC_224 225
+# define BOOST_PP_INC_225 226
+# define BOOST_PP_INC_226 227
+# define BOOST_PP_INC_227 228
+# define BOOST_PP_INC_228 229
+# define BOOST_PP_INC_229 230
+# define BOOST_PP_INC_230 231
+# define BOOST_PP_INC_231 232
+# define BOOST_PP_INC_232 233
+# define BOOST_PP_INC_233 234
+# define BOOST_PP_INC_234 235
+# define BOOST_PP_INC_235 236
+# define BOOST_PP_INC_236 237
+# define BOOST_PP_INC_237 238
+# define BOOST_PP_INC_238 239
+# define BOOST_PP_INC_239 240
+# define BOOST_PP_INC_240 241
+# define BOOST_PP_INC_241 242
+# define BOOST_PP_INC_242 243
+# define BOOST_PP_INC_243 244
+# define BOOST_PP_INC_244 245
+# define BOOST_PP_INC_245 246
+# define BOOST_PP_INC_246 247
+# define BOOST_PP_INC_247 248
+# define BOOST_PP_INC_248 249
+# define BOOST_PP_INC_249 250
+# define BOOST_PP_INC_250 251
+# define BOOST_PP_INC_251 252
+# define BOOST_PP_INC_252 253
+# define BOOST_PP_INC_253 254
+# define BOOST_PP_INC_254 255
+# define BOOST_PP_INC_255 256
+# define BOOST_PP_INC_256 256
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/arithmetic/mod.hpp b/third_party/boost/boost/preprocessor/arithmetic/mod.hpp
new file mode 100644
index 0000000..62489d1
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/arithmetic/mod.hpp
@@ -0,0 +1,39 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_ARITHMETIC_MOD_HPP
+# define BOOST_PREPROCESSOR_ARITHMETIC_MOD_HPP
+#
+# include <boost/preprocessor/arithmetic/detail/div_base.hpp>
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/tuple/elem.hpp>
+#
+# /* BOOST_PP_MOD */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_MOD(x, y) BOOST_PP_TUPLE_ELEM(3, 1, BOOST_PP_DIV_BASE(x, y))
+# else
+# define BOOST_PP_MOD(x, y) BOOST_PP_MOD_I(x, y)
+# define BOOST_PP_MOD_I(x, y) BOOST_PP_TUPLE_ELEM(3, 1, BOOST_PP_DIV_BASE(x, y))
+# endif
+#
+# /* BOOST_PP_MOD_D */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_MOD_D(d, x, y) BOOST_PP_TUPLE_ELEM(3, 1, BOOST_PP_DIV_BASE_D(d, x, y))
+# else
+# define BOOST_PP_MOD_D(d, x, y) BOOST_PP_MOD_D_I(d, x, y)
+# define BOOST_PP_MOD_D_I(d, x, y) BOOST_PP_TUPLE_ELEM(3, 1, BOOST_PP_DIV_BASE_D(d, x, y))
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/arithmetic/mul.hpp b/third_party/boost/boost/preprocessor/arithmetic/mul.hpp
new file mode 100644
index 0000000..f3d9ffc
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/arithmetic/mul.hpp
@@ -0,0 +1,53 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_ARITHMETIC_MUL_HPP
+# define BOOST_PREPROCESSOR_ARITHMETIC_MUL_HPP
+#
+# include <boost/preprocessor/arithmetic/add.hpp>
+# include <boost/preprocessor/arithmetic/dec.hpp>
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/control/while.hpp>
+# include <boost/preprocessor/tuple/elem.hpp>
+# include <boost/preprocessor/tuple/rem.hpp>
+#
+# /* BOOST_PP_MUL */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_MUL(x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_WHILE(BOOST_PP_MUL_P, BOOST_PP_MUL_O, (0, x, y)))
+# else
+# define BOOST_PP_MUL(x, y) BOOST_PP_MUL_I(x, y)
+# define BOOST_PP_MUL_I(x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_WHILE(BOOST_PP_MUL_P, BOOST_PP_MUL_O, (0, x, y)))
+# endif
+#
+# define BOOST_PP_MUL_P(d, rxy) BOOST_PP_TUPLE_ELEM(3, 2, rxy)
+#
+# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT()
+# define BOOST_PP_MUL_O(d, rxy) BOOST_PP_MUL_O_IM(d, BOOST_PP_TUPLE_REM_3 rxy)
+# define BOOST_PP_MUL_O_IM(d, im) BOOST_PP_MUL_O_I(d, im)
+# else
+# define BOOST_PP_MUL_O(d, rxy) BOOST_PP_MUL_O_I(d, BOOST_PP_TUPLE_ELEM(3, 0, rxy), BOOST_PP_TUPLE_ELEM(3, 1, rxy), BOOST_PP_TUPLE_ELEM(3, 2, rxy))
+# endif
+#
+# define BOOST_PP_MUL_O_I(d, r, x, y) (BOOST_PP_ADD_D(d, r, x), x, BOOST_PP_DEC(y))
+#
+# /* BOOST_PP_MUL_D */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_MUL_D(d, x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_WHILE_ ## d(BOOST_PP_MUL_P, BOOST_PP_MUL_O, (0, x, y)))
+# else
+# define BOOST_PP_MUL_D(d, x, y) BOOST_PP_MUL_D_I(d, x, y)
+# define BOOST_PP_MUL_D_I(d, x, y) BOOST_PP_TUPLE_ELEM(3, 0, BOOST_PP_WHILE_ ## d(BOOST_PP_MUL_P, BOOST_PP_MUL_O, (0, x, y)))
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/arithmetic/sub.hpp b/third_party/boost/boost/preprocessor/arithmetic/sub.hpp
new file mode 100644
index 0000000..5262cda
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/arithmetic/sub.hpp
@@ -0,0 +1,50 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_ARITHMETIC_SUB_HPP
+# define BOOST_PREPROCESSOR_ARITHMETIC_SUB_HPP
+#
+# include <boost/preprocessor/arithmetic/dec.hpp>
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/control/while.hpp>
+# include <boost/preprocessor/tuple/elem.hpp>
+#
+# /* BOOST_PP_SUB */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_SUB(x, y) BOOST_PP_TUPLE_ELEM(2, 0, BOOST_PP_WHILE(BOOST_PP_SUB_P, BOOST_PP_SUB_O, (x, y)))
+# else
+# define BOOST_PP_SUB(x, y) BOOST_PP_SUB_I(x, y)
+# define BOOST_PP_SUB_I(x, y) BOOST_PP_TUPLE_ELEM(2, 0, BOOST_PP_WHILE(BOOST_PP_SUB_P, BOOST_PP_SUB_O, (x, y)))
+# endif
+#
+# define BOOST_PP_SUB_P(d, xy) BOOST_PP_TUPLE_ELEM(2, 1, xy)
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MWCC()
+# define BOOST_PP_SUB_O(d, xy) BOOST_PP_SUB_O_I xy
+# else
+# define BOOST_PP_SUB_O(d, xy) BOOST_PP_SUB_O_I(BOOST_PP_TUPLE_ELEM(2, 0, xy), BOOST_PP_TUPLE_ELEM(2, 1, xy))
+# endif
+#
+# define BOOST_PP_SUB_O_I(x, y) (BOOST_PP_DEC(x), BOOST_PP_DEC(y))
+#
+# /* BOOST_PP_SUB_D */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_SUB_D(d, x, y) BOOST_PP_TUPLE_ELEM(2, 0, BOOST_PP_WHILE_ ## d(BOOST_PP_SUB_P, BOOST_PP_SUB_O, (x, y)))
+# else
+# define BOOST_PP_SUB_D(d, x, y) BOOST_PP_SUB_D_I(d, x, y)
+# define BOOST_PP_SUB_D_I(d, x, y) BOOST_PP_TUPLE_ELEM(2, 0, BOOST_PP_WHILE_ ## d(BOOST_PP_SUB_P, BOOST_PP_SUB_O, (x, y)))
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/array/data.hpp b/third_party/boost/boost/preprocessor/array/data.hpp
new file mode 100644
index 0000000..10c926a
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/array/data.hpp
@@ -0,0 +1,28 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_ARRAY_DATA_HPP
+# define BOOST_PREPROCESSOR_ARRAY_DATA_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/tuple/elem.hpp>
+#
+# /* BOOST_PP_ARRAY_DATA */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_ARRAY_DATA(array) BOOST_PP_TUPLE_ELEM(2, 1, array)
+# else
+# define BOOST_PP_ARRAY_DATA(array) BOOST_PP_ARRAY_DATA_I(array)
+# define BOOST_PP_ARRAY_DATA_I(array) BOOST_PP_ARRAY_DATA_II array
+# define BOOST_PP_ARRAY_DATA_II(size, data) data
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/array/elem.hpp b/third_party/boost/boost/preprocessor/array/elem.hpp
new file mode 100644
index 0000000..105ba24
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/array/elem.hpp
@@ -0,0 +1,29 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_ARRAY_ELEM_HPP
+# define BOOST_PREPROCESSOR_ARRAY_ELEM_HPP
+#
+# include <boost/preprocessor/array/data.hpp>
+# include <boost/preprocessor/array/size.hpp>
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/tuple/elem.hpp>
+#
+# /* BOOST_PP_ARRAY_ELEM */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_ARRAY_ELEM(i, array) BOOST_PP_TUPLE_ELEM(BOOST_PP_ARRAY_SIZE(array), i, BOOST_PP_ARRAY_DATA(array))
+# else
+# define BOOST_PP_ARRAY_ELEM(i, array) BOOST_PP_ARRAY_ELEM_I(i, array)
+# define BOOST_PP_ARRAY_ELEM_I(i, array) BOOST_PP_TUPLE_ELEM(BOOST_PP_ARRAY_SIZE(array), i, BOOST_PP_ARRAY_DATA(array))
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/array/size.hpp b/third_party/boost/boost/preprocessor/array/size.hpp
new file mode 100644
index 0000000..3f370ee
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/array/size.hpp
@@ -0,0 +1,28 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_ARRAY_SIZE_HPP
+# define BOOST_PREPROCESSOR_ARRAY_SIZE_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/tuple/elem.hpp>
+#
+# /* BOOST_PP_ARRAY_SIZE */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_ARRAY_SIZE(array) BOOST_PP_TUPLE_ELEM(2, 0, array)
+# else
+# define BOOST_PP_ARRAY_SIZE(array) BOOST_PP_ARRAY_SIZE_I(array)
+# define BOOST_PP_ARRAY_SIZE_I(array) BOOST_PP_ARRAY_SIZE_II array
+# define BOOST_PP_ARRAY_SIZE_II(size, data) size
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/cat.hpp b/third_party/boost/boost/preprocessor/cat.hpp
new file mode 100644
index 0000000..5e52850
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/cat.hpp
@@ -0,0 +1,35 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_CAT_HPP
+# define BOOST_PREPROCESSOR_CAT_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+#
+# /* BOOST_PP_CAT */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MWCC()
+# define BOOST_PP_CAT(a, b) BOOST_PP_CAT_I(a, b)
+# else
+# define BOOST_PP_CAT(a, b) BOOST_PP_CAT_OO((a, b))
+# define BOOST_PP_CAT_OO(par) BOOST_PP_CAT_I ## par
+# endif
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MSVC()
+# define BOOST_PP_CAT_I(a, b) a ## b
+# else
+# define BOOST_PP_CAT_I(a, b) BOOST_PP_CAT_II(~, a ## b)
+# define BOOST_PP_CAT_II(p, res) res
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/comma_if.hpp b/third_party/boost/boost/preprocessor/comma_if.hpp
new file mode 100644
index 0000000..9ceb079
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/comma_if.hpp
@@ -0,0 +1,17 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_COMMA_IF_HPP
+# define BOOST_PREPROCESSOR_COMMA_IF_HPP
+#
+# include <boost/preprocessor/punctuation/comma_if.hpp>
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/comparison/less_equal.hpp b/third_party/boost/boost/preprocessor/comparison/less_equal.hpp
new file mode 100644
index 0000000..1302d54
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/comparison/less_equal.hpp
@@ -0,0 +1,39 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_COMPARISON_LESS_EQUAL_HPP
+# define BOOST_PREPROCESSOR_COMPARISON_LESS_EQUAL_HPP
+#
+# include <boost/preprocessor/arithmetic/sub.hpp>
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/logical/not.hpp>
+#
+# /* BOOST_PP_LESS_EQUAL */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_LESS_EQUAL(x, y) BOOST_PP_NOT(BOOST_PP_SUB(x, y))
+# else
+# define BOOST_PP_LESS_EQUAL(x, y) BOOST_PP_LESS_EQUAL_I(x, y)
+# define BOOST_PP_LESS_EQUAL_I(x, y) BOOST_PP_NOT(BOOST_PP_SUB(x, y))
+# endif
+#
+# /* BOOST_PP_LESS_EQUAL_D */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_LESS_EQUAL_D(d, x, y) BOOST_PP_NOT(BOOST_PP_SUB_D(d, x, y))
+# else
+# define BOOST_PP_LESS_EQUAL_D(d, x, y) BOOST_PP_LESS_EQUAL_D_I(d, x, y)
+# define BOOST_PP_LESS_EQUAL_D_I(d, x, y) BOOST_PP_NOT(BOOST_PP_SUB_D(d, x, y))
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/config/config.hpp b/third_party/boost/boost/preprocessor/config/config.hpp
new file mode 100644
index 0000000..835b283
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/config/config.hpp
@@ -0,0 +1,104 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002-2011. *
+# * (C) Copyright Edward Diener 2011. *
+# * Distributed under the Boost Software License, Version 1.0. (See *
+# * accompanying file LICENSE_1_0.txt or copy at *
+# * http://www.boost.org/LICENSE_1_0.txt) *
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_CONFIG_CONFIG_HPP
+# define BOOST_PREPROCESSOR_CONFIG_CONFIG_HPP
+#
+# /* BOOST_PP_CONFIG_FLAGS */
+#
+# define BOOST_PP_CONFIG_STRICT() 0x0001
+# define BOOST_PP_CONFIG_IDEAL() 0x0002
+#
+# define BOOST_PP_CONFIG_MSVC() 0x0004
+# define BOOST_PP_CONFIG_MWCC() 0x0008
+# define BOOST_PP_CONFIG_BCC() 0x0010
+# define BOOST_PP_CONFIG_EDG() 0x0020
+# define BOOST_PP_CONFIG_DMC() 0x0040
+#
+# ifndef BOOST_PP_CONFIG_FLAGS
+# if defined(__GCCXML__)
+# define BOOST_PP_CONFIG_FLAGS() (BOOST_PP_CONFIG_STRICT())
+# elif defined(__WAVE__)
+# define BOOST_PP_CONFIG_FLAGS() (BOOST_PP_CONFIG_STRICT())
+# elif defined(__MWERKS__) && __MWERKS__ >= 0x3200
+# define BOOST_PP_CONFIG_FLAGS() (BOOST_PP_CONFIG_STRICT())
+# elif defined(__EDG__) || defined(__EDG_VERSION__)
+# if defined(_MSC_VER) && (defined(__INTELLISENSE__) || __EDG_VERSION__ >= 308)
+# define BOOST_PP_CONFIG_FLAGS() (BOOST_PP_CONFIG_MSVC())
+# else
+# define BOOST_PP_CONFIG_FLAGS() (BOOST_PP_CONFIG_EDG() | BOOST_PP_CONFIG_STRICT())
+# endif
+# elif defined(__MWERKS__)
+# define BOOST_PP_CONFIG_FLAGS() (BOOST_PP_CONFIG_MWCC())
+# elif defined(__DMC__)
+# define BOOST_PP_CONFIG_FLAGS() (BOOST_PP_CONFIG_DMC())
+# elif defined(__BORLANDC__) && __BORLANDC__ >= 0x581
+# define BOOST_PP_CONFIG_FLAGS() (BOOST_PP_CONFIG_STRICT())
+# elif defined(__BORLANDC__) || defined(__IBMC__) || defined(__IBMCPP__) || defined(__SUNPRO_CC)
+# define BOOST_PP_CONFIG_FLAGS() (BOOST_PP_CONFIG_BCC())
+# elif defined(_MSC_VER) && !defined(__clang__)
+# define BOOST_PP_CONFIG_FLAGS() (BOOST_PP_CONFIG_MSVC())
+# else
+# define BOOST_PP_CONFIG_FLAGS() (BOOST_PP_CONFIG_STRICT())
+# endif
+# endif
+#
+# /* BOOST_PP_CONFIG_EXTENDED_LINE_INFO */
+#
+# ifndef BOOST_PP_CONFIG_EXTENDED_LINE_INFO
+# define BOOST_PP_CONFIG_EXTENDED_LINE_INFO 0
+# endif
+#
+# /* BOOST_PP_CONFIG_ERRORS */
+#
+# ifndef BOOST_PP_CONFIG_ERRORS
+# ifdef NDEBUG
+# define BOOST_PP_CONFIG_ERRORS 0
+# else
+# define BOOST_PP_CONFIG_ERRORS 1
+# endif
+# endif
+#
+# /* BOOST_PP_VARIADICS */
+#
+# define BOOST_PP_VARIADICS_MSVC 0
+# if !defined BOOST_PP_VARIADICS
+# /* variadic support explicitly disabled for all untested compilers */
+# if defined __GCCXML__ || defined __CUDACC__ || defined __PATHSCALE__ || defined __DMC__ || defined __CODEGEARC__ || defined __BORLANDC__ || defined __MWERKS__ || ( defined __SUNPRO_CC && __SUNPRO_CC < 0x5130 ) || defined __HP_aCC && !defined __EDG__ || defined __MRC__ || defined __SC__ || defined __IBMCPP__ || defined __PGI
+# define BOOST_PP_VARIADICS 0
+# /* VC++ (C/C++) */
+# elif defined _MSC_VER && _MSC_VER >= 1400 && (!defined __EDG__ || defined(__INTELLISENSE__)) && !defined __clang__
+# define BOOST_PP_VARIADICS 1
+# undef BOOST_PP_VARIADICS_MSVC
+# define BOOST_PP_VARIADICS_MSVC 1
+# /* Wave (C/C++), GCC (C++) */
+# elif defined __WAVE__ && __WAVE_HAS_VARIADICS__ || defined __GNUC__ && defined __GXX_EXPERIMENTAL_CXX0X__ && __GXX_EXPERIMENTAL_CXX0X__
+# define BOOST_PP_VARIADICS 1
+# /* EDG-based (C/C++), GCC (C), and unknown (C/C++) */
+# elif !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L
+# define BOOST_PP_VARIADICS 1
+# else
+# define BOOST_PP_VARIADICS 0
+# endif
+# elif !BOOST_PP_VARIADICS + 1 < 2
+# undef BOOST_PP_VARIADICS
+# define BOOST_PP_VARIADICS 1
+# if defined _MSC_VER && _MSC_VER >= 1400 && (defined(__INTELLISENSE__) || !(defined __EDG__ || defined __GCCXML__ || defined __CUDACC__ || defined __PATHSCALE__ || defined __clang__ || defined __DMC__ || defined __CODEGEARC__ || defined __BORLANDC__ || defined __MWERKS__ || defined __SUNPRO_CC || defined __HP_aCC || defined __MRC__ || defined __SC__ || defined __IBMCPP__ || defined __PGI))
+# undef BOOST_PP_VARIADICS_MSVC
+# define BOOST_PP_VARIADICS_MSVC 1
+# endif
+# else
+# undef BOOST_PP_VARIADICS
+# define BOOST_PP_VARIADICS 0
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/control/detail/while.hpp b/third_party/boost/boost/preprocessor/control/detail/while.hpp
new file mode 100644
index 0000000..7315e1d
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/control/detail/while.hpp
@@ -0,0 +1,536 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_CONTROL_DETAIL_WHILE_HPP
+# define BOOST_PREPROCESSOR_CONTROL_DETAIL_WHILE_HPP
+#
+# include <boost/preprocessor/control/iif.hpp>
+# include <boost/preprocessor/logical/bool.hpp>
+# include <boost/preprocessor/tuple/eat.hpp>
+#
+# define BOOST_PP_WHILE_1(p, o, s) BOOST_PP_WHILE_1_C(BOOST_PP_BOOL(p(2, s)), p, o, s)
+# define BOOST_PP_WHILE_2(p, o, s) BOOST_PP_WHILE_2_C(BOOST_PP_BOOL(p(3, s)), p, o, s)
+# define BOOST_PP_WHILE_3(p, o, s) BOOST_PP_WHILE_3_C(BOOST_PP_BOOL(p(4, s)), p, o, s)
+# define BOOST_PP_WHILE_4(p, o, s) BOOST_PP_WHILE_4_C(BOOST_PP_BOOL(p(5, s)), p, o, s)
+# define BOOST_PP_WHILE_5(p, o, s) BOOST_PP_WHILE_5_C(BOOST_PP_BOOL(p(6, s)), p, o, s)
+# define BOOST_PP_WHILE_6(p, o, s) BOOST_PP_WHILE_6_C(BOOST_PP_BOOL(p(7, s)), p, o, s)
+# define BOOST_PP_WHILE_7(p, o, s) BOOST_PP_WHILE_7_C(BOOST_PP_BOOL(p(8, s)), p, o, s)
+# define BOOST_PP_WHILE_8(p, o, s) BOOST_PP_WHILE_8_C(BOOST_PP_BOOL(p(9, s)), p, o, s)
+# define BOOST_PP_WHILE_9(p, o, s) BOOST_PP_WHILE_9_C(BOOST_PP_BOOL(p(10, s)), p, o, s)
+# define BOOST_PP_WHILE_10(p, o, s) BOOST_PP_WHILE_10_C(BOOST_PP_BOOL(p(11, s)), p, o, s)
+# define BOOST_PP_WHILE_11(p, o, s) BOOST_PP_WHILE_11_C(BOOST_PP_BOOL(p(12, s)), p, o, s)
+# define BOOST_PP_WHILE_12(p, o, s) BOOST_PP_WHILE_12_C(BOOST_PP_BOOL(p(13, s)), p, o, s)
+# define BOOST_PP_WHILE_13(p, o, s) BOOST_PP_WHILE_13_C(BOOST_PP_BOOL(p(14, s)), p, o, s)
+# define BOOST_PP_WHILE_14(p, o, s) BOOST_PP_WHILE_14_C(BOOST_PP_BOOL(p(15, s)), p, o, s)
+# define BOOST_PP_WHILE_15(p, o, s) BOOST_PP_WHILE_15_C(BOOST_PP_BOOL(p(16, s)), p, o, s)
+# define BOOST_PP_WHILE_16(p, o, s) BOOST_PP_WHILE_16_C(BOOST_PP_BOOL(p(17, s)), p, o, s)
+# define BOOST_PP_WHILE_17(p, o, s) BOOST_PP_WHILE_17_C(BOOST_PP_BOOL(p(18, s)), p, o, s)
+# define BOOST_PP_WHILE_18(p, o, s) BOOST_PP_WHILE_18_C(BOOST_PP_BOOL(p(19, s)), p, o, s)
+# define BOOST_PP_WHILE_19(p, o, s) BOOST_PP_WHILE_19_C(BOOST_PP_BOOL(p(20, s)), p, o, s)
+# define BOOST_PP_WHILE_20(p, o, s) BOOST_PP_WHILE_20_C(BOOST_PP_BOOL(p(21, s)), p, o, s)
+# define BOOST_PP_WHILE_21(p, o, s) BOOST_PP_WHILE_21_C(BOOST_PP_BOOL(p(22, s)), p, o, s)
+# define BOOST_PP_WHILE_22(p, o, s) BOOST_PP_WHILE_22_C(BOOST_PP_BOOL(p(23, s)), p, o, s)
+# define BOOST_PP_WHILE_23(p, o, s) BOOST_PP_WHILE_23_C(BOOST_PP_BOOL(p(24, s)), p, o, s)
+# define BOOST_PP_WHILE_24(p, o, s) BOOST_PP_WHILE_24_C(BOOST_PP_BOOL(p(25, s)), p, o, s)
+# define BOOST_PP_WHILE_25(p, o, s) BOOST_PP_WHILE_25_C(BOOST_PP_BOOL(p(26, s)), p, o, s)
+# define BOOST_PP_WHILE_26(p, o, s) BOOST_PP_WHILE_26_C(BOOST_PP_BOOL(p(27, s)), p, o, s)
+# define BOOST_PP_WHILE_27(p, o, s) BOOST_PP_WHILE_27_C(BOOST_PP_BOOL(p(28, s)), p, o, s)
+# define BOOST_PP_WHILE_28(p, o, s) BOOST_PP_WHILE_28_C(BOOST_PP_BOOL(p(29, s)), p, o, s)
+# define BOOST_PP_WHILE_29(p, o, s) BOOST_PP_WHILE_29_C(BOOST_PP_BOOL(p(30, s)), p, o, s)
+# define BOOST_PP_WHILE_30(p, o, s) BOOST_PP_WHILE_30_C(BOOST_PP_BOOL(p(31, s)), p, o, s)
+# define BOOST_PP_WHILE_31(p, o, s) BOOST_PP_WHILE_31_C(BOOST_PP_BOOL(p(32, s)), p, o, s)
+# define BOOST_PP_WHILE_32(p, o, s) BOOST_PP_WHILE_32_C(BOOST_PP_BOOL(p(33, s)), p, o, s)
+# define BOOST_PP_WHILE_33(p, o, s) BOOST_PP_WHILE_33_C(BOOST_PP_BOOL(p(34, s)), p, o, s)
+# define BOOST_PP_WHILE_34(p, o, s) BOOST_PP_WHILE_34_C(BOOST_PP_BOOL(p(35, s)), p, o, s)
+# define BOOST_PP_WHILE_35(p, o, s) BOOST_PP_WHILE_35_C(BOOST_PP_BOOL(p(36, s)), p, o, s)
+# define BOOST_PP_WHILE_36(p, o, s) BOOST_PP_WHILE_36_C(BOOST_PP_BOOL(p(37, s)), p, o, s)
+# define BOOST_PP_WHILE_37(p, o, s) BOOST_PP_WHILE_37_C(BOOST_PP_BOOL(p(38, s)), p, o, s)
+# define BOOST_PP_WHILE_38(p, o, s) BOOST_PP_WHILE_38_C(BOOST_PP_BOOL(p(39, s)), p, o, s)
+# define BOOST_PP_WHILE_39(p, o, s) BOOST_PP_WHILE_39_C(BOOST_PP_BOOL(p(40, s)), p, o, s)
+# define BOOST_PP_WHILE_40(p, o, s) BOOST_PP_WHILE_40_C(BOOST_PP_BOOL(p(41, s)), p, o, s)
+# define BOOST_PP_WHILE_41(p, o, s) BOOST_PP_WHILE_41_C(BOOST_PP_BOOL(p(42, s)), p, o, s)
+# define BOOST_PP_WHILE_42(p, o, s) BOOST_PP_WHILE_42_C(BOOST_PP_BOOL(p(43, s)), p, o, s)
+# define BOOST_PP_WHILE_43(p, o, s) BOOST_PP_WHILE_43_C(BOOST_PP_BOOL(p(44, s)), p, o, s)
+# define BOOST_PP_WHILE_44(p, o, s) BOOST_PP_WHILE_44_C(BOOST_PP_BOOL(p(45, s)), p, o, s)
+# define BOOST_PP_WHILE_45(p, o, s) BOOST_PP_WHILE_45_C(BOOST_PP_BOOL(p(46, s)), p, o, s)
+# define BOOST_PP_WHILE_46(p, o, s) BOOST_PP_WHILE_46_C(BOOST_PP_BOOL(p(47, s)), p, o, s)
+# define BOOST_PP_WHILE_47(p, o, s) BOOST_PP_WHILE_47_C(BOOST_PP_BOOL(p(48, s)), p, o, s)
+# define BOOST_PP_WHILE_48(p, o, s) BOOST_PP_WHILE_48_C(BOOST_PP_BOOL(p(49, s)), p, o, s)
+# define BOOST_PP_WHILE_49(p, o, s) BOOST_PP_WHILE_49_C(BOOST_PP_BOOL(p(50, s)), p, o, s)
+# define BOOST_PP_WHILE_50(p, o, s) BOOST_PP_WHILE_50_C(BOOST_PP_BOOL(p(51, s)), p, o, s)
+# define BOOST_PP_WHILE_51(p, o, s) BOOST_PP_WHILE_51_C(BOOST_PP_BOOL(p(52, s)), p, o, s)
+# define BOOST_PP_WHILE_52(p, o, s) BOOST_PP_WHILE_52_C(BOOST_PP_BOOL(p(53, s)), p, o, s)
+# define BOOST_PP_WHILE_53(p, o, s) BOOST_PP_WHILE_53_C(BOOST_PP_BOOL(p(54, s)), p, o, s)
+# define BOOST_PP_WHILE_54(p, o, s) BOOST_PP_WHILE_54_C(BOOST_PP_BOOL(p(55, s)), p, o, s)
+# define BOOST_PP_WHILE_55(p, o, s) BOOST_PP_WHILE_55_C(BOOST_PP_BOOL(p(56, s)), p, o, s)
+# define BOOST_PP_WHILE_56(p, o, s) BOOST_PP_WHILE_56_C(BOOST_PP_BOOL(p(57, s)), p, o, s)
+# define BOOST_PP_WHILE_57(p, o, s) BOOST_PP_WHILE_57_C(BOOST_PP_BOOL(p(58, s)), p, o, s)
+# define BOOST_PP_WHILE_58(p, o, s) BOOST_PP_WHILE_58_C(BOOST_PP_BOOL(p(59, s)), p, o, s)
+# define BOOST_PP_WHILE_59(p, o, s) BOOST_PP_WHILE_59_C(BOOST_PP_BOOL(p(60, s)), p, o, s)
+# define BOOST_PP_WHILE_60(p, o, s) BOOST_PP_WHILE_60_C(BOOST_PP_BOOL(p(61, s)), p, o, s)
+# define BOOST_PP_WHILE_61(p, o, s) BOOST_PP_WHILE_61_C(BOOST_PP_BOOL(p(62, s)), p, o, s)
+# define BOOST_PP_WHILE_62(p, o, s) BOOST_PP_WHILE_62_C(BOOST_PP_BOOL(p(63, s)), p, o, s)
+# define BOOST_PP_WHILE_63(p, o, s) BOOST_PP_WHILE_63_C(BOOST_PP_BOOL(p(64, s)), p, o, s)
+# define BOOST_PP_WHILE_64(p, o, s) BOOST_PP_WHILE_64_C(BOOST_PP_BOOL(p(65, s)), p, o, s)
+# define BOOST_PP_WHILE_65(p, o, s) BOOST_PP_WHILE_65_C(BOOST_PP_BOOL(p(66, s)), p, o, s)
+# define BOOST_PP_WHILE_66(p, o, s) BOOST_PP_WHILE_66_C(BOOST_PP_BOOL(p(67, s)), p, o, s)
+# define BOOST_PP_WHILE_67(p, o, s) BOOST_PP_WHILE_67_C(BOOST_PP_BOOL(p(68, s)), p, o, s)
+# define BOOST_PP_WHILE_68(p, o, s) BOOST_PP_WHILE_68_C(BOOST_PP_BOOL(p(69, s)), p, o, s)
+# define BOOST_PP_WHILE_69(p, o, s) BOOST_PP_WHILE_69_C(BOOST_PP_BOOL(p(70, s)), p, o, s)
+# define BOOST_PP_WHILE_70(p, o, s) BOOST_PP_WHILE_70_C(BOOST_PP_BOOL(p(71, s)), p, o, s)
+# define BOOST_PP_WHILE_71(p, o, s) BOOST_PP_WHILE_71_C(BOOST_PP_BOOL(p(72, s)), p, o, s)
+# define BOOST_PP_WHILE_72(p, o, s) BOOST_PP_WHILE_72_C(BOOST_PP_BOOL(p(73, s)), p, o, s)
+# define BOOST_PP_WHILE_73(p, o, s) BOOST_PP_WHILE_73_C(BOOST_PP_BOOL(p(74, s)), p, o, s)
+# define BOOST_PP_WHILE_74(p, o, s) BOOST_PP_WHILE_74_C(BOOST_PP_BOOL(p(75, s)), p, o, s)
+# define BOOST_PP_WHILE_75(p, o, s) BOOST_PP_WHILE_75_C(BOOST_PP_BOOL(p(76, s)), p, o, s)
+# define BOOST_PP_WHILE_76(p, o, s) BOOST_PP_WHILE_76_C(BOOST_PP_BOOL(p(77, s)), p, o, s)
+# define BOOST_PP_WHILE_77(p, o, s) BOOST_PP_WHILE_77_C(BOOST_PP_BOOL(p(78, s)), p, o, s)
+# define BOOST_PP_WHILE_78(p, o, s) BOOST_PP_WHILE_78_C(BOOST_PP_BOOL(p(79, s)), p, o, s)
+# define BOOST_PP_WHILE_79(p, o, s) BOOST_PP_WHILE_79_C(BOOST_PP_BOOL(p(80, s)), p, o, s)
+# define BOOST_PP_WHILE_80(p, o, s) BOOST_PP_WHILE_80_C(BOOST_PP_BOOL(p(81, s)), p, o, s)
+# define BOOST_PP_WHILE_81(p, o, s) BOOST_PP_WHILE_81_C(BOOST_PP_BOOL(p(82, s)), p, o, s)
+# define BOOST_PP_WHILE_82(p, o, s) BOOST_PP_WHILE_82_C(BOOST_PP_BOOL(p(83, s)), p, o, s)
+# define BOOST_PP_WHILE_83(p, o, s) BOOST_PP_WHILE_83_C(BOOST_PP_BOOL(p(84, s)), p, o, s)
+# define BOOST_PP_WHILE_84(p, o, s) BOOST_PP_WHILE_84_C(BOOST_PP_BOOL(p(85, s)), p, o, s)
+# define BOOST_PP_WHILE_85(p, o, s) BOOST_PP_WHILE_85_C(BOOST_PP_BOOL(p(86, s)), p, o, s)
+# define BOOST_PP_WHILE_86(p, o, s) BOOST_PP_WHILE_86_C(BOOST_PP_BOOL(p(87, s)), p, o, s)
+# define BOOST_PP_WHILE_87(p, o, s) BOOST_PP_WHILE_87_C(BOOST_PP_BOOL(p(88, s)), p, o, s)
+# define BOOST_PP_WHILE_88(p, o, s) BOOST_PP_WHILE_88_C(BOOST_PP_BOOL(p(89, s)), p, o, s)
+# define BOOST_PP_WHILE_89(p, o, s) BOOST_PP_WHILE_89_C(BOOST_PP_BOOL(p(90, s)), p, o, s)
+# define BOOST_PP_WHILE_90(p, o, s) BOOST_PP_WHILE_90_C(BOOST_PP_BOOL(p(91, s)), p, o, s)
+# define BOOST_PP_WHILE_91(p, o, s) BOOST_PP_WHILE_91_C(BOOST_PP_BOOL(p(92, s)), p, o, s)
+# define BOOST_PP_WHILE_92(p, o, s) BOOST_PP_WHILE_92_C(BOOST_PP_BOOL(p(93, s)), p, o, s)
+# define BOOST_PP_WHILE_93(p, o, s) BOOST_PP_WHILE_93_C(BOOST_PP_BOOL(p(94, s)), p, o, s)
+# define BOOST_PP_WHILE_94(p, o, s) BOOST_PP_WHILE_94_C(BOOST_PP_BOOL(p(95, s)), p, o, s)
+# define BOOST_PP_WHILE_95(p, o, s) BOOST_PP_WHILE_95_C(BOOST_PP_BOOL(p(96, s)), p, o, s)
+# define BOOST_PP_WHILE_96(p, o, s) BOOST_PP_WHILE_96_C(BOOST_PP_BOOL(p(97, s)), p, o, s)
+# define BOOST_PP_WHILE_97(p, o, s) BOOST_PP_WHILE_97_C(BOOST_PP_BOOL(p(98, s)), p, o, s)
+# define BOOST_PP_WHILE_98(p, o, s) BOOST_PP_WHILE_98_C(BOOST_PP_BOOL(p(99, s)), p, o, s)
+# define BOOST_PP_WHILE_99(p, o, s) BOOST_PP_WHILE_99_C(BOOST_PP_BOOL(p(100, s)), p, o, s)
+# define BOOST_PP_WHILE_100(p, o, s) BOOST_PP_WHILE_100_C(BOOST_PP_BOOL(p(101, s)), p, o, s)
+# define BOOST_PP_WHILE_101(p, o, s) BOOST_PP_WHILE_101_C(BOOST_PP_BOOL(p(102, s)), p, o, s)
+# define BOOST_PP_WHILE_102(p, o, s) BOOST_PP_WHILE_102_C(BOOST_PP_BOOL(p(103, s)), p, o, s)
+# define BOOST_PP_WHILE_103(p, o, s) BOOST_PP_WHILE_103_C(BOOST_PP_BOOL(p(104, s)), p, o, s)
+# define BOOST_PP_WHILE_104(p, o, s) BOOST_PP_WHILE_104_C(BOOST_PP_BOOL(p(105, s)), p, o, s)
+# define BOOST_PP_WHILE_105(p, o, s) BOOST_PP_WHILE_105_C(BOOST_PP_BOOL(p(106, s)), p, o, s)
+# define BOOST_PP_WHILE_106(p, o, s) BOOST_PP_WHILE_106_C(BOOST_PP_BOOL(p(107, s)), p, o, s)
+# define BOOST_PP_WHILE_107(p, o, s) BOOST_PP_WHILE_107_C(BOOST_PP_BOOL(p(108, s)), p, o, s)
+# define BOOST_PP_WHILE_108(p, o, s) BOOST_PP_WHILE_108_C(BOOST_PP_BOOL(p(109, s)), p, o, s)
+# define BOOST_PP_WHILE_109(p, o, s) BOOST_PP_WHILE_109_C(BOOST_PP_BOOL(p(110, s)), p, o, s)
+# define BOOST_PP_WHILE_110(p, o, s) BOOST_PP_WHILE_110_C(BOOST_PP_BOOL(p(111, s)), p, o, s)
+# define BOOST_PP_WHILE_111(p, o, s) BOOST_PP_WHILE_111_C(BOOST_PP_BOOL(p(112, s)), p, o, s)
+# define BOOST_PP_WHILE_112(p, o, s) BOOST_PP_WHILE_112_C(BOOST_PP_BOOL(p(113, s)), p, o, s)
+# define BOOST_PP_WHILE_113(p, o, s) BOOST_PP_WHILE_113_C(BOOST_PP_BOOL(p(114, s)), p, o, s)
+# define BOOST_PP_WHILE_114(p, o, s) BOOST_PP_WHILE_114_C(BOOST_PP_BOOL(p(115, s)), p, o, s)
+# define BOOST_PP_WHILE_115(p, o, s) BOOST_PP_WHILE_115_C(BOOST_PP_BOOL(p(116, s)), p, o, s)
+# define BOOST_PP_WHILE_116(p, o, s) BOOST_PP_WHILE_116_C(BOOST_PP_BOOL(p(117, s)), p, o, s)
+# define BOOST_PP_WHILE_117(p, o, s) BOOST_PP_WHILE_117_C(BOOST_PP_BOOL(p(118, s)), p, o, s)
+# define BOOST_PP_WHILE_118(p, o, s) BOOST_PP_WHILE_118_C(BOOST_PP_BOOL(p(119, s)), p, o, s)
+# define BOOST_PP_WHILE_119(p, o, s) BOOST_PP_WHILE_119_C(BOOST_PP_BOOL(p(120, s)), p, o, s)
+# define BOOST_PP_WHILE_120(p, o, s) BOOST_PP_WHILE_120_C(BOOST_PP_BOOL(p(121, s)), p, o, s)
+# define BOOST_PP_WHILE_121(p, o, s) BOOST_PP_WHILE_121_C(BOOST_PP_BOOL(p(122, s)), p, o, s)
+# define BOOST_PP_WHILE_122(p, o, s) BOOST_PP_WHILE_122_C(BOOST_PP_BOOL(p(123, s)), p, o, s)
+# define BOOST_PP_WHILE_123(p, o, s) BOOST_PP_WHILE_123_C(BOOST_PP_BOOL(p(124, s)), p, o, s)
+# define BOOST_PP_WHILE_124(p, o, s) BOOST_PP_WHILE_124_C(BOOST_PP_BOOL(p(125, s)), p, o, s)
+# define BOOST_PP_WHILE_125(p, o, s) BOOST_PP_WHILE_125_C(BOOST_PP_BOOL(p(126, s)), p, o, s)
+# define BOOST_PP_WHILE_126(p, o, s) BOOST_PP_WHILE_126_C(BOOST_PP_BOOL(p(127, s)), p, o, s)
+# define BOOST_PP_WHILE_127(p, o, s) BOOST_PP_WHILE_127_C(BOOST_PP_BOOL(p(128, s)), p, o, s)
+# define BOOST_PP_WHILE_128(p, o, s) BOOST_PP_WHILE_128_C(BOOST_PP_BOOL(p(129, s)), p, o, s)
+# define BOOST_PP_WHILE_129(p, o, s) BOOST_PP_WHILE_129_C(BOOST_PP_BOOL(p(130, s)), p, o, s)
+# define BOOST_PP_WHILE_130(p, o, s) BOOST_PP_WHILE_130_C(BOOST_PP_BOOL(p(131, s)), p, o, s)
+# define BOOST_PP_WHILE_131(p, o, s) BOOST_PP_WHILE_131_C(BOOST_PP_BOOL(p(132, s)), p, o, s)
+# define BOOST_PP_WHILE_132(p, o, s) BOOST_PP_WHILE_132_C(BOOST_PP_BOOL(p(133, s)), p, o, s)
+# define BOOST_PP_WHILE_133(p, o, s) BOOST_PP_WHILE_133_C(BOOST_PP_BOOL(p(134, s)), p, o, s)
+# define BOOST_PP_WHILE_134(p, o, s) BOOST_PP_WHILE_134_C(BOOST_PP_BOOL(p(135, s)), p, o, s)
+# define BOOST_PP_WHILE_135(p, o, s) BOOST_PP_WHILE_135_C(BOOST_PP_BOOL(p(136, s)), p, o, s)
+# define BOOST_PP_WHILE_136(p, o, s) BOOST_PP_WHILE_136_C(BOOST_PP_BOOL(p(137, s)), p, o, s)
+# define BOOST_PP_WHILE_137(p, o, s) BOOST_PP_WHILE_137_C(BOOST_PP_BOOL(p(138, s)), p, o, s)
+# define BOOST_PP_WHILE_138(p, o, s) BOOST_PP_WHILE_138_C(BOOST_PP_BOOL(p(139, s)), p, o, s)
+# define BOOST_PP_WHILE_139(p, o, s) BOOST_PP_WHILE_139_C(BOOST_PP_BOOL(p(140, s)), p, o, s)
+# define BOOST_PP_WHILE_140(p, o, s) BOOST_PP_WHILE_140_C(BOOST_PP_BOOL(p(141, s)), p, o, s)
+# define BOOST_PP_WHILE_141(p, o, s) BOOST_PP_WHILE_141_C(BOOST_PP_BOOL(p(142, s)), p, o, s)
+# define BOOST_PP_WHILE_142(p, o, s) BOOST_PP_WHILE_142_C(BOOST_PP_BOOL(p(143, s)), p, o, s)
+# define BOOST_PP_WHILE_143(p, o, s) BOOST_PP_WHILE_143_C(BOOST_PP_BOOL(p(144, s)), p, o, s)
+# define BOOST_PP_WHILE_144(p, o, s) BOOST_PP_WHILE_144_C(BOOST_PP_BOOL(p(145, s)), p, o, s)
+# define BOOST_PP_WHILE_145(p, o, s) BOOST_PP_WHILE_145_C(BOOST_PP_BOOL(p(146, s)), p, o, s)
+# define BOOST_PP_WHILE_146(p, o, s) BOOST_PP_WHILE_146_C(BOOST_PP_BOOL(p(147, s)), p, o, s)
+# define BOOST_PP_WHILE_147(p, o, s) BOOST_PP_WHILE_147_C(BOOST_PP_BOOL(p(148, s)), p, o, s)
+# define BOOST_PP_WHILE_148(p, o, s) BOOST_PP_WHILE_148_C(BOOST_PP_BOOL(p(149, s)), p, o, s)
+# define BOOST_PP_WHILE_149(p, o, s) BOOST_PP_WHILE_149_C(BOOST_PP_BOOL(p(150, s)), p, o, s)
+# define BOOST_PP_WHILE_150(p, o, s) BOOST_PP_WHILE_150_C(BOOST_PP_BOOL(p(151, s)), p, o, s)
+# define BOOST_PP_WHILE_151(p, o, s) BOOST_PP_WHILE_151_C(BOOST_PP_BOOL(p(152, s)), p, o, s)
+# define BOOST_PP_WHILE_152(p, o, s) BOOST_PP_WHILE_152_C(BOOST_PP_BOOL(p(153, s)), p, o, s)
+# define BOOST_PP_WHILE_153(p, o, s) BOOST_PP_WHILE_153_C(BOOST_PP_BOOL(p(154, s)), p, o, s)
+# define BOOST_PP_WHILE_154(p, o, s) BOOST_PP_WHILE_154_C(BOOST_PP_BOOL(p(155, s)), p, o, s)
+# define BOOST_PP_WHILE_155(p, o, s) BOOST_PP_WHILE_155_C(BOOST_PP_BOOL(p(156, s)), p, o, s)
+# define BOOST_PP_WHILE_156(p, o, s) BOOST_PP_WHILE_156_C(BOOST_PP_BOOL(p(157, s)), p, o, s)
+# define BOOST_PP_WHILE_157(p, o, s) BOOST_PP_WHILE_157_C(BOOST_PP_BOOL(p(158, s)), p, o, s)
+# define BOOST_PP_WHILE_158(p, o, s) BOOST_PP_WHILE_158_C(BOOST_PP_BOOL(p(159, s)), p, o, s)
+# define BOOST_PP_WHILE_159(p, o, s) BOOST_PP_WHILE_159_C(BOOST_PP_BOOL(p(160, s)), p, o, s)
+# define BOOST_PP_WHILE_160(p, o, s) BOOST_PP_WHILE_160_C(BOOST_PP_BOOL(p(161, s)), p, o, s)
+# define BOOST_PP_WHILE_161(p, o, s) BOOST_PP_WHILE_161_C(BOOST_PP_BOOL(p(162, s)), p, o, s)
+# define BOOST_PP_WHILE_162(p, o, s) BOOST_PP_WHILE_162_C(BOOST_PP_BOOL(p(163, s)), p, o, s)
+# define BOOST_PP_WHILE_163(p, o, s) BOOST_PP_WHILE_163_C(BOOST_PP_BOOL(p(164, s)), p, o, s)
+# define BOOST_PP_WHILE_164(p, o, s) BOOST_PP_WHILE_164_C(BOOST_PP_BOOL(p(165, s)), p, o, s)
+# define BOOST_PP_WHILE_165(p, o, s) BOOST_PP_WHILE_165_C(BOOST_PP_BOOL(p(166, s)), p, o, s)
+# define BOOST_PP_WHILE_166(p, o, s) BOOST_PP_WHILE_166_C(BOOST_PP_BOOL(p(167, s)), p, o, s)
+# define BOOST_PP_WHILE_167(p, o, s) BOOST_PP_WHILE_167_C(BOOST_PP_BOOL(p(168, s)), p, o, s)
+# define BOOST_PP_WHILE_168(p, o, s) BOOST_PP_WHILE_168_C(BOOST_PP_BOOL(p(169, s)), p, o, s)
+# define BOOST_PP_WHILE_169(p, o, s) BOOST_PP_WHILE_169_C(BOOST_PP_BOOL(p(170, s)), p, o, s)
+# define BOOST_PP_WHILE_170(p, o, s) BOOST_PP_WHILE_170_C(BOOST_PP_BOOL(p(171, s)), p, o, s)
+# define BOOST_PP_WHILE_171(p, o, s) BOOST_PP_WHILE_171_C(BOOST_PP_BOOL(p(172, s)), p, o, s)
+# define BOOST_PP_WHILE_172(p, o, s) BOOST_PP_WHILE_172_C(BOOST_PP_BOOL(p(173, s)), p, o, s)
+# define BOOST_PP_WHILE_173(p, o, s) BOOST_PP_WHILE_173_C(BOOST_PP_BOOL(p(174, s)), p, o, s)
+# define BOOST_PP_WHILE_174(p, o, s) BOOST_PP_WHILE_174_C(BOOST_PP_BOOL(p(175, s)), p, o, s)
+# define BOOST_PP_WHILE_175(p, o, s) BOOST_PP_WHILE_175_C(BOOST_PP_BOOL(p(176, s)), p, o, s)
+# define BOOST_PP_WHILE_176(p, o, s) BOOST_PP_WHILE_176_C(BOOST_PP_BOOL(p(177, s)), p, o, s)
+# define BOOST_PP_WHILE_177(p, o, s) BOOST_PP_WHILE_177_C(BOOST_PP_BOOL(p(178, s)), p, o, s)
+# define BOOST_PP_WHILE_178(p, o, s) BOOST_PP_WHILE_178_C(BOOST_PP_BOOL(p(179, s)), p, o, s)
+# define BOOST_PP_WHILE_179(p, o, s) BOOST_PP_WHILE_179_C(BOOST_PP_BOOL(p(180, s)), p, o, s)
+# define BOOST_PP_WHILE_180(p, o, s) BOOST_PP_WHILE_180_C(BOOST_PP_BOOL(p(181, s)), p, o, s)
+# define BOOST_PP_WHILE_181(p, o, s) BOOST_PP_WHILE_181_C(BOOST_PP_BOOL(p(182, s)), p, o, s)
+# define BOOST_PP_WHILE_182(p, o, s) BOOST_PP_WHILE_182_C(BOOST_PP_BOOL(p(183, s)), p, o, s)
+# define BOOST_PP_WHILE_183(p, o, s) BOOST_PP_WHILE_183_C(BOOST_PP_BOOL(p(184, s)), p, o, s)
+# define BOOST_PP_WHILE_184(p, o, s) BOOST_PP_WHILE_184_C(BOOST_PP_BOOL(p(185, s)), p, o, s)
+# define BOOST_PP_WHILE_185(p, o, s) BOOST_PP_WHILE_185_C(BOOST_PP_BOOL(p(186, s)), p, o, s)
+# define BOOST_PP_WHILE_186(p, o, s) BOOST_PP_WHILE_186_C(BOOST_PP_BOOL(p(187, s)), p, o, s)
+# define BOOST_PP_WHILE_187(p, o, s) BOOST_PP_WHILE_187_C(BOOST_PP_BOOL(p(188, s)), p, o, s)
+# define BOOST_PP_WHILE_188(p, o, s) BOOST_PP_WHILE_188_C(BOOST_PP_BOOL(p(189, s)), p, o, s)
+# define BOOST_PP_WHILE_189(p, o, s) BOOST_PP_WHILE_189_C(BOOST_PP_BOOL(p(190, s)), p, o, s)
+# define BOOST_PP_WHILE_190(p, o, s) BOOST_PP_WHILE_190_C(BOOST_PP_BOOL(p(191, s)), p, o, s)
+# define BOOST_PP_WHILE_191(p, o, s) BOOST_PP_WHILE_191_C(BOOST_PP_BOOL(p(192, s)), p, o, s)
+# define BOOST_PP_WHILE_192(p, o, s) BOOST_PP_WHILE_192_C(BOOST_PP_BOOL(p(193, s)), p, o, s)
+# define BOOST_PP_WHILE_193(p, o, s) BOOST_PP_WHILE_193_C(BOOST_PP_BOOL(p(194, s)), p, o, s)
+# define BOOST_PP_WHILE_194(p, o, s) BOOST_PP_WHILE_194_C(BOOST_PP_BOOL(p(195, s)), p, o, s)
+# define BOOST_PP_WHILE_195(p, o, s) BOOST_PP_WHILE_195_C(BOOST_PP_BOOL(p(196, s)), p, o, s)
+# define BOOST_PP_WHILE_196(p, o, s) BOOST_PP_WHILE_196_C(BOOST_PP_BOOL(p(197, s)), p, o, s)
+# define BOOST_PP_WHILE_197(p, o, s) BOOST_PP_WHILE_197_C(BOOST_PP_BOOL(p(198, s)), p, o, s)
+# define BOOST_PP_WHILE_198(p, o, s) BOOST_PP_WHILE_198_C(BOOST_PP_BOOL(p(199, s)), p, o, s)
+# define BOOST_PP_WHILE_199(p, o, s) BOOST_PP_WHILE_199_C(BOOST_PP_BOOL(p(200, s)), p, o, s)
+# define BOOST_PP_WHILE_200(p, o, s) BOOST_PP_WHILE_200_C(BOOST_PP_BOOL(p(201, s)), p, o, s)
+# define BOOST_PP_WHILE_201(p, o, s) BOOST_PP_WHILE_201_C(BOOST_PP_BOOL(p(202, s)), p, o, s)
+# define BOOST_PP_WHILE_202(p, o, s) BOOST_PP_WHILE_202_C(BOOST_PP_BOOL(p(203, s)), p, o, s)
+# define BOOST_PP_WHILE_203(p, o, s) BOOST_PP_WHILE_203_C(BOOST_PP_BOOL(p(204, s)), p, o, s)
+# define BOOST_PP_WHILE_204(p, o, s) BOOST_PP_WHILE_204_C(BOOST_PP_BOOL(p(205, s)), p, o, s)
+# define BOOST_PP_WHILE_205(p, o, s) BOOST_PP_WHILE_205_C(BOOST_PP_BOOL(p(206, s)), p, o, s)
+# define BOOST_PP_WHILE_206(p, o, s) BOOST_PP_WHILE_206_C(BOOST_PP_BOOL(p(207, s)), p, o, s)
+# define BOOST_PP_WHILE_207(p, o, s) BOOST_PP_WHILE_207_C(BOOST_PP_BOOL(p(208, s)), p, o, s)
+# define BOOST_PP_WHILE_208(p, o, s) BOOST_PP_WHILE_208_C(BOOST_PP_BOOL(p(209, s)), p, o, s)
+# define BOOST_PP_WHILE_209(p, o, s) BOOST_PP_WHILE_209_C(BOOST_PP_BOOL(p(210, s)), p, o, s)
+# define BOOST_PP_WHILE_210(p, o, s) BOOST_PP_WHILE_210_C(BOOST_PP_BOOL(p(211, s)), p, o, s)
+# define BOOST_PP_WHILE_211(p, o, s) BOOST_PP_WHILE_211_C(BOOST_PP_BOOL(p(212, s)), p, o, s)
+# define BOOST_PP_WHILE_212(p, o, s) BOOST_PP_WHILE_212_C(BOOST_PP_BOOL(p(213, s)), p, o, s)
+# define BOOST_PP_WHILE_213(p, o, s) BOOST_PP_WHILE_213_C(BOOST_PP_BOOL(p(214, s)), p, o, s)
+# define BOOST_PP_WHILE_214(p, o, s) BOOST_PP_WHILE_214_C(BOOST_PP_BOOL(p(215, s)), p, o, s)
+# define BOOST_PP_WHILE_215(p, o, s) BOOST_PP_WHILE_215_C(BOOST_PP_BOOL(p(216, s)), p, o, s)
+# define BOOST_PP_WHILE_216(p, o, s) BOOST_PP_WHILE_216_C(BOOST_PP_BOOL(p(217, s)), p, o, s)
+# define BOOST_PP_WHILE_217(p, o, s) BOOST_PP_WHILE_217_C(BOOST_PP_BOOL(p(218, s)), p, o, s)
+# define BOOST_PP_WHILE_218(p, o, s) BOOST_PP_WHILE_218_C(BOOST_PP_BOOL(p(219, s)), p, o, s)
+# define BOOST_PP_WHILE_219(p, o, s) BOOST_PP_WHILE_219_C(BOOST_PP_BOOL(p(220, s)), p, o, s)
+# define BOOST_PP_WHILE_220(p, o, s) BOOST_PP_WHILE_220_C(BOOST_PP_BOOL(p(221, s)), p, o, s)
+# define BOOST_PP_WHILE_221(p, o, s) BOOST_PP_WHILE_221_C(BOOST_PP_BOOL(p(222, s)), p, o, s)
+# define BOOST_PP_WHILE_222(p, o, s) BOOST_PP_WHILE_222_C(BOOST_PP_BOOL(p(223, s)), p, o, s)
+# define BOOST_PP_WHILE_223(p, o, s) BOOST_PP_WHILE_223_C(BOOST_PP_BOOL(p(224, s)), p, o, s)
+# define BOOST_PP_WHILE_224(p, o, s) BOOST_PP_WHILE_224_C(BOOST_PP_BOOL(p(225, s)), p, o, s)
+# define BOOST_PP_WHILE_225(p, o, s) BOOST_PP_WHILE_225_C(BOOST_PP_BOOL(p(226, s)), p, o, s)
+# define BOOST_PP_WHILE_226(p, o, s) BOOST_PP_WHILE_226_C(BOOST_PP_BOOL(p(227, s)), p, o, s)
+# define BOOST_PP_WHILE_227(p, o, s) BOOST_PP_WHILE_227_C(BOOST_PP_BOOL(p(228, s)), p, o, s)
+# define BOOST_PP_WHILE_228(p, o, s) BOOST_PP_WHILE_228_C(BOOST_PP_BOOL(p(229, s)), p, o, s)
+# define BOOST_PP_WHILE_229(p, o, s) BOOST_PP_WHILE_229_C(BOOST_PP_BOOL(p(230, s)), p, o, s)
+# define BOOST_PP_WHILE_230(p, o, s) BOOST_PP_WHILE_230_C(BOOST_PP_BOOL(p(231, s)), p, o, s)
+# define BOOST_PP_WHILE_231(p, o, s) BOOST_PP_WHILE_231_C(BOOST_PP_BOOL(p(232, s)), p, o, s)
+# define BOOST_PP_WHILE_232(p, o, s) BOOST_PP_WHILE_232_C(BOOST_PP_BOOL(p(233, s)), p, o, s)
+# define BOOST_PP_WHILE_233(p, o, s) BOOST_PP_WHILE_233_C(BOOST_PP_BOOL(p(234, s)), p, o, s)
+# define BOOST_PP_WHILE_234(p, o, s) BOOST_PP_WHILE_234_C(BOOST_PP_BOOL(p(235, s)), p, o, s)
+# define BOOST_PP_WHILE_235(p, o, s) BOOST_PP_WHILE_235_C(BOOST_PP_BOOL(p(236, s)), p, o, s)
+# define BOOST_PP_WHILE_236(p, o, s) BOOST_PP_WHILE_236_C(BOOST_PP_BOOL(p(237, s)), p, o, s)
+# define BOOST_PP_WHILE_237(p, o, s) BOOST_PP_WHILE_237_C(BOOST_PP_BOOL(p(238, s)), p, o, s)
+# define BOOST_PP_WHILE_238(p, o, s) BOOST_PP_WHILE_238_C(BOOST_PP_BOOL(p(239, s)), p, o, s)
+# define BOOST_PP_WHILE_239(p, o, s) BOOST_PP_WHILE_239_C(BOOST_PP_BOOL(p(240, s)), p, o, s)
+# define BOOST_PP_WHILE_240(p, o, s) BOOST_PP_WHILE_240_C(BOOST_PP_BOOL(p(241, s)), p, o, s)
+# define BOOST_PP_WHILE_241(p, o, s) BOOST_PP_WHILE_241_C(BOOST_PP_BOOL(p(242, s)), p, o, s)
+# define BOOST_PP_WHILE_242(p, o, s) BOOST_PP_WHILE_242_C(BOOST_PP_BOOL(p(243, s)), p, o, s)
+# define BOOST_PP_WHILE_243(p, o, s) BOOST_PP_WHILE_243_C(BOOST_PP_BOOL(p(244, s)), p, o, s)
+# define BOOST_PP_WHILE_244(p, o, s) BOOST_PP_WHILE_244_C(BOOST_PP_BOOL(p(245, s)), p, o, s)
+# define BOOST_PP_WHILE_245(p, o, s) BOOST_PP_WHILE_245_C(BOOST_PP_BOOL(p(246, s)), p, o, s)
+# define BOOST_PP_WHILE_246(p, o, s) BOOST_PP_WHILE_246_C(BOOST_PP_BOOL(p(247, s)), p, o, s)
+# define BOOST_PP_WHILE_247(p, o, s) BOOST_PP_WHILE_247_C(BOOST_PP_BOOL(p(248, s)), p, o, s)
+# define BOOST_PP_WHILE_248(p, o, s) BOOST_PP_WHILE_248_C(BOOST_PP_BOOL(p(249, s)), p, o, s)
+# define BOOST_PP_WHILE_249(p, o, s) BOOST_PP_WHILE_249_C(BOOST_PP_BOOL(p(250, s)), p, o, s)
+# define BOOST_PP_WHILE_250(p, o, s) BOOST_PP_WHILE_250_C(BOOST_PP_BOOL(p(251, s)), p, o, s)
+# define BOOST_PP_WHILE_251(p, o, s) BOOST_PP_WHILE_251_C(BOOST_PP_BOOL(p(252, s)), p, o, s)
+# define BOOST_PP_WHILE_252(p, o, s) BOOST_PP_WHILE_252_C(BOOST_PP_BOOL(p(253, s)), p, o, s)
+# define BOOST_PP_WHILE_253(p, o, s) BOOST_PP_WHILE_253_C(BOOST_PP_BOOL(p(254, s)), p, o, s)
+# define BOOST_PP_WHILE_254(p, o, s) BOOST_PP_WHILE_254_C(BOOST_PP_BOOL(p(255, s)), p, o, s)
+# define BOOST_PP_WHILE_255(p, o, s) BOOST_PP_WHILE_255_C(BOOST_PP_BOOL(p(256, s)), p, o, s)
+# define BOOST_PP_WHILE_256(p, o, s) BOOST_PP_WHILE_256_C(BOOST_PP_BOOL(p(257, s)), p, o, s)
+#
+# define BOOST_PP_WHILE_1_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_2, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(2, s))
+# define BOOST_PP_WHILE_2_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_3, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(3, s))
+# define BOOST_PP_WHILE_3_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_4, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(4, s))
+# define BOOST_PP_WHILE_4_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_5, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(5, s))
+# define BOOST_PP_WHILE_5_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_6, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(6, s))
+# define BOOST_PP_WHILE_6_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_7, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(7, s))
+# define BOOST_PP_WHILE_7_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_8, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(8, s))
+# define BOOST_PP_WHILE_8_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_9, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(9, s))
+# define BOOST_PP_WHILE_9_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_10, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(10, s))
+# define BOOST_PP_WHILE_10_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_11, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(11, s))
+# define BOOST_PP_WHILE_11_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_12, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(12, s))
+# define BOOST_PP_WHILE_12_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_13, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(13, s))
+# define BOOST_PP_WHILE_13_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_14, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(14, s))
+# define BOOST_PP_WHILE_14_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_15, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(15, s))
+# define BOOST_PP_WHILE_15_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_16, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(16, s))
+# define BOOST_PP_WHILE_16_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_17, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(17, s))
+# define BOOST_PP_WHILE_17_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_18, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(18, s))
+# define BOOST_PP_WHILE_18_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_19, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(19, s))
+# define BOOST_PP_WHILE_19_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_20, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(20, s))
+# define BOOST_PP_WHILE_20_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_21, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(21, s))
+# define BOOST_PP_WHILE_21_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_22, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(22, s))
+# define BOOST_PP_WHILE_22_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_23, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(23, s))
+# define BOOST_PP_WHILE_23_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_24, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(24, s))
+# define BOOST_PP_WHILE_24_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_25, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(25, s))
+# define BOOST_PP_WHILE_25_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_26, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(26, s))
+# define BOOST_PP_WHILE_26_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_27, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(27, s))
+# define BOOST_PP_WHILE_27_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_28, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(28, s))
+# define BOOST_PP_WHILE_28_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_29, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(29, s))
+# define BOOST_PP_WHILE_29_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_30, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(30, s))
+# define BOOST_PP_WHILE_30_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_31, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(31, s))
+# define BOOST_PP_WHILE_31_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_32, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(32, s))
+# define BOOST_PP_WHILE_32_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_33, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(33, s))
+# define BOOST_PP_WHILE_33_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_34, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(34, s))
+# define BOOST_PP_WHILE_34_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_35, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(35, s))
+# define BOOST_PP_WHILE_35_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_36, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(36, s))
+# define BOOST_PP_WHILE_36_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_37, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(37, s))
+# define BOOST_PP_WHILE_37_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_38, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(38, s))
+# define BOOST_PP_WHILE_38_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_39, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(39, s))
+# define BOOST_PP_WHILE_39_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_40, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(40, s))
+# define BOOST_PP_WHILE_40_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_41, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(41, s))
+# define BOOST_PP_WHILE_41_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_42, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(42, s))
+# define BOOST_PP_WHILE_42_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_43, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(43, s))
+# define BOOST_PP_WHILE_43_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_44, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(44, s))
+# define BOOST_PP_WHILE_44_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_45, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(45, s))
+# define BOOST_PP_WHILE_45_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_46, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(46, s))
+# define BOOST_PP_WHILE_46_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_47, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(47, s))
+# define BOOST_PP_WHILE_47_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_48, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(48, s))
+# define BOOST_PP_WHILE_48_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_49, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(49, s))
+# define BOOST_PP_WHILE_49_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_50, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(50, s))
+# define BOOST_PP_WHILE_50_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_51, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(51, s))
+# define BOOST_PP_WHILE_51_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_52, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(52, s))
+# define BOOST_PP_WHILE_52_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_53, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(53, s))
+# define BOOST_PP_WHILE_53_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_54, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(54, s))
+# define BOOST_PP_WHILE_54_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_55, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(55, s))
+# define BOOST_PP_WHILE_55_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_56, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(56, s))
+# define BOOST_PP_WHILE_56_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_57, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(57, s))
+# define BOOST_PP_WHILE_57_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_58, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(58, s))
+# define BOOST_PP_WHILE_58_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_59, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(59, s))
+# define BOOST_PP_WHILE_59_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_60, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(60, s))
+# define BOOST_PP_WHILE_60_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_61, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(61, s))
+# define BOOST_PP_WHILE_61_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_62, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(62, s))
+# define BOOST_PP_WHILE_62_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_63, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(63, s))
+# define BOOST_PP_WHILE_63_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_64, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(64, s))
+# define BOOST_PP_WHILE_64_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_65, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(65, s))
+# define BOOST_PP_WHILE_65_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_66, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(66, s))
+# define BOOST_PP_WHILE_66_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_67, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(67, s))
+# define BOOST_PP_WHILE_67_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_68, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(68, s))
+# define BOOST_PP_WHILE_68_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_69, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(69, s))
+# define BOOST_PP_WHILE_69_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_70, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(70, s))
+# define BOOST_PP_WHILE_70_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_71, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(71, s))
+# define BOOST_PP_WHILE_71_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_72, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(72, s))
+# define BOOST_PP_WHILE_72_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_73, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(73, s))
+# define BOOST_PP_WHILE_73_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_74, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(74, s))
+# define BOOST_PP_WHILE_74_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_75, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(75, s))
+# define BOOST_PP_WHILE_75_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_76, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(76, s))
+# define BOOST_PP_WHILE_76_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_77, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(77, s))
+# define BOOST_PP_WHILE_77_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_78, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(78, s))
+# define BOOST_PP_WHILE_78_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_79, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(79, s))
+# define BOOST_PP_WHILE_79_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_80, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(80, s))
+# define BOOST_PP_WHILE_80_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_81, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(81, s))
+# define BOOST_PP_WHILE_81_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_82, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(82, s))
+# define BOOST_PP_WHILE_82_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_83, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(83, s))
+# define BOOST_PP_WHILE_83_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_84, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(84, s))
+# define BOOST_PP_WHILE_84_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_85, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(85, s))
+# define BOOST_PP_WHILE_85_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_86, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(86, s))
+# define BOOST_PP_WHILE_86_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_87, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(87, s))
+# define BOOST_PP_WHILE_87_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_88, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(88, s))
+# define BOOST_PP_WHILE_88_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_89, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(89, s))
+# define BOOST_PP_WHILE_89_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_90, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(90, s))
+# define BOOST_PP_WHILE_90_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_91, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(91, s))
+# define BOOST_PP_WHILE_91_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_92, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(92, s))
+# define BOOST_PP_WHILE_92_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_93, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(93, s))
+# define BOOST_PP_WHILE_93_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_94, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(94, s))
+# define BOOST_PP_WHILE_94_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_95, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(95, s))
+# define BOOST_PP_WHILE_95_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_96, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(96, s))
+# define BOOST_PP_WHILE_96_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_97, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(97, s))
+# define BOOST_PP_WHILE_97_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_98, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(98, s))
+# define BOOST_PP_WHILE_98_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_99, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(99, s))
+# define BOOST_PP_WHILE_99_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_100, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(100, s))
+# define BOOST_PP_WHILE_100_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_101, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(101, s))
+# define BOOST_PP_WHILE_101_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_102, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(102, s))
+# define BOOST_PP_WHILE_102_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_103, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(103, s))
+# define BOOST_PP_WHILE_103_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_104, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(104, s))
+# define BOOST_PP_WHILE_104_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_105, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(105, s))
+# define BOOST_PP_WHILE_105_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_106, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(106, s))
+# define BOOST_PP_WHILE_106_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_107, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(107, s))
+# define BOOST_PP_WHILE_107_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_108, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(108, s))
+# define BOOST_PP_WHILE_108_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_109, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(109, s))
+# define BOOST_PP_WHILE_109_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_110, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(110, s))
+# define BOOST_PP_WHILE_110_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_111, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(111, s))
+# define BOOST_PP_WHILE_111_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_112, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(112, s))
+# define BOOST_PP_WHILE_112_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_113, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(113, s))
+# define BOOST_PP_WHILE_113_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_114, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(114, s))
+# define BOOST_PP_WHILE_114_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_115, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(115, s))
+# define BOOST_PP_WHILE_115_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_116, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(116, s))
+# define BOOST_PP_WHILE_116_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_117, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(117, s))
+# define BOOST_PP_WHILE_117_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_118, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(118, s))
+# define BOOST_PP_WHILE_118_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_119, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(119, s))
+# define BOOST_PP_WHILE_119_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_120, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(120, s))
+# define BOOST_PP_WHILE_120_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_121, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(121, s))
+# define BOOST_PP_WHILE_121_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_122, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(122, s))
+# define BOOST_PP_WHILE_122_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_123, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(123, s))
+# define BOOST_PP_WHILE_123_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_124, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(124, s))
+# define BOOST_PP_WHILE_124_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_125, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(125, s))
+# define BOOST_PP_WHILE_125_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_126, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(126, s))
+# define BOOST_PP_WHILE_126_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_127, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(127, s))
+# define BOOST_PP_WHILE_127_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_128, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(128, s))
+# define BOOST_PP_WHILE_128_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_129, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(129, s))
+# define BOOST_PP_WHILE_129_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_130, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(130, s))
+# define BOOST_PP_WHILE_130_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_131, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(131, s))
+# define BOOST_PP_WHILE_131_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_132, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(132, s))
+# define BOOST_PP_WHILE_132_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_133, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(133, s))
+# define BOOST_PP_WHILE_133_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_134, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(134, s))
+# define BOOST_PP_WHILE_134_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_135, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(135, s))
+# define BOOST_PP_WHILE_135_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_136, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(136, s))
+# define BOOST_PP_WHILE_136_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_137, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(137, s))
+# define BOOST_PP_WHILE_137_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_138, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(138, s))
+# define BOOST_PP_WHILE_138_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_139, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(139, s))
+# define BOOST_PP_WHILE_139_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_140, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(140, s))
+# define BOOST_PP_WHILE_140_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_141, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(141, s))
+# define BOOST_PP_WHILE_141_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_142, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(142, s))
+# define BOOST_PP_WHILE_142_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_143, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(143, s))
+# define BOOST_PP_WHILE_143_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_144, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(144, s))
+# define BOOST_PP_WHILE_144_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_145, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(145, s))
+# define BOOST_PP_WHILE_145_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_146, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(146, s))
+# define BOOST_PP_WHILE_146_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_147, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(147, s))
+# define BOOST_PP_WHILE_147_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_148, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(148, s))
+# define BOOST_PP_WHILE_148_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_149, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(149, s))
+# define BOOST_PP_WHILE_149_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_150, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(150, s))
+# define BOOST_PP_WHILE_150_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_151, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(151, s))
+# define BOOST_PP_WHILE_151_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_152, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(152, s))
+# define BOOST_PP_WHILE_152_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_153, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(153, s))
+# define BOOST_PP_WHILE_153_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_154, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(154, s))
+# define BOOST_PP_WHILE_154_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_155, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(155, s))
+# define BOOST_PP_WHILE_155_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_156, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(156, s))
+# define BOOST_PP_WHILE_156_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_157, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(157, s))
+# define BOOST_PP_WHILE_157_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_158, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(158, s))
+# define BOOST_PP_WHILE_158_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_159, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(159, s))
+# define BOOST_PP_WHILE_159_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_160, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(160, s))
+# define BOOST_PP_WHILE_160_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_161, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(161, s))
+# define BOOST_PP_WHILE_161_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_162, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(162, s))
+# define BOOST_PP_WHILE_162_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_163, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(163, s))
+# define BOOST_PP_WHILE_163_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_164, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(164, s))
+# define BOOST_PP_WHILE_164_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_165, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(165, s))
+# define BOOST_PP_WHILE_165_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_166, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(166, s))
+# define BOOST_PP_WHILE_166_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_167, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(167, s))
+# define BOOST_PP_WHILE_167_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_168, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(168, s))
+# define BOOST_PP_WHILE_168_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_169, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(169, s))
+# define BOOST_PP_WHILE_169_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_170, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(170, s))
+# define BOOST_PP_WHILE_170_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_171, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(171, s))
+# define BOOST_PP_WHILE_171_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_172, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(172, s))
+# define BOOST_PP_WHILE_172_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_173, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(173, s))
+# define BOOST_PP_WHILE_173_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_174, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(174, s))
+# define BOOST_PP_WHILE_174_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_175, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(175, s))
+# define BOOST_PP_WHILE_175_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_176, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(176, s))
+# define BOOST_PP_WHILE_176_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_177, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(177, s))
+# define BOOST_PP_WHILE_177_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_178, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(178, s))
+# define BOOST_PP_WHILE_178_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_179, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(179, s))
+# define BOOST_PP_WHILE_179_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_180, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(180, s))
+# define BOOST_PP_WHILE_180_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_181, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(181, s))
+# define BOOST_PP_WHILE_181_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_182, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(182, s))
+# define BOOST_PP_WHILE_182_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_183, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(183, s))
+# define BOOST_PP_WHILE_183_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_184, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(184, s))
+# define BOOST_PP_WHILE_184_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_185, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(185, s))
+# define BOOST_PP_WHILE_185_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_186, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(186, s))
+# define BOOST_PP_WHILE_186_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_187, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(187, s))
+# define BOOST_PP_WHILE_187_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_188, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(188, s))
+# define BOOST_PP_WHILE_188_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_189, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(189, s))
+# define BOOST_PP_WHILE_189_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_190, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(190, s))
+# define BOOST_PP_WHILE_190_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_191, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(191, s))
+# define BOOST_PP_WHILE_191_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_192, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(192, s))
+# define BOOST_PP_WHILE_192_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_193, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(193, s))
+# define BOOST_PP_WHILE_193_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_194, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(194, s))
+# define BOOST_PP_WHILE_194_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_195, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(195, s))
+# define BOOST_PP_WHILE_195_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_196, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(196, s))
+# define BOOST_PP_WHILE_196_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_197, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(197, s))
+# define BOOST_PP_WHILE_197_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_198, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(198, s))
+# define BOOST_PP_WHILE_198_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_199, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(199, s))
+# define BOOST_PP_WHILE_199_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_200, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(200, s))
+# define BOOST_PP_WHILE_200_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_201, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(201, s))
+# define BOOST_PP_WHILE_201_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_202, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(202, s))
+# define BOOST_PP_WHILE_202_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_203, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(203, s))
+# define BOOST_PP_WHILE_203_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_204, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(204, s))
+# define BOOST_PP_WHILE_204_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_205, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(205, s))
+# define BOOST_PP_WHILE_205_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_206, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(206, s))
+# define BOOST_PP_WHILE_206_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_207, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(207, s))
+# define BOOST_PP_WHILE_207_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_208, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(208, s))
+# define BOOST_PP_WHILE_208_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_209, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(209, s))
+# define BOOST_PP_WHILE_209_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_210, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(210, s))
+# define BOOST_PP_WHILE_210_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_211, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(211, s))
+# define BOOST_PP_WHILE_211_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_212, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(212, s))
+# define BOOST_PP_WHILE_212_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_213, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(213, s))
+# define BOOST_PP_WHILE_213_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_214, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(214, s))
+# define BOOST_PP_WHILE_214_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_215, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(215, s))
+# define BOOST_PP_WHILE_215_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_216, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(216, s))
+# define BOOST_PP_WHILE_216_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_217, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(217, s))
+# define BOOST_PP_WHILE_217_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_218, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(218, s))
+# define BOOST_PP_WHILE_218_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_219, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(219, s))
+# define BOOST_PP_WHILE_219_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_220, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(220, s))
+# define BOOST_PP_WHILE_220_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_221, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(221, s))
+# define BOOST_PP_WHILE_221_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_222, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(222, s))
+# define BOOST_PP_WHILE_222_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_223, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(223, s))
+# define BOOST_PP_WHILE_223_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_224, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(224, s))
+# define BOOST_PP_WHILE_224_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_225, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(225, s))
+# define BOOST_PP_WHILE_225_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_226, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(226, s))
+# define BOOST_PP_WHILE_226_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_227, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(227, s))
+# define BOOST_PP_WHILE_227_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_228, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(228, s))
+# define BOOST_PP_WHILE_228_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_229, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(229, s))
+# define BOOST_PP_WHILE_229_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_230, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(230, s))
+# define BOOST_PP_WHILE_230_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_231, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(231, s))
+# define BOOST_PP_WHILE_231_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_232, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(232, s))
+# define BOOST_PP_WHILE_232_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_233, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(233, s))
+# define BOOST_PP_WHILE_233_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_234, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(234, s))
+# define BOOST_PP_WHILE_234_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_235, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(235, s))
+# define BOOST_PP_WHILE_235_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_236, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(236, s))
+# define BOOST_PP_WHILE_236_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_237, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(237, s))
+# define BOOST_PP_WHILE_237_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_238, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(238, s))
+# define BOOST_PP_WHILE_238_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_239, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(239, s))
+# define BOOST_PP_WHILE_239_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_240, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(240, s))
+# define BOOST_PP_WHILE_240_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_241, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(241, s))
+# define BOOST_PP_WHILE_241_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_242, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(242, s))
+# define BOOST_PP_WHILE_242_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_243, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(243, s))
+# define BOOST_PP_WHILE_243_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_244, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(244, s))
+# define BOOST_PP_WHILE_244_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_245, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(245, s))
+# define BOOST_PP_WHILE_245_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_246, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(246, s))
+# define BOOST_PP_WHILE_246_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_247, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(247, s))
+# define BOOST_PP_WHILE_247_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_248, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(248, s))
+# define BOOST_PP_WHILE_248_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_249, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(249, s))
+# define BOOST_PP_WHILE_249_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_250, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(250, s))
+# define BOOST_PP_WHILE_250_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_251, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(251, s))
+# define BOOST_PP_WHILE_251_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_252, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(252, s))
+# define BOOST_PP_WHILE_252_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_253, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(253, s))
+# define BOOST_PP_WHILE_253_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_254, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(254, s))
+# define BOOST_PP_WHILE_254_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_255, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(255, s))
+# define BOOST_PP_WHILE_255_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_256, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(256, s))
+# define BOOST_PP_WHILE_256_C(c, p, o, s) BOOST_PP_IIF(c, BOOST_PP_WHILE_257, s BOOST_PP_TUPLE_EAT_3)(p, o, BOOST_PP_IIF(c, o, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_2)(257, s))
+#
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/control/expr_if.hpp b/third_party/boost/boost/preprocessor/control/expr_if.hpp
new file mode 100644
index 0000000..0e1ab51
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/control/expr_if.hpp
@@ -0,0 +1,30 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_CONTROL_EXPR_IF_HPP
+# define BOOST_PREPROCESSOR_CONTROL_EXPR_IF_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/control/expr_iif.hpp>
+# include <boost/preprocessor/logical/bool.hpp>
+#
+# /* BOOST_PP_EXPR_IF */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_EXPR_IF(cond, expr) BOOST_PP_EXPR_IIF(BOOST_PP_BOOL(cond), expr)
+# else
+# define BOOST_PP_EXPR_IF(cond, expr) BOOST_PP_EXPR_IF_I(cond, expr)
+# define BOOST_PP_EXPR_IF_I(cond, expr) BOOST_PP_EXPR_IIF(BOOST_PP_BOOL(cond), expr)
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/control/expr_iif.hpp b/third_party/boost/boost/preprocessor/control/expr_iif.hpp
new file mode 100644
index 0000000..58f45a4
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/control/expr_iif.hpp
@@ -0,0 +1,31 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_CONTROL_EXPR_IIF_HPP
+# define BOOST_PREPROCESSOR_CONTROL_EXPR_IIF_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+#
+# /* BOOST_PP_EXPR_IIF */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MWCC()
+# define BOOST_PP_EXPR_IIF(bit, expr) BOOST_PP_EXPR_IIF_I(bit, expr)
+# else
+# define BOOST_PP_EXPR_IIF(bit, expr) BOOST_PP_EXPR_IIF_OO((bit, expr))
+# define BOOST_PP_EXPR_IIF_OO(par) BOOST_PP_EXPR_IIF_I ## par
+# endif
+#
+# define BOOST_PP_EXPR_IIF_I(bit, expr) BOOST_PP_EXPR_IIF_ ## bit(expr)
+#
+# define BOOST_PP_EXPR_IIF_0(expr)
+# define BOOST_PP_EXPR_IIF_1(expr) expr
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/control/if.hpp b/third_party/boost/boost/preprocessor/control/if.hpp
new file mode 100644
index 0000000..52cfc3d
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/control/if.hpp
@@ -0,0 +1,30 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_CONTROL_IF_HPP
+# define BOOST_PREPROCESSOR_CONTROL_IF_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/control/iif.hpp>
+# include <boost/preprocessor/logical/bool.hpp>
+#
+# /* BOOST_PP_IF */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_IF(cond, t, f) BOOST_PP_IIF(BOOST_PP_BOOL(cond), t, f)
+# else
+# define BOOST_PP_IF(cond, t, f) BOOST_PP_IF_I(cond, t, f)
+# define BOOST_PP_IF_I(cond, t, f) BOOST_PP_IIF(BOOST_PP_BOOL(cond), t, f)
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/control/iif.hpp b/third_party/boost/boost/preprocessor/control/iif.hpp
new file mode 100644
index 0000000..fd07817
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/control/iif.hpp
@@ -0,0 +1,34 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_CONTROL_IIF_HPP
+# define BOOST_PREPROCESSOR_CONTROL_IIF_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MWCC()
+# define BOOST_PP_IIF(bit, t, f) BOOST_PP_IIF_I(bit, t, f)
+# else
+# define BOOST_PP_IIF(bit, t, f) BOOST_PP_IIF_OO((bit, t, f))
+# define BOOST_PP_IIF_OO(par) BOOST_PP_IIF_I ## par
+# endif
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MSVC()
+# define BOOST_PP_IIF_I(bit, t, f) BOOST_PP_IIF_ ## bit(t, f)
+# else
+# define BOOST_PP_IIF_I(bit, t, f) BOOST_PP_IIF_II(BOOST_PP_IIF_ ## bit(t, f))
+# define BOOST_PP_IIF_II(id) id
+# endif
+#
+# define BOOST_PP_IIF_0(t, f) f
+# define BOOST_PP_IIF_1(t, f) t
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/control/while.hpp b/third_party/boost/boost/preprocessor/control/while.hpp
new file mode 100644
index 0000000..e8a65ff
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/control/while.hpp
@@ -0,0 +1,312 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_CONTROL_WHILE_HPP
+# define BOOST_PREPROCESSOR_CONTROL_WHILE_HPP
+#
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/debug/error.hpp>
+# include <boost/preprocessor/detail/auto_rec.hpp>
+# include <boost/preprocessor/list/fold_left.hpp>
+# include <boost/preprocessor/list/fold_right.hpp>
+# include <boost/preprocessor/logical/bitand.hpp>
+#
+# /* BOOST_PP_WHILE */
+#
+# if 0
+# define BOOST_PP_WHILE(pred, op, state)
+# endif
+#
+# define BOOST_PP_WHILE BOOST_PP_CAT(BOOST_PP_WHILE_, BOOST_PP_AUTO_REC(BOOST_PP_WHILE_P, 256))
+#
+# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_WHILE_P(n) BOOST_PP_BITAND(BOOST_PP_CAT(BOOST_PP_WHILE_CHECK_, BOOST_PP_WHILE_ ## n(BOOST_PP_WHILE_F, BOOST_PP_NIL, BOOST_PP_NIL)), BOOST_PP_BITAND(BOOST_PP_CAT(BOOST_PP_LIST_FOLD_LEFT_CHECK_, BOOST_PP_LIST_FOLD_LEFT_ ## n(BOOST_PP_NIL, BOOST_PP_NIL, BOOST_PP_NIL)), BOOST_PP_CAT(BOOST_PP_LIST_FOLD_RIGHT_CHECK_, BOOST_PP_LIST_FOLD_RIGHT_ ## n(BOOST_PP_NIL, BOOST_PP_NIL, BOOST_PP_NIL))))
+# else
+# define BOOST_PP_WHILE_P(n) BOOST_PP_BITAND(BOOST_PP_CAT(BOOST_PP_WHILE_CHECK_, BOOST_PP_WHILE_ ## n(BOOST_PP_WHILE_F, BOOST_PP_NIL, BOOST_PP_NIL)), BOOST_PP_CAT(BOOST_PP_LIST_FOLD_LEFT_CHECK_, BOOST_PP_LIST_FOLD_LEFT_ ## n(BOOST_PP_NIL, BOOST_PP_NIL, BOOST_PP_NIL)))
+# endif
+#
+# define BOOST_PP_WHILE_F(d, _) 0
+#
+# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# include <boost/preprocessor/control/detail/edg/while.hpp>
+# elif BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MSVC()
+# include <boost/preprocessor/control/detail/msvc/while.hpp>
+# elif BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_DMC()
+# include <boost/preprocessor/control/detail/dmc/while.hpp>
+# else
+# include <boost/preprocessor/control/detail/while.hpp>
+# endif
+#
+# define BOOST_PP_WHILE_257(p, o, s) BOOST_PP_ERROR(0x0001)
+#
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_NIL 1
+#
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_1(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_2(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_3(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_4(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_5(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_6(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_7(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_8(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_9(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_10(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_11(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_12(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_13(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_14(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_15(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_16(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_17(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_18(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_19(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_20(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_21(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_22(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_23(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_24(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_25(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_26(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_27(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_28(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_29(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_30(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_31(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_32(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_33(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_34(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_35(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_36(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_37(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_38(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_39(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_40(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_41(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_42(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_43(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_44(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_45(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_46(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_47(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_48(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_49(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_50(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_51(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_52(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_53(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_54(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_55(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_56(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_57(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_58(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_59(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_60(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_61(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_62(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_63(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_64(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_65(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_66(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_67(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_68(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_69(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_70(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_71(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_72(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_73(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_74(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_75(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_76(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_77(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_78(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_79(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_80(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_81(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_82(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_83(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_84(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_85(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_86(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_87(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_88(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_89(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_90(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_91(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_92(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_93(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_94(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_95(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_96(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_97(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_98(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_99(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_100(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_101(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_102(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_103(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_104(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_105(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_106(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_107(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_108(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_109(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_110(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_111(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_112(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_113(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_114(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_115(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_116(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_117(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_118(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_119(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_120(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_121(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_122(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_123(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_124(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_125(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_126(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_127(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_128(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_129(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_130(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_131(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_132(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_133(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_134(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_135(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_136(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_137(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_138(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_139(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_140(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_141(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_142(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_143(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_144(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_145(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_146(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_147(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_148(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_149(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_150(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_151(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_152(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_153(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_154(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_155(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_156(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_157(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_158(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_159(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_160(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_161(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_162(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_163(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_164(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_165(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_166(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_167(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_168(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_169(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_170(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_171(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_172(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_173(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_174(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_175(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_176(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_177(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_178(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_179(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_180(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_181(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_182(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_183(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_184(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_185(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_186(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_187(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_188(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_189(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_190(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_191(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_192(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_193(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_194(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_195(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_196(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_197(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_198(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_199(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_200(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_201(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_202(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_203(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_204(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_205(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_206(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_207(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_208(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_209(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_210(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_211(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_212(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_213(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_214(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_215(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_216(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_217(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_218(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_219(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_220(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_221(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_222(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_223(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_224(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_225(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_226(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_227(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_228(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_229(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_230(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_231(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_232(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_233(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_234(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_235(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_236(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_237(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_238(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_239(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_240(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_241(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_242(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_243(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_244(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_245(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_246(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_247(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_248(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_249(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_250(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_251(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_252(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_253(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_254(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_255(p, o, s) 0
+# define BOOST_PP_WHILE_CHECK_BOOST_PP_WHILE_256(p, o, s) 0
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/debug/error.hpp b/third_party/boost/boost/preprocessor/debug/error.hpp
new file mode 100644
index 0000000..c8ae5e7
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/debug/error.hpp
@@ -0,0 +1,33 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_DEBUG_ERROR_HPP
+# define BOOST_PREPROCESSOR_DEBUG_ERROR_HPP
+#
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/config/config.hpp>
+#
+# /* BOOST_PP_ERROR */
+#
+# if BOOST_PP_CONFIG_ERRORS
+# define BOOST_PP_ERROR(code) BOOST_PP_CAT(BOOST_PP_ERROR_, code)
+# endif
+#
+# define BOOST_PP_ERROR_0x0000 BOOST_PP_ERROR(0x0000, BOOST_PP_INDEX_OUT_OF_BOUNDS)
+# define BOOST_PP_ERROR_0x0001 BOOST_PP_ERROR(0x0001, BOOST_PP_WHILE_OVERFLOW)
+# define BOOST_PP_ERROR_0x0002 BOOST_PP_ERROR(0x0002, BOOST_PP_FOR_OVERFLOW)
+# define BOOST_PP_ERROR_0x0003 BOOST_PP_ERROR(0x0003, BOOST_PP_REPEAT_OVERFLOW)
+# define BOOST_PP_ERROR_0x0004 BOOST_PP_ERROR(0x0004, BOOST_PP_LIST_FOLD_OVERFLOW)
+# define BOOST_PP_ERROR_0x0005 BOOST_PP_ERROR(0x0005, BOOST_PP_SEQ_FOLD_OVERFLOW)
+# define BOOST_PP_ERROR_0x0006 BOOST_PP_ERROR(0x0006, BOOST_PP_ARITHMETIC_OVERFLOW)
+# define BOOST_PP_ERROR_0x0007 BOOST_PP_ERROR(0x0007, BOOST_PP_DIVISION_BY_ZERO)
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/detail/auto_rec.hpp b/third_party/boost/boost/preprocessor/detail/auto_rec.hpp
new file mode 100644
index 0000000..39de1d0
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/detail/auto_rec.hpp
@@ -0,0 +1,293 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# include <boost/preprocessor/config/config.hpp>
+#
+# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_DMC()
+# include <boost/preprocessor/detail/dmc/auto_rec.hpp>
+# else
+#
+# ifndef BOOST_PREPROCESSOR_DETAIL_AUTO_REC_HPP
+# define BOOST_PREPROCESSOR_DETAIL_AUTO_REC_HPP
+#
+# include <boost/preprocessor/control/iif.hpp>
+#
+# /* BOOST_PP_AUTO_REC */
+#
+# define BOOST_PP_AUTO_REC(pred, n) BOOST_PP_NODE_ENTRY_ ## n(pred)
+#
+# define BOOST_PP_NODE_ENTRY_256(p) BOOST_PP_NODE_128(p)(p)(p)(p)(p)(p)(p)(p)
+# define BOOST_PP_NODE_ENTRY_128(p) BOOST_PP_NODE_64(p)(p)(p)(p)(p)(p)(p)
+# define BOOST_PP_NODE_ENTRY_64(p) BOOST_PP_NODE_32(p)(p)(p)(p)(p)(p)
+# define BOOST_PP_NODE_ENTRY_32(p) BOOST_PP_NODE_16(p)(p)(p)(p)(p)
+# define BOOST_PP_NODE_ENTRY_16(p) BOOST_PP_NODE_8(p)(p)(p)(p)
+# define BOOST_PP_NODE_ENTRY_8(p) BOOST_PP_NODE_4(p)(p)(p)
+# define BOOST_PP_NODE_ENTRY_4(p) BOOST_PP_NODE_2(p)(p)
+# define BOOST_PP_NODE_ENTRY_2(p) BOOST_PP_NODE_1(p)
+#
+# define BOOST_PP_NODE_128(p) BOOST_PP_IIF(p(128), BOOST_PP_NODE_64, BOOST_PP_NODE_192)
+# define BOOST_PP_NODE_64(p) BOOST_PP_IIF(p(64), BOOST_PP_NODE_32, BOOST_PP_NODE_96)
+# define BOOST_PP_NODE_32(p) BOOST_PP_IIF(p(32), BOOST_PP_NODE_16, BOOST_PP_NODE_48)
+# define BOOST_PP_NODE_16(p) BOOST_PP_IIF(p(16), BOOST_PP_NODE_8, BOOST_PP_NODE_24)
+# define BOOST_PP_NODE_8(p) BOOST_PP_IIF(p(8), BOOST_PP_NODE_4, BOOST_PP_NODE_12)
+# define BOOST_PP_NODE_4(p) BOOST_PP_IIF(p(4), BOOST_PP_NODE_2, BOOST_PP_NODE_6)
+# define BOOST_PP_NODE_2(p) BOOST_PP_IIF(p(2), BOOST_PP_NODE_1, BOOST_PP_NODE_3)
+# define BOOST_PP_NODE_1(p) BOOST_PP_IIF(p(1), 1, 2)
+# define BOOST_PP_NODE_3(p) BOOST_PP_IIF(p(3), 3, 4)
+# define BOOST_PP_NODE_6(p) BOOST_PP_IIF(p(6), BOOST_PP_NODE_5, BOOST_PP_NODE_7)
+# define BOOST_PP_NODE_5(p) BOOST_PP_IIF(p(5), 5, 6)
+# define BOOST_PP_NODE_7(p) BOOST_PP_IIF(p(7), 7, 8)
+# define BOOST_PP_NODE_12(p) BOOST_PP_IIF(p(12), BOOST_PP_NODE_10, BOOST_PP_NODE_14)
+# define BOOST_PP_NODE_10(p) BOOST_PP_IIF(p(10), BOOST_PP_NODE_9, BOOST_PP_NODE_11)
+# define BOOST_PP_NODE_9(p) BOOST_PP_IIF(p(9), 9, 10)
+# define BOOST_PP_NODE_11(p) BOOST_PP_IIF(p(11), 11, 12)
+# define BOOST_PP_NODE_14(p) BOOST_PP_IIF(p(14), BOOST_PP_NODE_13, BOOST_PP_NODE_15)
+# define BOOST_PP_NODE_13(p) BOOST_PP_IIF(p(13), 13, 14)
+# define BOOST_PP_NODE_15(p) BOOST_PP_IIF(p(15), 15, 16)
+# define BOOST_PP_NODE_24(p) BOOST_PP_IIF(p(24), BOOST_PP_NODE_20, BOOST_PP_NODE_28)
+# define BOOST_PP_NODE_20(p) BOOST_PP_IIF(p(20), BOOST_PP_NODE_18, BOOST_PP_NODE_22)
+# define BOOST_PP_NODE_18(p) BOOST_PP_IIF(p(18), BOOST_PP_NODE_17, BOOST_PP_NODE_19)
+# define BOOST_PP_NODE_17(p) BOOST_PP_IIF(p(17), 17, 18)
+# define BOOST_PP_NODE_19(p) BOOST_PP_IIF(p(19), 19, 20)
+# define BOOST_PP_NODE_22(p) BOOST_PP_IIF(p(22), BOOST_PP_NODE_21, BOOST_PP_NODE_23)
+# define BOOST_PP_NODE_21(p) BOOST_PP_IIF(p(21), 21, 22)
+# define BOOST_PP_NODE_23(p) BOOST_PP_IIF(p(23), 23, 24)
+# define BOOST_PP_NODE_28(p) BOOST_PP_IIF(p(28), BOOST_PP_NODE_26, BOOST_PP_NODE_30)
+# define BOOST_PP_NODE_26(p) BOOST_PP_IIF(p(26), BOOST_PP_NODE_25, BOOST_PP_NODE_27)
+# define BOOST_PP_NODE_25(p) BOOST_PP_IIF(p(25), 25, 26)
+# define BOOST_PP_NODE_27(p) BOOST_PP_IIF(p(27), 27, 28)
+# define BOOST_PP_NODE_30(p) BOOST_PP_IIF(p(30), BOOST_PP_NODE_29, BOOST_PP_NODE_31)
+# define BOOST_PP_NODE_29(p) BOOST_PP_IIF(p(29), 29, 30)
+# define BOOST_PP_NODE_31(p) BOOST_PP_IIF(p(31), 31, 32)
+# define BOOST_PP_NODE_48(p) BOOST_PP_IIF(p(48), BOOST_PP_NODE_40, BOOST_PP_NODE_56)
+# define BOOST_PP_NODE_40(p) BOOST_PP_IIF(p(40), BOOST_PP_NODE_36, BOOST_PP_NODE_44)
+# define BOOST_PP_NODE_36(p) BOOST_PP_IIF(p(36), BOOST_PP_NODE_34, BOOST_PP_NODE_38)
+# define BOOST_PP_NODE_34(p) BOOST_PP_IIF(p(34), BOOST_PP_NODE_33, BOOST_PP_NODE_35)
+# define BOOST_PP_NODE_33(p) BOOST_PP_IIF(p(33), 33, 34)
+# define BOOST_PP_NODE_35(p) BOOST_PP_IIF(p(35), 35, 36)
+# define BOOST_PP_NODE_38(p) BOOST_PP_IIF(p(38), BOOST_PP_NODE_37, BOOST_PP_NODE_39)
+# define BOOST_PP_NODE_37(p) BOOST_PP_IIF(p(37), 37, 38)
+# define BOOST_PP_NODE_39(p) BOOST_PP_IIF(p(39), 39, 40)
+# define BOOST_PP_NODE_44(p) BOOST_PP_IIF(p(44), BOOST_PP_NODE_42, BOOST_PP_NODE_46)
+# define BOOST_PP_NODE_42(p) BOOST_PP_IIF(p(42), BOOST_PP_NODE_41, BOOST_PP_NODE_43)
+# define BOOST_PP_NODE_41(p) BOOST_PP_IIF(p(41), 41, 42)
+# define BOOST_PP_NODE_43(p) BOOST_PP_IIF(p(43), 43, 44)
+# define BOOST_PP_NODE_46(p) BOOST_PP_IIF(p(46), BOOST_PP_NODE_45, BOOST_PP_NODE_47)
+# define BOOST_PP_NODE_45(p) BOOST_PP_IIF(p(45), 45, 46)
+# define BOOST_PP_NODE_47(p) BOOST_PP_IIF(p(47), 47, 48)
+# define BOOST_PP_NODE_56(p) BOOST_PP_IIF(p(56), BOOST_PP_NODE_52, BOOST_PP_NODE_60)
+# define BOOST_PP_NODE_52(p) BOOST_PP_IIF(p(52), BOOST_PP_NODE_50, BOOST_PP_NODE_54)
+# define BOOST_PP_NODE_50(p) BOOST_PP_IIF(p(50), BOOST_PP_NODE_49, BOOST_PP_NODE_51)
+# define BOOST_PP_NODE_49(p) BOOST_PP_IIF(p(49), 49, 50)
+# define BOOST_PP_NODE_51(p) BOOST_PP_IIF(p(51), 51, 52)
+# define BOOST_PP_NODE_54(p) BOOST_PP_IIF(p(54), BOOST_PP_NODE_53, BOOST_PP_NODE_55)
+# define BOOST_PP_NODE_53(p) BOOST_PP_IIF(p(53), 53, 54)
+# define BOOST_PP_NODE_55(p) BOOST_PP_IIF(p(55), 55, 56)
+# define BOOST_PP_NODE_60(p) BOOST_PP_IIF(p(60), BOOST_PP_NODE_58, BOOST_PP_NODE_62)
+# define BOOST_PP_NODE_58(p) BOOST_PP_IIF(p(58), BOOST_PP_NODE_57, BOOST_PP_NODE_59)
+# define BOOST_PP_NODE_57(p) BOOST_PP_IIF(p(57), 57, 58)
+# define BOOST_PP_NODE_59(p) BOOST_PP_IIF(p(59), 59, 60)
+# define BOOST_PP_NODE_62(p) BOOST_PP_IIF(p(62), BOOST_PP_NODE_61, BOOST_PP_NODE_63)
+# define BOOST_PP_NODE_61(p) BOOST_PP_IIF(p(61), 61, 62)
+# define BOOST_PP_NODE_63(p) BOOST_PP_IIF(p(63), 63, 64)
+# define BOOST_PP_NODE_96(p) BOOST_PP_IIF(p(96), BOOST_PP_NODE_80, BOOST_PP_NODE_112)
+# define BOOST_PP_NODE_80(p) BOOST_PP_IIF(p(80), BOOST_PP_NODE_72, BOOST_PP_NODE_88)
+# define BOOST_PP_NODE_72(p) BOOST_PP_IIF(p(72), BOOST_PP_NODE_68, BOOST_PP_NODE_76)
+# define BOOST_PP_NODE_68(p) BOOST_PP_IIF(p(68), BOOST_PP_NODE_66, BOOST_PP_NODE_70)
+# define BOOST_PP_NODE_66(p) BOOST_PP_IIF(p(66), BOOST_PP_NODE_65, BOOST_PP_NODE_67)
+# define BOOST_PP_NODE_65(p) BOOST_PP_IIF(p(65), 65, 66)
+# define BOOST_PP_NODE_67(p) BOOST_PP_IIF(p(67), 67, 68)
+# define BOOST_PP_NODE_70(p) BOOST_PP_IIF(p(70), BOOST_PP_NODE_69, BOOST_PP_NODE_71)
+# define BOOST_PP_NODE_69(p) BOOST_PP_IIF(p(69), 69, 70)
+# define BOOST_PP_NODE_71(p) BOOST_PP_IIF(p(71), 71, 72)
+# define BOOST_PP_NODE_76(p) BOOST_PP_IIF(p(76), BOOST_PP_NODE_74, BOOST_PP_NODE_78)
+# define BOOST_PP_NODE_74(p) BOOST_PP_IIF(p(74), BOOST_PP_NODE_73, BOOST_PP_NODE_75)
+# define BOOST_PP_NODE_73(p) BOOST_PP_IIF(p(73), 73, 74)
+# define BOOST_PP_NODE_75(p) BOOST_PP_IIF(p(75), 75, 76)
+# define BOOST_PP_NODE_78(p) BOOST_PP_IIF(p(78), BOOST_PP_NODE_77, BOOST_PP_NODE_79)
+# define BOOST_PP_NODE_77(p) BOOST_PP_IIF(p(77), 77, 78)
+# define BOOST_PP_NODE_79(p) BOOST_PP_IIF(p(79), 79, 80)
+# define BOOST_PP_NODE_88(p) BOOST_PP_IIF(p(88), BOOST_PP_NODE_84, BOOST_PP_NODE_92)
+# define BOOST_PP_NODE_84(p) BOOST_PP_IIF(p(84), BOOST_PP_NODE_82, BOOST_PP_NODE_86)
+# define BOOST_PP_NODE_82(p) BOOST_PP_IIF(p(82), BOOST_PP_NODE_81, BOOST_PP_NODE_83)
+# define BOOST_PP_NODE_81(p) BOOST_PP_IIF(p(81), 81, 82)
+# define BOOST_PP_NODE_83(p) BOOST_PP_IIF(p(83), 83, 84)
+# define BOOST_PP_NODE_86(p) BOOST_PP_IIF(p(86), BOOST_PP_NODE_85, BOOST_PP_NODE_87)
+# define BOOST_PP_NODE_85(p) BOOST_PP_IIF(p(85), 85, 86)
+# define BOOST_PP_NODE_87(p) BOOST_PP_IIF(p(87), 87, 88)
+# define BOOST_PP_NODE_92(p) BOOST_PP_IIF(p(92), BOOST_PP_NODE_90, BOOST_PP_NODE_94)
+# define BOOST_PP_NODE_90(p) BOOST_PP_IIF(p(90), BOOST_PP_NODE_89, BOOST_PP_NODE_91)
+# define BOOST_PP_NODE_89(p) BOOST_PP_IIF(p(89), 89, 90)
+# define BOOST_PP_NODE_91(p) BOOST_PP_IIF(p(91), 91, 92)
+# define BOOST_PP_NODE_94(p) BOOST_PP_IIF(p(94), BOOST_PP_NODE_93, BOOST_PP_NODE_95)
+# define BOOST_PP_NODE_93(p) BOOST_PP_IIF(p(93), 93, 94)
+# define BOOST_PP_NODE_95(p) BOOST_PP_IIF(p(95), 95, 96)
+# define BOOST_PP_NODE_112(p) BOOST_PP_IIF(p(112), BOOST_PP_NODE_104, BOOST_PP_NODE_120)
+# define BOOST_PP_NODE_104(p) BOOST_PP_IIF(p(104), BOOST_PP_NODE_100, BOOST_PP_NODE_108)
+# define BOOST_PP_NODE_100(p) BOOST_PP_IIF(p(100), BOOST_PP_NODE_98, BOOST_PP_NODE_102)
+# define BOOST_PP_NODE_98(p) BOOST_PP_IIF(p(98), BOOST_PP_NODE_97, BOOST_PP_NODE_99)
+# define BOOST_PP_NODE_97(p) BOOST_PP_IIF(p(97), 97, 98)
+# define BOOST_PP_NODE_99(p) BOOST_PP_IIF(p(99), 99, 100)
+# define BOOST_PP_NODE_102(p) BOOST_PP_IIF(p(102), BOOST_PP_NODE_101, BOOST_PP_NODE_103)
+# define BOOST_PP_NODE_101(p) BOOST_PP_IIF(p(101), 101, 102)
+# define BOOST_PP_NODE_103(p) BOOST_PP_IIF(p(103), 103, 104)
+# define BOOST_PP_NODE_108(p) BOOST_PP_IIF(p(108), BOOST_PP_NODE_106, BOOST_PP_NODE_110)
+# define BOOST_PP_NODE_106(p) BOOST_PP_IIF(p(106), BOOST_PP_NODE_105, BOOST_PP_NODE_107)
+# define BOOST_PP_NODE_105(p) BOOST_PP_IIF(p(105), 105, 106)
+# define BOOST_PP_NODE_107(p) BOOST_PP_IIF(p(107), 107, 108)
+# define BOOST_PP_NODE_110(p) BOOST_PP_IIF(p(110), BOOST_PP_NODE_109, BOOST_PP_NODE_111)
+# define BOOST_PP_NODE_109(p) BOOST_PP_IIF(p(109), 109, 110)
+# define BOOST_PP_NODE_111(p) BOOST_PP_IIF(p(111), 111, 112)
+# define BOOST_PP_NODE_120(p) BOOST_PP_IIF(p(120), BOOST_PP_NODE_116, BOOST_PP_NODE_124)
+# define BOOST_PP_NODE_116(p) BOOST_PP_IIF(p(116), BOOST_PP_NODE_114, BOOST_PP_NODE_118)
+# define BOOST_PP_NODE_114(p) BOOST_PP_IIF(p(114), BOOST_PP_NODE_113, BOOST_PP_NODE_115)
+# define BOOST_PP_NODE_113(p) BOOST_PP_IIF(p(113), 113, 114)
+# define BOOST_PP_NODE_115(p) BOOST_PP_IIF(p(115), 115, 116)
+# define BOOST_PP_NODE_118(p) BOOST_PP_IIF(p(118), BOOST_PP_NODE_117, BOOST_PP_NODE_119)
+# define BOOST_PP_NODE_117(p) BOOST_PP_IIF(p(117), 117, 118)
+# define BOOST_PP_NODE_119(p) BOOST_PP_IIF(p(119), 119, 120)
+# define BOOST_PP_NODE_124(p) BOOST_PP_IIF(p(124), BOOST_PP_NODE_122, BOOST_PP_NODE_126)
+# define BOOST_PP_NODE_122(p) BOOST_PP_IIF(p(122), BOOST_PP_NODE_121, BOOST_PP_NODE_123)
+# define BOOST_PP_NODE_121(p) BOOST_PP_IIF(p(121), 121, 122)
+# define BOOST_PP_NODE_123(p) BOOST_PP_IIF(p(123), 123, 124)
+# define BOOST_PP_NODE_126(p) BOOST_PP_IIF(p(126), BOOST_PP_NODE_125, BOOST_PP_NODE_127)
+# define BOOST_PP_NODE_125(p) BOOST_PP_IIF(p(125), 125, 126)
+# define BOOST_PP_NODE_127(p) BOOST_PP_IIF(p(127), 127, 128)
+# define BOOST_PP_NODE_192(p) BOOST_PP_IIF(p(192), BOOST_PP_NODE_160, BOOST_PP_NODE_224)
+# define BOOST_PP_NODE_160(p) BOOST_PP_IIF(p(160), BOOST_PP_NODE_144, BOOST_PP_NODE_176)
+# define BOOST_PP_NODE_144(p) BOOST_PP_IIF(p(144), BOOST_PP_NODE_136, BOOST_PP_NODE_152)
+# define BOOST_PP_NODE_136(p) BOOST_PP_IIF(p(136), BOOST_PP_NODE_132, BOOST_PP_NODE_140)
+# define BOOST_PP_NODE_132(p) BOOST_PP_IIF(p(132), BOOST_PP_NODE_130, BOOST_PP_NODE_134)
+# define BOOST_PP_NODE_130(p) BOOST_PP_IIF(p(130), BOOST_PP_NODE_129, BOOST_PP_NODE_131)
+# define BOOST_PP_NODE_129(p) BOOST_PP_IIF(p(129), 129, 130)
+# define BOOST_PP_NODE_131(p) BOOST_PP_IIF(p(131), 131, 132)
+# define BOOST_PP_NODE_134(p) BOOST_PP_IIF(p(134), BOOST_PP_NODE_133, BOOST_PP_NODE_135)
+# define BOOST_PP_NODE_133(p) BOOST_PP_IIF(p(133), 133, 134)
+# define BOOST_PP_NODE_135(p) BOOST_PP_IIF(p(135), 135, 136)
+# define BOOST_PP_NODE_140(p) BOOST_PP_IIF(p(140), BOOST_PP_NODE_138, BOOST_PP_NODE_142)
+# define BOOST_PP_NODE_138(p) BOOST_PP_IIF(p(138), BOOST_PP_NODE_137, BOOST_PP_NODE_139)
+# define BOOST_PP_NODE_137(p) BOOST_PP_IIF(p(137), 137, 138)
+# define BOOST_PP_NODE_139(p) BOOST_PP_IIF(p(139), 139, 140)
+# define BOOST_PP_NODE_142(p) BOOST_PP_IIF(p(142), BOOST_PP_NODE_141, BOOST_PP_NODE_143)
+# define BOOST_PP_NODE_141(p) BOOST_PP_IIF(p(141), 141, 142)
+# define BOOST_PP_NODE_143(p) BOOST_PP_IIF(p(143), 143, 144)
+# define BOOST_PP_NODE_152(p) BOOST_PP_IIF(p(152), BOOST_PP_NODE_148, BOOST_PP_NODE_156)
+# define BOOST_PP_NODE_148(p) BOOST_PP_IIF(p(148), BOOST_PP_NODE_146, BOOST_PP_NODE_150)
+# define BOOST_PP_NODE_146(p) BOOST_PP_IIF(p(146), BOOST_PP_NODE_145, BOOST_PP_NODE_147)
+# define BOOST_PP_NODE_145(p) BOOST_PP_IIF(p(145), 145, 146)
+# define BOOST_PP_NODE_147(p) BOOST_PP_IIF(p(147), 147, 148)
+# define BOOST_PP_NODE_150(p) BOOST_PP_IIF(p(150), BOOST_PP_NODE_149, BOOST_PP_NODE_151)
+# define BOOST_PP_NODE_149(p) BOOST_PP_IIF(p(149), 149, 150)
+# define BOOST_PP_NODE_151(p) BOOST_PP_IIF(p(151), 151, 152)
+# define BOOST_PP_NODE_156(p) BOOST_PP_IIF(p(156), BOOST_PP_NODE_154, BOOST_PP_NODE_158)
+# define BOOST_PP_NODE_154(p) BOOST_PP_IIF(p(154), BOOST_PP_NODE_153, BOOST_PP_NODE_155)
+# define BOOST_PP_NODE_153(p) BOOST_PP_IIF(p(153), 153, 154)
+# define BOOST_PP_NODE_155(p) BOOST_PP_IIF(p(155), 155, 156)
+# define BOOST_PP_NODE_158(p) BOOST_PP_IIF(p(158), BOOST_PP_NODE_157, BOOST_PP_NODE_159)
+# define BOOST_PP_NODE_157(p) BOOST_PP_IIF(p(157), 157, 158)
+# define BOOST_PP_NODE_159(p) BOOST_PP_IIF(p(159), 159, 160)
+# define BOOST_PP_NODE_176(p) BOOST_PP_IIF(p(176), BOOST_PP_NODE_168, BOOST_PP_NODE_184)
+# define BOOST_PP_NODE_168(p) BOOST_PP_IIF(p(168), BOOST_PP_NODE_164, BOOST_PP_NODE_172)
+# define BOOST_PP_NODE_164(p) BOOST_PP_IIF(p(164), BOOST_PP_NODE_162, BOOST_PP_NODE_166)
+# define BOOST_PP_NODE_162(p) BOOST_PP_IIF(p(162), BOOST_PP_NODE_161, BOOST_PP_NODE_163)
+# define BOOST_PP_NODE_161(p) BOOST_PP_IIF(p(161), 161, 162)
+# define BOOST_PP_NODE_163(p) BOOST_PP_IIF(p(163), 163, 164)
+# define BOOST_PP_NODE_166(p) BOOST_PP_IIF(p(166), BOOST_PP_NODE_165, BOOST_PP_NODE_167)
+# define BOOST_PP_NODE_165(p) BOOST_PP_IIF(p(165), 165, 166)
+# define BOOST_PP_NODE_167(p) BOOST_PP_IIF(p(167), 167, 168)
+# define BOOST_PP_NODE_172(p) BOOST_PP_IIF(p(172), BOOST_PP_NODE_170, BOOST_PP_NODE_174)
+# define BOOST_PP_NODE_170(p) BOOST_PP_IIF(p(170), BOOST_PP_NODE_169, BOOST_PP_NODE_171)
+# define BOOST_PP_NODE_169(p) BOOST_PP_IIF(p(169), 169, 170)
+# define BOOST_PP_NODE_171(p) BOOST_PP_IIF(p(171), 171, 172)
+# define BOOST_PP_NODE_174(p) BOOST_PP_IIF(p(174), BOOST_PP_NODE_173, BOOST_PP_NODE_175)
+# define BOOST_PP_NODE_173(p) BOOST_PP_IIF(p(173), 173, 174)
+# define BOOST_PP_NODE_175(p) BOOST_PP_IIF(p(175), 175, 176)
+# define BOOST_PP_NODE_184(p) BOOST_PP_IIF(p(184), BOOST_PP_NODE_180, BOOST_PP_NODE_188)
+# define BOOST_PP_NODE_180(p) BOOST_PP_IIF(p(180), BOOST_PP_NODE_178, BOOST_PP_NODE_182)
+# define BOOST_PP_NODE_178(p) BOOST_PP_IIF(p(178), BOOST_PP_NODE_177, BOOST_PP_NODE_179)
+# define BOOST_PP_NODE_177(p) BOOST_PP_IIF(p(177), 177, 178)
+# define BOOST_PP_NODE_179(p) BOOST_PP_IIF(p(179), 179, 180)
+# define BOOST_PP_NODE_182(p) BOOST_PP_IIF(p(182), BOOST_PP_NODE_181, BOOST_PP_NODE_183)
+# define BOOST_PP_NODE_181(p) BOOST_PP_IIF(p(181), 181, 182)
+# define BOOST_PP_NODE_183(p) BOOST_PP_IIF(p(183), 183, 184)
+# define BOOST_PP_NODE_188(p) BOOST_PP_IIF(p(188), BOOST_PP_NODE_186, BOOST_PP_NODE_190)
+# define BOOST_PP_NODE_186(p) BOOST_PP_IIF(p(186), BOOST_PP_NODE_185, BOOST_PP_NODE_187)
+# define BOOST_PP_NODE_185(p) BOOST_PP_IIF(p(185), 185, 186)
+# define BOOST_PP_NODE_187(p) BOOST_PP_IIF(p(187), 187, 188)
+# define BOOST_PP_NODE_190(p) BOOST_PP_IIF(p(190), BOOST_PP_NODE_189, BOOST_PP_NODE_191)
+# define BOOST_PP_NODE_189(p) BOOST_PP_IIF(p(189), 189, 190)
+# define BOOST_PP_NODE_191(p) BOOST_PP_IIF(p(191), 191, 192)
+# define BOOST_PP_NODE_224(p) BOOST_PP_IIF(p(224), BOOST_PP_NODE_208, BOOST_PP_NODE_240)
+# define BOOST_PP_NODE_208(p) BOOST_PP_IIF(p(208), BOOST_PP_NODE_200, BOOST_PP_NODE_216)
+# define BOOST_PP_NODE_200(p) BOOST_PP_IIF(p(200), BOOST_PP_NODE_196, BOOST_PP_NODE_204)
+# define BOOST_PP_NODE_196(p) BOOST_PP_IIF(p(196), BOOST_PP_NODE_194, BOOST_PP_NODE_198)
+# define BOOST_PP_NODE_194(p) BOOST_PP_IIF(p(194), BOOST_PP_NODE_193, BOOST_PP_NODE_195)
+# define BOOST_PP_NODE_193(p) BOOST_PP_IIF(p(193), 193, 194)
+# define BOOST_PP_NODE_195(p) BOOST_PP_IIF(p(195), 195, 196)
+# define BOOST_PP_NODE_198(p) BOOST_PP_IIF(p(198), BOOST_PP_NODE_197, BOOST_PP_NODE_199)
+# define BOOST_PP_NODE_197(p) BOOST_PP_IIF(p(197), 197, 198)
+# define BOOST_PP_NODE_199(p) BOOST_PP_IIF(p(199), 199, 200)
+# define BOOST_PP_NODE_204(p) BOOST_PP_IIF(p(204), BOOST_PP_NODE_202, BOOST_PP_NODE_206)
+# define BOOST_PP_NODE_202(p) BOOST_PP_IIF(p(202), BOOST_PP_NODE_201, BOOST_PP_NODE_203)
+# define BOOST_PP_NODE_201(p) BOOST_PP_IIF(p(201), 201, 202)
+# define BOOST_PP_NODE_203(p) BOOST_PP_IIF(p(203), 203, 204)
+# define BOOST_PP_NODE_206(p) BOOST_PP_IIF(p(206), BOOST_PP_NODE_205, BOOST_PP_NODE_207)
+# define BOOST_PP_NODE_205(p) BOOST_PP_IIF(p(205), 205, 206)
+# define BOOST_PP_NODE_207(p) BOOST_PP_IIF(p(207), 207, 208)
+# define BOOST_PP_NODE_216(p) BOOST_PP_IIF(p(216), BOOST_PP_NODE_212, BOOST_PP_NODE_220)
+# define BOOST_PP_NODE_212(p) BOOST_PP_IIF(p(212), BOOST_PP_NODE_210, BOOST_PP_NODE_214)
+# define BOOST_PP_NODE_210(p) BOOST_PP_IIF(p(210), BOOST_PP_NODE_209, BOOST_PP_NODE_211)
+# define BOOST_PP_NODE_209(p) BOOST_PP_IIF(p(209), 209, 210)
+# define BOOST_PP_NODE_211(p) BOOST_PP_IIF(p(211), 211, 212)
+# define BOOST_PP_NODE_214(p) BOOST_PP_IIF(p(214), BOOST_PP_NODE_213, BOOST_PP_NODE_215)
+# define BOOST_PP_NODE_213(p) BOOST_PP_IIF(p(213), 213, 214)
+# define BOOST_PP_NODE_215(p) BOOST_PP_IIF(p(215), 215, 216)
+# define BOOST_PP_NODE_220(p) BOOST_PP_IIF(p(220), BOOST_PP_NODE_218, BOOST_PP_NODE_222)
+# define BOOST_PP_NODE_218(p) BOOST_PP_IIF(p(218), BOOST_PP_NODE_217, BOOST_PP_NODE_219)
+# define BOOST_PP_NODE_217(p) BOOST_PP_IIF(p(217), 217, 218)
+# define BOOST_PP_NODE_219(p) BOOST_PP_IIF(p(219), 219, 220)
+# define BOOST_PP_NODE_222(p) BOOST_PP_IIF(p(222), BOOST_PP_NODE_221, BOOST_PP_NODE_223)
+# define BOOST_PP_NODE_221(p) BOOST_PP_IIF(p(221), 221, 222)
+# define BOOST_PP_NODE_223(p) BOOST_PP_IIF(p(223), 223, 224)
+# define BOOST_PP_NODE_240(p) BOOST_PP_IIF(p(240), BOOST_PP_NODE_232, BOOST_PP_NODE_248)
+# define BOOST_PP_NODE_232(p) BOOST_PP_IIF(p(232), BOOST_PP_NODE_228, BOOST_PP_NODE_236)
+# define BOOST_PP_NODE_228(p) BOOST_PP_IIF(p(228), BOOST_PP_NODE_226, BOOST_PP_NODE_230)
+# define BOOST_PP_NODE_226(p) BOOST_PP_IIF(p(226), BOOST_PP_NODE_225, BOOST_PP_NODE_227)
+# define BOOST_PP_NODE_225(p) BOOST_PP_IIF(p(225), 225, 226)
+# define BOOST_PP_NODE_227(p) BOOST_PP_IIF(p(227), 227, 228)
+# define BOOST_PP_NODE_230(p) BOOST_PP_IIF(p(230), BOOST_PP_NODE_229, BOOST_PP_NODE_231)
+# define BOOST_PP_NODE_229(p) BOOST_PP_IIF(p(229), 229, 230)
+# define BOOST_PP_NODE_231(p) BOOST_PP_IIF(p(231), 231, 232)
+# define BOOST_PP_NODE_236(p) BOOST_PP_IIF(p(236), BOOST_PP_NODE_234, BOOST_PP_NODE_238)
+# define BOOST_PP_NODE_234(p) BOOST_PP_IIF(p(234), BOOST_PP_NODE_233, BOOST_PP_NODE_235)
+# define BOOST_PP_NODE_233(p) BOOST_PP_IIF(p(233), 233, 234)
+# define BOOST_PP_NODE_235(p) BOOST_PP_IIF(p(235), 235, 236)
+# define BOOST_PP_NODE_238(p) BOOST_PP_IIF(p(238), BOOST_PP_NODE_237, BOOST_PP_NODE_239)
+# define BOOST_PP_NODE_237(p) BOOST_PP_IIF(p(237), 237, 238)
+# define BOOST_PP_NODE_239(p) BOOST_PP_IIF(p(239), 239, 240)
+# define BOOST_PP_NODE_248(p) BOOST_PP_IIF(p(248), BOOST_PP_NODE_244, BOOST_PP_NODE_252)
+# define BOOST_PP_NODE_244(p) BOOST_PP_IIF(p(244), BOOST_PP_NODE_242, BOOST_PP_NODE_246)
+# define BOOST_PP_NODE_242(p) BOOST_PP_IIF(p(242), BOOST_PP_NODE_241, BOOST_PP_NODE_243)
+# define BOOST_PP_NODE_241(p) BOOST_PP_IIF(p(241), 241, 242)
+# define BOOST_PP_NODE_243(p) BOOST_PP_IIF(p(243), 243, 244)
+# define BOOST_PP_NODE_246(p) BOOST_PP_IIF(p(246), BOOST_PP_NODE_245, BOOST_PP_NODE_247)
+# define BOOST_PP_NODE_245(p) BOOST_PP_IIF(p(245), 245, 246)
+# define BOOST_PP_NODE_247(p) BOOST_PP_IIF(p(247), 247, 248)
+# define BOOST_PP_NODE_252(p) BOOST_PP_IIF(p(252), BOOST_PP_NODE_250, BOOST_PP_NODE_254)
+# define BOOST_PP_NODE_250(p) BOOST_PP_IIF(p(250), BOOST_PP_NODE_249, BOOST_PP_NODE_251)
+# define BOOST_PP_NODE_249(p) BOOST_PP_IIF(p(249), 249, 250)
+# define BOOST_PP_NODE_251(p) BOOST_PP_IIF(p(251), 251, 252)
+# define BOOST_PP_NODE_254(p) BOOST_PP_IIF(p(254), BOOST_PP_NODE_253, BOOST_PP_NODE_255)
+# define BOOST_PP_NODE_253(p) BOOST_PP_IIF(p(253), 253, 254)
+# define BOOST_PP_NODE_255(p) BOOST_PP_IIF(p(255), 255, 256)
+#
+# endif
+# endif
diff --git a/third_party/boost/boost/preprocessor/detail/check.hpp b/third_party/boost/boost/preprocessor/detail/check.hpp
new file mode 100644
index 0000000..63f8ff9
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/detail/check.hpp
@@ -0,0 +1,48 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_DETAIL_CHECK_HPP
+# define BOOST_PREPROCESSOR_DETAIL_CHECK_HPP
+#
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/config/config.hpp>
+#
+# /* BOOST_PP_CHECK */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MWCC()
+# define BOOST_PP_CHECK(x, type) BOOST_PP_CHECK_D(x, type)
+# else
+# define BOOST_PP_CHECK(x, type) BOOST_PP_CHECK_OO((x, type))
+# define BOOST_PP_CHECK_OO(par) BOOST_PP_CHECK_D ## par
+# endif
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MSVC() && ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_DMC()
+# define BOOST_PP_CHECK_D(x, type) BOOST_PP_CHECK_1(BOOST_PP_CAT(BOOST_PP_CHECK_RESULT_, type x))
+# define BOOST_PP_CHECK_1(chk) BOOST_PP_CHECK_2(chk)
+# define BOOST_PP_CHECK_2(res, _) res
+# elif BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MSVC()
+# define BOOST_PP_CHECK_D(x, type) BOOST_PP_CHECK_1(type x)
+# define BOOST_PP_CHECK_1(chk) BOOST_PP_CHECK_2(chk)
+# define BOOST_PP_CHECK_2(chk) BOOST_PP_CHECK_3((BOOST_PP_CHECK_RESULT_ ## chk))
+# define BOOST_PP_CHECK_3(im) BOOST_PP_CHECK_5(BOOST_PP_CHECK_4 im)
+# define BOOST_PP_CHECK_4(res, _) res
+# define BOOST_PP_CHECK_5(res) res
+# else /* DMC */
+# define BOOST_PP_CHECK_D(x, type) BOOST_PP_CHECK_OO((type x))
+# define BOOST_PP_CHECK_OO(par) BOOST_PP_CHECK_0 ## par
+# define BOOST_PP_CHECK_0(chk) BOOST_PP_CHECK_1(BOOST_PP_CAT(BOOST_PP_CHECK_RESULT_, chk))
+# define BOOST_PP_CHECK_1(chk) BOOST_PP_CHECK_2(chk)
+# define BOOST_PP_CHECK_2(res, _) res
+# endif
+#
+# define BOOST_PP_CHECK_RESULT_1 1, BOOST_PP_NIL
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/detail/is_binary.hpp b/third_party/boost/boost/preprocessor/detail/is_binary.hpp
new file mode 100644
index 0000000..3428833
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/detail/is_binary.hpp
@@ -0,0 +1,30 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_DETAIL_IS_BINARY_HPP
+# define BOOST_PREPROCESSOR_DETAIL_IS_BINARY_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/detail/check.hpp>
+#
+# /* BOOST_PP_IS_BINARY */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_IS_BINARY(x) BOOST_PP_CHECK(x, BOOST_PP_IS_BINARY_CHECK)
+# else
+# define BOOST_PP_IS_BINARY(x) BOOST_PP_IS_BINARY_I(x)
+# define BOOST_PP_IS_BINARY_I(x) BOOST_PP_CHECK(x, BOOST_PP_IS_BINARY_CHECK)
+# endif
+#
+# define BOOST_PP_IS_BINARY_CHECK(a, b) 1
+# define BOOST_PP_CHECK_RESULT_BOOST_PP_IS_BINARY_CHECK 0, BOOST_PP_NIL
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/empty.hpp b/third_party/boost/boost/preprocessor/empty.hpp
new file mode 100644
index 0000000..116ef74
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/empty.hpp
@@ -0,0 +1,17 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_EMPTY_HPP
+# define BOOST_PREPROCESSOR_EMPTY_HPP
+#
+# include <boost/preprocessor/facilities/empty.hpp>
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/enum.hpp b/third_party/boost/boost/preprocessor/enum.hpp
new file mode 100644
index 0000000..ae05bb0
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/enum.hpp
@@ -0,0 +1,17 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_ENUM_HPP
+# define BOOST_PREPROCESSOR_ENUM_HPP
+#
+# include <boost/preprocessor/repetition/enum.hpp>
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/enum_params.hpp b/third_party/boost/boost/preprocessor/enum_params.hpp
new file mode 100644
index 0000000..414f8aa
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/enum_params.hpp
@@ -0,0 +1,17 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_ENUM_PARAMS_HPP
+# define BOOST_PREPROCESSOR_ENUM_PARAMS_HPP
+#
+# include <boost/preprocessor/repetition/enum_params.hpp>
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/enum_shifted_params.hpp b/third_party/boost/boost/preprocessor/enum_shifted_params.hpp
new file mode 100644
index 0000000..462c642
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/enum_shifted_params.hpp
@@ -0,0 +1,17 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_ENUM_SHIFTED_PARAMS_HPP
+# define BOOST_PREPROCESSOR_ENUM_SHIFTED_PARAMS_HPP
+#
+# include <boost/preprocessor/repetition/enum_shifted_params.hpp>
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/facilities/empty.hpp b/third_party/boost/boost/preprocessor/facilities/empty.hpp
new file mode 100644
index 0000000..6f215dc
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/facilities/empty.hpp
@@ -0,0 +1,23 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_FACILITIES_EMPTY_HPP
+# define BOOST_PREPROCESSOR_FACILITIES_EMPTY_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+#
+# /* BOOST_PP_EMPTY */
+#
+# define BOOST_PP_EMPTY()
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/facilities/expand.hpp b/third_party/boost/boost/preprocessor/facilities/expand.hpp
new file mode 100644
index 0000000..c8661a1
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/facilities/expand.hpp
@@ -0,0 +1,28 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_FACILITIES_EXPAND_HPP
+# define BOOST_PREPROCESSOR_FACILITIES_EXPAND_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MWCC() && ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_DMC()
+# define BOOST_PP_EXPAND(x) BOOST_PP_EXPAND_I(x)
+# else
+# define BOOST_PP_EXPAND(x) BOOST_PP_EXPAND_OO((x))
+# define BOOST_PP_EXPAND_OO(par) BOOST_PP_EXPAND_I ## par
+# endif
+#
+# define BOOST_PP_EXPAND_I(x) x
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/facilities/identity.hpp b/third_party/boost/boost/preprocessor/facilities/identity.hpp
new file mode 100644
index 0000000..8a7834d
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/facilities/identity.hpp
@@ -0,0 +1,27 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+# /* Revised by Edward Diener (2015) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_FACILITIES_IDENTITY_HPP
+# define BOOST_PREPROCESSOR_FACILITIES_IDENTITY_HPP
+#
+# include <boost/preprocessor/facilities/empty.hpp>
+# include <boost/preprocessor/tuple/eat.hpp>
+#
+# /* BOOST_PP_IDENTITY */
+#
+# define BOOST_PP_IDENTITY(item) item BOOST_PP_EMPTY
+#
+# define BOOST_PP_IDENTITY_N(item,n) item BOOST_PP_TUPLE_EAT_N(n)
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/facilities/intercept.hpp b/third_party/boost/boost/preprocessor/facilities/intercept.hpp
new file mode 100644
index 0000000..41dcc6a
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/facilities/intercept.hpp
@@ -0,0 +1,277 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_FACILITIES_INTERCEPT_HPP
+# define BOOST_PREPROCESSOR_FACILITIES_INTERCEPT_HPP
+#
+# /* BOOST_PP_INTERCEPT */
+#
+# define BOOST_PP_INTERCEPT BOOST_PP_INTERCEPT_
+#
+# define BOOST_PP_INTERCEPT_0
+# define BOOST_PP_INTERCEPT_1
+# define BOOST_PP_INTERCEPT_2
+# define BOOST_PP_INTERCEPT_3
+# define BOOST_PP_INTERCEPT_4
+# define BOOST_PP_INTERCEPT_5
+# define BOOST_PP_INTERCEPT_6
+# define BOOST_PP_INTERCEPT_7
+# define BOOST_PP_INTERCEPT_8
+# define BOOST_PP_INTERCEPT_9
+# define BOOST_PP_INTERCEPT_10
+# define BOOST_PP_INTERCEPT_11
+# define BOOST_PP_INTERCEPT_12
+# define BOOST_PP_INTERCEPT_13
+# define BOOST_PP_INTERCEPT_14
+# define BOOST_PP_INTERCEPT_15
+# define BOOST_PP_INTERCEPT_16
+# define BOOST_PP_INTERCEPT_17
+# define BOOST_PP_INTERCEPT_18
+# define BOOST_PP_INTERCEPT_19
+# define BOOST_PP_INTERCEPT_20
+# define BOOST_PP_INTERCEPT_21
+# define BOOST_PP_INTERCEPT_22
+# define BOOST_PP_INTERCEPT_23
+# define BOOST_PP_INTERCEPT_24
+# define BOOST_PP_INTERCEPT_25
+# define BOOST_PP_INTERCEPT_26
+# define BOOST_PP_INTERCEPT_27
+# define BOOST_PP_INTERCEPT_28
+# define BOOST_PP_INTERCEPT_29
+# define BOOST_PP_INTERCEPT_30
+# define BOOST_PP_INTERCEPT_31
+# define BOOST_PP_INTERCEPT_32
+# define BOOST_PP_INTERCEPT_33
+# define BOOST_PP_INTERCEPT_34
+# define BOOST_PP_INTERCEPT_35
+# define BOOST_PP_INTERCEPT_36
+# define BOOST_PP_INTERCEPT_37
+# define BOOST_PP_INTERCEPT_38
+# define BOOST_PP_INTERCEPT_39
+# define BOOST_PP_INTERCEPT_40
+# define BOOST_PP_INTERCEPT_41
+# define BOOST_PP_INTERCEPT_42
+# define BOOST_PP_INTERCEPT_43
+# define BOOST_PP_INTERCEPT_44
+# define BOOST_PP_INTERCEPT_45
+# define BOOST_PP_INTERCEPT_46
+# define BOOST_PP_INTERCEPT_47
+# define BOOST_PP_INTERCEPT_48
+# define BOOST_PP_INTERCEPT_49
+# define BOOST_PP_INTERCEPT_50
+# define BOOST_PP_INTERCEPT_51
+# define BOOST_PP_INTERCEPT_52
+# define BOOST_PP_INTERCEPT_53
+# define BOOST_PP_INTERCEPT_54
+# define BOOST_PP_INTERCEPT_55
+# define BOOST_PP_INTERCEPT_56
+# define BOOST_PP_INTERCEPT_57
+# define BOOST_PP_INTERCEPT_58
+# define BOOST_PP_INTERCEPT_59
+# define BOOST_PP_INTERCEPT_60
+# define BOOST_PP_INTERCEPT_61
+# define BOOST_PP_INTERCEPT_62
+# define BOOST_PP_INTERCEPT_63
+# define BOOST_PP_INTERCEPT_64
+# define BOOST_PP_INTERCEPT_65
+# define BOOST_PP_INTERCEPT_66
+# define BOOST_PP_INTERCEPT_67
+# define BOOST_PP_INTERCEPT_68
+# define BOOST_PP_INTERCEPT_69
+# define BOOST_PP_INTERCEPT_70
+# define BOOST_PP_INTERCEPT_71
+# define BOOST_PP_INTERCEPT_72
+# define BOOST_PP_INTERCEPT_73
+# define BOOST_PP_INTERCEPT_74
+# define BOOST_PP_INTERCEPT_75
+# define BOOST_PP_INTERCEPT_76
+# define BOOST_PP_INTERCEPT_77
+# define BOOST_PP_INTERCEPT_78
+# define BOOST_PP_INTERCEPT_79
+# define BOOST_PP_INTERCEPT_80
+# define BOOST_PP_INTERCEPT_81
+# define BOOST_PP_INTERCEPT_82
+# define BOOST_PP_INTERCEPT_83
+# define BOOST_PP_INTERCEPT_84
+# define BOOST_PP_INTERCEPT_85
+# define BOOST_PP_INTERCEPT_86
+# define BOOST_PP_INTERCEPT_87
+# define BOOST_PP_INTERCEPT_88
+# define BOOST_PP_INTERCEPT_89
+# define BOOST_PP_INTERCEPT_90
+# define BOOST_PP_INTERCEPT_91
+# define BOOST_PP_INTERCEPT_92
+# define BOOST_PP_INTERCEPT_93
+# define BOOST_PP_INTERCEPT_94
+# define BOOST_PP_INTERCEPT_95
+# define BOOST_PP_INTERCEPT_96
+# define BOOST_PP_INTERCEPT_97
+# define BOOST_PP_INTERCEPT_98
+# define BOOST_PP_INTERCEPT_99
+# define BOOST_PP_INTERCEPT_100
+# define BOOST_PP_INTERCEPT_101
+# define BOOST_PP_INTERCEPT_102
+# define BOOST_PP_INTERCEPT_103
+# define BOOST_PP_INTERCEPT_104
+# define BOOST_PP_INTERCEPT_105
+# define BOOST_PP_INTERCEPT_106
+# define BOOST_PP_INTERCEPT_107
+# define BOOST_PP_INTERCEPT_108
+# define BOOST_PP_INTERCEPT_109
+# define BOOST_PP_INTERCEPT_110
+# define BOOST_PP_INTERCEPT_111
+# define BOOST_PP_INTERCEPT_112
+# define BOOST_PP_INTERCEPT_113
+# define BOOST_PP_INTERCEPT_114
+# define BOOST_PP_INTERCEPT_115
+# define BOOST_PP_INTERCEPT_116
+# define BOOST_PP_INTERCEPT_117
+# define BOOST_PP_INTERCEPT_118
+# define BOOST_PP_INTERCEPT_119
+# define BOOST_PP_INTERCEPT_120
+# define BOOST_PP_INTERCEPT_121
+# define BOOST_PP_INTERCEPT_122
+# define BOOST_PP_INTERCEPT_123
+# define BOOST_PP_INTERCEPT_124
+# define BOOST_PP_INTERCEPT_125
+# define BOOST_PP_INTERCEPT_126
+# define BOOST_PP_INTERCEPT_127
+# define BOOST_PP_INTERCEPT_128
+# define BOOST_PP_INTERCEPT_129
+# define BOOST_PP_INTERCEPT_130
+# define BOOST_PP_INTERCEPT_131
+# define BOOST_PP_INTERCEPT_132
+# define BOOST_PP_INTERCEPT_133
+# define BOOST_PP_INTERCEPT_134
+# define BOOST_PP_INTERCEPT_135
+# define BOOST_PP_INTERCEPT_136
+# define BOOST_PP_INTERCEPT_137
+# define BOOST_PP_INTERCEPT_138
+# define BOOST_PP_INTERCEPT_139
+# define BOOST_PP_INTERCEPT_140
+# define BOOST_PP_INTERCEPT_141
+# define BOOST_PP_INTERCEPT_142
+# define BOOST_PP_INTERCEPT_143
+# define BOOST_PP_INTERCEPT_144
+# define BOOST_PP_INTERCEPT_145
+# define BOOST_PP_INTERCEPT_146
+# define BOOST_PP_INTERCEPT_147
+# define BOOST_PP_INTERCEPT_148
+# define BOOST_PP_INTERCEPT_149
+# define BOOST_PP_INTERCEPT_150
+# define BOOST_PP_INTERCEPT_151
+# define BOOST_PP_INTERCEPT_152
+# define BOOST_PP_INTERCEPT_153
+# define BOOST_PP_INTERCEPT_154
+# define BOOST_PP_INTERCEPT_155
+# define BOOST_PP_INTERCEPT_156
+# define BOOST_PP_INTERCEPT_157
+# define BOOST_PP_INTERCEPT_158
+# define BOOST_PP_INTERCEPT_159
+# define BOOST_PP_INTERCEPT_160
+# define BOOST_PP_INTERCEPT_161
+# define BOOST_PP_INTERCEPT_162
+# define BOOST_PP_INTERCEPT_163
+# define BOOST_PP_INTERCEPT_164
+# define BOOST_PP_INTERCEPT_165
+# define BOOST_PP_INTERCEPT_166
+# define BOOST_PP_INTERCEPT_167
+# define BOOST_PP_INTERCEPT_168
+# define BOOST_PP_INTERCEPT_169
+# define BOOST_PP_INTERCEPT_170
+# define BOOST_PP_INTERCEPT_171
+# define BOOST_PP_INTERCEPT_172
+# define BOOST_PP_INTERCEPT_173
+# define BOOST_PP_INTERCEPT_174
+# define BOOST_PP_INTERCEPT_175
+# define BOOST_PP_INTERCEPT_176
+# define BOOST_PP_INTERCEPT_177
+# define BOOST_PP_INTERCEPT_178
+# define BOOST_PP_INTERCEPT_179
+# define BOOST_PP_INTERCEPT_180
+# define BOOST_PP_INTERCEPT_181
+# define BOOST_PP_INTERCEPT_182
+# define BOOST_PP_INTERCEPT_183
+# define BOOST_PP_INTERCEPT_184
+# define BOOST_PP_INTERCEPT_185
+# define BOOST_PP_INTERCEPT_186
+# define BOOST_PP_INTERCEPT_187
+# define BOOST_PP_INTERCEPT_188
+# define BOOST_PP_INTERCEPT_189
+# define BOOST_PP_INTERCEPT_190
+# define BOOST_PP_INTERCEPT_191
+# define BOOST_PP_INTERCEPT_192
+# define BOOST_PP_INTERCEPT_193
+# define BOOST_PP_INTERCEPT_194
+# define BOOST_PP_INTERCEPT_195
+# define BOOST_PP_INTERCEPT_196
+# define BOOST_PP_INTERCEPT_197
+# define BOOST_PP_INTERCEPT_198
+# define BOOST_PP_INTERCEPT_199
+# define BOOST_PP_INTERCEPT_200
+# define BOOST_PP_INTERCEPT_201
+# define BOOST_PP_INTERCEPT_202
+# define BOOST_PP_INTERCEPT_203
+# define BOOST_PP_INTERCEPT_204
+# define BOOST_PP_INTERCEPT_205
+# define BOOST_PP_INTERCEPT_206
+# define BOOST_PP_INTERCEPT_207
+# define BOOST_PP_INTERCEPT_208
+# define BOOST_PP_INTERCEPT_209
+# define BOOST_PP_INTERCEPT_210
+# define BOOST_PP_INTERCEPT_211
+# define BOOST_PP_INTERCEPT_212
+# define BOOST_PP_INTERCEPT_213
+# define BOOST_PP_INTERCEPT_214
+# define BOOST_PP_INTERCEPT_215
+# define BOOST_PP_INTERCEPT_216
+# define BOOST_PP_INTERCEPT_217
+# define BOOST_PP_INTERCEPT_218
+# define BOOST_PP_INTERCEPT_219
+# define BOOST_PP_INTERCEPT_220
+# define BOOST_PP_INTERCEPT_221
+# define BOOST_PP_INTERCEPT_222
+# define BOOST_PP_INTERCEPT_223
+# define BOOST_PP_INTERCEPT_224
+# define BOOST_PP_INTERCEPT_225
+# define BOOST_PP_INTERCEPT_226
+# define BOOST_PP_INTERCEPT_227
+# define BOOST_PP_INTERCEPT_228
+# define BOOST_PP_INTERCEPT_229
+# define BOOST_PP_INTERCEPT_230
+# define BOOST_PP_INTERCEPT_231
+# define BOOST_PP_INTERCEPT_232
+# define BOOST_PP_INTERCEPT_233
+# define BOOST_PP_INTERCEPT_234
+# define BOOST_PP_INTERCEPT_235
+# define BOOST_PP_INTERCEPT_236
+# define BOOST_PP_INTERCEPT_237
+# define BOOST_PP_INTERCEPT_238
+# define BOOST_PP_INTERCEPT_239
+# define BOOST_PP_INTERCEPT_240
+# define BOOST_PP_INTERCEPT_241
+# define BOOST_PP_INTERCEPT_242
+# define BOOST_PP_INTERCEPT_243
+# define BOOST_PP_INTERCEPT_244
+# define BOOST_PP_INTERCEPT_245
+# define BOOST_PP_INTERCEPT_246
+# define BOOST_PP_INTERCEPT_247
+# define BOOST_PP_INTERCEPT_248
+# define BOOST_PP_INTERCEPT_249
+# define BOOST_PP_INTERCEPT_250
+# define BOOST_PP_INTERCEPT_251
+# define BOOST_PP_INTERCEPT_252
+# define BOOST_PP_INTERCEPT_253
+# define BOOST_PP_INTERCEPT_254
+# define BOOST_PP_INTERCEPT_255
+# define BOOST_PP_INTERCEPT_256
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/facilities/overload.hpp b/third_party/boost/boost/preprocessor/facilities/overload.hpp
new file mode 100644
index 0000000..1576316
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/facilities/overload.hpp
@@ -0,0 +1,25 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2011. *
+# * (C) Copyright Edward Diener 2011. *
+# * Distributed under the Boost Software License, Version 1.0. (See *
+# * accompanying file LICENSE_1_0.txt or copy at *
+# * http://www.boost.org/LICENSE_1_0.txt) *
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_FACILITIES_OVERLOAD_HPP
+# define BOOST_PREPROCESSOR_FACILITIES_OVERLOAD_HPP
+#
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/variadic/size.hpp>
+#
+# /* BOOST_PP_OVERLOAD */
+#
+# if BOOST_PP_VARIADICS
+# define BOOST_PP_OVERLOAD(prefix, ...) BOOST_PP_CAT(prefix, BOOST_PP_VARIADIC_SIZE(__VA_ARGS__))
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/identity.hpp b/third_party/boost/boost/preprocessor/identity.hpp
new file mode 100644
index 0000000..847dd13
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/identity.hpp
@@ -0,0 +1,17 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_IDENTITY_HPP
+# define BOOST_PREPROCESSOR_IDENTITY_HPP
+#
+# include <boost/preprocessor/facilities/identity.hpp>
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/inc.hpp b/third_party/boost/boost/preprocessor/inc.hpp
new file mode 100644
index 0000000..b98d3a6
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/inc.hpp
@@ -0,0 +1,17 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_INC_HPP
+# define BOOST_PREPROCESSOR_INC_HPP
+#
+# include <boost/preprocessor/arithmetic/inc.hpp>
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/iterate.hpp b/third_party/boost/boost/preprocessor/iterate.hpp
new file mode 100644
index 0000000..e720ec8
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/iterate.hpp
@@ -0,0 +1,17 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_ITERATE_HPP
+# define BOOST_PREPROCESSOR_ITERATE_HPP
+#
+# include <boost/preprocessor/iteration/iterate.hpp>
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/iteration.hpp b/third_party/boost/boost/preprocessor/iteration.hpp
new file mode 100644
index 0000000..1055ac0
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/iteration.hpp
@@ -0,0 +1,19 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_ITERATION_HPP
+# define BOOST_PREPROCESSOR_ITERATION_HPP
+#
+# include <boost/preprocessor/iteration/iterate.hpp>
+# include <boost/preprocessor/iteration/local.hpp>
+# include <boost/preprocessor/iteration/self.hpp>
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/iteration/detail/bounds/lower1.hpp b/third_party/boost/boost/preprocessor/iteration/detail/bounds/lower1.hpp
new file mode 100644
index 0000000..6694d0b
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/iteration/detail/bounds/lower1.hpp
@@ -0,0 +1,99 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# include <boost/preprocessor/slot/detail/shared.hpp>
+#
+# undef BOOST_PP_ITERATION_START_1
+#
+# undef BOOST_PP_ITERATION_START_1_DIGIT_1
+# undef BOOST_PP_ITERATION_START_1_DIGIT_2
+# undef BOOST_PP_ITERATION_START_1_DIGIT_3
+# undef BOOST_PP_ITERATION_START_1_DIGIT_4
+# undef BOOST_PP_ITERATION_START_1_DIGIT_5
+# undef BOOST_PP_ITERATION_START_1_DIGIT_6
+# undef BOOST_PP_ITERATION_START_1_DIGIT_7
+# undef BOOST_PP_ITERATION_START_1_DIGIT_8
+# undef BOOST_PP_ITERATION_START_1_DIGIT_9
+# undef BOOST_PP_ITERATION_START_1_DIGIT_10
+#
+# if BOOST_PP_SLOT_TEMP_3 == 0
+# define BOOST_PP_ITERATION_START_1_DIGIT_3 0
+# elif BOOST_PP_SLOT_TEMP_3 == 1
+# define BOOST_PP_ITERATION_START_1_DIGIT_3 1
+# elif BOOST_PP_SLOT_TEMP_3 == 2
+# define BOOST_PP_ITERATION_START_1_DIGIT_3 2
+# elif BOOST_PP_SLOT_TEMP_3 == 3
+# define BOOST_PP_ITERATION_START_1_DIGIT_3 3
+# elif BOOST_PP_SLOT_TEMP_3 == 4
+# define BOOST_PP_ITERATION_START_1_DIGIT_3 4
+# elif BOOST_PP_SLOT_TEMP_3 == 5
+# define BOOST_PP_ITERATION_START_1_DIGIT_3 5
+# elif BOOST_PP_SLOT_TEMP_3 == 6
+# define BOOST_PP_ITERATION_START_1_DIGIT_3 6
+# elif BOOST_PP_SLOT_TEMP_3 == 7
+# define BOOST_PP_ITERATION_START_1_DIGIT_3 7
+# elif BOOST_PP_SLOT_TEMP_3 == 8
+# define BOOST_PP_ITERATION_START_1_DIGIT_3 8
+# elif BOOST_PP_SLOT_TEMP_3 == 9
+# define BOOST_PP_ITERATION_START_1_DIGIT_3 9
+# endif
+#
+# if BOOST_PP_SLOT_TEMP_2 == 0
+# define BOOST_PP_ITERATION_START_1_DIGIT_2 0
+# elif BOOST_PP_SLOT_TEMP_2 == 1
+# define BOOST_PP_ITERATION_START_1_DIGIT_2 1
+# elif BOOST_PP_SLOT_TEMP_2 == 2
+# define BOOST_PP_ITERATION_START_1_DIGIT_2 2
+# elif BOOST_PP_SLOT_TEMP_2 == 3
+# define BOOST_PP_ITERATION_START_1_DIGIT_2 3
+# elif BOOST_PP_SLOT_TEMP_2 == 4
+# define BOOST_PP_ITERATION_START_1_DIGIT_2 4
+# elif BOOST_PP_SLOT_TEMP_2 == 5
+# define BOOST_PP_ITERATION_START_1_DIGIT_2 5
+# elif BOOST_PP_SLOT_TEMP_2 == 6
+# define BOOST_PP_ITERATION_START_1_DIGIT_2 6
+# elif BOOST_PP_SLOT_TEMP_2 == 7
+# define BOOST_PP_ITERATION_START_1_DIGIT_2 7
+# elif BOOST_PP_SLOT_TEMP_2 == 8
+# define BOOST_PP_ITERATION_START_1_DIGIT_2 8
+# elif BOOST_PP_SLOT_TEMP_2 == 9
+# define BOOST_PP_ITERATION_START_1_DIGIT_2 9
+# endif
+#
+# if BOOST_PP_SLOT_TEMP_1 == 0
+# define BOOST_PP_ITERATION_START_1_DIGIT_1 0
+# elif BOOST_PP_SLOT_TEMP_1 == 1
+# define BOOST_PP_ITERATION_START_1_DIGIT_1 1
+# elif BOOST_PP_SLOT_TEMP_1 == 2
+# define BOOST_PP_ITERATION_START_1_DIGIT_1 2
+# elif BOOST_PP_SLOT_TEMP_1 == 3
+# define BOOST_PP_ITERATION_START_1_DIGIT_1 3
+# elif BOOST_PP_SLOT_TEMP_1 == 4
+# define BOOST_PP_ITERATION_START_1_DIGIT_1 4
+# elif BOOST_PP_SLOT_TEMP_1 == 5
+# define BOOST_PP_ITERATION_START_1_DIGIT_1 5
+# elif BOOST_PP_SLOT_TEMP_1 == 6
+# define BOOST_PP_ITERATION_START_1_DIGIT_1 6
+# elif BOOST_PP_SLOT_TEMP_1 == 7
+# define BOOST_PP_ITERATION_START_1_DIGIT_1 7
+# elif BOOST_PP_SLOT_TEMP_1 == 8
+# define BOOST_PP_ITERATION_START_1_DIGIT_1 8
+# elif BOOST_PP_SLOT_TEMP_1 == 9
+# define BOOST_PP_ITERATION_START_1_DIGIT_1 9
+# endif
+#
+# if BOOST_PP_ITERATION_START_1_DIGIT_3
+# define BOOST_PP_ITERATION_START_1 BOOST_PP_SLOT_CC_3(BOOST_PP_ITERATION_START_1_DIGIT_3, BOOST_PP_ITERATION_START_1_DIGIT_2, BOOST_PP_ITERATION_START_1_DIGIT_1)
+# elif BOOST_PP_ITERATION_START_1_DIGIT_2
+# define BOOST_PP_ITERATION_START_1 BOOST_PP_SLOT_CC_2(BOOST_PP_ITERATION_START_1_DIGIT_2, BOOST_PP_ITERATION_START_1_DIGIT_1)
+# else
+# define BOOST_PP_ITERATION_START_1 BOOST_PP_ITERATION_START_1_DIGIT_1
+# endif
diff --git a/third_party/boost/boost/preprocessor/iteration/detail/bounds/upper1.hpp b/third_party/boost/boost/preprocessor/iteration/detail/bounds/upper1.hpp
new file mode 100644
index 0000000..50d0fcf
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/iteration/detail/bounds/upper1.hpp
@@ -0,0 +1,99 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# include <boost/preprocessor/slot/detail/shared.hpp>
+#
+# undef BOOST_PP_ITERATION_FINISH_1
+#
+# undef BOOST_PP_ITERATION_FINISH_1_DIGIT_1
+# undef BOOST_PP_ITERATION_FINISH_1_DIGIT_2
+# undef BOOST_PP_ITERATION_FINISH_1_DIGIT_3
+# undef BOOST_PP_ITERATION_FINISH_1_DIGIT_4
+# undef BOOST_PP_ITERATION_FINISH_1_DIGIT_5
+# undef BOOST_PP_ITERATION_FINISH_1_DIGIT_6
+# undef BOOST_PP_ITERATION_FINISH_1_DIGIT_7
+# undef BOOST_PP_ITERATION_FINISH_1_DIGIT_8
+# undef BOOST_PP_ITERATION_FINISH_1_DIGIT_9
+# undef BOOST_PP_ITERATION_FINISH_1_DIGIT_10
+#
+# if BOOST_PP_SLOT_TEMP_3 == 0
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_3 0
+# elif BOOST_PP_SLOT_TEMP_3 == 1
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_3 1
+# elif BOOST_PP_SLOT_TEMP_3 == 2
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_3 2
+# elif BOOST_PP_SLOT_TEMP_3 == 3
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_3 3
+# elif BOOST_PP_SLOT_TEMP_3 == 4
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_3 4
+# elif BOOST_PP_SLOT_TEMP_3 == 5
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_3 5
+# elif BOOST_PP_SLOT_TEMP_3 == 6
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_3 6
+# elif BOOST_PP_SLOT_TEMP_3 == 7
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_3 7
+# elif BOOST_PP_SLOT_TEMP_3 == 8
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_3 8
+# elif BOOST_PP_SLOT_TEMP_3 == 9
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_3 9
+# endif
+#
+# if BOOST_PP_SLOT_TEMP_2 == 0
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_2 0
+# elif BOOST_PP_SLOT_TEMP_2 == 1
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_2 1
+# elif BOOST_PP_SLOT_TEMP_2 == 2
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_2 2
+# elif BOOST_PP_SLOT_TEMP_2 == 3
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_2 3
+# elif BOOST_PP_SLOT_TEMP_2 == 4
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_2 4
+# elif BOOST_PP_SLOT_TEMP_2 == 5
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_2 5
+# elif BOOST_PP_SLOT_TEMP_2 == 6
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_2 6
+# elif BOOST_PP_SLOT_TEMP_2 == 7
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_2 7
+# elif BOOST_PP_SLOT_TEMP_2 == 8
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_2 8
+# elif BOOST_PP_SLOT_TEMP_2 == 9
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_2 9
+# endif
+#
+# if BOOST_PP_SLOT_TEMP_1 == 0
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_1 0
+# elif BOOST_PP_SLOT_TEMP_1 == 1
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_1 1
+# elif BOOST_PP_SLOT_TEMP_1 == 2
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_1 2
+# elif BOOST_PP_SLOT_TEMP_1 == 3
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_1 3
+# elif BOOST_PP_SLOT_TEMP_1 == 4
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_1 4
+# elif BOOST_PP_SLOT_TEMP_1 == 5
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_1 5
+# elif BOOST_PP_SLOT_TEMP_1 == 6
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_1 6
+# elif BOOST_PP_SLOT_TEMP_1 == 7
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_1 7
+# elif BOOST_PP_SLOT_TEMP_1 == 8
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_1 8
+# elif BOOST_PP_SLOT_TEMP_1 == 9
+# define BOOST_PP_ITERATION_FINISH_1_DIGIT_1 9
+# endif
+#
+# if BOOST_PP_ITERATION_FINISH_1_DIGIT_3
+# define BOOST_PP_ITERATION_FINISH_1 BOOST_PP_SLOT_CC_3(BOOST_PP_ITERATION_FINISH_1_DIGIT_3, BOOST_PP_ITERATION_FINISH_1_DIGIT_2, BOOST_PP_ITERATION_FINISH_1_DIGIT_1)
+# elif BOOST_PP_ITERATION_FINISH_1_DIGIT_2
+# define BOOST_PP_ITERATION_FINISH_1 BOOST_PP_SLOT_CC_2(BOOST_PP_ITERATION_FINISH_1_DIGIT_2, BOOST_PP_ITERATION_FINISH_1_DIGIT_1)
+# else
+# define BOOST_PP_ITERATION_FINISH_1 BOOST_PP_ITERATION_FINISH_1_DIGIT_1
+# endif
diff --git a/third_party/boost/boost/preprocessor/iteration/detail/iter/forward1.hpp b/third_party/boost/boost/preprocessor/iteration/detail/iter/forward1.hpp
new file mode 100644
index 0000000..3c6a458
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/iteration/detail/iter/forward1.hpp
@@ -0,0 +1,1342 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# if defined(BOOST_PP_ITERATION_LIMITS)
+# if !defined(BOOST_PP_FILENAME_1)
+# error BOOST_PP_ERROR: depth #1 filename is not defined
+# endif
+# define BOOST_PP_VALUE BOOST_PP_TUPLE_ELEM(2, 0, BOOST_PP_ITERATION_LIMITS)
+# include <boost/preprocessor/iteration/detail/bounds/lower1.hpp>
+# define BOOST_PP_VALUE BOOST_PP_TUPLE_ELEM(2, 1, BOOST_PP_ITERATION_LIMITS)
+# include <boost/preprocessor/iteration/detail/bounds/upper1.hpp>
+# define BOOST_PP_ITERATION_FLAGS_1() 0
+# undef BOOST_PP_ITERATION_LIMITS
+# elif defined(BOOST_PP_ITERATION_PARAMS_1)
+# define BOOST_PP_VALUE BOOST_PP_ARRAY_ELEM(0, BOOST_PP_ITERATION_PARAMS_1)
+# include <boost/preprocessor/iteration/detail/bounds/lower1.hpp>
+# define BOOST_PP_VALUE BOOST_PP_ARRAY_ELEM(1, BOOST_PP_ITERATION_PARAMS_1)
+# include <boost/preprocessor/iteration/detail/bounds/upper1.hpp>
+# define BOOST_PP_FILENAME_1 BOOST_PP_ARRAY_ELEM(2, BOOST_PP_ITERATION_PARAMS_1)
+# if BOOST_PP_ARRAY_SIZE(BOOST_PP_ITERATION_PARAMS_1) >= 4
+# define BOOST_PP_ITERATION_FLAGS_1() BOOST_PP_ARRAY_ELEM(3, BOOST_PP_ITERATION_PARAMS_1)
+# else
+# define BOOST_PP_ITERATION_FLAGS_1() 0
+# endif
+# else
+# error BOOST_PP_ERROR: depth #1 iteration boundaries or filename not defined
+# endif
+#
+# undef BOOST_PP_ITERATION_DEPTH
+# define BOOST_PP_ITERATION_DEPTH() 1
+#
+# define BOOST_PP_IS_ITERATING 1
+#
+# if (BOOST_PP_ITERATION_START_1) > (BOOST_PP_ITERATION_FINISH_1)
+# include <boost/preprocessor/iteration/detail/iter/reverse1.hpp>
+# else
+# if BOOST_PP_ITERATION_START_1 <= 0 && BOOST_PP_ITERATION_FINISH_1 >= 0
+# define BOOST_PP_ITERATION_1 0
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 1 && BOOST_PP_ITERATION_FINISH_1 >= 1
+# define BOOST_PP_ITERATION_1 1
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 2 && BOOST_PP_ITERATION_FINISH_1 >= 2
+# define BOOST_PP_ITERATION_1 2
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 3 && BOOST_PP_ITERATION_FINISH_1 >= 3
+# define BOOST_PP_ITERATION_1 3
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 4 && BOOST_PP_ITERATION_FINISH_1 >= 4
+# define BOOST_PP_ITERATION_1 4
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 5 && BOOST_PP_ITERATION_FINISH_1 >= 5
+# define BOOST_PP_ITERATION_1 5
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 6 && BOOST_PP_ITERATION_FINISH_1 >= 6
+# define BOOST_PP_ITERATION_1 6
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 7 && BOOST_PP_ITERATION_FINISH_1 >= 7
+# define BOOST_PP_ITERATION_1 7
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 8 && BOOST_PP_ITERATION_FINISH_1 >= 8
+# define BOOST_PP_ITERATION_1 8
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 9 && BOOST_PP_ITERATION_FINISH_1 >= 9
+# define BOOST_PP_ITERATION_1 9
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 10 && BOOST_PP_ITERATION_FINISH_1 >= 10
+# define BOOST_PP_ITERATION_1 10
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 11 && BOOST_PP_ITERATION_FINISH_1 >= 11
+# define BOOST_PP_ITERATION_1 11
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 12 && BOOST_PP_ITERATION_FINISH_1 >= 12
+# define BOOST_PP_ITERATION_1 12
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 13 && BOOST_PP_ITERATION_FINISH_1 >= 13
+# define BOOST_PP_ITERATION_1 13
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 14 && BOOST_PP_ITERATION_FINISH_1 >= 14
+# define BOOST_PP_ITERATION_1 14
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 15 && BOOST_PP_ITERATION_FINISH_1 >= 15
+# define BOOST_PP_ITERATION_1 15
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 16 && BOOST_PP_ITERATION_FINISH_1 >= 16
+# define BOOST_PP_ITERATION_1 16
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 17 && BOOST_PP_ITERATION_FINISH_1 >= 17
+# define BOOST_PP_ITERATION_1 17
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 18 && BOOST_PP_ITERATION_FINISH_1 >= 18
+# define BOOST_PP_ITERATION_1 18
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 19 && BOOST_PP_ITERATION_FINISH_1 >= 19
+# define BOOST_PP_ITERATION_1 19
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 20 && BOOST_PP_ITERATION_FINISH_1 >= 20
+# define BOOST_PP_ITERATION_1 20
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 21 && BOOST_PP_ITERATION_FINISH_1 >= 21
+# define BOOST_PP_ITERATION_1 21
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 22 && BOOST_PP_ITERATION_FINISH_1 >= 22
+# define BOOST_PP_ITERATION_1 22
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 23 && BOOST_PP_ITERATION_FINISH_1 >= 23
+# define BOOST_PP_ITERATION_1 23
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 24 && BOOST_PP_ITERATION_FINISH_1 >= 24
+# define BOOST_PP_ITERATION_1 24
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 25 && BOOST_PP_ITERATION_FINISH_1 >= 25
+# define BOOST_PP_ITERATION_1 25
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 26 && BOOST_PP_ITERATION_FINISH_1 >= 26
+# define BOOST_PP_ITERATION_1 26
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 27 && BOOST_PP_ITERATION_FINISH_1 >= 27
+# define BOOST_PP_ITERATION_1 27
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 28 && BOOST_PP_ITERATION_FINISH_1 >= 28
+# define BOOST_PP_ITERATION_1 28
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 29 && BOOST_PP_ITERATION_FINISH_1 >= 29
+# define BOOST_PP_ITERATION_1 29
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 30 && BOOST_PP_ITERATION_FINISH_1 >= 30
+# define BOOST_PP_ITERATION_1 30
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 31 && BOOST_PP_ITERATION_FINISH_1 >= 31
+# define BOOST_PP_ITERATION_1 31
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 32 && BOOST_PP_ITERATION_FINISH_1 >= 32
+# define BOOST_PP_ITERATION_1 32
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 33 && BOOST_PP_ITERATION_FINISH_1 >= 33
+# define BOOST_PP_ITERATION_1 33
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 34 && BOOST_PP_ITERATION_FINISH_1 >= 34
+# define BOOST_PP_ITERATION_1 34
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 35 && BOOST_PP_ITERATION_FINISH_1 >= 35
+# define BOOST_PP_ITERATION_1 35
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 36 && BOOST_PP_ITERATION_FINISH_1 >= 36
+# define BOOST_PP_ITERATION_1 36
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 37 && BOOST_PP_ITERATION_FINISH_1 >= 37
+# define BOOST_PP_ITERATION_1 37
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 38 && BOOST_PP_ITERATION_FINISH_1 >= 38
+# define BOOST_PP_ITERATION_1 38
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 39 && BOOST_PP_ITERATION_FINISH_1 >= 39
+# define BOOST_PP_ITERATION_1 39
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 40 && BOOST_PP_ITERATION_FINISH_1 >= 40
+# define BOOST_PP_ITERATION_1 40
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 41 && BOOST_PP_ITERATION_FINISH_1 >= 41
+# define BOOST_PP_ITERATION_1 41
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 42 && BOOST_PP_ITERATION_FINISH_1 >= 42
+# define BOOST_PP_ITERATION_1 42
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 43 && BOOST_PP_ITERATION_FINISH_1 >= 43
+# define BOOST_PP_ITERATION_1 43
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 44 && BOOST_PP_ITERATION_FINISH_1 >= 44
+# define BOOST_PP_ITERATION_1 44
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 45 && BOOST_PP_ITERATION_FINISH_1 >= 45
+# define BOOST_PP_ITERATION_1 45
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 46 && BOOST_PP_ITERATION_FINISH_1 >= 46
+# define BOOST_PP_ITERATION_1 46
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 47 && BOOST_PP_ITERATION_FINISH_1 >= 47
+# define BOOST_PP_ITERATION_1 47
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 48 && BOOST_PP_ITERATION_FINISH_1 >= 48
+# define BOOST_PP_ITERATION_1 48
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 49 && BOOST_PP_ITERATION_FINISH_1 >= 49
+# define BOOST_PP_ITERATION_1 49
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 50 && BOOST_PP_ITERATION_FINISH_1 >= 50
+# define BOOST_PP_ITERATION_1 50
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 51 && BOOST_PP_ITERATION_FINISH_1 >= 51
+# define BOOST_PP_ITERATION_1 51
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 52 && BOOST_PP_ITERATION_FINISH_1 >= 52
+# define BOOST_PP_ITERATION_1 52
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 53 && BOOST_PP_ITERATION_FINISH_1 >= 53
+# define BOOST_PP_ITERATION_1 53
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 54 && BOOST_PP_ITERATION_FINISH_1 >= 54
+# define BOOST_PP_ITERATION_1 54
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 55 && BOOST_PP_ITERATION_FINISH_1 >= 55
+# define BOOST_PP_ITERATION_1 55
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 56 && BOOST_PP_ITERATION_FINISH_1 >= 56
+# define BOOST_PP_ITERATION_1 56
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 57 && BOOST_PP_ITERATION_FINISH_1 >= 57
+# define BOOST_PP_ITERATION_1 57
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 58 && BOOST_PP_ITERATION_FINISH_1 >= 58
+# define BOOST_PP_ITERATION_1 58
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 59 && BOOST_PP_ITERATION_FINISH_1 >= 59
+# define BOOST_PP_ITERATION_1 59
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 60 && BOOST_PP_ITERATION_FINISH_1 >= 60
+# define BOOST_PP_ITERATION_1 60
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 61 && BOOST_PP_ITERATION_FINISH_1 >= 61
+# define BOOST_PP_ITERATION_1 61
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 62 && BOOST_PP_ITERATION_FINISH_1 >= 62
+# define BOOST_PP_ITERATION_1 62
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 63 && BOOST_PP_ITERATION_FINISH_1 >= 63
+# define BOOST_PP_ITERATION_1 63
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 64 && BOOST_PP_ITERATION_FINISH_1 >= 64
+# define BOOST_PP_ITERATION_1 64
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 65 && BOOST_PP_ITERATION_FINISH_1 >= 65
+# define BOOST_PP_ITERATION_1 65
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 66 && BOOST_PP_ITERATION_FINISH_1 >= 66
+# define BOOST_PP_ITERATION_1 66
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 67 && BOOST_PP_ITERATION_FINISH_1 >= 67
+# define BOOST_PP_ITERATION_1 67
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 68 && BOOST_PP_ITERATION_FINISH_1 >= 68
+# define BOOST_PP_ITERATION_1 68
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 69 && BOOST_PP_ITERATION_FINISH_1 >= 69
+# define BOOST_PP_ITERATION_1 69
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 70 && BOOST_PP_ITERATION_FINISH_1 >= 70
+# define BOOST_PP_ITERATION_1 70
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 71 && BOOST_PP_ITERATION_FINISH_1 >= 71
+# define BOOST_PP_ITERATION_1 71
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 72 && BOOST_PP_ITERATION_FINISH_1 >= 72
+# define BOOST_PP_ITERATION_1 72
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 73 && BOOST_PP_ITERATION_FINISH_1 >= 73
+# define BOOST_PP_ITERATION_1 73
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 74 && BOOST_PP_ITERATION_FINISH_1 >= 74
+# define BOOST_PP_ITERATION_1 74
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 75 && BOOST_PP_ITERATION_FINISH_1 >= 75
+# define BOOST_PP_ITERATION_1 75
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 76 && BOOST_PP_ITERATION_FINISH_1 >= 76
+# define BOOST_PP_ITERATION_1 76
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 77 && BOOST_PP_ITERATION_FINISH_1 >= 77
+# define BOOST_PP_ITERATION_1 77
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 78 && BOOST_PP_ITERATION_FINISH_1 >= 78
+# define BOOST_PP_ITERATION_1 78
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 79 && BOOST_PP_ITERATION_FINISH_1 >= 79
+# define BOOST_PP_ITERATION_1 79
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 80 && BOOST_PP_ITERATION_FINISH_1 >= 80
+# define BOOST_PP_ITERATION_1 80
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 81 && BOOST_PP_ITERATION_FINISH_1 >= 81
+# define BOOST_PP_ITERATION_1 81
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 82 && BOOST_PP_ITERATION_FINISH_1 >= 82
+# define BOOST_PP_ITERATION_1 82
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 83 && BOOST_PP_ITERATION_FINISH_1 >= 83
+# define BOOST_PP_ITERATION_1 83
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 84 && BOOST_PP_ITERATION_FINISH_1 >= 84
+# define BOOST_PP_ITERATION_1 84
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 85 && BOOST_PP_ITERATION_FINISH_1 >= 85
+# define BOOST_PP_ITERATION_1 85
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 86 && BOOST_PP_ITERATION_FINISH_1 >= 86
+# define BOOST_PP_ITERATION_1 86
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 87 && BOOST_PP_ITERATION_FINISH_1 >= 87
+# define BOOST_PP_ITERATION_1 87
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 88 && BOOST_PP_ITERATION_FINISH_1 >= 88
+# define BOOST_PP_ITERATION_1 88
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 89 && BOOST_PP_ITERATION_FINISH_1 >= 89
+# define BOOST_PP_ITERATION_1 89
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 90 && BOOST_PP_ITERATION_FINISH_1 >= 90
+# define BOOST_PP_ITERATION_1 90
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 91 && BOOST_PP_ITERATION_FINISH_1 >= 91
+# define BOOST_PP_ITERATION_1 91
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 92 && BOOST_PP_ITERATION_FINISH_1 >= 92
+# define BOOST_PP_ITERATION_1 92
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 93 && BOOST_PP_ITERATION_FINISH_1 >= 93
+# define BOOST_PP_ITERATION_1 93
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 94 && BOOST_PP_ITERATION_FINISH_1 >= 94
+# define BOOST_PP_ITERATION_1 94
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 95 && BOOST_PP_ITERATION_FINISH_1 >= 95
+# define BOOST_PP_ITERATION_1 95
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 96 && BOOST_PP_ITERATION_FINISH_1 >= 96
+# define BOOST_PP_ITERATION_1 96
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 97 && BOOST_PP_ITERATION_FINISH_1 >= 97
+# define BOOST_PP_ITERATION_1 97
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 98 && BOOST_PP_ITERATION_FINISH_1 >= 98
+# define BOOST_PP_ITERATION_1 98
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 99 && BOOST_PP_ITERATION_FINISH_1 >= 99
+# define BOOST_PP_ITERATION_1 99
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 100 && BOOST_PP_ITERATION_FINISH_1 >= 100
+# define BOOST_PP_ITERATION_1 100
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 101 && BOOST_PP_ITERATION_FINISH_1 >= 101
+# define BOOST_PP_ITERATION_1 101
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 102 && BOOST_PP_ITERATION_FINISH_1 >= 102
+# define BOOST_PP_ITERATION_1 102
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 103 && BOOST_PP_ITERATION_FINISH_1 >= 103
+# define BOOST_PP_ITERATION_1 103
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 104 && BOOST_PP_ITERATION_FINISH_1 >= 104
+# define BOOST_PP_ITERATION_1 104
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 105 && BOOST_PP_ITERATION_FINISH_1 >= 105
+# define BOOST_PP_ITERATION_1 105
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 106 && BOOST_PP_ITERATION_FINISH_1 >= 106
+# define BOOST_PP_ITERATION_1 106
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 107 && BOOST_PP_ITERATION_FINISH_1 >= 107
+# define BOOST_PP_ITERATION_1 107
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 108 && BOOST_PP_ITERATION_FINISH_1 >= 108
+# define BOOST_PP_ITERATION_1 108
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 109 && BOOST_PP_ITERATION_FINISH_1 >= 109
+# define BOOST_PP_ITERATION_1 109
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 110 && BOOST_PP_ITERATION_FINISH_1 >= 110
+# define BOOST_PP_ITERATION_1 110
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 111 && BOOST_PP_ITERATION_FINISH_1 >= 111
+# define BOOST_PP_ITERATION_1 111
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 112 && BOOST_PP_ITERATION_FINISH_1 >= 112
+# define BOOST_PP_ITERATION_1 112
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 113 && BOOST_PP_ITERATION_FINISH_1 >= 113
+# define BOOST_PP_ITERATION_1 113
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 114 && BOOST_PP_ITERATION_FINISH_1 >= 114
+# define BOOST_PP_ITERATION_1 114
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 115 && BOOST_PP_ITERATION_FINISH_1 >= 115
+# define BOOST_PP_ITERATION_1 115
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 116 && BOOST_PP_ITERATION_FINISH_1 >= 116
+# define BOOST_PP_ITERATION_1 116
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 117 && BOOST_PP_ITERATION_FINISH_1 >= 117
+# define BOOST_PP_ITERATION_1 117
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 118 && BOOST_PP_ITERATION_FINISH_1 >= 118
+# define BOOST_PP_ITERATION_1 118
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 119 && BOOST_PP_ITERATION_FINISH_1 >= 119
+# define BOOST_PP_ITERATION_1 119
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 120 && BOOST_PP_ITERATION_FINISH_1 >= 120
+# define BOOST_PP_ITERATION_1 120
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 121 && BOOST_PP_ITERATION_FINISH_1 >= 121
+# define BOOST_PP_ITERATION_1 121
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 122 && BOOST_PP_ITERATION_FINISH_1 >= 122
+# define BOOST_PP_ITERATION_1 122
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 123 && BOOST_PP_ITERATION_FINISH_1 >= 123
+# define BOOST_PP_ITERATION_1 123
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 124 && BOOST_PP_ITERATION_FINISH_1 >= 124
+# define BOOST_PP_ITERATION_1 124
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 125 && BOOST_PP_ITERATION_FINISH_1 >= 125
+# define BOOST_PP_ITERATION_1 125
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 126 && BOOST_PP_ITERATION_FINISH_1 >= 126
+# define BOOST_PP_ITERATION_1 126
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 127 && BOOST_PP_ITERATION_FINISH_1 >= 127
+# define BOOST_PP_ITERATION_1 127
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 128 && BOOST_PP_ITERATION_FINISH_1 >= 128
+# define BOOST_PP_ITERATION_1 128
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 129 && BOOST_PP_ITERATION_FINISH_1 >= 129
+# define BOOST_PP_ITERATION_1 129
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 130 && BOOST_PP_ITERATION_FINISH_1 >= 130
+# define BOOST_PP_ITERATION_1 130
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 131 && BOOST_PP_ITERATION_FINISH_1 >= 131
+# define BOOST_PP_ITERATION_1 131
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 132 && BOOST_PP_ITERATION_FINISH_1 >= 132
+# define BOOST_PP_ITERATION_1 132
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 133 && BOOST_PP_ITERATION_FINISH_1 >= 133
+# define BOOST_PP_ITERATION_1 133
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 134 && BOOST_PP_ITERATION_FINISH_1 >= 134
+# define BOOST_PP_ITERATION_1 134
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 135 && BOOST_PP_ITERATION_FINISH_1 >= 135
+# define BOOST_PP_ITERATION_1 135
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 136 && BOOST_PP_ITERATION_FINISH_1 >= 136
+# define BOOST_PP_ITERATION_1 136
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 137 && BOOST_PP_ITERATION_FINISH_1 >= 137
+# define BOOST_PP_ITERATION_1 137
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 138 && BOOST_PP_ITERATION_FINISH_1 >= 138
+# define BOOST_PP_ITERATION_1 138
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 139 && BOOST_PP_ITERATION_FINISH_1 >= 139
+# define BOOST_PP_ITERATION_1 139
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 140 && BOOST_PP_ITERATION_FINISH_1 >= 140
+# define BOOST_PP_ITERATION_1 140
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 141 && BOOST_PP_ITERATION_FINISH_1 >= 141
+# define BOOST_PP_ITERATION_1 141
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 142 && BOOST_PP_ITERATION_FINISH_1 >= 142
+# define BOOST_PP_ITERATION_1 142
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 143 && BOOST_PP_ITERATION_FINISH_1 >= 143
+# define BOOST_PP_ITERATION_1 143
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 144 && BOOST_PP_ITERATION_FINISH_1 >= 144
+# define BOOST_PP_ITERATION_1 144
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 145 && BOOST_PP_ITERATION_FINISH_1 >= 145
+# define BOOST_PP_ITERATION_1 145
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 146 && BOOST_PP_ITERATION_FINISH_1 >= 146
+# define BOOST_PP_ITERATION_1 146
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 147 && BOOST_PP_ITERATION_FINISH_1 >= 147
+# define BOOST_PP_ITERATION_1 147
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 148 && BOOST_PP_ITERATION_FINISH_1 >= 148
+# define BOOST_PP_ITERATION_1 148
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 149 && BOOST_PP_ITERATION_FINISH_1 >= 149
+# define BOOST_PP_ITERATION_1 149
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 150 && BOOST_PP_ITERATION_FINISH_1 >= 150
+# define BOOST_PP_ITERATION_1 150
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 151 && BOOST_PP_ITERATION_FINISH_1 >= 151
+# define BOOST_PP_ITERATION_1 151
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 152 && BOOST_PP_ITERATION_FINISH_1 >= 152
+# define BOOST_PP_ITERATION_1 152
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 153 && BOOST_PP_ITERATION_FINISH_1 >= 153
+# define BOOST_PP_ITERATION_1 153
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 154 && BOOST_PP_ITERATION_FINISH_1 >= 154
+# define BOOST_PP_ITERATION_1 154
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 155 && BOOST_PP_ITERATION_FINISH_1 >= 155
+# define BOOST_PP_ITERATION_1 155
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 156 && BOOST_PP_ITERATION_FINISH_1 >= 156
+# define BOOST_PP_ITERATION_1 156
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 157 && BOOST_PP_ITERATION_FINISH_1 >= 157
+# define BOOST_PP_ITERATION_1 157
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 158 && BOOST_PP_ITERATION_FINISH_1 >= 158
+# define BOOST_PP_ITERATION_1 158
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 159 && BOOST_PP_ITERATION_FINISH_1 >= 159
+# define BOOST_PP_ITERATION_1 159
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 160 && BOOST_PP_ITERATION_FINISH_1 >= 160
+# define BOOST_PP_ITERATION_1 160
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 161 && BOOST_PP_ITERATION_FINISH_1 >= 161
+# define BOOST_PP_ITERATION_1 161
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 162 && BOOST_PP_ITERATION_FINISH_1 >= 162
+# define BOOST_PP_ITERATION_1 162
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 163 && BOOST_PP_ITERATION_FINISH_1 >= 163
+# define BOOST_PP_ITERATION_1 163
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 164 && BOOST_PP_ITERATION_FINISH_1 >= 164
+# define BOOST_PP_ITERATION_1 164
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 165 && BOOST_PP_ITERATION_FINISH_1 >= 165
+# define BOOST_PP_ITERATION_1 165
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 166 && BOOST_PP_ITERATION_FINISH_1 >= 166
+# define BOOST_PP_ITERATION_1 166
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 167 && BOOST_PP_ITERATION_FINISH_1 >= 167
+# define BOOST_PP_ITERATION_1 167
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 168 && BOOST_PP_ITERATION_FINISH_1 >= 168
+# define BOOST_PP_ITERATION_1 168
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 169 && BOOST_PP_ITERATION_FINISH_1 >= 169
+# define BOOST_PP_ITERATION_1 169
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 170 && BOOST_PP_ITERATION_FINISH_1 >= 170
+# define BOOST_PP_ITERATION_1 170
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 171 && BOOST_PP_ITERATION_FINISH_1 >= 171
+# define BOOST_PP_ITERATION_1 171
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 172 && BOOST_PP_ITERATION_FINISH_1 >= 172
+# define BOOST_PP_ITERATION_1 172
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 173 && BOOST_PP_ITERATION_FINISH_1 >= 173
+# define BOOST_PP_ITERATION_1 173
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 174 && BOOST_PP_ITERATION_FINISH_1 >= 174
+# define BOOST_PP_ITERATION_1 174
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 175 && BOOST_PP_ITERATION_FINISH_1 >= 175
+# define BOOST_PP_ITERATION_1 175
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 176 && BOOST_PP_ITERATION_FINISH_1 >= 176
+# define BOOST_PP_ITERATION_1 176
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 177 && BOOST_PP_ITERATION_FINISH_1 >= 177
+# define BOOST_PP_ITERATION_1 177
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 178 && BOOST_PP_ITERATION_FINISH_1 >= 178
+# define BOOST_PP_ITERATION_1 178
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 179 && BOOST_PP_ITERATION_FINISH_1 >= 179
+# define BOOST_PP_ITERATION_1 179
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 180 && BOOST_PP_ITERATION_FINISH_1 >= 180
+# define BOOST_PP_ITERATION_1 180
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 181 && BOOST_PP_ITERATION_FINISH_1 >= 181
+# define BOOST_PP_ITERATION_1 181
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 182 && BOOST_PP_ITERATION_FINISH_1 >= 182
+# define BOOST_PP_ITERATION_1 182
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 183 && BOOST_PP_ITERATION_FINISH_1 >= 183
+# define BOOST_PP_ITERATION_1 183
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 184 && BOOST_PP_ITERATION_FINISH_1 >= 184
+# define BOOST_PP_ITERATION_1 184
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 185 && BOOST_PP_ITERATION_FINISH_1 >= 185
+# define BOOST_PP_ITERATION_1 185
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 186 && BOOST_PP_ITERATION_FINISH_1 >= 186
+# define BOOST_PP_ITERATION_1 186
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 187 && BOOST_PP_ITERATION_FINISH_1 >= 187
+# define BOOST_PP_ITERATION_1 187
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 188 && BOOST_PP_ITERATION_FINISH_1 >= 188
+# define BOOST_PP_ITERATION_1 188
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 189 && BOOST_PP_ITERATION_FINISH_1 >= 189
+# define BOOST_PP_ITERATION_1 189
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 190 && BOOST_PP_ITERATION_FINISH_1 >= 190
+# define BOOST_PP_ITERATION_1 190
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 191 && BOOST_PP_ITERATION_FINISH_1 >= 191
+# define BOOST_PP_ITERATION_1 191
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 192 && BOOST_PP_ITERATION_FINISH_1 >= 192
+# define BOOST_PP_ITERATION_1 192
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 193 && BOOST_PP_ITERATION_FINISH_1 >= 193
+# define BOOST_PP_ITERATION_1 193
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 194 && BOOST_PP_ITERATION_FINISH_1 >= 194
+# define BOOST_PP_ITERATION_1 194
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 195 && BOOST_PP_ITERATION_FINISH_1 >= 195
+# define BOOST_PP_ITERATION_1 195
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 196 && BOOST_PP_ITERATION_FINISH_1 >= 196
+# define BOOST_PP_ITERATION_1 196
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 197 && BOOST_PP_ITERATION_FINISH_1 >= 197
+# define BOOST_PP_ITERATION_1 197
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 198 && BOOST_PP_ITERATION_FINISH_1 >= 198
+# define BOOST_PP_ITERATION_1 198
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 199 && BOOST_PP_ITERATION_FINISH_1 >= 199
+# define BOOST_PP_ITERATION_1 199
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 200 && BOOST_PP_ITERATION_FINISH_1 >= 200
+# define BOOST_PP_ITERATION_1 200
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 201 && BOOST_PP_ITERATION_FINISH_1 >= 201
+# define BOOST_PP_ITERATION_1 201
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 202 && BOOST_PP_ITERATION_FINISH_1 >= 202
+# define BOOST_PP_ITERATION_1 202
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 203 && BOOST_PP_ITERATION_FINISH_1 >= 203
+# define BOOST_PP_ITERATION_1 203
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 204 && BOOST_PP_ITERATION_FINISH_1 >= 204
+# define BOOST_PP_ITERATION_1 204
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 205 && BOOST_PP_ITERATION_FINISH_1 >= 205
+# define BOOST_PP_ITERATION_1 205
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 206 && BOOST_PP_ITERATION_FINISH_1 >= 206
+# define BOOST_PP_ITERATION_1 206
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 207 && BOOST_PP_ITERATION_FINISH_1 >= 207
+# define BOOST_PP_ITERATION_1 207
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 208 && BOOST_PP_ITERATION_FINISH_1 >= 208
+# define BOOST_PP_ITERATION_1 208
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 209 && BOOST_PP_ITERATION_FINISH_1 >= 209
+# define BOOST_PP_ITERATION_1 209
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 210 && BOOST_PP_ITERATION_FINISH_1 >= 210
+# define BOOST_PP_ITERATION_1 210
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 211 && BOOST_PP_ITERATION_FINISH_1 >= 211
+# define BOOST_PP_ITERATION_1 211
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 212 && BOOST_PP_ITERATION_FINISH_1 >= 212
+# define BOOST_PP_ITERATION_1 212
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 213 && BOOST_PP_ITERATION_FINISH_1 >= 213
+# define BOOST_PP_ITERATION_1 213
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 214 && BOOST_PP_ITERATION_FINISH_1 >= 214
+# define BOOST_PP_ITERATION_1 214
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 215 && BOOST_PP_ITERATION_FINISH_1 >= 215
+# define BOOST_PP_ITERATION_1 215
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 216 && BOOST_PP_ITERATION_FINISH_1 >= 216
+# define BOOST_PP_ITERATION_1 216
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 217 && BOOST_PP_ITERATION_FINISH_1 >= 217
+# define BOOST_PP_ITERATION_1 217
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 218 && BOOST_PP_ITERATION_FINISH_1 >= 218
+# define BOOST_PP_ITERATION_1 218
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 219 && BOOST_PP_ITERATION_FINISH_1 >= 219
+# define BOOST_PP_ITERATION_1 219
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 220 && BOOST_PP_ITERATION_FINISH_1 >= 220
+# define BOOST_PP_ITERATION_1 220
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 221 && BOOST_PP_ITERATION_FINISH_1 >= 221
+# define BOOST_PP_ITERATION_1 221
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 222 && BOOST_PP_ITERATION_FINISH_1 >= 222
+# define BOOST_PP_ITERATION_1 222
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 223 && BOOST_PP_ITERATION_FINISH_1 >= 223
+# define BOOST_PP_ITERATION_1 223
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 224 && BOOST_PP_ITERATION_FINISH_1 >= 224
+# define BOOST_PP_ITERATION_1 224
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 225 && BOOST_PP_ITERATION_FINISH_1 >= 225
+# define BOOST_PP_ITERATION_1 225
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 226 && BOOST_PP_ITERATION_FINISH_1 >= 226
+# define BOOST_PP_ITERATION_1 226
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 227 && BOOST_PP_ITERATION_FINISH_1 >= 227
+# define BOOST_PP_ITERATION_1 227
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 228 && BOOST_PP_ITERATION_FINISH_1 >= 228
+# define BOOST_PP_ITERATION_1 228
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 229 && BOOST_PP_ITERATION_FINISH_1 >= 229
+# define BOOST_PP_ITERATION_1 229
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 230 && BOOST_PP_ITERATION_FINISH_1 >= 230
+# define BOOST_PP_ITERATION_1 230
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 231 && BOOST_PP_ITERATION_FINISH_1 >= 231
+# define BOOST_PP_ITERATION_1 231
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 232 && BOOST_PP_ITERATION_FINISH_1 >= 232
+# define BOOST_PP_ITERATION_1 232
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 233 && BOOST_PP_ITERATION_FINISH_1 >= 233
+# define BOOST_PP_ITERATION_1 233
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 234 && BOOST_PP_ITERATION_FINISH_1 >= 234
+# define BOOST_PP_ITERATION_1 234
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 235 && BOOST_PP_ITERATION_FINISH_1 >= 235
+# define BOOST_PP_ITERATION_1 235
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 236 && BOOST_PP_ITERATION_FINISH_1 >= 236
+# define BOOST_PP_ITERATION_1 236
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 237 && BOOST_PP_ITERATION_FINISH_1 >= 237
+# define BOOST_PP_ITERATION_1 237
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 238 && BOOST_PP_ITERATION_FINISH_1 >= 238
+# define BOOST_PP_ITERATION_1 238
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 239 && BOOST_PP_ITERATION_FINISH_1 >= 239
+# define BOOST_PP_ITERATION_1 239
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 240 && BOOST_PP_ITERATION_FINISH_1 >= 240
+# define BOOST_PP_ITERATION_1 240
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 241 && BOOST_PP_ITERATION_FINISH_1 >= 241
+# define BOOST_PP_ITERATION_1 241
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 242 && BOOST_PP_ITERATION_FINISH_1 >= 242
+# define BOOST_PP_ITERATION_1 242
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 243 && BOOST_PP_ITERATION_FINISH_1 >= 243
+# define BOOST_PP_ITERATION_1 243
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 244 && BOOST_PP_ITERATION_FINISH_1 >= 244
+# define BOOST_PP_ITERATION_1 244
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 245 && BOOST_PP_ITERATION_FINISH_1 >= 245
+# define BOOST_PP_ITERATION_1 245
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 246 && BOOST_PP_ITERATION_FINISH_1 >= 246
+# define BOOST_PP_ITERATION_1 246
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 247 && BOOST_PP_ITERATION_FINISH_1 >= 247
+# define BOOST_PP_ITERATION_1 247
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 248 && BOOST_PP_ITERATION_FINISH_1 >= 248
+# define BOOST_PP_ITERATION_1 248
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 249 && BOOST_PP_ITERATION_FINISH_1 >= 249
+# define BOOST_PP_ITERATION_1 249
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 250 && BOOST_PP_ITERATION_FINISH_1 >= 250
+# define BOOST_PP_ITERATION_1 250
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 251 && BOOST_PP_ITERATION_FINISH_1 >= 251
+# define BOOST_PP_ITERATION_1 251
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 252 && BOOST_PP_ITERATION_FINISH_1 >= 252
+# define BOOST_PP_ITERATION_1 252
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 253 && BOOST_PP_ITERATION_FINISH_1 >= 253
+# define BOOST_PP_ITERATION_1 253
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 254 && BOOST_PP_ITERATION_FINISH_1 >= 254
+# define BOOST_PP_ITERATION_1 254
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 255 && BOOST_PP_ITERATION_FINISH_1 >= 255
+# define BOOST_PP_ITERATION_1 255
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# if BOOST_PP_ITERATION_START_1 <= 256 && BOOST_PP_ITERATION_FINISH_1 >= 256
+# define BOOST_PP_ITERATION_1 256
+# include BOOST_PP_FILENAME_1
+# undef BOOST_PP_ITERATION_1
+# endif
+# endif
+#
+# undef BOOST_PP_IS_ITERATING
+#
+# undef BOOST_PP_ITERATION_DEPTH
+# define BOOST_PP_ITERATION_DEPTH() 0
+#
+# undef BOOST_PP_ITERATION_START_1
+# undef BOOST_PP_ITERATION_FINISH_1
+# undef BOOST_PP_FILENAME_1
+#
+# undef BOOST_PP_ITERATION_FLAGS_1
+# undef BOOST_PP_ITERATION_PARAMS_1
diff --git a/third_party/boost/boost/preprocessor/iteration/iterate.hpp b/third_party/boost/boost/preprocessor/iteration/iterate.hpp
new file mode 100644
index 0000000..8f861e7
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/iteration/iterate.hpp
@@ -0,0 +1,82 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_ITERATION_ITERATE_HPP
+# define BOOST_PREPROCESSOR_ITERATION_ITERATE_HPP
+#
+# include <boost/preprocessor/arithmetic/dec.hpp>
+# include <boost/preprocessor/arithmetic/inc.hpp>
+# include <boost/preprocessor/array/elem.hpp>
+# include <boost/preprocessor/array/size.hpp>
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/slot/slot.hpp>
+# include <boost/preprocessor/tuple/elem.hpp>
+#
+# /* BOOST_PP_ITERATION_DEPTH */
+#
+# define BOOST_PP_ITERATION_DEPTH() 0
+#
+# /* BOOST_PP_ITERATION */
+#
+# define BOOST_PP_ITERATION() BOOST_PP_CAT(BOOST_PP_ITERATION_, BOOST_PP_ITERATION_DEPTH())
+#
+# /* BOOST_PP_ITERATION_START && BOOST_PP_ITERATION_FINISH */
+#
+# define BOOST_PP_ITERATION_START() BOOST_PP_CAT(BOOST_PP_ITERATION_START_, BOOST_PP_ITERATION_DEPTH())
+# define BOOST_PP_ITERATION_FINISH() BOOST_PP_CAT(BOOST_PP_ITERATION_FINISH_, BOOST_PP_ITERATION_DEPTH())
+#
+# /* BOOST_PP_ITERATION_FLAGS */
+#
+# define BOOST_PP_ITERATION_FLAGS() (BOOST_PP_CAT(BOOST_PP_ITERATION_FLAGS_, BOOST_PP_ITERATION_DEPTH())())
+#
+# /* BOOST_PP_FRAME_ITERATION */
+#
+# define BOOST_PP_FRAME_ITERATION(i) BOOST_PP_CAT(BOOST_PP_ITERATION_, i)
+#
+# /* BOOST_PP_FRAME_START && BOOST_PP_FRAME_FINISH */
+#
+# define BOOST_PP_FRAME_START(i) BOOST_PP_CAT(BOOST_PP_ITERATION_START_, i)
+# define BOOST_PP_FRAME_FINISH(i) BOOST_PP_CAT(BOOST_PP_ITERATION_FINISH_, i)
+#
+# /* BOOST_PP_FRAME_FLAGS */
+#
+# define BOOST_PP_FRAME_FLAGS(i) (BOOST_PP_CAT(BOOST_PP_ITERATION_FLAGS_, i)())
+#
+# /* BOOST_PP_RELATIVE_ITERATION */
+#
+# define BOOST_PP_RELATIVE_ITERATION(i) BOOST_PP_CAT(BOOST_PP_RELATIVE_, i)(BOOST_PP_ITERATION_)
+#
+# define BOOST_PP_RELATIVE_0(m) BOOST_PP_CAT(m, BOOST_PP_ITERATION_DEPTH())
+# define BOOST_PP_RELATIVE_1(m) BOOST_PP_CAT(m, BOOST_PP_DEC(BOOST_PP_ITERATION_DEPTH()))
+# define BOOST_PP_RELATIVE_2(m) BOOST_PP_CAT(m, BOOST_PP_DEC(BOOST_PP_DEC(BOOST_PP_ITERATION_DEPTH())))
+# define BOOST_PP_RELATIVE_3(m) BOOST_PP_CAT(m, BOOST_PP_DEC(BOOST_PP_DEC(BOOST_PP_DEC(BOOST_PP_ITERATION_DEPTH()))))
+# define BOOST_PP_RELATIVE_4(m) BOOST_PP_CAT(m, BOOST_PP_DEC(BOOST_PP_DEC(BOOST_PP_DEC(BOOST_PP_DEC(BOOST_PP_ITERATION_DEPTH())))))
+#
+# /* BOOST_PP_RELATIVE_START && BOOST_PP_RELATIVE_FINISH */
+#
+# define BOOST_PP_RELATIVE_START(i) BOOST_PP_CAT(BOOST_PP_RELATIVE_, i)(BOOST_PP_ITERATION_START_)
+# define BOOST_PP_RELATIVE_FINISH(i) BOOST_PP_CAT(BOOST_PP_RELATIVE_, i)(BOOST_PP_ITERATION_FINISH_)
+#
+# /* BOOST_PP_RELATIVE_FLAGS */
+#
+# define BOOST_PP_RELATIVE_FLAGS(i) (BOOST_PP_CAT(BOOST_PP_RELATIVE_, i)(BOOST_PP_ITERATION_FLAGS_)())
+#
+# /* BOOST_PP_ITERATE */
+#
+# define BOOST_PP_ITERATE() BOOST_PP_CAT(BOOST_PP_ITERATE_, BOOST_PP_INC(BOOST_PP_ITERATION_DEPTH()))
+#
+# define BOOST_PP_ITERATE_1 <boost/preprocessor/iteration/detail/iter/forward1.hpp>
+# define BOOST_PP_ITERATE_2 <boost/preprocessor/iteration/detail/iter/forward2.hpp>
+# define BOOST_PP_ITERATE_3 <boost/preprocessor/iteration/detail/iter/forward3.hpp>
+# define BOOST_PP_ITERATE_4 <boost/preprocessor/iteration/detail/iter/forward4.hpp>
+# define BOOST_PP_ITERATE_5 <boost/preprocessor/iteration/detail/iter/forward5.hpp>
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/iteration/local.hpp b/third_party/boost/boost/preprocessor/iteration/local.hpp
new file mode 100644
index 0000000..289fb1a
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/iteration/local.hpp
@@ -0,0 +1,26 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_ITERATION_LOCAL_HPP
+# define BOOST_PREPROCESSOR_ITERATION_LOCAL_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/slot/slot.hpp>
+# include <boost/preprocessor/tuple/elem.hpp>
+#
+# /* BOOST_PP_LOCAL_ITERATE */
+#
+# define BOOST_PP_LOCAL_ITERATE() <boost/preprocessor/iteration/detail/local.hpp>
+#
+# define BOOST_PP_LOCAL_C(n) (BOOST_PP_LOCAL_S) <= n && (BOOST_PP_LOCAL_F) >= n
+# define BOOST_PP_LOCAL_R(n) (BOOST_PP_LOCAL_F) <= n && (BOOST_PP_LOCAL_S) >= n
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/iteration/self.hpp b/third_party/boost/boost/preprocessor/iteration/self.hpp
new file mode 100644
index 0000000..6e0464c
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/iteration/self.hpp
@@ -0,0 +1,19 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_ITERATION_SELF_HPP
+# define BOOST_PREPROCESSOR_ITERATION_SELF_HPP
+#
+# /* BOOST_PP_INCLUDE_SELF */
+#
+# define BOOST_PP_INCLUDE_SELF() <boost/preprocessor/iteration/detail/self.hpp>
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/list/adt.hpp b/third_party/boost/boost/preprocessor/list/adt.hpp
new file mode 100644
index 0000000..b4f12ba
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/list/adt.hpp
@@ -0,0 +1,73 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# *
+# * See http://www.boost.org for most recent version.
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# ifndef BOOST_PREPROCESSOR_LIST_ADT_HPP
+# define BOOST_PREPROCESSOR_LIST_ADT_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/detail/is_binary.hpp>
+# include <boost/preprocessor/logical/compl.hpp>
+# include <boost/preprocessor/tuple/eat.hpp>
+#
+# /* BOOST_PP_LIST_CONS */
+#
+# define BOOST_PP_LIST_CONS(head, tail) (head, tail)
+#
+# /* BOOST_PP_LIST_NIL */
+#
+# define BOOST_PP_LIST_NIL BOOST_PP_NIL
+#
+# /* BOOST_PP_LIST_FIRST */
+#
+# define BOOST_PP_LIST_FIRST(list) BOOST_PP_LIST_FIRST_D(list)
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MWCC()
+# define BOOST_PP_LIST_FIRST_D(list) BOOST_PP_LIST_FIRST_I list
+# else
+# define BOOST_PP_LIST_FIRST_D(list) BOOST_PP_LIST_FIRST_I ## list
+# endif
+#
+# define BOOST_PP_LIST_FIRST_I(head, tail) head
+#
+# /* BOOST_PP_LIST_REST */
+#
+# define BOOST_PP_LIST_REST(list) BOOST_PP_LIST_REST_D(list)
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MWCC()
+# define BOOST_PP_LIST_REST_D(list) BOOST_PP_LIST_REST_I list
+# else
+# define BOOST_PP_LIST_REST_D(list) BOOST_PP_LIST_REST_I ## list
+# endif
+#
+# define BOOST_PP_LIST_REST_I(head, tail) tail
+#
+# /* BOOST_PP_LIST_IS_CONS */
+#
+# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_BCC()
+# define BOOST_PP_LIST_IS_CONS(list) BOOST_PP_LIST_IS_CONS_D(list)
+# define BOOST_PP_LIST_IS_CONS_D(list) BOOST_PP_LIST_IS_CONS_ ## list
+# define BOOST_PP_LIST_IS_CONS_(head, tail) 1
+# define BOOST_PP_LIST_IS_CONS_BOOST_PP_NIL 0
+# else
+# define BOOST_PP_LIST_IS_CONS(list) BOOST_PP_IS_BINARY(list)
+# endif
+#
+# /* BOOST_PP_LIST_IS_NIL */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_BCC()
+# define BOOST_PP_LIST_IS_NIL(list) BOOST_PP_COMPL(BOOST_PP_IS_BINARY(list))
+# else
+# define BOOST_PP_LIST_IS_NIL(list) BOOST_PP_COMPL(BOOST_PP_LIST_IS_CONS(list))
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/list/detail/fold_left.hpp b/third_party/boost/boost/preprocessor/list/detail/fold_left.hpp
new file mode 100644
index 0000000..f5fcab7
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/list/detail/fold_left.hpp
@@ -0,0 +1,279 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_LIST_DETAIL_FOLD_LEFT_HPP
+# define BOOST_PREPROCESSOR_LIST_DETAIL_FOLD_LEFT_HPP
+#
+# include <boost/preprocessor/control/expr_iif.hpp>
+# include <boost/preprocessor/control/iif.hpp>
+# include <boost/preprocessor/list/adt.hpp>
+# include <boost/preprocessor/tuple/eat.hpp>
+#
+# define BOOST_PP_LIST_FOLD_LEFT_1(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_2, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(2, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_2(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_3, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(3, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_3(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_4, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(4, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_4(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_5, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(5, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_5(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_6, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(6, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_6(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_7, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(7, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_7(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_8, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(8, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_8(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_9, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(9, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_9(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_10, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(10, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_10(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_11, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(11, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_11(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_12, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(12, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_12(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_13, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(13, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_13(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_14, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(14, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_14(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_15, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(15, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_15(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_16, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(16, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_16(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_17, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(17, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_17(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_18, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(18, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_18(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_19, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(19, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_19(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_20, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(20, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_20(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_21, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(21, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_21(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_22, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(22, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_22(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_23, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(23, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_23(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_24, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(24, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_24(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_25, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(25, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_25(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_26, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(26, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_26(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_27, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(27, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_27(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_28, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(28, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_28(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_29, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(29, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_29(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_30, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(30, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_30(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_31, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(31, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_31(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_32, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(32, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_32(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_33, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(33, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_33(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_34, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(34, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_34(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_35, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(35, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_35(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_36, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(36, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_36(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_37, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(37, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_37(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_38, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(38, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_38(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_39, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(39, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_39(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_40, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(40, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_40(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_41, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(41, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_41(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_42, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(42, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_42(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_43, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(43, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_43(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_44, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(44, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_44(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_45, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(45, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_45(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_46, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(46, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_46(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_47, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(47, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_47(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_48, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(48, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_48(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_49, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(49, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_49(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_50, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(50, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_50(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_51, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(51, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_51(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_52, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(52, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_52(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_53, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(53, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_53(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_54, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(54, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_54(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_55, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(55, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_55(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_56, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(56, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_56(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_57, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(57, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_57(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_58, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(58, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_58(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_59, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(59, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_59(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_60, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(60, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_60(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_61, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(61, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_61(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_62, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(62, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_62(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_63, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(63, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_63(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_64, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(64, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_64(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_65, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(65, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_65(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_66, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(66, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_66(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_67, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(67, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_67(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_68, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(68, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_68(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_69, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(69, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_69(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_70, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(70, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_70(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_71, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(71, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_71(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_72, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(72, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_72(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_73, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(73, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_73(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_74, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(74, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_74(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_75, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(75, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_75(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_76, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(76, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_76(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_77, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(77, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_77(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_78, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(78, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_78(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_79, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(79, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_79(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_80, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(80, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_80(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_81, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(81, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_81(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_82, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(82, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_82(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_83, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(83, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_83(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_84, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(84, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_84(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_85, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(85, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_85(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_86, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(86, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_86(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_87, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(87, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_87(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_88, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(88, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_88(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_89, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(89, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_89(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_90, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(90, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_90(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_91, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(91, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_91(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_92, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(92, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_92(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_93, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(93, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_93(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_94, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(94, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_94(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_95, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(95, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_95(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_96, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(96, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_96(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_97, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(97, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_97(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_98, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(98, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_98(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_99, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(99, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_99(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_100, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(100, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_100(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_101, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(101, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_101(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_102, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(102, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_102(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_103, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(103, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_103(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_104, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(104, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_104(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_105, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(105, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_105(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_106, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(106, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_106(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_107, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(107, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_107(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_108, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(108, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_108(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_109, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(109, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_109(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_110, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(110, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_110(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_111, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(111, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_111(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_112, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(112, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_112(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_113, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(113, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_113(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_114, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(114, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_114(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_115, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(115, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_115(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_116, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(116, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_116(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_117, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(117, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_117(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_118, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(118, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_118(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_119, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(119, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_119(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_120, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(120, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_120(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_121, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(121, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_121(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_122, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(122, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_122(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_123, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(123, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_123(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_124, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(124, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_124(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_125, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(125, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_125(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_126, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(126, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_126(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_127, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(127, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_127(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_128, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(128, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_128(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_129, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(129, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_129(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_130, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(130, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_130(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_131, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(131, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_131(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_132, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(132, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_132(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_133, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(133, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_133(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_134, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(134, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_134(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_135, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(135, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_135(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_136, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(136, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_136(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_137, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(137, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_137(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_138, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(138, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_138(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_139, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(139, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_139(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_140, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(140, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_140(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_141, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(141, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_141(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_142, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(142, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_142(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_143, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(143, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_143(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_144, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(144, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_144(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_145, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(145, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_145(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_146, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(146, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_146(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_147, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(147, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_147(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_148, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(148, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_148(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_149, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(149, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_149(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_150, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(150, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_150(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_151, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(151, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_151(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_152, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(152, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_152(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_153, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(153, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_153(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_154, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(154, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_154(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_155, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(155, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_155(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_156, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(156, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_156(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_157, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(157, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_157(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_158, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(158, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_158(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_159, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(159, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_159(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_160, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(160, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_160(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_161, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(161, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_161(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_162, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(162, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_162(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_163, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(163, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_163(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_164, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(164, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_164(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_165, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(165, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_165(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_166, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(166, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_166(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_167, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(167, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_167(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_168, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(168, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_168(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_169, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(169, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_169(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_170, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(170, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_170(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_171, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(171, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_171(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_172, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(172, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_172(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_173, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(173, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_173(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_174, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(174, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_174(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_175, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(175, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_175(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_176, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(176, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_176(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_177, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(177, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_177(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_178, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(178, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_178(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_179, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(179, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_179(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_180, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(180, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_180(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_181, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(181, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_181(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_182, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(182, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_182(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_183, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(183, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_183(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_184, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(184, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_184(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_185, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(185, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_185(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_186, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(186, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_186(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_187, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(187, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_187(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_188, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(188, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_188(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_189, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(189, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_189(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_190, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(190, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_190(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_191, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(191, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_191(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_192, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(192, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_192(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_193, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(193, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_193(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_194, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(194, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_194(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_195, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(195, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_195(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_196, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(196, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_196(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_197, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(197, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_197(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_198, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(198, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_198(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_199, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(199, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_199(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_200, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(200, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_200(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_201, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(201, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_201(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_202, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(202, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_202(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_203, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(203, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_203(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_204, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(204, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_204(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_205, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(205, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_205(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_206, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(206, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_206(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_207, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(207, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_207(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_208, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(208, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_208(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_209, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(209, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_209(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_210, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(210, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_210(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_211, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(211, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_211(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_212, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(212, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_212(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_213, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(213, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_213(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_214, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(214, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_214(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_215, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(215, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_215(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_216, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(216, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_216(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_217, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(217, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_217(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_218, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(218, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_218(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_219, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(219, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_219(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_220, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(220, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_220(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_221, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(221, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_221(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_222, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(222, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_222(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_223, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(223, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_223(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_224, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(224, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_224(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_225, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(225, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_225(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_226, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(226, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_226(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_227, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(227, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_227(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_228, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(228, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_228(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_229, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(229, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_229(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_230, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(230, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_230(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_231, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(231, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_231(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_232, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(232, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_232(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_233, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(233, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_233(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_234, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(234, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_234(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_235, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(235, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_235(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_236, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(236, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_236(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_237, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(237, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_237(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_238, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(238, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_238(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_239, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(239, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_239(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_240, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(240, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_240(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_241, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(241, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_241(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_242, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(242, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_242(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_243, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(243, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_243(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_244, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(244, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_244(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_245, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(245, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_245(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_246, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(246, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_246(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_247, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(247, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_247(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_248, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(248, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_248(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_249, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(249, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_249(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_250, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(250, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_250(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_251, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(251, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_251(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_252, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(252, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_252(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_253, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(253, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_253(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_254, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(254, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_254(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_255, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(255, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_255(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_256, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(256, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+# define BOOST_PP_LIST_FOLD_LEFT_256(o, s, l) BOOST_PP_IIF(BOOST_PP_LIST_IS_CONS(l), BOOST_PP_LIST_FOLD_LEFT_257, s BOOST_PP_TUPLE_EAT_3)(o, BOOST_PP_EXPR_IIF(BOOST_PP_LIST_IS_CONS(l), o)(257, s, BOOST_PP_LIST_FIRST(l)), BOOST_PP_LIST_REST(l))
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/list/detail/fold_right.hpp b/third_party/boost/boost/preprocessor/list/detail/fold_right.hpp
new file mode 100644
index 0000000..29146d5
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/list/detail/fold_right.hpp
@@ -0,0 +1,277 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_LIST_DETAIL_FOLD_RIGHT_HPP
+# define BOOST_PREPROCESSOR_LIST_DETAIL_FOLD_RIGHT_HPP
+#
+# include <boost/preprocessor/list/fold_left.hpp>
+# include <boost/preprocessor/list/reverse.hpp>
+#
+# define BOOST_PP_LIST_FOLD_RIGHT_1(o, s, l) BOOST_PP_LIST_FOLD_LEFT_1(o, s, BOOST_PP_LIST_REVERSE_D(1, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_2(o, s, l) BOOST_PP_LIST_FOLD_LEFT_2(o, s, BOOST_PP_LIST_REVERSE_D(2, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_3(o, s, l) BOOST_PP_LIST_FOLD_LEFT_3(o, s, BOOST_PP_LIST_REVERSE_D(3, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_4(o, s, l) BOOST_PP_LIST_FOLD_LEFT_4(o, s, BOOST_PP_LIST_REVERSE_D(4, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_5(o, s, l) BOOST_PP_LIST_FOLD_LEFT_5(o, s, BOOST_PP_LIST_REVERSE_D(5, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_6(o, s, l) BOOST_PP_LIST_FOLD_LEFT_6(o, s, BOOST_PP_LIST_REVERSE_D(6, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_7(o, s, l) BOOST_PP_LIST_FOLD_LEFT_7(o, s, BOOST_PP_LIST_REVERSE_D(7, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_8(o, s, l) BOOST_PP_LIST_FOLD_LEFT_8(o, s, BOOST_PP_LIST_REVERSE_D(8, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_9(o, s, l) BOOST_PP_LIST_FOLD_LEFT_9(o, s, BOOST_PP_LIST_REVERSE_D(9, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_10(o, s, l) BOOST_PP_LIST_FOLD_LEFT_10(o, s, BOOST_PP_LIST_REVERSE_D(10, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_11(o, s, l) BOOST_PP_LIST_FOLD_LEFT_11(o, s, BOOST_PP_LIST_REVERSE_D(11, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_12(o, s, l) BOOST_PP_LIST_FOLD_LEFT_12(o, s, BOOST_PP_LIST_REVERSE_D(12, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_13(o, s, l) BOOST_PP_LIST_FOLD_LEFT_13(o, s, BOOST_PP_LIST_REVERSE_D(13, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_14(o, s, l) BOOST_PP_LIST_FOLD_LEFT_14(o, s, BOOST_PP_LIST_REVERSE_D(14, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_15(o, s, l) BOOST_PP_LIST_FOLD_LEFT_15(o, s, BOOST_PP_LIST_REVERSE_D(15, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_16(o, s, l) BOOST_PP_LIST_FOLD_LEFT_16(o, s, BOOST_PP_LIST_REVERSE_D(16, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_17(o, s, l) BOOST_PP_LIST_FOLD_LEFT_17(o, s, BOOST_PP_LIST_REVERSE_D(17, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_18(o, s, l) BOOST_PP_LIST_FOLD_LEFT_18(o, s, BOOST_PP_LIST_REVERSE_D(18, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_19(o, s, l) BOOST_PP_LIST_FOLD_LEFT_19(o, s, BOOST_PP_LIST_REVERSE_D(19, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_20(o, s, l) BOOST_PP_LIST_FOLD_LEFT_20(o, s, BOOST_PP_LIST_REVERSE_D(20, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_21(o, s, l) BOOST_PP_LIST_FOLD_LEFT_21(o, s, BOOST_PP_LIST_REVERSE_D(21, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_22(o, s, l) BOOST_PP_LIST_FOLD_LEFT_22(o, s, BOOST_PP_LIST_REVERSE_D(22, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_23(o, s, l) BOOST_PP_LIST_FOLD_LEFT_23(o, s, BOOST_PP_LIST_REVERSE_D(23, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_24(o, s, l) BOOST_PP_LIST_FOLD_LEFT_24(o, s, BOOST_PP_LIST_REVERSE_D(24, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_25(o, s, l) BOOST_PP_LIST_FOLD_LEFT_25(o, s, BOOST_PP_LIST_REVERSE_D(25, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_26(o, s, l) BOOST_PP_LIST_FOLD_LEFT_26(o, s, BOOST_PP_LIST_REVERSE_D(26, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_27(o, s, l) BOOST_PP_LIST_FOLD_LEFT_27(o, s, BOOST_PP_LIST_REVERSE_D(27, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_28(o, s, l) BOOST_PP_LIST_FOLD_LEFT_28(o, s, BOOST_PP_LIST_REVERSE_D(28, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_29(o, s, l) BOOST_PP_LIST_FOLD_LEFT_29(o, s, BOOST_PP_LIST_REVERSE_D(29, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_30(o, s, l) BOOST_PP_LIST_FOLD_LEFT_30(o, s, BOOST_PP_LIST_REVERSE_D(30, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_31(o, s, l) BOOST_PP_LIST_FOLD_LEFT_31(o, s, BOOST_PP_LIST_REVERSE_D(31, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_32(o, s, l) BOOST_PP_LIST_FOLD_LEFT_32(o, s, BOOST_PP_LIST_REVERSE_D(32, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_33(o, s, l) BOOST_PP_LIST_FOLD_LEFT_33(o, s, BOOST_PP_LIST_REVERSE_D(33, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_34(o, s, l) BOOST_PP_LIST_FOLD_LEFT_34(o, s, BOOST_PP_LIST_REVERSE_D(34, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_35(o, s, l) BOOST_PP_LIST_FOLD_LEFT_35(o, s, BOOST_PP_LIST_REVERSE_D(35, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_36(o, s, l) BOOST_PP_LIST_FOLD_LEFT_36(o, s, BOOST_PP_LIST_REVERSE_D(36, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_37(o, s, l) BOOST_PP_LIST_FOLD_LEFT_37(o, s, BOOST_PP_LIST_REVERSE_D(37, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_38(o, s, l) BOOST_PP_LIST_FOLD_LEFT_38(o, s, BOOST_PP_LIST_REVERSE_D(38, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_39(o, s, l) BOOST_PP_LIST_FOLD_LEFT_39(o, s, BOOST_PP_LIST_REVERSE_D(39, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_40(o, s, l) BOOST_PP_LIST_FOLD_LEFT_40(o, s, BOOST_PP_LIST_REVERSE_D(40, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_41(o, s, l) BOOST_PP_LIST_FOLD_LEFT_41(o, s, BOOST_PP_LIST_REVERSE_D(41, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_42(o, s, l) BOOST_PP_LIST_FOLD_LEFT_42(o, s, BOOST_PP_LIST_REVERSE_D(42, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_43(o, s, l) BOOST_PP_LIST_FOLD_LEFT_43(o, s, BOOST_PP_LIST_REVERSE_D(43, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_44(o, s, l) BOOST_PP_LIST_FOLD_LEFT_44(o, s, BOOST_PP_LIST_REVERSE_D(44, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_45(o, s, l) BOOST_PP_LIST_FOLD_LEFT_45(o, s, BOOST_PP_LIST_REVERSE_D(45, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_46(o, s, l) BOOST_PP_LIST_FOLD_LEFT_46(o, s, BOOST_PP_LIST_REVERSE_D(46, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_47(o, s, l) BOOST_PP_LIST_FOLD_LEFT_47(o, s, BOOST_PP_LIST_REVERSE_D(47, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_48(o, s, l) BOOST_PP_LIST_FOLD_LEFT_48(o, s, BOOST_PP_LIST_REVERSE_D(48, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_49(o, s, l) BOOST_PP_LIST_FOLD_LEFT_49(o, s, BOOST_PP_LIST_REVERSE_D(49, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_50(o, s, l) BOOST_PP_LIST_FOLD_LEFT_50(o, s, BOOST_PP_LIST_REVERSE_D(50, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_51(o, s, l) BOOST_PP_LIST_FOLD_LEFT_51(o, s, BOOST_PP_LIST_REVERSE_D(51, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_52(o, s, l) BOOST_PP_LIST_FOLD_LEFT_52(o, s, BOOST_PP_LIST_REVERSE_D(52, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_53(o, s, l) BOOST_PP_LIST_FOLD_LEFT_53(o, s, BOOST_PP_LIST_REVERSE_D(53, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_54(o, s, l) BOOST_PP_LIST_FOLD_LEFT_54(o, s, BOOST_PP_LIST_REVERSE_D(54, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_55(o, s, l) BOOST_PP_LIST_FOLD_LEFT_55(o, s, BOOST_PP_LIST_REVERSE_D(55, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_56(o, s, l) BOOST_PP_LIST_FOLD_LEFT_56(o, s, BOOST_PP_LIST_REVERSE_D(56, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_57(o, s, l) BOOST_PP_LIST_FOLD_LEFT_57(o, s, BOOST_PP_LIST_REVERSE_D(57, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_58(o, s, l) BOOST_PP_LIST_FOLD_LEFT_58(o, s, BOOST_PP_LIST_REVERSE_D(58, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_59(o, s, l) BOOST_PP_LIST_FOLD_LEFT_59(o, s, BOOST_PP_LIST_REVERSE_D(59, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_60(o, s, l) BOOST_PP_LIST_FOLD_LEFT_60(o, s, BOOST_PP_LIST_REVERSE_D(60, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_61(o, s, l) BOOST_PP_LIST_FOLD_LEFT_61(o, s, BOOST_PP_LIST_REVERSE_D(61, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_62(o, s, l) BOOST_PP_LIST_FOLD_LEFT_62(o, s, BOOST_PP_LIST_REVERSE_D(62, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_63(o, s, l) BOOST_PP_LIST_FOLD_LEFT_63(o, s, BOOST_PP_LIST_REVERSE_D(63, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_64(o, s, l) BOOST_PP_LIST_FOLD_LEFT_64(o, s, BOOST_PP_LIST_REVERSE_D(64, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_65(o, s, l) BOOST_PP_LIST_FOLD_LEFT_65(o, s, BOOST_PP_LIST_REVERSE_D(65, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_66(o, s, l) BOOST_PP_LIST_FOLD_LEFT_66(o, s, BOOST_PP_LIST_REVERSE_D(66, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_67(o, s, l) BOOST_PP_LIST_FOLD_LEFT_67(o, s, BOOST_PP_LIST_REVERSE_D(67, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_68(o, s, l) BOOST_PP_LIST_FOLD_LEFT_68(o, s, BOOST_PP_LIST_REVERSE_D(68, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_69(o, s, l) BOOST_PP_LIST_FOLD_LEFT_69(o, s, BOOST_PP_LIST_REVERSE_D(69, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_70(o, s, l) BOOST_PP_LIST_FOLD_LEFT_70(o, s, BOOST_PP_LIST_REVERSE_D(70, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_71(o, s, l) BOOST_PP_LIST_FOLD_LEFT_71(o, s, BOOST_PP_LIST_REVERSE_D(71, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_72(o, s, l) BOOST_PP_LIST_FOLD_LEFT_72(o, s, BOOST_PP_LIST_REVERSE_D(72, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_73(o, s, l) BOOST_PP_LIST_FOLD_LEFT_73(o, s, BOOST_PP_LIST_REVERSE_D(73, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_74(o, s, l) BOOST_PP_LIST_FOLD_LEFT_74(o, s, BOOST_PP_LIST_REVERSE_D(74, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_75(o, s, l) BOOST_PP_LIST_FOLD_LEFT_75(o, s, BOOST_PP_LIST_REVERSE_D(75, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_76(o, s, l) BOOST_PP_LIST_FOLD_LEFT_76(o, s, BOOST_PP_LIST_REVERSE_D(76, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_77(o, s, l) BOOST_PP_LIST_FOLD_LEFT_77(o, s, BOOST_PP_LIST_REVERSE_D(77, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_78(o, s, l) BOOST_PP_LIST_FOLD_LEFT_78(o, s, BOOST_PP_LIST_REVERSE_D(78, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_79(o, s, l) BOOST_PP_LIST_FOLD_LEFT_79(o, s, BOOST_PP_LIST_REVERSE_D(79, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_80(o, s, l) BOOST_PP_LIST_FOLD_LEFT_80(o, s, BOOST_PP_LIST_REVERSE_D(80, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_81(o, s, l) BOOST_PP_LIST_FOLD_LEFT_81(o, s, BOOST_PP_LIST_REVERSE_D(81, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_82(o, s, l) BOOST_PP_LIST_FOLD_LEFT_82(o, s, BOOST_PP_LIST_REVERSE_D(82, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_83(o, s, l) BOOST_PP_LIST_FOLD_LEFT_83(o, s, BOOST_PP_LIST_REVERSE_D(83, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_84(o, s, l) BOOST_PP_LIST_FOLD_LEFT_84(o, s, BOOST_PP_LIST_REVERSE_D(84, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_85(o, s, l) BOOST_PP_LIST_FOLD_LEFT_85(o, s, BOOST_PP_LIST_REVERSE_D(85, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_86(o, s, l) BOOST_PP_LIST_FOLD_LEFT_86(o, s, BOOST_PP_LIST_REVERSE_D(86, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_87(o, s, l) BOOST_PP_LIST_FOLD_LEFT_87(o, s, BOOST_PP_LIST_REVERSE_D(87, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_88(o, s, l) BOOST_PP_LIST_FOLD_LEFT_88(o, s, BOOST_PP_LIST_REVERSE_D(88, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_89(o, s, l) BOOST_PP_LIST_FOLD_LEFT_89(o, s, BOOST_PP_LIST_REVERSE_D(89, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_90(o, s, l) BOOST_PP_LIST_FOLD_LEFT_90(o, s, BOOST_PP_LIST_REVERSE_D(90, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_91(o, s, l) BOOST_PP_LIST_FOLD_LEFT_91(o, s, BOOST_PP_LIST_REVERSE_D(91, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_92(o, s, l) BOOST_PP_LIST_FOLD_LEFT_92(o, s, BOOST_PP_LIST_REVERSE_D(92, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_93(o, s, l) BOOST_PP_LIST_FOLD_LEFT_93(o, s, BOOST_PP_LIST_REVERSE_D(93, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_94(o, s, l) BOOST_PP_LIST_FOLD_LEFT_94(o, s, BOOST_PP_LIST_REVERSE_D(94, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_95(o, s, l) BOOST_PP_LIST_FOLD_LEFT_95(o, s, BOOST_PP_LIST_REVERSE_D(95, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_96(o, s, l) BOOST_PP_LIST_FOLD_LEFT_96(o, s, BOOST_PP_LIST_REVERSE_D(96, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_97(o, s, l) BOOST_PP_LIST_FOLD_LEFT_97(o, s, BOOST_PP_LIST_REVERSE_D(97, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_98(o, s, l) BOOST_PP_LIST_FOLD_LEFT_98(o, s, BOOST_PP_LIST_REVERSE_D(98, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_99(o, s, l) BOOST_PP_LIST_FOLD_LEFT_99(o, s, BOOST_PP_LIST_REVERSE_D(99, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_100(o, s, l) BOOST_PP_LIST_FOLD_LEFT_100(o, s, BOOST_PP_LIST_REVERSE_D(100, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_101(o, s, l) BOOST_PP_LIST_FOLD_LEFT_101(o, s, BOOST_PP_LIST_REVERSE_D(101, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_102(o, s, l) BOOST_PP_LIST_FOLD_LEFT_102(o, s, BOOST_PP_LIST_REVERSE_D(102, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_103(o, s, l) BOOST_PP_LIST_FOLD_LEFT_103(o, s, BOOST_PP_LIST_REVERSE_D(103, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_104(o, s, l) BOOST_PP_LIST_FOLD_LEFT_104(o, s, BOOST_PP_LIST_REVERSE_D(104, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_105(o, s, l) BOOST_PP_LIST_FOLD_LEFT_105(o, s, BOOST_PP_LIST_REVERSE_D(105, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_106(o, s, l) BOOST_PP_LIST_FOLD_LEFT_106(o, s, BOOST_PP_LIST_REVERSE_D(106, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_107(o, s, l) BOOST_PP_LIST_FOLD_LEFT_107(o, s, BOOST_PP_LIST_REVERSE_D(107, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_108(o, s, l) BOOST_PP_LIST_FOLD_LEFT_108(o, s, BOOST_PP_LIST_REVERSE_D(108, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_109(o, s, l) BOOST_PP_LIST_FOLD_LEFT_109(o, s, BOOST_PP_LIST_REVERSE_D(109, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_110(o, s, l) BOOST_PP_LIST_FOLD_LEFT_110(o, s, BOOST_PP_LIST_REVERSE_D(110, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_111(o, s, l) BOOST_PP_LIST_FOLD_LEFT_111(o, s, BOOST_PP_LIST_REVERSE_D(111, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_112(o, s, l) BOOST_PP_LIST_FOLD_LEFT_112(o, s, BOOST_PP_LIST_REVERSE_D(112, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_113(o, s, l) BOOST_PP_LIST_FOLD_LEFT_113(o, s, BOOST_PP_LIST_REVERSE_D(113, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_114(o, s, l) BOOST_PP_LIST_FOLD_LEFT_114(o, s, BOOST_PP_LIST_REVERSE_D(114, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_115(o, s, l) BOOST_PP_LIST_FOLD_LEFT_115(o, s, BOOST_PP_LIST_REVERSE_D(115, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_116(o, s, l) BOOST_PP_LIST_FOLD_LEFT_116(o, s, BOOST_PP_LIST_REVERSE_D(116, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_117(o, s, l) BOOST_PP_LIST_FOLD_LEFT_117(o, s, BOOST_PP_LIST_REVERSE_D(117, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_118(o, s, l) BOOST_PP_LIST_FOLD_LEFT_118(o, s, BOOST_PP_LIST_REVERSE_D(118, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_119(o, s, l) BOOST_PP_LIST_FOLD_LEFT_119(o, s, BOOST_PP_LIST_REVERSE_D(119, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_120(o, s, l) BOOST_PP_LIST_FOLD_LEFT_120(o, s, BOOST_PP_LIST_REVERSE_D(120, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_121(o, s, l) BOOST_PP_LIST_FOLD_LEFT_121(o, s, BOOST_PP_LIST_REVERSE_D(121, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_122(o, s, l) BOOST_PP_LIST_FOLD_LEFT_122(o, s, BOOST_PP_LIST_REVERSE_D(122, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_123(o, s, l) BOOST_PP_LIST_FOLD_LEFT_123(o, s, BOOST_PP_LIST_REVERSE_D(123, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_124(o, s, l) BOOST_PP_LIST_FOLD_LEFT_124(o, s, BOOST_PP_LIST_REVERSE_D(124, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_125(o, s, l) BOOST_PP_LIST_FOLD_LEFT_125(o, s, BOOST_PP_LIST_REVERSE_D(125, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_126(o, s, l) BOOST_PP_LIST_FOLD_LEFT_126(o, s, BOOST_PP_LIST_REVERSE_D(126, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_127(o, s, l) BOOST_PP_LIST_FOLD_LEFT_127(o, s, BOOST_PP_LIST_REVERSE_D(127, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_128(o, s, l) BOOST_PP_LIST_FOLD_LEFT_128(o, s, BOOST_PP_LIST_REVERSE_D(128, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_129(o, s, l) BOOST_PP_LIST_FOLD_LEFT_129(o, s, BOOST_PP_LIST_REVERSE_D(129, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_130(o, s, l) BOOST_PP_LIST_FOLD_LEFT_130(o, s, BOOST_PP_LIST_REVERSE_D(130, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_131(o, s, l) BOOST_PP_LIST_FOLD_LEFT_131(o, s, BOOST_PP_LIST_REVERSE_D(131, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_132(o, s, l) BOOST_PP_LIST_FOLD_LEFT_132(o, s, BOOST_PP_LIST_REVERSE_D(132, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_133(o, s, l) BOOST_PP_LIST_FOLD_LEFT_133(o, s, BOOST_PP_LIST_REVERSE_D(133, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_134(o, s, l) BOOST_PP_LIST_FOLD_LEFT_134(o, s, BOOST_PP_LIST_REVERSE_D(134, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_135(o, s, l) BOOST_PP_LIST_FOLD_LEFT_135(o, s, BOOST_PP_LIST_REVERSE_D(135, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_136(o, s, l) BOOST_PP_LIST_FOLD_LEFT_136(o, s, BOOST_PP_LIST_REVERSE_D(136, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_137(o, s, l) BOOST_PP_LIST_FOLD_LEFT_137(o, s, BOOST_PP_LIST_REVERSE_D(137, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_138(o, s, l) BOOST_PP_LIST_FOLD_LEFT_138(o, s, BOOST_PP_LIST_REVERSE_D(138, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_139(o, s, l) BOOST_PP_LIST_FOLD_LEFT_139(o, s, BOOST_PP_LIST_REVERSE_D(139, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_140(o, s, l) BOOST_PP_LIST_FOLD_LEFT_140(o, s, BOOST_PP_LIST_REVERSE_D(140, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_141(o, s, l) BOOST_PP_LIST_FOLD_LEFT_141(o, s, BOOST_PP_LIST_REVERSE_D(141, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_142(o, s, l) BOOST_PP_LIST_FOLD_LEFT_142(o, s, BOOST_PP_LIST_REVERSE_D(142, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_143(o, s, l) BOOST_PP_LIST_FOLD_LEFT_143(o, s, BOOST_PP_LIST_REVERSE_D(143, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_144(o, s, l) BOOST_PP_LIST_FOLD_LEFT_144(o, s, BOOST_PP_LIST_REVERSE_D(144, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_145(o, s, l) BOOST_PP_LIST_FOLD_LEFT_145(o, s, BOOST_PP_LIST_REVERSE_D(145, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_146(o, s, l) BOOST_PP_LIST_FOLD_LEFT_146(o, s, BOOST_PP_LIST_REVERSE_D(146, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_147(o, s, l) BOOST_PP_LIST_FOLD_LEFT_147(o, s, BOOST_PP_LIST_REVERSE_D(147, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_148(o, s, l) BOOST_PP_LIST_FOLD_LEFT_148(o, s, BOOST_PP_LIST_REVERSE_D(148, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_149(o, s, l) BOOST_PP_LIST_FOLD_LEFT_149(o, s, BOOST_PP_LIST_REVERSE_D(149, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_150(o, s, l) BOOST_PP_LIST_FOLD_LEFT_150(o, s, BOOST_PP_LIST_REVERSE_D(150, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_151(o, s, l) BOOST_PP_LIST_FOLD_LEFT_151(o, s, BOOST_PP_LIST_REVERSE_D(151, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_152(o, s, l) BOOST_PP_LIST_FOLD_LEFT_152(o, s, BOOST_PP_LIST_REVERSE_D(152, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_153(o, s, l) BOOST_PP_LIST_FOLD_LEFT_153(o, s, BOOST_PP_LIST_REVERSE_D(153, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_154(o, s, l) BOOST_PP_LIST_FOLD_LEFT_154(o, s, BOOST_PP_LIST_REVERSE_D(154, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_155(o, s, l) BOOST_PP_LIST_FOLD_LEFT_155(o, s, BOOST_PP_LIST_REVERSE_D(155, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_156(o, s, l) BOOST_PP_LIST_FOLD_LEFT_156(o, s, BOOST_PP_LIST_REVERSE_D(156, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_157(o, s, l) BOOST_PP_LIST_FOLD_LEFT_157(o, s, BOOST_PP_LIST_REVERSE_D(157, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_158(o, s, l) BOOST_PP_LIST_FOLD_LEFT_158(o, s, BOOST_PP_LIST_REVERSE_D(158, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_159(o, s, l) BOOST_PP_LIST_FOLD_LEFT_159(o, s, BOOST_PP_LIST_REVERSE_D(159, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_160(o, s, l) BOOST_PP_LIST_FOLD_LEFT_160(o, s, BOOST_PP_LIST_REVERSE_D(160, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_161(o, s, l) BOOST_PP_LIST_FOLD_LEFT_161(o, s, BOOST_PP_LIST_REVERSE_D(161, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_162(o, s, l) BOOST_PP_LIST_FOLD_LEFT_162(o, s, BOOST_PP_LIST_REVERSE_D(162, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_163(o, s, l) BOOST_PP_LIST_FOLD_LEFT_163(o, s, BOOST_PP_LIST_REVERSE_D(163, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_164(o, s, l) BOOST_PP_LIST_FOLD_LEFT_164(o, s, BOOST_PP_LIST_REVERSE_D(164, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_165(o, s, l) BOOST_PP_LIST_FOLD_LEFT_165(o, s, BOOST_PP_LIST_REVERSE_D(165, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_166(o, s, l) BOOST_PP_LIST_FOLD_LEFT_166(o, s, BOOST_PP_LIST_REVERSE_D(166, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_167(o, s, l) BOOST_PP_LIST_FOLD_LEFT_167(o, s, BOOST_PP_LIST_REVERSE_D(167, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_168(o, s, l) BOOST_PP_LIST_FOLD_LEFT_168(o, s, BOOST_PP_LIST_REVERSE_D(168, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_169(o, s, l) BOOST_PP_LIST_FOLD_LEFT_169(o, s, BOOST_PP_LIST_REVERSE_D(169, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_170(o, s, l) BOOST_PP_LIST_FOLD_LEFT_170(o, s, BOOST_PP_LIST_REVERSE_D(170, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_171(o, s, l) BOOST_PP_LIST_FOLD_LEFT_171(o, s, BOOST_PP_LIST_REVERSE_D(171, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_172(o, s, l) BOOST_PP_LIST_FOLD_LEFT_172(o, s, BOOST_PP_LIST_REVERSE_D(172, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_173(o, s, l) BOOST_PP_LIST_FOLD_LEFT_173(o, s, BOOST_PP_LIST_REVERSE_D(173, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_174(o, s, l) BOOST_PP_LIST_FOLD_LEFT_174(o, s, BOOST_PP_LIST_REVERSE_D(174, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_175(o, s, l) BOOST_PP_LIST_FOLD_LEFT_175(o, s, BOOST_PP_LIST_REVERSE_D(175, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_176(o, s, l) BOOST_PP_LIST_FOLD_LEFT_176(o, s, BOOST_PP_LIST_REVERSE_D(176, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_177(o, s, l) BOOST_PP_LIST_FOLD_LEFT_177(o, s, BOOST_PP_LIST_REVERSE_D(177, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_178(o, s, l) BOOST_PP_LIST_FOLD_LEFT_178(o, s, BOOST_PP_LIST_REVERSE_D(178, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_179(o, s, l) BOOST_PP_LIST_FOLD_LEFT_179(o, s, BOOST_PP_LIST_REVERSE_D(179, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_180(o, s, l) BOOST_PP_LIST_FOLD_LEFT_180(o, s, BOOST_PP_LIST_REVERSE_D(180, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_181(o, s, l) BOOST_PP_LIST_FOLD_LEFT_181(o, s, BOOST_PP_LIST_REVERSE_D(181, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_182(o, s, l) BOOST_PP_LIST_FOLD_LEFT_182(o, s, BOOST_PP_LIST_REVERSE_D(182, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_183(o, s, l) BOOST_PP_LIST_FOLD_LEFT_183(o, s, BOOST_PP_LIST_REVERSE_D(183, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_184(o, s, l) BOOST_PP_LIST_FOLD_LEFT_184(o, s, BOOST_PP_LIST_REVERSE_D(184, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_185(o, s, l) BOOST_PP_LIST_FOLD_LEFT_185(o, s, BOOST_PP_LIST_REVERSE_D(185, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_186(o, s, l) BOOST_PP_LIST_FOLD_LEFT_186(o, s, BOOST_PP_LIST_REVERSE_D(186, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_187(o, s, l) BOOST_PP_LIST_FOLD_LEFT_187(o, s, BOOST_PP_LIST_REVERSE_D(187, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_188(o, s, l) BOOST_PP_LIST_FOLD_LEFT_188(o, s, BOOST_PP_LIST_REVERSE_D(188, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_189(o, s, l) BOOST_PP_LIST_FOLD_LEFT_189(o, s, BOOST_PP_LIST_REVERSE_D(189, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_190(o, s, l) BOOST_PP_LIST_FOLD_LEFT_190(o, s, BOOST_PP_LIST_REVERSE_D(190, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_191(o, s, l) BOOST_PP_LIST_FOLD_LEFT_191(o, s, BOOST_PP_LIST_REVERSE_D(191, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_192(o, s, l) BOOST_PP_LIST_FOLD_LEFT_192(o, s, BOOST_PP_LIST_REVERSE_D(192, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_193(o, s, l) BOOST_PP_LIST_FOLD_LEFT_193(o, s, BOOST_PP_LIST_REVERSE_D(193, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_194(o, s, l) BOOST_PP_LIST_FOLD_LEFT_194(o, s, BOOST_PP_LIST_REVERSE_D(194, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_195(o, s, l) BOOST_PP_LIST_FOLD_LEFT_195(o, s, BOOST_PP_LIST_REVERSE_D(195, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_196(o, s, l) BOOST_PP_LIST_FOLD_LEFT_196(o, s, BOOST_PP_LIST_REVERSE_D(196, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_197(o, s, l) BOOST_PP_LIST_FOLD_LEFT_197(o, s, BOOST_PP_LIST_REVERSE_D(197, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_198(o, s, l) BOOST_PP_LIST_FOLD_LEFT_198(o, s, BOOST_PP_LIST_REVERSE_D(198, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_199(o, s, l) BOOST_PP_LIST_FOLD_LEFT_199(o, s, BOOST_PP_LIST_REVERSE_D(199, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_200(o, s, l) BOOST_PP_LIST_FOLD_LEFT_200(o, s, BOOST_PP_LIST_REVERSE_D(200, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_201(o, s, l) BOOST_PP_LIST_FOLD_LEFT_201(o, s, BOOST_PP_LIST_REVERSE_D(201, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_202(o, s, l) BOOST_PP_LIST_FOLD_LEFT_202(o, s, BOOST_PP_LIST_REVERSE_D(202, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_203(o, s, l) BOOST_PP_LIST_FOLD_LEFT_203(o, s, BOOST_PP_LIST_REVERSE_D(203, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_204(o, s, l) BOOST_PP_LIST_FOLD_LEFT_204(o, s, BOOST_PP_LIST_REVERSE_D(204, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_205(o, s, l) BOOST_PP_LIST_FOLD_LEFT_205(o, s, BOOST_PP_LIST_REVERSE_D(205, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_206(o, s, l) BOOST_PP_LIST_FOLD_LEFT_206(o, s, BOOST_PP_LIST_REVERSE_D(206, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_207(o, s, l) BOOST_PP_LIST_FOLD_LEFT_207(o, s, BOOST_PP_LIST_REVERSE_D(207, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_208(o, s, l) BOOST_PP_LIST_FOLD_LEFT_208(o, s, BOOST_PP_LIST_REVERSE_D(208, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_209(o, s, l) BOOST_PP_LIST_FOLD_LEFT_209(o, s, BOOST_PP_LIST_REVERSE_D(209, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_210(o, s, l) BOOST_PP_LIST_FOLD_LEFT_210(o, s, BOOST_PP_LIST_REVERSE_D(210, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_211(o, s, l) BOOST_PP_LIST_FOLD_LEFT_211(o, s, BOOST_PP_LIST_REVERSE_D(211, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_212(o, s, l) BOOST_PP_LIST_FOLD_LEFT_212(o, s, BOOST_PP_LIST_REVERSE_D(212, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_213(o, s, l) BOOST_PP_LIST_FOLD_LEFT_213(o, s, BOOST_PP_LIST_REVERSE_D(213, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_214(o, s, l) BOOST_PP_LIST_FOLD_LEFT_214(o, s, BOOST_PP_LIST_REVERSE_D(214, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_215(o, s, l) BOOST_PP_LIST_FOLD_LEFT_215(o, s, BOOST_PP_LIST_REVERSE_D(215, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_216(o, s, l) BOOST_PP_LIST_FOLD_LEFT_216(o, s, BOOST_PP_LIST_REVERSE_D(216, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_217(o, s, l) BOOST_PP_LIST_FOLD_LEFT_217(o, s, BOOST_PP_LIST_REVERSE_D(217, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_218(o, s, l) BOOST_PP_LIST_FOLD_LEFT_218(o, s, BOOST_PP_LIST_REVERSE_D(218, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_219(o, s, l) BOOST_PP_LIST_FOLD_LEFT_219(o, s, BOOST_PP_LIST_REVERSE_D(219, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_220(o, s, l) BOOST_PP_LIST_FOLD_LEFT_220(o, s, BOOST_PP_LIST_REVERSE_D(220, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_221(o, s, l) BOOST_PP_LIST_FOLD_LEFT_221(o, s, BOOST_PP_LIST_REVERSE_D(221, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_222(o, s, l) BOOST_PP_LIST_FOLD_LEFT_222(o, s, BOOST_PP_LIST_REVERSE_D(222, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_223(o, s, l) BOOST_PP_LIST_FOLD_LEFT_223(o, s, BOOST_PP_LIST_REVERSE_D(223, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_224(o, s, l) BOOST_PP_LIST_FOLD_LEFT_224(o, s, BOOST_PP_LIST_REVERSE_D(224, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_225(o, s, l) BOOST_PP_LIST_FOLD_LEFT_225(o, s, BOOST_PP_LIST_REVERSE_D(225, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_226(o, s, l) BOOST_PP_LIST_FOLD_LEFT_226(o, s, BOOST_PP_LIST_REVERSE_D(226, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_227(o, s, l) BOOST_PP_LIST_FOLD_LEFT_227(o, s, BOOST_PP_LIST_REVERSE_D(227, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_228(o, s, l) BOOST_PP_LIST_FOLD_LEFT_228(o, s, BOOST_PP_LIST_REVERSE_D(228, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_229(o, s, l) BOOST_PP_LIST_FOLD_LEFT_229(o, s, BOOST_PP_LIST_REVERSE_D(229, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_230(o, s, l) BOOST_PP_LIST_FOLD_LEFT_230(o, s, BOOST_PP_LIST_REVERSE_D(230, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_231(o, s, l) BOOST_PP_LIST_FOLD_LEFT_231(o, s, BOOST_PP_LIST_REVERSE_D(231, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_232(o, s, l) BOOST_PP_LIST_FOLD_LEFT_232(o, s, BOOST_PP_LIST_REVERSE_D(232, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_233(o, s, l) BOOST_PP_LIST_FOLD_LEFT_233(o, s, BOOST_PP_LIST_REVERSE_D(233, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_234(o, s, l) BOOST_PP_LIST_FOLD_LEFT_234(o, s, BOOST_PP_LIST_REVERSE_D(234, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_235(o, s, l) BOOST_PP_LIST_FOLD_LEFT_235(o, s, BOOST_PP_LIST_REVERSE_D(235, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_236(o, s, l) BOOST_PP_LIST_FOLD_LEFT_236(o, s, BOOST_PP_LIST_REVERSE_D(236, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_237(o, s, l) BOOST_PP_LIST_FOLD_LEFT_237(o, s, BOOST_PP_LIST_REVERSE_D(237, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_238(o, s, l) BOOST_PP_LIST_FOLD_LEFT_238(o, s, BOOST_PP_LIST_REVERSE_D(238, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_239(o, s, l) BOOST_PP_LIST_FOLD_LEFT_239(o, s, BOOST_PP_LIST_REVERSE_D(239, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_240(o, s, l) BOOST_PP_LIST_FOLD_LEFT_240(o, s, BOOST_PP_LIST_REVERSE_D(240, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_241(o, s, l) BOOST_PP_LIST_FOLD_LEFT_241(o, s, BOOST_PP_LIST_REVERSE_D(241, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_242(o, s, l) BOOST_PP_LIST_FOLD_LEFT_242(o, s, BOOST_PP_LIST_REVERSE_D(242, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_243(o, s, l) BOOST_PP_LIST_FOLD_LEFT_243(o, s, BOOST_PP_LIST_REVERSE_D(243, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_244(o, s, l) BOOST_PP_LIST_FOLD_LEFT_244(o, s, BOOST_PP_LIST_REVERSE_D(244, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_245(o, s, l) BOOST_PP_LIST_FOLD_LEFT_245(o, s, BOOST_PP_LIST_REVERSE_D(245, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_246(o, s, l) BOOST_PP_LIST_FOLD_LEFT_246(o, s, BOOST_PP_LIST_REVERSE_D(246, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_247(o, s, l) BOOST_PP_LIST_FOLD_LEFT_247(o, s, BOOST_PP_LIST_REVERSE_D(247, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_248(o, s, l) BOOST_PP_LIST_FOLD_LEFT_248(o, s, BOOST_PP_LIST_REVERSE_D(248, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_249(o, s, l) BOOST_PP_LIST_FOLD_LEFT_249(o, s, BOOST_PP_LIST_REVERSE_D(249, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_250(o, s, l) BOOST_PP_LIST_FOLD_LEFT_250(o, s, BOOST_PP_LIST_REVERSE_D(250, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_251(o, s, l) BOOST_PP_LIST_FOLD_LEFT_251(o, s, BOOST_PP_LIST_REVERSE_D(251, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_252(o, s, l) BOOST_PP_LIST_FOLD_LEFT_252(o, s, BOOST_PP_LIST_REVERSE_D(252, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_253(o, s, l) BOOST_PP_LIST_FOLD_LEFT_253(o, s, BOOST_PP_LIST_REVERSE_D(253, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_254(o, s, l) BOOST_PP_LIST_FOLD_LEFT_254(o, s, BOOST_PP_LIST_REVERSE_D(254, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_255(o, s, l) BOOST_PP_LIST_FOLD_LEFT_255(o, s, BOOST_PP_LIST_REVERSE_D(255, l))
+# define BOOST_PP_LIST_FOLD_RIGHT_256(o, s, l) BOOST_PP_LIST_FOLD_LEFT_256(o, s, BOOST_PP_LIST_REVERSE_D(256, l))
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/list/fold_left.hpp b/third_party/boost/boost/preprocessor/list/fold_left.hpp
new file mode 100644
index 0000000..f235aec
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/list/fold_left.hpp
@@ -0,0 +1,303 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_LIST_FOLD_LEFT_HPP
+# define BOOST_PREPROCESSOR_LIST_FOLD_LEFT_HPP
+#
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/control/while.hpp>
+# include <boost/preprocessor/debug/error.hpp>
+# include <boost/preprocessor/detail/auto_rec.hpp>
+#
+# /* BOOST_PP_LIST_FOLD_LEFT */
+#
+# if 0
+# define BOOST_PP_LIST_FOLD_LEFT(op, state, list)
+# endif
+#
+# define BOOST_PP_LIST_FOLD_LEFT BOOST_PP_CAT(BOOST_PP_LIST_FOLD_LEFT_, BOOST_PP_AUTO_REC(BOOST_PP_WHILE_P, 256))
+#
+# define BOOST_PP_LIST_FOLD_LEFT_257(o, s, l) BOOST_PP_ERROR(0x0004)
+#
+# define BOOST_PP_LIST_FOLD_LEFT_D(d, o, s, l) BOOST_PP_LIST_FOLD_LEFT_ ## d(o, s, l)
+# define BOOST_PP_LIST_FOLD_LEFT_2ND BOOST_PP_LIST_FOLD_LEFT
+# define BOOST_PP_LIST_FOLD_LEFT_2ND_D BOOST_PP_LIST_FOLD_LEFT_D
+#
+# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# include <boost/preprocessor/list/detail/edg/fold_left.hpp>
+# elif BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_DMC()
+# include <boost/preprocessor/list/detail/dmc/fold_left.hpp>
+# else
+# include <boost/preprocessor/list/detail/fold_left.hpp>
+# endif
+#
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_NIL 1
+#
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_1(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_2(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_3(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_4(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_5(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_6(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_7(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_8(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_9(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_10(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_11(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_12(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_13(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_14(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_15(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_16(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_17(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_18(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_19(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_20(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_21(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_22(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_23(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_24(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_25(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_26(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_27(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_28(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_29(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_30(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_31(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_32(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_33(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_34(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_35(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_36(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_37(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_38(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_39(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_40(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_41(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_42(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_43(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_44(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_45(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_46(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_47(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_48(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_49(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_50(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_51(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_52(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_53(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_54(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_55(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_56(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_57(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_58(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_59(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_60(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_61(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_62(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_63(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_64(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_65(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_66(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_67(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_68(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_69(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_70(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_71(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_72(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_73(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_74(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_75(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_76(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_77(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_78(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_79(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_80(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_81(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_82(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_83(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_84(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_85(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_86(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_87(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_88(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_89(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_90(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_91(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_92(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_93(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_94(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_95(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_96(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_97(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_98(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_99(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_100(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_101(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_102(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_103(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_104(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_105(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_106(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_107(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_108(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_109(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_110(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_111(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_112(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_113(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_114(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_115(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_116(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_117(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_118(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_119(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_120(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_121(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_122(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_123(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_124(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_125(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_126(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_127(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_128(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_129(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_130(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_131(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_132(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_133(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_134(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_135(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_136(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_137(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_138(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_139(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_140(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_141(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_142(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_143(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_144(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_145(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_146(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_147(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_148(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_149(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_150(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_151(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_152(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_153(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_154(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_155(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_156(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_157(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_158(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_159(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_160(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_161(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_162(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_163(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_164(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_165(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_166(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_167(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_168(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_169(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_170(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_171(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_172(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_173(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_174(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_175(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_176(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_177(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_178(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_179(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_180(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_181(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_182(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_183(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_184(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_185(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_186(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_187(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_188(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_189(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_190(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_191(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_192(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_193(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_194(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_195(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_196(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_197(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_198(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_199(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_200(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_201(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_202(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_203(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_204(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_205(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_206(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_207(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_208(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_209(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_210(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_211(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_212(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_213(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_214(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_215(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_216(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_217(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_218(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_219(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_220(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_221(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_222(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_223(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_224(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_225(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_226(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_227(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_228(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_229(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_230(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_231(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_232(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_233(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_234(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_235(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_236(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_237(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_238(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_239(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_240(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_241(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_242(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_243(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_244(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_245(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_246(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_247(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_248(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_249(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_250(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_251(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_252(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_253(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_254(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_255(o, s, l) 0
+# define BOOST_PP_LIST_FOLD_LEFT_CHECK_BOOST_PP_LIST_FOLD_LEFT_256(o, s, l) 0
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/list/fold_right.hpp b/third_party/boost/boost/preprocessor/list/fold_right.hpp
new file mode 100644
index 0000000..ce18afe
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/list/fold_right.hpp
@@ -0,0 +1,40 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_LIST_FOLD_RIGHT_HPP
+# define BOOST_PREPROCESSOR_LIST_FOLD_RIGHT_HPP
+#
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/control/while.hpp>
+# include <boost/preprocessor/debug/error.hpp>
+# include <boost/preprocessor/detail/auto_rec.hpp>
+#
+# if 0
+# define BOOST_PP_LIST_FOLD_RIGHT(op, state, list)
+# endif
+#
+# define BOOST_PP_LIST_FOLD_RIGHT BOOST_PP_CAT(BOOST_PP_LIST_FOLD_RIGHT_, BOOST_PP_AUTO_REC(BOOST_PP_WHILE_P, 256))
+#
+# define BOOST_PP_LIST_FOLD_RIGHT_257(o, s, l) BOOST_PP_ERROR(0x0004)
+#
+# define BOOST_PP_LIST_FOLD_RIGHT_D(d, o, s, l) BOOST_PP_LIST_FOLD_RIGHT_ ## d(o, s, l)
+# define BOOST_PP_LIST_FOLD_RIGHT_2ND BOOST_PP_LIST_FOLD_RIGHT
+# define BOOST_PP_LIST_FOLD_RIGHT_2ND_D BOOST_PP_LIST_FOLD_RIGHT_D
+#
+# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# include <boost/preprocessor/list/detail/edg/fold_right.hpp>
+# else
+# include <boost/preprocessor/list/detail/fold_right.hpp>
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/list/reverse.hpp b/third_party/boost/boost/preprocessor/list/reverse.hpp
new file mode 100644
index 0000000..651da05
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/list/reverse.hpp
@@ -0,0 +1,40 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_LIST_REVERSE_HPP
+# define BOOST_PREPROCESSOR_LIST_REVERSE_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/list/fold_left.hpp>
+#
+# /* BOOST_PP_LIST_REVERSE */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_LIST_REVERSE(list) BOOST_PP_LIST_FOLD_LEFT(BOOST_PP_LIST_REVERSE_O, BOOST_PP_NIL, list)
+# else
+# define BOOST_PP_LIST_REVERSE(list) BOOST_PP_LIST_REVERSE_I(list)
+# define BOOST_PP_LIST_REVERSE_I(list) BOOST_PP_LIST_FOLD_LEFT(BOOST_PP_LIST_REVERSE_O, BOOST_PP_NIL, list)
+# endif
+#
+# define BOOST_PP_LIST_REVERSE_O(d, s, x) (x, s)
+#
+# /* BOOST_PP_LIST_REVERSE_D */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_LIST_REVERSE_D(d, list) BOOST_PP_LIST_FOLD_LEFT_ ## d(BOOST_PP_LIST_REVERSE_O, BOOST_PP_NIL, list)
+# else
+# define BOOST_PP_LIST_REVERSE_D(d, list) BOOST_PP_LIST_REVERSE_D_I(d, list)
+# define BOOST_PP_LIST_REVERSE_D_I(d, list) BOOST_PP_LIST_FOLD_LEFT_ ## d(BOOST_PP_LIST_REVERSE_O, BOOST_PP_NIL, list)
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/logical/and.hpp b/third_party/boost/boost/preprocessor/logical/and.hpp
new file mode 100644
index 0000000..8590365
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/logical/and.hpp
@@ -0,0 +1,30 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_LOGICAL_AND_HPP
+# define BOOST_PREPROCESSOR_LOGICAL_AND_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/logical/bool.hpp>
+# include <boost/preprocessor/logical/bitand.hpp>
+#
+# /* BOOST_PP_AND */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_AND(p, q) BOOST_PP_BITAND(BOOST_PP_BOOL(p), BOOST_PP_BOOL(q))
+# else
+# define BOOST_PP_AND(p, q) BOOST_PP_AND_I(p, q)
+# define BOOST_PP_AND_I(p, q) BOOST_PP_BITAND(BOOST_PP_BOOL(p), BOOST_PP_BOOL(q))
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/logical/bitand.hpp b/third_party/boost/boost/preprocessor/logical/bitand.hpp
new file mode 100644
index 0000000..74e9527
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/logical/bitand.hpp
@@ -0,0 +1,38 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_LOGICAL_BITAND_HPP
+# define BOOST_PREPROCESSOR_LOGICAL_BITAND_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+#
+# /* BOOST_PP_BITAND */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MWCC()
+# define BOOST_PP_BITAND(x, y) BOOST_PP_BITAND_I(x, y)
+# else
+# define BOOST_PP_BITAND(x, y) BOOST_PP_BITAND_OO((x, y))
+# define BOOST_PP_BITAND_OO(par) BOOST_PP_BITAND_I ## par
+# endif
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MSVC()
+# define BOOST_PP_BITAND_I(x, y) BOOST_PP_BITAND_ ## x ## y
+# else
+# define BOOST_PP_BITAND_I(x, y) BOOST_PP_BITAND_ID(BOOST_PP_BITAND_ ## x ## y)
+# define BOOST_PP_BITAND_ID(res) res
+# endif
+#
+# define BOOST_PP_BITAND_00 0
+# define BOOST_PP_BITAND_01 0
+# define BOOST_PP_BITAND_10 0
+# define BOOST_PP_BITAND_11 1
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/logical/bool.hpp b/third_party/boost/boost/preprocessor/logical/bool.hpp
new file mode 100644
index 0000000..fc01b5b
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/logical/bool.hpp
@@ -0,0 +1,288 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_LOGICAL_BOOL_HPP
+# define BOOST_PREPROCESSOR_LOGICAL_BOOL_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+#
+# /* BOOST_PP_BOOL */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MWCC()
+# define BOOST_PP_BOOL(x) BOOST_PP_BOOL_I(x)
+# else
+# define BOOST_PP_BOOL(x) BOOST_PP_BOOL_OO((x))
+# define BOOST_PP_BOOL_OO(par) BOOST_PP_BOOL_I ## par
+# endif
+#
+# define BOOST_PP_BOOL_I(x) BOOST_PP_BOOL_ ## x
+#
+# define BOOST_PP_BOOL_0 0
+# define BOOST_PP_BOOL_1 1
+# define BOOST_PP_BOOL_2 1
+# define BOOST_PP_BOOL_3 1
+# define BOOST_PP_BOOL_4 1
+# define BOOST_PP_BOOL_5 1
+# define BOOST_PP_BOOL_6 1
+# define BOOST_PP_BOOL_7 1
+# define BOOST_PP_BOOL_8 1
+# define BOOST_PP_BOOL_9 1
+# define BOOST_PP_BOOL_10 1
+# define BOOST_PP_BOOL_11 1
+# define BOOST_PP_BOOL_12 1
+# define BOOST_PP_BOOL_13 1
+# define BOOST_PP_BOOL_14 1
+# define BOOST_PP_BOOL_15 1
+# define BOOST_PP_BOOL_16 1
+# define BOOST_PP_BOOL_17 1
+# define BOOST_PP_BOOL_18 1
+# define BOOST_PP_BOOL_19 1
+# define BOOST_PP_BOOL_20 1
+# define BOOST_PP_BOOL_21 1
+# define BOOST_PP_BOOL_22 1
+# define BOOST_PP_BOOL_23 1
+# define BOOST_PP_BOOL_24 1
+# define BOOST_PP_BOOL_25 1
+# define BOOST_PP_BOOL_26 1
+# define BOOST_PP_BOOL_27 1
+# define BOOST_PP_BOOL_28 1
+# define BOOST_PP_BOOL_29 1
+# define BOOST_PP_BOOL_30 1
+# define BOOST_PP_BOOL_31 1
+# define BOOST_PP_BOOL_32 1
+# define BOOST_PP_BOOL_33 1
+# define BOOST_PP_BOOL_34 1
+# define BOOST_PP_BOOL_35 1
+# define BOOST_PP_BOOL_36 1
+# define BOOST_PP_BOOL_37 1
+# define BOOST_PP_BOOL_38 1
+# define BOOST_PP_BOOL_39 1
+# define BOOST_PP_BOOL_40 1
+# define BOOST_PP_BOOL_41 1
+# define BOOST_PP_BOOL_42 1
+# define BOOST_PP_BOOL_43 1
+# define BOOST_PP_BOOL_44 1
+# define BOOST_PP_BOOL_45 1
+# define BOOST_PP_BOOL_46 1
+# define BOOST_PP_BOOL_47 1
+# define BOOST_PP_BOOL_48 1
+# define BOOST_PP_BOOL_49 1
+# define BOOST_PP_BOOL_50 1
+# define BOOST_PP_BOOL_51 1
+# define BOOST_PP_BOOL_52 1
+# define BOOST_PP_BOOL_53 1
+# define BOOST_PP_BOOL_54 1
+# define BOOST_PP_BOOL_55 1
+# define BOOST_PP_BOOL_56 1
+# define BOOST_PP_BOOL_57 1
+# define BOOST_PP_BOOL_58 1
+# define BOOST_PP_BOOL_59 1
+# define BOOST_PP_BOOL_60 1
+# define BOOST_PP_BOOL_61 1
+# define BOOST_PP_BOOL_62 1
+# define BOOST_PP_BOOL_63 1
+# define BOOST_PP_BOOL_64 1
+# define BOOST_PP_BOOL_65 1
+# define BOOST_PP_BOOL_66 1
+# define BOOST_PP_BOOL_67 1
+# define BOOST_PP_BOOL_68 1
+# define BOOST_PP_BOOL_69 1
+# define BOOST_PP_BOOL_70 1
+# define BOOST_PP_BOOL_71 1
+# define BOOST_PP_BOOL_72 1
+# define BOOST_PP_BOOL_73 1
+# define BOOST_PP_BOOL_74 1
+# define BOOST_PP_BOOL_75 1
+# define BOOST_PP_BOOL_76 1
+# define BOOST_PP_BOOL_77 1
+# define BOOST_PP_BOOL_78 1
+# define BOOST_PP_BOOL_79 1
+# define BOOST_PP_BOOL_80 1
+# define BOOST_PP_BOOL_81 1
+# define BOOST_PP_BOOL_82 1
+# define BOOST_PP_BOOL_83 1
+# define BOOST_PP_BOOL_84 1
+# define BOOST_PP_BOOL_85 1
+# define BOOST_PP_BOOL_86 1
+# define BOOST_PP_BOOL_87 1
+# define BOOST_PP_BOOL_88 1
+# define BOOST_PP_BOOL_89 1
+# define BOOST_PP_BOOL_90 1
+# define BOOST_PP_BOOL_91 1
+# define BOOST_PP_BOOL_92 1
+# define BOOST_PP_BOOL_93 1
+# define BOOST_PP_BOOL_94 1
+# define BOOST_PP_BOOL_95 1
+# define BOOST_PP_BOOL_96 1
+# define BOOST_PP_BOOL_97 1
+# define BOOST_PP_BOOL_98 1
+# define BOOST_PP_BOOL_99 1
+# define BOOST_PP_BOOL_100 1
+# define BOOST_PP_BOOL_101 1
+# define BOOST_PP_BOOL_102 1
+# define BOOST_PP_BOOL_103 1
+# define BOOST_PP_BOOL_104 1
+# define BOOST_PP_BOOL_105 1
+# define BOOST_PP_BOOL_106 1
+# define BOOST_PP_BOOL_107 1
+# define BOOST_PP_BOOL_108 1
+# define BOOST_PP_BOOL_109 1
+# define BOOST_PP_BOOL_110 1
+# define BOOST_PP_BOOL_111 1
+# define BOOST_PP_BOOL_112 1
+# define BOOST_PP_BOOL_113 1
+# define BOOST_PP_BOOL_114 1
+# define BOOST_PP_BOOL_115 1
+# define BOOST_PP_BOOL_116 1
+# define BOOST_PP_BOOL_117 1
+# define BOOST_PP_BOOL_118 1
+# define BOOST_PP_BOOL_119 1
+# define BOOST_PP_BOOL_120 1
+# define BOOST_PP_BOOL_121 1
+# define BOOST_PP_BOOL_122 1
+# define BOOST_PP_BOOL_123 1
+# define BOOST_PP_BOOL_124 1
+# define BOOST_PP_BOOL_125 1
+# define BOOST_PP_BOOL_126 1
+# define BOOST_PP_BOOL_127 1
+# define BOOST_PP_BOOL_128 1
+# define BOOST_PP_BOOL_129 1
+# define BOOST_PP_BOOL_130 1
+# define BOOST_PP_BOOL_131 1
+# define BOOST_PP_BOOL_132 1
+# define BOOST_PP_BOOL_133 1
+# define BOOST_PP_BOOL_134 1
+# define BOOST_PP_BOOL_135 1
+# define BOOST_PP_BOOL_136 1
+# define BOOST_PP_BOOL_137 1
+# define BOOST_PP_BOOL_138 1
+# define BOOST_PP_BOOL_139 1
+# define BOOST_PP_BOOL_140 1
+# define BOOST_PP_BOOL_141 1
+# define BOOST_PP_BOOL_142 1
+# define BOOST_PP_BOOL_143 1
+# define BOOST_PP_BOOL_144 1
+# define BOOST_PP_BOOL_145 1
+# define BOOST_PP_BOOL_146 1
+# define BOOST_PP_BOOL_147 1
+# define BOOST_PP_BOOL_148 1
+# define BOOST_PP_BOOL_149 1
+# define BOOST_PP_BOOL_150 1
+# define BOOST_PP_BOOL_151 1
+# define BOOST_PP_BOOL_152 1
+# define BOOST_PP_BOOL_153 1
+# define BOOST_PP_BOOL_154 1
+# define BOOST_PP_BOOL_155 1
+# define BOOST_PP_BOOL_156 1
+# define BOOST_PP_BOOL_157 1
+# define BOOST_PP_BOOL_158 1
+# define BOOST_PP_BOOL_159 1
+# define BOOST_PP_BOOL_160 1
+# define BOOST_PP_BOOL_161 1
+# define BOOST_PP_BOOL_162 1
+# define BOOST_PP_BOOL_163 1
+# define BOOST_PP_BOOL_164 1
+# define BOOST_PP_BOOL_165 1
+# define BOOST_PP_BOOL_166 1
+# define BOOST_PP_BOOL_167 1
+# define BOOST_PP_BOOL_168 1
+# define BOOST_PP_BOOL_169 1
+# define BOOST_PP_BOOL_170 1
+# define BOOST_PP_BOOL_171 1
+# define BOOST_PP_BOOL_172 1
+# define BOOST_PP_BOOL_173 1
+# define BOOST_PP_BOOL_174 1
+# define BOOST_PP_BOOL_175 1
+# define BOOST_PP_BOOL_176 1
+# define BOOST_PP_BOOL_177 1
+# define BOOST_PP_BOOL_178 1
+# define BOOST_PP_BOOL_179 1
+# define BOOST_PP_BOOL_180 1
+# define BOOST_PP_BOOL_181 1
+# define BOOST_PP_BOOL_182 1
+# define BOOST_PP_BOOL_183 1
+# define BOOST_PP_BOOL_184 1
+# define BOOST_PP_BOOL_185 1
+# define BOOST_PP_BOOL_186 1
+# define BOOST_PP_BOOL_187 1
+# define BOOST_PP_BOOL_188 1
+# define BOOST_PP_BOOL_189 1
+# define BOOST_PP_BOOL_190 1
+# define BOOST_PP_BOOL_191 1
+# define BOOST_PP_BOOL_192 1
+# define BOOST_PP_BOOL_193 1
+# define BOOST_PP_BOOL_194 1
+# define BOOST_PP_BOOL_195 1
+# define BOOST_PP_BOOL_196 1
+# define BOOST_PP_BOOL_197 1
+# define BOOST_PP_BOOL_198 1
+# define BOOST_PP_BOOL_199 1
+# define BOOST_PP_BOOL_200 1
+# define BOOST_PP_BOOL_201 1
+# define BOOST_PP_BOOL_202 1
+# define BOOST_PP_BOOL_203 1
+# define BOOST_PP_BOOL_204 1
+# define BOOST_PP_BOOL_205 1
+# define BOOST_PP_BOOL_206 1
+# define BOOST_PP_BOOL_207 1
+# define BOOST_PP_BOOL_208 1
+# define BOOST_PP_BOOL_209 1
+# define BOOST_PP_BOOL_210 1
+# define BOOST_PP_BOOL_211 1
+# define BOOST_PP_BOOL_212 1
+# define BOOST_PP_BOOL_213 1
+# define BOOST_PP_BOOL_214 1
+# define BOOST_PP_BOOL_215 1
+# define BOOST_PP_BOOL_216 1
+# define BOOST_PP_BOOL_217 1
+# define BOOST_PP_BOOL_218 1
+# define BOOST_PP_BOOL_219 1
+# define BOOST_PP_BOOL_220 1
+# define BOOST_PP_BOOL_221 1
+# define BOOST_PP_BOOL_222 1
+# define BOOST_PP_BOOL_223 1
+# define BOOST_PP_BOOL_224 1
+# define BOOST_PP_BOOL_225 1
+# define BOOST_PP_BOOL_226 1
+# define BOOST_PP_BOOL_227 1
+# define BOOST_PP_BOOL_228 1
+# define BOOST_PP_BOOL_229 1
+# define BOOST_PP_BOOL_230 1
+# define BOOST_PP_BOOL_231 1
+# define BOOST_PP_BOOL_232 1
+# define BOOST_PP_BOOL_233 1
+# define BOOST_PP_BOOL_234 1
+# define BOOST_PP_BOOL_235 1
+# define BOOST_PP_BOOL_236 1
+# define BOOST_PP_BOOL_237 1
+# define BOOST_PP_BOOL_238 1
+# define BOOST_PP_BOOL_239 1
+# define BOOST_PP_BOOL_240 1
+# define BOOST_PP_BOOL_241 1
+# define BOOST_PP_BOOL_242 1
+# define BOOST_PP_BOOL_243 1
+# define BOOST_PP_BOOL_244 1
+# define BOOST_PP_BOOL_245 1
+# define BOOST_PP_BOOL_246 1
+# define BOOST_PP_BOOL_247 1
+# define BOOST_PP_BOOL_248 1
+# define BOOST_PP_BOOL_249 1
+# define BOOST_PP_BOOL_250 1
+# define BOOST_PP_BOOL_251 1
+# define BOOST_PP_BOOL_252 1
+# define BOOST_PP_BOOL_253 1
+# define BOOST_PP_BOOL_254 1
+# define BOOST_PP_BOOL_255 1
+# define BOOST_PP_BOOL_256 1
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/logical/compl.hpp b/third_party/boost/boost/preprocessor/logical/compl.hpp
new file mode 100644
index 0000000..ad4c7a4
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/logical/compl.hpp
@@ -0,0 +1,36 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_LOGICAL_COMPL_HPP
+# define BOOST_PREPROCESSOR_LOGICAL_COMPL_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+#
+# /* BOOST_PP_COMPL */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MWCC()
+# define BOOST_PP_COMPL(x) BOOST_PP_COMPL_I(x)
+# else
+# define BOOST_PP_COMPL(x) BOOST_PP_COMPL_OO((x))
+# define BOOST_PP_COMPL_OO(par) BOOST_PP_COMPL_I ## par
+# endif
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MSVC()
+# define BOOST_PP_COMPL_I(x) BOOST_PP_COMPL_ ## x
+# else
+# define BOOST_PP_COMPL_I(x) BOOST_PP_COMPL_ID(BOOST_PP_COMPL_ ## x)
+# define BOOST_PP_COMPL_ID(id) id
+# endif
+#
+# define BOOST_PP_COMPL_0 1
+# define BOOST_PP_COMPL_1 0
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/logical/not.hpp b/third_party/boost/boost/preprocessor/logical/not.hpp
new file mode 100644
index 0000000..b509d3f
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/logical/not.hpp
@@ -0,0 +1,30 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_LOGICAL_NOT_HPP
+# define BOOST_PREPROCESSOR_LOGICAL_NOT_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/logical/bool.hpp>
+# include <boost/preprocessor/logical/compl.hpp>
+#
+# /* BOOST_PP_NOT */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_NOT(x) BOOST_PP_COMPL(BOOST_PP_BOOL(x))
+# else
+# define BOOST_PP_NOT(x) BOOST_PP_NOT_I(x)
+# define BOOST_PP_NOT_I(x) BOOST_PP_COMPL(BOOST_PP_BOOL(x))
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/punctuation/comma.hpp b/third_party/boost/boost/preprocessor/punctuation/comma.hpp
new file mode 100644
index 0000000..38c2e0e
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/punctuation/comma.hpp
@@ -0,0 +1,21 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_PUNCTUATION_COMMA_HPP
+# define BOOST_PREPROCESSOR_PUNCTUATION_COMMA_HPP
+#
+# /* BOOST_PP_COMMA */
+#
+# define BOOST_PP_COMMA() ,
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/punctuation/comma_if.hpp b/third_party/boost/boost/preprocessor/punctuation/comma_if.hpp
new file mode 100644
index 0000000..c711f36
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/punctuation/comma_if.hpp
@@ -0,0 +1,31 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_PUNCTUATION_COMMA_IF_HPP
+# define BOOST_PREPROCESSOR_PUNCTUATION_COMMA_IF_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/control/if.hpp>
+# include <boost/preprocessor/facilities/empty.hpp>
+# include <boost/preprocessor/punctuation/comma.hpp>
+#
+# /* BOOST_PP_COMMA_IF */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_COMMA_IF(cond) BOOST_PP_IF(cond, BOOST_PP_COMMA, BOOST_PP_EMPTY)()
+# else
+# define BOOST_PP_COMMA_IF(cond) BOOST_PP_COMMA_IF_I(cond)
+# define BOOST_PP_COMMA_IF_I(cond) BOOST_PP_IF(cond, BOOST_PP_COMMA, BOOST_PP_EMPTY)()
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/repeat.hpp b/third_party/boost/boost/preprocessor/repeat.hpp
new file mode 100644
index 0000000..7c47ee8
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/repeat.hpp
@@ -0,0 +1,17 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_REPEAT_HPP
+# define BOOST_PREPROCESSOR_REPEAT_HPP
+#
+# include <boost/preprocessor/repetition/repeat.hpp>
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/repetition.hpp b/third_party/boost/boost/preprocessor/repetition.hpp
new file mode 100644
index 0000000..efcd60a
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/repetition.hpp
@@ -0,0 +1,32 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_REPETITION_HPP
+# define BOOST_PREPROCESSOR_REPETITION_HPP
+#
+# include <boost/preprocessor/repetition/deduce_r.hpp>
+# include <boost/preprocessor/repetition/deduce_z.hpp>
+# include <boost/preprocessor/repetition/enum.hpp>
+# include <boost/preprocessor/repetition/enum_binary_params.hpp>
+# include <boost/preprocessor/repetition/enum_params.hpp>
+# include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
+# include <boost/preprocessor/repetition/enum_params_with_defaults.hpp>
+# include <boost/preprocessor/repetition/enum_shifted.hpp>
+# include <boost/preprocessor/repetition/enum_shifted_binary_params.hpp>
+# include <boost/preprocessor/repetition/enum_shifted_params.hpp>
+# include <boost/preprocessor/repetition/enum_trailing.hpp>
+# include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
+# include <boost/preprocessor/repetition/enum_trailing_params.hpp>
+# include <boost/preprocessor/repetition/for.hpp>
+# include <boost/preprocessor/repetition/repeat.hpp>
+# include <boost/preprocessor/repetition/repeat_from_to.hpp>
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/repetition/deduce_r.hpp b/third_party/boost/boost/preprocessor/repetition/deduce_r.hpp
new file mode 100644
index 0000000..e49296a
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/repetition/deduce_r.hpp
@@ -0,0 +1,22 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_REPETITION_DEDUCE_R_HPP
+# define BOOST_PREPROCESSOR_REPETITION_DEDUCE_R_HPP
+#
+# include <boost/preprocessor/detail/auto_rec.hpp>
+# include <boost/preprocessor/repetition/for.hpp>
+#
+# /* BOOST_PP_DEDUCE_R */
+#
+# define BOOST_PP_DEDUCE_R() BOOST_PP_AUTO_REC(BOOST_PP_FOR_P, 256)
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/repetition/deduce_z.hpp b/third_party/boost/boost/preprocessor/repetition/deduce_z.hpp
new file mode 100644
index 0000000..14dedc2
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/repetition/deduce_z.hpp
@@ -0,0 +1,22 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_REPETITION_DEDUCE_Z_HPP
+# define BOOST_PREPROCESSOR_REPETITION_DEDUCE_Z_HPP
+#
+# include <boost/preprocessor/detail/auto_rec.hpp>
+# include <boost/preprocessor/repetition/repeat.hpp>
+#
+# /* BOOST_PP_DEDUCE_Z */
+#
+# define BOOST_PP_DEDUCE_Z() BOOST_PP_AUTO_REC(BOOST_PP_REPEAT_P, 4)
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/repetition/detail/for.hpp b/third_party/boost/boost/preprocessor/repetition/detail/for.hpp
new file mode 100644
index 0000000..2770f2c
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/repetition/detail/for.hpp
@@ -0,0 +1,536 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_REPETITION_DETAIL_FOR_HPP
+# define BOOST_PREPROCESSOR_REPETITION_DETAIL_FOR_HPP
+#
+# include <boost/preprocessor/control/expr_iif.hpp>
+# include <boost/preprocessor/control/iif.hpp>
+# include <boost/preprocessor/logical/bool.hpp>
+# include <boost/preprocessor/tuple/eat.hpp>
+#
+# define BOOST_PP_FOR_1(s, p, o, m) BOOST_PP_FOR_1_C(BOOST_PP_BOOL(p(2, s)), s, p, o, m)
+# define BOOST_PP_FOR_2(s, p, o, m) BOOST_PP_FOR_2_C(BOOST_PP_BOOL(p(3, s)), s, p, o, m)
+# define BOOST_PP_FOR_3(s, p, o, m) BOOST_PP_FOR_3_C(BOOST_PP_BOOL(p(4, s)), s, p, o, m)
+# define BOOST_PP_FOR_4(s, p, o, m) BOOST_PP_FOR_4_C(BOOST_PP_BOOL(p(5, s)), s, p, o, m)
+# define BOOST_PP_FOR_5(s, p, o, m) BOOST_PP_FOR_5_C(BOOST_PP_BOOL(p(6, s)), s, p, o, m)
+# define BOOST_PP_FOR_6(s, p, o, m) BOOST_PP_FOR_6_C(BOOST_PP_BOOL(p(7, s)), s, p, o, m)
+# define BOOST_PP_FOR_7(s, p, o, m) BOOST_PP_FOR_7_C(BOOST_PP_BOOL(p(8, s)), s, p, o, m)
+# define BOOST_PP_FOR_8(s, p, o, m) BOOST_PP_FOR_8_C(BOOST_PP_BOOL(p(9, s)), s, p, o, m)
+# define BOOST_PP_FOR_9(s, p, o, m) BOOST_PP_FOR_9_C(BOOST_PP_BOOL(p(10, s)), s, p, o, m)
+# define BOOST_PP_FOR_10(s, p, o, m) BOOST_PP_FOR_10_C(BOOST_PP_BOOL(p(11, s)), s, p, o, m)
+# define BOOST_PP_FOR_11(s, p, o, m) BOOST_PP_FOR_11_C(BOOST_PP_BOOL(p(12, s)), s, p, o, m)
+# define BOOST_PP_FOR_12(s, p, o, m) BOOST_PP_FOR_12_C(BOOST_PP_BOOL(p(13, s)), s, p, o, m)
+# define BOOST_PP_FOR_13(s, p, o, m) BOOST_PP_FOR_13_C(BOOST_PP_BOOL(p(14, s)), s, p, o, m)
+# define BOOST_PP_FOR_14(s, p, o, m) BOOST_PP_FOR_14_C(BOOST_PP_BOOL(p(15, s)), s, p, o, m)
+# define BOOST_PP_FOR_15(s, p, o, m) BOOST_PP_FOR_15_C(BOOST_PP_BOOL(p(16, s)), s, p, o, m)
+# define BOOST_PP_FOR_16(s, p, o, m) BOOST_PP_FOR_16_C(BOOST_PP_BOOL(p(17, s)), s, p, o, m)
+# define BOOST_PP_FOR_17(s, p, o, m) BOOST_PP_FOR_17_C(BOOST_PP_BOOL(p(18, s)), s, p, o, m)
+# define BOOST_PP_FOR_18(s, p, o, m) BOOST_PP_FOR_18_C(BOOST_PP_BOOL(p(19, s)), s, p, o, m)
+# define BOOST_PP_FOR_19(s, p, o, m) BOOST_PP_FOR_19_C(BOOST_PP_BOOL(p(20, s)), s, p, o, m)
+# define BOOST_PP_FOR_20(s, p, o, m) BOOST_PP_FOR_20_C(BOOST_PP_BOOL(p(21, s)), s, p, o, m)
+# define BOOST_PP_FOR_21(s, p, o, m) BOOST_PP_FOR_21_C(BOOST_PP_BOOL(p(22, s)), s, p, o, m)
+# define BOOST_PP_FOR_22(s, p, o, m) BOOST_PP_FOR_22_C(BOOST_PP_BOOL(p(23, s)), s, p, o, m)
+# define BOOST_PP_FOR_23(s, p, o, m) BOOST_PP_FOR_23_C(BOOST_PP_BOOL(p(24, s)), s, p, o, m)
+# define BOOST_PP_FOR_24(s, p, o, m) BOOST_PP_FOR_24_C(BOOST_PP_BOOL(p(25, s)), s, p, o, m)
+# define BOOST_PP_FOR_25(s, p, o, m) BOOST_PP_FOR_25_C(BOOST_PP_BOOL(p(26, s)), s, p, o, m)
+# define BOOST_PP_FOR_26(s, p, o, m) BOOST_PP_FOR_26_C(BOOST_PP_BOOL(p(27, s)), s, p, o, m)
+# define BOOST_PP_FOR_27(s, p, o, m) BOOST_PP_FOR_27_C(BOOST_PP_BOOL(p(28, s)), s, p, o, m)
+# define BOOST_PP_FOR_28(s, p, o, m) BOOST_PP_FOR_28_C(BOOST_PP_BOOL(p(29, s)), s, p, o, m)
+# define BOOST_PP_FOR_29(s, p, o, m) BOOST_PP_FOR_29_C(BOOST_PP_BOOL(p(30, s)), s, p, o, m)
+# define BOOST_PP_FOR_30(s, p, o, m) BOOST_PP_FOR_30_C(BOOST_PP_BOOL(p(31, s)), s, p, o, m)
+# define BOOST_PP_FOR_31(s, p, o, m) BOOST_PP_FOR_31_C(BOOST_PP_BOOL(p(32, s)), s, p, o, m)
+# define BOOST_PP_FOR_32(s, p, o, m) BOOST_PP_FOR_32_C(BOOST_PP_BOOL(p(33, s)), s, p, o, m)
+# define BOOST_PP_FOR_33(s, p, o, m) BOOST_PP_FOR_33_C(BOOST_PP_BOOL(p(34, s)), s, p, o, m)
+# define BOOST_PP_FOR_34(s, p, o, m) BOOST_PP_FOR_34_C(BOOST_PP_BOOL(p(35, s)), s, p, o, m)
+# define BOOST_PP_FOR_35(s, p, o, m) BOOST_PP_FOR_35_C(BOOST_PP_BOOL(p(36, s)), s, p, o, m)
+# define BOOST_PP_FOR_36(s, p, o, m) BOOST_PP_FOR_36_C(BOOST_PP_BOOL(p(37, s)), s, p, o, m)
+# define BOOST_PP_FOR_37(s, p, o, m) BOOST_PP_FOR_37_C(BOOST_PP_BOOL(p(38, s)), s, p, o, m)
+# define BOOST_PP_FOR_38(s, p, o, m) BOOST_PP_FOR_38_C(BOOST_PP_BOOL(p(39, s)), s, p, o, m)
+# define BOOST_PP_FOR_39(s, p, o, m) BOOST_PP_FOR_39_C(BOOST_PP_BOOL(p(40, s)), s, p, o, m)
+# define BOOST_PP_FOR_40(s, p, o, m) BOOST_PP_FOR_40_C(BOOST_PP_BOOL(p(41, s)), s, p, o, m)
+# define BOOST_PP_FOR_41(s, p, o, m) BOOST_PP_FOR_41_C(BOOST_PP_BOOL(p(42, s)), s, p, o, m)
+# define BOOST_PP_FOR_42(s, p, o, m) BOOST_PP_FOR_42_C(BOOST_PP_BOOL(p(43, s)), s, p, o, m)
+# define BOOST_PP_FOR_43(s, p, o, m) BOOST_PP_FOR_43_C(BOOST_PP_BOOL(p(44, s)), s, p, o, m)
+# define BOOST_PP_FOR_44(s, p, o, m) BOOST_PP_FOR_44_C(BOOST_PP_BOOL(p(45, s)), s, p, o, m)
+# define BOOST_PP_FOR_45(s, p, o, m) BOOST_PP_FOR_45_C(BOOST_PP_BOOL(p(46, s)), s, p, o, m)
+# define BOOST_PP_FOR_46(s, p, o, m) BOOST_PP_FOR_46_C(BOOST_PP_BOOL(p(47, s)), s, p, o, m)
+# define BOOST_PP_FOR_47(s, p, o, m) BOOST_PP_FOR_47_C(BOOST_PP_BOOL(p(48, s)), s, p, o, m)
+# define BOOST_PP_FOR_48(s, p, o, m) BOOST_PP_FOR_48_C(BOOST_PP_BOOL(p(49, s)), s, p, o, m)
+# define BOOST_PP_FOR_49(s, p, o, m) BOOST_PP_FOR_49_C(BOOST_PP_BOOL(p(50, s)), s, p, o, m)
+# define BOOST_PP_FOR_50(s, p, o, m) BOOST_PP_FOR_50_C(BOOST_PP_BOOL(p(51, s)), s, p, o, m)
+# define BOOST_PP_FOR_51(s, p, o, m) BOOST_PP_FOR_51_C(BOOST_PP_BOOL(p(52, s)), s, p, o, m)
+# define BOOST_PP_FOR_52(s, p, o, m) BOOST_PP_FOR_52_C(BOOST_PP_BOOL(p(53, s)), s, p, o, m)
+# define BOOST_PP_FOR_53(s, p, o, m) BOOST_PP_FOR_53_C(BOOST_PP_BOOL(p(54, s)), s, p, o, m)
+# define BOOST_PP_FOR_54(s, p, o, m) BOOST_PP_FOR_54_C(BOOST_PP_BOOL(p(55, s)), s, p, o, m)
+# define BOOST_PP_FOR_55(s, p, o, m) BOOST_PP_FOR_55_C(BOOST_PP_BOOL(p(56, s)), s, p, o, m)
+# define BOOST_PP_FOR_56(s, p, o, m) BOOST_PP_FOR_56_C(BOOST_PP_BOOL(p(57, s)), s, p, o, m)
+# define BOOST_PP_FOR_57(s, p, o, m) BOOST_PP_FOR_57_C(BOOST_PP_BOOL(p(58, s)), s, p, o, m)
+# define BOOST_PP_FOR_58(s, p, o, m) BOOST_PP_FOR_58_C(BOOST_PP_BOOL(p(59, s)), s, p, o, m)
+# define BOOST_PP_FOR_59(s, p, o, m) BOOST_PP_FOR_59_C(BOOST_PP_BOOL(p(60, s)), s, p, o, m)
+# define BOOST_PP_FOR_60(s, p, o, m) BOOST_PP_FOR_60_C(BOOST_PP_BOOL(p(61, s)), s, p, o, m)
+# define BOOST_PP_FOR_61(s, p, o, m) BOOST_PP_FOR_61_C(BOOST_PP_BOOL(p(62, s)), s, p, o, m)
+# define BOOST_PP_FOR_62(s, p, o, m) BOOST_PP_FOR_62_C(BOOST_PP_BOOL(p(63, s)), s, p, o, m)
+# define BOOST_PP_FOR_63(s, p, o, m) BOOST_PP_FOR_63_C(BOOST_PP_BOOL(p(64, s)), s, p, o, m)
+# define BOOST_PP_FOR_64(s, p, o, m) BOOST_PP_FOR_64_C(BOOST_PP_BOOL(p(65, s)), s, p, o, m)
+# define BOOST_PP_FOR_65(s, p, o, m) BOOST_PP_FOR_65_C(BOOST_PP_BOOL(p(66, s)), s, p, o, m)
+# define BOOST_PP_FOR_66(s, p, o, m) BOOST_PP_FOR_66_C(BOOST_PP_BOOL(p(67, s)), s, p, o, m)
+# define BOOST_PP_FOR_67(s, p, o, m) BOOST_PP_FOR_67_C(BOOST_PP_BOOL(p(68, s)), s, p, o, m)
+# define BOOST_PP_FOR_68(s, p, o, m) BOOST_PP_FOR_68_C(BOOST_PP_BOOL(p(69, s)), s, p, o, m)
+# define BOOST_PP_FOR_69(s, p, o, m) BOOST_PP_FOR_69_C(BOOST_PP_BOOL(p(70, s)), s, p, o, m)
+# define BOOST_PP_FOR_70(s, p, o, m) BOOST_PP_FOR_70_C(BOOST_PP_BOOL(p(71, s)), s, p, o, m)
+# define BOOST_PP_FOR_71(s, p, o, m) BOOST_PP_FOR_71_C(BOOST_PP_BOOL(p(72, s)), s, p, o, m)
+# define BOOST_PP_FOR_72(s, p, o, m) BOOST_PP_FOR_72_C(BOOST_PP_BOOL(p(73, s)), s, p, o, m)
+# define BOOST_PP_FOR_73(s, p, o, m) BOOST_PP_FOR_73_C(BOOST_PP_BOOL(p(74, s)), s, p, o, m)
+# define BOOST_PP_FOR_74(s, p, o, m) BOOST_PP_FOR_74_C(BOOST_PP_BOOL(p(75, s)), s, p, o, m)
+# define BOOST_PP_FOR_75(s, p, o, m) BOOST_PP_FOR_75_C(BOOST_PP_BOOL(p(76, s)), s, p, o, m)
+# define BOOST_PP_FOR_76(s, p, o, m) BOOST_PP_FOR_76_C(BOOST_PP_BOOL(p(77, s)), s, p, o, m)
+# define BOOST_PP_FOR_77(s, p, o, m) BOOST_PP_FOR_77_C(BOOST_PP_BOOL(p(78, s)), s, p, o, m)
+# define BOOST_PP_FOR_78(s, p, o, m) BOOST_PP_FOR_78_C(BOOST_PP_BOOL(p(79, s)), s, p, o, m)
+# define BOOST_PP_FOR_79(s, p, o, m) BOOST_PP_FOR_79_C(BOOST_PP_BOOL(p(80, s)), s, p, o, m)
+# define BOOST_PP_FOR_80(s, p, o, m) BOOST_PP_FOR_80_C(BOOST_PP_BOOL(p(81, s)), s, p, o, m)
+# define BOOST_PP_FOR_81(s, p, o, m) BOOST_PP_FOR_81_C(BOOST_PP_BOOL(p(82, s)), s, p, o, m)
+# define BOOST_PP_FOR_82(s, p, o, m) BOOST_PP_FOR_82_C(BOOST_PP_BOOL(p(83, s)), s, p, o, m)
+# define BOOST_PP_FOR_83(s, p, o, m) BOOST_PP_FOR_83_C(BOOST_PP_BOOL(p(84, s)), s, p, o, m)
+# define BOOST_PP_FOR_84(s, p, o, m) BOOST_PP_FOR_84_C(BOOST_PP_BOOL(p(85, s)), s, p, o, m)
+# define BOOST_PP_FOR_85(s, p, o, m) BOOST_PP_FOR_85_C(BOOST_PP_BOOL(p(86, s)), s, p, o, m)
+# define BOOST_PP_FOR_86(s, p, o, m) BOOST_PP_FOR_86_C(BOOST_PP_BOOL(p(87, s)), s, p, o, m)
+# define BOOST_PP_FOR_87(s, p, o, m) BOOST_PP_FOR_87_C(BOOST_PP_BOOL(p(88, s)), s, p, o, m)
+# define BOOST_PP_FOR_88(s, p, o, m) BOOST_PP_FOR_88_C(BOOST_PP_BOOL(p(89, s)), s, p, o, m)
+# define BOOST_PP_FOR_89(s, p, o, m) BOOST_PP_FOR_89_C(BOOST_PP_BOOL(p(90, s)), s, p, o, m)
+# define BOOST_PP_FOR_90(s, p, o, m) BOOST_PP_FOR_90_C(BOOST_PP_BOOL(p(91, s)), s, p, o, m)
+# define BOOST_PP_FOR_91(s, p, o, m) BOOST_PP_FOR_91_C(BOOST_PP_BOOL(p(92, s)), s, p, o, m)
+# define BOOST_PP_FOR_92(s, p, o, m) BOOST_PP_FOR_92_C(BOOST_PP_BOOL(p(93, s)), s, p, o, m)
+# define BOOST_PP_FOR_93(s, p, o, m) BOOST_PP_FOR_93_C(BOOST_PP_BOOL(p(94, s)), s, p, o, m)
+# define BOOST_PP_FOR_94(s, p, o, m) BOOST_PP_FOR_94_C(BOOST_PP_BOOL(p(95, s)), s, p, o, m)
+# define BOOST_PP_FOR_95(s, p, o, m) BOOST_PP_FOR_95_C(BOOST_PP_BOOL(p(96, s)), s, p, o, m)
+# define BOOST_PP_FOR_96(s, p, o, m) BOOST_PP_FOR_96_C(BOOST_PP_BOOL(p(97, s)), s, p, o, m)
+# define BOOST_PP_FOR_97(s, p, o, m) BOOST_PP_FOR_97_C(BOOST_PP_BOOL(p(98, s)), s, p, o, m)
+# define BOOST_PP_FOR_98(s, p, o, m) BOOST_PP_FOR_98_C(BOOST_PP_BOOL(p(99, s)), s, p, o, m)
+# define BOOST_PP_FOR_99(s, p, o, m) BOOST_PP_FOR_99_C(BOOST_PP_BOOL(p(100, s)), s, p, o, m)
+# define BOOST_PP_FOR_100(s, p, o, m) BOOST_PP_FOR_100_C(BOOST_PP_BOOL(p(101, s)), s, p, o, m)
+# define BOOST_PP_FOR_101(s, p, o, m) BOOST_PP_FOR_101_C(BOOST_PP_BOOL(p(102, s)), s, p, o, m)
+# define BOOST_PP_FOR_102(s, p, o, m) BOOST_PP_FOR_102_C(BOOST_PP_BOOL(p(103, s)), s, p, o, m)
+# define BOOST_PP_FOR_103(s, p, o, m) BOOST_PP_FOR_103_C(BOOST_PP_BOOL(p(104, s)), s, p, o, m)
+# define BOOST_PP_FOR_104(s, p, o, m) BOOST_PP_FOR_104_C(BOOST_PP_BOOL(p(105, s)), s, p, o, m)
+# define BOOST_PP_FOR_105(s, p, o, m) BOOST_PP_FOR_105_C(BOOST_PP_BOOL(p(106, s)), s, p, o, m)
+# define BOOST_PP_FOR_106(s, p, o, m) BOOST_PP_FOR_106_C(BOOST_PP_BOOL(p(107, s)), s, p, o, m)
+# define BOOST_PP_FOR_107(s, p, o, m) BOOST_PP_FOR_107_C(BOOST_PP_BOOL(p(108, s)), s, p, o, m)
+# define BOOST_PP_FOR_108(s, p, o, m) BOOST_PP_FOR_108_C(BOOST_PP_BOOL(p(109, s)), s, p, o, m)
+# define BOOST_PP_FOR_109(s, p, o, m) BOOST_PP_FOR_109_C(BOOST_PP_BOOL(p(110, s)), s, p, o, m)
+# define BOOST_PP_FOR_110(s, p, o, m) BOOST_PP_FOR_110_C(BOOST_PP_BOOL(p(111, s)), s, p, o, m)
+# define BOOST_PP_FOR_111(s, p, o, m) BOOST_PP_FOR_111_C(BOOST_PP_BOOL(p(112, s)), s, p, o, m)
+# define BOOST_PP_FOR_112(s, p, o, m) BOOST_PP_FOR_112_C(BOOST_PP_BOOL(p(113, s)), s, p, o, m)
+# define BOOST_PP_FOR_113(s, p, o, m) BOOST_PP_FOR_113_C(BOOST_PP_BOOL(p(114, s)), s, p, o, m)
+# define BOOST_PP_FOR_114(s, p, o, m) BOOST_PP_FOR_114_C(BOOST_PP_BOOL(p(115, s)), s, p, o, m)
+# define BOOST_PP_FOR_115(s, p, o, m) BOOST_PP_FOR_115_C(BOOST_PP_BOOL(p(116, s)), s, p, o, m)
+# define BOOST_PP_FOR_116(s, p, o, m) BOOST_PP_FOR_116_C(BOOST_PP_BOOL(p(117, s)), s, p, o, m)
+# define BOOST_PP_FOR_117(s, p, o, m) BOOST_PP_FOR_117_C(BOOST_PP_BOOL(p(118, s)), s, p, o, m)
+# define BOOST_PP_FOR_118(s, p, o, m) BOOST_PP_FOR_118_C(BOOST_PP_BOOL(p(119, s)), s, p, o, m)
+# define BOOST_PP_FOR_119(s, p, o, m) BOOST_PP_FOR_119_C(BOOST_PP_BOOL(p(120, s)), s, p, o, m)
+# define BOOST_PP_FOR_120(s, p, o, m) BOOST_PP_FOR_120_C(BOOST_PP_BOOL(p(121, s)), s, p, o, m)
+# define BOOST_PP_FOR_121(s, p, o, m) BOOST_PP_FOR_121_C(BOOST_PP_BOOL(p(122, s)), s, p, o, m)
+# define BOOST_PP_FOR_122(s, p, o, m) BOOST_PP_FOR_122_C(BOOST_PP_BOOL(p(123, s)), s, p, o, m)
+# define BOOST_PP_FOR_123(s, p, o, m) BOOST_PP_FOR_123_C(BOOST_PP_BOOL(p(124, s)), s, p, o, m)
+# define BOOST_PP_FOR_124(s, p, o, m) BOOST_PP_FOR_124_C(BOOST_PP_BOOL(p(125, s)), s, p, o, m)
+# define BOOST_PP_FOR_125(s, p, o, m) BOOST_PP_FOR_125_C(BOOST_PP_BOOL(p(126, s)), s, p, o, m)
+# define BOOST_PP_FOR_126(s, p, o, m) BOOST_PP_FOR_126_C(BOOST_PP_BOOL(p(127, s)), s, p, o, m)
+# define BOOST_PP_FOR_127(s, p, o, m) BOOST_PP_FOR_127_C(BOOST_PP_BOOL(p(128, s)), s, p, o, m)
+# define BOOST_PP_FOR_128(s, p, o, m) BOOST_PP_FOR_128_C(BOOST_PP_BOOL(p(129, s)), s, p, o, m)
+# define BOOST_PP_FOR_129(s, p, o, m) BOOST_PP_FOR_129_C(BOOST_PP_BOOL(p(130, s)), s, p, o, m)
+# define BOOST_PP_FOR_130(s, p, o, m) BOOST_PP_FOR_130_C(BOOST_PP_BOOL(p(131, s)), s, p, o, m)
+# define BOOST_PP_FOR_131(s, p, o, m) BOOST_PP_FOR_131_C(BOOST_PP_BOOL(p(132, s)), s, p, o, m)
+# define BOOST_PP_FOR_132(s, p, o, m) BOOST_PP_FOR_132_C(BOOST_PP_BOOL(p(133, s)), s, p, o, m)
+# define BOOST_PP_FOR_133(s, p, o, m) BOOST_PP_FOR_133_C(BOOST_PP_BOOL(p(134, s)), s, p, o, m)
+# define BOOST_PP_FOR_134(s, p, o, m) BOOST_PP_FOR_134_C(BOOST_PP_BOOL(p(135, s)), s, p, o, m)
+# define BOOST_PP_FOR_135(s, p, o, m) BOOST_PP_FOR_135_C(BOOST_PP_BOOL(p(136, s)), s, p, o, m)
+# define BOOST_PP_FOR_136(s, p, o, m) BOOST_PP_FOR_136_C(BOOST_PP_BOOL(p(137, s)), s, p, o, m)
+# define BOOST_PP_FOR_137(s, p, o, m) BOOST_PP_FOR_137_C(BOOST_PP_BOOL(p(138, s)), s, p, o, m)
+# define BOOST_PP_FOR_138(s, p, o, m) BOOST_PP_FOR_138_C(BOOST_PP_BOOL(p(139, s)), s, p, o, m)
+# define BOOST_PP_FOR_139(s, p, o, m) BOOST_PP_FOR_139_C(BOOST_PP_BOOL(p(140, s)), s, p, o, m)
+# define BOOST_PP_FOR_140(s, p, o, m) BOOST_PP_FOR_140_C(BOOST_PP_BOOL(p(141, s)), s, p, o, m)
+# define BOOST_PP_FOR_141(s, p, o, m) BOOST_PP_FOR_141_C(BOOST_PP_BOOL(p(142, s)), s, p, o, m)
+# define BOOST_PP_FOR_142(s, p, o, m) BOOST_PP_FOR_142_C(BOOST_PP_BOOL(p(143, s)), s, p, o, m)
+# define BOOST_PP_FOR_143(s, p, o, m) BOOST_PP_FOR_143_C(BOOST_PP_BOOL(p(144, s)), s, p, o, m)
+# define BOOST_PP_FOR_144(s, p, o, m) BOOST_PP_FOR_144_C(BOOST_PP_BOOL(p(145, s)), s, p, o, m)
+# define BOOST_PP_FOR_145(s, p, o, m) BOOST_PP_FOR_145_C(BOOST_PP_BOOL(p(146, s)), s, p, o, m)
+# define BOOST_PP_FOR_146(s, p, o, m) BOOST_PP_FOR_146_C(BOOST_PP_BOOL(p(147, s)), s, p, o, m)
+# define BOOST_PP_FOR_147(s, p, o, m) BOOST_PP_FOR_147_C(BOOST_PP_BOOL(p(148, s)), s, p, o, m)
+# define BOOST_PP_FOR_148(s, p, o, m) BOOST_PP_FOR_148_C(BOOST_PP_BOOL(p(149, s)), s, p, o, m)
+# define BOOST_PP_FOR_149(s, p, o, m) BOOST_PP_FOR_149_C(BOOST_PP_BOOL(p(150, s)), s, p, o, m)
+# define BOOST_PP_FOR_150(s, p, o, m) BOOST_PP_FOR_150_C(BOOST_PP_BOOL(p(151, s)), s, p, o, m)
+# define BOOST_PP_FOR_151(s, p, o, m) BOOST_PP_FOR_151_C(BOOST_PP_BOOL(p(152, s)), s, p, o, m)
+# define BOOST_PP_FOR_152(s, p, o, m) BOOST_PP_FOR_152_C(BOOST_PP_BOOL(p(153, s)), s, p, o, m)
+# define BOOST_PP_FOR_153(s, p, o, m) BOOST_PP_FOR_153_C(BOOST_PP_BOOL(p(154, s)), s, p, o, m)
+# define BOOST_PP_FOR_154(s, p, o, m) BOOST_PP_FOR_154_C(BOOST_PP_BOOL(p(155, s)), s, p, o, m)
+# define BOOST_PP_FOR_155(s, p, o, m) BOOST_PP_FOR_155_C(BOOST_PP_BOOL(p(156, s)), s, p, o, m)
+# define BOOST_PP_FOR_156(s, p, o, m) BOOST_PP_FOR_156_C(BOOST_PP_BOOL(p(157, s)), s, p, o, m)
+# define BOOST_PP_FOR_157(s, p, o, m) BOOST_PP_FOR_157_C(BOOST_PP_BOOL(p(158, s)), s, p, o, m)
+# define BOOST_PP_FOR_158(s, p, o, m) BOOST_PP_FOR_158_C(BOOST_PP_BOOL(p(159, s)), s, p, o, m)
+# define BOOST_PP_FOR_159(s, p, o, m) BOOST_PP_FOR_159_C(BOOST_PP_BOOL(p(160, s)), s, p, o, m)
+# define BOOST_PP_FOR_160(s, p, o, m) BOOST_PP_FOR_160_C(BOOST_PP_BOOL(p(161, s)), s, p, o, m)
+# define BOOST_PP_FOR_161(s, p, o, m) BOOST_PP_FOR_161_C(BOOST_PP_BOOL(p(162, s)), s, p, o, m)
+# define BOOST_PP_FOR_162(s, p, o, m) BOOST_PP_FOR_162_C(BOOST_PP_BOOL(p(163, s)), s, p, o, m)
+# define BOOST_PP_FOR_163(s, p, o, m) BOOST_PP_FOR_163_C(BOOST_PP_BOOL(p(164, s)), s, p, o, m)
+# define BOOST_PP_FOR_164(s, p, o, m) BOOST_PP_FOR_164_C(BOOST_PP_BOOL(p(165, s)), s, p, o, m)
+# define BOOST_PP_FOR_165(s, p, o, m) BOOST_PP_FOR_165_C(BOOST_PP_BOOL(p(166, s)), s, p, o, m)
+# define BOOST_PP_FOR_166(s, p, o, m) BOOST_PP_FOR_166_C(BOOST_PP_BOOL(p(167, s)), s, p, o, m)
+# define BOOST_PP_FOR_167(s, p, o, m) BOOST_PP_FOR_167_C(BOOST_PP_BOOL(p(168, s)), s, p, o, m)
+# define BOOST_PP_FOR_168(s, p, o, m) BOOST_PP_FOR_168_C(BOOST_PP_BOOL(p(169, s)), s, p, o, m)
+# define BOOST_PP_FOR_169(s, p, o, m) BOOST_PP_FOR_169_C(BOOST_PP_BOOL(p(170, s)), s, p, o, m)
+# define BOOST_PP_FOR_170(s, p, o, m) BOOST_PP_FOR_170_C(BOOST_PP_BOOL(p(171, s)), s, p, o, m)
+# define BOOST_PP_FOR_171(s, p, o, m) BOOST_PP_FOR_171_C(BOOST_PP_BOOL(p(172, s)), s, p, o, m)
+# define BOOST_PP_FOR_172(s, p, o, m) BOOST_PP_FOR_172_C(BOOST_PP_BOOL(p(173, s)), s, p, o, m)
+# define BOOST_PP_FOR_173(s, p, o, m) BOOST_PP_FOR_173_C(BOOST_PP_BOOL(p(174, s)), s, p, o, m)
+# define BOOST_PP_FOR_174(s, p, o, m) BOOST_PP_FOR_174_C(BOOST_PP_BOOL(p(175, s)), s, p, o, m)
+# define BOOST_PP_FOR_175(s, p, o, m) BOOST_PP_FOR_175_C(BOOST_PP_BOOL(p(176, s)), s, p, o, m)
+# define BOOST_PP_FOR_176(s, p, o, m) BOOST_PP_FOR_176_C(BOOST_PP_BOOL(p(177, s)), s, p, o, m)
+# define BOOST_PP_FOR_177(s, p, o, m) BOOST_PP_FOR_177_C(BOOST_PP_BOOL(p(178, s)), s, p, o, m)
+# define BOOST_PP_FOR_178(s, p, o, m) BOOST_PP_FOR_178_C(BOOST_PP_BOOL(p(179, s)), s, p, o, m)
+# define BOOST_PP_FOR_179(s, p, o, m) BOOST_PP_FOR_179_C(BOOST_PP_BOOL(p(180, s)), s, p, o, m)
+# define BOOST_PP_FOR_180(s, p, o, m) BOOST_PP_FOR_180_C(BOOST_PP_BOOL(p(181, s)), s, p, o, m)
+# define BOOST_PP_FOR_181(s, p, o, m) BOOST_PP_FOR_181_C(BOOST_PP_BOOL(p(182, s)), s, p, o, m)
+# define BOOST_PP_FOR_182(s, p, o, m) BOOST_PP_FOR_182_C(BOOST_PP_BOOL(p(183, s)), s, p, o, m)
+# define BOOST_PP_FOR_183(s, p, o, m) BOOST_PP_FOR_183_C(BOOST_PP_BOOL(p(184, s)), s, p, o, m)
+# define BOOST_PP_FOR_184(s, p, o, m) BOOST_PP_FOR_184_C(BOOST_PP_BOOL(p(185, s)), s, p, o, m)
+# define BOOST_PP_FOR_185(s, p, o, m) BOOST_PP_FOR_185_C(BOOST_PP_BOOL(p(186, s)), s, p, o, m)
+# define BOOST_PP_FOR_186(s, p, o, m) BOOST_PP_FOR_186_C(BOOST_PP_BOOL(p(187, s)), s, p, o, m)
+# define BOOST_PP_FOR_187(s, p, o, m) BOOST_PP_FOR_187_C(BOOST_PP_BOOL(p(188, s)), s, p, o, m)
+# define BOOST_PP_FOR_188(s, p, o, m) BOOST_PP_FOR_188_C(BOOST_PP_BOOL(p(189, s)), s, p, o, m)
+# define BOOST_PP_FOR_189(s, p, o, m) BOOST_PP_FOR_189_C(BOOST_PP_BOOL(p(190, s)), s, p, o, m)
+# define BOOST_PP_FOR_190(s, p, o, m) BOOST_PP_FOR_190_C(BOOST_PP_BOOL(p(191, s)), s, p, o, m)
+# define BOOST_PP_FOR_191(s, p, o, m) BOOST_PP_FOR_191_C(BOOST_PP_BOOL(p(192, s)), s, p, o, m)
+# define BOOST_PP_FOR_192(s, p, o, m) BOOST_PP_FOR_192_C(BOOST_PP_BOOL(p(193, s)), s, p, o, m)
+# define BOOST_PP_FOR_193(s, p, o, m) BOOST_PP_FOR_193_C(BOOST_PP_BOOL(p(194, s)), s, p, o, m)
+# define BOOST_PP_FOR_194(s, p, o, m) BOOST_PP_FOR_194_C(BOOST_PP_BOOL(p(195, s)), s, p, o, m)
+# define BOOST_PP_FOR_195(s, p, o, m) BOOST_PP_FOR_195_C(BOOST_PP_BOOL(p(196, s)), s, p, o, m)
+# define BOOST_PP_FOR_196(s, p, o, m) BOOST_PP_FOR_196_C(BOOST_PP_BOOL(p(197, s)), s, p, o, m)
+# define BOOST_PP_FOR_197(s, p, o, m) BOOST_PP_FOR_197_C(BOOST_PP_BOOL(p(198, s)), s, p, o, m)
+# define BOOST_PP_FOR_198(s, p, o, m) BOOST_PP_FOR_198_C(BOOST_PP_BOOL(p(199, s)), s, p, o, m)
+# define BOOST_PP_FOR_199(s, p, o, m) BOOST_PP_FOR_199_C(BOOST_PP_BOOL(p(200, s)), s, p, o, m)
+# define BOOST_PP_FOR_200(s, p, o, m) BOOST_PP_FOR_200_C(BOOST_PP_BOOL(p(201, s)), s, p, o, m)
+# define BOOST_PP_FOR_201(s, p, o, m) BOOST_PP_FOR_201_C(BOOST_PP_BOOL(p(202, s)), s, p, o, m)
+# define BOOST_PP_FOR_202(s, p, o, m) BOOST_PP_FOR_202_C(BOOST_PP_BOOL(p(203, s)), s, p, o, m)
+# define BOOST_PP_FOR_203(s, p, o, m) BOOST_PP_FOR_203_C(BOOST_PP_BOOL(p(204, s)), s, p, o, m)
+# define BOOST_PP_FOR_204(s, p, o, m) BOOST_PP_FOR_204_C(BOOST_PP_BOOL(p(205, s)), s, p, o, m)
+# define BOOST_PP_FOR_205(s, p, o, m) BOOST_PP_FOR_205_C(BOOST_PP_BOOL(p(206, s)), s, p, o, m)
+# define BOOST_PP_FOR_206(s, p, o, m) BOOST_PP_FOR_206_C(BOOST_PP_BOOL(p(207, s)), s, p, o, m)
+# define BOOST_PP_FOR_207(s, p, o, m) BOOST_PP_FOR_207_C(BOOST_PP_BOOL(p(208, s)), s, p, o, m)
+# define BOOST_PP_FOR_208(s, p, o, m) BOOST_PP_FOR_208_C(BOOST_PP_BOOL(p(209, s)), s, p, o, m)
+# define BOOST_PP_FOR_209(s, p, o, m) BOOST_PP_FOR_209_C(BOOST_PP_BOOL(p(210, s)), s, p, o, m)
+# define BOOST_PP_FOR_210(s, p, o, m) BOOST_PP_FOR_210_C(BOOST_PP_BOOL(p(211, s)), s, p, o, m)
+# define BOOST_PP_FOR_211(s, p, o, m) BOOST_PP_FOR_211_C(BOOST_PP_BOOL(p(212, s)), s, p, o, m)
+# define BOOST_PP_FOR_212(s, p, o, m) BOOST_PP_FOR_212_C(BOOST_PP_BOOL(p(213, s)), s, p, o, m)
+# define BOOST_PP_FOR_213(s, p, o, m) BOOST_PP_FOR_213_C(BOOST_PP_BOOL(p(214, s)), s, p, o, m)
+# define BOOST_PP_FOR_214(s, p, o, m) BOOST_PP_FOR_214_C(BOOST_PP_BOOL(p(215, s)), s, p, o, m)
+# define BOOST_PP_FOR_215(s, p, o, m) BOOST_PP_FOR_215_C(BOOST_PP_BOOL(p(216, s)), s, p, o, m)
+# define BOOST_PP_FOR_216(s, p, o, m) BOOST_PP_FOR_216_C(BOOST_PP_BOOL(p(217, s)), s, p, o, m)
+# define BOOST_PP_FOR_217(s, p, o, m) BOOST_PP_FOR_217_C(BOOST_PP_BOOL(p(218, s)), s, p, o, m)
+# define BOOST_PP_FOR_218(s, p, o, m) BOOST_PP_FOR_218_C(BOOST_PP_BOOL(p(219, s)), s, p, o, m)
+# define BOOST_PP_FOR_219(s, p, o, m) BOOST_PP_FOR_219_C(BOOST_PP_BOOL(p(220, s)), s, p, o, m)
+# define BOOST_PP_FOR_220(s, p, o, m) BOOST_PP_FOR_220_C(BOOST_PP_BOOL(p(221, s)), s, p, o, m)
+# define BOOST_PP_FOR_221(s, p, o, m) BOOST_PP_FOR_221_C(BOOST_PP_BOOL(p(222, s)), s, p, o, m)
+# define BOOST_PP_FOR_222(s, p, o, m) BOOST_PP_FOR_222_C(BOOST_PP_BOOL(p(223, s)), s, p, o, m)
+# define BOOST_PP_FOR_223(s, p, o, m) BOOST_PP_FOR_223_C(BOOST_PP_BOOL(p(224, s)), s, p, o, m)
+# define BOOST_PP_FOR_224(s, p, o, m) BOOST_PP_FOR_224_C(BOOST_PP_BOOL(p(225, s)), s, p, o, m)
+# define BOOST_PP_FOR_225(s, p, o, m) BOOST_PP_FOR_225_C(BOOST_PP_BOOL(p(226, s)), s, p, o, m)
+# define BOOST_PP_FOR_226(s, p, o, m) BOOST_PP_FOR_226_C(BOOST_PP_BOOL(p(227, s)), s, p, o, m)
+# define BOOST_PP_FOR_227(s, p, o, m) BOOST_PP_FOR_227_C(BOOST_PP_BOOL(p(228, s)), s, p, o, m)
+# define BOOST_PP_FOR_228(s, p, o, m) BOOST_PP_FOR_228_C(BOOST_PP_BOOL(p(229, s)), s, p, o, m)
+# define BOOST_PP_FOR_229(s, p, o, m) BOOST_PP_FOR_229_C(BOOST_PP_BOOL(p(230, s)), s, p, o, m)
+# define BOOST_PP_FOR_230(s, p, o, m) BOOST_PP_FOR_230_C(BOOST_PP_BOOL(p(231, s)), s, p, o, m)
+# define BOOST_PP_FOR_231(s, p, o, m) BOOST_PP_FOR_231_C(BOOST_PP_BOOL(p(232, s)), s, p, o, m)
+# define BOOST_PP_FOR_232(s, p, o, m) BOOST_PP_FOR_232_C(BOOST_PP_BOOL(p(233, s)), s, p, o, m)
+# define BOOST_PP_FOR_233(s, p, o, m) BOOST_PP_FOR_233_C(BOOST_PP_BOOL(p(234, s)), s, p, o, m)
+# define BOOST_PP_FOR_234(s, p, o, m) BOOST_PP_FOR_234_C(BOOST_PP_BOOL(p(235, s)), s, p, o, m)
+# define BOOST_PP_FOR_235(s, p, o, m) BOOST_PP_FOR_235_C(BOOST_PP_BOOL(p(236, s)), s, p, o, m)
+# define BOOST_PP_FOR_236(s, p, o, m) BOOST_PP_FOR_236_C(BOOST_PP_BOOL(p(237, s)), s, p, o, m)
+# define BOOST_PP_FOR_237(s, p, o, m) BOOST_PP_FOR_237_C(BOOST_PP_BOOL(p(238, s)), s, p, o, m)
+# define BOOST_PP_FOR_238(s, p, o, m) BOOST_PP_FOR_238_C(BOOST_PP_BOOL(p(239, s)), s, p, o, m)
+# define BOOST_PP_FOR_239(s, p, o, m) BOOST_PP_FOR_239_C(BOOST_PP_BOOL(p(240, s)), s, p, o, m)
+# define BOOST_PP_FOR_240(s, p, o, m) BOOST_PP_FOR_240_C(BOOST_PP_BOOL(p(241, s)), s, p, o, m)
+# define BOOST_PP_FOR_241(s, p, o, m) BOOST_PP_FOR_241_C(BOOST_PP_BOOL(p(242, s)), s, p, o, m)
+# define BOOST_PP_FOR_242(s, p, o, m) BOOST_PP_FOR_242_C(BOOST_PP_BOOL(p(243, s)), s, p, o, m)
+# define BOOST_PP_FOR_243(s, p, o, m) BOOST_PP_FOR_243_C(BOOST_PP_BOOL(p(244, s)), s, p, o, m)
+# define BOOST_PP_FOR_244(s, p, o, m) BOOST_PP_FOR_244_C(BOOST_PP_BOOL(p(245, s)), s, p, o, m)
+# define BOOST_PP_FOR_245(s, p, o, m) BOOST_PP_FOR_245_C(BOOST_PP_BOOL(p(246, s)), s, p, o, m)
+# define BOOST_PP_FOR_246(s, p, o, m) BOOST_PP_FOR_246_C(BOOST_PP_BOOL(p(247, s)), s, p, o, m)
+# define BOOST_PP_FOR_247(s, p, o, m) BOOST_PP_FOR_247_C(BOOST_PP_BOOL(p(248, s)), s, p, o, m)
+# define BOOST_PP_FOR_248(s, p, o, m) BOOST_PP_FOR_248_C(BOOST_PP_BOOL(p(249, s)), s, p, o, m)
+# define BOOST_PP_FOR_249(s, p, o, m) BOOST_PP_FOR_249_C(BOOST_PP_BOOL(p(250, s)), s, p, o, m)
+# define BOOST_PP_FOR_250(s, p, o, m) BOOST_PP_FOR_250_C(BOOST_PP_BOOL(p(251, s)), s, p, o, m)
+# define BOOST_PP_FOR_251(s, p, o, m) BOOST_PP_FOR_251_C(BOOST_PP_BOOL(p(252, s)), s, p, o, m)
+# define BOOST_PP_FOR_252(s, p, o, m) BOOST_PP_FOR_252_C(BOOST_PP_BOOL(p(253, s)), s, p, o, m)
+# define BOOST_PP_FOR_253(s, p, o, m) BOOST_PP_FOR_253_C(BOOST_PP_BOOL(p(254, s)), s, p, o, m)
+# define BOOST_PP_FOR_254(s, p, o, m) BOOST_PP_FOR_254_C(BOOST_PP_BOOL(p(255, s)), s, p, o, m)
+# define BOOST_PP_FOR_255(s, p, o, m) BOOST_PP_FOR_255_C(BOOST_PP_BOOL(p(256, s)), s, p, o, m)
+# define BOOST_PP_FOR_256(s, p, o, m) BOOST_PP_FOR_256_C(BOOST_PP_BOOL(p(257, s)), s, p, o, m)
+#
+# define BOOST_PP_FOR_1_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(2, s) BOOST_PP_IIF(c, BOOST_PP_FOR_2, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(2, s), p, o, m)
+# define BOOST_PP_FOR_2_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(3, s) BOOST_PP_IIF(c, BOOST_PP_FOR_3, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(3, s), p, o, m)
+# define BOOST_PP_FOR_3_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(4, s) BOOST_PP_IIF(c, BOOST_PP_FOR_4, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(4, s), p, o, m)
+# define BOOST_PP_FOR_4_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(5, s) BOOST_PP_IIF(c, BOOST_PP_FOR_5, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(5, s), p, o, m)
+# define BOOST_PP_FOR_5_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(6, s) BOOST_PP_IIF(c, BOOST_PP_FOR_6, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(6, s), p, o, m)
+# define BOOST_PP_FOR_6_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(7, s) BOOST_PP_IIF(c, BOOST_PP_FOR_7, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(7, s), p, o, m)
+# define BOOST_PP_FOR_7_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(8, s) BOOST_PP_IIF(c, BOOST_PP_FOR_8, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(8, s), p, o, m)
+# define BOOST_PP_FOR_8_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(9, s) BOOST_PP_IIF(c, BOOST_PP_FOR_9, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(9, s), p, o, m)
+# define BOOST_PP_FOR_9_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(10, s) BOOST_PP_IIF(c, BOOST_PP_FOR_10, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(10, s), p, o, m)
+# define BOOST_PP_FOR_10_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(11, s) BOOST_PP_IIF(c, BOOST_PP_FOR_11, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(11, s), p, o, m)
+# define BOOST_PP_FOR_11_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(12, s) BOOST_PP_IIF(c, BOOST_PP_FOR_12, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(12, s), p, o, m)
+# define BOOST_PP_FOR_12_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(13, s) BOOST_PP_IIF(c, BOOST_PP_FOR_13, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(13, s), p, o, m)
+# define BOOST_PP_FOR_13_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(14, s) BOOST_PP_IIF(c, BOOST_PP_FOR_14, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(14, s), p, o, m)
+# define BOOST_PP_FOR_14_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(15, s) BOOST_PP_IIF(c, BOOST_PP_FOR_15, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(15, s), p, o, m)
+# define BOOST_PP_FOR_15_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(16, s) BOOST_PP_IIF(c, BOOST_PP_FOR_16, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(16, s), p, o, m)
+# define BOOST_PP_FOR_16_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(17, s) BOOST_PP_IIF(c, BOOST_PP_FOR_17, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(17, s), p, o, m)
+# define BOOST_PP_FOR_17_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(18, s) BOOST_PP_IIF(c, BOOST_PP_FOR_18, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(18, s), p, o, m)
+# define BOOST_PP_FOR_18_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(19, s) BOOST_PP_IIF(c, BOOST_PP_FOR_19, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(19, s), p, o, m)
+# define BOOST_PP_FOR_19_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(20, s) BOOST_PP_IIF(c, BOOST_PP_FOR_20, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(20, s), p, o, m)
+# define BOOST_PP_FOR_20_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(21, s) BOOST_PP_IIF(c, BOOST_PP_FOR_21, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(21, s), p, o, m)
+# define BOOST_PP_FOR_21_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(22, s) BOOST_PP_IIF(c, BOOST_PP_FOR_22, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(22, s), p, o, m)
+# define BOOST_PP_FOR_22_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(23, s) BOOST_PP_IIF(c, BOOST_PP_FOR_23, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(23, s), p, o, m)
+# define BOOST_PP_FOR_23_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(24, s) BOOST_PP_IIF(c, BOOST_PP_FOR_24, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(24, s), p, o, m)
+# define BOOST_PP_FOR_24_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(25, s) BOOST_PP_IIF(c, BOOST_PP_FOR_25, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(25, s), p, o, m)
+# define BOOST_PP_FOR_25_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(26, s) BOOST_PP_IIF(c, BOOST_PP_FOR_26, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(26, s), p, o, m)
+# define BOOST_PP_FOR_26_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(27, s) BOOST_PP_IIF(c, BOOST_PP_FOR_27, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(27, s), p, o, m)
+# define BOOST_PP_FOR_27_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(28, s) BOOST_PP_IIF(c, BOOST_PP_FOR_28, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(28, s), p, o, m)
+# define BOOST_PP_FOR_28_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(29, s) BOOST_PP_IIF(c, BOOST_PP_FOR_29, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(29, s), p, o, m)
+# define BOOST_PP_FOR_29_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(30, s) BOOST_PP_IIF(c, BOOST_PP_FOR_30, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(30, s), p, o, m)
+# define BOOST_PP_FOR_30_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(31, s) BOOST_PP_IIF(c, BOOST_PP_FOR_31, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(31, s), p, o, m)
+# define BOOST_PP_FOR_31_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(32, s) BOOST_PP_IIF(c, BOOST_PP_FOR_32, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(32, s), p, o, m)
+# define BOOST_PP_FOR_32_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(33, s) BOOST_PP_IIF(c, BOOST_PP_FOR_33, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(33, s), p, o, m)
+# define BOOST_PP_FOR_33_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(34, s) BOOST_PP_IIF(c, BOOST_PP_FOR_34, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(34, s), p, o, m)
+# define BOOST_PP_FOR_34_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(35, s) BOOST_PP_IIF(c, BOOST_PP_FOR_35, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(35, s), p, o, m)
+# define BOOST_PP_FOR_35_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(36, s) BOOST_PP_IIF(c, BOOST_PP_FOR_36, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(36, s), p, o, m)
+# define BOOST_PP_FOR_36_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(37, s) BOOST_PP_IIF(c, BOOST_PP_FOR_37, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(37, s), p, o, m)
+# define BOOST_PP_FOR_37_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(38, s) BOOST_PP_IIF(c, BOOST_PP_FOR_38, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(38, s), p, o, m)
+# define BOOST_PP_FOR_38_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(39, s) BOOST_PP_IIF(c, BOOST_PP_FOR_39, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(39, s), p, o, m)
+# define BOOST_PP_FOR_39_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(40, s) BOOST_PP_IIF(c, BOOST_PP_FOR_40, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(40, s), p, o, m)
+# define BOOST_PP_FOR_40_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(41, s) BOOST_PP_IIF(c, BOOST_PP_FOR_41, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(41, s), p, o, m)
+# define BOOST_PP_FOR_41_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(42, s) BOOST_PP_IIF(c, BOOST_PP_FOR_42, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(42, s), p, o, m)
+# define BOOST_PP_FOR_42_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(43, s) BOOST_PP_IIF(c, BOOST_PP_FOR_43, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(43, s), p, o, m)
+# define BOOST_PP_FOR_43_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(44, s) BOOST_PP_IIF(c, BOOST_PP_FOR_44, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(44, s), p, o, m)
+# define BOOST_PP_FOR_44_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(45, s) BOOST_PP_IIF(c, BOOST_PP_FOR_45, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(45, s), p, o, m)
+# define BOOST_PP_FOR_45_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(46, s) BOOST_PP_IIF(c, BOOST_PP_FOR_46, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(46, s), p, o, m)
+# define BOOST_PP_FOR_46_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(47, s) BOOST_PP_IIF(c, BOOST_PP_FOR_47, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(47, s), p, o, m)
+# define BOOST_PP_FOR_47_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(48, s) BOOST_PP_IIF(c, BOOST_PP_FOR_48, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(48, s), p, o, m)
+# define BOOST_PP_FOR_48_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(49, s) BOOST_PP_IIF(c, BOOST_PP_FOR_49, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(49, s), p, o, m)
+# define BOOST_PP_FOR_49_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(50, s) BOOST_PP_IIF(c, BOOST_PP_FOR_50, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(50, s), p, o, m)
+# define BOOST_PP_FOR_50_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(51, s) BOOST_PP_IIF(c, BOOST_PP_FOR_51, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(51, s), p, o, m)
+# define BOOST_PP_FOR_51_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(52, s) BOOST_PP_IIF(c, BOOST_PP_FOR_52, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(52, s), p, o, m)
+# define BOOST_PP_FOR_52_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(53, s) BOOST_PP_IIF(c, BOOST_PP_FOR_53, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(53, s), p, o, m)
+# define BOOST_PP_FOR_53_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(54, s) BOOST_PP_IIF(c, BOOST_PP_FOR_54, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(54, s), p, o, m)
+# define BOOST_PP_FOR_54_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(55, s) BOOST_PP_IIF(c, BOOST_PP_FOR_55, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(55, s), p, o, m)
+# define BOOST_PP_FOR_55_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(56, s) BOOST_PP_IIF(c, BOOST_PP_FOR_56, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(56, s), p, o, m)
+# define BOOST_PP_FOR_56_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(57, s) BOOST_PP_IIF(c, BOOST_PP_FOR_57, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(57, s), p, o, m)
+# define BOOST_PP_FOR_57_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(58, s) BOOST_PP_IIF(c, BOOST_PP_FOR_58, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(58, s), p, o, m)
+# define BOOST_PP_FOR_58_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(59, s) BOOST_PP_IIF(c, BOOST_PP_FOR_59, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(59, s), p, o, m)
+# define BOOST_PP_FOR_59_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(60, s) BOOST_PP_IIF(c, BOOST_PP_FOR_60, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(60, s), p, o, m)
+# define BOOST_PP_FOR_60_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(61, s) BOOST_PP_IIF(c, BOOST_PP_FOR_61, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(61, s), p, o, m)
+# define BOOST_PP_FOR_61_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(62, s) BOOST_PP_IIF(c, BOOST_PP_FOR_62, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(62, s), p, o, m)
+# define BOOST_PP_FOR_62_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(63, s) BOOST_PP_IIF(c, BOOST_PP_FOR_63, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(63, s), p, o, m)
+# define BOOST_PP_FOR_63_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(64, s) BOOST_PP_IIF(c, BOOST_PP_FOR_64, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(64, s), p, o, m)
+# define BOOST_PP_FOR_64_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(65, s) BOOST_PP_IIF(c, BOOST_PP_FOR_65, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(65, s), p, o, m)
+# define BOOST_PP_FOR_65_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(66, s) BOOST_PP_IIF(c, BOOST_PP_FOR_66, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(66, s), p, o, m)
+# define BOOST_PP_FOR_66_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(67, s) BOOST_PP_IIF(c, BOOST_PP_FOR_67, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(67, s), p, o, m)
+# define BOOST_PP_FOR_67_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(68, s) BOOST_PP_IIF(c, BOOST_PP_FOR_68, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(68, s), p, o, m)
+# define BOOST_PP_FOR_68_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(69, s) BOOST_PP_IIF(c, BOOST_PP_FOR_69, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(69, s), p, o, m)
+# define BOOST_PP_FOR_69_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(70, s) BOOST_PP_IIF(c, BOOST_PP_FOR_70, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(70, s), p, o, m)
+# define BOOST_PP_FOR_70_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(71, s) BOOST_PP_IIF(c, BOOST_PP_FOR_71, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(71, s), p, o, m)
+# define BOOST_PP_FOR_71_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(72, s) BOOST_PP_IIF(c, BOOST_PP_FOR_72, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(72, s), p, o, m)
+# define BOOST_PP_FOR_72_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(73, s) BOOST_PP_IIF(c, BOOST_PP_FOR_73, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(73, s), p, o, m)
+# define BOOST_PP_FOR_73_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(74, s) BOOST_PP_IIF(c, BOOST_PP_FOR_74, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(74, s), p, o, m)
+# define BOOST_PP_FOR_74_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(75, s) BOOST_PP_IIF(c, BOOST_PP_FOR_75, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(75, s), p, o, m)
+# define BOOST_PP_FOR_75_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(76, s) BOOST_PP_IIF(c, BOOST_PP_FOR_76, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(76, s), p, o, m)
+# define BOOST_PP_FOR_76_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(77, s) BOOST_PP_IIF(c, BOOST_PP_FOR_77, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(77, s), p, o, m)
+# define BOOST_PP_FOR_77_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(78, s) BOOST_PP_IIF(c, BOOST_PP_FOR_78, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(78, s), p, o, m)
+# define BOOST_PP_FOR_78_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(79, s) BOOST_PP_IIF(c, BOOST_PP_FOR_79, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(79, s), p, o, m)
+# define BOOST_PP_FOR_79_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(80, s) BOOST_PP_IIF(c, BOOST_PP_FOR_80, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(80, s), p, o, m)
+# define BOOST_PP_FOR_80_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(81, s) BOOST_PP_IIF(c, BOOST_PP_FOR_81, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(81, s), p, o, m)
+# define BOOST_PP_FOR_81_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(82, s) BOOST_PP_IIF(c, BOOST_PP_FOR_82, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(82, s), p, o, m)
+# define BOOST_PP_FOR_82_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(83, s) BOOST_PP_IIF(c, BOOST_PP_FOR_83, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(83, s), p, o, m)
+# define BOOST_PP_FOR_83_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(84, s) BOOST_PP_IIF(c, BOOST_PP_FOR_84, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(84, s), p, o, m)
+# define BOOST_PP_FOR_84_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(85, s) BOOST_PP_IIF(c, BOOST_PP_FOR_85, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(85, s), p, o, m)
+# define BOOST_PP_FOR_85_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(86, s) BOOST_PP_IIF(c, BOOST_PP_FOR_86, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(86, s), p, o, m)
+# define BOOST_PP_FOR_86_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(87, s) BOOST_PP_IIF(c, BOOST_PP_FOR_87, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(87, s), p, o, m)
+# define BOOST_PP_FOR_87_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(88, s) BOOST_PP_IIF(c, BOOST_PP_FOR_88, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(88, s), p, o, m)
+# define BOOST_PP_FOR_88_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(89, s) BOOST_PP_IIF(c, BOOST_PP_FOR_89, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(89, s), p, o, m)
+# define BOOST_PP_FOR_89_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(90, s) BOOST_PP_IIF(c, BOOST_PP_FOR_90, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(90, s), p, o, m)
+# define BOOST_PP_FOR_90_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(91, s) BOOST_PP_IIF(c, BOOST_PP_FOR_91, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(91, s), p, o, m)
+# define BOOST_PP_FOR_91_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(92, s) BOOST_PP_IIF(c, BOOST_PP_FOR_92, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(92, s), p, o, m)
+# define BOOST_PP_FOR_92_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(93, s) BOOST_PP_IIF(c, BOOST_PP_FOR_93, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(93, s), p, o, m)
+# define BOOST_PP_FOR_93_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(94, s) BOOST_PP_IIF(c, BOOST_PP_FOR_94, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(94, s), p, o, m)
+# define BOOST_PP_FOR_94_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(95, s) BOOST_PP_IIF(c, BOOST_PP_FOR_95, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(95, s), p, o, m)
+# define BOOST_PP_FOR_95_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(96, s) BOOST_PP_IIF(c, BOOST_PP_FOR_96, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(96, s), p, o, m)
+# define BOOST_PP_FOR_96_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(97, s) BOOST_PP_IIF(c, BOOST_PP_FOR_97, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(97, s), p, o, m)
+# define BOOST_PP_FOR_97_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(98, s) BOOST_PP_IIF(c, BOOST_PP_FOR_98, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(98, s), p, o, m)
+# define BOOST_PP_FOR_98_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(99, s) BOOST_PP_IIF(c, BOOST_PP_FOR_99, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(99, s), p, o, m)
+# define BOOST_PP_FOR_99_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(100, s) BOOST_PP_IIF(c, BOOST_PP_FOR_100, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(100, s), p, o, m)
+# define BOOST_PP_FOR_100_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(101, s) BOOST_PP_IIF(c, BOOST_PP_FOR_101, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(101, s), p, o, m)
+# define BOOST_PP_FOR_101_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(102, s) BOOST_PP_IIF(c, BOOST_PP_FOR_102, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(102, s), p, o, m)
+# define BOOST_PP_FOR_102_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(103, s) BOOST_PP_IIF(c, BOOST_PP_FOR_103, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(103, s), p, o, m)
+# define BOOST_PP_FOR_103_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(104, s) BOOST_PP_IIF(c, BOOST_PP_FOR_104, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(104, s), p, o, m)
+# define BOOST_PP_FOR_104_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(105, s) BOOST_PP_IIF(c, BOOST_PP_FOR_105, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(105, s), p, o, m)
+# define BOOST_PP_FOR_105_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(106, s) BOOST_PP_IIF(c, BOOST_PP_FOR_106, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(106, s), p, o, m)
+# define BOOST_PP_FOR_106_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(107, s) BOOST_PP_IIF(c, BOOST_PP_FOR_107, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(107, s), p, o, m)
+# define BOOST_PP_FOR_107_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(108, s) BOOST_PP_IIF(c, BOOST_PP_FOR_108, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(108, s), p, o, m)
+# define BOOST_PP_FOR_108_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(109, s) BOOST_PP_IIF(c, BOOST_PP_FOR_109, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(109, s), p, o, m)
+# define BOOST_PP_FOR_109_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(110, s) BOOST_PP_IIF(c, BOOST_PP_FOR_110, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(110, s), p, o, m)
+# define BOOST_PP_FOR_110_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(111, s) BOOST_PP_IIF(c, BOOST_PP_FOR_111, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(111, s), p, o, m)
+# define BOOST_PP_FOR_111_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(112, s) BOOST_PP_IIF(c, BOOST_PP_FOR_112, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(112, s), p, o, m)
+# define BOOST_PP_FOR_112_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(113, s) BOOST_PP_IIF(c, BOOST_PP_FOR_113, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(113, s), p, o, m)
+# define BOOST_PP_FOR_113_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(114, s) BOOST_PP_IIF(c, BOOST_PP_FOR_114, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(114, s), p, o, m)
+# define BOOST_PP_FOR_114_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(115, s) BOOST_PP_IIF(c, BOOST_PP_FOR_115, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(115, s), p, o, m)
+# define BOOST_PP_FOR_115_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(116, s) BOOST_PP_IIF(c, BOOST_PP_FOR_116, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(116, s), p, o, m)
+# define BOOST_PP_FOR_116_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(117, s) BOOST_PP_IIF(c, BOOST_PP_FOR_117, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(117, s), p, o, m)
+# define BOOST_PP_FOR_117_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(118, s) BOOST_PP_IIF(c, BOOST_PP_FOR_118, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(118, s), p, o, m)
+# define BOOST_PP_FOR_118_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(119, s) BOOST_PP_IIF(c, BOOST_PP_FOR_119, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(119, s), p, o, m)
+# define BOOST_PP_FOR_119_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(120, s) BOOST_PP_IIF(c, BOOST_PP_FOR_120, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(120, s), p, o, m)
+# define BOOST_PP_FOR_120_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(121, s) BOOST_PP_IIF(c, BOOST_PP_FOR_121, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(121, s), p, o, m)
+# define BOOST_PP_FOR_121_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(122, s) BOOST_PP_IIF(c, BOOST_PP_FOR_122, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(122, s), p, o, m)
+# define BOOST_PP_FOR_122_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(123, s) BOOST_PP_IIF(c, BOOST_PP_FOR_123, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(123, s), p, o, m)
+# define BOOST_PP_FOR_123_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(124, s) BOOST_PP_IIF(c, BOOST_PP_FOR_124, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(124, s), p, o, m)
+# define BOOST_PP_FOR_124_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(125, s) BOOST_PP_IIF(c, BOOST_PP_FOR_125, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(125, s), p, o, m)
+# define BOOST_PP_FOR_125_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(126, s) BOOST_PP_IIF(c, BOOST_PP_FOR_126, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(126, s), p, o, m)
+# define BOOST_PP_FOR_126_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(127, s) BOOST_PP_IIF(c, BOOST_PP_FOR_127, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(127, s), p, o, m)
+# define BOOST_PP_FOR_127_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(128, s) BOOST_PP_IIF(c, BOOST_PP_FOR_128, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(128, s), p, o, m)
+# define BOOST_PP_FOR_128_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(129, s) BOOST_PP_IIF(c, BOOST_PP_FOR_129, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(129, s), p, o, m)
+# define BOOST_PP_FOR_129_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(130, s) BOOST_PP_IIF(c, BOOST_PP_FOR_130, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(130, s), p, o, m)
+# define BOOST_PP_FOR_130_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(131, s) BOOST_PP_IIF(c, BOOST_PP_FOR_131, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(131, s), p, o, m)
+# define BOOST_PP_FOR_131_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(132, s) BOOST_PP_IIF(c, BOOST_PP_FOR_132, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(132, s), p, o, m)
+# define BOOST_PP_FOR_132_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(133, s) BOOST_PP_IIF(c, BOOST_PP_FOR_133, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(133, s), p, o, m)
+# define BOOST_PP_FOR_133_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(134, s) BOOST_PP_IIF(c, BOOST_PP_FOR_134, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(134, s), p, o, m)
+# define BOOST_PP_FOR_134_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(135, s) BOOST_PP_IIF(c, BOOST_PP_FOR_135, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(135, s), p, o, m)
+# define BOOST_PP_FOR_135_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(136, s) BOOST_PP_IIF(c, BOOST_PP_FOR_136, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(136, s), p, o, m)
+# define BOOST_PP_FOR_136_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(137, s) BOOST_PP_IIF(c, BOOST_PP_FOR_137, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(137, s), p, o, m)
+# define BOOST_PP_FOR_137_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(138, s) BOOST_PP_IIF(c, BOOST_PP_FOR_138, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(138, s), p, o, m)
+# define BOOST_PP_FOR_138_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(139, s) BOOST_PP_IIF(c, BOOST_PP_FOR_139, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(139, s), p, o, m)
+# define BOOST_PP_FOR_139_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(140, s) BOOST_PP_IIF(c, BOOST_PP_FOR_140, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(140, s), p, o, m)
+# define BOOST_PP_FOR_140_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(141, s) BOOST_PP_IIF(c, BOOST_PP_FOR_141, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(141, s), p, o, m)
+# define BOOST_PP_FOR_141_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(142, s) BOOST_PP_IIF(c, BOOST_PP_FOR_142, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(142, s), p, o, m)
+# define BOOST_PP_FOR_142_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(143, s) BOOST_PP_IIF(c, BOOST_PP_FOR_143, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(143, s), p, o, m)
+# define BOOST_PP_FOR_143_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(144, s) BOOST_PP_IIF(c, BOOST_PP_FOR_144, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(144, s), p, o, m)
+# define BOOST_PP_FOR_144_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(145, s) BOOST_PP_IIF(c, BOOST_PP_FOR_145, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(145, s), p, o, m)
+# define BOOST_PP_FOR_145_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(146, s) BOOST_PP_IIF(c, BOOST_PP_FOR_146, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(146, s), p, o, m)
+# define BOOST_PP_FOR_146_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(147, s) BOOST_PP_IIF(c, BOOST_PP_FOR_147, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(147, s), p, o, m)
+# define BOOST_PP_FOR_147_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(148, s) BOOST_PP_IIF(c, BOOST_PP_FOR_148, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(148, s), p, o, m)
+# define BOOST_PP_FOR_148_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(149, s) BOOST_PP_IIF(c, BOOST_PP_FOR_149, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(149, s), p, o, m)
+# define BOOST_PP_FOR_149_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(150, s) BOOST_PP_IIF(c, BOOST_PP_FOR_150, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(150, s), p, o, m)
+# define BOOST_PP_FOR_150_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(151, s) BOOST_PP_IIF(c, BOOST_PP_FOR_151, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(151, s), p, o, m)
+# define BOOST_PP_FOR_151_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(152, s) BOOST_PP_IIF(c, BOOST_PP_FOR_152, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(152, s), p, o, m)
+# define BOOST_PP_FOR_152_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(153, s) BOOST_PP_IIF(c, BOOST_PP_FOR_153, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(153, s), p, o, m)
+# define BOOST_PP_FOR_153_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(154, s) BOOST_PP_IIF(c, BOOST_PP_FOR_154, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(154, s), p, o, m)
+# define BOOST_PP_FOR_154_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(155, s) BOOST_PP_IIF(c, BOOST_PP_FOR_155, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(155, s), p, o, m)
+# define BOOST_PP_FOR_155_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(156, s) BOOST_PP_IIF(c, BOOST_PP_FOR_156, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(156, s), p, o, m)
+# define BOOST_PP_FOR_156_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(157, s) BOOST_PP_IIF(c, BOOST_PP_FOR_157, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(157, s), p, o, m)
+# define BOOST_PP_FOR_157_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(158, s) BOOST_PP_IIF(c, BOOST_PP_FOR_158, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(158, s), p, o, m)
+# define BOOST_PP_FOR_158_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(159, s) BOOST_PP_IIF(c, BOOST_PP_FOR_159, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(159, s), p, o, m)
+# define BOOST_PP_FOR_159_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(160, s) BOOST_PP_IIF(c, BOOST_PP_FOR_160, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(160, s), p, o, m)
+# define BOOST_PP_FOR_160_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(161, s) BOOST_PP_IIF(c, BOOST_PP_FOR_161, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(161, s), p, o, m)
+# define BOOST_PP_FOR_161_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(162, s) BOOST_PP_IIF(c, BOOST_PP_FOR_162, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(162, s), p, o, m)
+# define BOOST_PP_FOR_162_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(163, s) BOOST_PP_IIF(c, BOOST_PP_FOR_163, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(163, s), p, o, m)
+# define BOOST_PP_FOR_163_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(164, s) BOOST_PP_IIF(c, BOOST_PP_FOR_164, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(164, s), p, o, m)
+# define BOOST_PP_FOR_164_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(165, s) BOOST_PP_IIF(c, BOOST_PP_FOR_165, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(165, s), p, o, m)
+# define BOOST_PP_FOR_165_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(166, s) BOOST_PP_IIF(c, BOOST_PP_FOR_166, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(166, s), p, o, m)
+# define BOOST_PP_FOR_166_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(167, s) BOOST_PP_IIF(c, BOOST_PP_FOR_167, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(167, s), p, o, m)
+# define BOOST_PP_FOR_167_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(168, s) BOOST_PP_IIF(c, BOOST_PP_FOR_168, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(168, s), p, o, m)
+# define BOOST_PP_FOR_168_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(169, s) BOOST_PP_IIF(c, BOOST_PP_FOR_169, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(169, s), p, o, m)
+# define BOOST_PP_FOR_169_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(170, s) BOOST_PP_IIF(c, BOOST_PP_FOR_170, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(170, s), p, o, m)
+# define BOOST_PP_FOR_170_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(171, s) BOOST_PP_IIF(c, BOOST_PP_FOR_171, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(171, s), p, o, m)
+# define BOOST_PP_FOR_171_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(172, s) BOOST_PP_IIF(c, BOOST_PP_FOR_172, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(172, s), p, o, m)
+# define BOOST_PP_FOR_172_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(173, s) BOOST_PP_IIF(c, BOOST_PP_FOR_173, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(173, s), p, o, m)
+# define BOOST_PP_FOR_173_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(174, s) BOOST_PP_IIF(c, BOOST_PP_FOR_174, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(174, s), p, o, m)
+# define BOOST_PP_FOR_174_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(175, s) BOOST_PP_IIF(c, BOOST_PP_FOR_175, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(175, s), p, o, m)
+# define BOOST_PP_FOR_175_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(176, s) BOOST_PP_IIF(c, BOOST_PP_FOR_176, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(176, s), p, o, m)
+# define BOOST_PP_FOR_176_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(177, s) BOOST_PP_IIF(c, BOOST_PP_FOR_177, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(177, s), p, o, m)
+# define BOOST_PP_FOR_177_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(178, s) BOOST_PP_IIF(c, BOOST_PP_FOR_178, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(178, s), p, o, m)
+# define BOOST_PP_FOR_178_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(179, s) BOOST_PP_IIF(c, BOOST_PP_FOR_179, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(179, s), p, o, m)
+# define BOOST_PP_FOR_179_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(180, s) BOOST_PP_IIF(c, BOOST_PP_FOR_180, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(180, s), p, o, m)
+# define BOOST_PP_FOR_180_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(181, s) BOOST_PP_IIF(c, BOOST_PP_FOR_181, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(181, s), p, o, m)
+# define BOOST_PP_FOR_181_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(182, s) BOOST_PP_IIF(c, BOOST_PP_FOR_182, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(182, s), p, o, m)
+# define BOOST_PP_FOR_182_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(183, s) BOOST_PP_IIF(c, BOOST_PP_FOR_183, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(183, s), p, o, m)
+# define BOOST_PP_FOR_183_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(184, s) BOOST_PP_IIF(c, BOOST_PP_FOR_184, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(184, s), p, o, m)
+# define BOOST_PP_FOR_184_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(185, s) BOOST_PP_IIF(c, BOOST_PP_FOR_185, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(185, s), p, o, m)
+# define BOOST_PP_FOR_185_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(186, s) BOOST_PP_IIF(c, BOOST_PP_FOR_186, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(186, s), p, o, m)
+# define BOOST_PP_FOR_186_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(187, s) BOOST_PP_IIF(c, BOOST_PP_FOR_187, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(187, s), p, o, m)
+# define BOOST_PP_FOR_187_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(188, s) BOOST_PP_IIF(c, BOOST_PP_FOR_188, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(188, s), p, o, m)
+# define BOOST_PP_FOR_188_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(189, s) BOOST_PP_IIF(c, BOOST_PP_FOR_189, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(189, s), p, o, m)
+# define BOOST_PP_FOR_189_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(190, s) BOOST_PP_IIF(c, BOOST_PP_FOR_190, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(190, s), p, o, m)
+# define BOOST_PP_FOR_190_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(191, s) BOOST_PP_IIF(c, BOOST_PP_FOR_191, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(191, s), p, o, m)
+# define BOOST_PP_FOR_191_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(192, s) BOOST_PP_IIF(c, BOOST_PP_FOR_192, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(192, s), p, o, m)
+# define BOOST_PP_FOR_192_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(193, s) BOOST_PP_IIF(c, BOOST_PP_FOR_193, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(193, s), p, o, m)
+# define BOOST_PP_FOR_193_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(194, s) BOOST_PP_IIF(c, BOOST_PP_FOR_194, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(194, s), p, o, m)
+# define BOOST_PP_FOR_194_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(195, s) BOOST_PP_IIF(c, BOOST_PP_FOR_195, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(195, s), p, o, m)
+# define BOOST_PP_FOR_195_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(196, s) BOOST_PP_IIF(c, BOOST_PP_FOR_196, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(196, s), p, o, m)
+# define BOOST_PP_FOR_196_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(197, s) BOOST_PP_IIF(c, BOOST_PP_FOR_197, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(197, s), p, o, m)
+# define BOOST_PP_FOR_197_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(198, s) BOOST_PP_IIF(c, BOOST_PP_FOR_198, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(198, s), p, o, m)
+# define BOOST_PP_FOR_198_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(199, s) BOOST_PP_IIF(c, BOOST_PP_FOR_199, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(199, s), p, o, m)
+# define BOOST_PP_FOR_199_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(200, s) BOOST_PP_IIF(c, BOOST_PP_FOR_200, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(200, s), p, o, m)
+# define BOOST_PP_FOR_200_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(201, s) BOOST_PP_IIF(c, BOOST_PP_FOR_201, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(201, s), p, o, m)
+# define BOOST_PP_FOR_201_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(202, s) BOOST_PP_IIF(c, BOOST_PP_FOR_202, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(202, s), p, o, m)
+# define BOOST_PP_FOR_202_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(203, s) BOOST_PP_IIF(c, BOOST_PP_FOR_203, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(203, s), p, o, m)
+# define BOOST_PP_FOR_203_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(204, s) BOOST_PP_IIF(c, BOOST_PP_FOR_204, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(204, s), p, o, m)
+# define BOOST_PP_FOR_204_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(205, s) BOOST_PP_IIF(c, BOOST_PP_FOR_205, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(205, s), p, o, m)
+# define BOOST_PP_FOR_205_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(206, s) BOOST_PP_IIF(c, BOOST_PP_FOR_206, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(206, s), p, o, m)
+# define BOOST_PP_FOR_206_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(207, s) BOOST_PP_IIF(c, BOOST_PP_FOR_207, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(207, s), p, o, m)
+# define BOOST_PP_FOR_207_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(208, s) BOOST_PP_IIF(c, BOOST_PP_FOR_208, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(208, s), p, o, m)
+# define BOOST_PP_FOR_208_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(209, s) BOOST_PP_IIF(c, BOOST_PP_FOR_209, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(209, s), p, o, m)
+# define BOOST_PP_FOR_209_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(210, s) BOOST_PP_IIF(c, BOOST_PP_FOR_210, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(210, s), p, o, m)
+# define BOOST_PP_FOR_210_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(211, s) BOOST_PP_IIF(c, BOOST_PP_FOR_211, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(211, s), p, o, m)
+# define BOOST_PP_FOR_211_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(212, s) BOOST_PP_IIF(c, BOOST_PP_FOR_212, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(212, s), p, o, m)
+# define BOOST_PP_FOR_212_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(213, s) BOOST_PP_IIF(c, BOOST_PP_FOR_213, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(213, s), p, o, m)
+# define BOOST_PP_FOR_213_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(214, s) BOOST_PP_IIF(c, BOOST_PP_FOR_214, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(214, s), p, o, m)
+# define BOOST_PP_FOR_214_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(215, s) BOOST_PP_IIF(c, BOOST_PP_FOR_215, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(215, s), p, o, m)
+# define BOOST_PP_FOR_215_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(216, s) BOOST_PP_IIF(c, BOOST_PP_FOR_216, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(216, s), p, o, m)
+# define BOOST_PP_FOR_216_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(217, s) BOOST_PP_IIF(c, BOOST_PP_FOR_217, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(217, s), p, o, m)
+# define BOOST_PP_FOR_217_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(218, s) BOOST_PP_IIF(c, BOOST_PP_FOR_218, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(218, s), p, o, m)
+# define BOOST_PP_FOR_218_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(219, s) BOOST_PP_IIF(c, BOOST_PP_FOR_219, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(219, s), p, o, m)
+# define BOOST_PP_FOR_219_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(220, s) BOOST_PP_IIF(c, BOOST_PP_FOR_220, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(220, s), p, o, m)
+# define BOOST_PP_FOR_220_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(221, s) BOOST_PP_IIF(c, BOOST_PP_FOR_221, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(221, s), p, o, m)
+# define BOOST_PP_FOR_221_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(222, s) BOOST_PP_IIF(c, BOOST_PP_FOR_222, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(222, s), p, o, m)
+# define BOOST_PP_FOR_222_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(223, s) BOOST_PP_IIF(c, BOOST_PP_FOR_223, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(223, s), p, o, m)
+# define BOOST_PP_FOR_223_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(224, s) BOOST_PP_IIF(c, BOOST_PP_FOR_224, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(224, s), p, o, m)
+# define BOOST_PP_FOR_224_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(225, s) BOOST_PP_IIF(c, BOOST_PP_FOR_225, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(225, s), p, o, m)
+# define BOOST_PP_FOR_225_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(226, s) BOOST_PP_IIF(c, BOOST_PP_FOR_226, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(226, s), p, o, m)
+# define BOOST_PP_FOR_226_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(227, s) BOOST_PP_IIF(c, BOOST_PP_FOR_227, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(227, s), p, o, m)
+# define BOOST_PP_FOR_227_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(228, s) BOOST_PP_IIF(c, BOOST_PP_FOR_228, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(228, s), p, o, m)
+# define BOOST_PP_FOR_228_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(229, s) BOOST_PP_IIF(c, BOOST_PP_FOR_229, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(229, s), p, o, m)
+# define BOOST_PP_FOR_229_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(230, s) BOOST_PP_IIF(c, BOOST_PP_FOR_230, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(230, s), p, o, m)
+# define BOOST_PP_FOR_230_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(231, s) BOOST_PP_IIF(c, BOOST_PP_FOR_231, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(231, s), p, o, m)
+# define BOOST_PP_FOR_231_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(232, s) BOOST_PP_IIF(c, BOOST_PP_FOR_232, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(232, s), p, o, m)
+# define BOOST_PP_FOR_232_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(233, s) BOOST_PP_IIF(c, BOOST_PP_FOR_233, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(233, s), p, o, m)
+# define BOOST_PP_FOR_233_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(234, s) BOOST_PP_IIF(c, BOOST_PP_FOR_234, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(234, s), p, o, m)
+# define BOOST_PP_FOR_234_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(235, s) BOOST_PP_IIF(c, BOOST_PP_FOR_235, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(235, s), p, o, m)
+# define BOOST_PP_FOR_235_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(236, s) BOOST_PP_IIF(c, BOOST_PP_FOR_236, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(236, s), p, o, m)
+# define BOOST_PP_FOR_236_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(237, s) BOOST_PP_IIF(c, BOOST_PP_FOR_237, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(237, s), p, o, m)
+# define BOOST_PP_FOR_237_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(238, s) BOOST_PP_IIF(c, BOOST_PP_FOR_238, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(238, s), p, o, m)
+# define BOOST_PP_FOR_238_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(239, s) BOOST_PP_IIF(c, BOOST_PP_FOR_239, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(239, s), p, o, m)
+# define BOOST_PP_FOR_239_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(240, s) BOOST_PP_IIF(c, BOOST_PP_FOR_240, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(240, s), p, o, m)
+# define BOOST_PP_FOR_240_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(241, s) BOOST_PP_IIF(c, BOOST_PP_FOR_241, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(241, s), p, o, m)
+# define BOOST_PP_FOR_241_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(242, s) BOOST_PP_IIF(c, BOOST_PP_FOR_242, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(242, s), p, o, m)
+# define BOOST_PP_FOR_242_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(243, s) BOOST_PP_IIF(c, BOOST_PP_FOR_243, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(243, s), p, o, m)
+# define BOOST_PP_FOR_243_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(244, s) BOOST_PP_IIF(c, BOOST_PP_FOR_244, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(244, s), p, o, m)
+# define BOOST_PP_FOR_244_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(245, s) BOOST_PP_IIF(c, BOOST_PP_FOR_245, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(245, s), p, o, m)
+# define BOOST_PP_FOR_245_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(246, s) BOOST_PP_IIF(c, BOOST_PP_FOR_246, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(246, s), p, o, m)
+# define BOOST_PP_FOR_246_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(247, s) BOOST_PP_IIF(c, BOOST_PP_FOR_247, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(247, s), p, o, m)
+# define BOOST_PP_FOR_247_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(248, s) BOOST_PP_IIF(c, BOOST_PP_FOR_248, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(248, s), p, o, m)
+# define BOOST_PP_FOR_248_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(249, s) BOOST_PP_IIF(c, BOOST_PP_FOR_249, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(249, s), p, o, m)
+# define BOOST_PP_FOR_249_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(250, s) BOOST_PP_IIF(c, BOOST_PP_FOR_250, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(250, s), p, o, m)
+# define BOOST_PP_FOR_250_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(251, s) BOOST_PP_IIF(c, BOOST_PP_FOR_251, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(251, s), p, o, m)
+# define BOOST_PP_FOR_251_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(252, s) BOOST_PP_IIF(c, BOOST_PP_FOR_252, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(252, s), p, o, m)
+# define BOOST_PP_FOR_252_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(253, s) BOOST_PP_IIF(c, BOOST_PP_FOR_253, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(253, s), p, o, m)
+# define BOOST_PP_FOR_253_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(254, s) BOOST_PP_IIF(c, BOOST_PP_FOR_254, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(254, s), p, o, m)
+# define BOOST_PP_FOR_254_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(255, s) BOOST_PP_IIF(c, BOOST_PP_FOR_255, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(255, s), p, o, m)
+# define BOOST_PP_FOR_255_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(256, s) BOOST_PP_IIF(c, BOOST_PP_FOR_256, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(256, s), p, o, m)
+# define BOOST_PP_FOR_256_C(c, s, p, o, m) BOOST_PP_IIF(c, m, BOOST_PP_TUPLE_EAT_2)(257, s) BOOST_PP_IIF(c, BOOST_PP_FOR_257, BOOST_PP_TUPLE_EAT_4)(BOOST_PP_EXPR_IIF(c, o)(257, s), p, o, m)
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/repetition/enum.hpp b/third_party/boost/boost/preprocessor/repetition/enum.hpp
new file mode 100644
index 0000000..0198cd9
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/repetition/enum.hpp
@@ -0,0 +1,66 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_REPETITION_ENUM_HPP
+# define BOOST_PREPROCESSOR_REPETITION_ENUM_HPP
+#
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/debug/error.hpp>
+# include <boost/preprocessor/detail/auto_rec.hpp>
+# include <boost/preprocessor/punctuation/comma_if.hpp>
+# include <boost/preprocessor/repetition/repeat.hpp>
+# include <boost/preprocessor/tuple/elem.hpp>
+# include <boost/preprocessor/tuple/rem.hpp>
+#
+# /* BOOST_PP_ENUM */
+#
+# if 0
+# define BOOST_PP_ENUM(count, macro, data)
+# endif
+#
+# define BOOST_PP_ENUM BOOST_PP_CAT(BOOST_PP_ENUM_, BOOST_PP_AUTO_REC(BOOST_PP_REPEAT_P, 4))
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_ENUM_1(c, m, d) BOOST_PP_REPEAT_1(c, BOOST_PP_ENUM_M_1, (m, d))
+# define BOOST_PP_ENUM_2(c, m, d) BOOST_PP_REPEAT_2(c, BOOST_PP_ENUM_M_2, (m, d))
+# define BOOST_PP_ENUM_3(c, m, d) BOOST_PP_REPEAT_3(c, BOOST_PP_ENUM_M_3, (m, d))
+# else
+# define BOOST_PP_ENUM_1(c, m, d) BOOST_PP_ENUM_1_I(c, m, d)
+# define BOOST_PP_ENUM_2(c, m, d) BOOST_PP_ENUM_2_I(c, m, d)
+# define BOOST_PP_ENUM_3(c, m, d) BOOST_PP_ENUM_3_I(c, m, d)
+# define BOOST_PP_ENUM_1_I(c, m, d) BOOST_PP_REPEAT_1(c, BOOST_PP_ENUM_M_1, (m, d))
+# define BOOST_PP_ENUM_2_I(c, m, d) BOOST_PP_REPEAT_2(c, BOOST_PP_ENUM_M_2, (m, d))
+# define BOOST_PP_ENUM_3_I(c, m, d) BOOST_PP_REPEAT_3(c, BOOST_PP_ENUM_M_3, (m, d))
+# endif
+#
+# define BOOST_PP_ENUM_4(c, m, d) BOOST_PP_ERROR(0x0003)
+#
+# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT()
+# define BOOST_PP_ENUM_M_1(z, n, md) BOOST_PP_ENUM_M_1_IM(z, n, BOOST_PP_TUPLE_REM_2 md)
+# define BOOST_PP_ENUM_M_2(z, n, md) BOOST_PP_ENUM_M_2_IM(z, n, BOOST_PP_TUPLE_REM_2 md)
+# define BOOST_PP_ENUM_M_3(z, n, md) BOOST_PP_ENUM_M_3_IM(z, n, BOOST_PP_TUPLE_REM_2 md)
+# define BOOST_PP_ENUM_M_1_IM(z, n, im) BOOST_PP_ENUM_M_1_I(z, n, im)
+# define BOOST_PP_ENUM_M_2_IM(z, n, im) BOOST_PP_ENUM_M_2_I(z, n, im)
+# define BOOST_PP_ENUM_M_3_IM(z, n, im) BOOST_PP_ENUM_M_3_I(z, n, im)
+# else
+# define BOOST_PP_ENUM_M_1(z, n, md) BOOST_PP_ENUM_M_1_I(z, n, BOOST_PP_TUPLE_ELEM(2, 0, md), BOOST_PP_TUPLE_ELEM(2, 1, md))
+# define BOOST_PP_ENUM_M_2(z, n, md) BOOST_PP_ENUM_M_2_I(z, n, BOOST_PP_TUPLE_ELEM(2, 0, md), BOOST_PP_TUPLE_ELEM(2, 1, md))
+# define BOOST_PP_ENUM_M_3(z, n, md) BOOST_PP_ENUM_M_3_I(z, n, BOOST_PP_TUPLE_ELEM(2, 0, md), BOOST_PP_TUPLE_ELEM(2, 1, md))
+# endif
+#
+# define BOOST_PP_ENUM_M_1_I(z, n, m, d) BOOST_PP_COMMA_IF(n) m(z, n, d)
+# define BOOST_PP_ENUM_M_2_I(z, n, m, d) BOOST_PP_COMMA_IF(n) m(z, n, d)
+# define BOOST_PP_ENUM_M_3_I(z, n, m, d) BOOST_PP_COMMA_IF(n) m(z, n, d)
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/repetition/enum_binary_params.hpp b/third_party/boost/boost/preprocessor/repetition/enum_binary_params.hpp
new file mode 100644
index 0000000..a2c1048
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/repetition/enum_binary_params.hpp
@@ -0,0 +1,54 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_REPETITION_ENUM_BINARY_PARAMS_HPP
+# define BOOST_PREPROCESSOR_REPETITION_ENUM_BINARY_PARAMS_HPP
+#
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/punctuation/comma_if.hpp>
+# include <boost/preprocessor/repetition/repeat.hpp>
+# include <boost/preprocessor/tuple/elem.hpp>
+# include <boost/preprocessor/tuple/rem.hpp>
+#
+# /* BOOST_PP_ENUM_BINARY_PARAMS */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_ENUM_BINARY_PARAMS(count, p1, p2) BOOST_PP_REPEAT(count, BOOST_PP_ENUM_BINARY_PARAMS_M, (p1, p2))
+# else
+# define BOOST_PP_ENUM_BINARY_PARAMS(count, p1, p2) BOOST_PP_ENUM_BINARY_PARAMS_I(count, p1, p2)
+# define BOOST_PP_ENUM_BINARY_PARAMS_I(count, p1, p2) BOOST_PP_REPEAT(count, BOOST_PP_ENUM_BINARY_PARAMS_M, (p1, p2))
+# endif
+#
+# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT()
+# define BOOST_PP_ENUM_BINARY_PARAMS_M(z, n, pp) BOOST_PP_ENUM_BINARY_PARAMS_M_IM(z, n, BOOST_PP_TUPLE_REM_2 pp)
+# define BOOST_PP_ENUM_BINARY_PARAMS_M_IM(z, n, im) BOOST_PP_ENUM_BINARY_PARAMS_M_I(z, n, im)
+# else
+# define BOOST_PP_ENUM_BINARY_PARAMS_M(z, n, pp) BOOST_PP_ENUM_BINARY_PARAMS_M_I(z, n, BOOST_PP_TUPLE_ELEM(2, 0, pp), BOOST_PP_TUPLE_ELEM(2, 1, pp))
+# endif
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MSVC()
+# define BOOST_PP_ENUM_BINARY_PARAMS_M_I(z, n, p1, p2) BOOST_PP_ENUM_BINARY_PARAMS_M_II(z, n, p1, p2)
+# define BOOST_PP_ENUM_BINARY_PARAMS_M_II(z, n, p1, p2) BOOST_PP_COMMA_IF(n) p1 ## n p2 ## n
+# else
+# define BOOST_PP_ENUM_BINARY_PARAMS_M_I(z, n, p1, p2) BOOST_PP_COMMA_IF(n) BOOST_PP_CAT(p1, n) BOOST_PP_CAT(p2, n)
+# endif
+#
+# /* BOOST_PP_ENUM_BINARY_PARAMS_Z */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_ENUM_BINARY_PARAMS_Z(z, count, p1, p2) BOOST_PP_REPEAT_ ## z(count, BOOST_PP_ENUM_BINARY_PARAMS_M, (p1, p2))
+# else
+# define BOOST_PP_ENUM_BINARY_PARAMS_Z(z, count, p1, p2) BOOST_PP_ENUM_BINARY_PARAMS_Z_I(z, count, p1, p2)
+# define BOOST_PP_ENUM_BINARY_PARAMS_Z_I(z, count, p1, p2) BOOST_PP_REPEAT_ ## z(count, BOOST_PP_ENUM_BINARY_PARAMS_M, (p1, p2))
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/repetition/enum_params.hpp b/third_party/boost/boost/preprocessor/repetition/enum_params.hpp
new file mode 100644
index 0000000..65a2369
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/repetition/enum_params.hpp
@@ -0,0 +1,41 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_REPETITION_ENUM_PARAMS_HPP
+# define BOOST_PREPROCESSOR_REPETITION_ENUM_PARAMS_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/punctuation/comma_if.hpp>
+# include <boost/preprocessor/repetition/repeat.hpp>
+#
+# /* BOOST_PP_ENUM_PARAMS */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_ENUM_PARAMS(count, param) BOOST_PP_REPEAT(count, BOOST_PP_ENUM_PARAMS_M, param)
+# else
+# define BOOST_PP_ENUM_PARAMS(count, param) BOOST_PP_ENUM_PARAMS_I(count, param)
+# define BOOST_PP_ENUM_PARAMS_I(count, param) BOOST_PP_REPEAT(count, BOOST_PP_ENUM_PARAMS_M, param)
+# endif
+#
+# define BOOST_PP_ENUM_PARAMS_M(z, n, param) BOOST_PP_COMMA_IF(n) param ## n
+#
+# /* BOOST_PP_ENUM_PARAMS_Z */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_ENUM_PARAMS_Z(z, count, param) BOOST_PP_REPEAT_ ## z(count, BOOST_PP_ENUM_PARAMS_M, param)
+# else
+# define BOOST_PP_ENUM_PARAMS_Z(z, count, param) BOOST_PP_ENUM_PARAMS_Z_I(z, count, param)
+# define BOOST_PP_ENUM_PARAMS_Z_I(z, count, param) BOOST_PP_REPEAT_ ## z(count, BOOST_PP_ENUM_PARAMS_M, param)
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/repetition/enum_params_with_a_default.hpp b/third_party/boost/boost/preprocessor/repetition/enum_params_with_a_default.hpp
new file mode 100644
index 0000000..7496df6
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/repetition/enum_params_with_a_default.hpp
@@ -0,0 +1,25 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_REPETITION_ENUM_PARAMS_WITH_A_DEFAULT_HPP
+# define BOOST_PREPROCESSOR_REPETITION_ENUM_PARAMS_WITH_A_DEFAULT_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/facilities/intercept.hpp>
+# include <boost/preprocessor/repetition/enum_binary_params.hpp>
+#
+# /* BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT */
+#
+# define BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(count, param, def) BOOST_PP_ENUM_BINARY_PARAMS(count, param, = def BOOST_PP_INTERCEPT)
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/repetition/enum_params_with_defaults.hpp b/third_party/boost/boost/preprocessor/repetition/enum_params_with_defaults.hpp
new file mode 100644
index 0000000..fa0106f
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/repetition/enum_params_with_defaults.hpp
@@ -0,0 +1,24 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_REPETITION_ENUM_PARAMS_WITH_DEFAULTS_HPP
+# define BOOST_PREPROCESSOR_REPETITION_ENUM_PARAMS_WITH_DEFAULTS_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/repetition/enum_binary_params.hpp>
+#
+# /* BOOST_PP_ENUM_PARAMS_WITH_DEFAULTS */
+#
+# define BOOST_PP_ENUM_PARAMS_WITH_DEFAULTS(count, param, def) BOOST_PP_ENUM_BINARY_PARAMS(count, param, = def)
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/repetition/enum_shifted.hpp b/third_party/boost/boost/preprocessor/repetition/enum_shifted.hpp
new file mode 100644
index 0000000..d5b006f
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/repetition/enum_shifted.hpp
@@ -0,0 +1,68 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_REPETITION_ENUM_SHIFTED_HPP
+# define BOOST_PREPROCESSOR_REPETITION_ENUM_SHIFTED_HPP
+#
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/arithmetic/dec.hpp>
+# include <boost/preprocessor/arithmetic/inc.hpp>
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/debug/error.hpp>
+# include <boost/preprocessor/detail/auto_rec.hpp>
+# include <boost/preprocessor/punctuation/comma_if.hpp>
+# include <boost/preprocessor/repetition/repeat.hpp>
+# include <boost/preprocessor/tuple/elem.hpp>
+# include <boost/preprocessor/tuple/rem.hpp>
+#
+# /* BOOST_PP_ENUM_SHIFTED */
+#
+# if 0
+# define BOOST_PP_ENUM_SHIFTED(count, macro, data)
+# endif
+#
+# define BOOST_PP_ENUM_SHIFTED BOOST_PP_CAT(BOOST_PP_ENUM_SHIFTED_, BOOST_PP_AUTO_REC(BOOST_PP_REPEAT_P, 4))
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_ENUM_SHIFTED_1(c, m, d) BOOST_PP_REPEAT_1(BOOST_PP_DEC(c), BOOST_PP_ENUM_SHIFTED_M_1, (m, d))
+# define BOOST_PP_ENUM_SHIFTED_2(c, m, d) BOOST_PP_REPEAT_2(BOOST_PP_DEC(c), BOOST_PP_ENUM_SHIFTED_M_2, (m, d))
+# define BOOST_PP_ENUM_SHIFTED_3(c, m, d) BOOST_PP_REPEAT_3(BOOST_PP_DEC(c), BOOST_PP_ENUM_SHIFTED_M_3, (m, d))
+# else
+# define BOOST_PP_ENUM_SHIFTED_1(c, m, d) BOOST_PP_ENUM_SHIFTED_1_I(c, m, d)
+# define BOOST_PP_ENUM_SHIFTED_2(c, m, d) BOOST_PP_ENUM_SHIFTED_1_2(c, m, d)
+# define BOOST_PP_ENUM_SHIFTED_3(c, m, d) BOOST_PP_ENUM_SHIFTED_1_3(c, m, d)
+# define BOOST_PP_ENUM_SHIFTED_1_I(c, m, d) BOOST_PP_REPEAT_1(BOOST_PP_DEC(c), BOOST_PP_ENUM_SHIFTED_M_1, (m, d))
+# define BOOST_PP_ENUM_SHIFTED_2_I(c, m, d) BOOST_PP_REPEAT_2(BOOST_PP_DEC(c), BOOST_PP_ENUM_SHIFTED_M_2, (m, d))
+# define BOOST_PP_ENUM_SHIFTED_3_I(c, m, d) BOOST_PP_REPEAT_3(BOOST_PP_DEC(c), BOOST_PP_ENUM_SHIFTED_M_3, (m, d))
+# endif
+#
+# define BOOST_PP_ENUM_SHIFTED_4(c, m, d) BOOST_PP_ERROR(0x0003)
+#
+# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT()
+# define BOOST_PP_ENUM_SHIFTED_M_1(z, n, md) BOOST_PP_ENUM_SHIFTED_M_1_IM(z, n, BOOST_PP_TUPLE_REM_2 md)
+# define BOOST_PP_ENUM_SHIFTED_M_2(z, n, md) BOOST_PP_ENUM_SHIFTED_M_2_IM(z, n, BOOST_PP_TUPLE_REM_2 md)
+# define BOOST_PP_ENUM_SHIFTED_M_3(z, n, md) BOOST_PP_ENUM_SHIFTED_M_3_IM(z, n, BOOST_PP_TUPLE_REM_2 md)
+# define BOOST_PP_ENUM_SHIFTED_M_1_IM(z, n, im) BOOST_PP_ENUM_SHIFTED_M_1_I(z, n, im)
+# define BOOST_PP_ENUM_SHIFTED_M_2_IM(z, n, im) BOOST_PP_ENUM_SHIFTED_M_2_I(z, n, im)
+# define BOOST_PP_ENUM_SHIFTED_M_3_IM(z, n, im) BOOST_PP_ENUM_SHIFTED_M_3_I(z, n, im)
+# else
+# define BOOST_PP_ENUM_SHIFTED_M_1(z, n, md) BOOST_PP_ENUM_SHIFTED_M_1_I(z, n, BOOST_PP_TUPLE_ELEM(2, 0, md), BOOST_PP_TUPLE_ELEM(2, 1, md))
+# define BOOST_PP_ENUM_SHIFTED_M_2(z, n, md) BOOST_PP_ENUM_SHIFTED_M_2_I(z, n, BOOST_PP_TUPLE_ELEM(2, 0, md), BOOST_PP_TUPLE_ELEM(2, 1, md))
+# define BOOST_PP_ENUM_SHIFTED_M_3(z, n, md) BOOST_PP_ENUM_SHIFTED_M_3_I(z, n, BOOST_PP_TUPLE_ELEM(2, 0, md), BOOST_PP_TUPLE_ELEM(2, 1, md))
+# endif
+#
+# define BOOST_PP_ENUM_SHIFTED_M_1_I(z, n, m, d) BOOST_PP_COMMA_IF(n) m(z, BOOST_PP_INC(n), d)
+# define BOOST_PP_ENUM_SHIFTED_M_2_I(z, n, m, d) BOOST_PP_COMMA_IF(n) m(z, BOOST_PP_INC(n), d)
+# define BOOST_PP_ENUM_SHIFTED_M_3_I(z, n, m, d) BOOST_PP_COMMA_IF(n) m(z, BOOST_PP_INC(n), d)
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/repetition/enum_shifted_binary_params.hpp b/third_party/boost/boost/preprocessor/repetition/enum_shifted_binary_params.hpp
new file mode 100644
index 0000000..f3d20fc
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/repetition/enum_shifted_binary_params.hpp
@@ -0,0 +1,51 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 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) *
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_REPETITION_ENUM_SHIFTED_BINARY_PARAMS_HPP
+# define BOOST_PREPROCESSOR_REPETITION_ENUM_SHIFTED_BINARY_PARAMS_HPP
+#
+# include <boost/preprocessor/arithmetic/dec.hpp>
+# include <boost/preprocessor/arithmetic/inc.hpp>
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/punctuation/comma_if.hpp>
+# include <boost/preprocessor/repetition/repeat.hpp>
+# include <boost/preprocessor/tuple/elem.hpp>
+# include <boost/preprocessor/tuple/rem.hpp>
+#
+# /* BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS(count, p1, p2) BOOST_PP_REPEAT(BOOST_PP_DEC(count), BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_M, (p1, p2))
+# else
+# define BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS(count, p1, p2) BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_I(count, p1, p2)
+# define BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_I(count, p1, p2) BOOST_PP_REPEAT(BOOST_PP_DEC(count), BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_M, (p1, p2))
+# endif
+#
+# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT()
+# define BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_M(z, n, pp) BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_M_IM(z, n, BOOST_PP_TUPLE_REM_2 pp)
+# define BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_M_IM(z, n, im) BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_M_I(z, n, im)
+# else
+# define BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_M(z, n, pp) BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_M_I(z, n, BOOST_PP_TUPLE_ELEM(2, 0, pp), BOOST_PP_TUPLE_ELEM(2, 1, pp))
+# endif
+#
+# define BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_M_I(z, n, p1, p2) BOOST_PP_COMMA_IF(n) BOOST_PP_CAT(p1, BOOST_PP_INC(n)) BOOST_PP_CAT(p2, BOOST_PP_INC(n))
+#
+# /* BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_Z */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_Z(z, count, p1, p2) BOOST_PP_REPEAT_ ## z(BOOST_PP_DEC(count), BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_M, (p1, p2))
+# else
+# define BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_Z(z, count, p1, p2) BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_Z_I(z, count, p1, p2)
+# define BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_Z_I(z, count, p1, p2) BOOST_PP_REPEAT_ ## z(BOOST_PP_DEC(count), BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS_M, (p1, p2))
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/repetition/enum_shifted_params.hpp b/third_party/boost/boost/preprocessor/repetition/enum_shifted_params.hpp
new file mode 100644
index 0000000..88b2bf4
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/repetition/enum_shifted_params.hpp
@@ -0,0 +1,44 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_REPETITION_ENUM_SHIFTED_PARAMS_HPP
+# define BOOST_PREPROCESSOR_REPETITION_ENUM_SHIFTED_PARAMS_HPP
+#
+# include <boost/preprocessor/arithmetic/dec.hpp>
+# include <boost/preprocessor/arithmetic/inc.hpp>
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/punctuation/comma_if.hpp>
+# include <boost/preprocessor/repetition/repeat.hpp>
+#
+# /* BOOST_PP_ENUM_SHIFTED_PARAMS */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_ENUM_SHIFTED_PARAMS(count, param) BOOST_PP_REPEAT(BOOST_PP_DEC(count), BOOST_PP_ENUM_SHIFTED_PARAMS_M, param)
+# else
+# define BOOST_PP_ENUM_SHIFTED_PARAMS(count, param) BOOST_PP_ENUM_SHIFTED_PARAMS_I(count, param)
+# define BOOST_PP_ENUM_SHIFTED_PARAMS_I(count, param) BOOST_PP_REPEAT(BOOST_PP_DEC(count), BOOST_PP_ENUM_SHIFTED_PARAMS_M, param)
+# endif
+#
+# define BOOST_PP_ENUM_SHIFTED_PARAMS_M(z, n, param) BOOST_PP_COMMA_IF(n) BOOST_PP_CAT(param, BOOST_PP_INC(n))
+#
+# /* BOOST_PP_ENUM_SHIFTED_PARAMS_Z */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_ENUM_SHIFTED_PARAMS_Z(z, count, param) BOOST_PP_REPEAT_ ## z(BOOST_PP_DEC(count), BOOST_PP_ENUM_SHIFTED_PARAMS_M, param)
+# else
+# define BOOST_PP_ENUM_SHIFTED_PARAMS_Z(z, count, param) BOOST_PP_ENUM_SHIFTED_PARAMS_Z_I(z, count, param)
+# define BOOST_PP_ENUM_SHIFTED_PARAMS_Z_I(z, count, param) BOOST_PP_REPEAT_ ## z(BOOST_PP_DEC(count), BOOST_PP_ENUM_SHIFTED_PARAMS_M, param)
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/repetition/enum_trailing.hpp b/third_party/boost/boost/preprocessor/repetition/enum_trailing.hpp
new file mode 100644
index 0000000..20af2d5
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/repetition/enum_trailing.hpp
@@ -0,0 +1,63 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_REPETITION_ENUM_TRAILING_HPP
+# define BOOST_PREPROCESSOR_REPETITION_ENUM_TRAILING_HPP
+#
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/debug/error.hpp>
+# include <boost/preprocessor/detail/auto_rec.hpp>
+# include <boost/preprocessor/repetition/repeat.hpp>
+# include <boost/preprocessor/tuple/elem.hpp>
+# include <boost/preprocessor/tuple/rem.hpp>
+#
+# /* BOOST_PP_ENUM_TRAILING */
+#
+# if 0
+# define BOOST_PP_ENUM_TRAILING(count, macro, data)
+# endif
+#
+# define BOOST_PP_ENUM_TRAILING BOOST_PP_CAT(BOOST_PP_ENUM_TRAILING_, BOOST_PP_AUTO_REC(BOOST_PP_REPEAT_P, 4))
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_ENUM_TRAILING_1(c, m, d) BOOST_PP_REPEAT_1(c, BOOST_PP_ENUM_TRAILING_M_1, (m, d))
+# define BOOST_PP_ENUM_TRAILING_2(c, m, d) BOOST_PP_REPEAT_2(c, BOOST_PP_ENUM_TRAILING_M_2, (m, d))
+# define BOOST_PP_ENUM_TRAILING_3(c, m, d) BOOST_PP_REPEAT_3(c, BOOST_PP_ENUM_TRAILING_M_3, (m, d))
+# else
+# define BOOST_PP_ENUM_TRAILING_1(c, m, d) BOOST_PP_ENUM_TRAILING_1_I(c, m, d)
+# define BOOST_PP_ENUM_TRAILING_2(c, m, d) BOOST_PP_ENUM_TRAILING_2_I(c, m, d)
+# define BOOST_PP_ENUM_TRAILING_3(c, m, d) BOOST_PP_ENUM_TRAILING_3_I(c, m, d)
+# define BOOST_PP_ENUM_TRAILING_1_I(c, m, d) BOOST_PP_REPEAT_1(c, BOOST_PP_ENUM_TRAILING_M_1, (m, d))
+# define BOOST_PP_ENUM_TRAILING_2_I(c, m, d) BOOST_PP_REPEAT_2(c, BOOST_PP_ENUM_TRAILING_M_2, (m, d))
+# define BOOST_PP_ENUM_TRAILING_3_I(c, m, d) BOOST_PP_REPEAT_3(c, BOOST_PP_ENUM_TRAILING_M_3, (m, d))
+# endif
+#
+# define BOOST_PP_ENUM_TRAILING_4(c, m, d) BOOST_PP_ERROR(0x0003)
+#
+# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT()
+# define BOOST_PP_ENUM_TRAILING_M_1(z, n, md) BOOST_PP_ENUM_TRAILING_M_1_IM(z, n, BOOST_PP_TUPLE_REM_2 md)
+# define BOOST_PP_ENUM_TRAILING_M_2(z, n, md) BOOST_PP_ENUM_TRAILING_M_2_IM(z, n, BOOST_PP_TUPLE_REM_2 md)
+# define BOOST_PP_ENUM_TRAILING_M_3(z, n, md) BOOST_PP_ENUM_TRAILING_M_3_IM(z, n, BOOST_PP_TUPLE_REM_2 md)
+# define BOOST_PP_ENUM_TRAILING_M_1_IM(z, n, im) BOOST_PP_ENUM_TRAILING_M_1_I(z, n, im)
+# define BOOST_PP_ENUM_TRAILING_M_2_IM(z, n, im) BOOST_PP_ENUM_TRAILING_M_2_I(z, n, im)
+# define BOOST_PP_ENUM_TRAILING_M_3_IM(z, n, im) BOOST_PP_ENUM_TRAILING_M_3_I(z, n, im)
+# else
+# define BOOST_PP_ENUM_TRAILING_M_1(z, n, md) BOOST_PP_ENUM_TRAILING_M_1_I(z, n, BOOST_PP_TUPLE_ELEM(2, 0, md), BOOST_PP_TUPLE_ELEM(2, 1, md))
+# define BOOST_PP_ENUM_TRAILING_M_2(z, n, md) BOOST_PP_ENUM_TRAILING_M_2_I(z, n, BOOST_PP_TUPLE_ELEM(2, 0, md), BOOST_PP_TUPLE_ELEM(2, 1, md))
+# define BOOST_PP_ENUM_TRAILING_M_3(z, n, md) BOOST_PP_ENUM_TRAILING_M_3_I(z, n, BOOST_PP_TUPLE_ELEM(2, 0, md), BOOST_PP_TUPLE_ELEM(2, 1, md))
+# endif
+#
+# define BOOST_PP_ENUM_TRAILING_M_1_I(z, n, m, d) , m(z, n, d)
+# define BOOST_PP_ENUM_TRAILING_M_2_I(z, n, m, d) , m(z, n, d)
+# define BOOST_PP_ENUM_TRAILING_M_3_I(z, n, m, d) , m(z, n, d)
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/repetition/enum_trailing_binary_params.hpp b/third_party/boost/boost/preprocessor/repetition/enum_trailing_binary_params.hpp
new file mode 100644
index 0000000..e201b69
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/repetition/enum_trailing_binary_params.hpp
@@ -0,0 +1,53 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_REPETITION_ENUM_TRAILING_BINARY_PARAMS_HPP
+# define BOOST_PREPROCESSOR_REPETITION_ENUM_TRAILING_BINARY_PARAMS_HPP
+#
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/repetition/repeat.hpp>
+# include <boost/preprocessor/tuple/elem.hpp>
+# include <boost/preprocessor/tuple/rem.hpp>
+#
+# /* BOOST_PP_ENUM_TRAILING_BINARY_PARAMS */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(count, p1, p2) BOOST_PP_REPEAT(count, BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M, (p1, p2))
+# else
+# define BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(count, p1, p2) BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_I(count, p1, p2)
+# define BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_I(count, p1, p2) BOOST_PP_REPEAT(count, BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M, (p1, p2))
+# endif
+#
+# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT()
+# define BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M(z, n, pp) BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M_IM(z, n, BOOST_PP_TUPLE_REM_2 pp)
+# define BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M_IM(z, n, im) BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M_I(z, n, im)
+# else
+# define BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M(z, n, pp) BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M_I(z, n, BOOST_PP_TUPLE_ELEM(2, 0, pp), BOOST_PP_TUPLE_ELEM(2, 1, pp))
+# endif
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MSVC()
+# define BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M_I(z, n, p1, p2) BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M_II(z, n, p1, p2)
+# define BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M_II(z, n, p1, p2) , p1 ## n p2 ## n
+# else
+# define BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M_I(z, n, p1, p2) , BOOST_PP_CAT(p1, n) BOOST_PP_CAT(p2, n)
+# endif
+#
+# /* BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, count, p1, p2) BOOST_PP_REPEAT_ ## z(count, BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M, (p1, p2))
+# else
+# define BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, count, p1, p2) BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z_I(z, count, p1, p2)
+# define BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z_I(z, count, p1, p2) BOOST_PP_REPEAT_ ## z(count, BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_M, (p1, p2))
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/repetition/enum_trailing_params.hpp b/third_party/boost/boost/preprocessor/repetition/enum_trailing_params.hpp
new file mode 100644
index 0000000..f7520db
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/repetition/enum_trailing_params.hpp
@@ -0,0 +1,38 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_REPETITION_ENUM_TRAILING_PARAMS_HPP
+# define BOOST_PREPROCESSOR_REPETITION_ENUM_TRAILING_PARAMS_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/repetition/repeat.hpp>
+#
+# /* BOOST_PP_ENUM_TRAILING_PARAMS */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_ENUM_TRAILING_PARAMS(count, param) BOOST_PP_REPEAT(count, BOOST_PP_ENUM_TRAILING_PARAMS_M, param)
+# else
+# define BOOST_PP_ENUM_TRAILING_PARAMS(count, param) BOOST_PP_ENUM_TRAILING_PARAMS_I(count, param)
+# define BOOST_PP_ENUM_TRAILING_PARAMS_I(count, param) BOOST_PP_REPEAT(count, BOOST_PP_ENUM_TRAILING_PARAMS_M, param)
+# endif
+#
+# define BOOST_PP_ENUM_TRAILING_PARAMS_M(z, n, param) , param ## n
+#
+# /* BOOST_PP_ENUM_TRAILING_PARAMS_Z */
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, count, param) BOOST_PP_REPEAT_ ## z(count, BOOST_PP_ENUM_TRAILING_PARAMS_M, param)
+# else
+# define BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, count, param) BOOST_PP_ENUM_TRAILING_PARAMS_Z_I(z, count, param)
+# define BOOST_PP_ENUM_TRAILING_PARAMS_Z_I(z, count, param) BOOST_PP_REPEAT_ ## z(count, BOOST_PP_ENUM_TRAILING_PARAMS_M, param)
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/repetition/for.hpp b/third_party/boost/boost/preprocessor/repetition/for.hpp
new file mode 100644
index 0000000..c38946b
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/repetition/for.hpp
@@ -0,0 +1,324 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_REPETITION_FOR_HPP
+# define BOOST_PREPROCESSOR_REPETITION_FOR_HPP
+#
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/debug/error.hpp>
+# include <boost/preprocessor/facilities/empty.hpp>
+# include <boost/preprocessor/logical/bool.hpp>
+# include <boost/preprocessor/detail/auto_rec.hpp>
+#
+# /* BOOST_PP_FOR */
+#
+# if 0
+# define BOOST_PP_FOR(state, pred, op, macro)
+# endif
+#
+# define BOOST_PP_FOR BOOST_PP_CAT(BOOST_PP_FOR_, BOOST_PP_AUTO_REC(BOOST_PP_FOR_P, 256))
+#
+# define BOOST_PP_FOR_P(n) BOOST_PP_CAT(BOOST_PP_FOR_CHECK_, BOOST_PP_FOR_ ## n(1, BOOST_PP_FOR_SR_P, BOOST_PP_FOR_SR_O, BOOST_PP_FOR_SR_M))
+#
+# define BOOST_PP_FOR_SR_P(r, s) s
+# define BOOST_PP_FOR_SR_O(r, s) 0
+# define BOOST_PP_FOR_SR_M(r, s) BOOST_PP_NIL
+#
+# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# include <boost/preprocessor/repetition/detail/edg/for.hpp>
+# elif BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MSVC()
+# include <boost/preprocessor/repetition/detail/msvc/for.hpp>
+# elif BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_DMC()
+# include <boost/preprocessor/repetition/detail/dmc/for.hpp>
+# else
+# include <boost/preprocessor/repetition/detail/for.hpp>
+# endif
+#
+# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_DMC()
+# define BOOST_PP_FOR_257_PR(s, p) BOOST_PP_BOOL(p##(257, s))
+# else
+# define BOOST_PP_FOR_257_PR(s, p) BOOST_PP_BOOL(p(257, s))
+# endif
+
+# define BOOST_PP_FOR_257_ERROR() BOOST_PP_ERROR(0x0002)
+# define BOOST_PP_FOR_257(s, p, o, m) \
+ BOOST_PP_IIF \
+ ( \
+ BOOST_PP_FOR_257_PR(s,p), \
+ BOOST_PP_FOR_257_ERROR, \
+ BOOST_PP_EMPTY \
+ ) \
+ () \
+/**/
+// # define BOOST_PP_FOR_257(s, p, o, m) BOOST_PP_ERROR(0x0002)
+#
+# define BOOST_PP_FOR_CHECK_BOOST_PP_NIL 1
+#
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_1(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_2(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_3(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_4(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_5(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_6(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_7(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_8(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_9(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_10(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_11(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_12(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_13(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_14(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_15(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_16(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_17(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_18(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_19(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_20(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_21(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_22(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_23(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_24(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_25(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_26(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_27(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_28(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_29(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_30(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_31(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_32(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_33(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_34(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_35(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_36(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_37(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_38(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_39(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_40(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_41(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_42(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_43(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_44(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_45(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_46(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_47(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_48(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_49(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_50(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_51(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_52(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_53(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_54(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_55(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_56(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_57(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_58(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_59(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_60(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_61(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_62(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_63(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_64(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_65(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_66(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_67(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_68(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_69(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_70(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_71(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_72(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_73(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_74(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_75(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_76(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_77(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_78(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_79(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_80(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_81(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_82(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_83(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_84(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_85(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_86(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_87(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_88(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_89(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_90(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_91(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_92(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_93(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_94(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_95(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_96(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_97(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_98(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_99(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_100(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_101(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_102(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_103(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_104(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_105(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_106(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_107(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_108(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_109(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_110(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_111(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_112(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_113(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_114(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_115(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_116(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_117(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_118(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_119(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_120(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_121(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_122(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_123(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_124(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_125(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_126(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_127(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_128(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_129(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_130(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_131(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_132(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_133(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_134(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_135(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_136(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_137(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_138(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_139(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_140(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_141(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_142(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_143(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_144(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_145(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_146(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_147(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_148(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_149(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_150(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_151(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_152(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_153(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_154(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_155(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_156(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_157(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_158(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_159(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_160(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_161(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_162(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_163(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_164(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_165(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_166(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_167(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_168(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_169(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_170(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_171(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_172(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_173(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_174(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_175(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_176(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_177(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_178(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_179(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_180(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_181(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_182(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_183(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_184(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_185(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_186(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_187(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_188(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_189(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_190(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_191(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_192(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_193(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_194(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_195(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_196(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_197(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_198(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_199(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_200(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_201(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_202(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_203(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_204(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_205(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_206(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_207(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_208(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_209(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_210(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_211(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_212(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_213(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_214(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_215(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_216(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_217(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_218(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_219(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_220(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_221(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_222(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_223(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_224(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_225(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_226(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_227(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_228(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_229(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_230(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_231(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_232(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_233(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_234(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_235(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_236(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_237(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_238(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_239(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_240(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_241(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_242(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_243(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_244(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_245(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_246(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_247(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_248(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_249(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_250(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_251(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_252(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_253(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_254(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_255(s, p, o, m) 0
+# define BOOST_PP_FOR_CHECK_BOOST_PP_FOR_256(s, p, o, m) 0
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/repetition/repeat.hpp b/third_party/boost/boost/preprocessor/repetition/repeat.hpp
new file mode 100644
index 0000000..0172738
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/repetition/repeat.hpp
@@ -0,0 +1,825 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_REPETITION_REPEAT_HPP
+# define BOOST_PREPROCESSOR_REPETITION_REPEAT_HPP
+#
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/debug/error.hpp>
+# include <boost/preprocessor/detail/auto_rec.hpp>
+# include <boost/preprocessor/tuple/eat.hpp>
+#
+# /* BOOST_PP_REPEAT */
+#
+# if 0
+# define BOOST_PP_REPEAT(count, macro, data)
+# endif
+#
+# define BOOST_PP_REPEAT BOOST_PP_CAT(BOOST_PP_REPEAT_, BOOST_PP_AUTO_REC(BOOST_PP_REPEAT_P, 4))
+#
+# define BOOST_PP_REPEAT_P(n) BOOST_PP_CAT(BOOST_PP_REPEAT_CHECK_, BOOST_PP_REPEAT_ ## n(1, BOOST_PP_NIL BOOST_PP_TUPLE_EAT_3, BOOST_PP_NIL))
+#
+# define BOOST_PP_REPEAT_CHECK_BOOST_PP_NIL 1
+# define BOOST_PP_REPEAT_CHECK_BOOST_PP_REPEAT_1(c, m, d) 0
+# define BOOST_PP_REPEAT_CHECK_BOOST_PP_REPEAT_2(c, m, d) 0
+# define BOOST_PP_REPEAT_CHECK_BOOST_PP_REPEAT_3(c, m, d) 0
+#
+# define BOOST_PP_REPEAT_1(c, m, d) BOOST_PP_REPEAT_1_I(c, m, d)
+# define BOOST_PP_REPEAT_2(c, m, d) BOOST_PP_REPEAT_2_I(c, m, d)
+# define BOOST_PP_REPEAT_3(c, m, d) BOOST_PP_REPEAT_3_I(c, m, d)
+# define BOOST_PP_REPEAT_4(c, m, d) BOOST_PP_ERROR(0x0003)
+#
+# define BOOST_PP_REPEAT_1_I(c, m, d) BOOST_PP_REPEAT_1_ ## c(m, d)
+# define BOOST_PP_REPEAT_2_I(c, m, d) BOOST_PP_REPEAT_2_ ## c(m, d)
+# define BOOST_PP_REPEAT_3_I(c, m, d) BOOST_PP_REPEAT_3_ ## c(m, d)
+#
+# define BOOST_PP_REPEAT_1ST BOOST_PP_REPEAT_1
+# define BOOST_PP_REPEAT_2ND BOOST_PP_REPEAT_2
+# define BOOST_PP_REPEAT_3RD BOOST_PP_REPEAT_3
+#
+# define BOOST_PP_REPEAT_1_0(m, d)
+# define BOOST_PP_REPEAT_1_1(m, d) m(2, 0, d)
+# define BOOST_PP_REPEAT_1_2(m, d) BOOST_PP_REPEAT_1_1(m, d) m(2, 1, d)
+# define BOOST_PP_REPEAT_1_3(m, d) BOOST_PP_REPEAT_1_2(m, d) m(2, 2, d)
+# define BOOST_PP_REPEAT_1_4(m, d) BOOST_PP_REPEAT_1_3(m, d) m(2, 3, d)
+# define BOOST_PP_REPEAT_1_5(m, d) BOOST_PP_REPEAT_1_4(m, d) m(2, 4, d)
+# define BOOST_PP_REPEAT_1_6(m, d) BOOST_PP_REPEAT_1_5(m, d) m(2, 5, d)
+# define BOOST_PP_REPEAT_1_7(m, d) BOOST_PP_REPEAT_1_6(m, d) m(2, 6, d)
+# define BOOST_PP_REPEAT_1_8(m, d) BOOST_PP_REPEAT_1_7(m, d) m(2, 7, d)
+# define BOOST_PP_REPEAT_1_9(m, d) BOOST_PP_REPEAT_1_8(m, d) m(2, 8, d)
+# define BOOST_PP_REPEAT_1_10(m, d) BOOST_PP_REPEAT_1_9(m, d) m(2, 9, d)
+# define BOOST_PP_REPEAT_1_11(m, d) BOOST_PP_REPEAT_1_10(m, d) m(2, 10, d)
+# define BOOST_PP_REPEAT_1_12(m, d) BOOST_PP_REPEAT_1_11(m, d) m(2, 11, d)
+# define BOOST_PP_REPEAT_1_13(m, d) BOOST_PP_REPEAT_1_12(m, d) m(2, 12, d)
+# define BOOST_PP_REPEAT_1_14(m, d) BOOST_PP_REPEAT_1_13(m, d) m(2, 13, d)
+# define BOOST_PP_REPEAT_1_15(m, d) BOOST_PP_REPEAT_1_14(m, d) m(2, 14, d)
+# define BOOST_PP_REPEAT_1_16(m, d) BOOST_PP_REPEAT_1_15(m, d) m(2, 15, d)
+# define BOOST_PP_REPEAT_1_17(m, d) BOOST_PP_REPEAT_1_16(m, d) m(2, 16, d)
+# define BOOST_PP_REPEAT_1_18(m, d) BOOST_PP_REPEAT_1_17(m, d) m(2, 17, d)
+# define BOOST_PP_REPEAT_1_19(m, d) BOOST_PP_REPEAT_1_18(m, d) m(2, 18, d)
+# define BOOST_PP_REPEAT_1_20(m, d) BOOST_PP_REPEAT_1_19(m, d) m(2, 19, d)
+# define BOOST_PP_REPEAT_1_21(m, d) BOOST_PP_REPEAT_1_20(m, d) m(2, 20, d)
+# define BOOST_PP_REPEAT_1_22(m, d) BOOST_PP_REPEAT_1_21(m, d) m(2, 21, d)
+# define BOOST_PP_REPEAT_1_23(m, d) BOOST_PP_REPEAT_1_22(m, d) m(2, 22, d)
+# define BOOST_PP_REPEAT_1_24(m, d) BOOST_PP_REPEAT_1_23(m, d) m(2, 23, d)
+# define BOOST_PP_REPEAT_1_25(m, d) BOOST_PP_REPEAT_1_24(m, d) m(2, 24, d)
+# define BOOST_PP_REPEAT_1_26(m, d) BOOST_PP_REPEAT_1_25(m, d) m(2, 25, d)
+# define BOOST_PP_REPEAT_1_27(m, d) BOOST_PP_REPEAT_1_26(m, d) m(2, 26, d)
+# define BOOST_PP_REPEAT_1_28(m, d) BOOST_PP_REPEAT_1_27(m, d) m(2, 27, d)
+# define BOOST_PP_REPEAT_1_29(m, d) BOOST_PP_REPEAT_1_28(m, d) m(2, 28, d)
+# define BOOST_PP_REPEAT_1_30(m, d) BOOST_PP_REPEAT_1_29(m, d) m(2, 29, d)
+# define BOOST_PP_REPEAT_1_31(m, d) BOOST_PP_REPEAT_1_30(m, d) m(2, 30, d)
+# define BOOST_PP_REPEAT_1_32(m, d) BOOST_PP_REPEAT_1_31(m, d) m(2, 31, d)
+# define BOOST_PP_REPEAT_1_33(m, d) BOOST_PP_REPEAT_1_32(m, d) m(2, 32, d)
+# define BOOST_PP_REPEAT_1_34(m, d) BOOST_PP_REPEAT_1_33(m, d) m(2, 33, d)
+# define BOOST_PP_REPEAT_1_35(m, d) BOOST_PP_REPEAT_1_34(m, d) m(2, 34, d)
+# define BOOST_PP_REPEAT_1_36(m, d) BOOST_PP_REPEAT_1_35(m, d) m(2, 35, d)
+# define BOOST_PP_REPEAT_1_37(m, d) BOOST_PP_REPEAT_1_36(m, d) m(2, 36, d)
+# define BOOST_PP_REPEAT_1_38(m, d) BOOST_PP_REPEAT_1_37(m, d) m(2, 37, d)
+# define BOOST_PP_REPEAT_1_39(m, d) BOOST_PP_REPEAT_1_38(m, d) m(2, 38, d)
+# define BOOST_PP_REPEAT_1_40(m, d) BOOST_PP_REPEAT_1_39(m, d) m(2, 39, d)
+# define BOOST_PP_REPEAT_1_41(m, d) BOOST_PP_REPEAT_1_40(m, d) m(2, 40, d)
+# define BOOST_PP_REPEAT_1_42(m, d) BOOST_PP_REPEAT_1_41(m, d) m(2, 41, d)
+# define BOOST_PP_REPEAT_1_43(m, d) BOOST_PP_REPEAT_1_42(m, d) m(2, 42, d)
+# define BOOST_PP_REPEAT_1_44(m, d) BOOST_PP_REPEAT_1_43(m, d) m(2, 43, d)
+# define BOOST_PP_REPEAT_1_45(m, d) BOOST_PP_REPEAT_1_44(m, d) m(2, 44, d)
+# define BOOST_PP_REPEAT_1_46(m, d) BOOST_PP_REPEAT_1_45(m, d) m(2, 45, d)
+# define BOOST_PP_REPEAT_1_47(m, d) BOOST_PP_REPEAT_1_46(m, d) m(2, 46, d)
+# define BOOST_PP_REPEAT_1_48(m, d) BOOST_PP_REPEAT_1_47(m, d) m(2, 47, d)
+# define BOOST_PP_REPEAT_1_49(m, d) BOOST_PP_REPEAT_1_48(m, d) m(2, 48, d)
+# define BOOST_PP_REPEAT_1_50(m, d) BOOST_PP_REPEAT_1_49(m, d) m(2, 49, d)
+# define BOOST_PP_REPEAT_1_51(m, d) BOOST_PP_REPEAT_1_50(m, d) m(2, 50, d)
+# define BOOST_PP_REPEAT_1_52(m, d) BOOST_PP_REPEAT_1_51(m, d) m(2, 51, d)
+# define BOOST_PP_REPEAT_1_53(m, d) BOOST_PP_REPEAT_1_52(m, d) m(2, 52, d)
+# define BOOST_PP_REPEAT_1_54(m, d) BOOST_PP_REPEAT_1_53(m, d) m(2, 53, d)
+# define BOOST_PP_REPEAT_1_55(m, d) BOOST_PP_REPEAT_1_54(m, d) m(2, 54, d)
+# define BOOST_PP_REPEAT_1_56(m, d) BOOST_PP_REPEAT_1_55(m, d) m(2, 55, d)
+# define BOOST_PP_REPEAT_1_57(m, d) BOOST_PP_REPEAT_1_56(m, d) m(2, 56, d)
+# define BOOST_PP_REPEAT_1_58(m, d) BOOST_PP_REPEAT_1_57(m, d) m(2, 57, d)
+# define BOOST_PP_REPEAT_1_59(m, d) BOOST_PP_REPEAT_1_58(m, d) m(2, 58, d)
+# define BOOST_PP_REPEAT_1_60(m, d) BOOST_PP_REPEAT_1_59(m, d) m(2, 59, d)
+# define BOOST_PP_REPEAT_1_61(m, d) BOOST_PP_REPEAT_1_60(m, d) m(2, 60, d)
+# define BOOST_PP_REPEAT_1_62(m, d) BOOST_PP_REPEAT_1_61(m, d) m(2, 61, d)
+# define BOOST_PP_REPEAT_1_63(m, d) BOOST_PP_REPEAT_1_62(m, d) m(2, 62, d)
+# define BOOST_PP_REPEAT_1_64(m, d) BOOST_PP_REPEAT_1_63(m, d) m(2, 63, d)
+# define BOOST_PP_REPEAT_1_65(m, d) BOOST_PP_REPEAT_1_64(m, d) m(2, 64, d)
+# define BOOST_PP_REPEAT_1_66(m, d) BOOST_PP_REPEAT_1_65(m, d) m(2, 65, d)
+# define BOOST_PP_REPEAT_1_67(m, d) BOOST_PP_REPEAT_1_66(m, d) m(2, 66, d)
+# define BOOST_PP_REPEAT_1_68(m, d) BOOST_PP_REPEAT_1_67(m, d) m(2, 67, d)
+# define BOOST_PP_REPEAT_1_69(m, d) BOOST_PP_REPEAT_1_68(m, d) m(2, 68, d)
+# define BOOST_PP_REPEAT_1_70(m, d) BOOST_PP_REPEAT_1_69(m, d) m(2, 69, d)
+# define BOOST_PP_REPEAT_1_71(m, d) BOOST_PP_REPEAT_1_70(m, d) m(2, 70, d)
+# define BOOST_PP_REPEAT_1_72(m, d) BOOST_PP_REPEAT_1_71(m, d) m(2, 71, d)
+# define BOOST_PP_REPEAT_1_73(m, d) BOOST_PP_REPEAT_1_72(m, d) m(2, 72, d)
+# define BOOST_PP_REPEAT_1_74(m, d) BOOST_PP_REPEAT_1_73(m, d) m(2, 73, d)
+# define BOOST_PP_REPEAT_1_75(m, d) BOOST_PP_REPEAT_1_74(m, d) m(2, 74, d)
+# define BOOST_PP_REPEAT_1_76(m, d) BOOST_PP_REPEAT_1_75(m, d) m(2, 75, d)
+# define BOOST_PP_REPEAT_1_77(m, d) BOOST_PP_REPEAT_1_76(m, d) m(2, 76, d)
+# define BOOST_PP_REPEAT_1_78(m, d) BOOST_PP_REPEAT_1_77(m, d) m(2, 77, d)
+# define BOOST_PP_REPEAT_1_79(m, d) BOOST_PP_REPEAT_1_78(m, d) m(2, 78, d)
+# define BOOST_PP_REPEAT_1_80(m, d) BOOST_PP_REPEAT_1_79(m, d) m(2, 79, d)
+# define BOOST_PP_REPEAT_1_81(m, d) BOOST_PP_REPEAT_1_80(m, d) m(2, 80, d)
+# define BOOST_PP_REPEAT_1_82(m, d) BOOST_PP_REPEAT_1_81(m, d) m(2, 81, d)
+# define BOOST_PP_REPEAT_1_83(m, d) BOOST_PP_REPEAT_1_82(m, d) m(2, 82, d)
+# define BOOST_PP_REPEAT_1_84(m, d) BOOST_PP_REPEAT_1_83(m, d) m(2, 83, d)
+# define BOOST_PP_REPEAT_1_85(m, d) BOOST_PP_REPEAT_1_84(m, d) m(2, 84, d)
+# define BOOST_PP_REPEAT_1_86(m, d) BOOST_PP_REPEAT_1_85(m, d) m(2, 85, d)
+# define BOOST_PP_REPEAT_1_87(m, d) BOOST_PP_REPEAT_1_86(m, d) m(2, 86, d)
+# define BOOST_PP_REPEAT_1_88(m, d) BOOST_PP_REPEAT_1_87(m, d) m(2, 87, d)
+# define BOOST_PP_REPEAT_1_89(m, d) BOOST_PP_REPEAT_1_88(m, d) m(2, 88, d)
+# define BOOST_PP_REPEAT_1_90(m, d) BOOST_PP_REPEAT_1_89(m, d) m(2, 89, d)
+# define BOOST_PP_REPEAT_1_91(m, d) BOOST_PP_REPEAT_1_90(m, d) m(2, 90, d)
+# define BOOST_PP_REPEAT_1_92(m, d) BOOST_PP_REPEAT_1_91(m, d) m(2, 91, d)
+# define BOOST_PP_REPEAT_1_93(m, d) BOOST_PP_REPEAT_1_92(m, d) m(2, 92, d)
+# define BOOST_PP_REPEAT_1_94(m, d) BOOST_PP_REPEAT_1_93(m, d) m(2, 93, d)
+# define BOOST_PP_REPEAT_1_95(m, d) BOOST_PP_REPEAT_1_94(m, d) m(2, 94, d)
+# define BOOST_PP_REPEAT_1_96(m, d) BOOST_PP_REPEAT_1_95(m, d) m(2, 95, d)
+# define BOOST_PP_REPEAT_1_97(m, d) BOOST_PP_REPEAT_1_96(m, d) m(2, 96, d)
+# define BOOST_PP_REPEAT_1_98(m, d) BOOST_PP_REPEAT_1_97(m, d) m(2, 97, d)
+# define BOOST_PP_REPEAT_1_99(m, d) BOOST_PP_REPEAT_1_98(m, d) m(2, 98, d)
+# define BOOST_PP_REPEAT_1_100(m, d) BOOST_PP_REPEAT_1_99(m, d) m(2, 99, d)
+# define BOOST_PP_REPEAT_1_101(m, d) BOOST_PP_REPEAT_1_100(m, d) m(2, 100, d)
+# define BOOST_PP_REPEAT_1_102(m, d) BOOST_PP_REPEAT_1_101(m, d) m(2, 101, d)
+# define BOOST_PP_REPEAT_1_103(m, d) BOOST_PP_REPEAT_1_102(m, d) m(2, 102, d)
+# define BOOST_PP_REPEAT_1_104(m, d) BOOST_PP_REPEAT_1_103(m, d) m(2, 103, d)
+# define BOOST_PP_REPEAT_1_105(m, d) BOOST_PP_REPEAT_1_104(m, d) m(2, 104, d)
+# define BOOST_PP_REPEAT_1_106(m, d) BOOST_PP_REPEAT_1_105(m, d) m(2, 105, d)
+# define BOOST_PP_REPEAT_1_107(m, d) BOOST_PP_REPEAT_1_106(m, d) m(2, 106, d)
+# define BOOST_PP_REPEAT_1_108(m, d) BOOST_PP_REPEAT_1_107(m, d) m(2, 107, d)
+# define BOOST_PP_REPEAT_1_109(m, d) BOOST_PP_REPEAT_1_108(m, d) m(2, 108, d)
+# define BOOST_PP_REPEAT_1_110(m, d) BOOST_PP_REPEAT_1_109(m, d) m(2, 109, d)
+# define BOOST_PP_REPEAT_1_111(m, d) BOOST_PP_REPEAT_1_110(m, d) m(2, 110, d)
+# define BOOST_PP_REPEAT_1_112(m, d) BOOST_PP_REPEAT_1_111(m, d) m(2, 111, d)
+# define BOOST_PP_REPEAT_1_113(m, d) BOOST_PP_REPEAT_1_112(m, d) m(2, 112, d)
+# define BOOST_PP_REPEAT_1_114(m, d) BOOST_PP_REPEAT_1_113(m, d) m(2, 113, d)
+# define BOOST_PP_REPEAT_1_115(m, d) BOOST_PP_REPEAT_1_114(m, d) m(2, 114, d)
+# define BOOST_PP_REPEAT_1_116(m, d) BOOST_PP_REPEAT_1_115(m, d) m(2, 115, d)
+# define BOOST_PP_REPEAT_1_117(m, d) BOOST_PP_REPEAT_1_116(m, d) m(2, 116, d)
+# define BOOST_PP_REPEAT_1_118(m, d) BOOST_PP_REPEAT_1_117(m, d) m(2, 117, d)
+# define BOOST_PP_REPEAT_1_119(m, d) BOOST_PP_REPEAT_1_118(m, d) m(2, 118, d)
+# define BOOST_PP_REPEAT_1_120(m, d) BOOST_PP_REPEAT_1_119(m, d) m(2, 119, d)
+# define BOOST_PP_REPEAT_1_121(m, d) BOOST_PP_REPEAT_1_120(m, d) m(2, 120, d)
+# define BOOST_PP_REPEAT_1_122(m, d) BOOST_PP_REPEAT_1_121(m, d) m(2, 121, d)
+# define BOOST_PP_REPEAT_1_123(m, d) BOOST_PP_REPEAT_1_122(m, d) m(2, 122, d)
+# define BOOST_PP_REPEAT_1_124(m, d) BOOST_PP_REPEAT_1_123(m, d) m(2, 123, d)
+# define BOOST_PP_REPEAT_1_125(m, d) BOOST_PP_REPEAT_1_124(m, d) m(2, 124, d)
+# define BOOST_PP_REPEAT_1_126(m, d) BOOST_PP_REPEAT_1_125(m, d) m(2, 125, d)
+# define BOOST_PP_REPEAT_1_127(m, d) BOOST_PP_REPEAT_1_126(m, d) m(2, 126, d)
+# define BOOST_PP_REPEAT_1_128(m, d) BOOST_PP_REPEAT_1_127(m, d) m(2, 127, d)
+# define BOOST_PP_REPEAT_1_129(m, d) BOOST_PP_REPEAT_1_128(m, d) m(2, 128, d)
+# define BOOST_PP_REPEAT_1_130(m, d) BOOST_PP_REPEAT_1_129(m, d) m(2, 129, d)
+# define BOOST_PP_REPEAT_1_131(m, d) BOOST_PP_REPEAT_1_130(m, d) m(2, 130, d)
+# define BOOST_PP_REPEAT_1_132(m, d) BOOST_PP_REPEAT_1_131(m, d) m(2, 131, d)
+# define BOOST_PP_REPEAT_1_133(m, d) BOOST_PP_REPEAT_1_132(m, d) m(2, 132, d)
+# define BOOST_PP_REPEAT_1_134(m, d) BOOST_PP_REPEAT_1_133(m, d) m(2, 133, d)
+# define BOOST_PP_REPEAT_1_135(m, d) BOOST_PP_REPEAT_1_134(m, d) m(2, 134, d)
+# define BOOST_PP_REPEAT_1_136(m, d) BOOST_PP_REPEAT_1_135(m, d) m(2, 135, d)
+# define BOOST_PP_REPEAT_1_137(m, d) BOOST_PP_REPEAT_1_136(m, d) m(2, 136, d)
+# define BOOST_PP_REPEAT_1_138(m, d) BOOST_PP_REPEAT_1_137(m, d) m(2, 137, d)
+# define BOOST_PP_REPEAT_1_139(m, d) BOOST_PP_REPEAT_1_138(m, d) m(2, 138, d)
+# define BOOST_PP_REPEAT_1_140(m, d) BOOST_PP_REPEAT_1_139(m, d) m(2, 139, d)
+# define BOOST_PP_REPEAT_1_141(m, d) BOOST_PP_REPEAT_1_140(m, d) m(2, 140, d)
+# define BOOST_PP_REPEAT_1_142(m, d) BOOST_PP_REPEAT_1_141(m, d) m(2, 141, d)
+# define BOOST_PP_REPEAT_1_143(m, d) BOOST_PP_REPEAT_1_142(m, d) m(2, 142, d)
+# define BOOST_PP_REPEAT_1_144(m, d) BOOST_PP_REPEAT_1_143(m, d) m(2, 143, d)
+# define BOOST_PP_REPEAT_1_145(m, d) BOOST_PP_REPEAT_1_144(m, d) m(2, 144, d)
+# define BOOST_PP_REPEAT_1_146(m, d) BOOST_PP_REPEAT_1_145(m, d) m(2, 145, d)
+# define BOOST_PP_REPEAT_1_147(m, d) BOOST_PP_REPEAT_1_146(m, d) m(2, 146, d)
+# define BOOST_PP_REPEAT_1_148(m, d) BOOST_PP_REPEAT_1_147(m, d) m(2, 147, d)
+# define BOOST_PP_REPEAT_1_149(m, d) BOOST_PP_REPEAT_1_148(m, d) m(2, 148, d)
+# define BOOST_PP_REPEAT_1_150(m, d) BOOST_PP_REPEAT_1_149(m, d) m(2, 149, d)
+# define BOOST_PP_REPEAT_1_151(m, d) BOOST_PP_REPEAT_1_150(m, d) m(2, 150, d)
+# define BOOST_PP_REPEAT_1_152(m, d) BOOST_PP_REPEAT_1_151(m, d) m(2, 151, d)
+# define BOOST_PP_REPEAT_1_153(m, d) BOOST_PP_REPEAT_1_152(m, d) m(2, 152, d)
+# define BOOST_PP_REPEAT_1_154(m, d) BOOST_PP_REPEAT_1_153(m, d) m(2, 153, d)
+# define BOOST_PP_REPEAT_1_155(m, d) BOOST_PP_REPEAT_1_154(m, d) m(2, 154, d)
+# define BOOST_PP_REPEAT_1_156(m, d) BOOST_PP_REPEAT_1_155(m, d) m(2, 155, d)
+# define BOOST_PP_REPEAT_1_157(m, d) BOOST_PP_REPEAT_1_156(m, d) m(2, 156, d)
+# define BOOST_PP_REPEAT_1_158(m, d) BOOST_PP_REPEAT_1_157(m, d) m(2, 157, d)
+# define BOOST_PP_REPEAT_1_159(m, d) BOOST_PP_REPEAT_1_158(m, d) m(2, 158, d)
+# define BOOST_PP_REPEAT_1_160(m, d) BOOST_PP_REPEAT_1_159(m, d) m(2, 159, d)
+# define BOOST_PP_REPEAT_1_161(m, d) BOOST_PP_REPEAT_1_160(m, d) m(2, 160, d)
+# define BOOST_PP_REPEAT_1_162(m, d) BOOST_PP_REPEAT_1_161(m, d) m(2, 161, d)
+# define BOOST_PP_REPEAT_1_163(m, d) BOOST_PP_REPEAT_1_162(m, d) m(2, 162, d)
+# define BOOST_PP_REPEAT_1_164(m, d) BOOST_PP_REPEAT_1_163(m, d) m(2, 163, d)
+# define BOOST_PP_REPEAT_1_165(m, d) BOOST_PP_REPEAT_1_164(m, d) m(2, 164, d)
+# define BOOST_PP_REPEAT_1_166(m, d) BOOST_PP_REPEAT_1_165(m, d) m(2, 165, d)
+# define BOOST_PP_REPEAT_1_167(m, d) BOOST_PP_REPEAT_1_166(m, d) m(2, 166, d)
+# define BOOST_PP_REPEAT_1_168(m, d) BOOST_PP_REPEAT_1_167(m, d) m(2, 167, d)
+# define BOOST_PP_REPEAT_1_169(m, d) BOOST_PP_REPEAT_1_168(m, d) m(2, 168, d)
+# define BOOST_PP_REPEAT_1_170(m, d) BOOST_PP_REPEAT_1_169(m, d) m(2, 169, d)
+# define BOOST_PP_REPEAT_1_171(m, d) BOOST_PP_REPEAT_1_170(m, d) m(2, 170, d)
+# define BOOST_PP_REPEAT_1_172(m, d) BOOST_PP_REPEAT_1_171(m, d) m(2, 171, d)
+# define BOOST_PP_REPEAT_1_173(m, d) BOOST_PP_REPEAT_1_172(m, d) m(2, 172, d)
+# define BOOST_PP_REPEAT_1_174(m, d) BOOST_PP_REPEAT_1_173(m, d) m(2, 173, d)
+# define BOOST_PP_REPEAT_1_175(m, d) BOOST_PP_REPEAT_1_174(m, d) m(2, 174, d)
+# define BOOST_PP_REPEAT_1_176(m, d) BOOST_PP_REPEAT_1_175(m, d) m(2, 175, d)
+# define BOOST_PP_REPEAT_1_177(m, d) BOOST_PP_REPEAT_1_176(m, d) m(2, 176, d)
+# define BOOST_PP_REPEAT_1_178(m, d) BOOST_PP_REPEAT_1_177(m, d) m(2, 177, d)
+# define BOOST_PP_REPEAT_1_179(m, d) BOOST_PP_REPEAT_1_178(m, d) m(2, 178, d)
+# define BOOST_PP_REPEAT_1_180(m, d) BOOST_PP_REPEAT_1_179(m, d) m(2, 179, d)
+# define BOOST_PP_REPEAT_1_181(m, d) BOOST_PP_REPEAT_1_180(m, d) m(2, 180, d)
+# define BOOST_PP_REPEAT_1_182(m, d) BOOST_PP_REPEAT_1_181(m, d) m(2, 181, d)
+# define BOOST_PP_REPEAT_1_183(m, d) BOOST_PP_REPEAT_1_182(m, d) m(2, 182, d)
+# define BOOST_PP_REPEAT_1_184(m, d) BOOST_PP_REPEAT_1_183(m, d) m(2, 183, d)
+# define BOOST_PP_REPEAT_1_185(m, d) BOOST_PP_REPEAT_1_184(m, d) m(2, 184, d)
+# define BOOST_PP_REPEAT_1_186(m, d) BOOST_PP_REPEAT_1_185(m, d) m(2, 185, d)
+# define BOOST_PP_REPEAT_1_187(m, d) BOOST_PP_REPEAT_1_186(m, d) m(2, 186, d)
+# define BOOST_PP_REPEAT_1_188(m, d) BOOST_PP_REPEAT_1_187(m, d) m(2, 187, d)
+# define BOOST_PP_REPEAT_1_189(m, d) BOOST_PP_REPEAT_1_188(m, d) m(2, 188, d)
+# define BOOST_PP_REPEAT_1_190(m, d) BOOST_PP_REPEAT_1_189(m, d) m(2, 189, d)
+# define BOOST_PP_REPEAT_1_191(m, d) BOOST_PP_REPEAT_1_190(m, d) m(2, 190, d)
+# define BOOST_PP_REPEAT_1_192(m, d) BOOST_PP_REPEAT_1_191(m, d) m(2, 191, d)
+# define BOOST_PP_REPEAT_1_193(m, d) BOOST_PP_REPEAT_1_192(m, d) m(2, 192, d)
+# define BOOST_PP_REPEAT_1_194(m, d) BOOST_PP_REPEAT_1_193(m, d) m(2, 193, d)
+# define BOOST_PP_REPEAT_1_195(m, d) BOOST_PP_REPEAT_1_194(m, d) m(2, 194, d)
+# define BOOST_PP_REPEAT_1_196(m, d) BOOST_PP_REPEAT_1_195(m, d) m(2, 195, d)
+# define BOOST_PP_REPEAT_1_197(m, d) BOOST_PP_REPEAT_1_196(m, d) m(2, 196, d)
+# define BOOST_PP_REPEAT_1_198(m, d) BOOST_PP_REPEAT_1_197(m, d) m(2, 197, d)
+# define BOOST_PP_REPEAT_1_199(m, d) BOOST_PP_REPEAT_1_198(m, d) m(2, 198, d)
+# define BOOST_PP_REPEAT_1_200(m, d) BOOST_PP_REPEAT_1_199(m, d) m(2, 199, d)
+# define BOOST_PP_REPEAT_1_201(m, d) BOOST_PP_REPEAT_1_200(m, d) m(2, 200, d)
+# define BOOST_PP_REPEAT_1_202(m, d) BOOST_PP_REPEAT_1_201(m, d) m(2, 201, d)
+# define BOOST_PP_REPEAT_1_203(m, d) BOOST_PP_REPEAT_1_202(m, d) m(2, 202, d)
+# define BOOST_PP_REPEAT_1_204(m, d) BOOST_PP_REPEAT_1_203(m, d) m(2, 203, d)
+# define BOOST_PP_REPEAT_1_205(m, d) BOOST_PP_REPEAT_1_204(m, d) m(2, 204, d)
+# define BOOST_PP_REPEAT_1_206(m, d) BOOST_PP_REPEAT_1_205(m, d) m(2, 205, d)
+# define BOOST_PP_REPEAT_1_207(m, d) BOOST_PP_REPEAT_1_206(m, d) m(2, 206, d)
+# define BOOST_PP_REPEAT_1_208(m, d) BOOST_PP_REPEAT_1_207(m, d) m(2, 207, d)
+# define BOOST_PP_REPEAT_1_209(m, d) BOOST_PP_REPEAT_1_208(m, d) m(2, 208, d)
+# define BOOST_PP_REPEAT_1_210(m, d) BOOST_PP_REPEAT_1_209(m, d) m(2, 209, d)
+# define BOOST_PP_REPEAT_1_211(m, d) BOOST_PP_REPEAT_1_210(m, d) m(2, 210, d)
+# define BOOST_PP_REPEAT_1_212(m, d) BOOST_PP_REPEAT_1_211(m, d) m(2, 211, d)
+# define BOOST_PP_REPEAT_1_213(m, d) BOOST_PP_REPEAT_1_212(m, d) m(2, 212, d)
+# define BOOST_PP_REPEAT_1_214(m, d) BOOST_PP_REPEAT_1_213(m, d) m(2, 213, d)
+# define BOOST_PP_REPEAT_1_215(m, d) BOOST_PP_REPEAT_1_214(m, d) m(2, 214, d)
+# define BOOST_PP_REPEAT_1_216(m, d) BOOST_PP_REPEAT_1_215(m, d) m(2, 215, d)
+# define BOOST_PP_REPEAT_1_217(m, d) BOOST_PP_REPEAT_1_216(m, d) m(2, 216, d)
+# define BOOST_PP_REPEAT_1_218(m, d) BOOST_PP_REPEAT_1_217(m, d) m(2, 217, d)
+# define BOOST_PP_REPEAT_1_219(m, d) BOOST_PP_REPEAT_1_218(m, d) m(2, 218, d)
+# define BOOST_PP_REPEAT_1_220(m, d) BOOST_PP_REPEAT_1_219(m, d) m(2, 219, d)
+# define BOOST_PP_REPEAT_1_221(m, d) BOOST_PP_REPEAT_1_220(m, d) m(2, 220, d)
+# define BOOST_PP_REPEAT_1_222(m, d) BOOST_PP_REPEAT_1_221(m, d) m(2, 221, d)
+# define BOOST_PP_REPEAT_1_223(m, d) BOOST_PP_REPEAT_1_222(m, d) m(2, 222, d)
+# define BOOST_PP_REPEAT_1_224(m, d) BOOST_PP_REPEAT_1_223(m, d) m(2, 223, d)
+# define BOOST_PP_REPEAT_1_225(m, d) BOOST_PP_REPEAT_1_224(m, d) m(2, 224, d)
+# define BOOST_PP_REPEAT_1_226(m, d) BOOST_PP_REPEAT_1_225(m, d) m(2, 225, d)
+# define BOOST_PP_REPEAT_1_227(m, d) BOOST_PP_REPEAT_1_226(m, d) m(2, 226, d)
+# define BOOST_PP_REPEAT_1_228(m, d) BOOST_PP_REPEAT_1_227(m, d) m(2, 227, d)
+# define BOOST_PP_REPEAT_1_229(m, d) BOOST_PP_REPEAT_1_228(m, d) m(2, 228, d)
+# define BOOST_PP_REPEAT_1_230(m, d) BOOST_PP_REPEAT_1_229(m, d) m(2, 229, d)
+# define BOOST_PP_REPEAT_1_231(m, d) BOOST_PP_REPEAT_1_230(m, d) m(2, 230, d)
+# define BOOST_PP_REPEAT_1_232(m, d) BOOST_PP_REPEAT_1_231(m, d) m(2, 231, d)
+# define BOOST_PP_REPEAT_1_233(m, d) BOOST_PP_REPEAT_1_232(m, d) m(2, 232, d)
+# define BOOST_PP_REPEAT_1_234(m, d) BOOST_PP_REPEAT_1_233(m, d) m(2, 233, d)
+# define BOOST_PP_REPEAT_1_235(m, d) BOOST_PP_REPEAT_1_234(m, d) m(2, 234, d)
+# define BOOST_PP_REPEAT_1_236(m, d) BOOST_PP_REPEAT_1_235(m, d) m(2, 235, d)
+# define BOOST_PP_REPEAT_1_237(m, d) BOOST_PP_REPEAT_1_236(m, d) m(2, 236, d)
+# define BOOST_PP_REPEAT_1_238(m, d) BOOST_PP_REPEAT_1_237(m, d) m(2, 237, d)
+# define BOOST_PP_REPEAT_1_239(m, d) BOOST_PP_REPEAT_1_238(m, d) m(2, 238, d)
+# define BOOST_PP_REPEAT_1_240(m, d) BOOST_PP_REPEAT_1_239(m, d) m(2, 239, d)
+# define BOOST_PP_REPEAT_1_241(m, d) BOOST_PP_REPEAT_1_240(m, d) m(2, 240, d)
+# define BOOST_PP_REPEAT_1_242(m, d) BOOST_PP_REPEAT_1_241(m, d) m(2, 241, d)
+# define BOOST_PP_REPEAT_1_243(m, d) BOOST_PP_REPEAT_1_242(m, d) m(2, 242, d)
+# define BOOST_PP_REPEAT_1_244(m, d) BOOST_PP_REPEAT_1_243(m, d) m(2, 243, d)
+# define BOOST_PP_REPEAT_1_245(m, d) BOOST_PP_REPEAT_1_244(m, d) m(2, 244, d)
+# define BOOST_PP_REPEAT_1_246(m, d) BOOST_PP_REPEAT_1_245(m, d) m(2, 245, d)
+# define BOOST_PP_REPEAT_1_247(m, d) BOOST_PP_REPEAT_1_246(m, d) m(2, 246, d)
+# define BOOST_PP_REPEAT_1_248(m, d) BOOST_PP_REPEAT_1_247(m, d) m(2, 247, d)
+# define BOOST_PP_REPEAT_1_249(m, d) BOOST_PP_REPEAT_1_248(m, d) m(2, 248, d)
+# define BOOST_PP_REPEAT_1_250(m, d) BOOST_PP_REPEAT_1_249(m, d) m(2, 249, d)
+# define BOOST_PP_REPEAT_1_251(m, d) BOOST_PP_REPEAT_1_250(m, d) m(2, 250, d)
+# define BOOST_PP_REPEAT_1_252(m, d) BOOST_PP_REPEAT_1_251(m, d) m(2, 251, d)
+# define BOOST_PP_REPEAT_1_253(m, d) BOOST_PP_REPEAT_1_252(m, d) m(2, 252, d)
+# define BOOST_PP_REPEAT_1_254(m, d) BOOST_PP_REPEAT_1_253(m, d) m(2, 253, d)
+# define BOOST_PP_REPEAT_1_255(m, d) BOOST_PP_REPEAT_1_254(m, d) m(2, 254, d)
+# define BOOST_PP_REPEAT_1_256(m, d) BOOST_PP_REPEAT_1_255(m, d) m(2, 255, d)
+#
+# define BOOST_PP_REPEAT_2_0(m, d)
+# define BOOST_PP_REPEAT_2_1(m, d) m(3, 0, d)
+# define BOOST_PP_REPEAT_2_2(m, d) BOOST_PP_REPEAT_2_1(m, d) m(3, 1, d)
+# define BOOST_PP_REPEAT_2_3(m, d) BOOST_PP_REPEAT_2_2(m, d) m(3, 2, d)
+# define BOOST_PP_REPEAT_2_4(m, d) BOOST_PP_REPEAT_2_3(m, d) m(3, 3, d)
+# define BOOST_PP_REPEAT_2_5(m, d) BOOST_PP_REPEAT_2_4(m, d) m(3, 4, d)
+# define BOOST_PP_REPEAT_2_6(m, d) BOOST_PP_REPEAT_2_5(m, d) m(3, 5, d)
+# define BOOST_PP_REPEAT_2_7(m, d) BOOST_PP_REPEAT_2_6(m, d) m(3, 6, d)
+# define BOOST_PP_REPEAT_2_8(m, d) BOOST_PP_REPEAT_2_7(m, d) m(3, 7, d)
+# define BOOST_PP_REPEAT_2_9(m, d) BOOST_PP_REPEAT_2_8(m, d) m(3, 8, d)
+# define BOOST_PP_REPEAT_2_10(m, d) BOOST_PP_REPEAT_2_9(m, d) m(3, 9, d)
+# define BOOST_PP_REPEAT_2_11(m, d) BOOST_PP_REPEAT_2_10(m, d) m(3, 10, d)
+# define BOOST_PP_REPEAT_2_12(m, d) BOOST_PP_REPEAT_2_11(m, d) m(3, 11, d)
+# define BOOST_PP_REPEAT_2_13(m, d) BOOST_PP_REPEAT_2_12(m, d) m(3, 12, d)
+# define BOOST_PP_REPEAT_2_14(m, d) BOOST_PP_REPEAT_2_13(m, d) m(3, 13, d)
+# define BOOST_PP_REPEAT_2_15(m, d) BOOST_PP_REPEAT_2_14(m, d) m(3, 14, d)
+# define BOOST_PP_REPEAT_2_16(m, d) BOOST_PP_REPEAT_2_15(m, d) m(3, 15, d)
+# define BOOST_PP_REPEAT_2_17(m, d) BOOST_PP_REPEAT_2_16(m, d) m(3, 16, d)
+# define BOOST_PP_REPEAT_2_18(m, d) BOOST_PP_REPEAT_2_17(m, d) m(3, 17, d)
+# define BOOST_PP_REPEAT_2_19(m, d) BOOST_PP_REPEAT_2_18(m, d) m(3, 18, d)
+# define BOOST_PP_REPEAT_2_20(m, d) BOOST_PP_REPEAT_2_19(m, d) m(3, 19, d)
+# define BOOST_PP_REPEAT_2_21(m, d) BOOST_PP_REPEAT_2_20(m, d) m(3, 20, d)
+# define BOOST_PP_REPEAT_2_22(m, d) BOOST_PP_REPEAT_2_21(m, d) m(3, 21, d)
+# define BOOST_PP_REPEAT_2_23(m, d) BOOST_PP_REPEAT_2_22(m, d) m(3, 22, d)
+# define BOOST_PP_REPEAT_2_24(m, d) BOOST_PP_REPEAT_2_23(m, d) m(3, 23, d)
+# define BOOST_PP_REPEAT_2_25(m, d) BOOST_PP_REPEAT_2_24(m, d) m(3, 24, d)
+# define BOOST_PP_REPEAT_2_26(m, d) BOOST_PP_REPEAT_2_25(m, d) m(3, 25, d)
+# define BOOST_PP_REPEAT_2_27(m, d) BOOST_PP_REPEAT_2_26(m, d) m(3, 26, d)
+# define BOOST_PP_REPEAT_2_28(m, d) BOOST_PP_REPEAT_2_27(m, d) m(3, 27, d)
+# define BOOST_PP_REPEAT_2_29(m, d) BOOST_PP_REPEAT_2_28(m, d) m(3, 28, d)
+# define BOOST_PP_REPEAT_2_30(m, d) BOOST_PP_REPEAT_2_29(m, d) m(3, 29, d)
+# define BOOST_PP_REPEAT_2_31(m, d) BOOST_PP_REPEAT_2_30(m, d) m(3, 30, d)
+# define BOOST_PP_REPEAT_2_32(m, d) BOOST_PP_REPEAT_2_31(m, d) m(3, 31, d)
+# define BOOST_PP_REPEAT_2_33(m, d) BOOST_PP_REPEAT_2_32(m, d) m(3, 32, d)
+# define BOOST_PP_REPEAT_2_34(m, d) BOOST_PP_REPEAT_2_33(m, d) m(3, 33, d)
+# define BOOST_PP_REPEAT_2_35(m, d) BOOST_PP_REPEAT_2_34(m, d) m(3, 34, d)
+# define BOOST_PP_REPEAT_2_36(m, d) BOOST_PP_REPEAT_2_35(m, d) m(3, 35, d)
+# define BOOST_PP_REPEAT_2_37(m, d) BOOST_PP_REPEAT_2_36(m, d) m(3, 36, d)
+# define BOOST_PP_REPEAT_2_38(m, d) BOOST_PP_REPEAT_2_37(m, d) m(3, 37, d)
+# define BOOST_PP_REPEAT_2_39(m, d) BOOST_PP_REPEAT_2_38(m, d) m(3, 38, d)
+# define BOOST_PP_REPEAT_2_40(m, d) BOOST_PP_REPEAT_2_39(m, d) m(3, 39, d)
+# define BOOST_PP_REPEAT_2_41(m, d) BOOST_PP_REPEAT_2_40(m, d) m(3, 40, d)
+# define BOOST_PP_REPEAT_2_42(m, d) BOOST_PP_REPEAT_2_41(m, d) m(3, 41, d)
+# define BOOST_PP_REPEAT_2_43(m, d) BOOST_PP_REPEAT_2_42(m, d) m(3, 42, d)
+# define BOOST_PP_REPEAT_2_44(m, d) BOOST_PP_REPEAT_2_43(m, d) m(3, 43, d)
+# define BOOST_PP_REPEAT_2_45(m, d) BOOST_PP_REPEAT_2_44(m, d) m(3, 44, d)
+# define BOOST_PP_REPEAT_2_46(m, d) BOOST_PP_REPEAT_2_45(m, d) m(3, 45, d)
+# define BOOST_PP_REPEAT_2_47(m, d) BOOST_PP_REPEAT_2_46(m, d) m(3, 46, d)
+# define BOOST_PP_REPEAT_2_48(m, d) BOOST_PP_REPEAT_2_47(m, d) m(3, 47, d)
+# define BOOST_PP_REPEAT_2_49(m, d) BOOST_PP_REPEAT_2_48(m, d) m(3, 48, d)
+# define BOOST_PP_REPEAT_2_50(m, d) BOOST_PP_REPEAT_2_49(m, d) m(3, 49, d)
+# define BOOST_PP_REPEAT_2_51(m, d) BOOST_PP_REPEAT_2_50(m, d) m(3, 50, d)
+# define BOOST_PP_REPEAT_2_52(m, d) BOOST_PP_REPEAT_2_51(m, d) m(3, 51, d)
+# define BOOST_PP_REPEAT_2_53(m, d) BOOST_PP_REPEAT_2_52(m, d) m(3, 52, d)
+# define BOOST_PP_REPEAT_2_54(m, d) BOOST_PP_REPEAT_2_53(m, d) m(3, 53, d)
+# define BOOST_PP_REPEAT_2_55(m, d) BOOST_PP_REPEAT_2_54(m, d) m(3, 54, d)
+# define BOOST_PP_REPEAT_2_56(m, d) BOOST_PP_REPEAT_2_55(m, d) m(3, 55, d)
+# define BOOST_PP_REPEAT_2_57(m, d) BOOST_PP_REPEAT_2_56(m, d) m(3, 56, d)
+# define BOOST_PP_REPEAT_2_58(m, d) BOOST_PP_REPEAT_2_57(m, d) m(3, 57, d)
+# define BOOST_PP_REPEAT_2_59(m, d) BOOST_PP_REPEAT_2_58(m, d) m(3, 58, d)
+# define BOOST_PP_REPEAT_2_60(m, d) BOOST_PP_REPEAT_2_59(m, d) m(3, 59, d)
+# define BOOST_PP_REPEAT_2_61(m, d) BOOST_PP_REPEAT_2_60(m, d) m(3, 60, d)
+# define BOOST_PP_REPEAT_2_62(m, d) BOOST_PP_REPEAT_2_61(m, d) m(3, 61, d)
+# define BOOST_PP_REPEAT_2_63(m, d) BOOST_PP_REPEAT_2_62(m, d) m(3, 62, d)
+# define BOOST_PP_REPEAT_2_64(m, d) BOOST_PP_REPEAT_2_63(m, d) m(3, 63, d)
+# define BOOST_PP_REPEAT_2_65(m, d) BOOST_PP_REPEAT_2_64(m, d) m(3, 64, d)
+# define BOOST_PP_REPEAT_2_66(m, d) BOOST_PP_REPEAT_2_65(m, d) m(3, 65, d)
+# define BOOST_PP_REPEAT_2_67(m, d) BOOST_PP_REPEAT_2_66(m, d) m(3, 66, d)
+# define BOOST_PP_REPEAT_2_68(m, d) BOOST_PP_REPEAT_2_67(m, d) m(3, 67, d)
+# define BOOST_PP_REPEAT_2_69(m, d) BOOST_PP_REPEAT_2_68(m, d) m(3, 68, d)
+# define BOOST_PP_REPEAT_2_70(m, d) BOOST_PP_REPEAT_2_69(m, d) m(3, 69, d)
+# define BOOST_PP_REPEAT_2_71(m, d) BOOST_PP_REPEAT_2_70(m, d) m(3, 70, d)
+# define BOOST_PP_REPEAT_2_72(m, d) BOOST_PP_REPEAT_2_71(m, d) m(3, 71, d)
+# define BOOST_PP_REPEAT_2_73(m, d) BOOST_PP_REPEAT_2_72(m, d) m(3, 72, d)
+# define BOOST_PP_REPEAT_2_74(m, d) BOOST_PP_REPEAT_2_73(m, d) m(3, 73, d)
+# define BOOST_PP_REPEAT_2_75(m, d) BOOST_PP_REPEAT_2_74(m, d) m(3, 74, d)
+# define BOOST_PP_REPEAT_2_76(m, d) BOOST_PP_REPEAT_2_75(m, d) m(3, 75, d)
+# define BOOST_PP_REPEAT_2_77(m, d) BOOST_PP_REPEAT_2_76(m, d) m(3, 76, d)
+# define BOOST_PP_REPEAT_2_78(m, d) BOOST_PP_REPEAT_2_77(m, d) m(3, 77, d)
+# define BOOST_PP_REPEAT_2_79(m, d) BOOST_PP_REPEAT_2_78(m, d) m(3, 78, d)
+# define BOOST_PP_REPEAT_2_80(m, d) BOOST_PP_REPEAT_2_79(m, d) m(3, 79, d)
+# define BOOST_PP_REPEAT_2_81(m, d) BOOST_PP_REPEAT_2_80(m, d) m(3, 80, d)
+# define BOOST_PP_REPEAT_2_82(m, d) BOOST_PP_REPEAT_2_81(m, d) m(3, 81, d)
+# define BOOST_PP_REPEAT_2_83(m, d) BOOST_PP_REPEAT_2_82(m, d) m(3, 82, d)
+# define BOOST_PP_REPEAT_2_84(m, d) BOOST_PP_REPEAT_2_83(m, d) m(3, 83, d)
+# define BOOST_PP_REPEAT_2_85(m, d) BOOST_PP_REPEAT_2_84(m, d) m(3, 84, d)
+# define BOOST_PP_REPEAT_2_86(m, d) BOOST_PP_REPEAT_2_85(m, d) m(3, 85, d)
+# define BOOST_PP_REPEAT_2_87(m, d) BOOST_PP_REPEAT_2_86(m, d) m(3, 86, d)
+# define BOOST_PP_REPEAT_2_88(m, d) BOOST_PP_REPEAT_2_87(m, d) m(3, 87, d)
+# define BOOST_PP_REPEAT_2_89(m, d) BOOST_PP_REPEAT_2_88(m, d) m(3, 88, d)
+# define BOOST_PP_REPEAT_2_90(m, d) BOOST_PP_REPEAT_2_89(m, d) m(3, 89, d)
+# define BOOST_PP_REPEAT_2_91(m, d) BOOST_PP_REPEAT_2_90(m, d) m(3, 90, d)
+# define BOOST_PP_REPEAT_2_92(m, d) BOOST_PP_REPEAT_2_91(m, d) m(3, 91, d)
+# define BOOST_PP_REPEAT_2_93(m, d) BOOST_PP_REPEAT_2_92(m, d) m(3, 92, d)
+# define BOOST_PP_REPEAT_2_94(m, d) BOOST_PP_REPEAT_2_93(m, d) m(3, 93, d)
+# define BOOST_PP_REPEAT_2_95(m, d) BOOST_PP_REPEAT_2_94(m, d) m(3, 94, d)
+# define BOOST_PP_REPEAT_2_96(m, d) BOOST_PP_REPEAT_2_95(m, d) m(3, 95, d)
+# define BOOST_PP_REPEAT_2_97(m, d) BOOST_PP_REPEAT_2_96(m, d) m(3, 96, d)
+# define BOOST_PP_REPEAT_2_98(m, d) BOOST_PP_REPEAT_2_97(m, d) m(3, 97, d)
+# define BOOST_PP_REPEAT_2_99(m, d) BOOST_PP_REPEAT_2_98(m, d) m(3, 98, d)
+# define BOOST_PP_REPEAT_2_100(m, d) BOOST_PP_REPEAT_2_99(m, d) m(3, 99, d)
+# define BOOST_PP_REPEAT_2_101(m, d) BOOST_PP_REPEAT_2_100(m, d) m(3, 100, d)
+# define BOOST_PP_REPEAT_2_102(m, d) BOOST_PP_REPEAT_2_101(m, d) m(3, 101, d)
+# define BOOST_PP_REPEAT_2_103(m, d) BOOST_PP_REPEAT_2_102(m, d) m(3, 102, d)
+# define BOOST_PP_REPEAT_2_104(m, d) BOOST_PP_REPEAT_2_103(m, d) m(3, 103, d)
+# define BOOST_PP_REPEAT_2_105(m, d) BOOST_PP_REPEAT_2_104(m, d) m(3, 104, d)
+# define BOOST_PP_REPEAT_2_106(m, d) BOOST_PP_REPEAT_2_105(m, d) m(3, 105, d)
+# define BOOST_PP_REPEAT_2_107(m, d) BOOST_PP_REPEAT_2_106(m, d) m(3, 106, d)
+# define BOOST_PP_REPEAT_2_108(m, d) BOOST_PP_REPEAT_2_107(m, d) m(3, 107, d)
+# define BOOST_PP_REPEAT_2_109(m, d) BOOST_PP_REPEAT_2_108(m, d) m(3, 108, d)
+# define BOOST_PP_REPEAT_2_110(m, d) BOOST_PP_REPEAT_2_109(m, d) m(3, 109, d)
+# define BOOST_PP_REPEAT_2_111(m, d) BOOST_PP_REPEAT_2_110(m, d) m(3, 110, d)
+# define BOOST_PP_REPEAT_2_112(m, d) BOOST_PP_REPEAT_2_111(m, d) m(3, 111, d)
+# define BOOST_PP_REPEAT_2_113(m, d) BOOST_PP_REPEAT_2_112(m, d) m(3, 112, d)
+# define BOOST_PP_REPEAT_2_114(m, d) BOOST_PP_REPEAT_2_113(m, d) m(3, 113, d)
+# define BOOST_PP_REPEAT_2_115(m, d) BOOST_PP_REPEAT_2_114(m, d) m(3, 114, d)
+# define BOOST_PP_REPEAT_2_116(m, d) BOOST_PP_REPEAT_2_115(m, d) m(3, 115, d)
+# define BOOST_PP_REPEAT_2_117(m, d) BOOST_PP_REPEAT_2_116(m, d) m(3, 116, d)
+# define BOOST_PP_REPEAT_2_118(m, d) BOOST_PP_REPEAT_2_117(m, d) m(3, 117, d)
+# define BOOST_PP_REPEAT_2_119(m, d) BOOST_PP_REPEAT_2_118(m, d) m(3, 118, d)
+# define BOOST_PP_REPEAT_2_120(m, d) BOOST_PP_REPEAT_2_119(m, d) m(3, 119, d)
+# define BOOST_PP_REPEAT_2_121(m, d) BOOST_PP_REPEAT_2_120(m, d) m(3, 120, d)
+# define BOOST_PP_REPEAT_2_122(m, d) BOOST_PP_REPEAT_2_121(m, d) m(3, 121, d)
+# define BOOST_PP_REPEAT_2_123(m, d) BOOST_PP_REPEAT_2_122(m, d) m(3, 122, d)
+# define BOOST_PP_REPEAT_2_124(m, d) BOOST_PP_REPEAT_2_123(m, d) m(3, 123, d)
+# define BOOST_PP_REPEAT_2_125(m, d) BOOST_PP_REPEAT_2_124(m, d) m(3, 124, d)
+# define BOOST_PP_REPEAT_2_126(m, d) BOOST_PP_REPEAT_2_125(m, d) m(3, 125, d)
+# define BOOST_PP_REPEAT_2_127(m, d) BOOST_PP_REPEAT_2_126(m, d) m(3, 126, d)
+# define BOOST_PP_REPEAT_2_128(m, d) BOOST_PP_REPEAT_2_127(m, d) m(3, 127, d)
+# define BOOST_PP_REPEAT_2_129(m, d) BOOST_PP_REPEAT_2_128(m, d) m(3, 128, d)
+# define BOOST_PP_REPEAT_2_130(m, d) BOOST_PP_REPEAT_2_129(m, d) m(3, 129, d)
+# define BOOST_PP_REPEAT_2_131(m, d) BOOST_PP_REPEAT_2_130(m, d) m(3, 130, d)
+# define BOOST_PP_REPEAT_2_132(m, d) BOOST_PP_REPEAT_2_131(m, d) m(3, 131, d)
+# define BOOST_PP_REPEAT_2_133(m, d) BOOST_PP_REPEAT_2_132(m, d) m(3, 132, d)
+# define BOOST_PP_REPEAT_2_134(m, d) BOOST_PP_REPEAT_2_133(m, d) m(3, 133, d)
+# define BOOST_PP_REPEAT_2_135(m, d) BOOST_PP_REPEAT_2_134(m, d) m(3, 134, d)
+# define BOOST_PP_REPEAT_2_136(m, d) BOOST_PP_REPEAT_2_135(m, d) m(3, 135, d)
+# define BOOST_PP_REPEAT_2_137(m, d) BOOST_PP_REPEAT_2_136(m, d) m(3, 136, d)
+# define BOOST_PP_REPEAT_2_138(m, d) BOOST_PP_REPEAT_2_137(m, d) m(3, 137, d)
+# define BOOST_PP_REPEAT_2_139(m, d) BOOST_PP_REPEAT_2_138(m, d) m(3, 138, d)
+# define BOOST_PP_REPEAT_2_140(m, d) BOOST_PP_REPEAT_2_139(m, d) m(3, 139, d)
+# define BOOST_PP_REPEAT_2_141(m, d) BOOST_PP_REPEAT_2_140(m, d) m(3, 140, d)
+# define BOOST_PP_REPEAT_2_142(m, d) BOOST_PP_REPEAT_2_141(m, d) m(3, 141, d)
+# define BOOST_PP_REPEAT_2_143(m, d) BOOST_PP_REPEAT_2_142(m, d) m(3, 142, d)
+# define BOOST_PP_REPEAT_2_144(m, d) BOOST_PP_REPEAT_2_143(m, d) m(3, 143, d)
+# define BOOST_PP_REPEAT_2_145(m, d) BOOST_PP_REPEAT_2_144(m, d) m(3, 144, d)
+# define BOOST_PP_REPEAT_2_146(m, d) BOOST_PP_REPEAT_2_145(m, d) m(3, 145, d)
+# define BOOST_PP_REPEAT_2_147(m, d) BOOST_PP_REPEAT_2_146(m, d) m(3, 146, d)
+# define BOOST_PP_REPEAT_2_148(m, d) BOOST_PP_REPEAT_2_147(m, d) m(3, 147, d)
+# define BOOST_PP_REPEAT_2_149(m, d) BOOST_PP_REPEAT_2_148(m, d) m(3, 148, d)
+# define BOOST_PP_REPEAT_2_150(m, d) BOOST_PP_REPEAT_2_149(m, d) m(3, 149, d)
+# define BOOST_PP_REPEAT_2_151(m, d) BOOST_PP_REPEAT_2_150(m, d) m(3, 150, d)
+# define BOOST_PP_REPEAT_2_152(m, d) BOOST_PP_REPEAT_2_151(m, d) m(3, 151, d)
+# define BOOST_PP_REPEAT_2_153(m, d) BOOST_PP_REPEAT_2_152(m, d) m(3, 152, d)
+# define BOOST_PP_REPEAT_2_154(m, d) BOOST_PP_REPEAT_2_153(m, d) m(3, 153, d)
+# define BOOST_PP_REPEAT_2_155(m, d) BOOST_PP_REPEAT_2_154(m, d) m(3, 154, d)
+# define BOOST_PP_REPEAT_2_156(m, d) BOOST_PP_REPEAT_2_155(m, d) m(3, 155, d)
+# define BOOST_PP_REPEAT_2_157(m, d) BOOST_PP_REPEAT_2_156(m, d) m(3, 156, d)
+# define BOOST_PP_REPEAT_2_158(m, d) BOOST_PP_REPEAT_2_157(m, d) m(3, 157, d)
+# define BOOST_PP_REPEAT_2_159(m, d) BOOST_PP_REPEAT_2_158(m, d) m(3, 158, d)
+# define BOOST_PP_REPEAT_2_160(m, d) BOOST_PP_REPEAT_2_159(m, d) m(3, 159, d)
+# define BOOST_PP_REPEAT_2_161(m, d) BOOST_PP_REPEAT_2_160(m, d) m(3, 160, d)
+# define BOOST_PP_REPEAT_2_162(m, d) BOOST_PP_REPEAT_2_161(m, d) m(3, 161, d)
+# define BOOST_PP_REPEAT_2_163(m, d) BOOST_PP_REPEAT_2_162(m, d) m(3, 162, d)
+# define BOOST_PP_REPEAT_2_164(m, d) BOOST_PP_REPEAT_2_163(m, d) m(3, 163, d)
+# define BOOST_PP_REPEAT_2_165(m, d) BOOST_PP_REPEAT_2_164(m, d) m(3, 164, d)
+# define BOOST_PP_REPEAT_2_166(m, d) BOOST_PP_REPEAT_2_165(m, d) m(3, 165, d)
+# define BOOST_PP_REPEAT_2_167(m, d) BOOST_PP_REPEAT_2_166(m, d) m(3, 166, d)
+# define BOOST_PP_REPEAT_2_168(m, d) BOOST_PP_REPEAT_2_167(m, d) m(3, 167, d)
+# define BOOST_PP_REPEAT_2_169(m, d) BOOST_PP_REPEAT_2_168(m, d) m(3, 168, d)
+# define BOOST_PP_REPEAT_2_170(m, d) BOOST_PP_REPEAT_2_169(m, d) m(3, 169, d)
+# define BOOST_PP_REPEAT_2_171(m, d) BOOST_PP_REPEAT_2_170(m, d) m(3, 170, d)
+# define BOOST_PP_REPEAT_2_172(m, d) BOOST_PP_REPEAT_2_171(m, d) m(3, 171, d)
+# define BOOST_PP_REPEAT_2_173(m, d) BOOST_PP_REPEAT_2_172(m, d) m(3, 172, d)
+# define BOOST_PP_REPEAT_2_174(m, d) BOOST_PP_REPEAT_2_173(m, d) m(3, 173, d)
+# define BOOST_PP_REPEAT_2_175(m, d) BOOST_PP_REPEAT_2_174(m, d) m(3, 174, d)
+# define BOOST_PP_REPEAT_2_176(m, d) BOOST_PP_REPEAT_2_175(m, d) m(3, 175, d)
+# define BOOST_PP_REPEAT_2_177(m, d) BOOST_PP_REPEAT_2_176(m, d) m(3, 176, d)
+# define BOOST_PP_REPEAT_2_178(m, d) BOOST_PP_REPEAT_2_177(m, d) m(3, 177, d)
+# define BOOST_PP_REPEAT_2_179(m, d) BOOST_PP_REPEAT_2_178(m, d) m(3, 178, d)
+# define BOOST_PP_REPEAT_2_180(m, d) BOOST_PP_REPEAT_2_179(m, d) m(3, 179, d)
+# define BOOST_PP_REPEAT_2_181(m, d) BOOST_PP_REPEAT_2_180(m, d) m(3, 180, d)
+# define BOOST_PP_REPEAT_2_182(m, d) BOOST_PP_REPEAT_2_181(m, d) m(3, 181, d)
+# define BOOST_PP_REPEAT_2_183(m, d) BOOST_PP_REPEAT_2_182(m, d) m(3, 182, d)
+# define BOOST_PP_REPEAT_2_184(m, d) BOOST_PP_REPEAT_2_183(m, d) m(3, 183, d)
+# define BOOST_PP_REPEAT_2_185(m, d) BOOST_PP_REPEAT_2_184(m, d) m(3, 184, d)
+# define BOOST_PP_REPEAT_2_186(m, d) BOOST_PP_REPEAT_2_185(m, d) m(3, 185, d)
+# define BOOST_PP_REPEAT_2_187(m, d) BOOST_PP_REPEAT_2_186(m, d) m(3, 186, d)
+# define BOOST_PP_REPEAT_2_188(m, d) BOOST_PP_REPEAT_2_187(m, d) m(3, 187, d)
+# define BOOST_PP_REPEAT_2_189(m, d) BOOST_PP_REPEAT_2_188(m, d) m(3, 188, d)
+# define BOOST_PP_REPEAT_2_190(m, d) BOOST_PP_REPEAT_2_189(m, d) m(3, 189, d)
+# define BOOST_PP_REPEAT_2_191(m, d) BOOST_PP_REPEAT_2_190(m, d) m(3, 190, d)
+# define BOOST_PP_REPEAT_2_192(m, d) BOOST_PP_REPEAT_2_191(m, d) m(3, 191, d)
+# define BOOST_PP_REPEAT_2_193(m, d) BOOST_PP_REPEAT_2_192(m, d) m(3, 192, d)
+# define BOOST_PP_REPEAT_2_194(m, d) BOOST_PP_REPEAT_2_193(m, d) m(3, 193, d)
+# define BOOST_PP_REPEAT_2_195(m, d) BOOST_PP_REPEAT_2_194(m, d) m(3, 194, d)
+# define BOOST_PP_REPEAT_2_196(m, d) BOOST_PP_REPEAT_2_195(m, d) m(3, 195, d)
+# define BOOST_PP_REPEAT_2_197(m, d) BOOST_PP_REPEAT_2_196(m, d) m(3, 196, d)
+# define BOOST_PP_REPEAT_2_198(m, d) BOOST_PP_REPEAT_2_197(m, d) m(3, 197, d)
+# define BOOST_PP_REPEAT_2_199(m, d) BOOST_PP_REPEAT_2_198(m, d) m(3, 198, d)
+# define BOOST_PP_REPEAT_2_200(m, d) BOOST_PP_REPEAT_2_199(m, d) m(3, 199, d)
+# define BOOST_PP_REPEAT_2_201(m, d) BOOST_PP_REPEAT_2_200(m, d) m(3, 200, d)
+# define BOOST_PP_REPEAT_2_202(m, d) BOOST_PP_REPEAT_2_201(m, d) m(3, 201, d)
+# define BOOST_PP_REPEAT_2_203(m, d) BOOST_PP_REPEAT_2_202(m, d) m(3, 202, d)
+# define BOOST_PP_REPEAT_2_204(m, d) BOOST_PP_REPEAT_2_203(m, d) m(3, 203, d)
+# define BOOST_PP_REPEAT_2_205(m, d) BOOST_PP_REPEAT_2_204(m, d) m(3, 204, d)
+# define BOOST_PP_REPEAT_2_206(m, d) BOOST_PP_REPEAT_2_205(m, d) m(3, 205, d)
+# define BOOST_PP_REPEAT_2_207(m, d) BOOST_PP_REPEAT_2_206(m, d) m(3, 206, d)
+# define BOOST_PP_REPEAT_2_208(m, d) BOOST_PP_REPEAT_2_207(m, d) m(3, 207, d)
+# define BOOST_PP_REPEAT_2_209(m, d) BOOST_PP_REPEAT_2_208(m, d) m(3, 208, d)
+# define BOOST_PP_REPEAT_2_210(m, d) BOOST_PP_REPEAT_2_209(m, d) m(3, 209, d)
+# define BOOST_PP_REPEAT_2_211(m, d) BOOST_PP_REPEAT_2_210(m, d) m(3, 210, d)
+# define BOOST_PP_REPEAT_2_212(m, d) BOOST_PP_REPEAT_2_211(m, d) m(3, 211, d)
+# define BOOST_PP_REPEAT_2_213(m, d) BOOST_PP_REPEAT_2_212(m, d) m(3, 212, d)
+# define BOOST_PP_REPEAT_2_214(m, d) BOOST_PP_REPEAT_2_213(m, d) m(3, 213, d)
+# define BOOST_PP_REPEAT_2_215(m, d) BOOST_PP_REPEAT_2_214(m, d) m(3, 214, d)
+# define BOOST_PP_REPEAT_2_216(m, d) BOOST_PP_REPEAT_2_215(m, d) m(3, 215, d)
+# define BOOST_PP_REPEAT_2_217(m, d) BOOST_PP_REPEAT_2_216(m, d) m(3, 216, d)
+# define BOOST_PP_REPEAT_2_218(m, d) BOOST_PP_REPEAT_2_217(m, d) m(3, 217, d)
+# define BOOST_PP_REPEAT_2_219(m, d) BOOST_PP_REPEAT_2_218(m, d) m(3, 218, d)
+# define BOOST_PP_REPEAT_2_220(m, d) BOOST_PP_REPEAT_2_219(m, d) m(3, 219, d)
+# define BOOST_PP_REPEAT_2_221(m, d) BOOST_PP_REPEAT_2_220(m, d) m(3, 220, d)
+# define BOOST_PP_REPEAT_2_222(m, d) BOOST_PP_REPEAT_2_221(m, d) m(3, 221, d)
+# define BOOST_PP_REPEAT_2_223(m, d) BOOST_PP_REPEAT_2_222(m, d) m(3, 222, d)
+# define BOOST_PP_REPEAT_2_224(m, d) BOOST_PP_REPEAT_2_223(m, d) m(3, 223, d)
+# define BOOST_PP_REPEAT_2_225(m, d) BOOST_PP_REPEAT_2_224(m, d) m(3, 224, d)
+# define BOOST_PP_REPEAT_2_226(m, d) BOOST_PP_REPEAT_2_225(m, d) m(3, 225, d)
+# define BOOST_PP_REPEAT_2_227(m, d) BOOST_PP_REPEAT_2_226(m, d) m(3, 226, d)
+# define BOOST_PP_REPEAT_2_228(m, d) BOOST_PP_REPEAT_2_227(m, d) m(3, 227, d)
+# define BOOST_PP_REPEAT_2_229(m, d) BOOST_PP_REPEAT_2_228(m, d) m(3, 228, d)
+# define BOOST_PP_REPEAT_2_230(m, d) BOOST_PP_REPEAT_2_229(m, d) m(3, 229, d)
+# define BOOST_PP_REPEAT_2_231(m, d) BOOST_PP_REPEAT_2_230(m, d) m(3, 230, d)
+# define BOOST_PP_REPEAT_2_232(m, d) BOOST_PP_REPEAT_2_231(m, d) m(3, 231, d)
+# define BOOST_PP_REPEAT_2_233(m, d) BOOST_PP_REPEAT_2_232(m, d) m(3, 232, d)
+# define BOOST_PP_REPEAT_2_234(m, d) BOOST_PP_REPEAT_2_233(m, d) m(3, 233, d)
+# define BOOST_PP_REPEAT_2_235(m, d) BOOST_PP_REPEAT_2_234(m, d) m(3, 234, d)
+# define BOOST_PP_REPEAT_2_236(m, d) BOOST_PP_REPEAT_2_235(m, d) m(3, 235, d)
+# define BOOST_PP_REPEAT_2_237(m, d) BOOST_PP_REPEAT_2_236(m, d) m(3, 236, d)
+# define BOOST_PP_REPEAT_2_238(m, d) BOOST_PP_REPEAT_2_237(m, d) m(3, 237, d)
+# define BOOST_PP_REPEAT_2_239(m, d) BOOST_PP_REPEAT_2_238(m, d) m(3, 238, d)
+# define BOOST_PP_REPEAT_2_240(m, d) BOOST_PP_REPEAT_2_239(m, d) m(3, 239, d)
+# define BOOST_PP_REPEAT_2_241(m, d) BOOST_PP_REPEAT_2_240(m, d) m(3, 240, d)
+# define BOOST_PP_REPEAT_2_242(m, d) BOOST_PP_REPEAT_2_241(m, d) m(3, 241, d)
+# define BOOST_PP_REPEAT_2_243(m, d) BOOST_PP_REPEAT_2_242(m, d) m(3, 242, d)
+# define BOOST_PP_REPEAT_2_244(m, d) BOOST_PP_REPEAT_2_243(m, d) m(3, 243, d)
+# define BOOST_PP_REPEAT_2_245(m, d) BOOST_PP_REPEAT_2_244(m, d) m(3, 244, d)
+# define BOOST_PP_REPEAT_2_246(m, d) BOOST_PP_REPEAT_2_245(m, d) m(3, 245, d)
+# define BOOST_PP_REPEAT_2_247(m, d) BOOST_PP_REPEAT_2_246(m, d) m(3, 246, d)
+# define BOOST_PP_REPEAT_2_248(m, d) BOOST_PP_REPEAT_2_247(m, d) m(3, 247, d)
+# define BOOST_PP_REPEAT_2_249(m, d) BOOST_PP_REPEAT_2_248(m, d) m(3, 248, d)
+# define BOOST_PP_REPEAT_2_250(m, d) BOOST_PP_REPEAT_2_249(m, d) m(3, 249, d)
+# define BOOST_PP_REPEAT_2_251(m, d) BOOST_PP_REPEAT_2_250(m, d) m(3, 250, d)
+# define BOOST_PP_REPEAT_2_252(m, d) BOOST_PP_REPEAT_2_251(m, d) m(3, 251, d)
+# define BOOST_PP_REPEAT_2_253(m, d) BOOST_PP_REPEAT_2_252(m, d) m(3, 252, d)
+# define BOOST_PP_REPEAT_2_254(m, d) BOOST_PP_REPEAT_2_253(m, d) m(3, 253, d)
+# define BOOST_PP_REPEAT_2_255(m, d) BOOST_PP_REPEAT_2_254(m, d) m(3, 254, d)
+# define BOOST_PP_REPEAT_2_256(m, d) BOOST_PP_REPEAT_2_255(m, d) m(3, 255, d)
+#
+# define BOOST_PP_REPEAT_3_0(m, d)
+# define BOOST_PP_REPEAT_3_1(m, d) m(4, 0, d)
+# define BOOST_PP_REPEAT_3_2(m, d) BOOST_PP_REPEAT_3_1(m, d) m(4, 1, d)
+# define BOOST_PP_REPEAT_3_3(m, d) BOOST_PP_REPEAT_3_2(m, d) m(4, 2, d)
+# define BOOST_PP_REPEAT_3_4(m, d) BOOST_PP_REPEAT_3_3(m, d) m(4, 3, d)
+# define BOOST_PP_REPEAT_3_5(m, d) BOOST_PP_REPEAT_3_4(m, d) m(4, 4, d)
+# define BOOST_PP_REPEAT_3_6(m, d) BOOST_PP_REPEAT_3_5(m, d) m(4, 5, d)
+# define BOOST_PP_REPEAT_3_7(m, d) BOOST_PP_REPEAT_3_6(m, d) m(4, 6, d)
+# define BOOST_PP_REPEAT_3_8(m, d) BOOST_PP_REPEAT_3_7(m, d) m(4, 7, d)
+# define BOOST_PP_REPEAT_3_9(m, d) BOOST_PP_REPEAT_3_8(m, d) m(4, 8, d)
+# define BOOST_PP_REPEAT_3_10(m, d) BOOST_PP_REPEAT_3_9(m, d) m(4, 9, d)
+# define BOOST_PP_REPEAT_3_11(m, d) BOOST_PP_REPEAT_3_10(m, d) m(4, 10, d)
+# define BOOST_PP_REPEAT_3_12(m, d) BOOST_PP_REPEAT_3_11(m, d) m(4, 11, d)
+# define BOOST_PP_REPEAT_3_13(m, d) BOOST_PP_REPEAT_3_12(m, d) m(4, 12, d)
+# define BOOST_PP_REPEAT_3_14(m, d) BOOST_PP_REPEAT_3_13(m, d) m(4, 13, d)
+# define BOOST_PP_REPEAT_3_15(m, d) BOOST_PP_REPEAT_3_14(m, d) m(4, 14, d)
+# define BOOST_PP_REPEAT_3_16(m, d) BOOST_PP_REPEAT_3_15(m, d) m(4, 15, d)
+# define BOOST_PP_REPEAT_3_17(m, d) BOOST_PP_REPEAT_3_16(m, d) m(4, 16, d)
+# define BOOST_PP_REPEAT_3_18(m, d) BOOST_PP_REPEAT_3_17(m, d) m(4, 17, d)
+# define BOOST_PP_REPEAT_3_19(m, d) BOOST_PP_REPEAT_3_18(m, d) m(4, 18, d)
+# define BOOST_PP_REPEAT_3_20(m, d) BOOST_PP_REPEAT_3_19(m, d) m(4, 19, d)
+# define BOOST_PP_REPEAT_3_21(m, d) BOOST_PP_REPEAT_3_20(m, d) m(4, 20, d)
+# define BOOST_PP_REPEAT_3_22(m, d) BOOST_PP_REPEAT_3_21(m, d) m(4, 21, d)
+# define BOOST_PP_REPEAT_3_23(m, d) BOOST_PP_REPEAT_3_22(m, d) m(4, 22, d)
+# define BOOST_PP_REPEAT_3_24(m, d) BOOST_PP_REPEAT_3_23(m, d) m(4, 23, d)
+# define BOOST_PP_REPEAT_3_25(m, d) BOOST_PP_REPEAT_3_24(m, d) m(4, 24, d)
+# define BOOST_PP_REPEAT_3_26(m, d) BOOST_PP_REPEAT_3_25(m, d) m(4, 25, d)
+# define BOOST_PP_REPEAT_3_27(m, d) BOOST_PP_REPEAT_3_26(m, d) m(4, 26, d)
+# define BOOST_PP_REPEAT_3_28(m, d) BOOST_PP_REPEAT_3_27(m, d) m(4, 27, d)
+# define BOOST_PP_REPEAT_3_29(m, d) BOOST_PP_REPEAT_3_28(m, d) m(4, 28, d)
+# define BOOST_PP_REPEAT_3_30(m, d) BOOST_PP_REPEAT_3_29(m, d) m(4, 29, d)
+# define BOOST_PP_REPEAT_3_31(m, d) BOOST_PP_REPEAT_3_30(m, d) m(4, 30, d)
+# define BOOST_PP_REPEAT_3_32(m, d) BOOST_PP_REPEAT_3_31(m, d) m(4, 31, d)
+# define BOOST_PP_REPEAT_3_33(m, d) BOOST_PP_REPEAT_3_32(m, d) m(4, 32, d)
+# define BOOST_PP_REPEAT_3_34(m, d) BOOST_PP_REPEAT_3_33(m, d) m(4, 33, d)
+# define BOOST_PP_REPEAT_3_35(m, d) BOOST_PP_REPEAT_3_34(m, d) m(4, 34, d)
+# define BOOST_PP_REPEAT_3_36(m, d) BOOST_PP_REPEAT_3_35(m, d) m(4, 35, d)
+# define BOOST_PP_REPEAT_3_37(m, d) BOOST_PP_REPEAT_3_36(m, d) m(4, 36, d)
+# define BOOST_PP_REPEAT_3_38(m, d) BOOST_PP_REPEAT_3_37(m, d) m(4, 37, d)
+# define BOOST_PP_REPEAT_3_39(m, d) BOOST_PP_REPEAT_3_38(m, d) m(4, 38, d)
+# define BOOST_PP_REPEAT_3_40(m, d) BOOST_PP_REPEAT_3_39(m, d) m(4, 39, d)
+# define BOOST_PP_REPEAT_3_41(m, d) BOOST_PP_REPEAT_3_40(m, d) m(4, 40, d)
+# define BOOST_PP_REPEAT_3_42(m, d) BOOST_PP_REPEAT_3_41(m, d) m(4, 41, d)
+# define BOOST_PP_REPEAT_3_43(m, d) BOOST_PP_REPEAT_3_42(m, d) m(4, 42, d)
+# define BOOST_PP_REPEAT_3_44(m, d) BOOST_PP_REPEAT_3_43(m, d) m(4, 43, d)
+# define BOOST_PP_REPEAT_3_45(m, d) BOOST_PP_REPEAT_3_44(m, d) m(4, 44, d)
+# define BOOST_PP_REPEAT_3_46(m, d) BOOST_PP_REPEAT_3_45(m, d) m(4, 45, d)
+# define BOOST_PP_REPEAT_3_47(m, d) BOOST_PP_REPEAT_3_46(m, d) m(4, 46, d)
+# define BOOST_PP_REPEAT_3_48(m, d) BOOST_PP_REPEAT_3_47(m, d) m(4, 47, d)
+# define BOOST_PP_REPEAT_3_49(m, d) BOOST_PP_REPEAT_3_48(m, d) m(4, 48, d)
+# define BOOST_PP_REPEAT_3_50(m, d) BOOST_PP_REPEAT_3_49(m, d) m(4, 49, d)
+# define BOOST_PP_REPEAT_3_51(m, d) BOOST_PP_REPEAT_3_50(m, d) m(4, 50, d)
+# define BOOST_PP_REPEAT_3_52(m, d) BOOST_PP_REPEAT_3_51(m, d) m(4, 51, d)
+# define BOOST_PP_REPEAT_3_53(m, d) BOOST_PP_REPEAT_3_52(m, d) m(4, 52, d)
+# define BOOST_PP_REPEAT_3_54(m, d) BOOST_PP_REPEAT_3_53(m, d) m(4, 53, d)
+# define BOOST_PP_REPEAT_3_55(m, d) BOOST_PP_REPEAT_3_54(m, d) m(4, 54, d)
+# define BOOST_PP_REPEAT_3_56(m, d) BOOST_PP_REPEAT_3_55(m, d) m(4, 55, d)
+# define BOOST_PP_REPEAT_3_57(m, d) BOOST_PP_REPEAT_3_56(m, d) m(4, 56, d)
+# define BOOST_PP_REPEAT_3_58(m, d) BOOST_PP_REPEAT_3_57(m, d) m(4, 57, d)
+# define BOOST_PP_REPEAT_3_59(m, d) BOOST_PP_REPEAT_3_58(m, d) m(4, 58, d)
+# define BOOST_PP_REPEAT_3_60(m, d) BOOST_PP_REPEAT_3_59(m, d) m(4, 59, d)
+# define BOOST_PP_REPEAT_3_61(m, d) BOOST_PP_REPEAT_3_60(m, d) m(4, 60, d)
+# define BOOST_PP_REPEAT_3_62(m, d) BOOST_PP_REPEAT_3_61(m, d) m(4, 61, d)
+# define BOOST_PP_REPEAT_3_63(m, d) BOOST_PP_REPEAT_3_62(m, d) m(4, 62, d)
+# define BOOST_PP_REPEAT_3_64(m, d) BOOST_PP_REPEAT_3_63(m, d) m(4, 63, d)
+# define BOOST_PP_REPEAT_3_65(m, d) BOOST_PP_REPEAT_3_64(m, d) m(4, 64, d)
+# define BOOST_PP_REPEAT_3_66(m, d) BOOST_PP_REPEAT_3_65(m, d) m(4, 65, d)
+# define BOOST_PP_REPEAT_3_67(m, d) BOOST_PP_REPEAT_3_66(m, d) m(4, 66, d)
+# define BOOST_PP_REPEAT_3_68(m, d) BOOST_PP_REPEAT_3_67(m, d) m(4, 67, d)
+# define BOOST_PP_REPEAT_3_69(m, d) BOOST_PP_REPEAT_3_68(m, d) m(4, 68, d)
+# define BOOST_PP_REPEAT_3_70(m, d) BOOST_PP_REPEAT_3_69(m, d) m(4, 69, d)
+# define BOOST_PP_REPEAT_3_71(m, d) BOOST_PP_REPEAT_3_70(m, d) m(4, 70, d)
+# define BOOST_PP_REPEAT_3_72(m, d) BOOST_PP_REPEAT_3_71(m, d) m(4, 71, d)
+# define BOOST_PP_REPEAT_3_73(m, d) BOOST_PP_REPEAT_3_72(m, d) m(4, 72, d)
+# define BOOST_PP_REPEAT_3_74(m, d) BOOST_PP_REPEAT_3_73(m, d) m(4, 73, d)
+# define BOOST_PP_REPEAT_3_75(m, d) BOOST_PP_REPEAT_3_74(m, d) m(4, 74, d)
+# define BOOST_PP_REPEAT_3_76(m, d) BOOST_PP_REPEAT_3_75(m, d) m(4, 75, d)
+# define BOOST_PP_REPEAT_3_77(m, d) BOOST_PP_REPEAT_3_76(m, d) m(4, 76, d)
+# define BOOST_PP_REPEAT_3_78(m, d) BOOST_PP_REPEAT_3_77(m, d) m(4, 77, d)
+# define BOOST_PP_REPEAT_3_79(m, d) BOOST_PP_REPEAT_3_78(m, d) m(4, 78, d)
+# define BOOST_PP_REPEAT_3_80(m, d) BOOST_PP_REPEAT_3_79(m, d) m(4, 79, d)
+# define BOOST_PP_REPEAT_3_81(m, d) BOOST_PP_REPEAT_3_80(m, d) m(4, 80, d)
+# define BOOST_PP_REPEAT_3_82(m, d) BOOST_PP_REPEAT_3_81(m, d) m(4, 81, d)
+# define BOOST_PP_REPEAT_3_83(m, d) BOOST_PP_REPEAT_3_82(m, d) m(4, 82, d)
+# define BOOST_PP_REPEAT_3_84(m, d) BOOST_PP_REPEAT_3_83(m, d) m(4, 83, d)
+# define BOOST_PP_REPEAT_3_85(m, d) BOOST_PP_REPEAT_3_84(m, d) m(4, 84, d)
+# define BOOST_PP_REPEAT_3_86(m, d) BOOST_PP_REPEAT_3_85(m, d) m(4, 85, d)
+# define BOOST_PP_REPEAT_3_87(m, d) BOOST_PP_REPEAT_3_86(m, d) m(4, 86, d)
+# define BOOST_PP_REPEAT_3_88(m, d) BOOST_PP_REPEAT_3_87(m, d) m(4, 87, d)
+# define BOOST_PP_REPEAT_3_89(m, d) BOOST_PP_REPEAT_3_88(m, d) m(4, 88, d)
+# define BOOST_PP_REPEAT_3_90(m, d) BOOST_PP_REPEAT_3_89(m, d) m(4, 89, d)
+# define BOOST_PP_REPEAT_3_91(m, d) BOOST_PP_REPEAT_3_90(m, d) m(4, 90, d)
+# define BOOST_PP_REPEAT_3_92(m, d) BOOST_PP_REPEAT_3_91(m, d) m(4, 91, d)
+# define BOOST_PP_REPEAT_3_93(m, d) BOOST_PP_REPEAT_3_92(m, d) m(4, 92, d)
+# define BOOST_PP_REPEAT_3_94(m, d) BOOST_PP_REPEAT_3_93(m, d) m(4, 93, d)
+# define BOOST_PP_REPEAT_3_95(m, d) BOOST_PP_REPEAT_3_94(m, d) m(4, 94, d)
+# define BOOST_PP_REPEAT_3_96(m, d) BOOST_PP_REPEAT_3_95(m, d) m(4, 95, d)
+# define BOOST_PP_REPEAT_3_97(m, d) BOOST_PP_REPEAT_3_96(m, d) m(4, 96, d)
+# define BOOST_PP_REPEAT_3_98(m, d) BOOST_PP_REPEAT_3_97(m, d) m(4, 97, d)
+# define BOOST_PP_REPEAT_3_99(m, d) BOOST_PP_REPEAT_3_98(m, d) m(4, 98, d)
+# define BOOST_PP_REPEAT_3_100(m, d) BOOST_PP_REPEAT_3_99(m, d) m(4, 99, d)
+# define BOOST_PP_REPEAT_3_101(m, d) BOOST_PP_REPEAT_3_100(m, d) m(4, 100, d)
+# define BOOST_PP_REPEAT_3_102(m, d) BOOST_PP_REPEAT_3_101(m, d) m(4, 101, d)
+# define BOOST_PP_REPEAT_3_103(m, d) BOOST_PP_REPEAT_3_102(m, d) m(4, 102, d)
+# define BOOST_PP_REPEAT_3_104(m, d) BOOST_PP_REPEAT_3_103(m, d) m(4, 103, d)
+# define BOOST_PP_REPEAT_3_105(m, d) BOOST_PP_REPEAT_3_104(m, d) m(4, 104, d)
+# define BOOST_PP_REPEAT_3_106(m, d) BOOST_PP_REPEAT_3_105(m, d) m(4, 105, d)
+# define BOOST_PP_REPEAT_3_107(m, d) BOOST_PP_REPEAT_3_106(m, d) m(4, 106, d)
+# define BOOST_PP_REPEAT_3_108(m, d) BOOST_PP_REPEAT_3_107(m, d) m(4, 107, d)
+# define BOOST_PP_REPEAT_3_109(m, d) BOOST_PP_REPEAT_3_108(m, d) m(4, 108, d)
+# define BOOST_PP_REPEAT_3_110(m, d) BOOST_PP_REPEAT_3_109(m, d) m(4, 109, d)
+# define BOOST_PP_REPEAT_3_111(m, d) BOOST_PP_REPEAT_3_110(m, d) m(4, 110, d)
+# define BOOST_PP_REPEAT_3_112(m, d) BOOST_PP_REPEAT_3_111(m, d) m(4, 111, d)
+# define BOOST_PP_REPEAT_3_113(m, d) BOOST_PP_REPEAT_3_112(m, d) m(4, 112, d)
+# define BOOST_PP_REPEAT_3_114(m, d) BOOST_PP_REPEAT_3_113(m, d) m(4, 113, d)
+# define BOOST_PP_REPEAT_3_115(m, d) BOOST_PP_REPEAT_3_114(m, d) m(4, 114, d)
+# define BOOST_PP_REPEAT_3_116(m, d) BOOST_PP_REPEAT_3_115(m, d) m(4, 115, d)
+# define BOOST_PP_REPEAT_3_117(m, d) BOOST_PP_REPEAT_3_116(m, d) m(4, 116, d)
+# define BOOST_PP_REPEAT_3_118(m, d) BOOST_PP_REPEAT_3_117(m, d) m(4, 117, d)
+# define BOOST_PP_REPEAT_3_119(m, d) BOOST_PP_REPEAT_3_118(m, d) m(4, 118, d)
+# define BOOST_PP_REPEAT_3_120(m, d) BOOST_PP_REPEAT_3_119(m, d) m(4, 119, d)
+# define BOOST_PP_REPEAT_3_121(m, d) BOOST_PP_REPEAT_3_120(m, d) m(4, 120, d)
+# define BOOST_PP_REPEAT_3_122(m, d) BOOST_PP_REPEAT_3_121(m, d) m(4, 121, d)
+# define BOOST_PP_REPEAT_3_123(m, d) BOOST_PP_REPEAT_3_122(m, d) m(4, 122, d)
+# define BOOST_PP_REPEAT_3_124(m, d) BOOST_PP_REPEAT_3_123(m, d) m(4, 123, d)
+# define BOOST_PP_REPEAT_3_125(m, d) BOOST_PP_REPEAT_3_124(m, d) m(4, 124, d)
+# define BOOST_PP_REPEAT_3_126(m, d) BOOST_PP_REPEAT_3_125(m, d) m(4, 125, d)
+# define BOOST_PP_REPEAT_3_127(m, d) BOOST_PP_REPEAT_3_126(m, d) m(4, 126, d)
+# define BOOST_PP_REPEAT_3_128(m, d) BOOST_PP_REPEAT_3_127(m, d) m(4, 127, d)
+# define BOOST_PP_REPEAT_3_129(m, d) BOOST_PP_REPEAT_3_128(m, d) m(4, 128, d)
+# define BOOST_PP_REPEAT_3_130(m, d) BOOST_PP_REPEAT_3_129(m, d) m(4, 129, d)
+# define BOOST_PP_REPEAT_3_131(m, d) BOOST_PP_REPEAT_3_130(m, d) m(4, 130, d)
+# define BOOST_PP_REPEAT_3_132(m, d) BOOST_PP_REPEAT_3_131(m, d) m(4, 131, d)
+# define BOOST_PP_REPEAT_3_133(m, d) BOOST_PP_REPEAT_3_132(m, d) m(4, 132, d)
+# define BOOST_PP_REPEAT_3_134(m, d) BOOST_PP_REPEAT_3_133(m, d) m(4, 133, d)
+# define BOOST_PP_REPEAT_3_135(m, d) BOOST_PP_REPEAT_3_134(m, d) m(4, 134, d)
+# define BOOST_PP_REPEAT_3_136(m, d) BOOST_PP_REPEAT_3_135(m, d) m(4, 135, d)
+# define BOOST_PP_REPEAT_3_137(m, d) BOOST_PP_REPEAT_3_136(m, d) m(4, 136, d)
+# define BOOST_PP_REPEAT_3_138(m, d) BOOST_PP_REPEAT_3_137(m, d) m(4, 137, d)
+# define BOOST_PP_REPEAT_3_139(m, d) BOOST_PP_REPEAT_3_138(m, d) m(4, 138, d)
+# define BOOST_PP_REPEAT_3_140(m, d) BOOST_PP_REPEAT_3_139(m, d) m(4, 139, d)
+# define BOOST_PP_REPEAT_3_141(m, d) BOOST_PP_REPEAT_3_140(m, d) m(4, 140, d)
+# define BOOST_PP_REPEAT_3_142(m, d) BOOST_PP_REPEAT_3_141(m, d) m(4, 141, d)
+# define BOOST_PP_REPEAT_3_143(m, d) BOOST_PP_REPEAT_3_142(m, d) m(4, 142, d)
+# define BOOST_PP_REPEAT_3_144(m, d) BOOST_PP_REPEAT_3_143(m, d) m(4, 143, d)
+# define BOOST_PP_REPEAT_3_145(m, d) BOOST_PP_REPEAT_3_144(m, d) m(4, 144, d)
+# define BOOST_PP_REPEAT_3_146(m, d) BOOST_PP_REPEAT_3_145(m, d) m(4, 145, d)
+# define BOOST_PP_REPEAT_3_147(m, d) BOOST_PP_REPEAT_3_146(m, d) m(4, 146, d)
+# define BOOST_PP_REPEAT_3_148(m, d) BOOST_PP_REPEAT_3_147(m, d) m(4, 147, d)
+# define BOOST_PP_REPEAT_3_149(m, d) BOOST_PP_REPEAT_3_148(m, d) m(4, 148, d)
+# define BOOST_PP_REPEAT_3_150(m, d) BOOST_PP_REPEAT_3_149(m, d) m(4, 149, d)
+# define BOOST_PP_REPEAT_3_151(m, d) BOOST_PP_REPEAT_3_150(m, d) m(4, 150, d)
+# define BOOST_PP_REPEAT_3_152(m, d) BOOST_PP_REPEAT_3_151(m, d) m(4, 151, d)
+# define BOOST_PP_REPEAT_3_153(m, d) BOOST_PP_REPEAT_3_152(m, d) m(4, 152, d)
+# define BOOST_PP_REPEAT_3_154(m, d) BOOST_PP_REPEAT_3_153(m, d) m(4, 153, d)
+# define BOOST_PP_REPEAT_3_155(m, d) BOOST_PP_REPEAT_3_154(m, d) m(4, 154, d)
+# define BOOST_PP_REPEAT_3_156(m, d) BOOST_PP_REPEAT_3_155(m, d) m(4, 155, d)
+# define BOOST_PP_REPEAT_3_157(m, d) BOOST_PP_REPEAT_3_156(m, d) m(4, 156, d)
+# define BOOST_PP_REPEAT_3_158(m, d) BOOST_PP_REPEAT_3_157(m, d) m(4, 157, d)
+# define BOOST_PP_REPEAT_3_159(m, d) BOOST_PP_REPEAT_3_158(m, d) m(4, 158, d)
+# define BOOST_PP_REPEAT_3_160(m, d) BOOST_PP_REPEAT_3_159(m, d) m(4, 159, d)
+# define BOOST_PP_REPEAT_3_161(m, d) BOOST_PP_REPEAT_3_160(m, d) m(4, 160, d)
+# define BOOST_PP_REPEAT_3_162(m, d) BOOST_PP_REPEAT_3_161(m, d) m(4, 161, d)
+# define BOOST_PP_REPEAT_3_163(m, d) BOOST_PP_REPEAT_3_162(m, d) m(4, 162, d)
+# define BOOST_PP_REPEAT_3_164(m, d) BOOST_PP_REPEAT_3_163(m, d) m(4, 163, d)
+# define BOOST_PP_REPEAT_3_165(m, d) BOOST_PP_REPEAT_3_164(m, d) m(4, 164, d)
+# define BOOST_PP_REPEAT_3_166(m, d) BOOST_PP_REPEAT_3_165(m, d) m(4, 165, d)
+# define BOOST_PP_REPEAT_3_167(m, d) BOOST_PP_REPEAT_3_166(m, d) m(4, 166, d)
+# define BOOST_PP_REPEAT_3_168(m, d) BOOST_PP_REPEAT_3_167(m, d) m(4, 167, d)
+# define BOOST_PP_REPEAT_3_169(m, d) BOOST_PP_REPEAT_3_168(m, d) m(4, 168, d)
+# define BOOST_PP_REPEAT_3_170(m, d) BOOST_PP_REPEAT_3_169(m, d) m(4, 169, d)
+# define BOOST_PP_REPEAT_3_171(m, d) BOOST_PP_REPEAT_3_170(m, d) m(4, 170, d)
+# define BOOST_PP_REPEAT_3_172(m, d) BOOST_PP_REPEAT_3_171(m, d) m(4, 171, d)
+# define BOOST_PP_REPEAT_3_173(m, d) BOOST_PP_REPEAT_3_172(m, d) m(4, 172, d)
+# define BOOST_PP_REPEAT_3_174(m, d) BOOST_PP_REPEAT_3_173(m, d) m(4, 173, d)
+# define BOOST_PP_REPEAT_3_175(m, d) BOOST_PP_REPEAT_3_174(m, d) m(4, 174, d)
+# define BOOST_PP_REPEAT_3_176(m, d) BOOST_PP_REPEAT_3_175(m, d) m(4, 175, d)
+# define BOOST_PP_REPEAT_3_177(m, d) BOOST_PP_REPEAT_3_176(m, d) m(4, 176, d)
+# define BOOST_PP_REPEAT_3_178(m, d) BOOST_PP_REPEAT_3_177(m, d) m(4, 177, d)
+# define BOOST_PP_REPEAT_3_179(m, d) BOOST_PP_REPEAT_3_178(m, d) m(4, 178, d)
+# define BOOST_PP_REPEAT_3_180(m, d) BOOST_PP_REPEAT_3_179(m, d) m(4, 179, d)
+# define BOOST_PP_REPEAT_3_181(m, d) BOOST_PP_REPEAT_3_180(m, d) m(4, 180, d)
+# define BOOST_PP_REPEAT_3_182(m, d) BOOST_PP_REPEAT_3_181(m, d) m(4, 181, d)
+# define BOOST_PP_REPEAT_3_183(m, d) BOOST_PP_REPEAT_3_182(m, d) m(4, 182, d)
+# define BOOST_PP_REPEAT_3_184(m, d) BOOST_PP_REPEAT_3_183(m, d) m(4, 183, d)
+# define BOOST_PP_REPEAT_3_185(m, d) BOOST_PP_REPEAT_3_184(m, d) m(4, 184, d)
+# define BOOST_PP_REPEAT_3_186(m, d) BOOST_PP_REPEAT_3_185(m, d) m(4, 185, d)
+# define BOOST_PP_REPEAT_3_187(m, d) BOOST_PP_REPEAT_3_186(m, d) m(4, 186, d)
+# define BOOST_PP_REPEAT_3_188(m, d) BOOST_PP_REPEAT_3_187(m, d) m(4, 187, d)
+# define BOOST_PP_REPEAT_3_189(m, d) BOOST_PP_REPEAT_3_188(m, d) m(4, 188, d)
+# define BOOST_PP_REPEAT_3_190(m, d) BOOST_PP_REPEAT_3_189(m, d) m(4, 189, d)
+# define BOOST_PP_REPEAT_3_191(m, d) BOOST_PP_REPEAT_3_190(m, d) m(4, 190, d)
+# define BOOST_PP_REPEAT_3_192(m, d) BOOST_PP_REPEAT_3_191(m, d) m(4, 191, d)
+# define BOOST_PP_REPEAT_3_193(m, d) BOOST_PP_REPEAT_3_192(m, d) m(4, 192, d)
+# define BOOST_PP_REPEAT_3_194(m, d) BOOST_PP_REPEAT_3_193(m, d) m(4, 193, d)
+# define BOOST_PP_REPEAT_3_195(m, d) BOOST_PP_REPEAT_3_194(m, d) m(4, 194, d)
+# define BOOST_PP_REPEAT_3_196(m, d) BOOST_PP_REPEAT_3_195(m, d) m(4, 195, d)
+# define BOOST_PP_REPEAT_3_197(m, d) BOOST_PP_REPEAT_3_196(m, d) m(4, 196, d)
+# define BOOST_PP_REPEAT_3_198(m, d) BOOST_PP_REPEAT_3_197(m, d) m(4, 197, d)
+# define BOOST_PP_REPEAT_3_199(m, d) BOOST_PP_REPEAT_3_198(m, d) m(4, 198, d)
+# define BOOST_PP_REPEAT_3_200(m, d) BOOST_PP_REPEAT_3_199(m, d) m(4, 199, d)
+# define BOOST_PP_REPEAT_3_201(m, d) BOOST_PP_REPEAT_3_200(m, d) m(4, 200, d)
+# define BOOST_PP_REPEAT_3_202(m, d) BOOST_PP_REPEAT_3_201(m, d) m(4, 201, d)
+# define BOOST_PP_REPEAT_3_203(m, d) BOOST_PP_REPEAT_3_202(m, d) m(4, 202, d)
+# define BOOST_PP_REPEAT_3_204(m, d) BOOST_PP_REPEAT_3_203(m, d) m(4, 203, d)
+# define BOOST_PP_REPEAT_3_205(m, d) BOOST_PP_REPEAT_3_204(m, d) m(4, 204, d)
+# define BOOST_PP_REPEAT_3_206(m, d) BOOST_PP_REPEAT_3_205(m, d) m(4, 205, d)
+# define BOOST_PP_REPEAT_3_207(m, d) BOOST_PP_REPEAT_3_206(m, d) m(4, 206, d)
+# define BOOST_PP_REPEAT_3_208(m, d) BOOST_PP_REPEAT_3_207(m, d) m(4, 207, d)
+# define BOOST_PP_REPEAT_3_209(m, d) BOOST_PP_REPEAT_3_208(m, d) m(4, 208, d)
+# define BOOST_PP_REPEAT_3_210(m, d) BOOST_PP_REPEAT_3_209(m, d) m(4, 209, d)
+# define BOOST_PP_REPEAT_3_211(m, d) BOOST_PP_REPEAT_3_210(m, d) m(4, 210, d)
+# define BOOST_PP_REPEAT_3_212(m, d) BOOST_PP_REPEAT_3_211(m, d) m(4, 211, d)
+# define BOOST_PP_REPEAT_3_213(m, d) BOOST_PP_REPEAT_3_212(m, d) m(4, 212, d)
+# define BOOST_PP_REPEAT_3_214(m, d) BOOST_PP_REPEAT_3_213(m, d) m(4, 213, d)
+# define BOOST_PP_REPEAT_3_215(m, d) BOOST_PP_REPEAT_3_214(m, d) m(4, 214, d)
+# define BOOST_PP_REPEAT_3_216(m, d) BOOST_PP_REPEAT_3_215(m, d) m(4, 215, d)
+# define BOOST_PP_REPEAT_3_217(m, d) BOOST_PP_REPEAT_3_216(m, d) m(4, 216, d)
+# define BOOST_PP_REPEAT_3_218(m, d) BOOST_PP_REPEAT_3_217(m, d) m(4, 217, d)
+# define BOOST_PP_REPEAT_3_219(m, d) BOOST_PP_REPEAT_3_218(m, d) m(4, 218, d)
+# define BOOST_PP_REPEAT_3_220(m, d) BOOST_PP_REPEAT_3_219(m, d) m(4, 219, d)
+# define BOOST_PP_REPEAT_3_221(m, d) BOOST_PP_REPEAT_3_220(m, d) m(4, 220, d)
+# define BOOST_PP_REPEAT_3_222(m, d) BOOST_PP_REPEAT_3_221(m, d) m(4, 221, d)
+# define BOOST_PP_REPEAT_3_223(m, d) BOOST_PP_REPEAT_3_222(m, d) m(4, 222, d)
+# define BOOST_PP_REPEAT_3_224(m, d) BOOST_PP_REPEAT_3_223(m, d) m(4, 223, d)
+# define BOOST_PP_REPEAT_3_225(m, d) BOOST_PP_REPEAT_3_224(m, d) m(4, 224, d)
+# define BOOST_PP_REPEAT_3_226(m, d) BOOST_PP_REPEAT_3_225(m, d) m(4, 225, d)
+# define BOOST_PP_REPEAT_3_227(m, d) BOOST_PP_REPEAT_3_226(m, d) m(4, 226, d)
+# define BOOST_PP_REPEAT_3_228(m, d) BOOST_PP_REPEAT_3_227(m, d) m(4, 227, d)
+# define BOOST_PP_REPEAT_3_229(m, d) BOOST_PP_REPEAT_3_228(m, d) m(4, 228, d)
+# define BOOST_PP_REPEAT_3_230(m, d) BOOST_PP_REPEAT_3_229(m, d) m(4, 229, d)
+# define BOOST_PP_REPEAT_3_231(m, d) BOOST_PP_REPEAT_3_230(m, d) m(4, 230, d)
+# define BOOST_PP_REPEAT_3_232(m, d) BOOST_PP_REPEAT_3_231(m, d) m(4, 231, d)
+# define BOOST_PP_REPEAT_3_233(m, d) BOOST_PP_REPEAT_3_232(m, d) m(4, 232, d)
+# define BOOST_PP_REPEAT_3_234(m, d) BOOST_PP_REPEAT_3_233(m, d) m(4, 233, d)
+# define BOOST_PP_REPEAT_3_235(m, d) BOOST_PP_REPEAT_3_234(m, d) m(4, 234, d)
+# define BOOST_PP_REPEAT_3_236(m, d) BOOST_PP_REPEAT_3_235(m, d) m(4, 235, d)
+# define BOOST_PP_REPEAT_3_237(m, d) BOOST_PP_REPEAT_3_236(m, d) m(4, 236, d)
+# define BOOST_PP_REPEAT_3_238(m, d) BOOST_PP_REPEAT_3_237(m, d) m(4, 237, d)
+# define BOOST_PP_REPEAT_3_239(m, d) BOOST_PP_REPEAT_3_238(m, d) m(4, 238, d)
+# define BOOST_PP_REPEAT_3_240(m, d) BOOST_PP_REPEAT_3_239(m, d) m(4, 239, d)
+# define BOOST_PP_REPEAT_3_241(m, d) BOOST_PP_REPEAT_3_240(m, d) m(4, 240, d)
+# define BOOST_PP_REPEAT_3_242(m, d) BOOST_PP_REPEAT_3_241(m, d) m(4, 241, d)
+# define BOOST_PP_REPEAT_3_243(m, d) BOOST_PP_REPEAT_3_242(m, d) m(4, 242, d)
+# define BOOST_PP_REPEAT_3_244(m, d) BOOST_PP_REPEAT_3_243(m, d) m(4, 243, d)
+# define BOOST_PP_REPEAT_3_245(m, d) BOOST_PP_REPEAT_3_244(m, d) m(4, 244, d)
+# define BOOST_PP_REPEAT_3_246(m, d) BOOST_PP_REPEAT_3_245(m, d) m(4, 245, d)
+# define BOOST_PP_REPEAT_3_247(m, d) BOOST_PP_REPEAT_3_246(m, d) m(4, 246, d)
+# define BOOST_PP_REPEAT_3_248(m, d) BOOST_PP_REPEAT_3_247(m, d) m(4, 247, d)
+# define BOOST_PP_REPEAT_3_249(m, d) BOOST_PP_REPEAT_3_248(m, d) m(4, 248, d)
+# define BOOST_PP_REPEAT_3_250(m, d) BOOST_PP_REPEAT_3_249(m, d) m(4, 249, d)
+# define BOOST_PP_REPEAT_3_251(m, d) BOOST_PP_REPEAT_3_250(m, d) m(4, 250, d)
+# define BOOST_PP_REPEAT_3_252(m, d) BOOST_PP_REPEAT_3_251(m, d) m(4, 251, d)
+# define BOOST_PP_REPEAT_3_253(m, d) BOOST_PP_REPEAT_3_252(m, d) m(4, 252, d)
+# define BOOST_PP_REPEAT_3_254(m, d) BOOST_PP_REPEAT_3_253(m, d) m(4, 253, d)
+# define BOOST_PP_REPEAT_3_255(m, d) BOOST_PP_REPEAT_3_254(m, d) m(4, 254, d)
+# define BOOST_PP_REPEAT_3_256(m, d) BOOST_PP_REPEAT_3_255(m, d) m(4, 255, d)
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/repetition/repeat_from_to.hpp b/third_party/boost/boost/preprocessor/repetition/repeat_from_to.hpp
new file mode 100644
index 0000000..efe539e
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/repetition/repeat_from_to.hpp
@@ -0,0 +1,87 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_REPETITION_REPEAT_FROM_TO_HPP
+# define BOOST_PREPROCESSOR_REPETITION_REPEAT_FROM_TO_HPP
+#
+# include <boost/preprocessor/arithmetic/add.hpp>
+# include <boost/preprocessor/arithmetic/sub.hpp>
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/control/while.hpp>
+# include <boost/preprocessor/debug/error.hpp>
+# include <boost/preprocessor/detail/auto_rec.hpp>
+# include <boost/preprocessor/repetition/repeat.hpp>
+# include <boost/preprocessor/tuple/elem.hpp>
+# include <boost/preprocessor/tuple/rem.hpp>
+#
+# /* BOOST_PP_REPEAT_FROM_TO */
+#
+# if 0
+# define BOOST_PP_REPEAT_FROM_TO(first, last, macro, data)
+# endif
+#
+# define BOOST_PP_REPEAT_FROM_TO BOOST_PP_CAT(BOOST_PP_REPEAT_FROM_TO_, BOOST_PP_AUTO_REC(BOOST_PP_REPEAT_P, 4))
+#
+# define BOOST_PP_REPEAT_FROM_TO_1(f, l, m, dt) BOOST_PP_REPEAT_FROM_TO_D_1(BOOST_PP_AUTO_REC(BOOST_PP_WHILE_P, 256), f, l, m, dt)
+# define BOOST_PP_REPEAT_FROM_TO_2(f, l, m, dt) BOOST_PP_REPEAT_FROM_TO_D_2(BOOST_PP_AUTO_REC(BOOST_PP_WHILE_P, 256), f, l, m, dt)
+# define BOOST_PP_REPEAT_FROM_TO_3(f, l, m, dt) BOOST_PP_REPEAT_FROM_TO_D_3(BOOST_PP_AUTO_REC(BOOST_PP_WHILE_P, 256), f, l, m, dt)
+# define BOOST_PP_REPEAT_FROM_TO_4(f, l, m, dt) BOOST_PP_ERROR(0x0003)
+#
+# define BOOST_PP_REPEAT_FROM_TO_1ST BOOST_PP_REPEAT_FROM_TO_1
+# define BOOST_PP_REPEAT_FROM_TO_2ND BOOST_PP_REPEAT_FROM_TO_2
+# define BOOST_PP_REPEAT_FROM_TO_3RD BOOST_PP_REPEAT_FROM_TO_3
+#
+# /* BOOST_PP_REPEAT_FROM_TO_D */
+#
+# if 0
+# define BOOST_PP_REPEAT_FROM_TO_D(d, first, last, macro, data)
+# endif
+#
+# define BOOST_PP_REPEAT_FROM_TO_D BOOST_PP_CAT(BOOST_PP_REPEAT_FROM_TO_D_, BOOST_PP_AUTO_REC(BOOST_PP_REPEAT_P, 4))
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_REPEAT_FROM_TO_D_1(d, f, l, m, dt) BOOST_PP_REPEAT_1(BOOST_PP_SUB_D(d, l, f), BOOST_PP_REPEAT_FROM_TO_M_1, (d, f, m, dt))
+# define BOOST_PP_REPEAT_FROM_TO_D_2(d, f, l, m, dt) BOOST_PP_REPEAT_2(BOOST_PP_SUB_D(d, l, f), BOOST_PP_REPEAT_FROM_TO_M_2, (d, f, m, dt))
+# define BOOST_PP_REPEAT_FROM_TO_D_3(d, f, l, m, dt) BOOST_PP_REPEAT_3(BOOST_PP_SUB_D(d, l, f), BOOST_PP_REPEAT_FROM_TO_M_3, (d, f, m, dt))
+# else
+# define BOOST_PP_REPEAT_FROM_TO_D_1(d, f, l, m, dt) BOOST_PP_REPEAT_FROM_TO_D_1_I(d, f, l, m, dt)
+# define BOOST_PP_REPEAT_FROM_TO_D_2(d, f, l, m, dt) BOOST_PP_REPEAT_FROM_TO_D_2_I(d, f, l, m, dt)
+# define BOOST_PP_REPEAT_FROM_TO_D_3(d, f, l, m, dt) BOOST_PP_REPEAT_FROM_TO_D_3_I(d, f, l, m, dt)
+# define BOOST_PP_REPEAT_FROM_TO_D_1_I(d, f, l, m, dt) BOOST_PP_REPEAT_1(BOOST_PP_SUB_D(d, l, f), BOOST_PP_REPEAT_FROM_TO_M_1, (d, f, m, dt))
+# define BOOST_PP_REPEAT_FROM_TO_D_2_I(d, f, l, m, dt) BOOST_PP_REPEAT_2(BOOST_PP_SUB_D(d, l, f), BOOST_PP_REPEAT_FROM_TO_M_2, (d, f, m, dt))
+# define BOOST_PP_REPEAT_FROM_TO_D_3_I(d, f, l, m, dt) BOOST_PP_REPEAT_3(BOOST_PP_SUB_D(d, l, f), BOOST_PP_REPEAT_FROM_TO_M_3, (d, f, m, dt))
+# endif
+#
+# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_STRICT()
+# define BOOST_PP_REPEAT_FROM_TO_M_1(z, n, dfmd) BOOST_PP_REPEAT_FROM_TO_M_1_IM(z, n, BOOST_PP_TUPLE_REM_4 dfmd)
+# define BOOST_PP_REPEAT_FROM_TO_M_2(z, n, dfmd) BOOST_PP_REPEAT_FROM_TO_M_2_IM(z, n, BOOST_PP_TUPLE_REM_4 dfmd)
+# define BOOST_PP_REPEAT_FROM_TO_M_3(z, n, dfmd) BOOST_PP_REPEAT_FROM_TO_M_3_IM(z, n, BOOST_PP_TUPLE_REM_4 dfmd)
+# define BOOST_PP_REPEAT_FROM_TO_M_1_IM(z, n, im) BOOST_PP_REPEAT_FROM_TO_M_1_I(z, n, im)
+# define BOOST_PP_REPEAT_FROM_TO_M_2_IM(z, n, im) BOOST_PP_REPEAT_FROM_TO_M_2_I(z, n, im)
+# define BOOST_PP_REPEAT_FROM_TO_M_3_IM(z, n, im) BOOST_PP_REPEAT_FROM_TO_M_3_I(z, n, im)
+# else
+# define BOOST_PP_REPEAT_FROM_TO_M_1(z, n, dfmd) BOOST_PP_REPEAT_FROM_TO_M_1_I(z, n, BOOST_PP_TUPLE_ELEM(4, 0, dfmd), BOOST_PP_TUPLE_ELEM(4, 1, dfmd), BOOST_PP_TUPLE_ELEM(4, 2, dfmd), BOOST_PP_TUPLE_ELEM(4, 3, dfmd))
+# define BOOST_PP_REPEAT_FROM_TO_M_2(z, n, dfmd) BOOST_PP_REPEAT_FROM_TO_M_2_I(z, n, BOOST_PP_TUPLE_ELEM(4, 0, dfmd), BOOST_PP_TUPLE_ELEM(4, 1, dfmd), BOOST_PP_TUPLE_ELEM(4, 2, dfmd), BOOST_PP_TUPLE_ELEM(4, 3, dfmd))
+# define BOOST_PP_REPEAT_FROM_TO_M_3(z, n, dfmd) BOOST_PP_REPEAT_FROM_TO_M_3_I(z, n, BOOST_PP_TUPLE_ELEM(4, 0, dfmd), BOOST_PP_TUPLE_ELEM(4, 1, dfmd), BOOST_PP_TUPLE_ELEM(4, 2, dfmd), BOOST_PP_TUPLE_ELEM(4, 3, dfmd))
+# endif
+#
+# define BOOST_PP_REPEAT_FROM_TO_M_1_I(z, n, d, f, m, dt) BOOST_PP_REPEAT_FROM_TO_M_1_II(z, BOOST_PP_ADD_D(d, n, f), m, dt)
+# define BOOST_PP_REPEAT_FROM_TO_M_2_I(z, n, d, f, m, dt) BOOST_PP_REPEAT_FROM_TO_M_2_II(z, BOOST_PP_ADD_D(d, n, f), m, dt)
+# define BOOST_PP_REPEAT_FROM_TO_M_3_I(z, n, d, f, m, dt) BOOST_PP_REPEAT_FROM_TO_M_3_II(z, BOOST_PP_ADD_D(d, n, f), m, dt)
+#
+# define BOOST_PP_REPEAT_FROM_TO_M_1_II(z, n, m, dt) m(z, n, dt)
+# define BOOST_PP_REPEAT_FROM_TO_M_2_II(z, n, m, dt) m(z, n, dt)
+# define BOOST_PP_REPEAT_FROM_TO_M_3_II(z, n, m, dt) m(z, n, dt)
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/slot/detail/def.hpp b/third_party/boost/boost/preprocessor/slot/detail/def.hpp
new file mode 100644
index 0000000..885099e
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/slot/detail/def.hpp
@@ -0,0 +1,49 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_SLOT_DETAIL_DEF_HPP
+# define BOOST_PREPROCESSOR_SLOT_DETAIL_DEF_HPP
+#
+# /* BOOST_PP_SLOT_OFFSET_x */
+#
+# define BOOST_PP_SLOT_OFFSET_10(x) (x) % 1000000000UL
+# define BOOST_PP_SLOT_OFFSET_9(x) BOOST_PP_SLOT_OFFSET_10(x) % 100000000UL
+# define BOOST_PP_SLOT_OFFSET_8(x) BOOST_PP_SLOT_OFFSET_9(x) % 10000000UL
+# define BOOST_PP_SLOT_OFFSET_7(x) BOOST_PP_SLOT_OFFSET_8(x) % 1000000UL
+# define BOOST_PP_SLOT_OFFSET_6(x) BOOST_PP_SLOT_OFFSET_7(x) % 100000UL
+# define BOOST_PP_SLOT_OFFSET_5(x) BOOST_PP_SLOT_OFFSET_6(x) % 10000UL
+# define BOOST_PP_SLOT_OFFSET_4(x) BOOST_PP_SLOT_OFFSET_5(x) % 1000UL
+# define BOOST_PP_SLOT_OFFSET_3(x) BOOST_PP_SLOT_OFFSET_4(x) % 100UL
+# define BOOST_PP_SLOT_OFFSET_2(x) BOOST_PP_SLOT_OFFSET_3(x) % 10UL
+#
+# /* BOOST_PP_SLOT_CC_x */
+#
+# define BOOST_PP_SLOT_CC_2(a, b) BOOST_PP_SLOT_CC_2_D(a, b)
+# define BOOST_PP_SLOT_CC_3(a, b, c) BOOST_PP_SLOT_CC_3_D(a, b, c)
+# define BOOST_PP_SLOT_CC_4(a, b, c, d) BOOST_PP_SLOT_CC_4_D(a, b, c, d)
+# define BOOST_PP_SLOT_CC_5(a, b, c, d, e) BOOST_PP_SLOT_CC_5_D(a, b, c, d, e)
+# define BOOST_PP_SLOT_CC_6(a, b, c, d, e, f) BOOST_PP_SLOT_CC_6_D(a, b, c, d, e, f)
+# define BOOST_PP_SLOT_CC_7(a, b, c, d, e, f, g) BOOST_PP_SLOT_CC_7_D(a, b, c, d, e, f, g)
+# define BOOST_PP_SLOT_CC_8(a, b, c, d, e, f, g, h) BOOST_PP_SLOT_CC_8_D(a, b, c, d, e, f, g, h)
+# define BOOST_PP_SLOT_CC_9(a, b, c, d, e, f, g, h, i) BOOST_PP_SLOT_CC_9_D(a, b, c, d, e, f, g, h, i)
+# define BOOST_PP_SLOT_CC_10(a, b, c, d, e, f, g, h, i, j) BOOST_PP_SLOT_CC_10_D(a, b, c, d, e, f, g, h, i, j)
+#
+# define BOOST_PP_SLOT_CC_2_D(a, b) a ## b
+# define BOOST_PP_SLOT_CC_3_D(a, b, c) a ## b ## c
+# define BOOST_PP_SLOT_CC_4_D(a, b, c, d) a ## b ## c ## d
+# define BOOST_PP_SLOT_CC_5_D(a, b, c, d, e) a ## b ## c ## d ## e
+# define BOOST_PP_SLOT_CC_6_D(a, b, c, d, e, f) a ## b ## c ## d ## e ## f
+# define BOOST_PP_SLOT_CC_7_D(a, b, c, d, e, f, g) a ## b ## c ## d ## e ## f ## g
+# define BOOST_PP_SLOT_CC_8_D(a, b, c, d, e, f, g, h) a ## b ## c ## d ## e ## f ## g ## h
+# define BOOST_PP_SLOT_CC_9_D(a, b, c, d, e, f, g, h, i) a ## b ## c ## d ## e ## f ## g ## h ## i
+# define BOOST_PP_SLOT_CC_10_D(a, b, c, d, e, f, g, h, i, j) a ## b ## c ## d ## e ## f ## g ## h ## i ## j
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/slot/detail/shared.hpp b/third_party/boost/boost/preprocessor/slot/detail/shared.hpp
new file mode 100644
index 0000000..c97ac54
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/slot/detail/shared.hpp
@@ -0,0 +1,247 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PP_VALUE
+# error BOOST_PP_ERROR: BOOST_PP_VALUE is not defined
+# endif
+#
+# undef BOOST_PP_SLOT_TEMP_1
+# undef BOOST_PP_SLOT_TEMP_2
+# undef BOOST_PP_SLOT_TEMP_3
+# undef BOOST_PP_SLOT_TEMP_4
+# undef BOOST_PP_SLOT_TEMP_5
+# undef BOOST_PP_SLOT_TEMP_6
+# undef BOOST_PP_SLOT_TEMP_7
+# undef BOOST_PP_SLOT_TEMP_8
+# undef BOOST_PP_SLOT_TEMP_9
+# undef BOOST_PP_SLOT_TEMP_10
+#
+# if (BOOST_PP_VALUE) / 1000000000UL == 0
+# define BOOST_PP_SLOT_TEMP_10 0
+# elif (BOOST_PP_VALUE) / 1000000000UL == 1
+# define BOOST_PP_SLOT_TEMP_10 1
+# elif (BOOST_PP_VALUE) / 1000000000UL == 2
+# define BOOST_PP_SLOT_TEMP_10 2
+# elif (BOOST_PP_VALUE) / 1000000000UL == 3
+# define BOOST_PP_SLOT_TEMP_10 3
+# elif (BOOST_PP_VALUE) / 1000000000UL == 4
+# define BOOST_PP_SLOT_TEMP_10 4
+# elif (BOOST_PP_VALUE) / 1000000000UL == 5
+# define BOOST_PP_SLOT_TEMP_10 5
+# elif (BOOST_PP_VALUE) / 1000000000UL == 6
+# define BOOST_PP_SLOT_TEMP_10 6
+# elif (BOOST_PP_VALUE) / 1000000000UL == 7
+# define BOOST_PP_SLOT_TEMP_10 7
+# elif (BOOST_PP_VALUE) / 1000000000UL == 8
+# define BOOST_PP_SLOT_TEMP_10 8
+# elif (BOOST_PP_VALUE) / 1000000000UL == 9
+# define BOOST_PP_SLOT_TEMP_10 9
+# endif
+#
+# if BOOST_PP_SLOT_OFFSET_10(BOOST_PP_VALUE) / 100000000UL == 0
+# define BOOST_PP_SLOT_TEMP_9 0
+# elif BOOST_PP_SLOT_OFFSET_10(BOOST_PP_VALUE) / 100000000UL == 1
+# define BOOST_PP_SLOT_TEMP_9 1
+# elif BOOST_PP_SLOT_OFFSET_10(BOOST_PP_VALUE) / 100000000UL == 2
+# define BOOST_PP_SLOT_TEMP_9 2
+# elif BOOST_PP_SLOT_OFFSET_10(BOOST_PP_VALUE) / 100000000UL == 3
+# define BOOST_PP_SLOT_TEMP_9 3
+# elif BOOST_PP_SLOT_OFFSET_10(BOOST_PP_VALUE) / 100000000UL == 4
+# define BOOST_PP_SLOT_TEMP_9 4
+# elif BOOST_PP_SLOT_OFFSET_10(BOOST_PP_VALUE) / 100000000UL == 5
+# define BOOST_PP_SLOT_TEMP_9 5
+# elif BOOST_PP_SLOT_OFFSET_10(BOOST_PP_VALUE) / 100000000UL == 6
+# define BOOST_PP_SLOT_TEMP_9 6
+# elif BOOST_PP_SLOT_OFFSET_10(BOOST_PP_VALUE) / 100000000UL == 7
+# define BOOST_PP_SLOT_TEMP_9 7
+# elif BOOST_PP_SLOT_OFFSET_10(BOOST_PP_VALUE) / 100000000UL == 8
+# define BOOST_PP_SLOT_TEMP_9 8
+# elif BOOST_PP_SLOT_OFFSET_10(BOOST_PP_VALUE) / 100000000UL == 9
+# define BOOST_PP_SLOT_TEMP_9 9
+# endif
+#
+# if BOOST_PP_SLOT_OFFSET_9(BOOST_PP_VALUE) / 10000000UL == 0
+# define BOOST_PP_SLOT_TEMP_8 0
+# elif BOOST_PP_SLOT_OFFSET_9(BOOST_PP_VALUE) / 10000000UL == 1
+# define BOOST_PP_SLOT_TEMP_8 1
+# elif BOOST_PP_SLOT_OFFSET_9(BOOST_PP_VALUE) / 10000000UL == 2
+# define BOOST_PP_SLOT_TEMP_8 2
+# elif BOOST_PP_SLOT_OFFSET_9(BOOST_PP_VALUE) / 10000000UL == 3
+# define BOOST_PP_SLOT_TEMP_8 3
+# elif BOOST_PP_SLOT_OFFSET_9(BOOST_PP_VALUE) / 10000000UL == 4
+# define BOOST_PP_SLOT_TEMP_8 4
+# elif BOOST_PP_SLOT_OFFSET_9(BOOST_PP_VALUE) / 10000000UL == 5
+# define BOOST_PP_SLOT_TEMP_8 5
+# elif BOOST_PP_SLOT_OFFSET_9(BOOST_PP_VALUE) / 10000000UL == 6
+# define BOOST_PP_SLOT_TEMP_8 6
+# elif BOOST_PP_SLOT_OFFSET_9(BOOST_PP_VALUE) / 10000000UL == 7
+# define BOOST_PP_SLOT_TEMP_8 7
+# elif BOOST_PP_SLOT_OFFSET_9(BOOST_PP_VALUE) / 10000000UL == 8
+# define BOOST_PP_SLOT_TEMP_8 8
+# elif BOOST_PP_SLOT_OFFSET_9(BOOST_PP_VALUE) / 10000000UL == 9
+# define BOOST_PP_SLOT_TEMP_8 9
+# endif
+#
+# if BOOST_PP_SLOT_OFFSET_8(BOOST_PP_VALUE) / 1000000UL == 0
+# define BOOST_PP_SLOT_TEMP_7 0
+# elif BOOST_PP_SLOT_OFFSET_8(BOOST_PP_VALUE) / 1000000UL == 1
+# define BOOST_PP_SLOT_TEMP_7 1
+# elif BOOST_PP_SLOT_OFFSET_8(BOOST_PP_VALUE) / 1000000UL == 2
+# define BOOST_PP_SLOT_TEMP_7 2
+# elif BOOST_PP_SLOT_OFFSET_8(BOOST_PP_VALUE) / 1000000UL == 3
+# define BOOST_PP_SLOT_TEMP_7 3
+# elif BOOST_PP_SLOT_OFFSET_8(BOOST_PP_VALUE) / 1000000UL == 4
+# define BOOST_PP_SLOT_TEMP_7 4
+# elif BOOST_PP_SLOT_OFFSET_8(BOOST_PP_VALUE) / 1000000UL == 5
+# define BOOST_PP_SLOT_TEMP_7 5
+# elif BOOST_PP_SLOT_OFFSET_8(BOOST_PP_VALUE) / 1000000UL == 6
+# define BOOST_PP_SLOT_TEMP_7 6
+# elif BOOST_PP_SLOT_OFFSET_8(BOOST_PP_VALUE) / 1000000UL == 7
+# define BOOST_PP_SLOT_TEMP_7 7
+# elif BOOST_PP_SLOT_OFFSET_8(BOOST_PP_VALUE) / 1000000UL == 8
+# define BOOST_PP_SLOT_TEMP_7 8
+# elif BOOST_PP_SLOT_OFFSET_8(BOOST_PP_VALUE) / 1000000UL == 9
+# define BOOST_PP_SLOT_TEMP_7 9
+# endif
+#
+# if BOOST_PP_SLOT_OFFSET_7(BOOST_PP_VALUE) / 100000UL == 0
+# define BOOST_PP_SLOT_TEMP_6 0
+# elif BOOST_PP_SLOT_OFFSET_7(BOOST_PP_VALUE) / 100000UL == 1
+# define BOOST_PP_SLOT_TEMP_6 1
+# elif BOOST_PP_SLOT_OFFSET_7(BOOST_PP_VALUE) / 100000UL == 2
+# define BOOST_PP_SLOT_TEMP_6 2
+# elif BOOST_PP_SLOT_OFFSET_7(BOOST_PP_VALUE) / 100000UL == 3
+# define BOOST_PP_SLOT_TEMP_6 3
+# elif BOOST_PP_SLOT_OFFSET_7(BOOST_PP_VALUE) / 100000UL == 4
+# define BOOST_PP_SLOT_TEMP_6 4
+# elif BOOST_PP_SLOT_OFFSET_7(BOOST_PP_VALUE) / 100000UL == 5
+# define BOOST_PP_SLOT_TEMP_6 5
+# elif BOOST_PP_SLOT_OFFSET_7(BOOST_PP_VALUE) / 100000UL == 6
+# define BOOST_PP_SLOT_TEMP_6 6
+# elif BOOST_PP_SLOT_OFFSET_7(BOOST_PP_VALUE) / 100000UL == 7
+# define BOOST_PP_SLOT_TEMP_6 7
+# elif BOOST_PP_SLOT_OFFSET_7(BOOST_PP_VALUE) / 100000UL == 8
+# define BOOST_PP_SLOT_TEMP_6 8
+# elif BOOST_PP_SLOT_OFFSET_7(BOOST_PP_VALUE) / 100000UL == 9
+# define BOOST_PP_SLOT_TEMP_6 9
+# endif
+#
+# if BOOST_PP_SLOT_OFFSET_6(BOOST_PP_VALUE) / 10000UL == 0
+# define BOOST_PP_SLOT_TEMP_5 0
+# elif BOOST_PP_SLOT_OFFSET_6(BOOST_PP_VALUE) / 10000UL == 1
+# define BOOST_PP_SLOT_TEMP_5 1
+# elif BOOST_PP_SLOT_OFFSET_6(BOOST_PP_VALUE) / 10000UL == 2
+# define BOOST_PP_SLOT_TEMP_5 2
+# elif BOOST_PP_SLOT_OFFSET_6(BOOST_PP_VALUE) / 10000UL == 3
+# define BOOST_PP_SLOT_TEMP_5 3
+# elif BOOST_PP_SLOT_OFFSET_6(BOOST_PP_VALUE) / 10000UL == 4
+# define BOOST_PP_SLOT_TEMP_5 4
+# elif BOOST_PP_SLOT_OFFSET_6(BOOST_PP_VALUE) / 10000UL == 5
+# define BOOST_PP_SLOT_TEMP_5 5
+# elif BOOST_PP_SLOT_OFFSET_6(BOOST_PP_VALUE) / 10000UL == 6
+# define BOOST_PP_SLOT_TEMP_5 6
+# elif BOOST_PP_SLOT_OFFSET_6(BOOST_PP_VALUE) / 10000UL == 7
+# define BOOST_PP_SLOT_TEMP_5 7
+# elif BOOST_PP_SLOT_OFFSET_6(BOOST_PP_VALUE) / 10000UL == 8
+# define BOOST_PP_SLOT_TEMP_5 8
+# elif BOOST_PP_SLOT_OFFSET_6(BOOST_PP_VALUE) / 10000UL == 9
+# define BOOST_PP_SLOT_TEMP_5 9
+# endif
+#
+# if BOOST_PP_SLOT_OFFSET_5(BOOST_PP_VALUE) / 1000UL == 0
+# define BOOST_PP_SLOT_TEMP_4 0
+# elif BOOST_PP_SLOT_OFFSET_5(BOOST_PP_VALUE) / 1000UL == 1
+# define BOOST_PP_SLOT_TEMP_4 1
+# elif BOOST_PP_SLOT_OFFSET_5(BOOST_PP_VALUE) / 1000UL == 2
+# define BOOST_PP_SLOT_TEMP_4 2
+# elif BOOST_PP_SLOT_OFFSET_5(BOOST_PP_VALUE) / 1000UL == 3
+# define BOOST_PP_SLOT_TEMP_4 3
+# elif BOOST_PP_SLOT_OFFSET_5(BOOST_PP_VALUE) / 1000UL == 4
+# define BOOST_PP_SLOT_TEMP_4 4
+# elif BOOST_PP_SLOT_OFFSET_5(BOOST_PP_VALUE) / 1000UL == 5
+# define BOOST_PP_SLOT_TEMP_4 5
+# elif BOOST_PP_SLOT_OFFSET_5(BOOST_PP_VALUE) / 1000UL == 6
+# define BOOST_PP_SLOT_TEMP_4 6
+# elif BOOST_PP_SLOT_OFFSET_5(BOOST_PP_VALUE) / 1000UL == 7
+# define BOOST_PP_SLOT_TEMP_4 7
+# elif BOOST_PP_SLOT_OFFSET_5(BOOST_PP_VALUE) / 1000UL == 8
+# define BOOST_PP_SLOT_TEMP_4 8
+# elif BOOST_PP_SLOT_OFFSET_5(BOOST_PP_VALUE) / 1000UL == 9
+# define BOOST_PP_SLOT_TEMP_4 9
+# endif
+#
+# if BOOST_PP_SLOT_OFFSET_4(BOOST_PP_VALUE) / 100UL == 0
+# define BOOST_PP_SLOT_TEMP_3 0
+# elif BOOST_PP_SLOT_OFFSET_4(BOOST_PP_VALUE) / 100UL == 1
+# define BOOST_PP_SLOT_TEMP_3 1
+# elif BOOST_PP_SLOT_OFFSET_4(BOOST_PP_VALUE) / 100UL == 2
+# define BOOST_PP_SLOT_TEMP_3 2
+# elif BOOST_PP_SLOT_OFFSET_4(BOOST_PP_VALUE) / 100UL == 3
+# define BOOST_PP_SLOT_TEMP_3 3
+# elif BOOST_PP_SLOT_OFFSET_4(BOOST_PP_VALUE) / 100UL == 4
+# define BOOST_PP_SLOT_TEMP_3 4
+# elif BOOST_PP_SLOT_OFFSET_4(BOOST_PP_VALUE) / 100UL == 5
+# define BOOST_PP_SLOT_TEMP_3 5
+# elif BOOST_PP_SLOT_OFFSET_4(BOOST_PP_VALUE) / 100UL == 6
+# define BOOST_PP_SLOT_TEMP_3 6
+# elif BOOST_PP_SLOT_OFFSET_4(BOOST_PP_VALUE) / 100UL == 7
+# define BOOST_PP_SLOT_TEMP_3 7
+# elif BOOST_PP_SLOT_OFFSET_4(BOOST_PP_VALUE) / 100UL == 8
+# define BOOST_PP_SLOT_TEMP_3 8
+# elif BOOST_PP_SLOT_OFFSET_4(BOOST_PP_VALUE) / 100UL == 9
+# define BOOST_PP_SLOT_TEMP_3 9
+# endif
+#
+# if BOOST_PP_SLOT_OFFSET_3(BOOST_PP_VALUE) / 10UL == 0
+# define BOOST_PP_SLOT_TEMP_2 0
+# elif BOOST_PP_SLOT_OFFSET_3(BOOST_PP_VALUE) / 10UL == 1
+# define BOOST_PP_SLOT_TEMP_2 1
+# elif BOOST_PP_SLOT_OFFSET_3(BOOST_PP_VALUE) / 10UL == 2
+# define BOOST_PP_SLOT_TEMP_2 2
+# elif BOOST_PP_SLOT_OFFSET_3(BOOST_PP_VALUE) / 10UL == 3
+# define BOOST_PP_SLOT_TEMP_2 3
+# elif BOOST_PP_SLOT_OFFSET_3(BOOST_PP_VALUE) / 10UL == 4
+# define BOOST_PP_SLOT_TEMP_2 4
+# elif BOOST_PP_SLOT_OFFSET_3(BOOST_PP_VALUE) / 10UL == 5
+# define BOOST_PP_SLOT_TEMP_2 5
+# elif BOOST_PP_SLOT_OFFSET_3(BOOST_PP_VALUE) / 10UL == 6
+# define BOOST_PP_SLOT_TEMP_2 6
+# elif BOOST_PP_SLOT_OFFSET_3(BOOST_PP_VALUE) / 10UL == 7
+# define BOOST_PP_SLOT_TEMP_2 7
+# elif BOOST_PP_SLOT_OFFSET_3(BOOST_PP_VALUE) / 10UL == 8
+# define BOOST_PP_SLOT_TEMP_2 8
+# elif BOOST_PP_SLOT_OFFSET_3(BOOST_PP_VALUE) / 10UL == 9
+# define BOOST_PP_SLOT_TEMP_2 9
+# endif
+#
+# if BOOST_PP_SLOT_OFFSET_2(BOOST_PP_VALUE) == 0
+# define BOOST_PP_SLOT_TEMP_1 0
+# elif BOOST_PP_SLOT_OFFSET_2(BOOST_PP_VALUE) == 1
+# define BOOST_PP_SLOT_TEMP_1 1
+# elif BOOST_PP_SLOT_OFFSET_2(BOOST_PP_VALUE) == 2
+# define BOOST_PP_SLOT_TEMP_1 2
+# elif BOOST_PP_SLOT_OFFSET_2(BOOST_PP_VALUE) == 3
+# define BOOST_PP_SLOT_TEMP_1 3
+# elif BOOST_PP_SLOT_OFFSET_2(BOOST_PP_VALUE) == 4
+# define BOOST_PP_SLOT_TEMP_1 4
+# elif BOOST_PP_SLOT_OFFSET_2(BOOST_PP_VALUE) == 5
+# define BOOST_PP_SLOT_TEMP_1 5
+# elif BOOST_PP_SLOT_OFFSET_2(BOOST_PP_VALUE) == 6
+# define BOOST_PP_SLOT_TEMP_1 6
+# elif BOOST_PP_SLOT_OFFSET_2(BOOST_PP_VALUE) == 7
+# define BOOST_PP_SLOT_TEMP_1 7
+# elif BOOST_PP_SLOT_OFFSET_2(BOOST_PP_VALUE) == 8
+# define BOOST_PP_SLOT_TEMP_1 8
+# elif BOOST_PP_SLOT_OFFSET_2(BOOST_PP_VALUE) == 9
+# define BOOST_PP_SLOT_TEMP_1 9
+# endif
+#
+# undef BOOST_PP_VALUE
diff --git a/third_party/boost/boost/preprocessor/slot/slot.hpp b/third_party/boost/boost/preprocessor/slot/slot.hpp
new file mode 100644
index 0000000..147b097
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/slot/slot.hpp
@@ -0,0 +1,32 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002.
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_SLOT_SLOT_HPP
+# define BOOST_PREPROCESSOR_SLOT_SLOT_HPP
+#
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/slot/detail/def.hpp>
+#
+# /* BOOST_PP_ASSIGN_SLOT */
+#
+# define BOOST_PP_ASSIGN_SLOT(i) BOOST_PP_CAT(BOOST_PP_ASSIGN_SLOT_, i)
+#
+# define BOOST_PP_ASSIGN_SLOT_1 <boost/preprocessor/slot/detail/slot1.hpp>
+# define BOOST_PP_ASSIGN_SLOT_2 <boost/preprocessor/slot/detail/slot2.hpp>
+# define BOOST_PP_ASSIGN_SLOT_3 <boost/preprocessor/slot/detail/slot3.hpp>
+# define BOOST_PP_ASSIGN_SLOT_4 <boost/preprocessor/slot/detail/slot4.hpp>
+# define BOOST_PP_ASSIGN_SLOT_5 <boost/preprocessor/slot/detail/slot5.hpp>
+#
+# /* BOOST_PP_SLOT */
+#
+# define BOOST_PP_SLOT(i) BOOST_PP_CAT(BOOST_PP_SLOT_, i)()
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/stringize.hpp b/third_party/boost/boost/preprocessor/stringize.hpp
new file mode 100644
index 0000000..64dd5fd
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/stringize.hpp
@@ -0,0 +1,33 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_STRINGIZE_HPP
+# define BOOST_PREPROCESSOR_STRINGIZE_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+#
+# /* BOOST_PP_STRINGIZE */
+#
+# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MSVC()
+# define BOOST_PP_STRINGIZE(text) BOOST_PP_STRINGIZE_A((text))
+# define BOOST_PP_STRINGIZE_A(arg) BOOST_PP_STRINGIZE_I arg
+# elif BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MWCC()
+# define BOOST_PP_STRINGIZE(text) BOOST_PP_STRINGIZE_OO((text))
+# define BOOST_PP_STRINGIZE_OO(par) BOOST_PP_STRINGIZE_I ## par
+# else
+# define BOOST_PP_STRINGIZE(text) BOOST_PP_STRINGIZE_I(text)
+# endif
+#
+# define BOOST_PP_STRINGIZE_I(text) #text
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/tuple/detail/is_single_return.hpp b/third_party/boost/boost/preprocessor/tuple/detail/is_single_return.hpp
new file mode 100644
index 0000000..02a4fb2
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/tuple/detail/is_single_return.hpp
@@ -0,0 +1,28 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Edward Diener 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) *
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_TUPLE_DETAIL_IS_SINGLE_RETURN_HPP
+# define BOOST_PREPROCESSOR_TUPLE_DETAIL_IS_SINGLE_RETURN_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+#
+# /* BOOST_PP_TUPLE_IS_SINGLE_RETURN */
+#
+# if BOOST_PP_VARIADICS && BOOST_PP_VARIADICS_MSVC
+# include <boost/preprocessor/control/iif.hpp>
+# include <boost/preprocessor/facilities/is_1.hpp>
+# include <boost/preprocessor/tuple/size.hpp>
+# define BOOST_PP_TUPLE_IS_SINGLE_RETURN(sr,nsr,tuple) \
+ BOOST_PP_IIF(BOOST_PP_IS_1(BOOST_PP_TUPLE_SIZE(tuple)),sr,nsr) \
+ /**/
+# endif /* BOOST_PP_VARIADICS && BOOST_PP_VARIADICS_MSVC */
+#
+# endif /* BOOST_PREPROCESSOR_TUPLE_DETAIL_IS_SINGLE_RETURN_HPP */
diff --git a/third_party/boost/boost/preprocessor/tuple/eat.hpp b/third_party/boost/boost/preprocessor/tuple/eat.hpp
new file mode 100644
index 0000000..7e8a100
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/tuple/eat.hpp
@@ -0,0 +1,115 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002-2011) */
+# /* Revised by Edward Diener (2011,2015) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_TUPLE_EAT_HPP
+# define BOOST_PREPROCESSOR_TUPLE_EAT_HPP
+#
+# include <boost/preprocessor/config/config.hpp>
+#
+# /* BOOST_PP_EAT */
+#
+# if BOOST_PP_VARIADICS
+# define BOOST_PP_EAT(...)
+# else
+# define BOOST_PP_EAT(x)
+# endif
+#
+# /* BOOST_PP_TUPLE_EAT */
+#
+# if BOOST_PP_VARIADICS
+# define BOOST_PP_TUPLE_EAT(size) BOOST_PP_EAT
+# else
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MWCC()
+# define BOOST_PP_TUPLE_EAT(size) BOOST_PP_TUPLE_EAT_I(size)
+# else
+# define BOOST_PP_TUPLE_EAT(size) BOOST_PP_TUPLE_EAT_OO((size))
+# define BOOST_PP_TUPLE_EAT_OO(par) BOOST_PP_TUPLE_EAT_I ## par
+# endif
+# define BOOST_PP_TUPLE_EAT_I(size) BOOST_PP_TUPLE_EAT_ ## size
+# endif
+#
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MWCC()
+# define BOOST_PP_TUPLE_EAT_N(size) BOOST_PP_TUPLE_EAT_N_I(size)
+# else
+# define BOOST_PP_TUPLE_EAT_N(size) BOOST_PP_TUPLE_EAT_N_OO((size))
+# define BOOST_PP_TUPLE_EAT_N_OO(par) BOOST_PP_TUPLE_EAT_N_I ## par
+# endif
+# define BOOST_PP_TUPLE_EAT_N_I(size) BOOST_PP_TUPLE_EAT_ ## size
+#
+# define BOOST_PP_TUPLE_EAT_1(e0)
+# define BOOST_PP_TUPLE_EAT_2(e0, e1)
+# define BOOST_PP_TUPLE_EAT_3(e0, e1, e2)
+# define BOOST_PP_TUPLE_EAT_4(e0, e1, e2, e3)
+# define BOOST_PP_TUPLE_EAT_5(e0, e1, e2, e3, e4)
+# define BOOST_PP_TUPLE_EAT_6(e0, e1, e2, e3, e4, e5)
+# define BOOST_PP_TUPLE_EAT_7(e0, e1, e2, e3, e4, e5, e6)
+# define BOOST_PP_TUPLE_EAT_8(e0, e1, e2, e3, e4, e5, e6, e7)
+# define BOOST_PP_TUPLE_EAT_9(e0, e1, e2, e3, e4, e5, e6, e7, e8)
+# define BOOST_PP_TUPLE_EAT_10(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9)
+# define BOOST_PP_TUPLE_EAT_11(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10)
+# define BOOST_PP_TUPLE_EAT_12(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11)
+# define BOOST_PP_TUPLE_EAT_13(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12)
+# define BOOST_PP_TUPLE_EAT_14(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13)
+# define BOOST_PP_TUPLE_EAT_15(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14)
+# define BOOST_PP_TUPLE_EAT_16(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15)
+# define BOOST_PP_TUPLE_EAT_17(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16)
+# define BOOST_PP_TUPLE_EAT_18(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17)
+# define BOOST_PP_TUPLE_EAT_19(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18)
+# define BOOST_PP_TUPLE_EAT_20(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19)
+# define BOOST_PP_TUPLE_EAT_21(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20)
+# define BOOST_PP_TUPLE_EAT_22(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21)
+# define BOOST_PP_TUPLE_EAT_23(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22)
+# define BOOST_PP_TUPLE_EAT_24(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23)
+# define BOOST_PP_TUPLE_EAT_25(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24)
+# define BOOST_PP_TUPLE_EAT_26(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25)
+# define BOOST_PP_TUPLE_EAT_27(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26)
+# define BOOST_PP_TUPLE_EAT_28(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27)
+# define BOOST_PP_TUPLE_EAT_29(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28)
+# define BOOST_PP_TUPLE_EAT_30(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29)
+# define BOOST_PP_TUPLE_EAT_31(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30)
+# define BOOST_PP_TUPLE_EAT_32(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31)
+# define BOOST_PP_TUPLE_EAT_33(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32)
+# define BOOST_PP_TUPLE_EAT_34(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33)
+# define BOOST_PP_TUPLE_EAT_35(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34)
+# define BOOST_PP_TUPLE_EAT_36(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35)
+# define BOOST_PP_TUPLE_EAT_37(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36)
+# define BOOST_PP_TUPLE_EAT_38(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37)
+# define BOOST_PP_TUPLE_EAT_39(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38)
+# define BOOST_PP_TUPLE_EAT_40(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39)
+# define BOOST_PP_TUPLE_EAT_41(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40)
+# define BOOST_PP_TUPLE_EAT_42(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41)
+# define BOOST_PP_TUPLE_EAT_43(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42)
+# define BOOST_PP_TUPLE_EAT_44(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43)
+# define BOOST_PP_TUPLE_EAT_45(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44)
+# define BOOST_PP_TUPLE_EAT_46(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45)
+# define BOOST_PP_TUPLE_EAT_47(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46)
+# define BOOST_PP_TUPLE_EAT_48(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47)
+# define BOOST_PP_TUPLE_EAT_49(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48)
+# define BOOST_PP_TUPLE_EAT_50(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49)
+# define BOOST_PP_TUPLE_EAT_51(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50)
+# define BOOST_PP_TUPLE_EAT_52(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51)
+# define BOOST_PP_TUPLE_EAT_53(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52)
+# define BOOST_PP_TUPLE_EAT_54(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53)
+# define BOOST_PP_TUPLE_EAT_55(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54)
+# define BOOST_PP_TUPLE_EAT_56(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55)
+# define BOOST_PP_TUPLE_EAT_57(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56)
+# define BOOST_PP_TUPLE_EAT_58(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57)
+# define BOOST_PP_TUPLE_EAT_59(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58)
+# define BOOST_PP_TUPLE_EAT_60(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59)
+# define BOOST_PP_TUPLE_EAT_61(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60)
+# define BOOST_PP_TUPLE_EAT_62(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61)
+# define BOOST_PP_TUPLE_EAT_63(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62)
+# define BOOST_PP_TUPLE_EAT_64(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63)
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/tuple/elem.hpp b/third_party/boost/boost/preprocessor/tuple/elem.hpp
new file mode 100644
index 0000000..88044d3
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/tuple/elem.hpp
@@ -0,0 +1,201 @@
+# /* Copyright (C) 2001
+# * Housemarque Oy
+# * http://www.housemarque.com
+# *
+# * Distributed under the Boost Software License, Version 1.0. (See
+# * accompanying file LICENSE_1_0.txt or copy at
+# * http://www.boost.org/LICENSE_1_0.txt)
+# */
+#
+# /* Revised by Paul Mensonides (2002-2011) */
+# /* Revised by Edward Diener (2011,2014) */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_TUPLE_ELEM_HPP
+# define BOOST_PREPROCESSOR_TUPLE_ELEM_HPP
+#
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/facilities/expand.hpp>
+# include <boost/preprocessor/facilities/overload.hpp>
+# include <boost/preprocessor/tuple/rem.hpp>
+# include <boost/preprocessor/variadic/elem.hpp>
+# include <boost/preprocessor/tuple/detail/is_single_return.hpp>
+#
+# if BOOST_PP_VARIADICS
+# if BOOST_PP_VARIADICS_MSVC
+# define BOOST_PP_TUPLE_ELEM(...) BOOST_PP_TUPLE_ELEM_I(BOOST_PP_OVERLOAD(BOOST_PP_TUPLE_ELEM_O_, __VA_ARGS__), (__VA_ARGS__))
+# define BOOST_PP_TUPLE_ELEM_I(m, args) BOOST_PP_TUPLE_ELEM_II(m, args)
+# define BOOST_PP_TUPLE_ELEM_II(m, args) BOOST_PP_CAT(m ## args,)
+/*
+ Use BOOST_PP_REM_CAT if it is a single element tuple ( which might be empty )
+ else use BOOST_PP_REM. This fixes a VC++ problem with an empty tuple and BOOST_PP_TUPLE_ELEM
+ functionality. See tuple_elem_bug_test.cxx.
+*/
+# define BOOST_PP_TUPLE_ELEM_O_2(n, tuple) \
+ BOOST_PP_VARIADIC_ELEM(n, BOOST_PP_EXPAND(BOOST_PP_TUPLE_IS_SINGLE_RETURN(BOOST_PP_REM_CAT,BOOST_PP_REM,tuple) tuple)) \
+ /**/
+# else
+# define BOOST_PP_TUPLE_ELEM(...) BOOST_PP_OVERLOAD(BOOST_PP_TUPLE_ELEM_O_, __VA_ARGS__)(__VA_ARGS__)
+# define BOOST_PP_TUPLE_ELEM_O_2(n, tuple) BOOST_PP_VARIADIC_ELEM(n, BOOST_PP_REM tuple)
+# endif
+# define BOOST_PP_TUPLE_ELEM_O_3(size, n, tuple) BOOST_PP_TUPLE_ELEM_O_2(n, tuple)
+# else
+# if BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MSVC()
+# define BOOST_PP_TUPLE_ELEM(size, n, tuple) BOOST_PP_TUPLE_ELEM_I(BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM_, n), BOOST_PP_CAT(BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM_E_, size), tuple))
+# define BOOST_PP_TUPLE_ELEM_I(m, args) BOOST_PP_TUPLE_ELEM_II(m, args)
+# define BOOST_PP_TUPLE_ELEM_II(m, args) BOOST_PP_CAT(m ## args,)
+# elif BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MWCC()
+# define BOOST_PP_TUPLE_ELEM(size, n, tuple) BOOST_PP_TUPLE_ELEM_I_OO((size, n, tuple))
+# define BOOST_PP_TUPLE_ELEM_I_OO(par) BOOST_PP_TUPLE_ELEM_I ## par
+# define BOOST_PP_TUPLE_ELEM_I(size, n, tuple) BOOST_PP_TUPLE_ELEM_II((n, BOOST_PP_TUPLE_ELEM_E_ ## size ## tuple))
+# define BOOST_PP_TUPLE_ELEM_II(par) BOOST_PP_TUPLE_ELEM_III_OO(par)
+# define BOOST_PP_TUPLE_ELEM_III_OO(par) BOOST_PP_TUPLE_ELEM_III ## par
+# define BOOST_PP_TUPLE_ELEM_III(n, etuple) BOOST_PP_TUPLE_ELEM_ ## n ## etuple
+# else
+# define BOOST_PP_TUPLE_ELEM(size, n, tuple) BOOST_PP_TUPLE_ELEM_I(BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM_, n) BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM_E_, size) tuple)
+# define BOOST_PP_TUPLE_ELEM_I(x) x
+# endif
+# define BOOST_PP_TUPLE_ELEM_E_1(e0) (e0, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_2(e0, e1) (e0, e1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_3(e0, e1, e2) (e0, e1, e2, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_4(e0, e1, e2, e3) (e0, e1, e2, e3, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_5(e0, e1, e2, e3, e4) (e0, e1, e2, e3, e4, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_6(e0, e1, e2, e3, e4, e5) (e0, e1, e2, e3, e4, e5, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_7(e0, e1, e2, e3, e4, e5, e6) (e0, e1, e2, e3, e4, e5, e6, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_8(e0, e1, e2, e3, e4, e5, e6, e7) (e0, e1, e2, e3, e4, e5, e6, e7, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_9(e0, e1, e2, e3, e4, e5, e6, e7, e8) (e0, e1, e2, e3, e4, e5, e6, e7, e8, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_10(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_11(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_12(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_13(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_14(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_15(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_16(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_17(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_18(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_19(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_20(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_21(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_22(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_23(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_24(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_25(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_26(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_27(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_28(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_29(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_30(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_31(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_32(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_33(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_34(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_35(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_36(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_37(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_38(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_39(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_40(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_41(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_42(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_43(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_44(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_45(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_46(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_47(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_48(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_49(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_50(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_51(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_52(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_53(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_54(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_55(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_56(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, ?, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_57(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, ?, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_58(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, ?, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_59(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, ?, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_60(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, ?, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_61(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, ?, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_62(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, ?, ?)
+# define BOOST_PP_TUPLE_ELEM_E_63(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62) (e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, ?)
+# define BOOST_PP_TUPLE_ELEM_E_64
+# define BOOST_PP_TUPLE_ELEM_0(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e0
+# define BOOST_PP_TUPLE_ELEM_1(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e1
+# define BOOST_PP_TUPLE_ELEM_2(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e2
+# define BOOST_PP_TUPLE_ELEM_3(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e3
+# define BOOST_PP_TUPLE_ELEM_4(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e4
+# define BOOST_PP_TUPLE_ELEM_5(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e5
+# define BOOST_PP_TUPLE_ELEM_6(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e6
+# define BOOST_PP_TUPLE_ELEM_7(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e7
+# define BOOST_PP_TUPLE_ELEM_8(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e8
+# define BOOST_PP_TUPLE_ELEM_9(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e9
+# define BOOST_PP_TUPLE_ELEM_10(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e10
+# define BOOST_PP_TUPLE_ELEM_11(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e11
+# define BOOST_PP_TUPLE_ELEM_12(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e12
+# define BOOST_PP_TUPLE_ELEM_13(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e13
+# define BOOST_PP_TUPLE_ELEM_14(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e14
+# define BOOST_PP_TUPLE_ELEM_15(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e15
+# define BOOST_PP_TUPLE_ELEM_16(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e16
+# define BOOST_PP_TUPLE_ELEM_17(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e17
+# define BOOST_PP_TUPLE_ELEM_18(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e18
+# define BOOST_PP_TUPLE_ELEM_19(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e19
+# define BOOST_PP_TUPLE_ELEM_20(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e20
+# define BOOST_PP_TUPLE_ELEM_21(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e21
+# define BOOST_PP_TUPLE_ELEM_22(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e22
+# define BOOST_PP_TUPLE_ELEM_23(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e23
+# define BOOST_PP_TUPLE_ELEM_24(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e24
+# define BOOST_PP_TUPLE_ELEM_25(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e25
+# define BOOST_PP_TUPLE_ELEM_26(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e26
+# define BOOST_PP_TUPLE_ELEM_27(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e27
+# define BOOST_PP_TUPLE_ELEM_28(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e28
+# define BOOST_PP_TUPLE_ELEM_29(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e29
+# define BOOST_PP_TUPLE_ELEM_30(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e30
+# define BOOST_PP_TUPLE_ELEM_31(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e31
+# define BOOST_PP_TUPLE_ELEM_32(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e32
+# define BOOST_PP_TUPLE_ELEM_33(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e33
+# define BOOST_PP_TUPLE_ELEM_34(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e34
+# define BOOST_PP_TUPLE_ELEM_35(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e35
+# define BOOST_PP_TUPLE_ELEM_36(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e36
+# define BOOST_PP_TUPLE_ELEM_37(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e37
+# define BOOST_PP_TUPLE_ELEM_38(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e38
+# define BOOST_PP_TUPLE_ELEM_39(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e39
+# define BOOST_PP_TUPLE_ELEM_40(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e40
+# define BOOST_PP_TUPLE_ELEM_41(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e41
+# define BOOST_PP_TUPLE_ELEM_42(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e42
+# define BOOST_PP_TUPLE_ELEM_43(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e43
+# define BOOST_PP_TUPLE_ELEM_44(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e44
+# define BOOST_PP_TUPLE_ELEM_45(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e45
+# define BOOST_PP_TUPLE_ELEM_46(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e46
+# define BOOST_PP_TUPLE_ELEM_47(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e47
+# define BOOST_PP_TUPLE_ELEM_48(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e48
+# define BOOST_PP_TUPLE_ELEM_49(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e49
+# define BOOST_PP_TUPLE_ELEM_50(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e50
+# define BOOST_PP_TUPLE_ELEM_51(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e51
+# define BOOST_PP_TUPLE_ELEM_52(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e52
+# define BOOST_PP_TUPLE_ELEM_53(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e53
+# define BOOST_PP_TUPLE_ELEM_54(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e54
+# define BOOST_PP_TUPLE_ELEM_55(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e55
+# define BOOST_PP_TUPLE_ELEM_56(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e56
+# define BOOST_PP_TUPLE_ELEM_57(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e57
+# define BOOST_PP_TUPLE_ELEM_58(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e58
+# define BOOST_PP_TUPLE_ELEM_59(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e59
+# define BOOST_PP_TUPLE_ELEM_60(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e60
+# define BOOST_PP_TUPLE_ELEM_61(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e61
+# define BOOST_PP_TUPLE_ELEM_62(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e62
+# define BOOST_PP_TUPLE_ELEM_63(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e63
+# endif
+#
+# /* directly used elsewhere in Boost... */
+#
+# define BOOST_PP_TUPLE_ELEM_1_0(a) a
+#
+# define BOOST_PP_TUPLE_ELEM_2_0(a, b) a
+# define BOOST_PP_TUPLE_ELEM_2_1(a, b) b
+#
+# define BOOST_PP_TUPLE_ELEM_3_0(a, b, c) a
+# define BOOST_PP_TUPLE_ELEM_3_1(a, b, c) b
+# define BOOST_PP_TUPLE_ELEM_3_2(a, b, c) c
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/tuple/rem.hpp b/third_party/boost/boost/preprocessor/tuple/rem.hpp
new file mode 100644
index 0000000..c934447
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/tuple/rem.hpp
@@ -0,0 +1,149 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Paul Mensonides 2002-2011. *
+# * (C) Copyright Edward Diener 2011,2013. *
+# * Distributed under the Boost Software License, Version 1.0. (See *
+# * accompanying file LICENSE_1_0.txt or copy at *
+# * http://www.boost.org/LICENSE_1_0.txt) *
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_TUPLE_REM_HPP
+# define BOOST_PREPROCESSOR_TUPLE_REM_HPP
+#
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/config/config.hpp>
+# include <boost/preprocessor/facilities/expand.hpp>
+# include <boost/preprocessor/facilities/overload.hpp>
+# include <boost/preprocessor/tuple/detail/is_single_return.hpp>
+#
+# /* BOOST_PP_REM */
+#
+# if BOOST_PP_VARIADICS
+# if BOOST_PP_VARIADICS_MSVC
+ /* To be used internally when __VA_ARGS__ could be empty ( or is a single element ) */
+# define BOOST_PP_REM_CAT(...) BOOST_PP_CAT(__VA_ARGS__,)
+# endif
+# define BOOST_PP_REM(...) __VA_ARGS__
+# else
+# define BOOST_PP_REM(x) x
+# endif
+#
+# /* BOOST_PP_TUPLE_REM */
+#
+/*
+ VC++8.0 cannot handle the variadic version of BOOST_PP_TUPLE_REM(size)
+*/
+# if BOOST_PP_VARIADICS && !(BOOST_PP_VARIADICS_MSVC && _MSC_VER <= 1400)
+# if BOOST_PP_VARIADICS_MSVC
+ /* To be used internally when the size could be 0 ( or 1 ) */
+# define BOOST_PP_TUPLE_REM_CAT(size) BOOST_PP_REM_CAT
+# endif
+# define BOOST_PP_TUPLE_REM(size) BOOST_PP_REM
+# else
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MWCC()
+# define BOOST_PP_TUPLE_REM(size) BOOST_PP_TUPLE_REM_I(size)
+# else
+# define BOOST_PP_TUPLE_REM(size) BOOST_PP_TUPLE_REM_OO((size))
+# define BOOST_PP_TUPLE_REM_OO(par) BOOST_PP_TUPLE_REM_I ## par
+# endif
+# define BOOST_PP_TUPLE_REM_I(size) BOOST_PP_TUPLE_REM_ ## size
+# endif
+# define BOOST_PP_TUPLE_REM_0()
+# define BOOST_PP_TUPLE_REM_1(e0) e0
+# define BOOST_PP_TUPLE_REM_2(e0, e1) e0, e1
+# define BOOST_PP_TUPLE_REM_3(e0, e1, e2) e0, e1, e2
+# define BOOST_PP_TUPLE_REM_4(e0, e1, e2, e3) e0, e1, e2, e3
+# define BOOST_PP_TUPLE_REM_5(e0, e1, e2, e3, e4) e0, e1, e2, e3, e4
+# define BOOST_PP_TUPLE_REM_6(e0, e1, e2, e3, e4, e5) e0, e1, e2, e3, e4, e5
+# define BOOST_PP_TUPLE_REM_7(e0, e1, e2, e3, e4, e5, e6) e0, e1, e2, e3, e4, e5, e6
+# define BOOST_PP_TUPLE_REM_8(e0, e1, e2, e3, e4, e5, e6, e7) e0, e1, e2, e3, e4, e5, e6, e7
+# define BOOST_PP_TUPLE_REM_9(e0, e1, e2, e3, e4, e5, e6, e7, e8) e0, e1, e2, e3, e4, e5, e6, e7, e8
+# define BOOST_PP_TUPLE_REM_10(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9
+# define BOOST_PP_TUPLE_REM_11(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10
+# define BOOST_PP_TUPLE_REM_12(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11
+# define BOOST_PP_TUPLE_REM_13(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12
+# define BOOST_PP_TUPLE_REM_14(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13
+# define BOOST_PP_TUPLE_REM_15(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14
+# define BOOST_PP_TUPLE_REM_16(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15
+# define BOOST_PP_TUPLE_REM_17(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16
+# define BOOST_PP_TUPLE_REM_18(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17
+# define BOOST_PP_TUPLE_REM_19(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18
+# define BOOST_PP_TUPLE_REM_20(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19
+# define BOOST_PP_TUPLE_REM_21(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20
+# define BOOST_PP_TUPLE_REM_22(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21
+# define BOOST_PP_TUPLE_REM_23(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22
+# define BOOST_PP_TUPLE_REM_24(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23
+# define BOOST_PP_TUPLE_REM_25(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24
+# define BOOST_PP_TUPLE_REM_26(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25
+# define BOOST_PP_TUPLE_REM_27(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26
+# define BOOST_PP_TUPLE_REM_28(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27
+# define BOOST_PP_TUPLE_REM_29(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28
+# define BOOST_PP_TUPLE_REM_30(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29
+# define BOOST_PP_TUPLE_REM_31(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30
+# define BOOST_PP_TUPLE_REM_32(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31
+# define BOOST_PP_TUPLE_REM_33(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32
+# define BOOST_PP_TUPLE_REM_34(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33
+# define BOOST_PP_TUPLE_REM_35(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34
+# define BOOST_PP_TUPLE_REM_36(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35
+# define BOOST_PP_TUPLE_REM_37(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36
+# define BOOST_PP_TUPLE_REM_38(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37
+# define BOOST_PP_TUPLE_REM_39(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38
+# define BOOST_PP_TUPLE_REM_40(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39
+# define BOOST_PP_TUPLE_REM_41(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40
+# define BOOST_PP_TUPLE_REM_42(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41
+# define BOOST_PP_TUPLE_REM_43(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42
+# define BOOST_PP_TUPLE_REM_44(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43
+# define BOOST_PP_TUPLE_REM_45(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44
+# define BOOST_PP_TUPLE_REM_46(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45
+# define BOOST_PP_TUPLE_REM_47(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46
+# define BOOST_PP_TUPLE_REM_48(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47
+# define BOOST_PP_TUPLE_REM_49(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48
+# define BOOST_PP_TUPLE_REM_50(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49
+# define BOOST_PP_TUPLE_REM_51(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50
+# define BOOST_PP_TUPLE_REM_52(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51
+# define BOOST_PP_TUPLE_REM_53(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52
+# define BOOST_PP_TUPLE_REM_54(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53
+# define BOOST_PP_TUPLE_REM_55(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54
+# define BOOST_PP_TUPLE_REM_56(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55
+# define BOOST_PP_TUPLE_REM_57(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56
+# define BOOST_PP_TUPLE_REM_58(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57
+# define BOOST_PP_TUPLE_REM_59(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58
+# define BOOST_PP_TUPLE_REM_60(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59
+# define BOOST_PP_TUPLE_REM_61(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60
+# define BOOST_PP_TUPLE_REM_62(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61
+# define BOOST_PP_TUPLE_REM_63(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62
+# define BOOST_PP_TUPLE_REM_64(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63) e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63
+#
+# /* BOOST_PP_TUPLE_REM_CTOR */
+#
+# if BOOST_PP_VARIADICS
+# if BOOST_PP_VARIADICS_MSVC
+# define BOOST_PP_TUPLE_REM_CTOR(...) BOOST_PP_TUPLE_REM_CTOR_I(BOOST_PP_OVERLOAD(BOOST_PP_TUPLE_REM_CTOR_O_, __VA_ARGS__), (__VA_ARGS__))
+# define BOOST_PP_TUPLE_REM_CTOR_I(m, args) BOOST_PP_TUPLE_REM_CTOR_II(m, args)
+# define BOOST_PP_TUPLE_REM_CTOR_II(m, args) BOOST_PP_CAT(m ## args,)
+# define BOOST_PP_TUPLE_REM_CTOR_O_1(tuple) BOOST_PP_EXPAND(BOOST_PP_TUPLE_IS_SINGLE_RETURN(BOOST_PP_REM_CAT,BOOST_PP_REM,tuple) tuple)
+# else
+# define BOOST_PP_TUPLE_REM_CTOR(...) BOOST_PP_OVERLOAD(BOOST_PP_TUPLE_REM_CTOR_O_, __VA_ARGS__)(__VA_ARGS__)
+# define BOOST_PP_TUPLE_REM_CTOR_O_1(tuple) BOOST_PP_REM tuple
+# endif
+# define BOOST_PP_TUPLE_REM_CTOR_O_2(size, tuple) BOOST_PP_TUPLE_REM_CTOR_O_1(tuple)
+# else
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_EDG()
+# define BOOST_PP_TUPLE_REM_CTOR(size, tuple) BOOST_PP_TUPLE_REM_CTOR_I(BOOST_PP_TUPLE_REM(size), tuple)
+# else
+# define BOOST_PP_TUPLE_REM_CTOR(size, tuple) BOOST_PP_TUPLE_REM_CTOR_D(size, tuple)
+# define BOOST_PP_TUPLE_REM_CTOR_D(size, tuple) BOOST_PP_TUPLE_REM_CTOR_I(BOOST_PP_TUPLE_REM(size), tuple)
+# endif
+# if ~BOOST_PP_CONFIG_FLAGS() & BOOST_PP_CONFIG_MWCC()
+# define BOOST_PP_TUPLE_REM_CTOR_I(ext, tuple) ext tuple
+# else
+# define BOOST_PP_TUPLE_REM_CTOR_I(ext, tuple) BOOST_PP_TUPLE_REM_CTOR_OO((ext, tuple))
+# define BOOST_PP_TUPLE_REM_CTOR_OO(par) BOOST_PP_TUPLE_REM_CTOR_II ## par
+# define BOOST_PP_TUPLE_REM_CTOR_II(ext, tuple) ext ## tuple
+# endif
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/variadic/elem.hpp b/third_party/boost/boost/preprocessor/variadic/elem.hpp
new file mode 100644
index 0000000..be38a94
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/variadic/elem.hpp
@@ -0,0 +1,94 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Edward Diener 2011. *
+# * (C) Copyright Paul Mensonides 2011. *
+# * Distributed under the Boost Software License, Version 1.0. (See *
+# * accompanying file LICENSE_1_0.txt or copy at *
+# * http://www.boost.org/LICENSE_1_0.txt) *
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_VARIADIC_ELEM_HPP
+# define BOOST_PREPROCESSOR_VARIADIC_ELEM_HPP
+#
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/config/config.hpp>
+#
+# /* BOOST_PP_VARIADIC_ELEM */
+#
+# if BOOST_PP_VARIADICS
+# if BOOST_PP_VARIADICS_MSVC
+# define BOOST_PP_VARIADIC_ELEM(n, ...) BOOST_PP_VARIADIC_ELEM_I(n,__VA_ARGS__)
+# define BOOST_PP_VARIADIC_ELEM_I(n, ...) BOOST_PP_CAT(BOOST_PP_CAT(BOOST_PP_VARIADIC_ELEM_, n)(__VA_ARGS__,),)
+# else
+# define BOOST_PP_VARIADIC_ELEM(n, ...) BOOST_PP_CAT(BOOST_PP_VARIADIC_ELEM_, n)(__VA_ARGS__,)
+# endif
+# define BOOST_PP_VARIADIC_ELEM_0(e0, ...) e0
+# define BOOST_PP_VARIADIC_ELEM_1(e0, e1, ...) e1
+# define BOOST_PP_VARIADIC_ELEM_2(e0, e1, e2, ...) e2
+# define BOOST_PP_VARIADIC_ELEM_3(e0, e1, e2, e3, ...) e3
+# define BOOST_PP_VARIADIC_ELEM_4(e0, e1, e2, e3, e4, ...) e4
+# define BOOST_PP_VARIADIC_ELEM_5(e0, e1, e2, e3, e4, e5, ...) e5
+# define BOOST_PP_VARIADIC_ELEM_6(e0, e1, e2, e3, e4, e5, e6, ...) e6
+# define BOOST_PP_VARIADIC_ELEM_7(e0, e1, e2, e3, e4, e5, e6, e7, ...) e7
+# define BOOST_PP_VARIADIC_ELEM_8(e0, e1, e2, e3, e4, e5, e6, e7, e8, ...) e8
+# define BOOST_PP_VARIADIC_ELEM_9(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, ...) e9
+# define BOOST_PP_VARIADIC_ELEM_10(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, ...) e10
+# define BOOST_PP_VARIADIC_ELEM_11(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, ...) e11
+# define BOOST_PP_VARIADIC_ELEM_12(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, ...) e12
+# define BOOST_PP_VARIADIC_ELEM_13(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, ...) e13
+# define BOOST_PP_VARIADIC_ELEM_14(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, ...) e14
+# define BOOST_PP_VARIADIC_ELEM_15(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, ...) e15
+# define BOOST_PP_VARIADIC_ELEM_16(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, ...) e16
+# define BOOST_PP_VARIADIC_ELEM_17(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, ...) e17
+# define BOOST_PP_VARIADIC_ELEM_18(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, ...) e18
+# define BOOST_PP_VARIADIC_ELEM_19(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, ...) e19
+# define BOOST_PP_VARIADIC_ELEM_20(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, ...) e20
+# define BOOST_PP_VARIADIC_ELEM_21(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, ...) e21
+# define BOOST_PP_VARIADIC_ELEM_22(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, ...) e22
+# define BOOST_PP_VARIADIC_ELEM_23(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, ...) e23
+# define BOOST_PP_VARIADIC_ELEM_24(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, ...) e24
+# define BOOST_PP_VARIADIC_ELEM_25(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, ...) e25
+# define BOOST_PP_VARIADIC_ELEM_26(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, ...) e26
+# define BOOST_PP_VARIADIC_ELEM_27(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, ...) e27
+# define BOOST_PP_VARIADIC_ELEM_28(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, ...) e28
+# define BOOST_PP_VARIADIC_ELEM_29(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, ...) e29
+# define BOOST_PP_VARIADIC_ELEM_30(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, ...) e30
+# define BOOST_PP_VARIADIC_ELEM_31(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, ...) e31
+# define BOOST_PP_VARIADIC_ELEM_32(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, ...) e32
+# define BOOST_PP_VARIADIC_ELEM_33(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, ...) e33
+# define BOOST_PP_VARIADIC_ELEM_34(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, ...) e34
+# define BOOST_PP_VARIADIC_ELEM_35(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, ...) e35
+# define BOOST_PP_VARIADIC_ELEM_36(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, ...) e36
+# define BOOST_PP_VARIADIC_ELEM_37(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, ...) e37
+# define BOOST_PP_VARIADIC_ELEM_38(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, ...) e38
+# define BOOST_PP_VARIADIC_ELEM_39(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, ...) e39
+# define BOOST_PP_VARIADIC_ELEM_40(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, ...) e40
+# define BOOST_PP_VARIADIC_ELEM_41(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, ...) e41
+# define BOOST_PP_VARIADIC_ELEM_42(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, ...) e42
+# define BOOST_PP_VARIADIC_ELEM_43(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, ...) e43
+# define BOOST_PP_VARIADIC_ELEM_44(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, ...) e44
+# define BOOST_PP_VARIADIC_ELEM_45(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, ...) e45
+# define BOOST_PP_VARIADIC_ELEM_46(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, ...) e46
+# define BOOST_PP_VARIADIC_ELEM_47(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, ...) e47
+# define BOOST_PP_VARIADIC_ELEM_48(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, ...) e48
+# define BOOST_PP_VARIADIC_ELEM_49(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, ...) e49
+# define BOOST_PP_VARIADIC_ELEM_50(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, ...) e50
+# define BOOST_PP_VARIADIC_ELEM_51(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, ...) e51
+# define BOOST_PP_VARIADIC_ELEM_52(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, ...) e52
+# define BOOST_PP_VARIADIC_ELEM_53(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, ...) e53
+# define BOOST_PP_VARIADIC_ELEM_54(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, ...) e54
+# define BOOST_PP_VARIADIC_ELEM_55(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, ...) e55
+# define BOOST_PP_VARIADIC_ELEM_56(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, ...) e56
+# define BOOST_PP_VARIADIC_ELEM_57(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, ...) e57
+# define BOOST_PP_VARIADIC_ELEM_58(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, ...) e58
+# define BOOST_PP_VARIADIC_ELEM_59(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, ...) e59
+# define BOOST_PP_VARIADIC_ELEM_60(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, ...) e60
+# define BOOST_PP_VARIADIC_ELEM_61(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, ...) e61
+# define BOOST_PP_VARIADIC_ELEM_62(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, ...) e62
+# define BOOST_PP_VARIADIC_ELEM_63(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63, ...) e63
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/preprocessor/variadic/size.hpp b/third_party/boost/boost/preprocessor/variadic/size.hpp
new file mode 100644
index 0000000..b92a5ff
--- /dev/null
+++ b/third_party/boost/boost/preprocessor/variadic/size.hpp
@@ -0,0 +1,30 @@
+# /* **************************************************************************
+# * *
+# * (C) Copyright Edward Diener 2011. *
+# * (C) Copyright Paul Mensonides 2011. *
+# * Distributed under the Boost Software License, Version 1.0. (See *
+# * accompanying file LICENSE_1_0.txt or copy at *
+# * http://www.boost.org/LICENSE_1_0.txt) *
+# * *
+# ************************************************************************** */
+#
+# /* See http://www.boost.org for most recent version. */
+#
+# ifndef BOOST_PREPROCESSOR_VARIADIC_SIZE_HPP
+# define BOOST_PREPROCESSOR_VARIADIC_SIZE_HPP
+#
+# include <boost/preprocessor/cat.hpp>
+# include <boost/preprocessor/config/config.hpp>
+#
+# /* BOOST_PP_VARIADIC_SIZE */
+#
+# if BOOST_PP_VARIADICS
+# if BOOST_PP_VARIADICS_MSVC
+# define BOOST_PP_VARIADIC_SIZE(...) BOOST_PP_CAT(BOOST_PP_VARIADIC_SIZE_I(__VA_ARGS__, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,),)
+# else
+# define BOOST_PP_VARIADIC_SIZE(...) BOOST_PP_VARIADIC_SIZE_I(__VA_ARGS__, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,)
+# endif
+# define BOOST_PP_VARIADIC_SIZE_I(e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31, e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46, e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61, e62, e63, size, ...) size
+# endif
+#
+# endif
diff --git a/third_party/boost/boost/ref.hpp b/third_party/boost/boost/ref.hpp
new file mode 100644
index 0000000..17b56ec
--- /dev/null
+++ b/third_party/boost/boost/ref.hpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2014 Glen Fernandes
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_REF_HPP
+#define BOOST_REF_HPP
+
+// The header file at this path is deprecated;
+// use boost/core/ref.hpp instead.
+
+#include <boost/core/ref.hpp>
+
+#endif
diff --git a/third_party/boost/boost/scoped_ptr.hpp b/third_party/boost/boost/scoped_ptr.hpp
new file mode 100644
index 0000000..cb916da
--- /dev/null
+++ b/third_party/boost/boost/scoped_ptr.hpp
@@ -0,0 +1,16 @@
+#ifndef BOOST_SCOPED_PTR_HPP_INCLUDED
+#define BOOST_SCOPED_PTR_HPP_INCLUDED
+
+// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
+// Copyright (c) 2001, 2002 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org/libs/smart_ptr/scoped_ptr.htm
+//
+
+#include <boost/smart_ptr/scoped_ptr.hpp>
+
+#endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED
diff --git a/third_party/boost/boost/shared_ptr.hpp b/third_party/boost/boost/shared_ptr.hpp
new file mode 100644
index 0000000..d31978c
--- /dev/null
+++ b/third_party/boost/boost/shared_ptr.hpp
@@ -0,0 +1,19 @@
+#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
+#define BOOST_SHARED_PTR_HPP_INCLUDED
+
+//
+// shared_ptr.hpp
+//
+// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
+// Copyright (c) 2001-2008 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
+//
+
+#include <boost/smart_ptr/shared_ptr.hpp>
+
+#endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED
diff --git a/third_party/boost/boost/signals2/connection.hpp b/third_party/boost/boost/signals2/connection.hpp
new file mode 100644
index 0000000..bc03789
--- /dev/null
+++ b/third_party/boost/boost/signals2/connection.hpp
@@ -0,0 +1,374 @@
+/*
+ boost::signals2::connection provides a handle to a signal/slot connection.
+
+ Author: Frank Mori Hess <fmhess@users.sourceforge.net>
+ Begin: 2007-01-23
+*/
+// Copyright Frank Mori Hess 2007-2008.
+// Distributed under the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/signals2 for library home page.
+
+#ifndef BOOST_SIGNALS2_CONNECTION_HPP
+#define BOOST_SIGNALS2_CONNECTION_HPP
+
+#include <boost/function.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/signals2/detail/auto_buffer.hpp>
+#include <boost/signals2/detail/null_output_iterator.hpp>
+#include <boost/signals2/detail/unique_lock.hpp>
+#include <boost/signals2/slot.hpp>
+#include <boost/weak_ptr.hpp>
+
+namespace boost
+{
+ namespace signals2
+ {
+ inline void null_deleter(const void*) {}
+ namespace detail
+ {
+ // This lock maintains a list of shared_ptr<void>
+ // which will be destroyed only after the lock
+ // has released its mutex. Used to garbage
+ // collect disconnected slots
+ template<typename Mutex>
+ class garbage_collecting_lock: public noncopyable
+ {
+ public:
+ garbage_collecting_lock(Mutex &m):
+ lock(m)
+ {}
+ void add_trash(const shared_ptr<void> &piece_of_trash)
+ {
+ garbage.push_back(piece_of_trash);
+ }
+ private:
+ // garbage must be declared before lock
+ // to insure it is destroyed after lock is
+ // destroyed.
+ auto_buffer<shared_ptr<void>, store_n_objects<10> > garbage;
+ unique_lock<Mutex> lock;
+ };
+
+ class connection_body_base
+ {
+ public:
+ connection_body_base():
+ _connected(true), m_slot_refcount(1)
+ {
+ }
+ virtual ~connection_body_base() {}
+ void disconnect()
+ {
+ garbage_collecting_lock<connection_body_base> local_lock(*this);
+ nolock_disconnect(local_lock);
+ }
+ template<typename Mutex>
+ void nolock_disconnect(garbage_collecting_lock<Mutex> &lock_arg) const
+ {
+ if(_connected)
+ {
+ _connected = false;
+ dec_slot_refcount(lock_arg);
+ }
+ }
+ virtual bool connected() const = 0;
+ shared_ptr<void> get_blocker()
+ {
+ unique_lock<connection_body_base> local_lock(*this);
+ shared_ptr<void> blocker = _weak_blocker.lock();
+ if(blocker == shared_ptr<void>())
+ {
+ blocker.reset(this, &null_deleter);
+ _weak_blocker = blocker;
+ }
+ return blocker;
+ }
+ bool blocked() const
+ {
+ return !_weak_blocker.expired();
+ }
+ bool nolock_nograb_blocked() const
+ {
+ return nolock_nograb_connected() == false || blocked();
+ }
+ bool nolock_nograb_connected() const {return _connected;}
+ // expose part of Lockable concept of mutex
+ virtual void lock() = 0;
+ virtual void unlock() = 0;
+
+ // Slot refcount should be incremented while
+ // a signal invocation is using the slot, in order
+ // to prevent slot from being destroyed mid-invocation.
+ // garbage_collecting_lock parameter enforces
+ // the existance of a lock before this
+ // method is called
+ template<typename Mutex>
+ void inc_slot_refcount(const garbage_collecting_lock<Mutex> &)
+ {
+ BOOST_ASSERT(m_slot_refcount != 0);
+ ++m_slot_refcount;
+ }
+ // if slot refcount decrements to zero due to this call,
+ // it puts a
+ // shared_ptr to the slot in the garbage collecting lock,
+ // which will destroy the slot only after it unlocks.
+ template<typename Mutex>
+ void dec_slot_refcount(garbage_collecting_lock<Mutex> &lock_arg) const
+ {
+ BOOST_ASSERT(m_slot_refcount != 0);
+ if(--m_slot_refcount == 0)
+ {
+ lock_arg.add_trash(release_slot());
+ }
+ }
+
+ protected:
+ virtual shared_ptr<void> release_slot() const = 0;
+
+ weak_ptr<void> _weak_blocker;
+ private:
+ mutable bool _connected;
+ mutable unsigned m_slot_refcount;
+ };
+
+ template<typename GroupKey, typename SlotType, typename Mutex>
+ class connection_body: public connection_body_base
+ {
+ public:
+ typedef Mutex mutex_type;
+ connection_body(const SlotType &slot_in, const boost::shared_ptr<mutex_type> &signal_mutex):
+ m_slot(new SlotType(slot_in)), _mutex(signal_mutex)
+ {
+ }
+ virtual ~connection_body() {}
+ virtual bool connected() const
+ {
+ garbage_collecting_lock<mutex_type> local_lock(*_mutex);
+ nolock_grab_tracked_objects(local_lock, detail::null_output_iterator());
+ return nolock_nograb_connected();
+ }
+ const GroupKey& group_key() const {return _group_key;}
+ void set_group_key(const GroupKey &key) {_group_key = key;}
+ template<typename M>
+ void disconnect_expired_slot(garbage_collecting_lock<M> &lock_arg)
+ {
+ if(!m_slot) return;
+ bool expired = slot().expired();
+ if(expired == true)
+ {
+ nolock_disconnect(lock_arg);
+ }
+ }
+ template<typename M, typename OutputIterator>
+ void nolock_grab_tracked_objects(garbage_collecting_lock<M> &lock_arg,
+ OutputIterator inserter) const
+ {
+ if(!m_slot) return;
+ slot_base::tracked_container_type::const_iterator it;
+ for(it = slot().tracked_objects().begin();
+ it != slot().tracked_objects().end();
+ ++it)
+ {
+ void_shared_ptr_variant locked_object
+ (
+ apply_visitor
+ (
+ detail::lock_weak_ptr_visitor(),
+ *it
+ )
+ );
+ if(apply_visitor(detail::expired_weak_ptr_visitor(), *it))
+ {
+ nolock_disconnect(lock_arg);
+ return;
+ }
+ *inserter++ = locked_object;
+ }
+ }
+ // expose Lockable concept of mutex
+ virtual void lock()
+ {
+ _mutex->lock();
+ }
+ virtual void unlock()
+ {
+ _mutex->unlock();
+ }
+ SlotType &slot()
+ {
+ return *m_slot;
+ }
+ const SlotType &slot() const
+ {
+ return *m_slot;
+ }
+ protected:
+ virtual shared_ptr<void> release_slot() const
+ {
+
+ shared_ptr<void> released_slot = m_slot;
+ m_slot.reset();
+ return released_slot;
+ }
+ private:
+ mutable boost::shared_ptr<SlotType> m_slot;
+ const boost::shared_ptr<mutex_type> _mutex;
+ GroupKey _group_key;
+ };
+ }
+
+ class shared_connection_block;
+
+ class connection
+ {
+ public:
+ friend class shared_connection_block;
+
+ connection() {}
+ connection(const connection &other): _weak_connection_body(other._weak_connection_body)
+ {}
+ connection(const boost::weak_ptr<detail::connection_body_base> &connectionBody):
+ _weak_connection_body(connectionBody)
+ {}
+
+ // move support
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ connection(connection && other): _weak_connection_body(std::move(other._weak_connection_body))
+ {
+ // make sure other is reset, in case it is a scoped_connection (so it
+ // won't disconnect on destruction after being moved away from).
+ other._weak_connection_body.reset();
+ }
+ connection & operator=(connection && other)
+ {
+ if(&other == this) return *this;
+ _weak_connection_body = std::move(other._weak_connection_body);
+ // make sure other is reset, in case it is a scoped_connection (so it
+ // won't disconnect on destruction after being moved away from).
+ other._weak_connection_body.reset();
+ return *this;
+ }
+#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ connection & operator=(const connection & other)
+ {
+ if(&other == this) return *this;
+ _weak_connection_body = other._weak_connection_body;
+ return *this;
+ }
+
+ ~connection() {}
+ void disconnect() const
+ {
+ boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock());
+ if(connectionBody == 0) return;
+ connectionBody->disconnect();
+ }
+ bool connected() const
+ {
+ boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock());
+ if(connectionBody == 0) return false;
+ return connectionBody->connected();
+ }
+ bool blocked() const
+ {
+ boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock());
+ if(connectionBody == 0) return true;
+ return connectionBody->blocked();
+ }
+ bool operator==(const connection& other) const
+ {
+ boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock());
+ boost::shared_ptr<detail::connection_body_base> otherConnectionBody(other._weak_connection_body.lock());
+ return connectionBody == otherConnectionBody;
+ }
+ bool operator!=(const connection& other) const
+ {
+ return !(*this == other);
+ }
+ bool operator<(const connection& other) const
+ {
+ boost::shared_ptr<detail::connection_body_base> connectionBody(_weak_connection_body.lock());
+ boost::shared_ptr<detail::connection_body_base> otherConnectionBody(other._weak_connection_body.lock());
+ return connectionBody < otherConnectionBody;
+ }
+ void swap(connection &other)
+ {
+ using std::swap;
+ swap(_weak_connection_body, other._weak_connection_body);
+ }
+ protected:
+
+ boost::weak_ptr<detail::connection_body_base> _weak_connection_body;
+ };
+ inline void swap(connection &conn1, connection &conn2)
+ {
+ conn1.swap(conn2);
+ }
+
+ class scoped_connection: public connection
+ {
+ public:
+ scoped_connection() {}
+ scoped_connection(const connection &other):
+ connection(other)
+ {}
+ ~scoped_connection()
+ {
+ disconnect();
+ }
+ scoped_connection& operator=(const connection &rhs)
+ {
+ disconnect();
+ connection::operator=(rhs);
+ return *this;
+ }
+
+ // move support
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ scoped_connection(scoped_connection && other): connection(std::move(other))
+ {
+ }
+ scoped_connection(connection && other): connection(std::move(other))
+ {
+ }
+ scoped_connection & operator=(scoped_connection && other)
+ {
+ if(&other == this) return *this;
+ disconnect();
+ connection::operator=(std::move(other));
+ return *this;
+ }
+ scoped_connection & operator=(connection && other)
+ {
+ if(&other == this) return *this;
+ disconnect();
+ connection::operator=(std::move(other));
+ return *this;
+ }
+#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+ connection release()
+ {
+ connection conn(_weak_connection_body);
+ _weak_connection_body.reset();
+ return conn;
+ }
+ private:
+ scoped_connection(const scoped_connection &other);
+ scoped_connection& operator=(const scoped_connection &rhs);
+ };
+ // Sun 5.9 compiler doesn't find the swap for base connection class when
+ // arguments are scoped_connection, so we provide this explicitly.
+ inline void swap(scoped_connection &conn1, scoped_connection &conn2)
+ {
+ conn1.swap(conn2);
+ }
+ }
+}
+
+#endif // BOOST_SIGNALS2_CONNECTION_HPP
diff --git a/third_party/boost/boost/signals2/detail/auto_buffer.hpp b/third_party/boost/boost/signals2/detail/auto_buffer.hpp
new file mode 100644
index 0000000..0970d3d
--- /dev/null
+++ b/third_party/boost/boost/signals2/detail/auto_buffer.hpp
@@ -0,0 +1,1137 @@
+// Copyright Thorsten Ottosen, 2009.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_SIGNALS2_DETAIL_AUTO_BUFFER_HPP_25_02_2009
+#define BOOST_SIGNALS2_DETAIL_AUTO_BUFFER_HPP_25_02_2009
+
+#include <boost/detail/workaround.hpp>
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4996)
+#endif
+
+#include <boost/assert.hpp>
+#include <boost/iterator/reverse_iterator.hpp>
+#include <boost/iterator/iterator_traits.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/multi_index/detail/scope_guard.hpp>
+#include <boost/swap.hpp>
+#include <boost/type_traits/aligned_storage.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/type_traits/has_nothrow_copy.hpp>
+#include <boost/type_traits/has_nothrow_assign.hpp>
+#include <boost/type_traits/has_trivial_assign.hpp>
+#include <boost/type_traits/has_trivial_constructor.hpp>
+#include <boost/type_traits/has_trivial_destructor.hpp>
+#include <algorithm>
+#include <cstring>
+#include <iterator>
+#include <memory>
+#include <stdexcept>
+
+namespace boost
+{
+namespace signals2
+{
+namespace detail
+{
+ //
+ // Policies for creating the stack buffer.
+ //
+ template< unsigned N >
+ struct store_n_objects
+ {
+ BOOST_STATIC_CONSTANT( unsigned, value = N );
+ };
+
+ template< unsigned N >
+ struct store_n_bytes
+ {
+ BOOST_STATIC_CONSTANT( unsigned, value = N );
+ };
+
+ namespace auto_buffer_detail
+ {
+ template< class Policy, class T >
+ struct compute_buffer_size
+ {
+ BOOST_STATIC_CONSTANT( unsigned, value = Policy::value * sizeof(T) );
+ };
+
+ template< unsigned N, class T >
+ struct compute_buffer_size< store_n_bytes<N>, T >
+ {
+ BOOST_STATIC_CONSTANT( unsigned, value = N );
+ };
+
+ template< class Policy, class T >
+ struct compute_buffer_objects
+ {
+ BOOST_STATIC_CONSTANT( unsigned, value = Policy::value );
+ };
+
+ template< unsigned N, class T >
+ struct compute_buffer_objects< store_n_bytes<N>, T >
+ {
+ BOOST_STATIC_CONSTANT( unsigned, value = N / sizeof(T) );
+ };
+ }
+
+ struct default_grow_policy
+ {
+ template< class SizeType >
+ static SizeType new_capacity( SizeType capacity )
+ {
+ //
+ // @remark: we grow the capacity quite agressively.
+ // this is justified since we aim to minimize
+ // heap-allocations, and because we mostly use
+ // the buffer locally.
+ return capacity * 4u;
+ }
+
+ template< class SizeType >
+ static bool should_shrink( SizeType, SizeType )
+ {
+ //
+ // @remark: when defining a new grow policy, one might
+ // choose that if the waated space is less
+ // than a certain percentage, then it is of
+ // little use to shrink.
+ //
+ return true;
+ }
+ };
+
+ template< class T,
+ class StackBufferPolicy = store_n_objects<256>,
+ class GrowPolicy = default_grow_policy,
+ class Allocator = std::allocator<T> >
+ class auto_buffer;
+
+
+
+ template
+ <
+ class T,
+ class StackBufferPolicy,
+ class GrowPolicy,
+ class Allocator
+ >
+ class auto_buffer : Allocator
+ {
+ private:
+ enum { N = auto_buffer_detail::
+ compute_buffer_objects<StackBufferPolicy,T>::value };
+
+ BOOST_STATIC_CONSTANT( bool, is_stack_buffer_empty = N == 0u );
+
+ typedef auto_buffer<T, store_n_objects<0>, GrowPolicy, Allocator>
+ local_buffer;
+
+ public:
+ typedef Allocator allocator_type;
+ typedef T value_type;
+ typedef typename Allocator::size_type size_type;
+ typedef typename Allocator::difference_type difference_type;
+ typedef T* pointer;
+ typedef typename Allocator::pointer allocator_pointer;
+ typedef const T* const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef pointer iterator;
+ typedef const_pointer const_iterator;
+ typedef boost::reverse_iterator<iterator> reverse_iterator;
+ typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef typename boost::mpl::if_c< boost::has_trivial_assign<T>::value
+ && sizeof(T) <= sizeof(long double),
+ const value_type,
+ const_reference >::type
+ optimized_const_reference;
+ private:
+
+ pointer allocate( size_type capacity_arg )
+ {
+ if( capacity_arg > N )
+ return &*get_allocator().allocate( capacity_arg );
+ else
+ return static_cast<T*>( members_.address() );
+ }
+
+ void deallocate( pointer where, size_type capacity_arg )
+ {
+ if( capacity_arg <= N )
+ return;
+ get_allocator().deallocate( allocator_pointer(where), capacity_arg );
+ }
+
+ template< class I >
+ static void copy_impl( I begin, I end, pointer where, std::random_access_iterator_tag )
+ {
+ copy_rai( begin, end, where, boost::has_trivial_assign<T>() );
+ }
+
+ static void copy_rai( const T* begin, const T* end,
+ pointer where, const boost::true_type& )
+ {
+ std::memcpy( where, begin, sizeof(T) * std::distance(begin,end) );
+ }
+
+ template< class I, bool b >
+ static void copy_rai( I begin, I end,
+ pointer where, const boost::integral_constant<bool, b>& )
+ {
+ std::uninitialized_copy( begin, end, where );
+ }
+
+ template< class I >
+ static void copy_impl( I begin, I end, pointer where, std::bidirectional_iterator_tag )
+ {
+ std::uninitialized_copy( begin, end, where );
+ }
+
+ template< class I >
+ static void copy_impl( I begin, I end, pointer where )
+ {
+ copy_impl( begin, end, where,
+ typename std::iterator_traits<I>::iterator_category() );
+ }
+
+ template< class I, class I2 >
+ static void assign_impl( I begin, I end, I2 where )
+ {
+ assign_impl( begin, end, where, boost::has_trivial_assign<T>() );
+ }
+
+ template< class I, class I2 >
+ static void assign_impl( I begin, I end, I2 where, const boost::true_type& )
+ {
+ std::memcpy( where, begin, sizeof(T) * std::distance(begin,end) );
+ }
+
+ template< class I, class I2 >
+ static void assign_impl( I begin, I end, I2 where, const boost::false_type& )
+ {
+ for( ; begin != end; ++begin, ++where )
+ *where = *begin;
+ }
+
+ void unchecked_push_back_n( size_type n, const boost::true_type& )
+ {
+ std::uninitialized_fill( end(), end() + n, T() );
+ size_ += n;
+ }
+
+ void unchecked_push_back_n( size_type n, const boost::false_type& )
+ {
+ for( size_type i = 0u; i < n; ++i )
+ unchecked_push_back();
+ }
+
+ void auto_buffer_destroy( pointer where, const boost::false_type& )
+ {
+ (*where).~T();
+ }
+
+ void auto_buffer_destroy( pointer, const boost::true_type& )
+ { }
+
+ void auto_buffer_destroy( pointer where )
+ {
+ auto_buffer_destroy( where, boost::has_trivial_destructor<T>() );
+ }
+
+ void destroy_back_n( size_type n, const boost::false_type& )
+ {
+ BOOST_ASSERT( n > 0 );
+ pointer buffer = buffer_ + size_ - 1u;
+ pointer new_end = buffer - n;
+ for( ; buffer > new_end; --buffer )
+ auto_buffer_destroy( buffer );
+ }
+
+ void destroy_back_n( size_type, const boost::true_type& )
+ { }
+
+ void destroy_back_n( size_type n )
+ {
+ destroy_back_n( n, boost::has_trivial_destructor<T>() );
+ }
+
+ void auto_buffer_destroy( const boost::false_type& x )
+ {
+ if( size_ )
+ destroy_back_n( size_, x );
+ deallocate( buffer_, members_.capacity_ );
+ }
+
+ void auto_buffer_destroy( const boost::true_type& )
+ {
+ deallocate( buffer_, members_.capacity_ );
+ }
+
+ pointer move_to_new_buffer( size_type new_capacity, const boost::false_type& )
+ {
+ pointer new_buffer = allocate( new_capacity ); // strong
+ boost::multi_index::detail::scope_guard guard =
+ boost::multi_index::detail::make_obj_guard( *this,
+ &auto_buffer::deallocate,
+ new_buffer,
+ new_capacity );
+ copy_impl( begin(), end(), new_buffer ); // strong
+ guard.dismiss(); // nothrow
+ return new_buffer;
+ }
+
+ pointer move_to_new_buffer( size_type new_capacity, const boost::true_type& )
+ {
+ pointer new_buffer = allocate( new_capacity ); // strong
+ copy_impl( begin(), end(), new_buffer ); // nothrow
+ return new_buffer;
+ }
+
+ void reserve_impl( size_type new_capacity )
+ {
+ pointer new_buffer = move_to_new_buffer( new_capacity,
+ boost::has_nothrow_copy<T>() );
+ (*this).~auto_buffer();
+ buffer_ = new_buffer;
+ members_.capacity_ = new_capacity;
+ BOOST_ASSERT( size_ <= members_.capacity_ );
+ }
+
+ size_type new_capacity_impl( size_type n )
+ {
+ BOOST_ASSERT( n > members_.capacity_ );
+ size_type new_capacity = GrowPolicy::new_capacity( members_.capacity_ );
+ // @todo: consider to check for allocator.max_size()
+ return (std::max)(new_capacity,n);
+ }
+
+ static void swap_helper( auto_buffer& l, auto_buffer& r,
+ const boost::true_type& )
+ {
+ BOOST_ASSERT( l.is_on_stack() && r.is_on_stack() );
+
+ auto_buffer temp( l.begin(), l.end() );
+ assign_impl( r.begin(), r.end(), l.begin() );
+ assign_impl( temp.begin(), temp.end(), r.begin() );
+ boost::swap( l.size_, r.size_ );
+ boost::swap( l.members_.capacity_, r.members_.capacity_ );
+ }
+
+ static void swap_helper( auto_buffer& l, auto_buffer& r,
+ const boost::false_type& )
+ {
+ BOOST_ASSERT( l.is_on_stack() && r.is_on_stack() );
+ size_type min_size = (std::min)(l.size_,r.size_);
+ size_type max_size = (std::max)(l.size_,r.size_);
+ size_type diff = max_size - min_size;
+ auto_buffer* smallest = l.size_ == min_size ? &l : &r;
+ auto_buffer* largest = smallest == &l ? &r : &l;
+
+ // @remark: the implementation below is not as fast
+ // as it could be if we assumed T had a default
+ // constructor.
+
+ size_type i = 0u;
+ for( ; i < min_size; ++i )
+ boost::swap( (*smallest)[i], (*largest)[i] );
+
+ for( ; i < max_size; ++i )
+ smallest->unchecked_push_back( (*largest)[i] );
+
+ largest->pop_back_n( diff );
+ boost::swap( l.members_.capacity_, r.members_.capacity_ );
+ }
+
+ void one_sided_swap( auto_buffer& temp ) // nothrow
+ {
+ BOOST_ASSERT( !temp.is_on_stack() );
+ this->~auto_buffer();
+ // @remark: must be nothrow
+ get_allocator() = temp.get_allocator();
+ members_.capacity_ = temp.members_.capacity_;
+ buffer_ = temp.buffer_;
+ BOOST_ASSERT( temp.size_ >= size_ + 1u );
+ size_ = temp.size_;
+ temp.buffer_ = 0;
+ BOOST_ASSERT( temp.is_valid() );
+ }
+
+ template< class I >
+ void insert_impl( const_iterator before, I begin_arg, I end_arg,
+ std::input_iterator_tag )
+ {
+ for( ; begin_arg != end_arg; ++begin_arg )
+ {
+ before = insert( before, *begin_arg );
+ ++before;
+ }
+ }
+
+ void grow_back( size_type n, const boost::true_type& )
+ {
+ BOOST_ASSERT( size_ + n <= members_.capacity_ );
+ size_ += n;
+ }
+
+ void grow_back( size_type n, const boost::false_type& )
+ {
+ unchecked_push_back_n(n);
+ }
+
+ void grow_back( size_type n )
+ {
+ grow_back( n, boost::has_trivial_constructor<T>() );
+ }
+
+ void grow_back_one( const boost::true_type& )
+ {
+ BOOST_ASSERT( size_ + 1 <= members_.capacity_ );
+ size_ += 1;
+ }
+
+ void grow_back_one( const boost::false_type& )
+ {
+ unchecked_push_back();
+ }
+
+ void grow_back_one()
+ {
+ grow_back_one( boost::has_trivial_constructor<T>() );
+ }
+
+ template< class I >
+ void insert_impl( const_iterator before, I begin_arg, I end_arg,
+ std::forward_iterator_tag )
+ {
+ difference_type n = std::distance(begin_arg, end_arg);
+
+ if( size_ + n <= members_.capacity_ )
+ {
+ bool is_back_insertion = before == cend();
+ if( !is_back_insertion )
+ {
+ grow_back( n );
+ iterator where = const_cast<T*>(before);
+ std::copy( before, cend() - n, where + n );
+ assign_impl( begin_arg, end_arg, where );
+ }
+ else
+ {
+ unchecked_push_back( begin_arg, end_arg );
+ }
+ BOOST_ASSERT( is_valid() );
+ return;
+ }
+
+ auto_buffer temp( new_capacity_impl( size_ + n ) );
+ temp.unchecked_push_back( cbegin(), before );
+ temp.unchecked_push_back( begin_arg, end_arg );
+ temp.unchecked_push_back( before, cend() );
+ one_sided_swap( temp );
+ BOOST_ASSERT( is_valid() );
+ }
+
+ public:
+ bool is_valid() const // invariant
+ {
+ // @remark: allowed for N==0 and when
+ // using a locally instance
+ // in insert()/one_sided_swap()
+ if( buffer_ == 0 )
+ return true;
+
+ if( members_.capacity_ < N )
+ return false;
+
+ if( !is_on_stack() && members_.capacity_ <= N )
+ return false;
+
+ if( buffer_ == members_.address() )
+ if( members_.capacity_ > N )
+ return false;
+
+ if( size_ > members_.capacity_ )
+ return false;
+
+ return true;
+ }
+
+ auto_buffer()
+ : members_( N ),
+ buffer_( static_cast<T*>(members_.address()) ),
+ size_( 0u )
+ {
+ BOOST_ASSERT( is_valid() );
+ }
+
+ auto_buffer( const auto_buffer& r )
+ : members_( (std::max)(r.size_,size_type(N)) ),
+ buffer_( allocate( members_.capacity_ ) ),
+ size_( 0 )
+ {
+ copy_impl( r.begin(), r.end(), buffer_ );
+ size_ = r.size_;
+ BOOST_ASSERT( is_valid() );
+ }
+
+ auto_buffer& operator=( const auto_buffer& r ) // basic
+ {
+ if( this == &r )
+ return *this;
+
+ difference_type diff = size_ - r.size_;
+ if( diff >= 0 )
+ {
+ pop_back_n( static_cast<size_type>(diff) );
+ assign_impl( r.begin(), r.end(), begin() );
+ }
+ else
+ {
+ if( members_.capacity_ >= r.size() )
+ {
+ unchecked_push_back_n( static_cast<size_type>(-diff) );
+ assign_impl( r.begin(), r.end(), begin() );
+ }
+ else
+ {
+ // @remark: we release memory as early as possible
+ // since we only give the basic guarantee
+ (*this).~auto_buffer();
+ buffer_ = 0;
+ pointer new_buffer = allocate( r.size() );
+ boost::multi_index::detail::scope_guard guard =
+ boost::multi_index::detail::make_obj_guard( *this,
+ &auto_buffer::deallocate,
+ new_buffer,
+ r.size() );
+ copy_impl( r.begin(), r.end(), new_buffer );
+ guard.dismiss();
+ buffer_ = new_buffer;
+ members_.capacity_ = r.size();
+ size_ = members_.capacity_;
+ }
+ }
+
+ BOOST_ASSERT( size() == r.size() );
+ BOOST_ASSERT( is_valid() );
+ return *this;
+ }
+
+ explicit auto_buffer( size_type capacity_arg )
+ : members_( (std::max)(capacity_arg, size_type(N)) ),
+ buffer_( allocate(members_.capacity_) ),
+ size_( 0 )
+ {
+ BOOST_ASSERT( is_valid() );
+ }
+
+ auto_buffer( size_type size_arg, optimized_const_reference init_value )
+ : members_( (std::max)(size_arg, size_type(N)) ),
+ buffer_( allocate(members_.capacity_) ),
+ size_( 0 )
+ {
+ std::uninitialized_fill( buffer_, buffer_ + size_arg, init_value );
+ size_ = size_arg;
+ BOOST_ASSERT( is_valid() );
+ }
+
+ auto_buffer( size_type capacity_arg, const allocator_type& a )
+ : allocator_type( a ),
+ members_( (std::max)(capacity_arg, size_type(N)) ),
+ buffer_( allocate(members_.capacity_) ),
+ size_( 0 )
+ {
+ BOOST_ASSERT( is_valid() );
+ }
+
+ auto_buffer( size_type size_arg, optimized_const_reference init_value,
+ const allocator_type& a )
+ : allocator_type( a ),
+ members_( (std::max)(size_arg, size_type(N)) ),
+ buffer_( allocate(members_.capacity_) ),
+ size_( 0 )
+ {
+ std::uninitialized_fill( buffer_, buffer_ + size_arg, init_value );
+ size_ = size_arg;
+ BOOST_ASSERT( is_valid() );
+ }
+
+ template< class ForwardIterator >
+ auto_buffer( ForwardIterator begin_arg, ForwardIterator end_arg )
+ :
+ members_( std::distance(begin_arg, end_arg) ),
+ buffer_( allocate(members_.capacity_) ),
+ size_( 0 )
+ {
+ copy_impl( begin_arg, end_arg, buffer_ );
+ size_ = members_.capacity_;
+ if( members_.capacity_ < N )
+ members_.capacity_ = N;
+ BOOST_ASSERT( is_valid() );
+ }
+
+ template< class ForwardIterator >
+ auto_buffer( ForwardIterator begin_arg, ForwardIterator end_arg,
+ const allocator_type& a )
+ : allocator_type( a ),
+ members_( std::distance(begin_arg, end_arg) ),
+ buffer_( allocate(members_.capacity_) ),
+ size_( 0 )
+ {
+ copy_impl( begin_arg, end_arg, buffer_ );
+ size_ = members_.capacity_;
+ if( members_.capacity_ < N )
+ members_.capacity_ = N;
+ BOOST_ASSERT( is_valid() );
+ }
+
+ ~auto_buffer()
+ {
+ BOOST_ASSERT( is_valid() );
+ if( buffer_ ) // do we need this check? Yes, but only
+ // for N = 0u + local instances in one_sided_swap()
+ auto_buffer_destroy( boost::has_trivial_destructor<T>() );
+ }
+
+ public:
+ bool empty() const
+ {
+ return size_ == 0;
+ }
+
+ bool full() const
+ {
+ return size_ == members_.capacity_;
+ }
+
+ bool is_on_stack() const
+ {
+ return members_.capacity_ <= N;
+ }
+
+ size_type size() const
+ {
+ return size_;
+ }
+
+ size_type capacity() const
+ {
+ return members_.capacity_;
+ }
+
+ public:
+ pointer data()
+ {
+ return buffer_;
+ }
+
+ const_pointer data() const
+ {
+ return buffer_;
+ }
+
+ allocator_type& get_allocator()
+ {
+ return static_cast<allocator_type&>(*this);
+ }
+
+ const allocator_type& get_allocator() const
+ {
+ return static_cast<const allocator_type&>(*this);
+ }
+
+ public:
+ iterator begin()
+ {
+ return buffer_;
+ }
+
+ const_iterator begin() const
+ {
+ return buffer_;
+ }
+
+ iterator end()
+ {
+ return buffer_ + size_;
+ }
+
+ const_iterator end() const
+ {
+ return buffer_ + size_;
+ }
+
+ reverse_iterator rbegin()
+ {
+ return reverse_iterator(end());
+ }
+
+ const_reverse_iterator rbegin() const
+ {
+ return const_reverse_iterator(end());
+ }
+
+ reverse_iterator rend()
+ {
+ return reverse_iterator(begin());
+ }
+
+ const_reverse_iterator rend() const
+ {
+ return const_reverse_iterator(begin());
+ }
+
+ const_iterator cbegin() const
+ {
+ return const_cast<const auto_buffer*>(this)->begin();
+ }
+
+ const_iterator cend() const
+ {
+ return const_cast<const auto_buffer*>(this)->end();
+ }
+
+ const_reverse_iterator crbegin() const
+ {
+ return const_cast<const auto_buffer*>(this)->rbegin();
+ }
+
+ const_reverse_iterator crend() const
+ {
+ return const_cast<const auto_buffer*>(this)->rend();
+ }
+
+ public:
+ reference front()
+ {
+ return buffer_[0];
+ }
+
+ optimized_const_reference front() const
+ {
+ return buffer_[0];
+ }
+
+ reference back()
+ {
+ return buffer_[size_-1];
+ }
+
+ optimized_const_reference back() const
+ {
+ return buffer_[size_-1];
+ }
+
+ reference operator[]( size_type n )
+ {
+ BOOST_ASSERT( n < size_ );
+ return buffer_[n];
+ }
+
+ optimized_const_reference operator[]( size_type n ) const
+ {
+ BOOST_ASSERT( n < size_ );
+ return buffer_[n];
+ }
+
+ void unchecked_push_back()
+ {
+ BOOST_ASSERT( !full() );
+ new (buffer_ + size_) T;
+ ++size_;
+ }
+
+ void unchecked_push_back_n( size_type n )
+ {
+ BOOST_ASSERT( size_ + n <= members_.capacity_ );
+ unchecked_push_back_n( n, boost::has_trivial_assign<T>() );
+ }
+
+ void unchecked_push_back( optimized_const_reference x ) // non-growing
+ {
+ BOOST_ASSERT( !full() );
+ new (buffer_ + size_) T( x );
+ ++size_;
+ }
+
+ template< class ForwardIterator >
+ void unchecked_push_back( ForwardIterator begin_arg,
+ ForwardIterator end_arg ) // non-growing
+ {
+ BOOST_ASSERT( size_ + std::distance(begin_arg, end_arg) <= members_.capacity_ );
+ copy_impl( begin_arg, end_arg, buffer_ + size_ );
+ size_ += std::distance(begin_arg, end_arg);
+ }
+
+ void reserve_precisely( size_type n )
+ {
+ BOOST_ASSERT( members_.capacity_ >= N );
+
+ if( n <= members_.capacity_ )
+ return;
+ reserve_impl( n );
+ BOOST_ASSERT( members_.capacity_ == n );
+ }
+
+ void reserve( size_type n ) // strong
+ {
+ BOOST_ASSERT( members_.capacity_ >= N );
+
+ if( n <= members_.capacity_ )
+ return;
+
+ reserve_impl( new_capacity_impl( n ) );
+ BOOST_ASSERT( members_.capacity_ >= n );
+ }
+
+ void push_back()
+ {
+ if( size_ != members_.capacity_ )
+ {
+ unchecked_push_back();
+ }
+ else
+ {
+ reserve( size_ + 1u );
+ unchecked_push_back();
+ }
+ }
+
+ void push_back( optimized_const_reference x )
+ {
+ if( size_ != members_.capacity_ )
+ {
+ unchecked_push_back( x );
+ }
+ else
+ {
+ reserve( size_ + 1u );
+ unchecked_push_back( x );
+ }
+ }
+
+ template< class ForwardIterator >
+ void push_back( ForwardIterator begin_arg, ForwardIterator end_arg )
+ {
+ difference_type diff = std::distance(begin_arg, end_arg);
+ if( size_ + diff > members_.capacity_ )
+ reserve( size_ + diff );
+ unchecked_push_back( begin_arg, end_arg );
+ }
+
+ iterator insert( const_iterator before, optimized_const_reference x ) // basic
+ {
+ // @todo: consider if we want to support x in 'this'
+ if( size_ < members_.capacity_ )
+ {
+ bool is_back_insertion = before == cend();
+ iterator where = const_cast<T*>(before);
+
+ if( !is_back_insertion )
+ {
+ grow_back_one();
+ std::copy( before, cend() - 1u, where + 1u );
+ *where = x;
+ BOOST_ASSERT( is_valid() );
+ }
+ else
+ {
+ unchecked_push_back( x );
+ }
+ return where;
+ }
+
+ auto_buffer temp( new_capacity_impl( size_ + 1u ) );
+ temp.unchecked_push_back( cbegin(), before );
+ iterator result = temp.end();
+ temp.unchecked_push_back( x );
+ temp.unchecked_push_back( before, cend() );
+ one_sided_swap( temp );
+ BOOST_ASSERT( is_valid() );
+ return result;
+ }
+
+ void insert( const_iterator before, size_type n,
+ optimized_const_reference x )
+ {
+ // @todo: see problems above
+ if( size_ + n <= members_.capacity_ )
+ {
+ grow_back( n );
+ iterator where = const_cast<T*>(before);
+ std::copy( before, cend() - n, where + n );
+ std::fill( where, where + n, x );
+ BOOST_ASSERT( is_valid() );
+ return;
+ }
+
+ auto_buffer temp( new_capacity_impl( size_ + n ) );
+ temp.unchecked_push_back( cbegin(), before );
+ std::uninitialized_fill_n( temp.end(), n, x );
+ temp.size_ += n;
+ temp.unchecked_push_back( before, cend() );
+ one_sided_swap( temp );
+ BOOST_ASSERT( is_valid() );
+ }
+
+ template< class ForwardIterator >
+ void insert( const_iterator before,
+ ForwardIterator begin_arg, ForwardIterator end_arg ) // basic
+ {
+ typedef typename std::iterator_traits<ForwardIterator>
+ ::iterator_category category;
+ insert_impl( before, begin_arg, end_arg, category() );
+ }
+
+ void pop_back()
+ {
+ BOOST_ASSERT( !empty() );
+ auto_buffer_destroy( buffer_ + size_ - 1, boost::has_trivial_destructor<T>() );
+ --size_;
+ }
+
+ void pop_back_n( size_type n )
+ {
+ BOOST_ASSERT( n <= size_ );
+ if( n )
+ {
+ destroy_back_n( n );
+ size_ -= n;
+ }
+ }
+
+ void clear()
+ {
+ pop_back_n( size_ );
+ }
+
+ iterator erase( const_iterator where )
+ {
+ BOOST_ASSERT( !empty() );
+ BOOST_ASSERT( cbegin() <= where );
+ BOOST_ASSERT( cend() > where );
+
+ unsigned elements = cend() - where - 1u;
+
+ if( elements > 0u )
+ {
+ const_iterator start = where + 1u;
+ std::copy( start, start + elements,
+ const_cast<T*>(where) );
+ }
+ pop_back();
+ BOOST_ASSERT( !full() );
+ iterator result = const_cast<T*>( where );
+ BOOST_ASSERT( result <= end() );
+ return result;
+ }
+
+ iterator erase( const_iterator from, const_iterator to )
+ {
+ BOOST_ASSERT( !(std::distance(from,to)>0) ||
+ !empty() );
+ BOOST_ASSERT( cbegin() <= from );
+ BOOST_ASSERT( cend() >= to );
+
+ unsigned elements = std::distance(to,cend());
+
+ if( elements > 0u )
+ {
+ BOOST_ASSERT( elements > 0u );
+ std::copy( to, to + elements,
+ const_cast<T*>(from) );
+ }
+ pop_back_n( std::distance(from,to) );
+ BOOST_ASSERT( !full() );
+ iterator result = const_cast<T*>( from );
+ BOOST_ASSERT( result <= end() );
+ return result;
+ }
+
+ void shrink_to_fit()
+ {
+ if( is_on_stack() || !GrowPolicy::should_shrink(size_,members_.capacity_) )
+ return;
+
+ reserve_impl( size_ );
+ members_.capacity_ = (std::max)(size_type(N),members_.capacity_);
+ BOOST_ASSERT( is_on_stack() || size_ == members_.capacity_ );
+ BOOST_ASSERT( !is_on_stack() || size_ <= members_.capacity_ );
+ }
+
+ pointer uninitialized_grow( size_type n ) // strong
+ {
+ if( size_ + n <= members_.capacity_ )
+ reserve( size_ + n );
+
+ pointer res = end();
+ size_ += n;
+ return res;
+ }
+
+ void uninitialized_shrink( size_type n ) // nothrow
+ {
+ // @remark: test for wrap-around
+ BOOST_ASSERT( size_ - n <= members_.capacity_ );
+ size_ -= n;
+ }
+
+ void uninitialized_resize( size_type n )
+ {
+ if( n > size() )
+ uninitialized_grow( n - size() );
+ else if( n < size() )
+ uninitialized_shrink( size() - n );
+
+ BOOST_ASSERT( size() == n );
+ }
+
+ // nothrow - if both buffer are on the heap, or
+ // - if one buffer is on the heap and one has
+ // 'has_allocated_buffer() == false', or
+ // - if copy-construction cannot throw
+ // basic - otherwise (better guarantee impossible)
+ // requirement: the allocator must be no-throw-swappable
+ void swap( auto_buffer& r )
+ {
+ bool on_stack = is_on_stack();
+ bool r_on_stack = r.is_on_stack();
+ bool both_on_heap = !on_stack && !r_on_stack;
+ if( both_on_heap )
+ {
+ boost::swap( get_allocator(), r.get_allocator() );
+ boost::swap( members_.capacity_, r.members_.capacity_ );
+ boost::swap( buffer_, r.buffer_ );
+ boost::swap( size_, r.size_ );
+ BOOST_ASSERT( is_valid() );
+ BOOST_ASSERT( r.is_valid() );
+ return;
+ }
+
+ BOOST_ASSERT( on_stack || r_on_stack );
+ bool exactly_one_on_stack = (on_stack && !r_on_stack) ||
+ (!on_stack && r_on_stack);
+
+ //
+ // Remark: we now know that we can copy into
+ // the unused stack buffer.
+ //
+ if( exactly_one_on_stack )
+ {
+ auto_buffer* one_on_stack = on_stack ? this : &r;
+ auto_buffer* other = on_stack ? &r : this;
+ pointer new_buffer = static_cast<T*>(other->members_.address());
+ copy_impl( one_on_stack->begin(), one_on_stack->end(),
+ new_buffer ); // strong
+ one_on_stack->~auto_buffer(); // nothrow
+ boost::swap( get_allocator(), r.get_allocator() ); // assume nothrow
+ boost::swap( members_.capacity_, r.members_.capacity_ );
+ boost::swap( size_, r.size_ );
+ one_on_stack->buffer_ = other->buffer_;
+ other->buffer_ = new_buffer;
+ BOOST_ASSERT( other->is_on_stack() );
+ BOOST_ASSERT( !one_on_stack->is_on_stack() );
+ BOOST_ASSERT( is_valid() );
+ BOOST_ASSERT( r.is_valid() );
+ return;
+ }
+
+ BOOST_ASSERT( on_stack && r_on_stack );
+ swap_helper( *this, r, boost::has_trivial_assign<T>() );
+ BOOST_ASSERT( is_valid() );
+ BOOST_ASSERT( r.is_valid() );
+ }
+
+ private:
+ typedef boost::aligned_storage< N * sizeof(T),
+ boost::alignment_of<T>::value >
+ storage;
+
+ struct members_type : storage /* to enable EBO */
+ {
+ size_type capacity_;
+
+ members_type( size_type capacity )
+ : capacity_(capacity)
+ { }
+
+ void* address() const
+ { return const_cast<storage&>(static_cast<const storage&>(*this)).address(); }
+ };
+
+ members_type members_;
+ pointer buffer_;
+ size_type size_;
+
+ };
+
+ template< class T, class SBP, class GP, class A >
+ inline void swap( auto_buffer<T,SBP,GP,A>& l, auto_buffer<T,SBP,GP,A>& r )
+ {
+ l.swap( r );
+ }
+
+ template< class T, class SBP, class GP, class A >
+ inline bool operator==( const auto_buffer<T,SBP,GP,A>& l,
+ const auto_buffer<T,SBP,GP,A>& r )
+ {
+ if( l.size() != r.size() )
+ return false;
+ return std::equal( l.begin(), l.end(), r.begin() );
+ }
+
+ template< class T, class SBP, class GP, class A >
+ inline bool operator!=( const auto_buffer<T,SBP,GP,A>& l,
+ const auto_buffer<T,SBP,GP,A>& r )
+ {
+ return !(l == r);
+ }
+
+ template< class T, class SBP, class GP, class A >
+ inline bool operator<( const auto_buffer<T,SBP,GP,A>& l,
+ const auto_buffer<T,SBP,GP,A>& r )
+ {
+ return std::lexicographical_compare( l.begin(), l.end(),
+ r.begin(), r.end() );
+ }
+
+ template< class T, class SBP, class GP, class A >
+ inline bool operator>( const auto_buffer<T,SBP,GP,A>& l,
+ const auto_buffer<T,SBP,GP,A>& r )
+ {
+ return (r < l);
+ }
+
+ template< class T, class SBP, class GP, class A >
+ inline bool operator<=( const auto_buffer<T,SBP,GP,A>& l,
+ const auto_buffer<T,SBP,GP,A>& r )
+ {
+ return !(r > l);
+ }
+
+ template< class T, class SBP, class GP, class A >
+ inline bool operator>=( const auto_buffer<T,SBP,GP,A>& l,
+ const auto_buffer<T,SBP,GP,A>& r )
+ {
+ return !(l < r);
+ }
+
+} // namespace detail
+} // namespace signals2
+}
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+#endif
diff --git a/third_party/boost/boost/signals2/detail/foreign_ptr.hpp b/third_party/boost/boost/signals2/detail/foreign_ptr.hpp
new file mode 100644
index 0000000..4349b38
--- /dev/null
+++ b/third_party/boost/boost/signals2/detail/foreign_ptr.hpp
@@ -0,0 +1,185 @@
+
+// helper code for dealing with tracking non-boost shared_ptr/weak_ptr
+
+// Copyright Frank Mori Hess 2009.
+// Distributed under the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/signals2 for library home page.
+
+#ifndef BOOST_SIGNALS2_FOREIGN_PTR_HPP
+#define BOOST_SIGNALS2_FOREIGN_PTR_HPP
+
+#include <algorithm>
+#include <boost/config.hpp>
+#include <boost/assert.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/smart_ptr/bad_weak_ptr.hpp>
+#include <boost/utility/swap.hpp>
+
+#ifndef BOOST_NO_CXX11_SMART_PTR
+#include <memory>
+#endif
+
+namespace boost
+{
+ template<typename T> class shared_ptr;
+ template<typename T> class weak_ptr;
+
+ namespace signals2
+ {
+ template<typename WeakPtr> struct weak_ptr_traits
+ {};
+ template<typename T> struct weak_ptr_traits<boost::weak_ptr<T> >
+ {
+ typedef boost::shared_ptr<T> shared_type;
+ };
+#ifndef BOOST_NO_CXX11_SMART_PTR
+ template<typename T> struct weak_ptr_traits<std::weak_ptr<T> >
+ {
+ typedef std::shared_ptr<T> shared_type;
+ };
+#endif
+
+ template<typename SharedPtr> struct shared_ptr_traits
+ {};
+
+ template<typename T> struct shared_ptr_traits<boost::shared_ptr<T> >
+ {
+ typedef boost::weak_ptr<T> weak_type;
+ };
+#ifndef BOOST_NO_CXX11_SMART_PTR
+ template<typename T> struct shared_ptr_traits<std::shared_ptr<T> >
+ {
+ typedef std::weak_ptr<T> weak_type;
+ };
+#endif
+
+ namespace detail
+ {
+ struct foreign_shared_ptr_impl_base
+ {
+ virtual ~foreign_shared_ptr_impl_base() {}
+ virtual void* get() const = 0;
+ virtual foreign_shared_ptr_impl_base * clone() const = 0;
+ };
+
+ template<typename FSP>
+ class foreign_shared_ptr_impl: public foreign_shared_ptr_impl_base
+ {
+ public:
+ foreign_shared_ptr_impl(const FSP &p): _p(p)
+ {}
+ virtual void * get() const
+ {
+ return _p.get();
+ }
+ virtual foreign_shared_ptr_impl * clone() const
+ {
+ return new foreign_shared_ptr_impl(*this);
+ }
+ private:
+ FSP _p;
+ };
+
+ class foreign_void_shared_ptr
+ {
+ public:
+ foreign_void_shared_ptr():
+ _p(0)
+ {}
+ foreign_void_shared_ptr(const foreign_void_shared_ptr &other):
+ _p(other._p->clone())
+ {}
+ template<typename FSP>
+ explicit foreign_void_shared_ptr(const FSP &fsp):
+ _p(new foreign_shared_ptr_impl<FSP>(fsp))
+ {}
+ ~foreign_void_shared_ptr()
+ {
+ delete _p;
+ }
+ foreign_void_shared_ptr & operator=(const foreign_void_shared_ptr &other)
+ {
+ if(&other == this) return *this;
+ foreign_void_shared_ptr(other).swap(*this);
+ return *this;
+ }
+ void swap(foreign_void_shared_ptr &other)
+ {
+ boost::swap(_p, other._p);
+ }
+ private:
+ foreign_shared_ptr_impl_base *_p;
+ };
+
+ struct foreign_weak_ptr_impl_base
+ {
+ virtual ~foreign_weak_ptr_impl_base() {}
+ virtual foreign_void_shared_ptr lock() const = 0;
+ virtual bool expired() const = 0;
+ virtual foreign_weak_ptr_impl_base * clone() const = 0;
+ };
+
+ template<typename FWP>
+ class foreign_weak_ptr_impl: public foreign_weak_ptr_impl_base
+ {
+ public:
+ foreign_weak_ptr_impl(const FWP &p): _p(p)
+ {}
+ virtual foreign_void_shared_ptr lock() const
+ {
+ return foreign_void_shared_ptr(_p.lock());
+ }
+ virtual bool expired() const
+ {
+ return _p.expired();
+ }
+ virtual foreign_weak_ptr_impl * clone() const
+ {
+ return new foreign_weak_ptr_impl(*this);
+ }
+ private:
+ FWP _p;
+ };
+
+ class foreign_void_weak_ptr
+ {
+ public:
+ foreign_void_weak_ptr()
+ {}
+ foreign_void_weak_ptr(const foreign_void_weak_ptr &other):
+ _p(other._p->clone())
+ {}
+ template<typename FWP>
+ explicit foreign_void_weak_ptr(const FWP &fwp):
+ _p(new foreign_weak_ptr_impl<FWP>(fwp))
+ {}
+ foreign_void_weak_ptr & operator=(const foreign_void_weak_ptr &other)
+ {
+ if(&other == this) return *this;
+ foreign_void_weak_ptr(other).swap(*this);
+ return *this;
+ }
+ void swap(foreign_void_weak_ptr &other)
+ {
+ boost::swap(_p, other._p);
+ }
+ foreign_void_shared_ptr lock() const
+ {
+ return _p->lock();
+ }
+ bool expired() const
+ {
+ return _p->expired();
+ }
+ private:
+ boost::scoped_ptr<foreign_weak_ptr_impl_base> _p;
+ };
+ } // namespace detail
+
+ } // namespace signals2
+} // namespace boost
+
+#endif // BOOST_SIGNALS2_FOREIGN_PTR_HPP
diff --git a/third_party/boost/boost/signals2/detail/lwm_pthreads.hpp b/third_party/boost/boost/signals2/detail/lwm_pthreads.hpp
new file mode 100644
index 0000000..fb0dd66
--- /dev/null
+++ b/third_party/boost/boost/signals2/detail/lwm_pthreads.hpp
@@ -0,0 +1,78 @@
+//
+// boost/signals2/detail/lwm_pthreads.hpp
+//
+// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
+// Copyright (c) 2008 Frank Mori Hess
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_SIGNALS2_LWM_PTHREADS_HPP
+#define BOOST_SIGNALS2_LWM_PTHREADS_HPP
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/assert.hpp>
+#include <pthread.h>
+
+namespace boost
+{
+
+namespace signals2
+{
+
+class mutex
+{
+private:
+
+ pthread_mutex_t m_;
+
+ mutex(mutex const &);
+ mutex & operator=(mutex const &);
+
+public:
+
+ mutex()
+ {
+
+// HPUX 10.20 / DCE has a nonstandard pthread_mutex_init
+
+#if defined(__hpux) && defined(_DECTHREADS_)
+ BOOST_VERIFY(pthread_mutex_init(&m_, pthread_mutexattr_default) == 0);
+#else
+ BOOST_VERIFY(pthread_mutex_init(&m_, 0) == 0);
+#endif
+ }
+
+ ~mutex()
+ {
+ BOOST_VERIFY(pthread_mutex_destroy(&m_) == 0);
+ }
+
+ void lock()
+ {
+ BOOST_VERIFY(pthread_mutex_lock(&m_) == 0);
+ }
+
+ bool try_lock()
+ {
+ return pthread_mutex_trylock(&m_) == 0;
+ }
+
+ void unlock()
+ {
+ BOOST_VERIFY(pthread_mutex_unlock(&m_) == 0);
+ }
+};
+
+} // namespace signals2
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SIGNALS2_LWM_PTHREADS_HPP
diff --git a/third_party/boost/boost/signals2/detail/null_output_iterator.hpp b/third_party/boost/boost/signals2/detail/null_output_iterator.hpp
new file mode 100644
index 0000000..9e98695
--- /dev/null
+++ b/third_party/boost/boost/signals2/detail/null_output_iterator.hpp
@@ -0,0 +1,34 @@
+/*
+ An output iterator which simply discards output.
+*/
+// Copyright Frank Mori Hess 2008.
+// Distributed under the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/signals2 for library home page.
+
+#ifndef BOOST_SIGNALS2_NULL_OUTPUT_ITERATOR_HPP
+#define BOOST_SIGNALS2_NULL_OUTPUT_ITERATOR_HPP
+
+#include <boost/function_output_iterator.hpp>
+
+namespace boost
+{
+ namespace signals2
+ {
+ namespace detail
+ {
+ class does_nothing
+ {
+ public:
+ template<typename T>
+ void operator()(const T&) const
+ {}
+ };
+ typedef boost::function_output_iterator<does_nothing> null_output_iterator;
+ } // namespace detail
+ } // namespace signals2
+} // namespace boost
+
+#endif // BOOST_SIGNALS2_NULL_OUTPUT_ITERATOR_HPP
diff --git a/third_party/boost/boost/signals2/detail/preprocessed_arg_type.hpp b/third_party/boost/boost/signals2/detail/preprocessed_arg_type.hpp
new file mode 100644
index 0000000..02717c9
--- /dev/null
+++ b/third_party/boost/boost/signals2/detail/preprocessed_arg_type.hpp
@@ -0,0 +1,34 @@
+// Boost.Signals2 library
+
+// Copyright Frank Mori Hess 2007-2009.
+// Copyright Timmo Stange 2007.
+// Copyright Douglas Gregor 2001-2004. Use, modification and
+// distribution is subject to the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// For more information, see http://www.boost.org
+
+#ifndef BOOST_SIGNALS2_PREPROCESSED_ARG_TYPE_HPP
+#define BOOST_SIGNALS2_PREPROCESSED_ARG_TYPE_HPP
+
+#include <boost/preprocessor/repetition.hpp>
+#include <boost/signals2/detail/signals_common_macros.hpp>
+
+#define BOOST_PP_ITERATION_LIMITS (0, BOOST_PP_INC(BOOST_SIGNALS2_MAX_ARGS))
+#define BOOST_PP_FILENAME_1 <boost/signals2/detail/preprocessed_arg_type_template.hpp>
+#include BOOST_PP_ITERATE()
+
+namespace boost
+{
+ namespace signals2
+ {
+ namespace detail
+ {
+ struct std_functional_base
+ {};
+ } // namespace detail
+ } // namespace signals2
+} // namespace boost
+
+#endif // BOOST_SIGNALS2_PREPROCESSED_ARG_TYPE_HPP
diff --git a/third_party/boost/boost/signals2/detail/preprocessed_arg_type_template.hpp b/third_party/boost/boost/signals2/detail/preprocessed_arg_type_template.hpp
new file mode 100644
index 0000000..4f39433
--- /dev/null
+++ b/third_party/boost/boost/signals2/detail/preprocessed_arg_type_template.hpp
@@ -0,0 +1,39 @@
+// Copyright Frank Mori Hess 2009
+//
+// Use, modification and
+// distribution is subject to the 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
+
+// This file is included iteratively, and should not be protected from multiple inclusion
+
+#define BOOST_SIGNALS2_NUM_ARGS BOOST_PP_ITERATION()
+
+namespace boost
+{
+ namespace signals2
+ {
+ namespace detail
+ {
+ template<unsigned n BOOST_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
+ BOOST_SIGNALS2_ARGS_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
+ class BOOST_SIGNALS2_PREPROCESSED_ARG_N_TYPE_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS);
+
+// template<typename T1, typename T2, ... , typename TN> class preprocessed_arg_typeN<n, T1, T2, ..., TN>{...} ...
+#define BOOST_SIGNALS2_PREPROCESSED_ARG_TYPE_CLASS_TEMPLATE_SPECIALIZATION(z, n, data) \
+ template<BOOST_SIGNALS2_ARGS_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)> \
+ class BOOST_SIGNALS2_PREPROCESSED_ARG_N_TYPE_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)<n, \
+ BOOST_SIGNALS2_ARGS_TEMPLATE_INSTANTIATION(BOOST_SIGNALS2_NUM_ARGS)> \
+ { \
+ public: \
+ typedef BOOST_PP_CAT(T, BOOST_PP_INC(n)) type; \
+ };
+ BOOST_PP_REPEAT(BOOST_SIGNALS2_NUM_ARGS, BOOST_SIGNALS2_PREPROCESSED_ARG_TYPE_CLASS_TEMPLATE_SPECIALIZATION, ~)
+
+ } // namespace detail
+ } // namespace signals2
+} // namespace boost
+
+#undef BOOST_SIGNALS2_NUM_ARGS
diff --git a/third_party/boost/boost/signals2/detail/replace_slot_function.hpp b/third_party/boost/boost/signals2/detail/replace_slot_function.hpp
new file mode 100644
index 0000000..de8f425
--- /dev/null
+++ b/third_party/boost/boost/signals2/detail/replace_slot_function.hpp
@@ -0,0 +1,32 @@
+// Copyright Frank Mori Hess 2007-2009
+//
+// Use, modification and
+// distribution is subject to the 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_SIGNALS2_DETAIL_REPLACE_SLOT_FUNCTION_HPP
+#define BOOST_SIGNALS2_DETAIL_REPLACE_SLOT_FUNCTION_HPP
+
+#include <boost/signals2/slot_base.hpp>
+
+namespace boost
+{
+ namespace signals2
+ {
+ namespace detail
+ {
+ template<typename ResultSlot, typename SlotIn, typename SlotFunction>
+ ResultSlot replace_slot_function(const SlotIn &slot_in, const SlotFunction &fun)
+ {
+ ResultSlot slot(fun);
+ slot.track(slot_in);
+ return slot;
+ }
+ } // namespace detail
+ } // namespace signals2
+} // namespace boost
+
+#endif // BOOST_SIGNALS2_DETAIL_REPLACE_SLOT_FUNCTION_HPP
diff --git a/third_party/boost/boost/signals2/detail/result_type_wrapper.hpp b/third_party/boost/boost/signals2/detail/result_type_wrapper.hpp
new file mode 100644
index 0000000..35dea7c
--- /dev/null
+++ b/third_party/boost/boost/signals2/detail/result_type_wrapper.hpp
@@ -0,0 +1,72 @@
+// Boost.Signals2 library
+
+// Copyright Douglas Gregor 2001-2004.
+// Copyright Frank Mori Hess 2007. Use, modification and
+// distribution is subject to the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// For more information, see http://www.boost.org
+
+#ifndef BOOST_SIGNALS2_RESULT_TYPE_WRAPPER_HPP
+#define BOOST_SIGNALS2_RESULT_TYPE_WRAPPER_HPP
+
+#include <boost/config.hpp>
+
+namespace boost {
+ namespace signals2 {
+ namespace detail {
+ // A placeholder for void on compilers that don't support void returns
+ struct void_type {};
+
+ // Replaces void with void_type
+ template<typename R>
+ struct nonvoid {
+ typedef R type;
+ };
+ template<>
+ struct nonvoid<void> {
+ typedef void_type type;
+ };
+
+ // Replaces void with void_type only if compiler doesn't support void returns
+ template<typename R>
+ struct result_type_wrapper {
+ typedef R type;
+ };
+#ifdef BOOST_NO_VOID_RETURNS
+ template<>
+ struct result_type_wrapper<void> {
+ typedef void_type type;
+ };
+#endif
+
+ // specialization deals with possible void return from combiners
+ template<typename R> class combiner_invoker
+ {
+ public:
+ typedef R result_type;
+ template<typename Combiner, typename InputIterator>
+ result_type operator()(Combiner &combiner,
+ InputIterator first, InputIterator last) const
+ {
+ return combiner(first, last);
+ }
+ };
+ template<> class combiner_invoker<void>
+ {
+ public:
+ typedef result_type_wrapper<void>::type result_type;
+ template<typename Combiner, typename InputIterator>
+ result_type operator()(Combiner &combiner,
+ InputIterator first, InputIterator last) const
+ {
+ combiner(first, last);
+ return result_type();
+ }
+ };
+ } // end namespace detail
+ } // end namespace signals2
+} // end namespace boost
+
+#endif // BOOST_SIGNALS2_RESULT_TYPE_WRAPPER_HPP
diff --git a/third_party/boost/boost/signals2/detail/signal_template.hpp b/third_party/boost/boost/signals2/detail/signal_template.hpp
new file mode 100644
index 0000000..cbaca65
--- /dev/null
+++ b/third_party/boost/boost/signals2/detail/signal_template.hpp
@@ -0,0 +1,864 @@
+/*
+ Template for Signa1, Signal2, ... classes that support signals
+ with 1, 2, ... parameters
+
+ Begin: 2007-01-23
+*/
+// Copyright Frank Mori Hess 2007-2008
+//
+// Use, modification and
+// distribution is subject to the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// This file is included iteratively, and should not be protected from multiple inclusion
+
+#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
+#define BOOST_SIGNALS2_NUM_ARGS BOOST_PP_ITERATION()
+#else
+#define BOOST_SIGNALS2_NUM_ARGS 1
+#endif
+
+// R, T1, T2, ..., TN, Combiner, Group, GroupCompare, SlotFunction, ExtendedSlotFunction, Mutex
+#define BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION \
+ BOOST_SIGNALS2_SIGNATURE_TEMPLATE_INSTANTIATION(BOOST_SIGNALS2_NUM_ARGS), \
+ Combiner, Group, GroupCompare, SlotFunction, ExtendedSlotFunction, Mutex
+
+namespace boost
+{
+ namespace signals2
+ {
+ namespace detail
+ {
+ // helper for bound_extended_slot_function that handles specialization for void return
+ template<typename R>
+ class BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_INVOKER_N(BOOST_SIGNALS2_NUM_ARGS)
+ {
+ public:
+ typedef R result_type;
+ template<typename ExtendedSlotFunction BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
+ BOOST_SIGNALS2_ARGS_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
+ result_type operator()(ExtendedSlotFunction &func, const connection &conn
+ BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
+ BOOST_SIGNALS2_FULL_FORWARD_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
+ {
+ return func(conn BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
+ BOOST_SIGNALS2_FORWARDED_ARGS(BOOST_SIGNALS2_NUM_ARGS));
+ }
+ };
+#ifdef BOOST_NO_VOID_RETURNS
+ template<>
+ class BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_INVOKER_N(BOOST_SIGNALS2_NUM_ARGS)<void>
+ {
+ public:
+ typedef result_type_wrapper<void>::type result_type;
+ template<typename ExtendedSlotFunction BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
+ BOOST_SIGNALS2_ARGS_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
+ result_type operator()(ExtendedSlotFunction &func, const connection &conn
+ BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
+ BOOST_SIGNALS2_FULL_FORWARD_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
+ {
+ func(conn BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
+ BOOST_SIGNALS2_FORWARDED_ARGS(BOOST_SIGNALS2_NUM_ARGS));
+ return result_type();
+ }
+ };
+#endif
+// wrapper around an signalN::extended_slot_function which binds the
+// connection argument so it looks like a normal
+// signalN::slot_function
+
+ template<typename ExtendedSlotFunction>
+ class BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_N(BOOST_SIGNALS2_NUM_ARGS)
+ {
+ public:
+ typedef typename result_type_wrapper<typename ExtendedSlotFunction::result_type>::type result_type;
+ BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_N(BOOST_SIGNALS2_NUM_ARGS)(const ExtendedSlotFunction &fun):
+ _fun(fun), _connection(new connection)
+ {}
+ void set_connection(const connection &conn)
+ {
+ *_connection = conn;
+ }
+
+#if BOOST_SIGNALS2_NUM_ARGS > 0
+ template<BOOST_SIGNALS2_ARGS_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
+#endif // BOOST_SIGNALS2_NUM_ARGS > 0
+ result_type operator()(BOOST_SIGNALS2_FULL_FORWARD_ARGS(BOOST_SIGNALS2_NUM_ARGS))
+ {
+ return BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_INVOKER_N(BOOST_SIGNALS2_NUM_ARGS)
+ <typename ExtendedSlotFunction::result_type>()
+ (_fun, *_connection BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
+ BOOST_SIGNALS2_FORWARDED_ARGS(BOOST_SIGNALS2_NUM_ARGS));
+ }
+ // const overload
+#if BOOST_SIGNALS2_NUM_ARGS > 0
+ template<BOOST_SIGNALS2_ARGS_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
+#endif // BOOST_SIGNALS2_NUM_ARGS > 0
+ result_type operator()(BOOST_SIGNALS2_FULL_FORWARD_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
+ {
+ return BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_INVOKER_N(BOOST_SIGNALS2_NUM_ARGS)
+ <typename ExtendedSlotFunction::result_type>()
+ (_fun, *_connection BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
+ BOOST_SIGNALS2_FORWARDED_ARGS(BOOST_SIGNALS2_NUM_ARGS));
+ }
+ template<typename T>
+ bool operator==(const T &other) const
+ {
+ return _fun == other;
+ }
+ private:
+ BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_N(BOOST_SIGNALS2_NUM_ARGS)()
+ {}
+
+ ExtendedSlotFunction _fun;
+ boost::shared_ptr<connection> _connection;
+ };
+
+ template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
+ class BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS);
+
+ template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION_DECL(BOOST_SIGNALS2_NUM_ARGS)>
+ class BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION
+ {
+ public:
+ typedef SlotFunction slot_function_type;
+ // typedef slotN<Signature, SlotFunction> slot_type;
+ typedef BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
+ <BOOST_SIGNALS2_SIGNATURE_TEMPLATE_INSTANTIATION(BOOST_SIGNALS2_NUM_ARGS),
+ slot_function_type> slot_type;
+ typedef ExtendedSlotFunction extended_slot_function_type;
+ // typedef slotN+1<R, const connection &, T1, T2, ..., TN, extended_slot_function_type> extended_slot_type;
+ typedef BOOST_SIGNALS2_EXTENDED_SLOT_TYPE(BOOST_SIGNALS2_NUM_ARGS) extended_slot_type;
+ typedef typename nonvoid<typename slot_function_type::result_type>::type nonvoid_slot_result_type;
+ private:
+#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
+ class slot_invoker;
+#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
+ typedef variadic_slot_invoker<nonvoid_slot_result_type, Args...> slot_invoker;
+#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
+ typedef slot_call_iterator_cache<nonvoid_slot_result_type, slot_invoker> slot_call_iterator_cache_type;
+ typedef typename group_key<Group>::type group_key_type;
+ typedef shared_ptr<connection_body<group_key_type, slot_type, Mutex> > connection_body_type;
+ typedef grouped_list<Group, GroupCompare, connection_body_type> connection_list_type;
+ typedef BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_N(BOOST_SIGNALS2_NUM_ARGS)<extended_slot_function_type>
+ bound_extended_slot_function_type;
+ public:
+ typedef Combiner combiner_type;
+ typedef typename result_type_wrapper<typename combiner_type::result_type>::type result_type;
+ typedef Group group_type;
+ typedef GroupCompare group_compare_type;
+ typedef typename detail::slot_call_iterator_t<slot_invoker,
+ typename connection_list_type::iterator, connection_body<group_key_type, slot_type, Mutex> > slot_call_iterator;
+
+ BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(const combiner_type &combiner_arg,
+ const group_compare_type &group_compare):
+ _shared_state(new invocation_state(connection_list_type(group_compare), combiner_arg)),
+ _garbage_collector_it(_shared_state->connection_bodies().end()),
+ _mutex(new mutex_type())
+ {}
+ // connect slot
+ connection connect(const slot_type &slot, connect_position position = at_back)
+ {
+ garbage_collecting_lock<mutex_type> lock(*_mutex);
+ return nolock_connect(lock, slot, position);
+ }
+ connection connect(const group_type &group,
+ const slot_type &slot, connect_position position = at_back)
+ {
+ garbage_collecting_lock<mutex_type> lock(*_mutex);
+ return nolock_connect(lock, group, slot, position);
+ }
+ // connect extended slot
+ connection connect_extended(const extended_slot_type &ext_slot, connect_position position = at_back)
+ {
+ garbage_collecting_lock<mutex_type> lock(*_mutex);
+ bound_extended_slot_function_type bound_slot(ext_slot.slot_function());
+ slot_type slot = replace_slot_function<slot_type>(ext_slot, bound_slot);
+ connection conn = nolock_connect(lock, slot, position);
+ bound_slot.set_connection(conn);
+ return conn;
+ }
+ connection connect_extended(const group_type &group,
+ const extended_slot_type &ext_slot, connect_position position = at_back)
+ {
+ garbage_collecting_lock<Mutex> lock(*_mutex);
+ bound_extended_slot_function_type bound_slot(ext_slot.slot_function());
+ slot_type slot = replace_slot_function<slot_type>(ext_slot, bound_slot);
+ connection conn = nolock_connect(lock, group, slot, position);
+ bound_slot.set_connection(conn);
+ return conn;
+ }
+ // disconnect slot(s)
+ void disconnect_all_slots()
+ {
+ shared_ptr<invocation_state> local_state =
+ get_readable_state();
+ typename connection_list_type::iterator it;
+ for(it = local_state->connection_bodies().begin();
+ it != local_state->connection_bodies().end(); ++it)
+ {
+ (*it)->disconnect();
+ }
+ }
+ void disconnect(const group_type &group)
+ {
+ shared_ptr<invocation_state> local_state =
+ get_readable_state();
+ group_key_type group_key(grouped_slots, group);
+ typename connection_list_type::iterator it;
+ typename connection_list_type::iterator end_it =
+ local_state->connection_bodies().upper_bound(group_key);
+ for(it = local_state->connection_bodies().lower_bound(group_key);
+ it != end_it; ++it)
+ {
+ (*it)->disconnect();
+ }
+ }
+ template <typename T>
+ void disconnect(const T &slot)
+ {
+ typedef mpl::bool_<(is_convertible<T, group_type>::value)> is_group;
+ do_disconnect(slot, is_group());
+ }
+ // emit signal
+ result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS))
+ {
+ shared_ptr<invocation_state> local_state;
+ typename connection_list_type::iterator it;
+ {
+ garbage_collecting_lock<mutex_type> list_lock(*_mutex);
+ // only clean up if it is safe to do so
+ if(_shared_state.unique())
+ nolock_cleanup_connections(list_lock, false, 1);
+ /* Make a local copy of _shared_state while holding mutex, so we are
+ thread safe against the combiner or connection list getting modified
+ during invocation. */
+ local_state = _shared_state;
+ }
+ slot_invoker invoker = slot_invoker(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
+ slot_call_iterator_cache_type cache(invoker);
+ invocation_janitor janitor(cache, *this, &local_state->connection_bodies());
+ return detail::combiner_invoker<typename combiner_type::result_type>()
+ (
+ local_state->combiner(),
+ slot_call_iterator(local_state->connection_bodies().begin(), local_state->connection_bodies().end(), cache),
+ slot_call_iterator(local_state->connection_bodies().end(), local_state->connection_bodies().end(), cache)
+ );
+ }
+ result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
+ {
+ shared_ptr<invocation_state> local_state;
+ typename connection_list_type::iterator it;
+ {
+ garbage_collecting_lock<mutex_type> list_lock(*_mutex);
+ // only clean up if it is safe to do so
+ if(_shared_state.unique())
+ nolock_cleanup_connections(list_lock, false, 1);
+ /* Make a local copy of _shared_state while holding mutex, so we are
+ thread safe against the combiner or connection list getting modified
+ during invocation. */
+ local_state = _shared_state;
+ }
+ slot_invoker invoker = slot_invoker(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
+ slot_call_iterator_cache_type cache(invoker);
+ invocation_janitor janitor(cache, *this, &local_state->connection_bodies());
+ return detail::combiner_invoker<typename combiner_type::result_type>()
+ (
+ local_state->combiner(),
+ slot_call_iterator(local_state->connection_bodies().begin(), local_state->connection_bodies().end(), cache),
+ slot_call_iterator(local_state->connection_bodies().end(), local_state->connection_bodies().end(), cache)
+ );
+ }
+ std::size_t num_slots() const
+ {
+ shared_ptr<invocation_state> local_state =
+ get_readable_state();
+ typename connection_list_type::iterator it;
+ std::size_t count = 0;
+ for(it = local_state->connection_bodies().begin();
+ it != local_state->connection_bodies().end(); ++it)
+ {
+ if((*it)->connected()) ++count;
+ }
+ return count;
+ }
+ bool empty() const
+ {
+ shared_ptr<invocation_state> local_state =
+ get_readable_state();
+ typename connection_list_type::iterator it;
+ for(it = local_state->connection_bodies().begin();
+ it != local_state->connection_bodies().end(); ++it)
+ {
+ if((*it)->connected()) return false;
+ }
+ return true;
+ }
+ combiner_type combiner() const
+ {
+ unique_lock<mutex_type> lock(*_mutex);
+ return _shared_state->combiner();
+ }
+ void set_combiner(const combiner_type &combiner_arg)
+ {
+ unique_lock<mutex_type> lock(*_mutex);
+ if(_shared_state.unique())
+ _shared_state->combiner() = combiner_arg;
+ else
+ _shared_state.reset(new invocation_state(*_shared_state, combiner_arg));
+ }
+ private:
+ typedef Mutex mutex_type;
+
+ // slot_invoker is passed to slot_call_iterator_t to run slots
+#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
+ class slot_invoker
+ {
+ public:
+ typedef nonvoid_slot_result_type result_type;
+// typename add_reference<Tn>::type
+#define BOOST_SIGNALS2_ADD_REF_TYPE(z, n, data) \
+ typename add_reference<BOOST_PP_CAT(T, BOOST_PP_INC(n))>::type
+// typename add_reference<Tn>::type argn
+#define BOOST_SIGNALS2_ADD_REF_ARG(z, n, data) \
+ BOOST_SIGNALS2_ADD_REF_TYPE(~, n, ~) \
+ BOOST_SIGNALS2_SIGNATURE_ARG_NAME(~, n, ~)
+// typename add_reference<T1>::type arg1, typename add_reference<T2>::type arg2, ..., typename add_reference<Tn>::type argn
+#define BOOST_SIGNALS2_ADD_REF_ARGS(arity) \
+ BOOST_PP_ENUM(arity, BOOST_SIGNALS2_ADD_REF_ARG, ~)
+ slot_invoker(BOOST_SIGNALS2_ADD_REF_ARGS(BOOST_SIGNALS2_NUM_ARGS)) BOOST_PP_EXPR_IF(BOOST_SIGNALS2_NUM_ARGS, :)
+#undef BOOST_SIGNALS2_ADD_REF_ARGS
+
+// m_argn
+#define BOOST_SIGNALS2_M_ARG_NAME(z, n, data) BOOST_PP_CAT(m_arg, BOOST_PP_INC(n))
+// m_argn ( argn )
+#define BOOST_SIGNALS2_MISC_STATEMENT(z, n, data) \
+ BOOST_SIGNALS2_M_ARG_NAME(~, n, ~) ( BOOST_SIGNALS2_SIGNATURE_ARG_NAME(~, n, ~) )
+// m_arg1(arg1), m_arg2(arg2), ..., m_argn(argn)
+ BOOST_PP_ENUM(BOOST_SIGNALS2_NUM_ARGS, BOOST_SIGNALS2_MISC_STATEMENT, ~)
+#undef BOOST_SIGNALS2_MISC_STATEMENT
+ {}
+ result_type operator ()(const connection_body_type &connectionBody) const
+ {
+ return m_invoke<typename slot_type::result_type>(connectionBody);
+ }
+ private:
+ // declare assignment operator private since this class might have reference or const members
+ slot_invoker & operator=(const slot_invoker &);
+
+#define BOOST_SIGNALS2_ADD_REF_M_ARG_STATEMENT(z, n, data) \
+ BOOST_SIGNALS2_ADD_REF_TYPE(~, n, ~) BOOST_SIGNALS2_M_ARG_NAME(~, n, ~) ;
+ BOOST_PP_REPEAT(BOOST_SIGNALS2_NUM_ARGS, BOOST_SIGNALS2_ADD_REF_M_ARG_STATEMENT, ~)
+#undef BOOST_SIGNALS2_ADD_REF_M_ARG_STATEMENT
+#undef BOOST_SIGNALS2_ADD_REF_ARG
+#undef BOOST_SIGNALS2_ADD_REF_TYPE
+
+// m_arg1, m_arg2, ..., m_argn
+#define BOOST_SIGNALS2_M_ARG_NAMES(arity) BOOST_PP_ENUM(arity, BOOST_SIGNALS2_M_ARG_NAME, ~)
+ template<typename SlotResultType>
+ result_type m_invoke(const connection_body_type &connectionBody,
+ typename boost::enable_if<boost::is_void<SlotResultType> >::type * = 0) const
+ {
+ connectionBody->slot().slot_function()(BOOST_SIGNALS2_M_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
+ return void_type();
+ }
+ template<typename SlotResultType>
+ result_type m_invoke(const connection_body_type &connectionBody,
+ typename boost::disable_if<boost::is_void<SlotResultType> >::type * = 0) const
+ {
+ return connectionBody->slot().slot_function()(BOOST_SIGNALS2_M_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
+ }
+ };
+#undef BOOST_SIGNALS2_M_ARG_NAMES
+#undef BOOST_SIGNALS2_M_ARG_NAME
+
+#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
+ // a struct used to optimize (minimize) the number of shared_ptrs that need to be created
+ // inside operator()
+ class invocation_state
+ {
+ public:
+ invocation_state(const connection_list_type &connections_in,
+ const combiner_type &combiner_in): _connection_bodies(new connection_list_type(connections_in)),
+ _combiner(new combiner_type(combiner_in))
+ {}
+ invocation_state(const invocation_state &other, const connection_list_type &connections_in):
+ _connection_bodies(new connection_list_type(connections_in)),
+ _combiner(other._combiner)
+ {}
+ invocation_state(const invocation_state &other, const combiner_type &combiner_in):
+ _connection_bodies(other._connection_bodies),
+ _combiner(new combiner_type(combiner_in))
+ {}
+ connection_list_type & connection_bodies() { return *_connection_bodies; }
+ const connection_list_type & connection_bodies() const { return *_connection_bodies; }
+ combiner_type & combiner() { return *_combiner; }
+ const combiner_type & combiner() const { return *_combiner; }
+ private:
+ invocation_state(const invocation_state &);
+
+ shared_ptr<connection_list_type> _connection_bodies;
+ shared_ptr<combiner_type> _combiner;
+ };
+ // Destructor of invocation_janitor does some cleanup when a signal invocation completes.
+ // Code can't be put directly in signal's operator() due to complications from void return types.
+ class invocation_janitor: noncopyable
+ {
+ public:
+ typedef BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) signal_type;
+ invocation_janitor
+ (
+ const slot_call_iterator_cache_type &cache,
+ const signal_type &sig,
+ const connection_list_type *connection_bodies
+ ):_cache(cache), _sig(sig), _connection_bodies(connection_bodies)
+ {}
+ ~invocation_janitor()
+ {
+ // force a full cleanup of disconnected slots if there are too many
+ if(_cache.disconnected_slot_count > _cache.connected_slot_count)
+ {
+ _sig.force_cleanup_connections(_connection_bodies);
+ }
+ }
+ private:
+ const slot_call_iterator_cache_type &_cache;
+ const signal_type &_sig;
+ const connection_list_type *_connection_bodies;
+ };
+
+ // clean up disconnected connections
+ void nolock_cleanup_connections_from(garbage_collecting_lock<mutex_type> &lock,
+ bool grab_tracked,
+ const typename connection_list_type::iterator &begin, unsigned count = 0) const
+ {
+ BOOST_ASSERT(_shared_state.unique());
+ typename connection_list_type::iterator it;
+ unsigned i;
+ for(it = begin, i = 0;
+ it != _shared_state->connection_bodies().end() && (count == 0 || i < count);
+ ++i)
+ {
+ bool connected;
+ if(grab_tracked)
+ (*it)->disconnect_expired_slot(lock);
+ connected = (*it)->nolock_nograb_connected();
+ if(connected == false)
+ {
+ it = _shared_state->connection_bodies().erase((*it)->group_key(), it);
+ }else
+ {
+ ++it;
+ }
+ }
+ _garbage_collector_it = it;
+ }
+ // clean up a few connections in constant time
+ void nolock_cleanup_connections(garbage_collecting_lock<mutex_type> &lock,
+ bool grab_tracked, unsigned count) const
+ {
+ BOOST_ASSERT(_shared_state.unique());
+ typename connection_list_type::iterator begin;
+ if(_garbage_collector_it == _shared_state->connection_bodies().end())
+ {
+ begin = _shared_state->connection_bodies().begin();
+ }else
+ {
+ begin = _garbage_collector_it;
+ }
+ nolock_cleanup_connections_from(lock, grab_tracked, begin, count);
+ }
+ /* Make a new copy of the slot list if it is currently being read somewhere else
+ */
+ void nolock_force_unique_connection_list(garbage_collecting_lock<mutex_type> &lock)
+ {
+ if(_shared_state.unique() == false)
+ {
+ _shared_state.reset(new invocation_state(*_shared_state, _shared_state->connection_bodies()));
+ nolock_cleanup_connections_from(lock, true, _shared_state->connection_bodies().begin());
+ }else
+ {
+ /* We need to try and check more than just 1 connection here to avoid corner
+ cases where certain repeated connect/disconnect patterns cause the slot
+ list to grow without limit. */
+ nolock_cleanup_connections(lock, true, 2);
+ }
+ }
+ // force a full cleanup of the connection list
+ void force_cleanup_connections(const connection_list_type *connection_bodies) const
+ {
+ garbage_collecting_lock<mutex_type> list_lock(*_mutex);
+ // if the connection list passed in as a parameter is no longer in use,
+ // we don't need to do any cleanup.
+ if(&_shared_state->connection_bodies() != connection_bodies)
+ {
+ return;
+ }
+ if(_shared_state.unique() == false)
+ {
+ _shared_state.reset(new invocation_state(*_shared_state, _shared_state->connection_bodies()));
+ }
+ nolock_cleanup_connections_from(list_lock, false, _shared_state->connection_bodies().begin());
+ }
+ shared_ptr<invocation_state> get_readable_state() const
+ {
+ unique_lock<mutex_type> list_lock(*_mutex);
+ return _shared_state;
+ }
+ connection_body_type create_new_connection(garbage_collecting_lock<mutex_type> &lock,
+ const slot_type &slot)
+ {
+ nolock_force_unique_connection_list(lock);
+ return connection_body_type(new connection_body<group_key_type, slot_type, Mutex>(slot, _mutex));
+ }
+ void do_disconnect(const group_type &group, mpl::bool_<true> /* is_group */)
+ {
+ disconnect(group);
+ }
+ template<typename T>
+ void do_disconnect(const T &slot, mpl::bool_<false> /* is_group */)
+ {
+ shared_ptr<invocation_state> local_state =
+ get_readable_state();
+ typename connection_list_type::iterator it;
+ for(it = local_state->connection_bodies().begin();
+ it != local_state->connection_bodies().end(); ++it)
+ {
+ garbage_collecting_lock<connection_body_base> lock(**it);
+ if((*it)->nolock_nograb_connected() == false) continue;
+ if((*it)->slot().slot_function() == slot)
+ {
+ (*it)->nolock_disconnect(lock);
+ }else
+ {
+ // check for wrapped extended slot
+ bound_extended_slot_function_type *fp;
+ fp = (*it)->slot().slot_function().template target<bound_extended_slot_function_type>();
+ if(fp && *fp == slot)
+ {
+ (*it)->nolock_disconnect(lock);
+ }
+ }
+ }
+ }
+ // connect slot
+ connection nolock_connect(garbage_collecting_lock<mutex_type> &lock,
+ const slot_type &slot, connect_position position)
+ {
+ connection_body_type newConnectionBody =
+ create_new_connection(lock, slot);
+ group_key_type group_key;
+ if(position == at_back)
+ {
+ group_key.first = back_ungrouped_slots;
+ _shared_state->connection_bodies().push_back(group_key, newConnectionBody);
+ }else
+ {
+ group_key.first = front_ungrouped_slots;
+ _shared_state->connection_bodies().push_front(group_key, newConnectionBody);
+ }
+ newConnectionBody->set_group_key(group_key);
+ return connection(newConnectionBody);
+ }
+ connection nolock_connect(garbage_collecting_lock<mutex_type> &lock,
+ const group_type &group,
+ const slot_type &slot, connect_position position)
+ {
+ connection_body_type newConnectionBody =
+ create_new_connection(lock, slot);
+ // update map to first connection body in group if needed
+ group_key_type group_key(grouped_slots, group);
+ newConnectionBody->set_group_key(group_key);
+ if(position == at_back)
+ {
+ _shared_state->connection_bodies().push_back(group_key, newConnectionBody);
+ }else // at_front
+ {
+ _shared_state->connection_bodies().push_front(group_key, newConnectionBody);
+ }
+ return connection(newConnectionBody);
+ }
+
+ // _shared_state is mutable so we can do force_cleanup_connections during a const invocation
+ mutable shared_ptr<invocation_state> _shared_state;
+ mutable typename connection_list_type::iterator _garbage_collector_it;
+ // connection list mutex must never be locked when attempting a blocking lock on a slot,
+ // or you could deadlock.
+ const boost::shared_ptr<mutex_type> _mutex;
+ };
+
+ template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
+ class BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS);
+ }
+
+ template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_DEFAULTED_DECL(BOOST_SIGNALS2_NUM_ARGS)>
+ class BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS);
+
+ template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION_DECL(BOOST_SIGNALS2_NUM_ARGS)>
+ class BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
+ BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION: public signal_base,
+ public detail::BOOST_SIGNALS2_STD_FUNCTIONAL_BASE
+ (typename detail::result_type_wrapper<typename Combiner::result_type>::type)
+ {
+ typedef detail::BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
+ <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> impl_class;
+ public:
+ typedef detail::BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
+ <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> weak_signal_type;
+ friend class detail::BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
+ <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION>;
+
+ typedef SlotFunction slot_function_type;
+ // typedef slotN<Signature, SlotFunction> slot_type;
+ typedef typename impl_class::slot_type slot_type;
+ typedef typename impl_class::extended_slot_function_type extended_slot_function_type;
+ typedef typename impl_class::extended_slot_type extended_slot_type;
+ typedef typename slot_function_type::result_type slot_result_type;
+ typedef Combiner combiner_type;
+ typedef typename impl_class::result_type result_type;
+ typedef Group group_type;
+ typedef GroupCompare group_compare_type;
+ typedef typename impl_class::slot_call_iterator
+ slot_call_iterator;
+ typedef typename mpl::identity<BOOST_SIGNALS2_SIGNATURE_FUNCTION_TYPE(BOOST_SIGNALS2_NUM_ARGS)>::type signature_type;
+
+#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+// typedef Tn argn_type;
+#define BOOST_SIGNALS2_MISC_STATEMENT(z, n, data) \
+ typedef BOOST_PP_CAT(T, BOOST_PP_INC(n)) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(n)), _type);
+ BOOST_PP_REPEAT(BOOST_SIGNALS2_NUM_ARGS, BOOST_SIGNALS2_MISC_STATEMENT, ~)
+#undef BOOST_SIGNALS2_MISC_STATEMENT
+#if BOOST_SIGNALS2_NUM_ARGS == 1
+ typedef arg1_type argument_type;
+#elif BOOST_SIGNALS2_NUM_ARGS == 2
+ typedef arg1_type first_argument_type;
+ typedef arg2_type second_argument_type;
+#endif
+
+ template<unsigned n> class arg : public
+ detail::BOOST_SIGNALS2_PREPROCESSED_ARG_N_TYPE_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
+ <n BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
+ BOOST_SIGNALS2_ARGS_TEMPLATE_INSTANTIATION(BOOST_SIGNALS2_NUM_ARGS)>
+ {};
+
+ BOOST_STATIC_CONSTANT(int, arity = BOOST_SIGNALS2_NUM_ARGS);
+
+#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+ template<unsigned n> class arg
+ {
+ public:
+ typedef typename detail::variadic_arg_type<n, Args...>::type type;
+ };
+ BOOST_STATIC_CONSTANT(int, arity = sizeof...(Args));
+
+#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+ BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(const combiner_type &combiner_arg = combiner_type(),
+ const group_compare_type &group_compare = group_compare_type()):
+ _pimpl(new impl_class(combiner_arg, group_compare))
+ {};
+ virtual ~BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)()
+ {
+ }
+
+ //move support
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(
+ BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) && other)
+ {
+ using std::swap;
+ swap(_pimpl, other._pimpl);
+ };
+
+ BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) &
+ operator=(BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) && rhs)
+ {
+ if(this == &rhs)
+ {
+ return *this;
+ }
+ _pimpl.reset();
+ using std::swap;
+ swap(_pimpl, rhs._pimpl);
+ return *this;
+ }
+#endif // !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+ connection connect(const slot_type &slot, connect_position position = at_back)
+ {
+ return (*_pimpl).connect(slot, position);
+ }
+ connection connect(const group_type &group,
+ const slot_type &slot, connect_position position = at_back)
+ {
+ return (*_pimpl).connect(group, slot, position);
+ }
+ connection connect_extended(const extended_slot_type &slot, connect_position position = at_back)
+ {
+ return (*_pimpl).connect_extended(slot, position);
+ }
+ connection connect_extended(const group_type &group,
+ const extended_slot_type &slot, connect_position position = at_back)
+ {
+ return (*_pimpl).connect_extended(group, slot, position);
+ }
+ void disconnect_all_slots()
+ {
+ (*_pimpl).disconnect_all_slots();
+ }
+ void disconnect(const group_type &group)
+ {
+ (*_pimpl).disconnect(group);
+ }
+ template <typename T>
+ void disconnect(const T &slot)
+ {
+ (*_pimpl).disconnect(slot);
+ }
+ result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS))
+ {
+ return (*_pimpl)(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
+ }
+ result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
+ {
+ return (*_pimpl)(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
+ }
+ std::size_t num_slots() const
+ {
+ return (*_pimpl).num_slots();
+ }
+ bool empty() const
+ {
+ return (*_pimpl).empty();
+ }
+ combiner_type combiner() const
+ {
+ return (*_pimpl).combiner();
+ }
+ void set_combiner(const combiner_type &combiner_arg)
+ {
+ return (*_pimpl).set_combiner(combiner_arg);
+ }
+ void swap(BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) & other)
+ {
+ using std::swap;
+ swap(_pimpl, other._pimpl);
+ }
+ protected:
+ virtual shared_ptr<void> lock_pimpl() const
+ {
+ return _pimpl;
+ }
+ private:
+ shared_ptr<impl_class>
+ _pimpl;
+ };
+
+#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
+ // free swap function for signalN classes, findable by ADL
+ template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
+ void swap(
+ BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> &sig1,
+ BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> &sig2 )
+ {
+ sig1.swap(sig2);
+ }
+#endif
+
+ namespace detail
+ {
+ // wrapper class for storing other signals as slots with automatic lifetime tracking
+ template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS)>
+ class BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS);
+
+ template<BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION_DECL(BOOST_SIGNALS2_NUM_ARGS)>
+ class BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
+ BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION
+ {
+ public:
+ typedef typename BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
+ <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION>::result_type
+ result_type;
+
+ BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
+ (const BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
+ <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION>
+ &signal):
+ _weak_pimpl(signal._pimpl)
+ {}
+ result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS))
+ {
+ shared_ptr<detail::BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
+ <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> >
+ shared_pimpl(_weak_pimpl.lock());
+ if(shared_pimpl == 0) throw expired_slot();
+ return (*shared_pimpl)(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
+ }
+ result_type operator ()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
+ {
+ shared_ptr<detail::BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
+ <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> >
+ shared_pimpl(_weak_pimpl.lock());
+ if(shared_pimpl == 0) throw expired_slot();
+ return (*shared_pimpl)(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
+ }
+ private:
+ boost::weak_ptr<detail::BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
+ <BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION> > _weak_pimpl;
+ };
+
+#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
+ template<int arity, typename Signature>
+ class extended_signature: public variadic_extended_signature<Signature>
+ {};
+#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
+ template<int arity, typename Signature>
+ class extended_signature;
+ // partial template specialization
+ template<typename Signature>
+ class extended_signature<BOOST_SIGNALS2_NUM_ARGS, Signature>
+ {
+ public:
+// typename function_traits<Signature>::result_type (
+// const boost::signals2::connection &,
+// typename function_traits<Signature>::arg1_type,
+// typename function_traits<Signature>::arg2_type,
+// ...,
+// typename function_traits<Signature>::argn_type)
+#define BOOST_SIGNALS2_EXT_SIGNATURE(arity, Signature) \
+ typename function_traits<Signature>::result_type ( \
+ const boost::signals2::connection & BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS) \
+ BOOST_PP_ENUM(arity, BOOST_SIGNALS2_SIGNATURE_TO_ARGN_TYPE, Signature) )
+ typedef function<BOOST_SIGNALS2_EXT_SIGNATURE(BOOST_SIGNALS2_NUM_ARGS, Signature)> function_type;
+#undef BOOST_SIGNALS2_EXT_SIGNATURE
+ };
+
+ template<unsigned arity, typename Signature, typename Combiner,
+ typename Group, typename GroupCompare, typename SlotFunction,
+ typename ExtendedSlotFunction, typename Mutex>
+ class signalN;
+ // partial template specialization
+ template<typename Signature, typename Combiner, typename Group,
+ typename GroupCompare, typename SlotFunction,
+ typename ExtendedSlotFunction, typename Mutex>
+ class signalN<BOOST_SIGNALS2_NUM_ARGS, Signature, Combiner, Group,
+ GroupCompare, SlotFunction, ExtendedSlotFunction, Mutex>
+ {
+ public:
+ typedef BOOST_SIGNALS2_SIGNAL_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)<
+ BOOST_SIGNALS2_PORTABLE_SIGNATURE(BOOST_SIGNALS2_NUM_ARGS, Signature),
+ Combiner, Group,
+ GroupCompare, SlotFunction, ExtendedSlotFunction, Mutex> type;
+ };
+
+#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+ } // namespace detail
+ } // namespace signals2
+} // namespace boost
+
+#undef BOOST_SIGNALS2_NUM_ARGS
+#undef BOOST_SIGNALS2_SIGNAL_TEMPLATE_INSTANTIATION
diff --git a/third_party/boost/boost/signals2/detail/signals_common.hpp b/third_party/boost/boost/signals2/detail/signals_common.hpp
new file mode 100644
index 0000000..8c4baf0
--- /dev/null
+++ b/third_party/boost/boost/signals2/detail/signals_common.hpp
@@ -0,0 +1,77 @@
+// Boost.Signals library
+
+// Copyright Douglas Gregor 2001-2004.
+// Copyright Frank Mori Hess 2007. Use, modification and
+// distribution is subject to the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// For more information, see http://www.boost.org
+
+#ifndef BOOST_SIGNALS2_SIGNALS_COMMON_HPP
+#define BOOST_SIGNALS2_SIGNALS_COMMON_HPP
+
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/ref.hpp>
+#include <boost/signals2/signal_base.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+
+namespace boost {
+ namespace signals2 {
+ namespace detail {
+ // Determine if the given type T is a signal
+ template<typename T>
+ class is_signal: public mpl::bool_<is_base_of<signal_base, T>::value>
+ {};
+
+ // A slot can be a signal, a reference to a function object, or a
+ // function object.
+ struct signal_tag {};
+ struct reference_tag {};
+ struct value_tag {};
+
+ // Classify the given slot as a signal, a reference-to-slot, or a
+ // standard slot
+ template<typename S>
+ class get_slot_tag {
+ typedef typename mpl::if_<is_signal<S>,
+ signal_tag, value_tag>::type signal_or_value;
+ public:
+ typedef typename mpl::if_<is_reference_wrapper<S>,
+ reference_tag,
+ signal_or_value>::type type;
+ };
+
+ // Get the slot so that it can be copied
+ template<typename F>
+ typename F::weak_signal_type
+ get_invocable_slot(const F &signal, signal_tag)
+ { return typename F::weak_signal_type(signal); }
+
+ template<typename F>
+ const F&
+ get_invocable_slot(const F& f, reference_tag)
+ { return f; }
+
+ template<typename F>
+ const F&
+ get_invocable_slot(const F& f, value_tag)
+ { return f; }
+
+ // Determines the type of the slot - is it a signal, a reference to a
+ // slot or just a normal slot.
+ template<typename F>
+ typename get_slot_tag<F>::type
+ tag_type(const F&)
+ {
+ typedef typename get_slot_tag<F>::type
+ the_tag_type;
+ the_tag_type tag = the_tag_type();
+ return tag;
+ }
+ } // end namespace detail
+ } // end namespace signals2
+} // end namespace boost
+
+#endif // BOOST_SIGNALS2_SIGNALS_COMMON_HPP
diff --git a/third_party/boost/boost/signals2/detail/signals_common_macros.hpp b/third_party/boost/boost/signals2/detail/signals_common_macros.hpp
new file mode 100644
index 0000000..4ca4403
--- /dev/null
+++ b/third_party/boost/boost/signals2/detail/signals_common_macros.hpp
@@ -0,0 +1,215 @@
+/*
+ Author: Frank Mori Hess <fmhess@users.sourceforge.net>
+ Begin: 2007-01-23
+*/
+// Copyright Frank Mori Hess 2007-2008
+// Use, modification and
+// distribution is subject to the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_SIGNALS2_SIGNALS_COMMON_MACROS_HPP
+#define BOOST_SIGNALS2_SIGNALS_COMMON_MACROS_HPP
+
+#include <boost/config.hpp>
+
+#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+#ifndef BOOST_SIGNALS2_MAX_ARGS
+#define BOOST_SIGNALS2_MAX_ARGS 9
+#endif
+
+// signaln
+#define BOOST_SIGNALS2_SIGNAL_CLASS_NAME(arity) BOOST_PP_CAT(signal, arity)
+// weak_signaln
+#define BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(arity) BOOST_PP_CAT(weak_, BOOST_SIGNALS2_SIGNAL_CLASS_NAME(arity))
+// signaln_impl
+#define BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(arity) BOOST_PP_CAT(BOOST_SIGNALS2_SIGNAL_CLASS_NAME(arity), _impl)
+// argn
+#define BOOST_SIGNALS2_SIGNATURE_ARG_NAME(z, n, data) BOOST_PP_CAT(arg, BOOST_PP_INC(n))
+// Tn argn
+#define BOOST_SIGNALS2_SIGNATURE_FULL_ARG(z, n, data) \
+ BOOST_PP_CAT(T, BOOST_PP_INC(n)) BOOST_SIGNALS2_SIGNATURE_ARG_NAME(~, n, ~)
+// T1 arg1, T2 arg2, ..., Tn argn
+#define BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(arity) \
+ BOOST_PP_ENUM(arity, BOOST_SIGNALS2_SIGNATURE_FULL_ARG, ~)
+// arg1, arg2, ..., argn
+#define BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(arity) BOOST_PP_ENUM(arity, BOOST_SIGNALS2_SIGNATURE_ARG_NAME, ~)
+// T1, T2, ..., TN
+#define BOOST_SIGNALS2_ARGS_TEMPLATE_INSTANTIATION(arity) \
+ BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(arity), T)
+// R (T1, T2, ..., TN)
+#define BOOST_SIGNALS2_SIGNATURE_FUNCTION_TYPE(arity) \
+ R ( BOOST_SIGNALS2_ARGS_TEMPLATE_INSTANTIATION(arity) )
+// typename prefixR, typename prefixT1, typename prefixT2, ..., typename prefixTN
+#define BOOST_SIGNALS2_PREFIXED_SIGNATURE_TEMPLATE_DECL(arity, prefix) \
+ typename BOOST_PP_CAT(prefix, R) BOOST_PP_COMMA_IF(arity) \
+ BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(arity), typename BOOST_PP_CAT(prefix, T))
+// typename R, typename T1, typename T2, ..., typename TN
+#define BOOST_SIGNALS2_SIGNATURE_TEMPLATE_DECL(arity) \
+ typename R BOOST_PP_COMMA_IF(arity) \
+ BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(arity), typename T)
+// typename prefixT1, typename prefixT2, ..., typename prefixTN
+#define BOOST_SIGNALS2_PREFIXED_ARGS_TEMPLATE_DECL(arity, prefix) \
+ BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(arity), typename BOOST_PP_CAT(prefix, T))
+// typename T1, typename T2, ..., typename TN
+#define BOOST_SIGNALS2_ARGS_TEMPLATE_DECL(arity) \
+ BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(arity), typename T)
+// prefixR, prefixT1, prefixT2, ..., prefixTN
+#define BOOST_SIGNALS2_PREFIXED_SIGNATURE_TEMPLATE_INSTANTIATION(arity, prefix) \
+ BOOST_PP_CAT(prefix, R) BOOST_PP_COMMA_IF(arity) BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(arity), BOOST_PP_CAT(prefix, T))
+// R, T1, T2, ..., TN
+#define BOOST_SIGNALS2_SIGNATURE_TEMPLATE_INSTANTIATION(arity) \
+ R BOOST_PP_COMMA_IF(arity) BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(arity), T)
+// boost::functionN<R, T1, T2, ..., TN>
+#define BOOST_SIGNALS2_FUNCTION_N_DECL(arity) BOOST_PP_CAT(boost::function, arity)<\
+ BOOST_SIGNALS2_SIGNATURE_TEMPLATE_INSTANTIATION(arity) >
+// R, const boost::signals2::connection&, T1, T2, ..., TN
+#define BOOST_SIGNALS2_EXT_SLOT_TEMPLATE_INSTANTIATION(arity) \
+ R, const boost::signals2::connection& BOOST_PP_COMMA_IF(arity) \
+ BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_INC(arity), T)
+// boost::functionN<R, const boost::signals2::connection &, T1, T2, ..., TN>
+#define BOOST_SIGNALS2_EXT_FUNCTION_N_DECL(arity) BOOST_PP_CAT(boost::function, BOOST_PP_INC(arity))<\
+ BOOST_SIGNALS2_EXT_SLOT_TEMPLATE_INSTANTIATION(arity) >
+// slotN
+#define BOOST_SIGNALS2_SLOT_CLASS_NAME(arity) BOOST_PP_CAT(slot, arity)
+// slotN+1<R, const connection &, T1, T2, ..., TN, extended_slot_function_type>
+#define BOOST_SIGNALS2_EXTENDED_SLOT_TYPE(arity) \
+ BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_PP_INC(arity))< \
+ BOOST_SIGNALS2_EXT_SLOT_TEMPLATE_INSTANTIATION(arity), \
+ extended_slot_function_type>
+// bound_extended_slot_functionN
+#define BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_N(arity) BOOST_PP_CAT(bound_extended_slot_function, arity)
+// bound_extended_slot_function_helperN
+#define BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_INVOKER_N(arity) BOOST_PP_CAT(bound_extended_slot_function_invoker, arity)
+// typename function_traits<Signature>::argn_type
+#define BOOST_SIGNALS2_SIGNATURE_TO_ARGN_TYPE(z, n, Signature) \
+ BOOST_PP_CAT(BOOST_PP_CAT(typename function_traits<Signature>::arg, BOOST_PP_INC(n)), _type)
+// typename function_traits<Signature>::result_type,
+// typename function_traits<Signature>::arg1_type,
+// typename function_traits<Signature>::arg2_type,
+// ...,
+// typename function_traits<Signature>::argn_type
+#define BOOST_SIGNALS2_PORTABLE_SIGNATURE(arity, Signature) \
+ typename function_traits<Signature>::result_type \
+ BOOST_PP_COMMA_IF(arity) BOOST_PP_ENUM(arity, BOOST_SIGNALS2_SIGNATURE_TO_ARGN_TYPE, Signature)
+// prefixTn & argn
+#define BOOST_SIGNALS2_PREFIXED_FULL_REF_ARG(z, n, prefix) \
+ BOOST_PP_CAT(BOOST_PP_CAT(prefix, T), BOOST_PP_INC(n)) & BOOST_SIGNALS2_SIGNATURE_ARG_NAME(~, n, ~)
+// prefixT1 & arg1, prefixT2 & arg2, ..., prefixTn & argn
+#define BOOST_SIGNALS2_PREFIXED_FULL_REF_ARGS(arity, prefix) \
+ BOOST_PP_ENUM(arity, BOOST_SIGNALS2_PREFIXED_FULL_REF_ARG, prefix)
+// Tn & argn
+#define BOOST_SIGNALS2_FULL_CREF_ARG(z, n, data) \
+ const BOOST_PP_CAT(T, BOOST_PP_INC(n)) & BOOST_SIGNALS2_SIGNATURE_ARG_NAME(~, n, ~)
+// const T1 & arg1, const T2 & arg2, ..., const Tn & argn
+#define BOOST_SIGNALS2_FULL_FORWARD_ARGS(arity) \
+ BOOST_PP_ENUM(arity, BOOST_SIGNALS2_FULL_CREF_ARG, ~)
+#define BOOST_SIGNALS2_FORWARDED_ARGS(arity) \
+ BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(arity)
+// preprocessed_arg_typeN
+#define BOOST_SIGNALS2_PREPROCESSED_ARG_N_TYPE_CLASS_NAME(arity) BOOST_PP_CAT(preprocessed_arg_type, arity)
+
+// typename R, typename T1, typename T2, ..., typename TN, typename SlotFunction
+#define BOOST_SIGNALS2_SLOT_TEMPLATE_SPECIALIZATION_DECL(arity) \
+ BOOST_SIGNALS2_SIGNATURE_TEMPLATE_DECL(arity), \
+ typename SlotFunction
+#define BOOST_SIGNALS2_SLOT_TEMPLATE_SPECIALIZATION
+
+// typename R, typename T1, typename T2, ..., typename TN, typename Combiner, ...
+#define BOOST_SIGNALS2_SIGNAL_TEMPLATE_DECL(arity) \
+ BOOST_SIGNALS2_SIGNATURE_TEMPLATE_DECL(arity), \
+ typename Combiner, \
+ typename Group, \
+ typename GroupCompare, \
+ typename SlotFunction, \
+ typename ExtendedSlotFunction, \
+ typename Mutex
+// typename R, typename T1, typename T2, ..., typename TN, typename Combiner = optional_last_value<R>, ...
+#define BOOST_SIGNALS2_SIGNAL_TEMPLATE_DEFAULTED_DECL(arity) \
+ BOOST_SIGNALS2_SIGNATURE_TEMPLATE_DECL(arity), \
+ typename Combiner = optional_last_value<R>, \
+ typename Group = int, \
+ typename GroupCompare = std::less<Group>, \
+ typename SlotFunction = BOOST_SIGNALS2_FUNCTION_N_DECL(arity), \
+ typename ExtendedSlotFunction = BOOST_SIGNALS2_EXT_FUNCTION_N_DECL(arity), \
+ typename Mutex = signals2::mutex
+#define BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION_DECL(arity) BOOST_SIGNALS2_SIGNAL_TEMPLATE_DECL(arity)
+#define BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION
+
+#define BOOST_SIGNALS2_STD_FUNCTIONAL_BASE(result_type) std_functional_base
+
+#define BOOST_SIGNALS2_PP_COMMA_IF(arity) BOOST_PP_COMMA_IF(arity)
+
+#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+#define BOOST_SIGNALS2_SIGNAL_CLASS_NAME(arity) signal
+#define BOOST_SIGNALS2_WEAK_SIGNAL_CLASS_NAME(arity) weak_signal
+#define BOOST_SIGNALS2_SIGNAL_IMPL_CLASS_NAME(arity) signal_impl
+#define BOOST_SIGNALS2_SIGNATURE_TEMPLATE_DECL(arity) typename Signature
+#define BOOST_SIGNALS2_ARGS_TEMPLATE_INSTANTIATION(arity) Args...
+#define BOOST_SIGNALS2_SIGNATURE_TEMPLATE_INSTANTIATION(arity) R (Args...)
+#define BOOST_SIGNALS2_SIGNATURE_FUNCTION_TYPE(arity) R (Args...)
+#define BOOST_SIGNALS2_ARGS_TEMPLATE_DECL(arity) typename ... Args
+#define BOOST_SIGNALS2_FULL_FORWARD_ARGS(arity) Args && ... args
+#define BOOST_SIGNALS2_FORWARDED_ARGS(arity) std::forward<Args>(args)...
+#define BOOST_SIGNALS2_SLOT_CLASS_NAME(arity) slot
+#define BOOST_SIGNALS2_EXTENDED_SLOT_TYPE(arity) slot<R (const connection &, Args...), extended_slot_function_type>
+#define BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_N(arity) bound_extended_slot_function
+#define BOOST_SIGNALS2_BOUND_EXTENDED_SLOT_FUNCTION_INVOKER_N(arity) bound_extended_slot_function_invoker
+#define BOOST_SIGNALS2_FUNCTION_N_DECL(arity) boost::function<Signature>
+#define BOOST_SIGNALS2_PREFIXED_SIGNATURE_TEMPLATE_DECL(arity, prefix) typename prefixSignature
+#define BOOST_SIGNALS2_PREFIXED_SIGNATURE_TEMPLATE_INSTANTIATION(arity, prefix) prefixSignature
+#define BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(arity) Args ... args
+#define BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(arity) args...
+#define BOOST_SIGNALS2_PORTABLE_SIGNATURE(arity, Signature) Signature
+
+#define BOOST_SIGNALS2_SLOT_TEMPLATE_SPECIALIZATION_DECL(arity) \
+ typename SlotFunction, \
+ typename R, \
+ typename ... Args
+#define BOOST_SIGNALS2_SLOT_TEMPLATE_SPECIALIZATION \
+ <R (Args...), SlotFunction>
+
+#define BOOST_SIGNALS2_SIGNAL_TEMPLATE_DECL(arity) \
+ typename Signature, \
+ typename Combiner, \
+ typename Group, \
+ typename GroupCompare, \
+ typename SlotFunction, \
+ typename ExtendedSlotFunction, \
+ typename Mutex
+#define BOOST_SIGNALS2_SIGNAL_TEMPLATE_DEFAULTED_DECL(arity) \
+ typename Signature, \
+ typename Combiner = optional_last_value<typename boost::function_traits<Signature>::result_type>, \
+ typename Group = int, \
+ typename GroupCompare = std::less<Group>, \
+ typename SlotFunction = boost::function<Signature>, \
+ typename ExtendedSlotFunction = typename detail::variadic_extended_signature<Signature>::function_type, \
+ typename Mutex = signals2::mutex
+#define BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION_DECL(arity) \
+ typename Combiner, \
+ typename Group, \
+ typename GroupCompare, \
+ typename SlotFunction, \
+ typename ExtendedSlotFunction, \
+ typename Mutex, \
+ typename R, \
+ typename ... Args
+#define BOOST_SIGNALS2_SIGNAL_TEMPLATE_SPECIALIZATION <\
+ R (Args...), \
+ Combiner, \
+ Group, \
+ GroupCompare, \
+ SlotFunction, \
+ ExtendedSlotFunction, \
+ Mutex>
+
+#define BOOST_SIGNALS2_STD_FUNCTIONAL_BASE(result_type) \
+ std_functional_base<result_type , Args...>
+
+#define BOOST_SIGNALS2_PP_COMMA_IF(arity) ,
+
+#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+#endif // BOOST_SIGNALS2_SIGNALS_COMMON_MACROS_HPP
diff --git a/third_party/boost/boost/signals2/detail/slot_call_iterator.hpp b/third_party/boost/boost/signals2/detail/slot_call_iterator.hpp
new file mode 100644
index 0000000..418ec0b
--- /dev/null
+++ b/third_party/boost/boost/signals2/detail/slot_call_iterator.hpp
@@ -0,0 +1,194 @@
+// Boost.Signals2 library
+
+// Copyright Douglas Gregor 2001-2004.
+// Copyright Frank Mori Hess 2007-2008.
+// Use, modification and
+// distribution is subject to the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// For more information, see http://www.boost.org
+
+#ifndef BOOST_SIGNALS2_SLOT_CALL_ITERATOR_HPP
+#define BOOST_SIGNALS2_SLOT_CALL_ITERATOR_HPP
+
+#include <boost/assert.hpp>
+#include <boost/aligned_storage.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/optional.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/signals2/connection.hpp>
+#include <boost/signals2/slot_base.hpp>
+#include <boost/signals2/detail/auto_buffer.hpp>
+#include <boost/signals2/detail/unique_lock.hpp>
+#include <boost/type_traits/add_const.hpp>
+#include <boost/type_traits/add_reference.hpp>
+#include <boost/weak_ptr.hpp>
+
+namespace boost {
+ namespace signals2 {
+ namespace detail {
+ template<typename ResultType, typename Function>
+ class slot_call_iterator_cache
+ {
+ public:
+ slot_call_iterator_cache(const Function &f_arg):
+ f(f_arg),
+ connected_slot_count(0),
+ disconnected_slot_count(0),
+ m_active_slot(0)
+ {}
+
+ ~slot_call_iterator_cache()
+ {
+ if(m_active_slot)
+ {
+ garbage_collecting_lock<connection_body_base> lock(*m_active_slot);
+ m_active_slot->dec_slot_refcount(lock);
+ }
+ }
+
+ template<typename M>
+ void set_active_slot(garbage_collecting_lock<M> &lock,
+ connection_body_base *active_slot)
+ {
+ if(m_active_slot)
+ m_active_slot->dec_slot_refcount(lock);
+ m_active_slot = active_slot;
+ if(m_active_slot)
+ m_active_slot->inc_slot_refcount(lock);
+ }
+
+ optional<ResultType> result;
+ typedef auto_buffer<void_shared_ptr_variant, store_n_objects<10> > tracked_ptrs_type;
+ tracked_ptrs_type tracked_ptrs;
+ Function f;
+ unsigned connected_slot_count;
+ unsigned disconnected_slot_count;
+ connection_body_base *m_active_slot;
+ };
+
+ // Generates a slot call iterator. Essentially, this is an iterator that:
+ // - skips over disconnected slots in the underlying list
+ // - calls the connected slots when dereferenced
+ // - caches the result of calling the slots
+ template<typename Function, typename Iterator, typename ConnectionBody>
+ class slot_call_iterator_t
+ : public boost::iterator_facade<slot_call_iterator_t<Function, Iterator, ConnectionBody>,
+ typename Function::result_type,
+ boost::single_pass_traversal_tag,
+ typename boost::add_const<typename boost::add_reference<typename Function::result_type>::type>::type >
+ {
+ typedef boost::iterator_facade<slot_call_iterator_t<Function, Iterator, ConnectionBody>,
+ typename Function::result_type,
+ boost::single_pass_traversal_tag,
+ typename boost::add_const<typename boost::add_reference<typename Function::result_type>::type>::type >
+ inherited;
+
+ typedef typename Function::result_type result_type;
+
+ typedef slot_call_iterator_cache<result_type, Function> cache_type;
+
+ friend class boost::iterator_core_access;
+
+ public:
+ slot_call_iterator_t(Iterator iter_in, Iterator end_in,
+ cache_type &c):
+ iter(iter_in), end(end_in),
+ cache(&c), callable_iter(end_in)
+ {
+ lock_next_callable();
+ }
+
+ typename inherited::reference
+ dereference() const
+ {
+ if (!cache->result) {
+ try
+ {
+ cache->result.reset(cache->f(*iter));
+ }
+ catch(expired_slot &)
+ {
+ (*iter)->disconnect();
+ throw;
+ }
+ }
+ return cache->result.get();
+ }
+
+ void increment()
+ {
+ ++iter;
+ lock_next_callable();
+ cache->result.reset();
+ }
+
+ bool equal(const slot_call_iterator_t& other) const
+ {
+ return iter == other.iter;
+ }
+
+ private:
+ typedef garbage_collecting_lock<connection_body_base> lock_type;
+
+ void set_callable_iter(lock_type &lock, Iterator newValue) const
+ {
+ callable_iter = newValue;
+ if(callable_iter == end)
+ cache->set_active_slot(lock, 0);
+ else
+ cache->set_active_slot(lock, (*callable_iter).get());
+ }
+
+ void lock_next_callable() const
+ {
+ if(iter == callable_iter)
+ {
+ return;
+ }
+ if(iter == end)
+ {
+ if(callable_iter != end)
+ {
+ lock_type lock(**callable_iter);
+ set_callable_iter(lock, end);
+ return;
+ }
+ }
+ // we're only locking the first connection body,
+ // but it doesn't matter they all use the same mutex
+ lock_type lock(**iter);
+ for(;iter != end; ++iter)
+ {
+ cache->tracked_ptrs.clear();
+ (*iter)->nolock_grab_tracked_objects(lock, std::back_inserter(cache->tracked_ptrs));
+ if((*iter)->nolock_nograb_connected())
+ {
+ ++cache->connected_slot_count;
+ }else
+ {
+ ++cache->disconnected_slot_count;
+ }
+ if((*iter)->nolock_nograb_blocked() == false)
+ {
+ set_callable_iter(lock, iter);
+ break;
+ }
+ }
+ if(iter == end)
+ {
+ set_callable_iter(lock, end);
+ }
+ }
+
+ mutable Iterator iter;
+ Iterator end;
+ cache_type *cache;
+ mutable Iterator callable_iter;
+ };
+ } // end namespace detail
+ } // end namespace BOOST_SIGNALS_NAMESPACE
+} // end namespace boost
+
+#endif // BOOST_SIGNALS2_SLOT_CALL_ITERATOR_HPP
diff --git a/third_party/boost/boost/signals2/detail/slot_groups.hpp b/third_party/boost/boost/signals2/detail/slot_groups.hpp
new file mode 100644
index 0000000..5e1853a
--- /dev/null
+++ b/third_party/boost/boost/signals2/detail/slot_groups.hpp
@@ -0,0 +1,235 @@
+// Boost.Signals2 library
+
+// Copyright Frank Mori Hess 2007-2008.
+// Use, modification and
+// distribution is subject to the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// For more information, see http://www.boost.org
+
+#ifndef BOOST_SIGNALS2_SLOT_GROUPS_HPP
+#define BOOST_SIGNALS2_SLOT_GROUPS_HPP
+
+#include <boost/signals2/connection.hpp>
+#include <boost/optional.hpp>
+#include <list>
+#include <map>
+#include <utility>
+
+namespace boost {
+ namespace signals2 {
+ namespace detail {
+ enum slot_meta_group {front_ungrouped_slots, grouped_slots, back_ungrouped_slots};
+ template<typename Group>
+ struct group_key
+ {
+ typedef std::pair<enum slot_meta_group, boost::optional<Group> > type;
+ };
+ template<typename Group, typename GroupCompare>
+ class group_key_less
+ {
+ public:
+ group_key_less()
+ {}
+ group_key_less(const GroupCompare &group_compare): _group_compare(group_compare)
+ {}
+ bool operator ()(const typename group_key<Group>::type &key1, const typename group_key<Group>::type &key2) const
+ {
+ if(key1.first != key2.first) return key1.first < key2.first;
+ if(key1.first != grouped_slots) return false;
+ return _group_compare(key1.second.get(), key2.second.get());
+ }
+ private:
+ GroupCompare _group_compare;
+ };
+ template<typename Group, typename GroupCompare, typename ValueType>
+ class grouped_list
+ {
+ public:
+ typedef group_key_less<Group, GroupCompare> group_key_compare_type;
+ private:
+ typedef std::list<ValueType> list_type;
+ typedef std::map
+ <
+ typename group_key<Group>::type,
+ typename list_type::iterator,
+ group_key_compare_type
+ > map_type;
+ typedef typename map_type::iterator map_iterator;
+ typedef typename map_type::const_iterator const_map_iterator;
+ public:
+ typedef typename list_type::iterator iterator;
+ typedef typename list_type::const_iterator const_iterator;
+ typedef typename group_key<Group>::type group_key_type;
+
+ grouped_list(const group_key_compare_type &group_key_compare):
+ _group_key_compare(group_key_compare)
+ {}
+ grouped_list(const grouped_list &other): _list(other._list),
+ _group_map(other._group_map), _group_key_compare(other._group_key_compare)
+ {
+ // fix up _group_map
+ typename map_type::const_iterator other_map_it;
+ typename list_type::iterator this_list_it = _list.begin();
+ typename map_type::iterator this_map_it = _group_map.begin();
+ for(other_map_it = other._group_map.begin();
+ other_map_it != other._group_map.end();
+ ++other_map_it, ++this_map_it)
+ {
+ BOOST_ASSERT(this_map_it != _group_map.end());
+ this_map_it->second = this_list_it;
+ typename list_type::const_iterator other_list_it = other.get_list_iterator(other_map_it);
+ typename map_type::const_iterator other_next_map_it = other_map_it;
+ ++other_next_map_it;
+ typename list_type::const_iterator other_next_list_it = other.get_list_iterator(other_next_map_it);
+ while(other_list_it != other_next_list_it)
+ {
+ ++other_list_it;
+ ++this_list_it;
+ }
+ }
+ }
+ iterator begin()
+ {
+ return _list.begin();
+ }
+ iterator end()
+ {
+ return _list.end();
+ }
+ iterator lower_bound(const group_key_type &key)
+ {
+ map_iterator map_it = _group_map.lower_bound(key);
+ return get_list_iterator(map_it);
+ }
+ iterator upper_bound(const group_key_type &key)
+ {
+ map_iterator map_it = _group_map.upper_bound(key);
+ return get_list_iterator(map_it);
+ }
+ void push_front(const group_key_type &key, const ValueType &value)
+ {
+ map_iterator map_it;
+ if(key.first == front_ungrouped_slots)
+ {// optimization
+ map_it = _group_map.begin();
+ }else
+ {
+ map_it = _group_map.lower_bound(key);
+ }
+ m_insert(map_it, key, value);
+ }
+ void push_back(const group_key_type &key, const ValueType &value)
+ {
+ map_iterator map_it;
+ if(key.first == back_ungrouped_slots)
+ {// optimization
+ map_it = _group_map.end();
+ }else
+ {
+ map_it = _group_map.upper_bound(key);
+ }
+ m_insert(map_it, key, value);
+ }
+ void erase(const group_key_type &key)
+ {
+ map_iterator map_it = _group_map.lower_bound(key);
+ iterator begin_list_it = get_list_iterator(map_it);
+ iterator end_list_it = upper_bound(key);
+ if(begin_list_it != end_list_it)
+ {
+ _list.erase(begin_list_it, end_list_it);
+ _group_map.erase(map_it);
+ }
+ }
+ iterator erase(const group_key_type &key, const iterator &it)
+ {
+ BOOST_ASSERT(it != _list.end());
+ map_iterator map_it = _group_map.lower_bound(key);
+ BOOST_ASSERT(map_it != _group_map.end());
+ BOOST_ASSERT(weakly_equivalent(map_it->first, key));
+ if(map_it->second == it)
+ {
+ iterator next = it;
+ ++next;
+ // if next is in same group
+ if(next != upper_bound(key))
+ {
+ _group_map[key] = next;
+ }else
+ {
+ _group_map.erase(map_it);
+ }
+ }
+ return _list.erase(it);
+ }
+ void clear()
+ {
+ _list.clear();
+ _group_map.clear();
+ }
+ private:
+ /* Suppress default assignment operator, since it has the wrong semantics. */
+ grouped_list& operator=(const grouped_list &other);
+
+ bool weakly_equivalent(const group_key_type &arg1, const group_key_type &arg2)
+ {
+ if(_group_key_compare(arg1, arg2)) return false;
+ if(_group_key_compare(arg2, arg1)) return false;
+ return true;
+ }
+ void m_insert(const map_iterator &map_it, const group_key_type &key, const ValueType &value)
+ {
+ iterator list_it = get_list_iterator(map_it);
+ iterator new_it = _list.insert(list_it, value);
+ if(map_it != _group_map.end() && weakly_equivalent(key, map_it->first))
+ {
+ _group_map.erase(map_it);
+ }
+ map_iterator lower_bound_it = _group_map.lower_bound(key);
+ if(lower_bound_it == _group_map.end() ||
+ weakly_equivalent(lower_bound_it->first, key) == false)
+ {
+ /* doing the following instead of just
+ _group_map[key] = new_it;
+ to avoid bogus error when enabling checked iterators with g++ */
+ _group_map.insert(typename map_type::value_type(key, new_it));
+ }
+ }
+ iterator get_list_iterator(const const_map_iterator &map_it)
+ {
+ iterator list_it;
+ if(map_it == _group_map.end())
+ {
+ list_it = _list.end();
+ }else
+ {
+ list_it = map_it->second;
+ }
+ return list_it;
+ }
+ const_iterator get_list_iterator(const const_map_iterator &map_it) const
+ {
+ const_iterator list_it;
+ if(map_it == _group_map.end())
+ {
+ list_it = _list.end();
+ }else
+ {
+ list_it = map_it->second;
+ }
+ return list_it;
+ }
+
+ list_type _list;
+ // holds iterators to first list item in each group
+ map_type _group_map;
+ group_key_compare_type _group_key_compare;
+ };
+ } // end namespace detail
+ enum connect_position { at_back, at_front };
+ } // end namespace signals2
+} // end namespace boost
+
+#endif // BOOST_SIGNALS2_SLOT_GROUPS_HPP
diff --git a/third_party/boost/boost/signals2/detail/slot_template.hpp b/third_party/boost/boost/signals2/detail/slot_template.hpp
new file mode 100644
index 0000000..fc19f51
--- /dev/null
+++ b/third_party/boost/boost/signals2/detail/slot_template.hpp
@@ -0,0 +1,187 @@
+// Boost.Signals2 library
+
+// Copyright Frank Mori Hess 2007-2008.
+// Copyright Timmo Stange 2007.
+// Copyright Douglas Gregor 2001-2004. Use, modification and
+// distribution is subject to the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// For more information, see http://www.boost.org
+
+// This file is included iteratively, and should not be protected from multiple inclusion
+
+#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
+#define BOOST_SIGNALS2_NUM_ARGS BOOST_PP_ITERATION()
+#else
+#define BOOST_SIGNALS2_NUM_ARGS 1
+#endif
+
+
+namespace boost
+{
+ namespace signals2
+ {
+#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
+ template<typename Signature, typename SlotFunction> class slot;
+#else
+ template<typename Signature, typename SlotFunction = boost::function<Signature> >
+ class slot;
+
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1900)
+ template<typename Signature, typename SlotFunction> class slot{};
+#endif
+#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+ template<BOOST_SIGNALS2_SLOT_TEMPLATE_SPECIALIZATION_DECL(BOOST_SIGNALS2_NUM_ARGS)>
+ class BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS) BOOST_SIGNALS2_SLOT_TEMPLATE_SPECIALIZATION
+ : public slot_base, public detail::BOOST_SIGNALS2_STD_FUNCTIONAL_BASE(R)
+
+ {
+ public:
+ template<BOOST_SIGNALS2_PREFIXED_SIGNATURE_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS, Other), typename OtherSlotFunction>
+ friend class BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS);
+
+ typedef SlotFunction slot_function_type;
+ typedef R result_type;
+ typedef typename mpl::identity<BOOST_SIGNALS2_SIGNATURE_FUNCTION_TYPE(BOOST_SIGNALS2_NUM_ARGS)>::type signature_type;
+
+#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+// typedef Tn argn_type;
+#define BOOST_SIGNALS2_MISC_STATEMENT(z, n, data) \
+ typedef BOOST_PP_CAT(T, BOOST_PP_INC(n)) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(n)), _type);
+ BOOST_PP_REPEAT(BOOST_SIGNALS2_NUM_ARGS, BOOST_SIGNALS2_MISC_STATEMENT, ~)
+#undef BOOST_SIGNALS2_MISC_STATEMENT
+#if BOOST_SIGNALS2_NUM_ARGS == 1
+ typedef arg1_type argument_type;
+#elif BOOST_SIGNALS2_NUM_ARGS == 2
+ typedef arg1_type first_argument_type;
+ typedef arg2_type second_argument_type;
+#endif
+
+ template<unsigned n> class arg : public
+ detail::BOOST_SIGNALS2_PREPROCESSED_ARG_N_TYPE_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
+ <n BOOST_SIGNALS2_PP_COMMA_IF(BOOST_SIGNALS2_NUM_ARGS)
+ BOOST_SIGNALS2_ARGS_TEMPLATE_INSTANTIATION(BOOST_SIGNALS2_NUM_ARGS)>
+ {};
+
+ BOOST_STATIC_CONSTANT(int, arity = BOOST_SIGNALS2_NUM_ARGS);
+
+#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+ template<unsigned n> class arg
+ {
+ public:
+ typedef typename detail::variadic_arg_type<n, Args...>::type type;
+ };
+ BOOST_STATIC_CONSTANT(int, arity = sizeof...(Args));
+
+#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+ template<typename F>
+ BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(const F& f)
+ {
+ init_slot_function(f);
+ }
+ // copy constructors
+#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
+ template<BOOST_SIGNALS2_PREFIXED_SIGNATURE_TEMPLATE_DECL(BOOST_SIGNALS2_NUM_ARGS, Other), typename OtherSlotFunction>
+ BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(const BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)
+ <BOOST_SIGNALS2_PREFIXED_SIGNATURE_TEMPLATE_INSTANTIATION(BOOST_SIGNALS2_NUM_ARGS, Other), OtherSlotFunction> &other_slot):
+ slot_base(other_slot), _slot_function(other_slot._slot_function)
+ {
+ }
+#endif
+ template<typename Signature, typename OtherSlotFunction>
+ BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)(const slot<Signature, OtherSlotFunction> &other_slot):
+ slot_base(other_slot), _slot_function(other_slot._slot_function)
+ {
+ }
+ // bind syntactic sugar
+ BOOST_SIGNALS2_SLOT_N_BINDING_CONSTRUCTORS
+ // invocation
+ R operator()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS))
+ {
+ locked_container_type locked_objects = lock();
+ return _slot_function(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
+ }
+ R operator()(BOOST_SIGNALS2_SIGNATURE_FULL_ARGS(BOOST_SIGNALS2_NUM_ARGS)) const
+ {
+ locked_container_type locked_objects = lock();
+ return _slot_function(BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(BOOST_SIGNALS2_NUM_ARGS));
+ }
+ // tracking
+ BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)& track(const weak_ptr<void> &tracked) {
+ _tracked_objects.push_back(tracked);
+ return *this;
+ }
+ BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)& track(const signal_base &signal)
+ {
+ track_signal(signal);
+ return *this;
+ }
+ BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)& track(const slot_base &slot)
+ {
+ tracked_container_type::const_iterator it;
+ for(it = slot.tracked_objects().begin(); it != slot.tracked_objects().end(); ++it)
+ {
+ _tracked_objects.push_back(*it);
+ }
+ return *this;
+ }
+ template<typename ForeignWeakPtr>
+ BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)& track_foreign(const ForeignWeakPtr &tracked,
+ typename weak_ptr_traits<ForeignWeakPtr>::shared_type * /*SFINAE*/ = 0)
+ {
+ _tracked_objects.push_back(detail::foreign_void_weak_ptr(tracked));
+ return *this;
+ }
+ template<typename ForeignSharedPtr>
+ BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)& track_foreign(const ForeignSharedPtr &tracked,
+ typename shared_ptr_traits<ForeignSharedPtr>::weak_type * /*SFINAE*/ = 0)
+ {
+ _tracked_objects.push_back
+ (
+ detail::foreign_void_weak_ptr
+ (
+ typename shared_ptr_traits<ForeignSharedPtr>::weak_type(tracked)
+ )
+ );
+ return *this;
+ }
+
+ const slot_function_type& slot_function() const {return _slot_function;}
+ slot_function_type& slot_function() {return _slot_function;}
+ private:
+ template<typename F>
+ void init_slot_function(const F& f)
+ {
+ _slot_function = detail::get_invocable_slot(f, detail::tag_type(f));
+ signals2::detail::tracked_objects_visitor visitor(this);
+ boost::visit_each(visitor, f);
+ }
+
+ SlotFunction _slot_function;
+ };
+
+#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
+ namespace detail
+ {
+ template<unsigned arity, typename Signature, typename SlotFunction>
+ class slotN;
+ // partial template specialization
+ template<typename Signature, typename SlotFunction>
+ class slotN<BOOST_SIGNALS2_NUM_ARGS, Signature, SlotFunction>
+ {
+ public:
+ typedef BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)<
+ BOOST_SIGNALS2_PORTABLE_SIGNATURE(BOOST_SIGNALS2_NUM_ARGS, Signature),
+ SlotFunction> type;
+ };
+ }
+#endif
+ } // end namespace signals2
+} // end namespace boost
+
+#undef BOOST_SIGNALS2_NUM_ARGS
diff --git a/third_party/boost/boost/signals2/detail/tracked_objects_visitor.hpp b/third_party/boost/boost/signals2/detail/tracked_objects_visitor.hpp
new file mode 100644
index 0000000..8f0ba7a
--- /dev/null
+++ b/third_party/boost/boost/signals2/detail/tracked_objects_visitor.hpp
@@ -0,0 +1,97 @@
+// Boost.Signals2 library
+
+// Copyright Frank Mori Hess 2007-2008.
+// Copyright Timmo Stange 2007.
+// Copyright Douglas Gregor 2001-2004. Use, modification and
+// distribution is subject to the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// For more information, see http://www.boost.org
+
+#ifndef BOOST_SIGNALS2_TRACKED_OBJECTS_VISITOR_HPP
+#define BOOST_SIGNALS2_TRACKED_OBJECTS_VISITOR_HPP
+
+#include <boost/mpl/bool.hpp>
+#include <boost/ref.hpp>
+#include <boost/signals2/detail/signals_common.hpp>
+#include <boost/signals2/slot_base.hpp>
+#include <boost/signals2/trackable.hpp>
+#include <boost/type_traits/is_function.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/type_traits/remove_pointer.hpp>
+#include <boost/utility/addressof.hpp>
+
+namespace boost
+{
+ namespace signals2
+ {
+ namespace detail
+ {
+ // Visitor to collect tracked objects from a bound function.
+ class tracked_objects_visitor
+ {
+ public:
+ tracked_objects_visitor(slot_base *slot) : slot_(slot)
+ {}
+ template<typename T>
+ void operator()(const T& t) const
+ {
+ m_visit_reference_wrapper(t, mpl::bool_<is_reference_wrapper<T>::value>());
+ }
+ private:
+ template<typename T>
+ void m_visit_reference_wrapper(const reference_wrapper<T> &t, const mpl::bool_<true> &) const
+ {
+ m_visit_pointer(t.get_pointer(), mpl::bool_<true>());
+ }
+ template<typename T>
+ void m_visit_reference_wrapper(const T &t, const mpl::bool_<false> &) const
+ {
+ m_visit_pointer(t, mpl::bool_<is_pointer<T>::value>());
+ }
+ template<typename T>
+ void m_visit_pointer(const T &t, const mpl::bool_<true> &) const
+ {
+ m_visit_not_function_pointer(t, mpl::bool_<!is_function<typename remove_pointer<T>::type>::value>());
+ }
+ template<typename T>
+ void m_visit_pointer(const T &t, const mpl::bool_<false> &) const
+ {
+ m_visit_pointer(boost::addressof(t), mpl::bool_<true>());
+ }
+ template<typename T>
+ void m_visit_not_function_pointer(const T *t, const mpl::bool_<true> &) const
+ {
+ m_visit_signal(t, mpl::bool_<is_signal<T>::value>());
+ }
+ template<typename T>
+ void m_visit_not_function_pointer(const T &, const mpl::bool_<false> &) const
+ {}
+ template<typename T>
+ void m_visit_signal(const T *signal, const mpl::bool_<true> &) const
+ {
+ if(signal)
+ slot_->track_signal(*signal);
+ }
+ template<typename T>
+ void m_visit_signal(const T &t, const mpl::bool_<false> &) const
+ {
+ add_if_trackable(t);
+ }
+ void add_if_trackable(const trackable *trackable) const
+ {
+ if(trackable)
+ slot_->_tracked_objects.push_back(trackable->get_weak_ptr());
+ }
+ void add_if_trackable(const void *) const {}
+
+ mutable slot_base * slot_;
+ };
+
+
+ } // end namespace detail
+ } // end namespace signals2
+} // end namespace boost
+
+#endif // BOOST_SIGNALS2_TRACKED_OBJECTS_VISITOR_HPP
diff --git a/third_party/boost/boost/signals2/detail/unique_lock.hpp b/third_party/boost/boost/signals2/detail/unique_lock.hpp
new file mode 100644
index 0000000..13fecf2
--- /dev/null
+++ b/third_party/boost/boost/signals2/detail/unique_lock.hpp
@@ -0,0 +1,42 @@
+/*
+ Provides a basic subset of boost::unique_lock functionality. Provided only because
+ including boost/thread/locks.hpp requires linking to thread library
+*/
+// Copyright Frank Mori Hess 2008.
+// Distributed under the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/signals2 for library home page.
+
+#ifndef BOOST_SIGNALS2_UNIQUE_LOCK_HPP
+#define BOOST_SIGNALS2_UNIQUE_LOCK_HPP
+
+#include <boost/noncopyable.hpp>
+
+namespace boost
+{
+ namespace signals2
+ {
+ namespace detail
+ {
+ template<typename Mutex>
+ class unique_lock: public noncopyable
+ {
+ public:
+ unique_lock(Mutex &m): _mutex(m)
+ {
+ _mutex.lock();
+ }
+ ~unique_lock()
+ {
+ _mutex.unlock();
+ }
+ private:
+ Mutex &_mutex;
+ };
+ } // namespace detail
+ } // namespace signals2
+} // namespace boost
+
+#endif // BOOST_SIGNALS2_UNIQUE_LOCK_HPP
diff --git a/third_party/boost/boost/signals2/expired_slot.hpp b/third_party/boost/boost/signals2/expired_slot.hpp
new file mode 100644
index 0000000..fa6db22
--- /dev/null
+++ b/third_party/boost/boost/signals2/expired_slot.hpp
@@ -0,0 +1,31 @@
+// Boost.Signals2 library
+
+// Copyright Frank Mori Hess 2007-2010.
+// Use, modification and
+// distribution is subject to the 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_SIGNALS2_EXPIRED_SLOT_HPP
+#define BOOST_SIGNALS2_EXPIRED_SLOT_HPP
+
+#include <boost/smart_ptr/bad_weak_ptr.hpp>
+
+namespace boost
+{
+ namespace signals2
+ {
+ class expired_slot: public bad_weak_ptr
+ {
+ public:
+ virtual char const * what() const throw()
+ {
+ return "boost::signals2::expired_slot";
+ }
+ };
+ }
+} // end namespace boost
+
+#endif // BOOST_SIGNALS2_EXPIRED_SLOT_HPP
diff --git a/third_party/boost/boost/signals2/mutex.hpp b/third_party/boost/boost/signals2/mutex.hpp
new file mode 100644
index 0000000..e58aca1
--- /dev/null
+++ b/third_party/boost/boost/signals2/mutex.hpp
@@ -0,0 +1,38 @@
+//
+// boost/signals2/mutex.hpp - header-only mutex
+//
+// Copyright (c) 2002, 2003 Peter Dimov and Multi Media Ltd.
+// Copyright (c) 2008 Frank Mori Hess
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// boost::signals2::mutex is a modification of
+// boost::detail::lightweight_mutex to follow the newer Lockable
+// concept of Boost.Thread.
+//
+
+#ifndef BOOST_SIGNALS2_MUTEX_HPP
+#define BOOST_SIGNALS2_MUTEX_HPP
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#if !defined(BOOST_HAS_THREADS)
+# include <boost/signals2/detail/lwm_nop.hpp>
+#elif defined(BOOST_HAS_PTHREADS)
+# include <boost/signals2/detail/lwm_pthreads.hpp>
+#elif defined(BOOST_HAS_WINTHREADS)
+# include <boost/signals2/detail/lwm_win32_cs.hpp>
+#else
+// Use #define BOOST_DISABLE_THREADS to avoid the error
+# error Unrecognized threading platform
+#endif
+
+#endif // #ifndef BOOST_SIGNALS2_MUTEX_HPP
diff --git a/third_party/boost/boost/signals2/optional_last_value.hpp b/third_party/boost/boost/signals2/optional_last_value.hpp
new file mode 100644
index 0000000..766e99b
--- /dev/null
+++ b/third_party/boost/boost/signals2/optional_last_value.hpp
@@ -0,0 +1,65 @@
+// optional_last_value function object (documented as part of Boost.Signals2)
+
+// Copyright Frank Mori Hess 2007-2008.
+// Copyright Douglas Gregor 2001-2003.
+// Distributed under the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/signals2 for library home page.
+
+#ifndef BOOST_SIGNALS2_OPTIONAL_LAST_VALUE_HPP
+#define BOOST_SIGNALS2_OPTIONAL_LAST_VALUE_HPP
+
+#include <boost/optional.hpp>
+#include <boost/signals2/expired_slot.hpp>
+
+namespace boost {
+ namespace signals2 {
+
+ template<typename T>
+ class optional_last_value
+ {
+ public:
+ typedef optional<T> result_type;
+
+ template<typename InputIterator>
+ optional<T> operator()(InputIterator first, InputIterator last) const
+ {
+ optional<T> value;
+ while (first != last)
+ {
+ try
+ {
+ value = *first;
+ }
+ catch(const expired_slot &) {}
+ ++first;
+ }
+ return value;
+ }
+ };
+
+ template<>
+ class optional_last_value<void>
+ {
+ public:
+ typedef void result_type;
+ template<typename InputIterator>
+ result_type operator()(InputIterator first, InputIterator last) const
+ {
+ while (first != last)
+ {
+ try
+ {
+ *first;
+ }
+ catch(const expired_slot &) {}
+ ++first;
+ }
+ return;
+ }
+ };
+ } // namespace signals2
+} // namespace boost
+#endif // BOOST_SIGNALS2_OPTIONAL_LAST_VALUE_HPP
diff --git a/third_party/boost/boost/signals2/preprocessed_signal.hpp b/third_party/boost/boost/signals2/preprocessed_signal.hpp
new file mode 100644
index 0000000..7d43bd5
--- /dev/null
+++ b/third_party/boost/boost/signals2/preprocessed_signal.hpp
@@ -0,0 +1,61 @@
+/*
+ A thread-safe version of Boost.Signals.
+
+ Author: Frank Mori Hess <fmhess@users.sourceforge.net>
+ Begin: 2007-01-23
+*/
+// Copyright Frank Mori Hess 2007-2008
+// Use, modification and
+// distribution is subject to the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// For more information, see http://www.boost.org
+
+#ifndef BOOST_SIGNALS2_PREPROCESSED_SIGNAL_HPP
+#define BOOST_SIGNALS2_PREPROCESSED_SIGNAL_HPP
+
+#include <boost/preprocessor/arithmetic.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/control/expr_if.hpp>
+#include <boost/preprocessor/iteration.hpp>
+#include <boost/preprocessor/repetition.hpp>
+#include <boost/signals2/detail/preprocessed_arg_type.hpp>
+#include <boost/type_traits/add_reference.hpp>
+#include <boost/type_traits/is_void.hpp>
+#include <boost/utility/enable_if.hpp>
+
+#define BOOST_PP_ITERATION_LIMITS (0, BOOST_SIGNALS2_MAX_ARGS)
+#define BOOST_PP_FILENAME_1 <boost/signals2/detail/signal_template.hpp>
+#include BOOST_PP_ITERATE()
+
+namespace boost
+{
+ namespace signals2
+ {
+ template<typename Signature,
+ typename Combiner = optional_last_value<typename boost::function_traits<Signature>::result_type>,
+ typename Group = int,
+ typename GroupCompare = std::less<Group>,
+ typename SlotFunction = function<Signature>,
+ typename ExtendedSlotFunction = typename detail::extended_signature<function_traits<Signature>::arity, Signature>::function_type,
+ typename Mutex = mutex >
+ class signal: public detail::signalN<function_traits<Signature>::arity,
+ Signature, Combiner, Group, GroupCompare, SlotFunction, ExtendedSlotFunction, Mutex>::type
+ {
+ private:
+ typedef typename detail::signalN<boost::function_traits<Signature>::arity,
+ Signature, Combiner, Group, GroupCompare, SlotFunction, ExtendedSlotFunction, Mutex>::type base_type;
+ public:
+ signal(const Combiner &combiner_arg = Combiner(), const GroupCompare &group_compare = GroupCompare()):
+ base_type(combiner_arg, group_compare)
+ {}
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && BOOST_WORKAROUND(BOOST_MSVC, < 1800)
+ signal(signal && other) : base_type(std::move(other)) {}
+ signal & operator=(signal && other) { base_type::operator=(std::move(other)); return *this; }
+#endif
+ };
+ }
+}
+
+#endif // BOOST_SIGNALS2_PREPROCESSED_SIGNAL_HPP
diff --git a/third_party/boost/boost/signals2/preprocessed_slot.hpp b/third_party/boost/boost/signals2/preprocessed_slot.hpp
new file mode 100644
index 0000000..322b1a1
--- /dev/null
+++ b/third_party/boost/boost/signals2/preprocessed_slot.hpp
@@ -0,0 +1,72 @@
+// Boost.Signals2 library
+
+// Copyright Frank Mori Hess 2007-2009.
+// Copyright Timmo Stange 2007.
+// Copyright Douglas Gregor 2001-2004. Use, modification and
+// distribution is subject to the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// For more information, see http://www.boost.org
+
+#ifndef BOOST_SIGNALS2_PREPROCESSED_SLOT_HPP
+#define BOOST_SIGNALS2_PREPROCESSED_SLOT_HPP
+
+#include <boost/preprocessor/repetition.hpp>
+#include <boost/signals2/detail/preprocessed_arg_type.hpp>
+#include <boost/type_traits/function_traits.hpp>
+
+#ifndef BOOST_SIGNALS2_SLOT_MAX_BINDING_ARGS
+#define BOOST_SIGNALS2_SLOT_MAX_BINDING_ARGS 10
+#endif
+
+
+// template<typename Func, typename BindArgT0, typename BindArgT1, ..., typename BindArgTN-1> slotN(...
+#define BOOST_SIGNALS2_SLOT_N_BINDING_CONSTRUCTOR(z, n, data) \
+ template<typename Func, BOOST_SIGNALS2_PREFIXED_ARGS_TEMPLATE_DECL(n, BindArg)> \
+ BOOST_SIGNALS2_SLOT_CLASS_NAME(BOOST_SIGNALS2_NUM_ARGS)( \
+ const Func &func, BOOST_SIGNALS2_PREFIXED_FULL_REF_ARGS(n, const BindArg)) \
+ { \
+ init_slot_function(boost::bind(func, BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(n))); \
+ }
+#define BOOST_SIGNALS2_SLOT_N_BINDING_CONSTRUCTORS \
+ BOOST_PP_REPEAT_FROM_TO(1, BOOST_SIGNALS2_SLOT_MAX_BINDING_ARGS, BOOST_SIGNALS2_SLOT_N_BINDING_CONSTRUCTOR, ~)
+
+
+#define BOOST_PP_ITERATION_LIMITS (0, BOOST_PP_INC(BOOST_SIGNALS2_MAX_ARGS))
+#define BOOST_PP_FILENAME_1 <boost/signals2/detail/slot_template.hpp>
+#include BOOST_PP_ITERATE()
+
+#undef BOOST_SIGNALS2_SLOT_N_BINDING_CONSTRUCTOR
+#undef BOOST_SIGNALS2_SLOT_N_BINDING_CONSTRUCTORS
+
+namespace boost
+{
+ namespace signals2
+ {
+ template<typename Signature,
+ typename SlotFunction = boost::function<Signature> >
+ class slot: public detail::slotN<function_traits<Signature>::arity,
+ Signature, SlotFunction>::type
+ {
+ private:
+ typedef typename detail::slotN<boost::function_traits<Signature>::arity,
+ Signature, SlotFunction>::type base_type;
+ public:
+ template<typename F>
+ slot(const F& f): base_type(f)
+ {}
+ // bind syntactic sugar
+// template<typename F, typename BindArgT0, typename BindArgT1, ..., typename BindArgTn-1> slot(...
+#define BOOST_SIGNALS2_SLOT_BINDING_CONSTRUCTOR(z, n, data) \
+ template<typename Func, BOOST_SIGNALS2_PREFIXED_ARGS_TEMPLATE_DECL(n, BindArg)> \
+ slot(const Func &func, BOOST_SIGNALS2_PREFIXED_FULL_REF_ARGS(n, const BindArg)): \
+ base_type(func, BOOST_SIGNALS2_SIGNATURE_ARG_NAMES(n)) \
+ {}
+ BOOST_PP_REPEAT_FROM_TO(1, BOOST_SIGNALS2_SLOT_MAX_BINDING_ARGS, BOOST_SIGNALS2_SLOT_BINDING_CONSTRUCTOR, ~)
+#undef BOOST_SIGNALS2_SLOT_BINDING_CONSTRUCTOR
+ };
+ } // namespace signals2
+}
+
+#endif // BOOST_SIGNALS2_PREPROCESSED_SLOT_HPP
diff --git a/third_party/boost/boost/signals2/signal.hpp b/third_party/boost/boost/signals2/signal.hpp
new file mode 100644
index 0000000..afdfa66
--- /dev/null
+++ b/third_party/boost/boost/signals2/signal.hpp
@@ -0,0 +1,62 @@
+// A thread-safe version of Boost.Signals.
+
+// Copyright Frank Mori Hess 2007-2009
+//
+// Use, modification and
+// distribution is subject to the 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_SIGNALS2_SIGNAL_HPP
+#define BOOST_SIGNALS2_SIGNAL_HPP
+
+#include <algorithm>
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/function.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/signals2/connection.hpp>
+#include <boost/signals2/detail/unique_lock.hpp>
+#include <boost/signals2/detail/replace_slot_function.hpp>
+#include <boost/signals2/detail/result_type_wrapper.hpp>
+#include <boost/signals2/detail/signals_common.hpp>
+#include <boost/signals2/detail/signals_common_macros.hpp>
+#include <boost/signals2/detail/slot_groups.hpp>
+#include <boost/signals2/detail/slot_call_iterator.hpp>
+#include <boost/signals2/optional_last_value.hpp>
+#include <boost/signals2/mutex.hpp>
+#include <boost/signals2/slot.hpp>
+#include <functional>
+
+#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
+#include <boost/signals2/preprocessed_signal.hpp>
+#else
+#include <boost/signals2/variadic_signal.hpp>
+#endif
+
+namespace boost
+{
+ namespace signals2
+ {
+ // free swap function, findable by ADL
+ template<typename Signature,
+ typename Combiner,
+ typename Group,
+ typename GroupCompare,
+ typename SlotFunction,
+ typename ExtendedSlotFunction,
+ typename Mutex>
+ void swap(
+ signal<Signature, Combiner, Group, GroupCompare, SlotFunction, ExtendedSlotFunction, Mutex> &sig1,
+ signal<Signature, Combiner, Group, GroupCompare, SlotFunction, ExtendedSlotFunction, Mutex> &sig2)
+ {
+ sig1.swap(sig2);
+ }
+ }
+}
+
+#endif // BOOST_SIGNALS2_SIGNAL_HPP
diff --git a/third_party/boost/boost/signals2/signal_base.hpp b/third_party/boost/boost/signals2/signal_base.hpp
new file mode 100644
index 0000000..05b6b5f
--- /dev/null
+++ b/third_party/boost/boost/signals2/signal_base.hpp
@@ -0,0 +1,33 @@
+// Boost.Signals2 library
+
+// Copyright Frank Mori Hess 2007-2008.
+// Use, modification and
+// distribution is subject to the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// For more information, see http://www.boost.org
+
+#ifndef BOOST_SIGNALS2_SIGNAL_BASE_HPP
+#define BOOST_SIGNALS2_SIGNAL_BASE_HPP
+
+#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
+
+namespace boost {
+ namespace signals2 {
+ class slot_base;
+
+ class signal_base : public noncopyable
+ {
+ public:
+ friend class slot_base;
+
+ virtual ~signal_base() {}
+ protected:
+ virtual shared_ptr<void> lock_pimpl() const = 0;
+ };
+ } // end namespace signals2
+} // end namespace boost
+
+#endif // BOOST_SIGNALS2_SIGNAL_BASE_HPP
diff --git a/third_party/boost/boost/signals2/slot.hpp b/third_party/boost/boost/signals2/slot.hpp
new file mode 100644
index 0000000..b6ec4d7
--- /dev/null
+++ b/third_party/boost/boost/signals2/slot.hpp
@@ -0,0 +1,33 @@
+// Boost.Signals2 library
+
+// Copyright Frank Mori Hess 2009.
+//
+// Use, modification and
+// distribution is subject to the 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_SIGNALS2_SLOT_HPP
+#define BOOST_SIGNALS2_SLOT_HPP
+
+#include <boost/bind.hpp>
+#include <boost/config.hpp>
+#include <boost/function.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/ref.hpp>
+#include <boost/signals2/detail/signals_common.hpp>
+#include <boost/signals2/detail/signals_common_macros.hpp>
+#include <boost/signals2/detail/tracked_objects_visitor.hpp>
+#include <boost/signals2/slot_base.hpp>
+#include <boost/visit_each.hpp>
+#include <boost/weak_ptr.hpp>
+
+#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
+#include <boost/signals2/preprocessed_slot.hpp>
+#else
+#include <boost/signals2/variadic_slot.hpp>
+#endif
+
+#endif // BOOST_SIGNALS2_SLOT_HPP
diff --git a/third_party/boost/boost/signals2/slot_base.hpp b/third_party/boost/boost/signals2/slot_base.hpp
new file mode 100644
index 0000000..0dd80db
--- /dev/null
+++ b/third_party/boost/boost/signals2/slot_base.hpp
@@ -0,0 +1,106 @@
+// Boost.Signals2 library
+
+// Copyright Frank Mori Hess 2007-2008.
+// Copyright Timmo Stange 2007.
+// Copyright Douglas Gregor 2001-2004. Use, modification and
+// distribution is subject to the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// For more information, see http://www.boost.org
+
+#ifndef BOOST_SIGNALS2_SLOT_BASE_HPP
+#define BOOST_SIGNALS2_SLOT_BASE_HPP
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/signals2/detail/foreign_ptr.hpp>
+#include <boost/signals2/expired_slot.hpp>
+#include <boost/signals2/signal_base.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/variant.hpp>
+#include <vector>
+
+namespace boost
+{
+ namespace signals2
+ {
+ namespace detail
+ {
+ class tracked_objects_visitor;
+ class trackable_pointee;
+
+ typedef boost::variant<boost::weak_ptr<trackable_pointee>, boost::weak_ptr<void>, detail::foreign_void_weak_ptr > void_weak_ptr_variant;
+ typedef boost::variant<boost::shared_ptr<void>, detail::foreign_void_shared_ptr > void_shared_ptr_variant;
+ class lock_weak_ptr_visitor
+ {
+ public:
+ typedef void_shared_ptr_variant result_type;
+ template<typename WeakPtr>
+ result_type operator()(const WeakPtr &wp) const
+ {
+ return wp.lock();
+ }
+ // overload to prevent incrementing use count of shared_ptr associated
+ // with signals2::trackable objects
+ result_type operator()(const weak_ptr<trackable_pointee> &) const
+ {
+ return boost::shared_ptr<void>();
+ }
+ };
+ class expired_weak_ptr_visitor
+ {
+ public:
+ typedef bool result_type;
+ template<typename WeakPtr>
+ bool operator()(const WeakPtr &wp) const
+ {
+ return wp.expired();
+ }
+ };
+ }
+
+ class slot_base
+ {
+ public:
+ typedef std::vector<detail::void_weak_ptr_variant> tracked_container_type;
+ typedef std::vector<detail::void_shared_ptr_variant> locked_container_type;
+
+ const tracked_container_type& tracked_objects() const {return _tracked_objects;}
+ locked_container_type lock() const
+ {
+ locked_container_type locked_objects;
+ tracked_container_type::const_iterator it;
+ for(it = tracked_objects().begin(); it != tracked_objects().end(); ++it)
+ {
+ locked_objects.push_back(apply_visitor(detail::lock_weak_ptr_visitor(), *it));
+ if(apply_visitor(detail::expired_weak_ptr_visitor(), *it))
+ {
+ throw expired_slot();
+ }
+ }
+ return locked_objects;
+ }
+ bool expired() const
+ {
+ tracked_container_type::const_iterator it;
+ for(it = tracked_objects().begin(); it != tracked_objects().end(); ++it)
+ {
+ if(apply_visitor(detail::expired_weak_ptr_visitor(), *it)) return true;
+ }
+ return false;
+ }
+ protected:
+ friend class detail::tracked_objects_visitor;
+
+ void track_signal(const signal_base &signal)
+ {
+ _tracked_objects.push_back(signal.lock_pimpl());
+ }
+
+ tracked_container_type _tracked_objects;
+ };
+ }
+} // end namespace boost
+
+#endif // BOOST_SIGNALS2_SLOT_BASE_HPP
diff --git a/third_party/boost/boost/signals2/trackable.hpp b/third_party/boost/boost/signals2/trackable.hpp
new file mode 100644
index 0000000..7837d3f
--- /dev/null
+++ b/third_party/boost/boost/signals2/trackable.hpp
@@ -0,0 +1,59 @@
+// Boost.Signals2 library
+
+// Copyright Frank Mori Hess 2007,2009.
+// Copyright Timmo Stange 2007.
+// Copyright Douglas Gregor 2001-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)
+
+// Compatibility class to ease porting from the original
+// Boost.Signals library. However,
+// boost::signals2::trackable is NOT thread-safe.
+
+// For more information, see http://www.boost.org
+
+#ifndef BOOST_SIGNALS2_TRACKABLE_HPP
+#define BOOST_SIGNALS2_TRACKABLE_HPP
+
+#include <boost/assert.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+namespace boost {
+ namespace signals2 {
+ namespace detail
+ {
+ class tracked_objects_visitor;
+
+ // trackable_pointee is used to identify the tracked shared_ptr
+ // originating from the signals2::trackable class. These tracked
+ // shared_ptr are special in that we shouldn't bother to
+ // increment their use count during signal invocation, since
+ // they don't actually control the lifetime of the
+ // signals2::trackable object they are associated with.
+ class trackable_pointee
+ {};
+ }
+ class trackable {
+ protected:
+ trackable(): _tracked_ptr(static_cast<detail::trackable_pointee*>(0)) {}
+ trackable(const trackable &): _tracked_ptr(static_cast<detail::trackable_pointee*>(0)) {}
+ trackable& operator=(const trackable &)
+ {
+ return *this;
+ }
+ ~trackable() {}
+ private:
+ friend class detail::tracked_objects_visitor;
+ weak_ptr<detail::trackable_pointee> get_weak_ptr() const
+ {
+ return _tracked_ptr;
+ }
+
+ shared_ptr<detail::trackable_pointee> _tracked_ptr;
+ };
+ } // end namespace signals2
+} // end namespace boost
+
+#endif // BOOST_SIGNALS2_TRACKABLE_HPP
diff --git a/third_party/boost/boost/smart_ptr/bad_weak_ptr.hpp b/third_party/boost/boost/smart_ptr/bad_weak_ptr.hpp
new file mode 100644
index 0000000..3e0a1b7
--- /dev/null
+++ b/third_party/boost/boost/smart_ptr/bad_weak_ptr.hpp
@@ -0,0 +1,59 @@
+#ifndef BOOST_SMART_PTR_BAD_WEAK_PTR_HPP_INCLUDED
+#define BOOST_SMART_PTR_BAD_WEAK_PTR_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// boost/smart_ptr/bad_weak_ptr.hpp
+//
+// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <exception>
+
+#ifdef __BORLANDC__
+# pragma warn -8026 // Functions with excep. spec. are not expanded inline
+#endif
+
+namespace boost
+{
+
+// The standard library that comes with Borland C++ 5.5.1, 5.6.4
+// defines std::exception and its members as having C calling
+// convention (-pc). When the definition of bad_weak_ptr
+// is compiled with -ps, the compiler issues an error.
+// Hence, the temporary #pragma option -pc below.
+
+#if defined(__BORLANDC__) && __BORLANDC__ <= 0x564
+# pragma option push -pc
+#endif
+
+class bad_weak_ptr: public std::exception
+{
+public:
+
+ virtual char const * what() const throw()
+ {
+ return "tr1::bad_weak_ptr";
+ }
+};
+
+#if defined(__BORLANDC__) && __BORLANDC__ <= 0x564
+# pragma option pop
+#endif
+
+} // namespace boost
+
+#ifdef __BORLANDC__
+# pragma warn .8026 // Functions with excep. spec. are not expanded inline
+#endif
+
+#endif // #ifndef BOOST_SMART_PTR_BAD_WEAK_PTR_HPP_INCLUDED
diff --git a/third_party/boost/boost/smart_ptr/detail/operator_bool.hpp b/third_party/boost/boost/smart_ptr/detail/operator_bool.hpp
new file mode 100644
index 0000000..c0289b8
--- /dev/null
+++ b/third_party/boost/boost/smart_ptr/detail/operator_bool.hpp
@@ -0,0 +1,64 @@
+// This header intentionally has no include guards.
+//
+// Copyright (c) 2001-2009, 2012 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#if !defined( BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS ) && !defined( BOOST_NO_CXX11_NULLPTR )\
+ && !(defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5130))
+
+ explicit operator bool () const BOOST_NOEXCEPT
+ {
+ return px != 0;
+ }
+
+#elif ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__)
+
+ operator bool () const BOOST_NOEXCEPT
+ {
+ return px != 0;
+ }
+
+#elif defined( _MANAGED )
+
+ static void unspecified_bool( this_type*** )
+ {
+ }
+
+ typedef void (*unspecified_bool_type)( this_type*** );
+
+ operator unspecified_bool_type() const BOOST_NOEXCEPT
+ {
+ return px == 0? 0: unspecified_bool;
+ }
+
+#elif \
+ ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \
+ ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) || \
+ ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) )
+
+ typedef element_type * (this_type::*unspecified_bool_type)() const;
+
+ operator unspecified_bool_type() const BOOST_NOEXCEPT
+ {
+ return px == 0? 0: &this_type::get;
+ }
+
+#else
+
+ typedef element_type * this_type::*unspecified_bool_type;
+
+ operator unspecified_bool_type() const BOOST_NOEXCEPT
+ {
+ return px == 0? 0: &this_type::px;
+ }
+
+#endif
+
+ // operator! is redundant, but some compilers need it
+ bool operator! () const BOOST_NOEXCEPT
+ {
+ return px == 0;
+ }
diff --git a/third_party/boost/boost/smart_ptr/detail/shared_count.hpp b/third_party/boost/boost/smart_ptr/detail/shared_count.hpp
new file mode 100644
index 0000000..c52f91a
--- /dev/null
+++ b/third_party/boost/boost/smart_ptr/detail/shared_count.hpp
@@ -0,0 +1,709 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// detail/shared_count.hpp
+//
+// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
+// Copyright 2004-2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifdef __BORLANDC__
+# pragma warn -8027 // Functions containing try are not expanded inline
+#endif
+
+#include <boost/config.hpp>
+#include <boost/checked_delete.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/smart_ptr/bad_weak_ptr.hpp>
+#include <boost/smart_ptr/detail/sp_counted_base.hpp>
+#include <boost/smart_ptr/detail/sp_counted_impl.hpp>
+#include <boost/smart_ptr/detail/sp_disable_deprecated.hpp>
+#include <boost/detail/workaround.hpp>
+// In order to avoid circular dependencies with Boost.TR1
+// we make sure that our include of <memory> doesn't try to
+// pull in the TR1 headers: that's why we use this header
+// rather than including <memory> directly:
+#include <boost/config/no_tr1/memory.hpp> // std::auto_ptr
+#include <functional> // std::less
+
+#ifdef BOOST_NO_EXCEPTIONS
+# include <new> // std::bad_alloc
+#endif
+
+#include <boost/core/addressof.hpp>
+
+#if defined( BOOST_SP_DISABLE_DEPRECATED )
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
+namespace boost
+{
+
+namespace movelib
+{
+
+ template< class T, class D > class unique_ptr;
+
+} // namespace movelib
+
+namespace detail
+{
+
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+
+int const shared_count_id = 0x2C35F101;
+int const weak_count_id = 0x298C38A4;
+
+#endif
+
+struct sp_nothrow_tag {};
+
+template< class D > struct sp_inplace_tag
+{
+};
+
+template< class T > class sp_reference_wrapper
+{
+public:
+
+ explicit sp_reference_wrapper( T & t): t_( boost::addressof( t ) )
+ {
+ }
+
+ template< class Y > void operator()( Y * p ) const
+ {
+ (*t_)( p );
+ }
+
+private:
+
+ T * t_;
+};
+
+template< class D > struct sp_convert_reference
+{
+ typedef D type;
+};
+
+template< class D > struct sp_convert_reference< D& >
+{
+ typedef sp_reference_wrapper< D > type;
+};
+
+class weak_count;
+
+class shared_count
+{
+private:
+
+ sp_counted_base * pi_;
+
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ int id_;
+#endif
+
+ friend class weak_count;
+
+public:
+
+ shared_count(): pi_(0) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+ {
+ }
+
+ template<class Y> explicit shared_count( Y * p ): pi_( 0 )
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+ {
+#ifndef BOOST_NO_EXCEPTIONS
+
+ try
+ {
+ pi_ = new sp_counted_impl_p<Y>( p );
+ }
+ catch(...)
+ {
+ boost::checked_delete( p );
+ throw;
+ }
+
+#else
+
+ pi_ = new sp_counted_impl_p<Y>( p );
+
+ if( pi_ == 0 )
+ {
+ boost::checked_delete( p );
+ boost::throw_exception( std::bad_alloc() );
+ }
+
+#endif
+ }
+
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 )
+ template<class Y, class D> shared_count( Y * p, D d ): pi_(0)
+#else
+ template<class P, class D> shared_count( P p, D d ): pi_(0)
+#endif
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+ {
+#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 )
+ typedef Y* P;
+#endif
+#ifndef BOOST_NO_EXCEPTIONS
+
+ try
+ {
+ pi_ = new sp_counted_impl_pd<P, D>(p, d);
+ }
+ catch(...)
+ {
+ d(p); // delete p
+ throw;
+ }
+
+#else
+
+ pi_ = new sp_counted_impl_pd<P, D>(p, d);
+
+ if(pi_ == 0)
+ {
+ d(p); // delete p
+ boost::throw_exception(std::bad_alloc());
+ }
+
+#endif
+ }
+
+#if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
+
+ template< class P, class D > shared_count( P p, sp_inplace_tag<D> ): pi_( 0 )
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+ {
+#ifndef BOOST_NO_EXCEPTIONS
+
+ try
+ {
+ pi_ = new sp_counted_impl_pd< P, D >( p );
+ }
+ catch( ... )
+ {
+ D::operator_fn( p ); // delete p
+ throw;
+ }
+
+#else
+
+ pi_ = new sp_counted_impl_pd< P, D >( p );
+
+ if( pi_ == 0 )
+ {
+ D::operator_fn( p ); // delete p
+ boost::throw_exception( std::bad_alloc() );
+ }
+
+#endif // #ifndef BOOST_NO_EXCEPTIONS
+ }
+
+#endif // !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
+
+ template<class P, class D, class A> shared_count( P p, D d, A a ): pi_( 0 )
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+ {
+ typedef sp_counted_impl_pda<P, D, A> impl_type;
+
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+ typedef typename std::allocator_traits<A>::template rebind_alloc< impl_type > A2;
+
+#else
+
+ typedef typename A::template rebind< impl_type >::other A2;
+
+#endif
+
+ A2 a2( a );
+
+#ifndef BOOST_NO_EXCEPTIONS
+
+ try
+ {
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+ impl_type * pi = std::allocator_traits<A2>::allocate( a2, 1 );
+ pi_ = pi;
+ std::allocator_traits<A2>::construct( a2, pi, p, d, a );
+
+#else
+
+ pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
+ ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
+
+#endif
+ }
+ catch(...)
+ {
+ d( p );
+
+ if( pi_ != 0 )
+ {
+ a2.deallocate( static_cast< impl_type* >( pi_ ), 1 );
+ }
+
+ throw;
+ }
+
+#else
+
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+ impl_type * pi = std::allocator_traits<A2>::allocate( a2, 1 );
+ pi_ = pi;
+
+#else
+
+ pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
+
+#endif
+
+ if( pi_ != 0 )
+ {
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+ std::allocator_traits<A2>::construct( a2, pi, p, d, a );
+
+#else
+
+ ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
+
+#endif
+ }
+ else
+ {
+ d( p );
+ boost::throw_exception( std::bad_alloc() );
+ }
+
+#endif
+ }
+
+#if !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
+
+ template< class P, class D, class A > shared_count( P p, sp_inplace_tag< D >, A a ): pi_( 0 )
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+ {
+ typedef sp_counted_impl_pda< P, D, A > impl_type;
+
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+ typedef typename std::allocator_traits<A>::template rebind_alloc< impl_type > A2;
+
+#else
+
+ typedef typename A::template rebind< impl_type >::other A2;
+
+#endif
+
+ A2 a2( a );
+
+#ifndef BOOST_NO_EXCEPTIONS
+
+ try
+ {
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+ impl_type * pi = std::allocator_traits<A2>::allocate( a2, 1 );
+ pi_ = pi;
+ std::allocator_traits<A2>::construct( a2, pi, p, a );
+
+#else
+
+ pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
+ ::new( static_cast< void* >( pi_ ) ) impl_type( p, a );
+
+#endif
+ }
+ catch(...)
+ {
+ D::operator_fn( p );
+
+ if( pi_ != 0 )
+ {
+ a2.deallocate( static_cast< impl_type* >( pi_ ), 1 );
+ }
+
+ throw;
+ }
+
+#else
+
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+ impl_type * pi = std::allocator_traits<A2>::allocate( a2, 1 );
+ pi_ = pi;
+
+#else
+
+ pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
+
+#endif
+
+ if( pi_ != 0 )
+ {
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+ std::allocator_traits<A2>::construct( a2, pi, p, a );
+
+#else
+
+ ::new( static_cast< void* >( pi_ ) ) impl_type( p, a );
+
+#endif
+ }
+ else
+ {
+ D::operator_fn( p );
+ boost::throw_exception( std::bad_alloc() );
+ }
+
+#endif // #ifndef BOOST_NO_EXCEPTIONS
+ }
+
+#endif // !defined( BOOST_NO_FUNCTION_TEMPLATE_ORDERING )
+
+#ifndef BOOST_NO_AUTO_PTR
+
+ // auto_ptr<Y> is special cased to provide the strong guarantee
+
+ template<class Y>
+ explicit shared_count( std::auto_ptr<Y> & r ): pi_( new sp_counted_impl_p<Y>( r.get() ) )
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+ {
+#ifdef BOOST_NO_EXCEPTIONS
+
+ if( pi_ == 0 )
+ {
+ boost::throw_exception(std::bad_alloc());
+ }
+
+#endif
+
+ r.release();
+ }
+
+#endif
+
+#if !defined( BOOST_NO_CXX11_SMART_PTR )
+
+ template<class Y, class D>
+ explicit shared_count( std::unique_ptr<Y, D> & r ): pi_( 0 )
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+ {
+ typedef typename sp_convert_reference<D>::type D2;
+
+ D2 d2( r.get_deleter() );
+ pi_ = new sp_counted_impl_pd< typename std::unique_ptr<Y, D>::pointer, D2 >( r.get(), d2 );
+
+#ifdef BOOST_NO_EXCEPTIONS
+
+ if( pi_ == 0 )
+ {
+ boost::throw_exception( std::bad_alloc() );
+ }
+
+#endif
+
+ r.release();
+ }
+
+#endif
+
+ template<class Y, class D>
+ explicit shared_count( boost::movelib::unique_ptr<Y, D> & r ): pi_( 0 )
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+ {
+ typedef typename sp_convert_reference<D>::type D2;
+
+ D2 d2( r.get_deleter() );
+ pi_ = new sp_counted_impl_pd< typename boost::movelib::unique_ptr<Y, D>::pointer, D2 >( r.get(), d2 );
+
+#ifdef BOOST_NO_EXCEPTIONS
+
+ if( pi_ == 0 )
+ {
+ boost::throw_exception( std::bad_alloc() );
+ }
+
+#endif
+
+ r.release();
+ }
+
+ ~shared_count() // nothrow
+ {
+ if( pi_ != 0 ) pi_->release();
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ id_ = 0;
+#endif
+ }
+
+ shared_count(shared_count const & r): pi_(r.pi_) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+ {
+ if( pi_ != 0 ) pi_->add_ref_copy();
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ shared_count(shared_count && r): pi_(r.pi_) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+ {
+ r.pi_ = 0;
+ }
+
+#endif
+
+ explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0
+ shared_count( weak_count const & r, sp_nothrow_tag ); // constructs an empty *this when r.use_count() == 0
+
+ shared_count & operator= (shared_count const & r) // nothrow
+ {
+ sp_counted_base * tmp = r.pi_;
+
+ if( tmp != pi_ )
+ {
+ if( tmp != 0 ) tmp->add_ref_copy();
+ if( pi_ != 0 ) pi_->release();
+ pi_ = tmp;
+ }
+
+ return *this;
+ }
+
+ void swap(shared_count & r) // nothrow
+ {
+ sp_counted_base * tmp = r.pi_;
+ r.pi_ = pi_;
+ pi_ = tmp;
+ }
+
+ long use_count() const // nothrow
+ {
+ return pi_ != 0? pi_->use_count(): 0;
+ }
+
+ bool unique() const // nothrow
+ {
+ return use_count() == 1;
+ }
+
+ bool empty() const // nothrow
+ {
+ return pi_ == 0;
+ }
+
+ friend inline bool operator==(shared_count const & a, shared_count const & b)
+ {
+ return a.pi_ == b.pi_;
+ }
+
+ friend inline bool operator<(shared_count const & a, shared_count const & b)
+ {
+ return std::less<sp_counted_base *>()( a.pi_, b.pi_ );
+ }
+
+ void * get_deleter( sp_typeinfo const & ti ) const
+ {
+ return pi_? pi_->get_deleter( ti ): 0;
+ }
+
+ void * get_untyped_deleter() const
+ {
+ return pi_? pi_->get_untyped_deleter(): 0;
+ }
+};
+
+
+class weak_count
+{
+private:
+
+ sp_counted_base * pi_;
+
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ int id_;
+#endif
+
+ friend class shared_count;
+
+public:
+
+ weak_count(): pi_(0) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(weak_count_id)
+#endif
+ {
+ }
+
+ weak_count(shared_count const & r): pi_(r.pi_) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(weak_count_id)
+#endif
+ {
+ if(pi_ != 0) pi_->weak_add_ref();
+ }
+
+ weak_count(weak_count const & r): pi_(r.pi_) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(weak_count_id)
+#endif
+ {
+ if(pi_ != 0) pi_->weak_add_ref();
+ }
+
+// Move support
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ weak_count(weak_count && r): pi_(r.pi_) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(weak_count_id)
+#endif
+ {
+ r.pi_ = 0;
+ }
+
+#endif
+
+ ~weak_count() // nothrow
+ {
+ if(pi_ != 0) pi_->weak_release();
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ id_ = 0;
+#endif
+ }
+
+ weak_count & operator= (shared_count const & r) // nothrow
+ {
+ sp_counted_base * tmp = r.pi_;
+
+ if( tmp != pi_ )
+ {
+ if(tmp != 0) tmp->weak_add_ref();
+ if(pi_ != 0) pi_->weak_release();
+ pi_ = tmp;
+ }
+
+ return *this;
+ }
+
+ weak_count & operator= (weak_count const & r) // nothrow
+ {
+ sp_counted_base * tmp = r.pi_;
+
+ if( tmp != pi_ )
+ {
+ if(tmp != 0) tmp->weak_add_ref();
+ if(pi_ != 0) pi_->weak_release();
+ pi_ = tmp;
+ }
+
+ return *this;
+ }
+
+ void swap(weak_count & r) // nothrow
+ {
+ sp_counted_base * tmp = r.pi_;
+ r.pi_ = pi_;
+ pi_ = tmp;
+ }
+
+ long use_count() const // nothrow
+ {
+ return pi_ != 0? pi_->use_count(): 0;
+ }
+
+ bool empty() const // nothrow
+ {
+ return pi_ == 0;
+ }
+
+ friend inline bool operator==(weak_count const & a, weak_count const & b)
+ {
+ return a.pi_ == b.pi_;
+ }
+
+ friend inline bool operator<(weak_count const & a, weak_count const & b)
+ {
+ return std::less<sp_counted_base *>()(a.pi_, b.pi_);
+ }
+};
+
+inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ )
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+{
+ if( pi_ == 0 || !pi_->add_ref_lock() )
+ {
+ boost::throw_exception( boost::bad_weak_ptr() );
+ }
+}
+
+inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ): pi_( r.pi_ )
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ , id_(shared_count_id)
+#endif
+{
+ if( pi_ != 0 && !pi_->add_ref_lock() )
+ {
+ pi_ = 0;
+ }
+}
+
+} // namespace detail
+
+} // namespace boost
+
+#if defined( BOOST_SP_DISABLE_DEPRECATED )
+#pragma GCC diagnostic pop
+#endif
+
+#ifdef __BORLANDC__
+# pragma warn .8027 // Functions containing try are not expanded inline
+#endif
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
diff --git a/third_party/boost/boost/smart_ptr/detail/sp_convertible.hpp b/third_party/boost/boost/smart_ptr/detail/sp_convertible.hpp
new file mode 100644
index 0000000..4bba9ed
--- /dev/null
+++ b/third_party/boost/boost/smart_ptr/detail/sp_convertible.hpp
@@ -0,0 +1,92 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// detail/sp_convertible.hpp
+//
+// Copyright 2008 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/config.hpp>
+#include <cstddef>
+
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( BOOST_NO_SFINAE )
+# define BOOST_SP_NO_SP_CONVERTIBLE
+#endif
+
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ < 303 )
+# define BOOST_SP_NO_SP_CONVERTIBLE
+#endif
+
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __BORLANDC__ ) && ( __BORLANDC__ < 0x630 )
+# define BOOST_SP_NO_SP_CONVERTIBLE
+#endif
+
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
+
+namespace boost
+{
+
+namespace detail
+{
+
+template< class Y, class T > struct sp_convertible
+{
+ typedef char (&yes) [1];
+ typedef char (&no) [2];
+
+ static yes f( T* );
+ static no f( ... );
+
+ enum _vt { value = sizeof( (f)( static_cast<Y*>(0) ) ) == sizeof(yes) };
+};
+
+template< class Y, class T > struct sp_convertible< Y, T[] >
+{
+ enum _vt { value = false };
+};
+
+template< class Y, class T > struct sp_convertible< Y[], T[] >
+{
+ enum _vt { value = sp_convertible< Y[1], T[1] >::value };
+};
+
+template< class Y, std::size_t N, class T > struct sp_convertible< Y[N], T[] >
+{
+ enum _vt { value = sp_convertible< Y[1], T[1] >::value };
+};
+
+struct sp_empty
+{
+};
+
+template< bool > struct sp_enable_if_convertible_impl;
+
+template<> struct sp_enable_if_convertible_impl<true>
+{
+ typedef sp_empty type;
+};
+
+template<> struct sp_enable_if_convertible_impl<false>
+{
+};
+
+template< class Y, class T > struct sp_enable_if_convertible: public sp_enable_if_convertible_impl< sp_convertible< Y, T >::value >
+{
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // !defined( BOOST_SP_NO_SP_CONVERTIBLE )
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED
diff --git a/third_party/boost/boost/smart_ptr/detail/sp_counted_base.hpp b/third_party/boost/boost/smart_ptr/detail/sp_counted_base.hpp
new file mode 100644
index 0000000..0addf07
--- /dev/null
+++ b/third_party/boost/boost/smart_ptr/detail/sp_counted_base.hpp
@@ -0,0 +1,93 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// detail/sp_counted_base.hpp
+//
+// Copyright 2005-2013 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/config.hpp>
+#include <boost/smart_ptr/detail/sp_has_sync.hpp>
+
+#if defined( __clang__ ) && defined( __has_extension )
+# if __has_extension( __c_atomic__ )
+# define BOOST_SP_HAS_CLANG_C11_ATOMICS
+# endif
+#endif
+
+#if defined( BOOST_SP_DISABLE_THREADS )
+# include <boost/smart_ptr/detail/sp_counted_base_nt.hpp>
+
+#elif defined( BOOST_SP_USE_STD_ATOMIC )
+# include <boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp>
+
+#elif defined( BOOST_SP_USE_SPINLOCK )
+# include <boost/smart_ptr/detail/sp_counted_base_spin.hpp>
+
+#elif defined( BOOST_SP_USE_PTHREADS )
+# include <boost/smart_ptr/detail/sp_counted_base_pt.hpp>
+
+#elif defined( BOOST_DISABLE_THREADS ) && !defined( BOOST_SP_ENABLE_THREADS ) && !defined( BOOST_DISABLE_WIN32 )
+# include <boost/smart_ptr/detail/sp_counted_base_nt.hpp>
+
+#elif defined( BOOST_SP_HAS_CLANG_C11_ATOMICS )
+# include <boost/smart_ptr/detail/sp_counted_base_clang.hpp>
+
+#elif defined( __SNC__ )
+# include <boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp>
+
+#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) && !defined(__PATHSCALE__)
+# include <boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp>
+
+#elif defined(__HP_aCC) && defined(__ia64)
+# include <boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp>
+
+#elif defined( __GNUC__ ) && defined( __ia64__ ) && !defined( __INTEL_COMPILER ) && !defined(__PATHSCALE__)
+# include <boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp>
+
+#elif defined( __IBMCPP__ ) && defined( __powerpc )
+# include <boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp>
+
+#elif defined( __MWERKS__ ) && defined( __POWERPC__ )
+# include <boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp>
+
+#elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) && !defined(__PATHSCALE__) && !defined( _AIX )
+# include <boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp>
+
+#elif defined( __GNUC__ ) && ( defined( __mips__ ) || defined( _mips ) ) && !defined(__PATHSCALE__)
+# include <boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp>
+
+#elif defined( BOOST_SP_HAS_SYNC )
+# include <boost/smart_ptr/detail/sp_counted_base_sync.hpp>
+
+#elif defined(__GNUC__) && ( defined( __sparcv9 ) || ( defined( __sparcv8 ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 402 ) ) )
+# include <boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp>
+
+#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined(__CYGWIN__)
+# include <boost/smart_ptr/detail/sp_counted_base_w32.hpp>
+
+#elif defined( _AIX )
+# include <boost/smart_ptr/detail/sp_counted_base_aix.hpp>
+
+#elif !defined( BOOST_HAS_THREADS )
+# include <boost/smart_ptr/detail/sp_counted_base_nt.hpp>
+
+#else
+# include <boost/smart_ptr/detail/sp_counted_base_spin.hpp>
+
+#endif
+
+#undef BOOST_SP_HAS_CLANG_C11_ATOMICS
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED
diff --git a/third_party/boost/boost/smart_ptr/detail/sp_counted_base_clang.hpp b/third_party/boost/boost/smart_ptr/detail/sp_counted_base_clang.hpp
new file mode 100644
index 0000000..b3a9f3c
--- /dev/null
+++ b/third_party/boost/boost/smart_ptr/detail/sp_counted_base_clang.hpp
@@ -0,0 +1,140 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CLANG_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CLANG_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// detail/sp_counted_base_clang.hpp - __c11 clang intrinsics
+//
+// Copyright (c) 2007, 2013, 2015 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/detail/sp_typeinfo.hpp>
+#include <boost/cstdint.hpp>
+
+namespace boost
+{
+
+namespace detail
+{
+
+typedef _Atomic( boost::int_least32_t ) atomic_int_least32_t;
+
+inline void atomic_increment( atomic_int_least32_t * pw )
+{
+ __c11_atomic_fetch_add( pw, 1, __ATOMIC_RELAXED );
+}
+
+inline boost::int_least32_t atomic_decrement( atomic_int_least32_t * pw )
+{
+ return __c11_atomic_fetch_sub( pw, 1, __ATOMIC_ACQ_REL );
+}
+
+inline boost::int_least32_t atomic_conditional_increment( atomic_int_least32_t * pw )
+{
+ // long r = *pw;
+ // if( r != 0 ) ++*pw;
+ // return r;
+
+ boost::int_least32_t r = __c11_atomic_load( pw, __ATOMIC_RELAXED );
+
+ for( ;; )
+ {
+ if( r == 0 )
+ {
+ return r;
+ }
+
+ if( __c11_atomic_compare_exchange_weak( pw, &r, r + 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED ) )
+ {
+ return r;
+ }
+ }
+}
+
+class sp_counted_base
+{
+private:
+
+ sp_counted_base( sp_counted_base const & );
+ sp_counted_base & operator= ( sp_counted_base const & );
+
+ atomic_int_least32_t use_count_; // #shared
+ atomic_int_least32_t weak_count_; // #weak + (#shared != 0)
+
+public:
+
+ sp_counted_base()
+ {
+ __c11_atomic_init( &use_count_, 1 );
+ __c11_atomic_init( &weak_count_, 1 );
+ }
+
+ virtual ~sp_counted_base() // nothrow
+ {
+ }
+
+ // dispose() is called when use_count_ drops to zero, to release
+ // the resources managed by *this.
+
+ virtual void dispose() = 0; // nothrow
+
+ // destroy() is called when weak_count_ drops to zero.
+
+ virtual void destroy() // nothrow
+ {
+ delete this;
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_untyped_deleter() = 0;
+
+ void add_ref_copy()
+ {
+ atomic_increment( &use_count_ );
+ }
+
+ bool add_ref_lock() // true on success
+ {
+ return atomic_conditional_increment( &use_count_ ) != 0;
+ }
+
+ void release() // nothrow
+ {
+ if( atomic_decrement( &use_count_ ) == 1 )
+ {
+ dispose();
+ weak_release();
+ }
+ }
+
+ void weak_add_ref() // nothrow
+ {
+ atomic_increment( &weak_count_ );
+ }
+
+ void weak_release() // nothrow
+ {
+ if( atomic_decrement( &weak_count_ ) == 1 )
+ {
+ destroy();
+ }
+ }
+
+ long use_count() const // nothrow
+ {
+ return __c11_atomic_load( const_cast< atomic_int_least32_t* >( &use_count_ ), __ATOMIC_ACQUIRE );
+ }
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CLANG_HPP_INCLUDED
diff --git a/third_party/boost/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp b/third_party/boost/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp
new file mode 100644
index 0000000..173dce5
--- /dev/null
+++ b/third_party/boost/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp
@@ -0,0 +1,174 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// detail/sp_counted_base_gcc_x86.hpp - g++ on 486+ or AMD64
+//
+// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
+// Copyright 2004-2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+//
+// Lock-free algorithm by Alexander Terekhov
+//
+// Thanks to Ben Hitchings for the #weak + (#shared != 0)
+// formulation
+//
+
+#include <boost/detail/sp_typeinfo.hpp>
+
+namespace boost
+{
+
+namespace detail
+{
+
+inline int atomic_exchange_and_add( int * pw, int dv )
+{
+ // int r = *pw;
+ // *pw += dv;
+ // return r;
+
+ int r;
+
+ __asm__ __volatile__
+ (
+ "lock\n\t"
+ "xadd %1, %0":
+ "=m"( *pw ), "=r"( r ): // outputs (%0, %1)
+ "m"( *pw ), "1"( dv ): // inputs (%2, %3 == %1)
+ "memory", "cc" // clobbers
+ );
+
+ return r;
+}
+
+inline void atomic_increment( int * pw )
+{
+ //atomic_exchange_and_add( pw, 1 );
+
+ __asm__
+ (
+ "lock\n\t"
+ "incl %0":
+ "=m"( *pw ): // output (%0)
+ "m"( *pw ): // input (%1)
+ "cc" // clobbers
+ );
+}
+
+inline int atomic_conditional_increment( int * pw )
+{
+ // int rv = *pw;
+ // if( rv != 0 ) ++*pw;
+ // return rv;
+
+ int rv, tmp;
+
+ __asm__
+ (
+ "movl %0, %%eax\n\t"
+ "0:\n\t"
+ "test %%eax, %%eax\n\t"
+ "je 1f\n\t"
+ "movl %%eax, %2\n\t"
+ "incl %2\n\t"
+ "lock\n\t"
+ "cmpxchgl %2, %0\n\t"
+ "jne 0b\n\t"
+ "1:":
+ "=m"( *pw ), "=&a"( rv ), "=&r"( tmp ): // outputs (%0, %1, %2)
+ "m"( *pw ): // input (%3)
+ "cc" // clobbers
+ );
+
+ return rv;
+}
+
+class sp_counted_base
+{
+private:
+
+ sp_counted_base( sp_counted_base const & );
+ sp_counted_base & operator= ( sp_counted_base const & );
+
+ int use_count_; // #shared
+ int weak_count_; // #weak + (#shared != 0)
+
+public:
+
+ sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
+ {
+ }
+
+ virtual ~sp_counted_base() // nothrow
+ {
+ }
+
+ // dispose() is called when use_count_ drops to zero, to release
+ // the resources managed by *this.
+
+ virtual void dispose() = 0; // nothrow
+
+ // destroy() is called when weak_count_ drops to zero.
+
+ virtual void destroy() // nothrow
+ {
+ delete this;
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
+ virtual void * get_untyped_deleter() = 0;
+
+ void add_ref_copy()
+ {
+ atomic_increment( &use_count_ );
+ }
+
+ bool add_ref_lock() // true on success
+ {
+ return atomic_conditional_increment( &use_count_ ) != 0;
+ }
+
+ void release() // nothrow
+ {
+ if( atomic_exchange_and_add( &use_count_, -1 ) == 1 )
+ {
+ dispose();
+ weak_release();
+ }
+ }
+
+ void weak_add_ref() // nothrow
+ {
+ atomic_increment( &weak_count_ );
+ }
+
+ void weak_release() // nothrow
+ {
+ if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 )
+ {
+ destroy();
+ }
+ }
+
+ long use_count() const // nothrow
+ {
+ return static_cast<int const volatile &>( use_count_ );
+ }
+};
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED
diff --git a/third_party/boost/boost/smart_ptr/detail/sp_counted_impl.hpp b/third_party/boost/boost/smart_ptr/detail/sp_counted_impl.hpp
new file mode 100644
index 0000000..1222f3c
--- /dev/null
+++ b/third_party/boost/boost/smart_ptr/detail/sp_counted_impl.hpp
@@ -0,0 +1,271 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// detail/sp_counted_impl.hpp
+//
+// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
+// Copyright 2004-2005 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/config.hpp>
+
+#if defined(BOOST_SP_USE_STD_ALLOCATOR) && defined(BOOST_SP_USE_QUICK_ALLOCATOR)
+# error BOOST_SP_USE_STD_ALLOCATOR and BOOST_SP_USE_QUICK_ALLOCATOR are incompatible.
+#endif
+
+#include <boost/checked_delete.hpp>
+#include <boost/smart_ptr/detail/sp_counted_base.hpp>
+
+#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
+#include <boost/smart_ptr/detail/quick_allocator.hpp>
+#endif
+
+#if defined(BOOST_SP_USE_STD_ALLOCATOR)
+#include <memory> // std::allocator
+#endif
+
+#include <cstddef> // std::size_t
+
+namespace boost
+{
+
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+
+void sp_scalar_constructor_hook( void * px, std::size_t size, void * pn );
+void sp_scalar_destructor_hook( void * px, std::size_t size, void * pn );
+
+#endif
+
+namespace detail
+{
+
+template<class X> class sp_counted_impl_p: public sp_counted_base
+{
+private:
+
+ X * px_;
+
+ sp_counted_impl_p( sp_counted_impl_p const & );
+ sp_counted_impl_p & operator= ( sp_counted_impl_p const & );
+
+ typedef sp_counted_impl_p<X> this_type;
+
+public:
+
+ explicit sp_counted_impl_p( X * px ): px_( px )
+ {
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ boost::sp_scalar_constructor_hook( px, sizeof(X), this );
+#endif
+ }
+
+ virtual void dispose() // nothrow
+ {
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ boost::sp_scalar_destructor_hook( px_, sizeof(X), this );
+#endif
+ boost::checked_delete( px_ );
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & )
+ {
+ return 0;
+ }
+
+ virtual void * get_untyped_deleter()
+ {
+ return 0;
+ }
+
+#if defined(BOOST_SP_USE_STD_ALLOCATOR)
+
+ void * operator new( std::size_t )
+ {
+ return std::allocator<this_type>().allocate( 1, static_cast<this_type *>(0) );
+ }
+
+ void operator delete( void * p )
+ {
+ std::allocator<this_type>().deallocate( static_cast<this_type *>(p), 1 );
+ }
+
+#endif
+
+#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
+
+ void * operator new( std::size_t )
+ {
+ return quick_allocator<this_type>::alloc();
+ }
+
+ void operator delete( void * p )
+ {
+ quick_allocator<this_type>::dealloc( p );
+ }
+
+#endif
+};
+
+//
+// Borland's Codeguard trips up over the -Vx- option here:
+//
+#ifdef __CODEGUARD__
+# pragma option push -Vx-
+#endif
+
+template<class P, class D> class sp_counted_impl_pd: public sp_counted_base
+{
+private:
+
+ P ptr; // copy constructor must not throw
+ D del; // copy constructor must not throw
+
+ sp_counted_impl_pd( sp_counted_impl_pd const & );
+ sp_counted_impl_pd & operator= ( sp_counted_impl_pd const & );
+
+ typedef sp_counted_impl_pd<P, D> this_type;
+
+public:
+
+ // pre: d(p) must not throw
+
+ sp_counted_impl_pd( P p, D & d ): ptr( p ), del( d )
+ {
+ }
+
+ sp_counted_impl_pd( P p ): ptr( p ), del()
+ {
+ }
+
+ virtual void dispose() // nothrow
+ {
+ del( ptr );
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti )
+ {
+ return ti == BOOST_SP_TYPEID(D)? &reinterpret_cast<char&>( del ): 0;
+ }
+
+ virtual void * get_untyped_deleter()
+ {
+ return &reinterpret_cast<char&>( del );
+ }
+
+#if defined(BOOST_SP_USE_STD_ALLOCATOR)
+
+ void * operator new( std::size_t )
+ {
+ return std::allocator<this_type>().allocate( 1, static_cast<this_type *>(0) );
+ }
+
+ void operator delete( void * p )
+ {
+ std::allocator<this_type>().deallocate( static_cast<this_type *>(p), 1 );
+ }
+
+#endif
+
+#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
+
+ void * operator new( std::size_t )
+ {
+ return quick_allocator<this_type>::alloc();
+ }
+
+ void operator delete( void * p )
+ {
+ quick_allocator<this_type>::dealloc( p );
+ }
+
+#endif
+};
+
+template<class P, class D, class A> class sp_counted_impl_pda: public sp_counted_base
+{
+private:
+
+ P p_; // copy constructor must not throw
+ D d_; // copy constructor must not throw
+ A a_; // copy constructor must not throw
+
+ sp_counted_impl_pda( sp_counted_impl_pda const & );
+ sp_counted_impl_pda & operator= ( sp_counted_impl_pda const & );
+
+ typedef sp_counted_impl_pda<P, D, A> this_type;
+
+public:
+
+ // pre: d( p ) must not throw
+
+ sp_counted_impl_pda( P p, D & d, A a ): p_( p ), d_( d ), a_( a )
+ {
+ }
+
+ sp_counted_impl_pda( P p, A a ): p_( p ), d_( a ), a_( a )
+ {
+ }
+
+ virtual void dispose() // nothrow
+ {
+ d_( p_ );
+ }
+
+ virtual void destroy() // nothrow
+ {
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+ typedef typename std::allocator_traits<A>::template rebind_alloc< this_type > A2;
+
+#else
+
+ typedef typename A::template rebind< this_type >::other A2;
+
+#endif
+
+ A2 a2( a_ );
+
+#if !defined( BOOST_NO_CXX11_ALLOCATOR )
+
+ std::allocator_traits<A2>::destroy( a2, this );
+
+#else
+
+ this->~this_type();
+
+#endif
+
+ a2.deallocate( this, 1 );
+ }
+
+ virtual void * get_deleter( sp_typeinfo const & ti )
+ {
+ return ti == BOOST_SP_TYPEID( D )? &reinterpret_cast<char&>( d_ ): 0;
+ }
+
+ virtual void * get_untyped_deleter()
+ {
+ return &reinterpret_cast<char&>( d_ );
+ }
+};
+
+#ifdef __CODEGUARD__
+# pragma option pop
+#endif
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED
diff --git a/third_party/boost/boost/smart_ptr/detail/sp_disable_deprecated.hpp b/third_party/boost/boost/smart_ptr/detail/sp_disable_deprecated.hpp
new file mode 100644
index 0000000..f79bdf3
--- /dev/null
+++ b/third_party/boost/boost/smart_ptr/detail/sp_disable_deprecated.hpp
@@ -0,0 +1,40 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_DISABLE_DEPRECATED_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_DISABLE_DEPRECATED_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// boost/smart_ptr/detail/sp_disable_deprecated.hpp
+//
+// Copyright 2015 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/config.hpp>
+
+#if defined( __GNUC__ ) && ( defined( __GXX_EXPERIMENTAL_CXX0X__ ) || ( __cplusplus >= 201103L ) )
+
+# if defined( BOOST_GCC )
+
+# if BOOST_GCC >= 40600
+# define BOOST_SP_DISABLE_DEPRECATED
+# endif
+
+# elif defined( __clang__ ) && defined( __has_warning )
+
+# if __has_warning( "-Wdeprecated-declarations" )
+# define BOOST_SP_DISABLE_DEPRECATED
+# endif
+
+# endif
+
+#endif
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_DISABLE_DEPRECATED_HPP_INCLUDED
diff --git a/third_party/boost/boost/smart_ptr/detail/sp_has_sync.hpp b/third_party/boost/boost/smart_ptr/detail/sp_has_sync.hpp
new file mode 100644
index 0000000..51c8682
--- /dev/null
+++ b/third_party/boost/boost/smart_ptr/detail/sp_has_sync.hpp
@@ -0,0 +1,69 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// boost/smart_ptr/detail/sp_has_sync.hpp
+//
+// Copyright (c) 2008, 2009 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// Defines the BOOST_SP_HAS_SYNC macro if the __sync_* intrinsics
+// are available.
+//
+
+#ifndef BOOST_SP_NO_SYNC
+
+#if defined( __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 )
+
+# define BOOST_SP_HAS_SYNC
+
+#elif defined( __IBMCPP__ ) && ( __IBMCPP__ >= 1210 )
+
+# define BOOST_SP_HAS_SYNC
+
+#elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
+
+#define BOOST_SP_HAS_SYNC
+
+#if defined( __arm__ ) || defined( __armel__ )
+#undef BOOST_SP_HAS_SYNC
+#endif
+
+#if defined( __hppa ) || defined( __hppa__ )
+#undef BOOST_SP_HAS_SYNC
+#endif
+
+#if defined( __m68k__ )
+#undef BOOST_SP_HAS_SYNC
+#endif
+
+#if defined( __sh__ )
+#undef BOOST_SP_HAS_SYNC
+#endif
+
+#if defined( __sparc__ )
+#undef BOOST_SP_HAS_SYNC
+#endif
+
+#if defined( __INTEL_COMPILER ) && !defined( __ia64__ ) && ( __INTEL_COMPILER < 1110 )
+#undef BOOST_SP_HAS_SYNC
+#endif
+
+#if defined(__PATHSCALE__) && ((__PATHCC__ == 4) && (__PATHCC_MINOR__ < 9))
+#undef BOOST_SP_HAS_SYNC
+#endif
+
+#endif
+
+#endif // #ifndef BOOST_SP_NO_SYNC
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED
diff --git a/third_party/boost/boost/smart_ptr/detail/sp_nullptr_t.hpp b/third_party/boost/boost/smart_ptr/detail/sp_nullptr_t.hpp
new file mode 100644
index 0000000..219ae80
--- /dev/null
+++ b/third_party/boost/boost/smart_ptr/detail/sp_nullptr_t.hpp
@@ -0,0 +1,45 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SP_NULLPTR_T_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SP_NULLPTR_T_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// detail/sp_nullptr_t.hpp
+//
+// Copyright 2013 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+
+#include <boost/config.hpp>
+#include <cstddef>
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+namespace boost
+{
+
+namespace detail
+{
+
+#if !defined( BOOST_NO_CXX11_DECLTYPE ) && ( ( defined( __clang__ ) && !defined( _LIBCPP_VERSION ) ) || defined( __INTEL_COMPILER ) )
+
+ typedef decltype(nullptr) sp_nullptr_t;
+
+#else
+
+ typedef std::nullptr_t sp_nullptr_t;
+
+#endif
+
+} // namespace detail
+
+} // namespace boost
+
+#endif // !defined( BOOST_NO_CXX11_NULLPTR )
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_NULLPTR_T_HPP_INCLUDED
diff --git a/third_party/boost/boost/smart_ptr/detail/spinlock.hpp b/third_party/boost/boost/smart_ptr/detail/spinlock.hpp
new file mode 100644
index 0000000..19f93d7
--- /dev/null
+++ b/third_party/boost/boost/smart_ptr/detail/spinlock.hpp
@@ -0,0 +1,65 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SPINLOCK_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// boost/detail/spinlock.hpp
+//
+// Copyright (c) 2008 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// struct spinlock
+// {
+// void lock();
+// bool try_lock();
+// void unlock();
+//
+// class scoped_lock;
+// };
+//
+// #define BOOST_DETAIL_SPINLOCK_INIT <unspecified>
+//
+
+#include <boost/config.hpp>
+#include <boost/smart_ptr/detail/sp_has_sync.hpp>
+
+#if defined( BOOST_SP_USE_STD_ATOMIC )
+# if !defined( __clang__ )
+# include <boost/smart_ptr/detail/spinlock_std_atomic.hpp>
+# else
+// Clang (at least up to 3.4) can't compile spinlock_pool when
+// using std::atomic, so substitute the __sync implementation instead.
+# include <boost/smart_ptr/detail/spinlock_sync.hpp>
+# endif
+
+#elif defined( BOOST_SP_USE_PTHREADS )
+# include <boost/smart_ptr/detail/spinlock_pt.hpp>
+
+#elif defined(__GNUC__) && defined( __arm__ ) && !defined( __thumb__ )
+# include <boost/smart_ptr/detail/spinlock_gcc_arm.hpp>
+
+#elif defined( BOOST_SP_HAS_SYNC )
+# include <boost/smart_ptr/detail/spinlock_sync.hpp>
+
+#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+# include <boost/smart_ptr/detail/spinlock_w32.hpp>
+
+#elif defined(BOOST_HAS_PTHREADS)
+# include <boost/smart_ptr/detail/spinlock_pt.hpp>
+
+#elif !defined(BOOST_HAS_THREADS)
+# include <boost/smart_ptr/detail/spinlock_nt.hpp>
+
+#else
+# error Unrecognized threading platform
+#endif
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_HPP_INCLUDED
diff --git a/third_party/boost/boost/smart_ptr/detail/spinlock_pool.hpp b/third_party/boost/boost/smart_ptr/detail/spinlock_pool.hpp
new file mode 100644
index 0000000..2ddf22e
--- /dev/null
+++ b/third_party/boost/boost/smart_ptr/detail/spinlock_pool.hpp
@@ -0,0 +1,91 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_POOL_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SPINLOCK_POOL_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// boost/detail/spinlock_pool.hpp
+//
+// Copyright (c) 2008 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// spinlock_pool<0> is reserved for atomic<>, when/if it arrives
+// spinlock_pool<1> is reserved for shared_ptr reference counts
+// spinlock_pool<2> is reserved for shared_ptr atomic access
+//
+
+#include <boost/config.hpp>
+#include <boost/smart_ptr/detail/spinlock.hpp>
+#include <cstddef>
+
+namespace boost
+{
+
+namespace detail
+{
+
+template< int M > class spinlock_pool
+{
+private:
+
+ static spinlock pool_[ 41 ];
+
+public:
+
+ static spinlock & spinlock_for( void const * pv )
+ {
+#if defined(__VMS) && __INITIAL_POINTER_SIZE == 64
+ std::size_t i = reinterpret_cast< unsigned long long >( pv ) % 41;
+#else
+ std::size_t i = reinterpret_cast< std::size_t >( pv ) % 41;
+#endif
+ return pool_[ i ];
+ }
+
+ class scoped_lock
+ {
+ private:
+
+ spinlock & sp_;
+
+ scoped_lock( scoped_lock const & );
+ scoped_lock & operator=( scoped_lock const & );
+
+ public:
+
+ explicit scoped_lock( void const * pv ): sp_( spinlock_for( pv ) )
+ {
+ sp_.lock();
+ }
+
+ ~scoped_lock()
+ {
+ sp_.unlock();
+ }
+ };
+};
+
+template< int M > spinlock spinlock_pool< M >::pool_[ 41 ] =
+{
+ BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
+ BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
+ BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
+ BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
+ BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
+ BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
+ BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
+ BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
+ BOOST_DETAIL_SPINLOCK_INIT
+};
+
+} // namespace detail
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_POOL_HPP_INCLUDED
diff --git a/third_party/boost/boost/smart_ptr/detail/spinlock_sync.hpp b/third_party/boost/boost/smart_ptr/detail/spinlock_sync.hpp
new file mode 100644
index 0000000..a7145c5
--- /dev/null
+++ b/third_party/boost/boost/smart_ptr/detail/spinlock_sync.hpp
@@ -0,0 +1,87 @@
+#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// Copyright (c) 2008 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/smart_ptr/detail/yield_k.hpp>
+
+#if defined( __ia64__ ) && defined( __INTEL_COMPILER )
+# include <ia64intrin.h>
+#endif
+
+namespace boost
+{
+
+namespace detail
+{
+
+class spinlock
+{
+public:
+
+ int v_;
+
+public:
+
+ bool try_lock()
+ {
+ int r = __sync_lock_test_and_set( &v_, 1 );
+ return r == 0;
+ }
+
+ void lock()
+ {
+ for( unsigned k = 0; !try_lock(); ++k )
+ {
+ boost::detail::yield( k );
+ }
+ }
+
+ void unlock()
+ {
+ __sync_lock_release( &v_ );
+ }
+
+public:
+
+ class scoped_lock
+ {
+ private:
+
+ spinlock & sp_;
+
+ scoped_lock( scoped_lock const & );
+ scoped_lock & operator=( scoped_lock const & );
+
+ public:
+
+ explicit scoped_lock( spinlock & sp ): sp_( sp )
+ {
+ sp.lock();
+ }
+
+ ~scoped_lock()
+ {
+ sp_.unlock();
+ }
+ };
+};
+
+} // namespace detail
+} // namespace boost
+
+#define BOOST_DETAIL_SPINLOCK_INIT {0}
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED
diff --git a/third_party/boost/boost/smart_ptr/detail/yield_k.hpp b/third_party/boost/boost/smart_ptr/detail/yield_k.hpp
new file mode 100644
index 0000000..44d1836
--- /dev/null
+++ b/third_party/boost/boost/smart_ptr/detail/yield_k.hpp
@@ -0,0 +1,177 @@
+#ifndef BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED
+#define BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// yield_k.hpp
+//
+// Copyright (c) 2008 Peter Dimov
+// Copyright (c) Microsoft Corporation 2014
+//
+// void yield( unsigned k );
+//
+// Typical use:
+//
+// for( unsigned k = 0; !try_lock(); ++k ) yield( k );
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+
+#include <boost/config.hpp>
+#include <boost/predef.h>
+
+#if BOOST_PLAT_WINDOWS_RUNTIME
+#include <thread>
+#endif
+
+// BOOST_SMT_PAUSE
+
+#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) )
+
+extern "C" void _mm_pause();
+
+#define BOOST_SMT_PAUSE _mm_pause();
+
+#elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
+
+#define BOOST_SMT_PAUSE __asm__ __volatile__( "rep; nop" : : : "memory" );
+
+#endif
+
+//
+
+#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ )
+
+#if defined( BOOST_USE_WINDOWS_H )
+# include <windows.h>
+#endif
+
+namespace boost
+{
+
+namespace detail
+{
+
+#if !defined( BOOST_USE_WINDOWS_H ) && !BOOST_PLAT_WINDOWS_RUNTIME
+#if !BOOST_COMP_CLANG || !defined __MINGW32__
+ extern "C" void __stdcall Sleep( unsigned long ms );
+#else
+#include <_mingw.h>
+#if !defined __MINGW64_VERSION_MAJOR
+ extern "C" void __stdcall Sleep( unsigned long ms );
+#else
+ extern "C" __declspec(dllimport) void __stdcall Sleep( unsigned long ms );
+#endif
+#endif
+#endif
+
+inline void yield( unsigned k )
+{
+ if( k < 4 )
+ {
+ }
+#if defined( BOOST_SMT_PAUSE )
+ else if( k < 16 )
+ {
+ BOOST_SMT_PAUSE
+ }
+#endif
+#if !BOOST_PLAT_WINDOWS_RUNTIME
+ else if( k < 32 )
+ {
+ Sleep( 0 );
+ }
+ else
+ {
+ Sleep( 1 );
+ }
+#else
+ else
+ {
+ // Sleep isn't supported on the Windows Runtime.
+ std::this_thread::yield();
+ }
+#endif
+}
+
+} // namespace detail
+
+} // namespace boost
+
+#elif defined( BOOST_HAS_PTHREADS )
+
+#ifndef _AIX
+#include <sched.h>
+#else
+ // AIX's sched.h defines ::var which sometimes conflicts with Lambda's var
+ extern "C" int sched_yield(void);
+#endif
+
+#include <time.h>
+
+namespace boost
+{
+
+namespace detail
+{
+
+inline void yield( unsigned k )
+{
+ if( k < 4 )
+ {
+ }
+#if defined( BOOST_SMT_PAUSE )
+ else if( k < 16 )
+ {
+ BOOST_SMT_PAUSE
+ }
+#endif
+ else if( k < 32 || k & 1 )
+ {
+ sched_yield();
+ }
+ else
+ {
+ // g++ -Wextra warns on {} or {0}
+ struct timespec rqtp = { 0, 0 };
+
+ // POSIX says that timespec has tv_sec and tv_nsec
+ // But it doesn't guarantee order or placement
+
+ rqtp.tv_sec = 0;
+ rqtp.tv_nsec = 1000;
+
+ nanosleep( &rqtp, 0 );
+ }
+}
+
+} // namespace detail
+
+} // namespace boost
+
+#else
+
+namespace boost
+{
+
+namespace detail
+{
+
+inline void yield( unsigned )
+{
+}
+
+} // namespace detail
+
+} // namespace boost
+
+#endif
+
+#endif // #ifndef BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED
diff --git a/third_party/boost/boost/smart_ptr/enable_shared_from_this.hpp b/third_party/boost/boost/smart_ptr/enable_shared_from_this.hpp
new file mode 100644
index 0000000..4e3f243
--- /dev/null
+++ b/third_party/boost/boost/smart_ptr/enable_shared_from_this.hpp
@@ -0,0 +1,89 @@
+#ifndef BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
+#define BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
+
+//
+// enable_shared_from_this.hpp
+//
+// Copyright 2002, 2009 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html
+//
+
+#include <boost/smart_ptr/weak_ptr.hpp>
+#include <boost/smart_ptr/shared_ptr.hpp>
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+
+namespace boost
+{
+
+template<class T> class enable_shared_from_this
+{
+protected:
+
+ enable_shared_from_this() BOOST_NOEXCEPT
+ {
+ }
+
+ enable_shared_from_this(enable_shared_from_this const &) BOOST_NOEXCEPT
+ {
+ }
+
+ enable_shared_from_this & operator=(enable_shared_from_this const &) BOOST_NOEXCEPT
+ {
+ return *this;
+ }
+
+ ~enable_shared_from_this() BOOST_NOEXCEPT // ~weak_ptr<T> newer throws, so this call also must not throw
+ {
+ }
+
+public:
+
+ shared_ptr<T> shared_from_this()
+ {
+ shared_ptr<T> p( weak_this_ );
+ BOOST_ASSERT( p.get() == this );
+ return p;
+ }
+
+ shared_ptr<T const> shared_from_this() const
+ {
+ shared_ptr<T const> p( weak_this_ );
+ BOOST_ASSERT( p.get() == this );
+ return p;
+ }
+
+ weak_ptr<T> weak_from_this() BOOST_NOEXCEPT
+ {
+ return weak_this_;
+ }
+
+ weak_ptr<T const> weak_from_this() const BOOST_NOEXCEPT
+ {
+ return weak_this_;
+ }
+
+public: // actually private, but avoids compiler template friendship issues
+
+ // Note: invoked automatically by shared_ptr; do not call
+ template<class X, class Y> void _internal_accept_owner( shared_ptr<X> const * ppx, Y * py ) const
+ {
+ if( weak_this_.expired() )
+ {
+ weak_this_ = shared_ptr<T>( *ppx, py );
+ }
+ }
+
+private:
+
+ mutable weak_ptr<T> weak_this_;
+};
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
diff --git a/third_party/boost/boost/smart_ptr/scoped_ptr.hpp b/third_party/boost/boost/smart_ptr/scoped_ptr.hpp
new file mode 100644
index 0000000..d5d8720
--- /dev/null
+++ b/third_party/boost/boost/smart_ptr/scoped_ptr.hpp
@@ -0,0 +1,167 @@
+#ifndef BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED
+#define BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED
+
+// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
+// Copyright (c) 2001, 2002 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org/libs/smart_ptr/scoped_ptr.htm
+//
+
+#include <boost/config.hpp>
+#include <boost/assert.hpp>
+#include <boost/checked_delete.hpp>
+#include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
+#include <boost/smart_ptr/detail/sp_disable_deprecated.hpp>
+#include <boost/detail/workaround.hpp>
+
+#ifndef BOOST_NO_AUTO_PTR
+# include <memory> // for std::auto_ptr
+#endif
+
+#if defined( BOOST_SP_DISABLE_DEPRECATED )
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
+namespace boost
+{
+
+// Debug hooks
+
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+
+void sp_scalar_constructor_hook(void * p);
+void sp_scalar_destructor_hook(void * p);
+
+#endif
+
+// scoped_ptr mimics a built-in pointer except that it guarantees deletion
+// of the object pointed to, either on destruction of the scoped_ptr or via
+// an explicit reset(). scoped_ptr is a simple solution for simple needs;
+// use shared_ptr or std::auto_ptr if your needs are more complex.
+
+template<class T> class scoped_ptr // noncopyable
+{
+private:
+
+ T * px;
+
+ scoped_ptr(scoped_ptr const &);
+ scoped_ptr & operator=(scoped_ptr const &);
+
+ typedef scoped_ptr<T> this_type;
+
+ void operator==( scoped_ptr const& ) const;
+ void operator!=( scoped_ptr const& ) const;
+
+public:
+
+ typedef T element_type;
+
+ explicit scoped_ptr( T * p = 0 ): px( p ) // never throws
+ {
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ boost::sp_scalar_constructor_hook( px );
+#endif
+ }
+
+#ifndef BOOST_NO_AUTO_PTR
+
+ explicit scoped_ptr( std::auto_ptr<T> p ) BOOST_NOEXCEPT : px( p.release() )
+ {
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ boost::sp_scalar_constructor_hook( px );
+#endif
+ }
+
+#endif
+
+ ~scoped_ptr() // never throws
+ {
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+ boost::sp_scalar_destructor_hook( px );
+#endif
+ boost::checked_delete( px );
+ }
+
+ void reset(T * p = 0) // never throws
+ {
+ BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors
+ this_type(p).swap(*this);
+ }
+
+ T & operator*() const // never throws
+ {
+ BOOST_ASSERT( px != 0 );
+ return *px;
+ }
+
+ T * operator->() const // never throws
+ {
+ BOOST_ASSERT( px != 0 );
+ return px;
+ }
+
+ T * get() const BOOST_NOEXCEPT
+ {
+ return px;
+ }
+
+// implicit conversion to "bool"
+#include <boost/smart_ptr/detail/operator_bool.hpp>
+
+ void swap(scoped_ptr & b) BOOST_NOEXCEPT
+ {
+ T * tmp = b.px;
+ b.px = px;
+ px = tmp;
+ }
+};
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+template<class T> inline bool operator==( scoped_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
+{
+ return p.get() == 0;
+}
+
+template<class T> inline bool operator==( boost::detail::sp_nullptr_t, scoped_ptr<T> const & p ) BOOST_NOEXCEPT
+{
+ return p.get() == 0;
+}
+
+template<class T> inline bool operator!=( scoped_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
+{
+ return p.get() != 0;
+}
+
+template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, scoped_ptr<T> const & p ) BOOST_NOEXCEPT
+{
+ return p.get() != 0;
+}
+
+#endif
+
+template<class T> inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) BOOST_NOEXCEPT
+{
+ a.swap(b);
+}
+
+// get_pointer(p) is a generic way to say p.get()
+
+template<class T> inline T * get_pointer(scoped_ptr<T> const & p) BOOST_NOEXCEPT
+{
+ return p.get();
+}
+
+} // namespace boost
+
+#if defined( BOOST_SP_DISABLE_DEPRECATED )
+#pragma GCC diagnostic pop
+#endif
+
+#endif // #ifndef BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED
diff --git a/third_party/boost/boost/smart_ptr/shared_ptr.hpp b/third_party/boost/boost/smart_ptr/shared_ptr.hpp
new file mode 100644
index 0000000..e8ccb2a
--- /dev/null
+++ b/third_party/boost/boost/smart_ptr/shared_ptr.hpp
@@ -0,0 +1,1077 @@
+#ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
+#define BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
+
+//
+// shared_ptr.hpp
+//
+// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
+// Copyright (c) 2001-2008 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
+//
+
+#include <boost/config.hpp> // for broken compiler workarounds
+
+// In order to avoid circular dependencies with Boost.TR1
+// we make sure that our include of <memory> doesn't try to
+// pull in the TR1 headers: that's why we use this header
+// rather than including <memory> directly:
+#include <boost/config/no_tr1/memory.hpp> // std::auto_ptr
+
+#include <boost/assert.hpp>
+#include <boost/checked_delete.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/smart_ptr/detail/shared_count.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/smart_ptr/detail/sp_convertible.hpp>
+#include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
+#include <boost/smart_ptr/detail/sp_disable_deprecated.hpp>
+
+#if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
+#include <boost/smart_ptr/detail/spinlock_pool.hpp>
+#endif
+
+#include <algorithm> // for std::swap
+#include <functional> // for std::less
+#include <typeinfo> // for std::bad_cast
+#include <cstddef> // for std::size_t
+
+#if !defined(BOOST_NO_IOSTREAM)
+#if !defined(BOOST_NO_IOSFWD)
+#include <iosfwd> // for std::basic_ostream
+#else
+#include <ostream>
+#endif
+#endif
+
+#if defined( BOOST_SP_DISABLE_DEPRECATED )
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
+namespace boost
+{
+
+template<class T> class shared_ptr;
+template<class T> class weak_ptr;
+template<class T> class enable_shared_from_this;
+class enable_shared_from_raw;
+
+namespace movelib
+{
+
+ template< class T, class D > class unique_ptr;
+
+} // namespace movelib
+
+namespace detail
+{
+
+// sp_element, element_type
+
+template< class T > struct sp_element
+{
+ typedef T type;
+};
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template< class T > struct sp_element< T[] >
+{
+ typedef T type;
+};
+
+#if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
+
+template< class T, std::size_t N > struct sp_element< T[N] >
+{
+ typedef T type;
+};
+
+#endif
+
+#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+// sp_dereference, return type of operator*
+
+template< class T > struct sp_dereference
+{
+ typedef T & type;
+};
+
+template<> struct sp_dereference< void >
+{
+ typedef void type;
+};
+
+#if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
+
+template<> struct sp_dereference< void const >
+{
+ typedef void type;
+};
+
+template<> struct sp_dereference< void volatile >
+{
+ typedef void type;
+};
+
+template<> struct sp_dereference< void const volatile >
+{
+ typedef void type;
+};
+
+#endif // !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template< class T > struct sp_dereference< T[] >
+{
+ typedef void type;
+};
+
+#if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
+
+template< class T, std::size_t N > struct sp_dereference< T[N] >
+{
+ typedef void type;
+};
+
+#endif
+
+#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+// sp_member_access, return type of operator->
+
+template< class T > struct sp_member_access
+{
+ typedef T * type;
+};
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template< class T > struct sp_member_access< T[] >
+{
+ typedef void type;
+};
+
+#if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
+
+template< class T, std::size_t N > struct sp_member_access< T[N] >
+{
+ typedef void type;
+};
+
+#endif
+
+#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+// sp_array_access, return type of operator[]
+
+template< class T > struct sp_array_access
+{
+ typedef void type;
+};
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template< class T > struct sp_array_access< T[] >
+{
+ typedef T & type;
+};
+
+#if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
+
+template< class T, std::size_t N > struct sp_array_access< T[N] >
+{
+ typedef T & type;
+};
+
+#endif
+
+#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+// sp_extent, for operator[] index check
+
+template< class T > struct sp_extent
+{
+ enum _vt { value = 0 };
+};
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template< class T, std::size_t N > struct sp_extent< T[N] >
+{
+ enum _vt { value = N };
+};
+
+#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+// enable_shared_from_this support
+
+template< class X, class Y, class T > inline void sp_enable_shared_from_this( boost::shared_ptr<X> const * ppx, Y const * py, boost::enable_shared_from_this< T > const * pe )
+{
+ if( pe != 0 )
+ {
+ pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
+ }
+}
+
+template< class X, class Y > inline void sp_enable_shared_from_this( boost::shared_ptr<X> * ppx, Y const * py, boost::enable_shared_from_raw const * pe );
+
+#ifdef _MANAGED
+
+// Avoid C4793, ... causes native code generation
+
+struct sp_any_pointer
+{
+ template<class T> sp_any_pointer( T* ) {}
+};
+
+inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer, sp_any_pointer )
+{
+}
+
+#else // _MANAGED
+
+inline void sp_enable_shared_from_this( ... )
+{
+}
+
+#endif // _MANAGED
+
+#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR )
+
+// rvalue auto_ptr support based on a technique by Dave Abrahams
+
+template< class T, class R > struct sp_enable_if_auto_ptr
+{
+};
+
+template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R >
+{
+ typedef R type;
+};
+
+#endif
+
+// sp_assert_convertible
+
+template< class Y, class T > inline void sp_assert_convertible()
+{
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
+
+ // static_assert( sp_convertible< Y, T >::value );
+ typedef char tmp[ sp_convertible< Y, T >::value? 1: -1 ];
+ (void)sizeof( tmp );
+
+#else
+
+ T* p = static_cast< Y* >( 0 );
+ (void)p;
+
+#endif
+}
+
+// pointer constructor helper
+
+template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T > * ppx, Y * p, boost::detail::shared_count & pn )
+{
+ boost::detail::shared_count( p ).swap( pn );
+ boost::detail::sp_enable_shared_from_this( ppx, p, p );
+}
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * p, boost::detail::shared_count & pn )
+{
+ sp_assert_convertible< Y[], T[] >();
+ boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn );
+}
+
+template< class T, std::size_t N, class Y > inline void sp_pointer_construct( boost::shared_ptr< T[N] > * /*ppx*/, Y * p, boost::detail::shared_count & pn )
+{
+ sp_assert_convertible< Y[N], T[N] >();
+ boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn );
+}
+
+#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+// deleter constructor helper
+
+template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T > * ppx, Y * p )
+{
+ boost::detail::sp_enable_shared_from_this( ppx, p, p );
+}
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * /*p*/ )
+{
+ sp_assert_convertible< Y[], T[] >();
+}
+
+template< class T, std::size_t N, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[N] > * /*ppx*/, Y * /*p*/ )
+{
+ sp_assert_convertible< Y[N], T[N] >();
+}
+
+#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+} // namespace detail
+
+
+//
+// shared_ptr
+//
+// An enhanced relative of scoped_ptr with reference counted copy semantics.
+// The object pointed to is deleted when the last shared_ptr pointing to it
+// is destroyed or reset.
+//
+
+template<class T> class shared_ptr
+{
+private:
+
+ // Borland 5.5.1 specific workaround
+ typedef shared_ptr<T> this_type;
+
+public:
+
+ typedef typename boost::detail::sp_element< T >::type element_type;
+
+ shared_ptr() BOOST_NOEXCEPT : px( 0 ), pn() // never throws in 1.30+
+ {
+ }
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+ shared_ptr( boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT : px( 0 ), pn() // never throws
+ {
+ }
+
+#endif
+
+ template<class Y>
+ explicit shared_ptr( Y * p ): px( p ), pn() // Y must be complete
+ {
+ boost::detail::sp_pointer_construct( this, p, pn );
+ }
+
+ //
+ // Requirements: D's copy constructor must not throw
+ //
+ // shared_ptr will release p by calling d(p)
+ //
+
+ template<class Y, class D> shared_ptr( Y * p, D d ): px( p ), pn( p, d )
+ {
+ boost::detail::sp_deleter_construct( this, p );
+ }
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+ template<class D> shared_ptr( boost::detail::sp_nullptr_t p, D d ): px( p ), pn( p, d )
+ {
+ }
+
+#endif
+
+ // As above, but with allocator. A's copy constructor shall not throw.
+
+ template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a )
+ {
+ boost::detail::sp_deleter_construct( this, p );
+ }
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+ template<class D, class A> shared_ptr( boost::detail::sp_nullptr_t p, D d, A a ): px( p ), pn( p, d, a )
+ {
+ }
+
+#endif
+
+// generated copy constructor, destructor are fine...
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+// ... except in C++0x, move disables the implicit copy
+
+ shared_ptr( shared_ptr const & r ) BOOST_NOEXCEPT : px( r.px ), pn( r.pn )
+ {
+ }
+
+#endif
+
+ template<class Y>
+ explicit shared_ptr( weak_ptr<Y> const & r ): pn( r.pn ) // may throw
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ // it is now safe to copy r.px, as pn(r.pn) did not throw
+ px = r.px;
+ }
+
+ template<class Y>
+ shared_ptr( weak_ptr<Y> const & r, boost::detail::sp_nothrow_tag )
+ BOOST_NOEXCEPT : px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() )
+ {
+ if( !pn.empty() )
+ {
+ px = r.px;
+ }
+ }
+
+ template<class Y>
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
+
+ shared_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
+
+#else
+
+ shared_ptr( shared_ptr<Y> const & r )
+
+#endif
+ BOOST_NOEXCEPT : px( r.px ), pn( r.pn )
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+ }
+
+ // aliasing
+ template< class Y >
+ shared_ptr( shared_ptr<Y> const & r, element_type * p ) BOOST_NOEXCEPT : px( p ), pn( r.pn )
+ {
+ }
+
+#ifndef BOOST_NO_AUTO_PTR
+
+ template<class Y>
+ explicit shared_ptr( std::auto_ptr<Y> & r ): px(r.get()), pn()
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ Y * tmp = r.get();
+ pn = boost::detail::shared_count( r );
+
+ boost::detail::sp_deleter_construct( this, tmp );
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template<class Y>
+ shared_ptr( std::auto_ptr<Y> && r ): px(r.get()), pn()
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ Y * tmp = r.get();
+ pn = boost::detail::shared_count( r );
+
+ boost::detail::sp_deleter_construct( this, tmp );
+ }
+
+#elif !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+ template<class Ap>
+ explicit shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr<Ap, int>::type = 0 ): px( r.get() ), pn()
+ {
+ typedef typename Ap::element_type Y;
+
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ Y * tmp = r.get();
+ pn = boost::detail::shared_count( r );
+
+ boost::detail::sp_deleter_construct( this, tmp );
+ }
+
+#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+
+#endif // BOOST_NO_AUTO_PTR
+
+#if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template< class Y, class D >
+ shared_ptr( std::unique_ptr< Y, D > && r ): px( r.get() ), pn()
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ typename std::unique_ptr< Y, D >::pointer tmp = r.get();
+ pn = boost::detail::shared_count( r );
+
+ boost::detail::sp_deleter_construct( this, tmp );
+ }
+
+#endif
+
+ template< class Y, class D >
+ shared_ptr( boost::movelib::unique_ptr< Y, D > r ): px( r.get() ), pn()
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ typename boost::movelib::unique_ptr< Y, D >::pointer tmp = r.get();
+ pn = boost::detail::shared_count( r );
+
+ boost::detail::sp_deleter_construct( this, tmp );
+ }
+
+ // assignment
+
+ shared_ptr & operator=( shared_ptr const & r ) BOOST_NOEXCEPT
+ {
+ this_type(r).swap(*this);
+ return *this;
+ }
+
+#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400)
+
+ template<class Y>
+ shared_ptr & operator=(shared_ptr<Y> const & r) BOOST_NOEXCEPT
+ {
+ this_type(r).swap(*this);
+ return *this;
+ }
+
+#endif
+
+#ifndef BOOST_NO_AUTO_PTR
+
+ template<class Y>
+ shared_ptr & operator=( std::auto_ptr<Y> & r )
+ {
+ this_type( r ).swap( *this );
+ return *this;
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template<class Y>
+ shared_ptr & operator=( std::auto_ptr<Y> && r )
+ {
+ this_type( static_cast< std::auto_ptr<Y> && >( r ) ).swap( *this );
+ return *this;
+ }
+
+#elif !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+ template<class Ap>
+ typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r )
+ {
+ this_type( r ).swap( *this );
+ return *this;
+ }
+
+#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+
+#endif // BOOST_NO_AUTO_PTR
+
+#if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template<class Y, class D>
+ shared_ptr & operator=( std::unique_ptr<Y, D> && r )
+ {
+ this_type( static_cast< std::unique_ptr<Y, D> && >( r ) ).swap(*this);
+ return *this;
+ }
+
+#endif
+
+ template<class Y, class D>
+ shared_ptr & operator=( boost::movelib::unique_ptr<Y, D> r )
+ {
+ // this_type( static_cast< unique_ptr<Y, D> && >( r ) ).swap( *this );
+
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ typename boost::movelib::unique_ptr< Y, D >::pointer p = r.get();
+
+ shared_ptr tmp;
+
+ tmp.px = p;
+ tmp.pn = boost::detail::shared_count( r );
+
+ boost::detail::sp_deleter_construct( &tmp, p );
+
+ tmp.swap( *this );
+
+ return *this;
+ }
+
+// Move support
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ shared_ptr( shared_ptr && r ) BOOST_NOEXCEPT : px( r.px ), pn()
+ {
+ pn.swap( r.pn );
+ r.px = 0;
+ }
+
+ template<class Y>
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
+
+ shared_ptr( shared_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
+
+#else
+
+ shared_ptr( shared_ptr<Y> && r )
+
+#endif
+ BOOST_NOEXCEPT : px( r.px ), pn()
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ pn.swap( r.pn );
+ r.px = 0;
+ }
+
+ shared_ptr & operator=( shared_ptr && r ) BOOST_NOEXCEPT
+ {
+ this_type( static_cast< shared_ptr && >( r ) ).swap( *this );
+ return *this;
+ }
+
+ template<class Y>
+ shared_ptr & operator=( shared_ptr<Y> && r ) BOOST_NOEXCEPT
+ {
+ this_type( static_cast< shared_ptr<Y> && >( r ) ).swap( *this );
+ return *this;
+ }
+
+#endif
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+ shared_ptr & operator=( boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT // never throws
+ {
+ this_type().swap(*this);
+ return *this;
+ }
+
+#endif
+
+ void reset() BOOST_NOEXCEPT // never throws in 1.30+
+ {
+ this_type().swap(*this);
+ }
+
+ template<class Y> void reset( Y * p ) // Y must be complete
+ {
+ BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors
+ this_type( p ).swap( *this );
+ }
+
+ template<class Y, class D> void reset( Y * p, D d )
+ {
+ this_type( p, d ).swap( *this );
+ }
+
+ template<class Y, class D, class A> void reset( Y * p, D d, A a )
+ {
+ this_type( p, d, a ).swap( *this );
+ }
+
+ template<class Y> void reset( shared_ptr<Y> const & r, element_type * p )
+ {
+ this_type( r, p ).swap( *this );
+ }
+
+ // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
+ typename boost::detail::sp_dereference< T >::type operator* () const
+ {
+ BOOST_ASSERT( px != 0 );
+ return *px;
+ }
+
+ // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
+ typename boost::detail::sp_member_access< T >::type operator-> () const
+ {
+ BOOST_ASSERT( px != 0 );
+ return px;
+ }
+
+ // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
+ typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const
+ {
+ BOOST_ASSERT( px != 0 );
+ BOOST_ASSERT( i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 ) );
+
+ return static_cast< typename boost::detail::sp_array_access< T >::type >( px[ i ] );
+ }
+
+ element_type * get() const BOOST_NOEXCEPT
+ {
+ return px;
+ }
+
+// implicit conversion to "bool"
+#include <boost/smart_ptr/detail/operator_bool.hpp>
+
+ bool unique() const BOOST_NOEXCEPT
+ {
+ return pn.unique();
+ }
+
+ long use_count() const BOOST_NOEXCEPT
+ {
+ return pn.use_count();
+ }
+
+ void swap( shared_ptr & other ) BOOST_NOEXCEPT
+ {
+ std::swap(px, other.px);
+ pn.swap(other.pn);
+ }
+
+ template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_NOEXCEPT
+ {
+ return pn < rhs.pn;
+ }
+
+ template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_NOEXCEPT
+ {
+ return pn < rhs.pn;
+ }
+
+ void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const BOOST_NOEXCEPT
+ {
+ return pn.get_deleter( ti );
+ }
+
+ void * _internal_get_untyped_deleter() const BOOST_NOEXCEPT
+ {
+ return pn.get_untyped_deleter();
+ }
+
+ bool _internal_equiv( shared_ptr const & r ) const BOOST_NOEXCEPT
+ {
+ return px == r.px && pn == r.pn;
+ }
+
+// Tasteless as this may seem, making all members public allows member templates
+// to work in the absence of member template friends. (Matthew Langston)
+
+#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+
+private:
+
+ template<class Y> friend class shared_ptr;
+ template<class Y> friend class weak_ptr;
+
+
+#endif
+
+ element_type * px; // contained pointer
+ boost::detail::shared_count pn; // reference counter
+
+}; // shared_ptr
+
+template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT
+{
+ return a.get() == b.get();
+}
+
+template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT
+{
+ return a.get() != b.get();
+}
+
+#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
+
+// Resolve the ambiguity between our op!= and the one in rel_ops
+
+template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b) BOOST_NOEXCEPT
+{
+ return a.get() != b.get();
+}
+
+#endif
+
+#if !defined( BOOST_NO_CXX11_NULLPTR )
+
+template<class T> inline bool operator==( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
+{
+ return p.get() == 0;
+}
+
+template<class T> inline bool operator==( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_NOEXCEPT
+{
+ return p.get() == 0;
+}
+
+template<class T> inline bool operator!=( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
+{
+ return p.get() != 0;
+}
+
+template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_NOEXCEPT
+{
+ return p.get() != 0;
+}
+
+#endif
+
+template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT
+{
+ return a.owner_before( b );
+}
+
+template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) BOOST_NOEXCEPT
+{
+ a.swap(b);
+}
+
+template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
+{
+ (void) static_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename shared_ptr<T>::element_type E;
+
+ E * p = static_cast< E* >( r.get() );
+ return shared_ptr<T>( r, p );
+}
+
+template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
+{
+ (void) const_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename shared_ptr<T>::element_type E;
+
+ E * p = const_cast< E* >( r.get() );
+ return shared_ptr<T>( r, p );
+}
+
+template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
+{
+ (void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename shared_ptr<T>::element_type E;
+
+ E * p = dynamic_cast< E* >( r.get() );
+ return p? shared_ptr<T>( r, p ): shared_ptr<T>();
+}
+
+template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
+{
+ (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
+
+ typedef typename shared_ptr<T>::element_type E;
+
+ E * p = reinterpret_cast< E* >( r.get() );
+ return shared_ptr<T>( r, p );
+}
+
+// get_pointer() enables boost::mem_fn to recognize shared_ptr
+
+template<class T> inline typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p) BOOST_NOEXCEPT
+{
+ return p.get();
+}
+
+// operator<<
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) )
+
+template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
+{
+ os << p.get();
+ return os;
+}
+
+#else
+
+// in STLport's no-iostreams mode no iostream symbols can be used
+#ifndef _STLP_NO_IOSTREAMS
+
+# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)
+// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
+using std::basic_ostream;
+template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
+# else
+template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
+# endif
+{
+ os << p.get();
+ return os;
+}
+
+#endif // _STLP_NO_IOSTREAMS
+
+#endif // __GNUC__ < 3
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+// get_deleter
+
+namespace detail
+{
+
+#if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \
+ ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \
+ ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) )
+
+// g++ 2.9x doesn't allow static_cast<X const *>(void *)
+// apparently EDG 2.38 and HP aCC A.03.35 also don't accept it
+
+template<class D, class T> D * basic_get_deleter(shared_ptr<T> const & p)
+{
+ void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D));
+ return const_cast<D *>(static_cast<D const *>(q));
+}
+
+#else
+
+template<class D, class T> D * basic_get_deleter( shared_ptr<T> const & p ) BOOST_NOEXCEPT
+{
+ return static_cast<D *>( p._internal_get_deleter(BOOST_SP_TYPEID(D)) );
+}
+
+#endif
+
+class esft2_deleter_wrapper
+{
+private:
+
+ shared_ptr<void const volatile> deleter_;
+
+public:
+
+ esft2_deleter_wrapper()
+ {
+ }
+
+ template< class T > void set_deleter( shared_ptr<T> const & deleter )
+ {
+ deleter_ = deleter;
+ }
+
+ template<typename D> D* get_deleter() const BOOST_NOEXCEPT
+ {
+ return boost::detail::basic_get_deleter<D>( deleter_ );
+ }
+
+ template< class T> void operator()( T* )
+ {
+ BOOST_ASSERT( deleter_.use_count() <= 1 );
+ deleter_.reset();
+ }
+};
+
+} // namespace detail
+
+template<class D, class T> D * get_deleter( shared_ptr<T> const & p ) BOOST_NOEXCEPT
+{
+ D *del = boost::detail::basic_get_deleter<D>(p);
+
+ if(del == 0)
+ {
+ boost::detail::esft2_deleter_wrapper *del_wrapper = boost::detail::basic_get_deleter<boost::detail::esft2_deleter_wrapper>(p);
+// The following get_deleter method call is fully qualified because
+// older versions of gcc (2.95, 3.2.3) fail to compile it when written del_wrapper->get_deleter<D>()
+ if(del_wrapper) del = del_wrapper->::boost::detail::esft2_deleter_wrapper::get_deleter<D>();
+ }
+
+ return del;
+}
+
+// atomic access
+
+#if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
+
+template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ ) BOOST_NOEXCEPT
+{
+ return false;
+}
+
+template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p )
+{
+ boost::detail::spinlock_pool<2>::scoped_lock lock( p );
+ return *p;
+}
+
+template<class T> inline shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, /*memory_order mo*/ int )
+{
+ return atomic_load( p );
+}
+
+template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r )
+{
+ boost::detail::spinlock_pool<2>::scoped_lock lock( p );
+ p->swap( r );
+}
+
+template<class T> inline void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ int )
+{
+ atomic_store( p, r ); // std::move( r )
+}
+
+template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r )
+{
+ boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
+
+ sp.lock();
+ p->swap( r );
+ sp.unlock();
+
+ return r; // return std::move( r )
+}
+
+template<class T> shared_ptr<T> atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ int )
+{
+ return atomic_exchange( p, r ); // std::move( r )
+}
+
+template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w )
+{
+ boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
+
+ sp.lock();
+
+ if( p->_internal_equiv( *v ) )
+ {
+ p->swap( w );
+
+ sp.unlock();
+
+ return true;
+ }
+ else
+ {
+ shared_ptr<T> tmp( *p );
+
+ sp.unlock();
+
+ tmp.swap( *v );
+ return false;
+ }
+}
+
+template<class T> inline bool atomic_compare_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, /*memory_order success*/ int, /*memory_order failure*/ int )
+{
+ return atomic_compare_exchange( p, v, w ); // std::move( w )
+}
+
+#endif // !defined(BOOST_SP_NO_ATOMIC_ACCESS)
+
+// hash_value
+
+template< class T > struct hash;
+
+template< class T > std::size_t hash_value( boost::shared_ptr<T> const & p ) BOOST_NOEXCEPT
+{
+ return boost::hash< T* >()( p.get() );
+}
+
+} // namespace boost
+
+#if defined( BOOST_SP_DISABLE_DEPRECATED )
+#pragma GCC diagnostic pop
+#endif
+
+#endif // #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
diff --git a/third_party/boost/boost/smart_ptr/weak_ptr.hpp b/third_party/boost/boost/smart_ptr/weak_ptr.hpp
new file mode 100644
index 0000000..e3e9ad9
--- /dev/null
+++ b/third_party/boost/boost/smart_ptr/weak_ptr.hpp
@@ -0,0 +1,253 @@
+#ifndef BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED
+#define BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED
+
+//
+// weak_ptr.hpp
+//
+// Copyright (c) 2001, 2002, 2003 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/smart_ptr/weak_ptr.htm for documentation.
+//
+
+#include <memory> // boost.TR1 include order fix
+#include <boost/smart_ptr/detail/shared_count.hpp>
+#include <boost/smart_ptr/shared_ptr.hpp>
+
+namespace boost
+{
+
+template<class T> class weak_ptr
+{
+private:
+
+ // Borland 5.5.1 specific workarounds
+ typedef weak_ptr<T> this_type;
+
+public:
+
+ typedef typename boost::detail::sp_element< T >::type element_type;
+
+ weak_ptr() BOOST_NOEXCEPT : px(0), pn() // never throws in 1.30+
+ {
+ }
+
+// generated copy constructor, assignment, destructor are fine...
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+// ... except in C++0x, move disables the implicit copy
+
+ weak_ptr( weak_ptr const & r ) BOOST_NOEXCEPT : px( r.px ), pn( r.pn )
+ {
+ }
+
+ weak_ptr & operator=( weak_ptr const & r ) BOOST_NOEXCEPT
+ {
+ px = r.px;
+ pn = r.pn;
+ return *this;
+ }
+
+#endif
+
+//
+// The "obvious" converting constructor implementation:
+//
+// template<class Y>
+// weak_ptr(weak_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
+// {
+// }
+//
+// has a serious problem.
+//
+// r.px may already have been invalidated. The px(r.px)
+// conversion may require access to *r.px (virtual inheritance).
+//
+// It is not possible to avoid spurious access violations since
+// in multithreaded programs r.px may be invalidated at any point.
+//
+
+ template<class Y>
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
+
+ weak_ptr( weak_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
+
+#else
+
+ weak_ptr( weak_ptr<Y> const & r )
+
+#endif
+ BOOST_NOEXCEPT : px(r.lock().get()), pn(r.pn)
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template<class Y>
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
+
+ weak_ptr( weak_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
+
+#else
+
+ weak_ptr( weak_ptr<Y> && r )
+
+#endif
+ BOOST_NOEXCEPT : px( r.lock().get() ), pn( static_cast< boost::detail::weak_count && >( r.pn ) )
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+ r.px = 0;
+ }
+
+ // for better efficiency in the T == Y case
+ weak_ptr( weak_ptr && r )
+ BOOST_NOEXCEPT : px( r.px ), pn( static_cast< boost::detail::weak_count && >( r.pn ) )
+ {
+ r.px = 0;
+ }
+
+ // for better efficiency in the T == Y case
+ weak_ptr & operator=( weak_ptr && r ) BOOST_NOEXCEPT
+ {
+ this_type( static_cast< weak_ptr && >( r ) ).swap( *this );
+ return *this;
+ }
+
+
+#endif
+
+ template<class Y>
+#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
+
+ weak_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
+
+#else
+
+ weak_ptr( shared_ptr<Y> const & r )
+
+#endif
+ BOOST_NOEXCEPT : px( r.px ), pn( r.pn )
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+ }
+
+#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300)
+
+ template<class Y>
+ weak_ptr & operator=( weak_ptr<Y> const & r ) BOOST_NOEXCEPT
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ px = r.lock().get();
+ pn = r.pn;
+
+ return *this;
+ }
+
+#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
+
+ template<class Y>
+ weak_ptr & operator=( weak_ptr<Y> && r ) BOOST_NOEXCEPT
+ {
+ this_type( static_cast< weak_ptr<Y> && >( r ) ).swap( *this );
+ return *this;
+ }
+
+#endif
+
+ template<class Y>
+ weak_ptr & operator=( shared_ptr<Y> const & r ) BOOST_NOEXCEPT
+ {
+ boost::detail::sp_assert_convertible< Y, T >();
+
+ px = r.px;
+ pn = r.pn;
+
+ return *this;
+ }
+
+#endif
+
+ shared_ptr<T> lock() const BOOST_NOEXCEPT
+ {
+ return shared_ptr<T>( *this, boost::detail::sp_nothrow_tag() );
+ }
+
+ long use_count() const BOOST_NOEXCEPT
+ {
+ return pn.use_count();
+ }
+
+ bool expired() const BOOST_NOEXCEPT
+ {
+ return pn.use_count() == 0;
+ }
+
+ bool _empty() const // extension, not in std::weak_ptr
+ {
+ return pn.empty();
+ }
+
+ void reset() BOOST_NOEXCEPT // never throws in 1.30+
+ {
+ this_type().swap(*this);
+ }
+
+ void swap(this_type & other) BOOST_NOEXCEPT
+ {
+ std::swap(px, other.px);
+ pn.swap(other.pn);
+ }
+
+ template<typename Y>
+ void _internal_aliasing_assign(weak_ptr<Y> const & r, element_type * px2)
+ {
+ px = px2;
+ pn = r.pn;
+ }
+
+ template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_NOEXCEPT
+ {
+ return pn < rhs.pn;
+ }
+
+ template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_NOEXCEPT
+ {
+ return pn < rhs.pn;
+ }
+
+// Tasteless as this may seem, making all members public allows member templates
+// to work in the absence of member template friends. (Matthew Langston)
+
+#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+
+private:
+
+ template<class Y> friend class weak_ptr;
+ template<class Y> friend class shared_ptr;
+
+#endif
+
+ element_type * px; // contained pointer
+ boost::detail::weak_count pn; // reference counter
+
+}; // weak_ptr
+
+template<class T, class U> inline bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) BOOST_NOEXCEPT
+{
+ return a.owner_before( b );
+}
+
+template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) BOOST_NOEXCEPT
+{
+ a.swap(b);
+}
+
+} // namespace boost
+
+#endif // #ifndef BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED
diff --git a/third_party/boost/boost/static_assert.hpp b/third_party/boost/boost/static_assert.hpp
new file mode 100644
index 0000000..3170923
--- /dev/null
+++ b/third_party/boost/boost/static_assert.hpp
@@ -0,0 +1,178 @@
+// (C) Copyright John Maddock 2000.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/static_assert for documentation.
+
+/*
+ Revision history:
+ 02 August 2000
+ Initial version.
+*/
+
+#ifndef BOOST_STATIC_ASSERT_HPP
+#define BOOST_STATIC_ASSERT_HPP
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+
+#if defined(__GNUC__) && !defined(__GXX_EXPERIMENTAL_CXX0X__)
+//
+// This is horrible, but it seems to be the only we can shut up the
+// "anonymous variadic macros were introduced in C99 [-Wvariadic-macros]"
+// warning that get spewed out otherwise in non-C++11 mode.
+//
+#pragma GCC system_header
+#endif
+
+#ifndef BOOST_NO_CXX11_STATIC_ASSERT
+# ifndef BOOST_NO_CXX11_VARIADIC_MACROS
+# define BOOST_STATIC_ASSERT_MSG( ... ) static_assert(__VA_ARGS__)
+# else
+# define BOOST_STATIC_ASSERT_MSG( B, Msg ) static_assert( B, Msg )
+# endif
+#else
+# define BOOST_STATIC_ASSERT_MSG( B, Msg ) BOOST_STATIC_ASSERT( B )
+#endif
+
+#ifdef __BORLANDC__
+//
+// workaround for buggy integral-constant expression support:
+#define BOOST_BUGGY_INTEGRAL_CONSTANT_EXPRESSIONS
+#endif
+
+#if defined(__GNUC__) && (__GNUC__ == 3) && ((__GNUC_MINOR__ == 3) || (__GNUC_MINOR__ == 4))
+// gcc 3.3 and 3.4 don't produce good error messages with the default version:
+# define BOOST_SA_GCC_WORKAROUND
+#endif
+
+//
+// If the compiler issues warnings about old C style casts,
+// then enable this:
+//
+#if defined(__GNUC__) && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4)))
+# ifndef BOOST_NO_CXX11_VARIADIC_MACROS
+# define BOOST_STATIC_ASSERT_BOOL_CAST( ... ) ((__VA_ARGS__) == 0 ? false : true)
+# else
+# define BOOST_STATIC_ASSERT_BOOL_CAST( x ) ((x) == 0 ? false : true)
+# endif
+#else
+# ifndef BOOST_NO_CXX11_VARIADIC_MACROS
+# define BOOST_STATIC_ASSERT_BOOL_CAST( ... ) (bool)(__VA_ARGS__)
+# else
+# define BOOST_STATIC_ASSERT_BOOL_CAST(x) (bool)(x)
+# endif
+#endif
+
+#ifndef BOOST_NO_CXX11_STATIC_ASSERT
+# ifndef BOOST_NO_CXX11_VARIADIC_MACROS
+# define BOOST_STATIC_ASSERT( ... ) static_assert(__VA_ARGS__, #__VA_ARGS__)
+# else
+# define BOOST_STATIC_ASSERT( B ) static_assert(B, #B)
+# endif
+#else
+
+namespace boost{
+
+// HP aCC cannot deal with missing names for template value parameters
+template <bool x> struct STATIC_ASSERTION_FAILURE;
+
+template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
+
+// HP aCC cannot deal with missing names for template value parameters
+template<int x> struct static_assert_test{};
+
+}
+
+//
+// Implicit instantiation requires that all member declarations be
+// instantiated, but that the definitions are *not* instantiated.
+//
+// It's not particularly clear how this applies to enum's or typedefs;
+// both are described as declarations [7.1.3] and [7.2] in the standard,
+// however some compilers use "delayed evaluation" of one or more of
+// these when implicitly instantiating templates. We use typedef declarations
+// by default, but try defining BOOST_USE_ENUM_STATIC_ASSERT if the enum
+// version gets better results from your compiler...
+//
+// Implementation:
+// Both of these versions rely on sizeof(incomplete_type) generating an error
+// message containing the name of the incomplete type. We use
+// "STATIC_ASSERTION_FAILURE" as the type name here to generate
+// an eye catching error message. The result of the sizeof expression is either
+// used as an enum initialiser, or as a template argument depending which version
+// is in use...
+// Note that the argument to the assert is explicitly cast to bool using old-
+// style casts: too many compilers currently have problems with static_cast
+// when used inside integral constant expressions.
+//
+#if !defined(BOOST_BUGGY_INTEGRAL_CONSTANT_EXPRESSIONS)
+
+#if defined(BOOST_MSVC) && defined(BOOST_NO_CXX11_VARIADIC_MACROS)
+#define BOOST_STATIC_ASSERT( B ) \
+ typedef ::boost::static_assert_test<\
+ sizeof(::boost::STATIC_ASSERTION_FAILURE< BOOST_STATIC_ASSERT_BOOL_CAST ( B ) >)>\
+ BOOST_JOIN(boost_static_assert_typedef_, __COUNTER__)
+#elif defined(BOOST_MSVC)
+#define BOOST_STATIC_ASSERT(...) \
+ typedef ::boost::static_assert_test<\
+ sizeof(::boost::STATIC_ASSERTION_FAILURE< BOOST_STATIC_ASSERT_BOOL_CAST (__VA_ARGS__) >)>\
+ BOOST_JOIN(boost_static_assert_typedef_, __COUNTER__)
+#elif (defined(BOOST_INTEL_CXX_VERSION) || defined(BOOST_SA_GCC_WORKAROUND)) && defined(BOOST_NO_CXX11_VARIADIC_MACROS)
+// agurt 15/sep/02: a special care is needed to force Intel C++ issue an error
+// instead of warning in case of failure
+# define BOOST_STATIC_ASSERT( B ) \
+ typedef char BOOST_JOIN(boost_static_assert_typedef_, __LINE__) \
+ [ ::boost::STATIC_ASSERTION_FAILURE< BOOST_STATIC_ASSERT_BOOL_CAST( B ) >::value ]
+#elif (defined(BOOST_INTEL_CXX_VERSION) || defined(BOOST_SA_GCC_WORKAROUND)) && !defined(BOOST_NO_CXX11_VARIADIC_MACROS)
+// agurt 15/sep/02: a special care is needed to force Intel C++ issue an error
+// instead of warning in case of failure
+# define BOOST_STATIC_ASSERT(...) \
+ typedef char BOOST_JOIN(boost_static_assert_typedef_, __LINE__) \
+ [ ::boost::STATIC_ASSERTION_FAILURE< BOOST_STATIC_ASSERT_BOOL_CAST( __VA_ARGS__ ) >::value ]
+#elif defined(__sgi)
+// special version for SGI MIPSpro compiler
+#define BOOST_STATIC_ASSERT( B ) \
+ BOOST_STATIC_CONSTANT(bool, \
+ BOOST_JOIN(boost_static_assert_test_, __LINE__) = ( B )); \
+ typedef ::boost::static_assert_test<\
+ sizeof(::boost::STATIC_ASSERTION_FAILURE< \
+ BOOST_JOIN(boost_static_assert_test_, __LINE__) >)>\
+ BOOST_JOIN(boost_static_assert_typedef_, __LINE__)
+#elif BOOST_WORKAROUND(__MWERKS__, <= 0x3003)
+// special version for CodeWarrior <= 8.x
+#define BOOST_STATIC_ASSERT( B ) \
+ BOOST_STATIC_CONSTANT(int, \
+ BOOST_JOIN(boost_static_assert_test_, __LINE__) = \
+ sizeof(::boost::STATIC_ASSERTION_FAILURE< BOOST_STATIC_ASSERT_BOOL_CAST( B ) >) )
+#else
+// generic version
+# ifndef BOOST_NO_CXX11_VARIADIC_MACROS
+# define BOOST_STATIC_ASSERT( ... ) \
+ typedef ::boost::static_assert_test<\
+ sizeof(::boost::STATIC_ASSERTION_FAILURE< BOOST_STATIC_ASSERT_BOOL_CAST( __VA_ARGS__ ) >)>\
+ BOOST_JOIN(boost_static_assert_typedef_, __LINE__) BOOST_ATTRIBUTE_UNUSED
+# else
+# define BOOST_STATIC_ASSERT( B ) \
+ typedef ::boost::static_assert_test<\
+ sizeof(::boost::STATIC_ASSERTION_FAILURE< BOOST_STATIC_ASSERT_BOOL_CAST( B ) >)>\
+ BOOST_JOIN(boost_static_assert_typedef_, __LINE__) BOOST_ATTRIBUTE_UNUSED
+# endif
+#endif
+
+#else
+// alternative enum based implementation:
+# ifndef BOOST_NO_CXX11_VARIADIC_MACROS
+# define BOOST_STATIC_ASSERT( ... ) \
+ enum { BOOST_JOIN(boost_static_assert_enum_, __LINE__) \
+ = sizeof(::boost::STATIC_ASSERTION_FAILURE< (bool)( __VA_ARGS__ ) >) }
+# else
+# define BOOST_STATIC_ASSERT(B) \
+ enum { BOOST_JOIN(boost_static_assert_enum_, __LINE__) \
+ = sizeof(::boost::STATIC_ASSERTION_FAILURE< (bool)( B ) >) }
+# endif
+#endif
+#endif // defined(BOOST_NO_CXX11_STATIC_ASSERT)
+
+#endif // BOOST_STATIC_ASSERT_HPP
diff --git a/third_party/boost/boost/swap.hpp b/third_party/boost/boost/swap.hpp
new file mode 100644
index 0000000..55cafa4
--- /dev/null
+++ b/third_party/boost/boost/swap.hpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2014 Glen Fernandes
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_SWAP_HPP
+#define BOOST_SWAP_HPP
+
+// The header file at this path is deprecated;
+// use boost/core/swap.hpp instead.
+
+#include <boost/core/swap.hpp>
+
+#endif
diff --git a/third_party/boost/boost/throw_exception.hpp b/third_party/boost/boost/throw_exception.hpp
new file mode 100644
index 0000000..aa977df
--- /dev/null
+++ b/third_party/boost/boost/throw_exception.hpp
@@ -0,0 +1,102 @@
+#ifndef UUID_AA15E74A856F11E08B8D93F24824019B
+#define UUID_AA15E74A856F11E08B8D93F24824019B
+#if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
+#pragma GCC system_header
+#endif
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
+#pragma warning(push,1)
+#endif
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+// boost/throw_exception.hpp
+//
+// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
+// Copyright (c) 2008-2009 Emil Dotchevski and Reverge Studios, Inc.
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org/libs/utility/throw_exception.html
+//
+
+#include <boost/detail/workaround.hpp>
+#include <boost/config.hpp>
+#include <exception>
+
+#if !defined( BOOST_EXCEPTION_DISABLE ) && defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x593) )
+# define BOOST_EXCEPTION_DISABLE
+#endif
+
+#if !defined( BOOST_EXCEPTION_DISABLE ) && defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1310 )
+# define BOOST_EXCEPTION_DISABLE
+#endif
+
+#if !defined( BOOST_EXCEPTION_DISABLE )
+# include <boost/exception/exception.hpp>
+#if !defined(BOOST_THROW_EXCEPTION_CURRENT_FUNCTION)
+# include <boost/current_function.hpp>
+# define BOOST_THROW_EXCEPTION_CURRENT_FUNCTION BOOST_CURRENT_FUNCTION
+#endif
+# define BOOST_THROW_EXCEPTION(x) ::boost::exception_detail::throw_exception_(x,BOOST_THROW_EXCEPTION_CURRENT_FUNCTION,__FILE__,__LINE__)
+#else
+# define BOOST_THROW_EXCEPTION(x) ::boost::throw_exception(x)
+#endif
+
+namespace boost
+{
+#ifdef BOOST_NO_EXCEPTIONS
+
+void throw_exception( std::exception const & e ); // user defined
+
+#else
+
+inline void throw_exception_assert_compatibility( std::exception const & ) { }
+
+template<class E> BOOST_NORETURN inline void throw_exception( E const & e )
+{
+ //All boost exceptions are required to derive from std::exception,
+ //to ensure compatibility with BOOST_NO_EXCEPTIONS.
+ throw_exception_assert_compatibility(e);
+
+#ifndef BOOST_EXCEPTION_DISABLE
+ throw enable_current_exception(enable_error_info(e));
+#else
+ throw e;
+#endif
+}
+
+#endif
+
+#if !defined( BOOST_EXCEPTION_DISABLE )
+ namespace
+ exception_detail
+ {
+ template <class E>
+ BOOST_NORETURN
+ void
+ throw_exception_( E const & x, char const * current_function, char const * file, int line )
+ {
+ boost::throw_exception(
+ set_info(
+ set_info(
+ set_info(
+ enable_error_info(x),
+ throw_function(current_function)),
+ throw_file(file)),
+ throw_line(line)));
+ }
+ }
+#endif
+} // namespace boost
+
+#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
+#pragma warning(pop)
+#endif
+#endif
diff --git a/third_party/boost/boost/type.hpp b/third_party/boost/boost/type.hpp
new file mode 100644
index 0000000..ab81c91
--- /dev/null
+++ b/third_party/boost/boost/type.hpp
@@ -0,0 +1,18 @@
+// (C) Copyright David Abrahams 2001.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TYPE_DWA20010120_HPP
+# define BOOST_TYPE_DWA20010120_HPP
+
+namespace boost {
+
+ // Just a simple "type envelope". Useful in various contexts, mostly to work
+ // around some MSVC deficiencies.
+ template <class T>
+ struct type {};
+
+}
+
+#endif // BOOST_TYPE_DWA20010120_HPP
diff --git a/third_party/boost/boost/type_index.hpp b/third_party/boost/boost/type_index.hpp
new file mode 100644
index 0000000..7a9b146
--- /dev/null
+++ b/third_party/boost/boost/type_index.hpp
@@ -0,0 +1,264 @@
+//
+// Copyright (c) Antony Polukhin, 2012-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)
+//
+
+#ifndef BOOST_TYPE_INDEX_HPP
+#define BOOST_TYPE_INDEX_HPP
+
+/// \file boost/type_index.hpp
+/// \brief Includes minimal set of headers required to use the Boost.TypeIndex library.
+///
+/// By inclusion of this file most optimal type index classes will be included and used
+/// as a boost::typeindex::type_index and boost::typeindex::type_info.
+
+#include <boost/config.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+#if defined(BOOST_TYPE_INDEX_USER_TYPEINDEX)
+# include BOOST_TYPE_INDEX_USER_TYPEINDEX
+# ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH
+# pragma detect_mismatch( "boost__type_index__abi", "user defined type_index class is used: " BOOST_STRINGIZE(BOOST_TYPE_INDEX_USER_TYPEINDEX))
+# endif
+#elif (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC)
+# include <boost/type_index/stl_type_index.hpp>
+# if defined(BOOST_NO_RTTI) || defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)
+# include <boost/type_index/detail/stl_register_class.hpp>
+# ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH
+# pragma detect_mismatch( "boost__type_index__abi", "RTTI is off - typeid() is used only for templates")
+# endif
+# else
+# ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH
+# pragma detect_mismatch( "boost__type_index__abi", "RTTI is used")
+# endif
+# endif
+#else
+# include <boost/type_index/ctti_type_index.hpp>
+# include <boost/type_index/detail/ctti_register_class.hpp>
+# ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH
+# pragma detect_mismatch( "boost__type_index__abi", "RTTI is off - using CTTI")
+# endif
+#endif
+
+#ifndef BOOST_TYPE_INDEX_REGISTER_CLASS
+#define BOOST_TYPE_INDEX_REGISTER_CLASS
+#endif
+
+namespace boost { namespace typeindex {
+
+#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
+
+/// \def BOOST_TYPE_INDEX_FUNCTION_SIGNATURE
+/// BOOST_TYPE_INDEX_FUNCTION_SIGNATURE is used by boost::typeindex::ctti_type_index class to
+/// deduce the name of a type. If your compiler is not recognized
+/// by the TypeIndex library and you wish to work with boost::typeindex::ctti_type_index, you may
+/// define this macro by yourself.
+///
+/// BOOST_TYPE_INDEX_FUNCTION_SIGNATURE must be defined to a compiler specific macro
+/// that outputs the \b whole function signature \b including \b template \b parameters.
+///
+/// If your compiler is not recognised and BOOST_TYPE_INDEX_FUNCTION_SIGNATURE is not defined,
+/// then a compile-time error will arise at any attempt to use boost::typeindex::ctti_type_index classes.
+///
+/// See BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS and BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING
+/// for an information of how to tune the implementation to make a nice pretty_name() output.
+#define BOOST_TYPE_INDEX_FUNCTION_SIGNATURE BOOST_CURRENT_FUNCTION
+
+/// \def BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING
+/// This is a helper macro for making correct pretty_names() with RTTI off.
+///
+/// BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING macro may be defined to
+/// '(begin_skip, end_skip, runtime_skip, runtime_skip_until)' with parameters for adding a
+/// support for compilers, that by default are not recognized by TypeIndex library.
+///
+/// \b Example:
+///
+/// Imagine the situation when
+/// \code boost::typeindex::ctti_type_index::type_id<int>().pretty_name() \endcode
+/// returns the following string:
+/// \code "static const char *boost::detail::ctti<int>::n() [T = int]" \endcode
+/// and \code boost::typeindex::ctti_type_index::type_id<short>().pretty_name() \endcode returns the following:
+/// \code "static const char *boost::detail::ctti<short>::n() [T = short]" \endcode
+///
+/// As we may see first 39 characters are "static const char *boost::detail::ctti<" and they do not depend on
+/// the type T. After first 39 characters we have a human readable type name which is duplicated at the end
+/// of a string. String always ends on ']', which consumes 1 character.
+///
+/// Now if we define `BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING` to
+/// `(39, 1, false, "")` we'll be getting \code "int>::n() [T = int" \endcode
+/// for `boost::typeindex::ctti_type_index::type_id<int>().pretty_name()` and \code "short>::n() [T = short" \endcode
+/// for `boost::typeindex::ctti_type_index::type_id<short>().pretty_name()`.
+///
+/// Now we need to take additional care of the characters that go before the last mention of our type. We'll
+/// do that by telling the macro that we need to cut off everything that goes before the "T = " including the "T = "
+/// itself:
+///
+/// \code (39, 1, true, "T = ") \endcode
+///
+/// In case of GCC or Clang command line we need to add the following line while compiling all the sources:
+///
+/// \code
+/// -DBOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING='(39, 1, true, "T = ")'
+/// \endcode
+/// \param begin_skip How many characters must be skipped at the beginning of the type holding string.
+/// Must be a compile time constant.
+/// \param end_skip How many characters must be skipped at the end of the type holding string.
+/// Must be a compile time constant.
+/// \param runtime_skip Do we need additional checks at runtime to cut off the more characters.
+/// Must be `true` or `false`.
+/// \param runtime_skip_until Skip all the characters before the following string (including the string itself).
+/// Must be a compile time array of characters.
+///
+/// See [RTTI emulation limitations](boost_typeindex/rtti_emulation_limitations.html) for more info.
+#define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING (0, 0, false, "")
+
+
+ /// Depending on a compiler flags, optimal implementation of type_index will be used
+ /// as a default boost::typeindex::type_index.
+ ///
+ /// Could be a boost::typeindex::stl_type_index, boost::typeindex::ctti_type_index or
+ /// user defined type_index class.
+ ///
+ /// \b See boost::typeindex::type_index_facade for a full description of type_index functions.
+ typedef platform_specific type_index;
+#elif defined(BOOST_TYPE_INDEX_USER_TYPEINDEX)
+ // Nothing to do
+#elif (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC)
+ typedef boost::typeindex::stl_type_index type_index;
+#else
+ typedef boost::typeindex::ctti_type_index type_index;
+#endif
+
+/// Depending on a compiler flags, optimal implementation of type_info will be used
+/// as a default boost::typeindex::type_info.
+///
+/// Could be a std::type_info, boost::typeindex::detail::ctti_data or
+/// some user defined class.
+///
+/// type_info \b is \b not copyable or default constructible. It is \b not assignable too!
+typedef type_index::type_info_t type_info;
+
+#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
+
+/// \def BOOST_TYPE_INDEX_USER_TYPEINDEX
+/// BOOST_TYPE_INDEX_USER_TYPEINDEX can be defined to the path to header file
+/// with user provided implementation of type_index.
+///
+/// See [Making a custom type_index](boost_typeindex/making_a_custom_type_index.html) section
+/// of documentation for usage example.
+#define BOOST_TYPE_INDEX_USER_TYPEINDEX <full/absolute/path/to/header/with/type_index.hpp>
+
+
+/// \def BOOST_TYPE_INDEX_REGISTER_CLASS
+/// BOOST_TYPE_INDEX_REGISTER_CLASS is used to help to emulate RTTI.
+/// Put this macro into the public section of polymorphic class to allow runtime type detection.
+///
+/// Depending on the typeid() availability this macro will expand to nothing or to virtual helper function
+/// `virtual const type_info& boost_type_info_type_id_runtime_() const noexcept`.
+///
+/// \b Example:
+/// \code
+/// class A {
+/// public:
+/// BOOST_TYPE_INDEX_REGISTER_CLASS
+/// virtual ~A(){}
+/// };
+///
+/// struct B: public A {
+/// BOOST_TYPE_INDEX_REGISTER_CLASS
+/// };
+///
+/// struct C: public B {
+/// BOOST_TYPE_INDEX_REGISTER_CLASS
+/// };
+///
+/// ...
+///
+/// C c1;
+/// A* pc1 = &c1;
+/// assert(boost::typeindex::type_id<C>() == boost::typeindex::type_id_runtime(*pc1));
+/// \endcode
+#define BOOST_TYPE_INDEX_REGISTER_CLASS nothing-or-some-virtual-functions
+
+/// \def BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY
+/// BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY is a helper macro that must be defined if mixing
+/// RTTI on/off modules. See
+/// [Mixing sources with RTTI on and RTTI off](boost_typeindex/mixing_sources_with_rtti_on_and_.html)
+/// section of documentation for more info.
+#define BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY
+
+#endif // defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
+
+
+/// Function to get boost::typeindex::type_index for a type T.
+/// Removes const, volatile && and & modifiers from T.
+///
+/// \b Example:
+/// \code
+/// type_index ti = type_id<int&>();
+/// std::cout << ti.pretty_name(); // Outputs 'int'
+/// \endcode
+///
+/// \tparam T Type for which type_index must be created.
+/// \throw Nothing.
+/// \return boost::typeindex::type_index with information about the specified type T.
+template <class T>
+inline type_index type_id() BOOST_NOEXCEPT {
+ return type_index::type_id<T>();
+}
+
+/// Function for constructing boost::typeindex::type_index instance for type T.
+/// Does not remove const, volatile, & and && modifiers from T.
+///
+/// If T has no const, volatile, & and && modifiers, then returns exactly
+/// the same result as in case of calling `type_id<T>()`.
+///
+/// \b Example:
+/// \code
+/// type_index ti = type_id_with_cvr<int&>();
+/// std::cout << ti.pretty_name(); // Outputs 'int&'
+/// \endcode
+///
+/// \tparam T Type for which type_index must be created.
+/// \throw Nothing.
+/// \return boost::typeindex::type_index with information about the specified type T.
+template <class T>
+inline type_index type_id_with_cvr() BOOST_NOEXCEPT {
+ return type_index::type_id_with_cvr<T>();
+}
+
+/// Function that works exactly like C++ typeid(rtti_val) call, but returns boost::type_index.
+///
+/// Retunrs runtime information about specified type.
+///
+/// \b Requirements: RTTI available or Base and Derived classes must be marked with BOOST_TYPE_INDEX_REGISTER_CLASS.
+///
+/// \b Example:
+/// \code
+/// struct Base { virtual ~Base(){} };
+/// struct Derived: public Base {};
+/// ...
+/// Derived d;
+/// Base& b = d;
+/// type_index ti = type_id_runtime(b);
+/// std::cout << ti.pretty_name(); // Outputs 'Derived'
+/// \endcode
+///
+/// \param runtime_val Varaible which runtime type must be returned.
+/// \throw Nothing.
+/// \return boost::typeindex::type_index with information about the specified variable.
+template <class T>
+inline type_index type_id_runtime(const T& runtime_val) BOOST_NOEXCEPT {
+ return type_index::type_id_runtime(runtime_val);
+}
+
+}} // namespace boost::typeindex
+
+
+
+#endif // BOOST_TYPE_INDEX_HPP
diff --git a/third_party/boost/boost/type_index/ctti_type_index.hpp b/third_party/boost/boost/type_index/ctti_type_index.hpp
new file mode 100644
index 0000000..1583ff8
--- /dev/null
+++ b/third_party/boost/boost/type_index/ctti_type_index.hpp
@@ -0,0 +1,178 @@
+//
+// Copyright (c) Antony Polukhin, 2013-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)
+//
+
+#ifndef BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_HPP
+#define BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_HPP
+
+/// \file ctti_type_index.hpp
+/// \brief Contains boost::typeindex::ctti_type_index class.
+///
+/// boost::typeindex::ctti_type_index class can be used as a drop-in replacement
+/// for std::type_index.
+///
+/// It is used in situations when typeid() method is not available or
+/// BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro is defined.
+
+#include <boost/type_index/type_index_facade.hpp>
+#include <boost/type_index/detail/compile_time_type_info.hpp>
+
+#include <cstring>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+namespace boost { namespace typeindex {
+
+namespace detail {
+
+// That's the most trickiest part of the TypeIndex library:
+// 1) we do not want to give user ability to manually construct and compare `struct-that-represents-type`
+// 2) we need to distinguish between `struct-that-represents-type` and `const char*`
+// 3) we need a thread-safe way to have references to instances `struct-that-represents-type`
+// 4) we need a compile-time control to make sure that user does not copy or
+// default construct `struct-that-represents-type`
+//
+// Solution would be the following:
+
+/// \class ctti_data
+/// Standard-layout class with private constructors and assignment operators.
+///
+/// You can not work with this class directly. The purpose of this class is to hold type info
+/// \b when \b RTTI \b is \b off and allow ctti_type_index construction from itself.
+///
+/// \b Example:
+/// \code
+/// const detail::ctti_data& foo();
+/// ...
+/// type_index ti = type_index(foo());
+/// std::cout << ti.pretty_name();
+/// \endcode
+class ctti_data {
+#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
+public:
+ ctti_data() = delete;
+ ctti_data(const ctti_data&) = delete;
+ ctti_data& operator=(const ctti_data&) = delete;
+#else
+private:
+ ctti_data();
+ ctti_data(const ctti_data&);
+ ctti_data& operator=(const ctti_data&);
+#endif
+};
+
+} // namespace detail
+
+/// Helper method for getting detail::ctti_data of a template parameter T.
+template <class T>
+inline const detail::ctti_data& ctti_construct() BOOST_NOEXCEPT {
+ // Standard C++11, 5.2.10 Reinterpret cast:
+ // An object pointer can be explicitly converted to an object pointer of a different type. When a prvalue
+ // v of type "pointer to T1" is converted to the type "pointer to cv T2", the result is static_cast<cv
+ // T2*>(static_cast<cv void*>(v)) if both T1 and T2 are standard-layout types (3.9) and the alignment
+ // requirements of T2 are no stricter than those of T1, or if either type is void. Converting a prvalue of type
+ // "pointer to T1" to the type "pointer to T2" (where T1 and T2 are object types and where the alignment
+ // requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer
+ // value.
+ //
+ // Alignments are checked in `type_index_test_ctti_alignment.cpp` test.
+ return *reinterpret_cast<const detail::ctti_data*>(boost::detail::ctti<T>::n());
+}
+
+/// \class ctti_type_index
+/// This class is a wrapper that pretends to work exactly like stl_type_index, but does
+/// not require RTTI support. \b For \b description \b of \b functions \b see type_index_facade.
+///
+/// This class produces slightly longer type names, so consider using stl_type_index
+/// in situations when typeid() is working.
+class ctti_type_index: public type_index_facade<ctti_type_index, detail::ctti_data> {
+ const detail::ctti_data* data_;
+
+ inline std::size_t get_raw_name_length() const BOOST_NOEXCEPT;
+
+public:
+ typedef detail::ctti_data type_info_t;
+
+ inline ctti_type_index() BOOST_NOEXCEPT
+ : data_(&ctti_construct<void>())
+ {}
+
+ inline ctti_type_index(const type_info_t& data) BOOST_NOEXCEPT
+ : data_(&data)
+ {}
+
+ inline const type_info_t& type_info() const BOOST_NOEXCEPT;
+ inline const char* raw_name() const BOOST_NOEXCEPT;
+ inline std::string pretty_name() const;
+ inline std::size_t hash_code() const BOOST_NOEXCEPT;
+
+ template <class T>
+ inline static ctti_type_index type_id() BOOST_NOEXCEPT;
+
+ template <class T>
+ inline static ctti_type_index type_id_with_cvr() BOOST_NOEXCEPT;
+
+ template <class T>
+ inline static ctti_type_index type_id_runtime(const T& variable) BOOST_NOEXCEPT;
+};
+
+
+inline const ctti_type_index::type_info_t& ctti_type_index::type_info() const BOOST_NOEXCEPT {
+ return *data_;
+}
+
+
+template <class T>
+inline ctti_type_index ctti_type_index::type_id() BOOST_NOEXCEPT {
+ typedef BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type no_ref_t;
+ typedef BOOST_DEDUCED_TYPENAME boost::remove_cv<no_ref_t>::type no_cvr_t;
+ return ctti_construct<no_cvr_t>();
+}
+
+
+
+template <class T>
+inline ctti_type_index ctti_type_index::type_id_with_cvr() BOOST_NOEXCEPT {
+ return ctti_construct<T>();
+}
+
+
+template <class T>
+inline ctti_type_index ctti_type_index::type_id_runtime(const T& variable) BOOST_NOEXCEPT {
+ return variable.boost_type_index_type_id_runtime_();
+}
+
+
+inline const char* ctti_type_index::raw_name() const BOOST_NOEXCEPT {
+ return reinterpret_cast<const char*>(data_);
+}
+
+inline std::size_t ctti_type_index::get_raw_name_length() const BOOST_NOEXCEPT {
+ return std::strlen(raw_name() + detail::ctti_skip_size_at_end);
+}
+
+
+inline std::string ctti_type_index::pretty_name() const {
+ std::size_t len = get_raw_name_length();
+ while (raw_name()[len - 1] == ' ') --len; // MSVC sometimes adds whitespaces
+ return std::string(raw_name(), len);
+}
+
+
+inline std::size_t ctti_type_index::hash_code() const BOOST_NOEXCEPT {
+ return boost::hash_range(raw_name(), raw_name() + get_raw_name_length());
+}
+
+
+}} // namespace boost::typeindex
+
+#endif // BOOST_TYPE_INDEX_CTTI_TYPE_INDEX_HPP
diff --git a/third_party/boost/boost/type_index/detail/compile_time_type_info.hpp b/third_party/boost/boost/type_index/detail/compile_time_type_info.hpp
new file mode 100644
index 0000000..be4a84c
--- /dev/null
+++ b/third_party/boost/boost/type_index/detail/compile_time_type_info.hpp
@@ -0,0 +1,143 @@
+//
+// Copyright (c) Antony Polukhin, 2012-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)
+//
+
+#ifndef BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP
+#define BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP
+
+/// \file compile_time_type_info.hpp
+/// \brief Contains helper macros and implementation details of boost::typeindex::ctti_type_index.
+/// Not intended for inclusion from user's code.
+
+#include <boost/config.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/mpl/bool.hpp>
+#include <algorithm>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+/// @cond
+#define BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(begin_skip, end_skip, runtime_skip, runtime_skip_until) \
+ namespace boost { namespace typeindex { namespace detail { \
+ BOOST_STATIC_CONSTEXPR std::size_t ctti_skip_size_at_begin = begin_skip; \
+ BOOST_STATIC_CONSTEXPR std::size_t ctti_skip_size_at_end = end_skip; \
+ BOOST_STATIC_CONSTEXPR bool ctti_skip_more_at_runtime = runtime_skip; \
+ BOOST_STATIC_CONSTEXPR char ctti_skip_until_runtime[] = runtime_skip_until; \
+ }}} /* namespace boost::typeindex::detail */ \
+ /**/
+/// @endcond
+
+#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
+ /* Nothing to document. All the macro docs are moved to <boost/type_index.hpp> */
+#elif defined(BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING)
+
+# include <boost/preprocessor/facilities/expand.hpp>
+ BOOST_PP_EXPAND( BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING )
+
+#elif defined(_MSC_VER)
+ // sizeof("const char *__cdecl boost::detail::ctti<") - 1, sizeof(">::n(void)") - 1
+ BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(40, 10, false, "")
+#elif defined(__clang__) && defined(__APPLE__)
+ // Someone made __clang_major__ equal to LLVM version rather than compiler version
+ // on APPLE platform.
+ //
+ // Using less efficient solution because there is no good way to detect real version of Clang.
+ // sizeof("static const char *boost::detail::ctti<") - 1, sizeof("]") - 1, true, "???????????>::n() [T = int"
+ BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(39, 1, true, "T = ")
+#elif defined(__clang__) && (__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ == 0))
+ // sizeof("static const char *boost::detail::ctti<") - 1, sizeof(">::n()") - 1
+ // note: checked on 3.0
+ BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(39, 6, false, "")
+#elif defined(__clang__) && __clang_major__ == 3 && __clang_minor__ > 0
+ // sizeof("static const char *boost::detail::ctti<") - 1, sizeof("]") - 1, true, "int>::n() [T = int"
+ // note: checked on 3.1, 3.4
+ BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(39, 1, true, "T = ")
+#elif defined(__GNUC__)
+ // sizeof("static const char* boost::detail::ctti<T>::n() [with T = ") - 1, sizeof("]") - 1
+ BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(57, 1, false, "")
+#else
+ // Deafult code for other platforms... Just skip nothing!
+ BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(0, 0, false, "")
+#endif
+
+#undef BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS
+
+namespace boost { namespace typeindex { namespace detail {
+ template <bool Condition>
+ inline void assert_compile_time_legths() BOOST_NOEXCEPT {
+ BOOST_STATIC_ASSERT_MSG(
+ Condition,
+ "TypeIndex library is misconfigured for your compiler. "
+ "Please define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING to correct values. See section "
+ "'RTTI emulation limitations' of the documentation for more information."
+ );
+ }
+
+ template <std::size_t ArrayLength>
+ inline const char* skip_begining_runtime(const char* begin, boost::mpl::false_) BOOST_NOEXCEPT {
+ return begin;
+ }
+
+ template <std::size_t ArrayLength>
+ inline const char* skip_begining_runtime(const char* begin, boost::mpl::true_) BOOST_NOEXCEPT {
+ const char* const it = std::search(
+ begin, begin + ArrayLength,
+ ctti_skip_until_runtime, ctti_skip_until_runtime + sizeof(ctti_skip_until_runtime) - 1
+ );
+ return (it == begin + ArrayLength ? begin : it + sizeof(ctti_skip_until_runtime) - 1);
+ }
+
+ template <std::size_t ArrayLength>
+ inline const char* skip_begining(const char* begin) BOOST_NOEXCEPT {
+ assert_compile_time_legths<(ArrayLength > ctti_skip_size_at_begin + ctti_skip_size_at_end)>();
+ return skip_begining_runtime<ArrayLength - ctti_skip_size_at_begin>(
+ begin + ctti_skip_size_at_begin,
+ boost::mpl::bool_<ctti_skip_more_at_runtime>()
+ );
+ }
+}}} // namespace boost::typeindex::detail
+
+namespace boost { namespace detail {
+
+/// Noncopyable type_info that does not require RTTI.
+/// CTTI == Compile Time Type Info.
+/// This name must be as short as possible, to avoid code bloat
+template <class T>
+struct ctti {
+
+ /// Returns raw name. Must be as short, as possible, to avoid code bloat
+ static const char* n() BOOST_NOEXCEPT {
+ #if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE)
+ return boost::typeindex::detail::skip_begining< sizeof(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE >(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE);
+ #elif defined(__FUNCSIG__)
+ return boost::typeindex::detail::skip_begining< sizeof(__FUNCSIG__) >(__FUNCSIG__);
+ #elif defined(__PRETTY_FUNCTION__) \
+ || defined(__GNUC__) \
+ || (defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5130)) \
+ || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) \
+ || (defined(__ICC) && (__ICC >= 600)) \
+ || defined(__ghs__) \
+ || defined(__DMC__)
+
+ return boost::typeindex::detail::skip_begining< sizeof(__PRETTY_FUNCTION__) >(__PRETTY_FUNCTION__);
+ #else
+ BOOST_STATIC_ASSERT_MSG(
+ sizeof(T) && false,
+ "TypeIndex library could not detect your compiler. "
+ "Please make the BOOST_TYPE_INDEX_FUNCTION_SIGNATURE macro use "
+ "correct compiler macro for getting the whole function name. "
+ "Define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING to correct value after that."
+ );
+ #endif
+ }
+};
+
+}} // namespace boost::detail
+
+#endif // BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP
diff --git a/third_party/boost/boost/type_index/detail/ctti_register_class.hpp b/third_party/boost/boost/type_index/detail/ctti_register_class.hpp
new file mode 100644
index 0000000..fa8598e
--- /dev/null
+++ b/third_party/boost/boost/type_index/detail/ctti_register_class.hpp
@@ -0,0 +1,39 @@
+//
+// Copyright (c) Antony Polukhin, 2013-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)
+//
+
+#ifndef BOOST_TYPE_INDEX_CTTI_REGISTER_CLASS_HPP
+#define BOOST_TYPE_INDEX_CTTI_REGISTER_CLASS_HPP
+
+/// \file ctti_register_class.hpp
+/// \brief Contains BOOST_TYPE_INDEX_REGISTER_CLASS macro implementation that uses boost::typeindex::ctti_type_index.
+/// Not intended for inclusion from user's code.
+
+#include <boost/type_index/ctti_type_index.hpp>
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+namespace boost { namespace typeindex { namespace detail {
+
+template <class T>
+inline const ctti_data& ctti_construct_typeid_ref(const T*) BOOST_NOEXCEPT {
+ return ctti_construct<T>();
+}
+
+}}} // namespace boost::typeindex::detail
+
+/// @cond
+#define BOOST_TYPE_INDEX_REGISTER_CLASS \
+ virtual const boost::typeindex::detail::ctti_data& boost_type_index_type_id_runtime_() const BOOST_NOEXCEPT { \
+ return boost::typeindex::detail::ctti_construct_typeid_ref(this); \
+ } \
+/**/
+/// @endcond
+
+#endif // BOOST_TYPE_INDEX_CTTI_REGISTER_CLASS_HPP
diff --git a/third_party/boost/boost/type_index/stl_type_index.hpp b/third_party/boost/boost/type_index/stl_type_index.hpp
new file mode 100644
index 0000000..3e1f658
--- /dev/null
+++ b/third_party/boost/boost/type_index/stl_type_index.hpp
@@ -0,0 +1,272 @@
+//
+// Copyright (c) Antony Polukhin, 2013-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)
+//
+
+#ifndef BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP
+#define BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP
+
+/// \file stl_type_index.hpp
+/// \brief Contains boost::typeindex::stl_type_index class.
+///
+/// boost::typeindex::stl_type_index class can be used as a drop-in replacement
+/// for std::type_index.
+///
+/// It is used in situations when RTTI is enabled or typeid() method is available.
+/// When typeid() is disabled or BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY macro
+/// is defined boost::typeindex::ctti is usually used instead of boost::typeindex::stl_type_index.
+
+#include <boost/type_index/type_index_facade.hpp>
+
+// MSVC is capable of calling typeid(T) even when RTTI is off
+#if defined(BOOST_NO_RTTI) && !defined(BOOST_MSVC)
+#error "File boost/type_index/stl_type_index.ipp is not usable when typeid() is not available."
+#endif
+
+#include <typeinfo>
+#include <cstring> // std::strcmp, std::strlen, std::strstr
+#include <stdexcept>
+#include <boost/static_assert.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/core/demangle.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/is_reference.hpp>
+#include <boost/type_traits/is_volatile.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/or.hpp>
+
+#if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \
+ || (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744)
+# include <boost/type_traits/is_signed.hpp>
+# include <boost/type_traits/make_signed.hpp>
+# include <boost/mpl/identity.hpp>
+#endif
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+namespace boost { namespace typeindex {
+
+/// \class stl_type_index
+/// This class is a wrapper around std::type_info, that workarounds issues and provides
+/// much more rich interface. \b For \b description \b of \b functions \b see type_index_facade.
+///
+/// This class requires typeid() to work. For cases when RTTI is disabled see ctti_type_index.
+class stl_type_index
+ : public type_index_facade<
+ stl_type_index,
+ #ifdef BOOST_NO_STD_TYPEINFO
+ type_info
+ #else
+ std::type_info
+ #endif
+ >
+{
+public:
+#ifdef BOOST_NO_STD_TYPEINFO
+ typedef type_info type_info_t;
+#else
+ typedef std::type_info type_info_t;
+#endif
+
+private:
+ const type_info_t* data_;
+
+public:
+ inline stl_type_index() BOOST_NOEXCEPT
+ : data_(&typeid(void))
+ {}
+
+ inline stl_type_index(const type_info_t& data) BOOST_NOEXCEPT
+ : data_(&data)
+ {}
+
+ inline const type_info_t& type_info() const BOOST_NOEXCEPT;
+
+ inline const char* raw_name() const BOOST_NOEXCEPT;
+ inline const char* name() const BOOST_NOEXCEPT;
+ inline std::string pretty_name() const;
+
+ inline std::size_t hash_code() const BOOST_NOEXCEPT;
+ inline bool equal(const stl_type_index& rhs) const BOOST_NOEXCEPT;
+ inline bool before(const stl_type_index& rhs) const BOOST_NOEXCEPT;
+
+ template <class T>
+ inline static stl_type_index type_id() BOOST_NOEXCEPT;
+
+ template <class T>
+ inline static stl_type_index type_id_with_cvr() BOOST_NOEXCEPT;
+
+ template <class T>
+ inline static stl_type_index type_id_runtime(const T& value) BOOST_NOEXCEPT;
+};
+
+inline const stl_type_index::type_info_t& stl_type_index::type_info() const BOOST_NOEXCEPT {
+ return *data_;
+}
+
+
+inline const char* stl_type_index::raw_name() const BOOST_NOEXCEPT {
+#ifdef _MSC_VER
+ return data_->raw_name();
+#else
+ return data_->name();
+#endif
+}
+
+inline const char* stl_type_index::name() const BOOST_NOEXCEPT {
+ return data_->name();
+}
+
+inline std::string stl_type_index::pretty_name() const {
+ static const char cvr_saver_name[] = "boost::typeindex::detail::cvr_saver<";
+ static BOOST_CONSTEXPR_OR_CONST std::string::size_type cvr_saver_name_len = sizeof(cvr_saver_name) - 1;
+
+ // In case of MSVC demangle() is a no-op, and name() already returns demangled name.
+ // In case of GCC and Clang (on non-Windows systems) name() returns mangled name and demangle() undecorates it.
+ const boost::core::scoped_demangled_name demangled_name(data_->name());
+
+ const char* begin = demangled_name.get();
+ if (!begin) {
+ boost::throw_exception(std::runtime_error("Type name demangling failed"));
+ }
+
+ const std::string::size_type len = std::strlen(begin);
+ const char* end = begin + len;
+
+ if (len > cvr_saver_name_len) {
+ const char* b = std::strstr(begin, cvr_saver_name);
+ if (b) {
+ b += cvr_saver_name_len;
+
+ // Trim leading spaces
+ while (*b == ' ') { // the string is zero terminated, we won't exceed the buffer size
+ ++ b;
+ }
+
+ // Skip the closing angle bracket
+ const char* e = end - 1;
+ while (e > b && *e != '>') {
+ -- e;
+ }
+
+ // Trim trailing spaces
+ while (e > b && *(e - 1) == ' ') {
+ -- e;
+ }
+
+ if (b < e) {
+ // Parsing seems to have succeeded, the type name is not empty
+ begin = b;
+ end = e;
+ }
+ }
+ }
+
+ return std::string(begin, end);
+}
+
+
+inline std::size_t stl_type_index::hash_code() const BOOST_NOEXCEPT {
+#if _MSC_VER > 1600 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5 && defined(__GXX_EXPERIMENTAL_CXX0X__))
+ return data_->hash_code();
+#else
+ return boost::hash_range(raw_name(), raw_name() + std::strlen(raw_name()));
+#endif
+}
+
+
+/// @cond
+
+// for this compiler at least, cross-shared-library type_info
+// comparisons don't work, so we are using typeid(x).name() instead.
+# if (defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5))) \
+ || defined(_AIX) \
+ || (defined(__sgi) && defined(__host_mips)) \
+ || (defined(__hpux) && defined(__HP_aCC)) \
+ || (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC))
+# define BOOST_CLASSINFO_COMPARE_BY_NAMES
+# endif
+
+/// @endcond
+
+inline bool stl_type_index::equal(const stl_type_index& rhs) const BOOST_NOEXCEPT {
+#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
+ return raw_name() == rhs.raw_name() || !std::strcmp(raw_name(), rhs.raw_name());
+#else
+ return *data_ == *rhs.data_;
+#endif
+}
+
+inline bool stl_type_index::before(const stl_type_index& rhs) const BOOST_NOEXCEPT {
+#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
+ return raw_name() != rhs.raw_name() && std::strcmp(raw_name(), rhs.raw_name()) < 0;
+#else
+ return !!data_->before(*rhs.data_);
+#endif
+}
+
+#ifdef BOOST_CLASSINFO_COMPARE_BY_NAMES
+#undef BOOST_CLASSINFO_COMPARE_BY_NAMES
+#endif
+
+
+
+template <class T>
+inline stl_type_index stl_type_index::type_id() BOOST_NOEXCEPT {
+ typedef BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type no_ref_t;
+ typedef BOOST_DEDUCED_TYPENAME boost::remove_cv<no_ref_t>::type no_cvr_prefinal_t;
+
+ # if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \
+ || (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744)
+
+ // Old EDG-based compilers seem to mistakenly distinguish 'integral' from 'signed integral'
+ // in typeid() expressions. Full template specialization for 'integral' fixes that issue:
+ typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<
+ boost::is_signed<no_cvr_prefinal_t>,
+ boost::make_signed<no_cvr_prefinal_t>,
+ boost::mpl::identity<no_cvr_prefinal_t>
+ >::type no_cvr_prefinal_lazy_t;
+
+ typedef BOOST_DEDUCED_TYPENAME no_cvr_prefinal_t::type no_cvr_t;
+ #else
+ typedef no_cvr_prefinal_t no_cvr_t;
+ #endif
+
+ return typeid(no_cvr_t);
+}
+
+namespace detail {
+ template <class T> class cvr_saver{};
+}
+
+template <class T>
+inline stl_type_index stl_type_index::type_id_with_cvr() BOOST_NOEXCEPT {
+ typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<
+ boost::mpl::or_<boost::is_reference<T>, boost::is_const<T>, boost::is_volatile<T> >,
+ detail::cvr_saver<T>,
+ T
+ >::type type;
+
+ return typeid(type);
+}
+
+
+template <class T>
+inline stl_type_index stl_type_index::type_id_runtime(const T& value) BOOST_NOEXCEPT {
+#ifdef BOOST_NO_RTTI
+ return value.boost_type_index_type_id_runtime_();
+#else
+ return typeid(value);
+#endif
+}
+
+}} // namespace boost::typeindex
+
+#endif // BOOST_TYPE_INDEX_STL_TYPE_INDEX_HPP
diff --git a/third_party/boost/boost/type_index/type_index_facade.hpp b/third_party/boost/boost/type_index/type_index_facade.hpp
new file mode 100644
index 0000000..4c8481a
--- /dev/null
+++ b/third_party/boost/boost/type_index/type_index_facade.hpp
@@ -0,0 +1,299 @@
+//
+// Copyright (c) Antony Polukhin, 2013-2015.
+//
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP
+#define BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP
+
+#include <boost/config.hpp>
+#include <string>
+#include <cstring>
+
+#if !defined(BOOST_NO_IOSTREAM)
+#if !defined(BOOST_NO_IOSFWD)
+#include <iosfwd> // for std::basic_ostream
+#else
+#include <ostream>
+#endif
+#endif
+
+#ifdef BOOST_HAS_PRAGMA_ONCE
+# pragma once
+#endif
+
+// Forward declaration from #include <boost/functional/hash_fwd.hpp>
+namespace boost {
+ template <class It> std::size_t hash_range(It, It);
+}
+
+namespace boost { namespace typeindex {
+
+/// \class type_index_facade
+///
+/// This class takes care about the comparison operators, hash functions and
+/// ostream operators. Use this class as a public base class for defining new
+/// type_info-conforming classes.
+///
+/// \b Example:
+/// \code
+/// class stl_type_index: public type_index_facade<stl_type_index, std::type_info>
+/// {
+/// public:
+/// typedef std::type_info type_info_t;
+/// private:
+/// const type_info_t* data_;
+///
+/// public:
+/// stl_type_index(const type_info_t& data) noexcept
+/// : data_(&data)
+/// {}
+/// // ...
+/// };
+/// \endcode
+///
+/// \tparam Derived Class derived from type_index_facade.
+/// \tparam TypeInfo Class that will be used as a base type_info class.
+/// \note Take a look at the protected methods. They are \b not \b defined in type_index_facade.
+/// Protected member functions raw_name() \b must be defined in Derived class. All the other
+/// methods are mandatory.
+/// \see 'Making a custom type_index' section for more information about
+/// creating your own type_index using type_index_facade.
+template <class Derived, class TypeInfo>
+class type_index_facade {
+private:
+ /// @cond
+ const Derived & derived() const BOOST_NOEXCEPT {
+ return *static_cast<Derived const*>(this);
+ }
+ /// @endcond
+public:
+ typedef TypeInfo type_info_t;
+
+ /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
+ /// \return Name of a type. By default returns Derived::raw_name().
+ inline const char* name() const BOOST_NOEXCEPT {
+ return derived().raw_name();
+ }
+
+ /// \b Override: This function \b may be redefined in Derived class. Overrides may throw.
+ /// \return Human readable type name. By default returns Derived::name().
+ inline std::string pretty_name() const {
+ return derived().name();
+ }
+
+ /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
+ /// \return True if two types are equal. By default compares types by raw_name().
+ inline bool equal(const Derived& rhs) const BOOST_NOEXCEPT {
+ const char* const left = derived().raw_name();
+ const char* const right = rhs.raw_name();
+ return left == right || !std::strcmp(left, right);
+ }
+
+ /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
+ /// \return True if rhs is greater than this. By default compares types by raw_name().
+ inline bool before(const Derived& rhs) const BOOST_NOEXCEPT {
+ const char* const left = derived().raw_name();
+ const char* const right = rhs.raw_name();
+ return left != right && std::strcmp(left, right) < 0;
+ }
+
+ /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
+ /// \return Hash code of a type. By default hashes types by raw_name().
+ /// \note <boost/functional/hash.hpp> has to be included if this function is used.
+ inline std::size_t hash_code() const BOOST_NOEXCEPT {
+ const char* const name_raw = derived().raw_name();
+ return boost::hash_range(name_raw, name_raw + std::strlen(name_raw));
+ }
+
+#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
+protected:
+ /// \b Override: This function \b must be redefined in Derived class. Overrides \b must not throw.
+ /// \return Pointer to unredable/raw type name.
+ inline const char* raw_name() const BOOST_NOEXCEPT;
+
+ /// \b Override: This function \b may be redefined in Derived class. Overrides \b must not throw.
+ /// \return Const reference to underlying low level type_info_t.
+ inline const type_info_t& type_info() const BOOST_NOEXCEPT;
+
+ /// This is a factory method that is used to create instances of Derived classes.
+ /// boost::typeindex::type_id() will call this method, if Derived has same type as boost::typeindex::type_index.
+ ///
+ /// \b Override: This function \b may be redefined and made public in Derived class. Overrides \b must not throw.
+ /// Overrides \b must remove const, volatile && and & modifiers from T.
+ /// \tparam T Type for which type_index must be created.
+ /// \return type_index for type T.
+ template <class T>
+ static Derived type_id() BOOST_NOEXCEPT;
+
+ /// This is a factory method that is used to create instances of Derived classes.
+ /// boost::typeindex::type_id_with_cvr() will call this method, if Derived has same type as boost::typeindex::type_index.
+ ///
+ /// \b Override: This function \b may be redefined and made public in Derived class. Overrides \b must not throw.
+ /// Overrides \b must \b not remove const, volatile && and & modifiers from T.
+ /// \tparam T Type for which type_index must be created.
+ /// \return type_index for type T.
+ template <class T>
+ static Derived type_id_with_cvr() BOOST_NOEXCEPT;
+
+ /// This is a factory method that is used to create instances of Derived classes.
+ /// boost::typeindex::type_id_runtime(const T&) will call this method, if Derived has same type as boost::typeindex::type_index.
+ ///
+ /// \b Override: This function \b may be redefined and made public in Derived class.
+ /// \param variable Variable which runtime type will be stored in type_index.
+ /// \return type_index with runtime type of variable.
+ template <class T>
+ static Derived type_id_runtime(const T& variable) BOOST_NOEXCEPT;
+
+#endif
+
+};
+
+/// @cond
+template <class Derived, class TypeInfo>
+inline bool operator == (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
+ return static_cast<Derived const&>(lhs).equal(static_cast<Derived const&>(rhs));
+}
+
+template <class Derived, class TypeInfo>
+inline bool operator < (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
+ return static_cast<Derived const&>(lhs).before(static_cast<Derived const&>(rhs));;
+}
+
+
+
+template <class Derived, class TypeInfo>
+inline bool operator > (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
+ return rhs < lhs;
+}
+
+template <class Derived, class TypeInfo>
+inline bool operator <= (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
+ return !(lhs > rhs);
+}
+
+template <class Derived, class TypeInfo>
+inline bool operator >= (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
+ return !(lhs < rhs);
+}
+
+template <class Derived, class TypeInfo>
+inline bool operator != (const type_index_facade<Derived, TypeInfo>& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
+ return !(lhs == rhs);
+}
+
+// ######################### COMPARISONS with Derived ############################ //
+template <class Derived, class TypeInfo>
+inline bool operator == (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
+ return Derived(lhs) == rhs;
+}
+
+template <class Derived, class TypeInfo>
+inline bool operator < (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
+ return Derived(lhs) < rhs;
+}
+
+template <class Derived, class TypeInfo>
+inline bool operator > (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
+ return rhs < Derived(lhs);
+}
+
+template <class Derived, class TypeInfo>
+inline bool operator <= (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
+ return !(Derived(lhs) > rhs);
+}
+
+template <class Derived, class TypeInfo>
+inline bool operator >= (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
+ return !(Derived(lhs) < rhs);
+}
+
+template <class Derived, class TypeInfo>
+inline bool operator != (const TypeInfo& lhs, const type_index_facade<Derived, TypeInfo>& rhs) BOOST_NOEXCEPT {
+ return !(Derived(lhs) == rhs);
+}
+
+
+template <class Derived, class TypeInfo>
+inline bool operator == (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT {
+ return lhs == Derived(rhs);
+}
+
+template <class Derived, class TypeInfo>
+inline bool operator < (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT {
+ return lhs < Derived(rhs);
+}
+
+template <class Derived, class TypeInfo>
+inline bool operator > (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT {
+ return Derived(rhs) < lhs;
+}
+
+template <class Derived, class TypeInfo>
+inline bool operator <= (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT {
+ return !(lhs > Derived(rhs));
+}
+
+template <class Derived, class TypeInfo>
+inline bool operator >= (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT {
+ return !(lhs < Derived(rhs));
+}
+
+template <class Derived, class TypeInfo>
+inline bool operator != (const type_index_facade<Derived, TypeInfo>& lhs, const TypeInfo& rhs) BOOST_NOEXCEPT {
+ return !(lhs == Derived(rhs));
+}
+
+// ######################### COMPARISONS with Derived END ############################ //
+
+/// @endcond
+
+#if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
+
+/// noexcept comparison operators for type_index_facade classes.
+bool operator ==, !=, <, ... (const type_index_facade& lhs, const type_index_facade& rhs) noexcept;
+
+/// noexcept comparison operators for type_index_facade and it's TypeInfo classes.
+bool operator ==, !=, <, ... (const type_index_facade& lhs, const TypeInfo& rhs) noexcept;
+
+/// noexcept comparison operators for type_index_facade's TypeInfo and type_index_facade classes.
+bool operator ==, !=, <, ... (const TypeInfo& lhs, const type_index_facade& rhs) noexcept;
+
+#endif
+
+#ifndef BOOST_NO_IOSTREAM
+#ifdef BOOST_NO_TEMPLATED_IOSTREAMS
+/// @cond
+/// Ostream operator that will output demangled name
+template <class Derived, class TypeInfo>
+inline std::ostream& operator<<(std::ostream& ostr, const type_index_facade<Derived, TypeInfo>& ind) {
+ ostr << static_cast<Derived const&>(ind).pretty_name();
+ return ostr;
+}
+/// @endcond
+#else
+/// Ostream operator that will output demangled name.
+template <class CharT, class TriatT, class Derived, class TypeInfo>
+inline std::basic_ostream<CharT, TriatT>& operator<<(
+ std::basic_ostream<CharT, TriatT>& ostr,
+ const type_index_facade<Derived, TypeInfo>& ind)
+{
+ ostr << static_cast<Derived const&>(ind).pretty_name();
+ return ostr;
+}
+#endif // BOOST_NO_TEMPLATED_IOSTREAMS
+#endif // BOOST_NO_IOSTREAM
+
+/// This free function is used by Boost's unordered containers.
+/// \note <boost/functional/hash.hpp> has to be included if this function is used.
+template <class Derived, class TypeInfo>
+inline std::size_t hash_value(const type_index_facade<Derived, TypeInfo>& lhs) BOOST_NOEXCEPT {
+ return static_cast<Derived const&>(lhs).hash_code();
+}
+
+}} // namespace boost::typeindex
+
+#endif // BOOST_TYPE_INDEX_TYPE_INDEX_FACADE_HPP
diff --git a/third_party/boost/boost/type_traits/add_const.hpp b/third_party/boost/boost/type_traits/add_const.hpp
new file mode 100644
index 0000000..5b0b455
--- /dev/null
+++ b/third_party/boost/boost/type_traits/add_const.hpp
@@ -0,0 +1,46 @@
+
+// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes, Howard
+// Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_ADD_CONST_HPP_INCLUDED
+#define BOOST_TT_ADD_CONST_HPP_INCLUDED
+
+#include <boost/type_traits/detail/config.hpp>
+
+namespace boost {
+
+// * convert a type T to const type - add_const<T>
+// this is not required since the result is always
+// the same as "T const", but it does suppress warnings
+// from some compilers:
+
+#if defined(BOOST_MSVC)
+// This bogus warning will appear when add_const is applied to a
+// const volatile reference because we can't detect const volatile
+// references with MSVC6.
+# pragma warning(push)
+# pragma warning(disable:4181) // warning C4181: qualifier applied to reference type ignored
+#endif
+
+ template <class T> struct add_const
+ {
+ typedef T const type;
+ };
+
+#if defined(BOOST_MSVC)
+# pragma warning(pop)
+#endif
+
+ template <class T> struct add_const<T&>
+ {
+ typedef T& type;
+ };
+
+} // namespace boost
+
+#endif // BOOST_TT_ADD_CONST_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/add_lvalue_reference.hpp b/third_party/boost/boost/type_traits/add_lvalue_reference.hpp
new file mode 100644
index 0000000..5539c94
--- /dev/null
+++ b/third_party/boost/boost/type_traits/add_lvalue_reference.hpp
@@ -0,0 +1,27 @@
+// Copyright 2010 John Maddock
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_TYPE_TRAITS_EXT_ADD_LVALUE_REFERENCE__HPP
+#define BOOST_TYPE_TRAITS_EXT_ADD_LVALUE_REFERENCE__HPP
+
+#include <boost/type_traits/add_reference.hpp>
+
+namespace boost{
+
+template <class T> struct add_lvalue_reference
+{
+ typedef typename boost::add_reference<T>::type type;
+};
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+template <class T> struct add_lvalue_reference<T&&>
+{
+ typedef T& type;
+};
+#endif
+
+}
+
+#endif // BOOST_TYPE_TRAITS_EXT_ADD_LVALUE_REFERENCE__HPP
diff --git a/third_party/boost/boost/type_traits/add_pointer.hpp b/third_party/boost/boost/type_traits/add_pointer.hpp
new file mode 100644
index 0000000..745f63a
--- /dev/null
+++ b/third_party/boost/boost/type_traits/add_pointer.hpp
@@ -0,0 +1,61 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_ADD_POINTER_HPP_INCLUDED
+#define BOOST_TT_ADD_POINTER_HPP_INCLUDED
+
+#include <boost/type_traits/remove_reference.hpp>
+
+namespace boost {
+
+#if defined(__BORLANDC__) && (__BORLANDC__ < 0x5A0)
+//
+// For some reason this implementation stops Borlands compiler
+// from dropping cv-qualifiers, it still fails with references
+// to arrays for some reason though (shrug...) (JM 20021104)
+//
+template <typename T>
+struct add_pointer
+{
+ typedef T* type;
+};
+template <typename T>
+struct add_pointer<T&>
+{
+ typedef T* type;
+};
+template <typename T>
+struct add_pointer<T&const>
+{
+ typedef T* type;
+};
+template <typename T>
+struct add_pointer<T&volatile>
+{
+ typedef T* type;
+};
+template <typename T>
+struct add_pointer<T&const volatile>
+{
+ typedef T* type;
+};
+
+#else
+
+template <typename T>
+struct add_pointer
+{
+ typedef typename remove_reference<T>::type no_ref_type;
+ typedef no_ref_type* type;
+};
+
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TT_ADD_POINTER_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/add_reference.hpp b/third_party/boost/boost/type_traits/add_reference.hpp
new file mode 100644
index 0000000..526f259
--- /dev/null
+++ b/third_party/boost/boost/type_traits/add_reference.hpp
@@ -0,0 +1,59 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_ADD_REFERENCE_HPP_INCLUDED
+#define BOOST_TT_ADD_REFERENCE_HPP_INCLUDED
+
+#include <boost/detail/workaround.hpp>
+#include <boost/config.hpp>
+
+namespace boost {
+
+namespace detail {
+
+//
+// We can't filter out rvalue_references at the same level as
+// references or we get ambiguities from msvc:
+//
+
+template <typename T>
+struct add_reference_impl
+{
+ typedef T& type;
+};
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+template <typename T>
+struct add_reference_impl<T&&>
+{
+ typedef T&& type;
+};
+#endif
+
+} // namespace detail
+
+template <class T> struct add_reference
+{
+ typedef typename boost::detail::add_reference_impl<T>::type type;
+};
+template <class T> struct add_reference<T&>
+{
+ typedef T& type;
+};
+
+// these full specialisations are always required:
+template <> struct add_reference<void> { typedef void type; };
+#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
+template <> struct add_reference<const void> { typedef void type; };
+template <> struct add_reference<const volatile void> { typedef void type; };
+template <> struct add_reference<volatile void> { typedef void type; };
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TT_ADD_REFERENCE_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/add_rvalue_reference.hpp b/third_party/boost/boost/type_traits/add_rvalue_reference.hpp
new file mode 100644
index 0000000..0ec0ff2
--- /dev/null
+++ b/third_party/boost/boost/type_traits/add_rvalue_reference.hpp
@@ -0,0 +1,63 @@
+// add_rvalue_reference.hpp ---------------------------------------------------------//
+
+// Copyright 2010 Vicente J. Botet Escriba
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_TYPE_TRAITS_EXT_ADD_RVALUE_REFERENCE__HPP
+#define BOOST_TYPE_TRAITS_EXT_ADD_RVALUE_REFERENCE__HPP
+
+#include <boost/config.hpp>
+
+//----------------------------------------------------------------------------//
+
+#include <boost/type_traits/is_void.hpp>
+#include <boost/type_traits/is_reference.hpp>
+
+//----------------------------------------------------------------------------//
+// //
+// C++03 implementation of //
+// 20.9.7.2 Reference modifications [meta.trans.ref] //
+// Written by Vicente J. Botet Escriba //
+// //
+// If T names an object or function type then the member typedef type
+// shall name T&&; otherwise, type shall name T. [ Note: This rule reflects
+// the semantics of reference collapsing. For example, when a type T names
+// a type T1&, the type add_rvalue_reference<T>::type is not an rvalue
+// reference. -end note ]
+//----------------------------------------------------------------------------//
+
+namespace boost {
+
+namespace type_traits_detail {
+
+ template <typename T, bool b>
+ struct add_rvalue_reference_helper
+ { typedef T type; };
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template <typename T>
+ struct add_rvalue_reference_helper<T, true>
+ {
+ typedef T&& type;
+ };
+#endif
+
+ template <typename T>
+ struct add_rvalue_reference_imp
+ {
+ typedef typename boost::type_traits_detail::add_rvalue_reference_helper
+ <T, (is_void<T>::value == false && is_reference<T>::value == false) >::type type;
+ };
+
+}
+
+template <class T> struct add_rvalue_reference
+{
+ typedef typename boost::type_traits_detail::add_rvalue_reference_imp<T>::type type;
+};
+
+} // namespace boost
+
+#endif // BOOST_TYPE_TRAITS_EXT_ADD_RVALUE_REFERENCE__HPP
diff --git a/third_party/boost/boost/type_traits/add_volatile.hpp b/third_party/boost/boost/type_traits/add_volatile.hpp
new file mode 100644
index 0000000..cc43b0d
--- /dev/null
+++ b/third_party/boost/boost/type_traits/add_volatile.hpp
@@ -0,0 +1,40 @@
+
+// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes, Howard
+// Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_ADD_VOLATILE_HPP_INCLUDED
+#define BOOST_TT_ADD_VOLATILE_HPP_INCLUDED
+
+#include <boost/config.hpp>
+
+namespace boost {
+
+// * convert a type T to volatile type - add_volatile<T>
+// this is not required since the result is always
+// the same as "T volatile", but it does suppress warnings
+// from some compilers:
+
+#if defined(BOOST_MSVC)
+// This bogus warning will appear when add_volatile is applied to a
+// const volatile reference because we can't detect const volatile
+// references with MSVC6.
+# pragma warning(push)
+# pragma warning(disable:4181) // warning C4181: qualifier applied to reference type ignored
+#endif
+
+template <class T> struct add_volatile{ typedef T volatile type; };
+
+#if defined(BOOST_MSVC)
+# pragma warning(pop)
+#endif
+
+template <class T> struct add_volatile<T&>{ typedef T& type; };
+
+} // namespace boost
+
+#endif // BOOST_TT_ADD_VOLATILE_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/aligned_storage.hpp b/third_party/boost/boost/type_traits/aligned_storage.hpp
new file mode 100644
index 0000000..13a5c9e
--- /dev/null
+++ b/third_party/boost/boost/type_traits/aligned_storage.hpp
@@ -0,0 +1,138 @@
+//-----------------------------------------------------------------------------
+// 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_TT_ALIGNED_STORAGE_HPP
+#define BOOST_TT_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/type_traits/conditional.hpp"
+
+namespace boost {
+
+namespace detail { namespace aligned_storage {
+
+BOOST_STATIC_CONSTANT(
+ std::size_t
+ , alignment_of_max_align = ::boost::alignment_of<boost::detail::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::type_with_alignment<alignment_>::type align_;
+ } data_;
+ void* address() const { return const_cast<aligned_storage_imp*>(this); }
+};
+template <std::size_t size>
+struct aligned_storage_imp<size, std::size_t(-1)>
+{
+ union data_t
+ {
+ char buf[size];
+ ::boost::detail::max_align 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_> > : public true_type{};
+
+} // namespace boost
+
+#endif // BOOST_ALIGNED_STORAGE_HPP
diff --git a/third_party/boost/boost/type_traits/alignment_of.hpp b/third_party/boost/boost/type_traits/alignment_of.hpp
new file mode 100644
index 0000000..9fe9b3b
--- /dev/null
+++ b/third_party/boost/boost/type_traits/alignment_of.hpp
@@ -0,0 +1,118 @@
+
+// (C) Copyright John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_ALIGNMENT_OF_HPP_INCLUDED
+#define BOOST_TT_ALIGNMENT_OF_HPP_INCLUDED
+
+#include <boost/config.hpp>
+#include <cstddef>
+
+#include <boost/type_traits/intrinsics.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+
+#ifdef BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable: 4121 4512) // alignment is sensitive to packing
+#endif
+#if defined(__BORLANDC__) && (__BORLANDC__ < 0x600)
+#pragma option push -Vx- -Ve-
+#endif
+
+namespace boost {
+
+template <typename T> struct alignment_of;
+
+// get the alignment of some arbitrary type:
+namespace detail {
+
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable:4324) // structure was padded due to __declspec(align())
+#endif
+template <typename T>
+struct alignment_of_hack
+{
+ char c;
+ T t;
+ alignment_of_hack();
+};
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+template <unsigned A, unsigned S>
+struct alignment_logic
+{
+ BOOST_STATIC_CONSTANT(std::size_t, value = A < S ? A : S);
+};
+
+
+template< typename T >
+struct alignment_of_impl
+{
+#if defined(BOOST_MSVC) && (BOOST_MSVC >= 1400)
+ //
+ // With MSVC both the native __alignof operator
+ // and our own logic gets things wrong from time to time :-(
+ // Using a combination of the two seems to make the most of a bad job:
+ //
+ BOOST_STATIC_CONSTANT(std::size_t, value =
+ (::boost::detail::alignment_logic<
+ sizeof(::boost::detail::alignment_of_hack<T>) - sizeof(T),
+ __alignof(T)
+ >::value));
+#elif !defined(BOOST_ALIGNMENT_OF)
+ BOOST_STATIC_CONSTANT(std::size_t, value =
+ (::boost::detail::alignment_logic<
+ sizeof(::boost::detail::alignment_of_hack<T>) - sizeof(T),
+ sizeof(T)
+ >::value));
+#else
+ //
+ // We put this here, rather than in the definition of
+ // alignment_of below, because MSVC's __alignof doesn't
+ // always work in that context for some unexplained reason.
+ // (See type_with_alignment tests for test cases).
+ //
+ BOOST_STATIC_CONSTANT(std::size_t, value = BOOST_ALIGNMENT_OF(T));
+#endif
+};
+
+} // namespace detail
+
+template <class T> struct alignment_of : public integral_constant<std::size_t, ::boost::detail::alignment_of_impl<T>::value>{};
+
+// references have to be treated specially, assume
+// that a reference is just a special pointer:
+template <typename T> struct alignment_of<T&> : public alignment_of<T*>{};
+
+#ifdef __BORLANDC__
+// long double gives an incorrect value of 10 (!)
+// unless we do this...
+struct long_double_wrapper{ long double ld; };
+template<> struct alignment_of<long double> : public alignment_of<long_double_wrapper>{};
+#endif
+
+// void has to be treated specially:
+template<> struct alignment_of<void> : integral_constant<std::size_t, 0>{};
+#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
+template<> struct alignment_of<void const> : integral_constant<std::size_t, 0>{};
+template<> struct alignment_of<void const volatile> : integral_constant<std::size_t, 0>{};
+template<> struct alignment_of<void volatile> : integral_constant<std::size_t, 0>{};
+#endif
+
+} // namespace boost
+
+#if defined(__BORLANDC__) && (__BORLANDC__ < 0x600)
+#pragma option pop
+#endif
+#ifdef BOOST_MSVC
+# pragma warning(pop)
+#endif
+
+#endif // BOOST_TT_ALIGNMENT_OF_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/composite_traits.hpp b/third_party/boost/boost/type_traits/composite_traits.hpp
new file mode 100644
index 0000000..cc394a4
--- /dev/null
+++ b/third_party/boost/boost/type_traits/composite_traits.hpp
@@ -0,0 +1,24 @@
+// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes, Howard
+// Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+//
+// defines traits classes for composite types:
+// is_array, is_pointer, is_reference, is_member_pointer, is_enum, is_union.
+//
+
+#ifndef BOOST_TT_COMPOSITE_TRAITS_HPP_INCLUDED
+#define BOOST_TT_COMPOSITE_TRAITS_HPP_INCLUDED
+
+#include <boost/type_traits/is_array.hpp>
+#include <boost/type_traits/is_enum.hpp>
+#include <boost/type_traits/is_member_pointer.hpp>
+#include <boost/type_traits/is_member_function_pointer.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/type_traits/is_reference.hpp>
+#include <boost/type_traits/is_union.hpp>
+
+#endif // BOOST_TT_COMPOSITE_TRAITS_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/conditional.hpp b/third_party/boost/boost/type_traits/conditional.hpp
new file mode 100644
index 0000000..675d9d5
--- /dev/null
+++ b/third_party/boost/boost/type_traits/conditional.hpp
@@ -0,0 +1,20 @@
+// (C) Copyright John Maddock 2010.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+
+#ifndef BOOST_TT_CONDITIONAL_HPP_INCLUDED
+#define BOOST_TT_CONDITIONAL_HPP_INCLUDED
+
+namespace boost {
+
+template <bool b, class T, class U> struct conditional { typedef T type; };
+template <class T, class U> struct conditional<false, T, U> { typedef U type; };
+
+} // namespace boost
+
+
+#endif // BOOST_TT_CONDITIONAL_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/decay.hpp b/third_party/boost/boost/type_traits/decay.hpp
new file mode 100644
index 0000000..fa1ed9a
--- /dev/null
+++ b/third_party/boost/boost/type_traits/decay.hpp
@@ -0,0 +1,43 @@
+// (C) Copyright John Maddock & Thorsten Ottosen 2005.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+
+#ifndef BOOST_TT_DECAY_HPP_INCLUDED
+#define BOOST_TT_DECAY_HPP_INCLUDED
+
+#include <boost/type_traits/is_array.hpp>
+#include <boost/type_traits/is_function.hpp>
+#include <boost/type_traits/remove_bounds.hpp>
+#include <boost/type_traits/add_pointer.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+
+namespace boost
+{
+
+ namespace detail
+ {
+
+ template <class T, bool Array, bool Function> struct decay_imp { typedef typename remove_cv<T>::type type; };
+ template <class T> struct decay_imp<T, true, false> { typedef typename remove_bounds<T>::type* type; };
+ template <class T> struct decay_imp<T, false, true> { typedef T* type; };
+
+ }
+
+ template< class T >
+ struct decay
+ {
+ private:
+ typedef typename remove_reference<T>::type Ty;
+ public:
+ typedef typename boost::detail::decay_imp<Ty, boost::is_array<Ty>::value, boost::is_function<Ty>::value>::type type;
+ };
+
+} // namespace boost
+
+
+#endif // BOOST_TT_DECAY_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/declval.hpp b/third_party/boost/boost/type_traits/declval.hpp
new file mode 100644
index 0000000..a050012
--- /dev/null
+++ b/third_party/boost/boost/type_traits/declval.hpp
@@ -0,0 +1,44 @@
+// declval.hpp -------------------------------------------------------------//
+
+// Copyright 2010 Vicente J. Botet Escriba
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_TYPE_TRAITS_DECLVAL_HPP_INCLUDED
+#define BOOST_TYPE_TRAITS_DECLVAL_HPP_INCLUDED
+
+#include <boost/config.hpp>
+
+//----------------------------------------------------------------------------//
+
+#include <boost/type_traits/add_rvalue_reference.hpp>
+
+//----------------------------------------------------------------------------//
+// //
+// C++03 implementation of //
+// 20.2.4 Function template declval [declval] //
+// Written by Vicente J. Botet Escriba //
+// //
+// 1 The library provides the function template declval to simplify the
+// definition of expressions which occur as unevaluated operands.
+// 2 Remarks: If this function is used, the program is ill-formed.
+// 3 Remarks: The template parameter T of declval may be an incomplete type.
+// [ Example:
+//
+// template <class To, class From>
+// decltype(static_cast<To>(declval<From>())) convert(From&&);
+//
+// declares a function template convert which only participates in overloading
+// if the type From can be explicitly converted to type To. For another example
+// see class template common_type (20.9.7.6). -end example ]
+//----------------------------------------------------------------------------//
+
+namespace boost {
+
+ template <typename T>
+ typename add_rvalue_reference<T>::type declval() BOOST_NOEXCEPT; // as unevaluated operand
+
+} // namespace boost
+
+#endif // BOOST_TYPE_TRAITS_DECLVAL_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/detail/config.hpp b/third_party/boost/boost/type_traits/detail/config.hpp
new file mode 100644
index 0000000..13ef3c1
--- /dev/null
+++ b/third_party/boost/boost/type_traits/detail/config.hpp
@@ -0,0 +1,70 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_CONFIG_HPP_INCLUDED
+#define BOOST_TT_CONFIG_HPP_INCLUDED
+
+#ifndef BOOST_CONFIG_HPP
+#include <boost/config.hpp>
+#endif
+#include <boost/version.hpp>
+#include <boost/detail/workaround.hpp>
+
+//
+// whenever we have a conversion function with ellipses
+// it needs to be declared __cdecl to suppress compiler
+// warnings from MS and Borland compilers (this *must*
+// appear before we include is_same.hpp below):
+#if defined(BOOST_MSVC) || (defined(__BORLANDC__) && !defined(BOOST_DISABLE_WIN32))
+# define BOOST_TT_DECL __cdecl
+#else
+# define BOOST_TT_DECL /**/
+#endif
+
+# if (BOOST_WORKAROUND(__MWERKS__, < 0x3000) \
+ || BOOST_WORKAROUND(__IBMCPP__, < 600 ) \
+ || BOOST_WORKAROUND(__BORLANDC__, < 0x5A0) \
+ || defined(__ghs) \
+ || BOOST_WORKAROUND(__HP_aCC, < 60700) \
+ || BOOST_WORKAROUND(MPW_CPLUS, BOOST_TESTED_AT(0x890)) \
+ || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x580))) \
+ && defined(BOOST_NO_IS_ABSTRACT)
+
+# define BOOST_TT_NO_CONFORMING_IS_CLASS_IMPLEMENTATION 1
+
+#endif
+
+#ifndef BOOST_TT_NO_CONFORMING_IS_CLASS_IMPLEMENTATION
+# define BOOST_TT_HAS_CONFORMING_IS_CLASS_IMPLEMENTATION 1
+#endif
+
+//
+// define BOOST_TT_TEST_MS_FUNC_SIGS
+// when we want to test __stdcall etc function types with is_function etc
+// (Note, does not work with Borland, even though it does support __stdcall etc):
+//
+#if defined(_MSC_EXTENSIONS) && !defined(__BORLANDC__)
+# define BOOST_TT_TEST_MS_FUNC_SIGS
+#endif
+
+//
+// define BOOST_TT_NO_CV_FUNC_TEST
+// if tests for cv-qualified member functions don't
+// work in is_member_function_pointer
+//
+#if BOOST_WORKAROUND(__MWERKS__, < 0x3000) || BOOST_WORKAROUND(__IBMCPP__, <= 600)
+# define BOOST_TT_NO_CV_FUNC_TEST
+#endif
+
+//
+// Macros that have been deprecated, defined here for backwards compatibility:
+//
+#define BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(x)
+#define BOOST_TT_BROKEN_COMPILER_SPEC(x)
+
+#endif // BOOST_TT_CONFIG_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/detail/has_binary_operator.hpp b/third_party/boost/boost/type_traits/detail/has_binary_operator.hpp
new file mode 100644
index 0000000..039a6bb
--- /dev/null
+++ b/third_party/boost/boost/type_traits/detail/has_binary_operator.hpp
@@ -0,0 +1,222 @@
+// (C) Copyright 2009-2011 Frederic Bron, Robert Stewart, Steven Watanabe & Roman Perepelitsa.
+//
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#include <boost/config.hpp>
+#include <boost/type_traits/detail/yes_no_type.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/is_fundamental.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/is_void.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_pointer.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+
+// cannot include this header without getting warnings of the kind:
+// gcc:
+// warning: value computed is not used
+// warning: comparison between signed and unsigned integer expressions
+// msvc:
+// warning C4018: '<' : signed/unsigned mismatch
+// warning C4244: '+=' : conversion from 'double' to 'char', possible loss of data
+// warning C4547: '*' : operator before comma has no effect; expected operator with side-effect
+// warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)
+// warning C4804: '<' : unsafe use of type 'bool' in operation
+// warning C4805: '==' : unsafe mix of type 'bool' and type 'char' in operation
+// cannot find another implementation -> declared as system header to suppress these warnings.
+#if defined(__GNUC__)
+# pragma GCC system_header
+#elif defined(BOOST_MSVC)
+# pragma warning ( push )
+# pragma warning ( disable : 4018 4244 4547 4800 4804 4805 4913)
+# if BOOST_WORKAROUND(BOOST_MSVC_FULL_VER, >= 140050000)
+# pragma warning ( disable : 6334)
+# endif
+#endif
+
+namespace boost {
+namespace detail {
+
+// This namespace ensures that argument-dependent name lookup does not mess things up.
+namespace BOOST_JOIN(BOOST_TT_TRAIT_NAME,_impl) {
+
+// 1. a function to have an instance of type T without requiring T to be default
+// constructible
+template <typename T> T &make();
+
+
+// 2. we provide our operator definition for types that do not have one already
+
+// a type returned from operator BOOST_TT_TRAIT_OP when no such operator is
+// found in the type's own namespace (our own operator is used) so that we have
+// a means to know that our operator was used
+struct no_operator { };
+
+// this class allows implicit conversions and makes the following operator
+// definition less-preferred than any other such operators that might be found
+// via argument-dependent name lookup
+struct any { template <class T> any(T const&); };
+
+// when operator BOOST_TT_TRAIT_OP is not available, this one is used
+no_operator operator BOOST_TT_TRAIT_OP (const any&, const any&);
+
+
+// 3. checks if the operator returns void or not
+// conditions: Lhs!=void and Rhs!=void
+
+// we first redefine "operator," so that we have no compilation error if
+// operator BOOST_TT_TRAIT_OP returns void and we can use the return type of
+// (lhs BOOST_TT_TRAIT_OP rhs, returns_void_t()) to deduce if
+// operator BOOST_TT_TRAIT_OP returns void or not:
+// - operator BOOST_TT_TRAIT_OP returns void -> (lhs BOOST_TT_TRAIT_OP rhs, returns_void_t()) returns returns_void_t
+// - operator BOOST_TT_TRAIT_OP returns !=void -> (lhs BOOST_TT_TRAIT_OP rhs, returns_void_t()) returns int
+struct returns_void_t { };
+template <typename T> int operator,(const T&, returns_void_t);
+template <typename T> int operator,(const volatile T&, returns_void_t);
+
+// this intermediate trait has member value of type bool:
+// - value==true -> operator BOOST_TT_TRAIT_OP returns void
+// - value==false -> operator BOOST_TT_TRAIT_OP does not return void
+template < typename Lhs, typename Rhs >
+struct operator_returns_void {
+ // overloads of function returns_void make the difference
+ // yes_type and no_type have different size by construction
+ static ::boost::type_traits::yes_type returns_void(returns_void_t);
+ static ::boost::type_traits::no_type returns_void(int);
+ BOOST_STATIC_CONSTANT(bool, value = (sizeof(::boost::type_traits::yes_type)==sizeof(returns_void((make<Lhs>() BOOST_TT_TRAIT_OP make<Rhs>(),returns_void_t())))));
+};
+
+
+// 4. checks if the return type is Ret or Ret==dont_care
+// conditions: Lhs!=void and Rhs!=void
+
+struct dont_care { };
+
+template < typename Lhs, typename Rhs, typename Ret, bool Returns_void >
+struct operator_returns_Ret;
+
+template < typename Lhs, typename Rhs >
+struct operator_returns_Ret < Lhs, Rhs, dont_care, true > {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+};
+
+template < typename Lhs, typename Rhs >
+struct operator_returns_Ret < Lhs, Rhs, dont_care, false > {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+};
+
+template < typename Lhs, typename Rhs >
+struct operator_returns_Ret < Lhs, Rhs, void, true > {
+ BOOST_STATIC_CONSTANT(bool, value = true);
+};
+
+template < typename Lhs, typename Rhs >
+struct operator_returns_Ret < Lhs, Rhs, void, false > {
+ BOOST_STATIC_CONSTANT(bool, value = false);
+};
+
+template < typename Lhs, typename Rhs, typename Ret >
+struct operator_returns_Ret < Lhs, Rhs, Ret, true > {
+ BOOST_STATIC_CONSTANT(bool, value = false);
+};
+
+// otherwise checks if it is convertible to Ret using the sizeof trick
+// based on overload resolution
+// condition: Ret!=void and Ret!=dont_care and the operator does not return void
+template < typename Lhs, typename Rhs, typename Ret >
+struct operator_returns_Ret < Lhs, Rhs, Ret, false > {
+ static ::boost::type_traits::yes_type is_convertible_to_Ret(Ret); // this version is preferred for types convertible to Ret
+ static ::boost::type_traits::no_type is_convertible_to_Ret(...); // this version is used otherwise
+
+ BOOST_STATIC_CONSTANT(bool, value = (sizeof(is_convertible_to_Ret(make<Lhs>() BOOST_TT_TRAIT_OP make<Rhs>()))==sizeof(::boost::type_traits::yes_type)));
+};
+
+
+// 5. checks for operator existence
+// condition: Lhs!=void and Rhs!=void
+
+// checks if our definition of operator BOOST_TT_TRAIT_OP is used or an other
+// existing one;
+// this is done with redefinition of "operator," that returns no_operator or has_operator
+struct has_operator { };
+no_operator operator,(no_operator, has_operator);
+
+template < typename Lhs, typename Rhs >
+struct operator_exists {
+ static ::boost::type_traits::yes_type s_check(has_operator); // this version is preferred when operator exists
+ static ::boost::type_traits::no_type s_check(no_operator); // this version is used otherwise
+
+ BOOST_STATIC_CONSTANT(bool, value = (sizeof(s_check(((make<Lhs>() BOOST_TT_TRAIT_OP make<Rhs>()),make<has_operator>())))==sizeof(::boost::type_traits::yes_type)));
+};
+
+
+// 6. main trait: to avoid any compilation error, this class behaves
+// differently when operator BOOST_TT_TRAIT_OP(Lhs, Rhs) is forbidden by the
+// standard.
+// Forbidden_if is a bool that is:
+// - true when the operator BOOST_TT_TRAIT_OP(Lhs, Rhs) is forbidden by the standard
+// (would yield compilation error if used)
+// - false otherwise
+template < typename Lhs, typename Rhs, typename Ret, bool Forbidden_if >
+struct trait_impl1;
+
+template < typename Lhs, typename Rhs, typename Ret >
+struct trait_impl1 < Lhs, Rhs, Ret, true > {
+ BOOST_STATIC_CONSTANT(bool, value = false);
+};
+
+template < typename Lhs, typename Rhs, typename Ret >
+struct trait_impl1 < Lhs, Rhs, Ret, false > {
+ BOOST_STATIC_CONSTANT(bool,
+ value = (operator_exists < Lhs, Rhs >::value && operator_returns_Ret < Lhs, Rhs, Ret, operator_returns_void < Lhs, Rhs >::value >::value));
+};
+
+// some specializations needs to be declared for the special void case
+template < typename Rhs, typename Ret >
+struct trait_impl1 < void, Rhs, Ret, false > {
+ BOOST_STATIC_CONSTANT(bool, value = false);
+};
+
+template < typename Lhs, typename Ret >
+struct trait_impl1 < Lhs, void, Ret, false > {
+ BOOST_STATIC_CONSTANT(bool, value = false);
+};
+
+template < typename Ret >
+struct trait_impl1 < void, void, Ret, false > {
+ BOOST_STATIC_CONSTANT(bool, value = false);
+};
+
+// defines some typedef for convenience
+template < typename Lhs, typename Rhs, typename Ret >
+struct trait_impl {
+ typedef typename ::boost::remove_reference<Lhs>::type Lhs_noref;
+ typedef typename ::boost::remove_reference<Rhs>::type Rhs_noref;
+ typedef typename ::boost::remove_cv<Lhs_noref>::type Lhs_nocv;
+ typedef typename ::boost::remove_cv<Rhs_noref>::type Rhs_nocv;
+ typedef typename ::boost::remove_cv< typename ::boost::remove_reference< typename ::boost::remove_pointer<Lhs_noref>::type >::type >::type Lhs_noptr;
+ typedef typename ::boost::remove_cv< typename ::boost::remove_reference< typename ::boost::remove_pointer<Rhs_noref>::type >::type >::type Rhs_noptr;
+ BOOST_STATIC_CONSTANT(bool, value = (trait_impl1 < Lhs_noref, Rhs_noref, Ret, BOOST_TT_FORBIDDEN_IF >::value));
+};
+
+} // namespace impl
+} // namespace detail
+
+// this is the accessible definition of the trait to end user
+template <class Lhs, class Rhs=Lhs, class Ret=::boost::detail::BOOST_JOIN(BOOST_TT_TRAIT_NAME,_impl)::dont_care>
+struct BOOST_TT_TRAIT_NAME : public integral_constant<bool, (::boost::detail::BOOST_JOIN(BOOST_TT_TRAIT_NAME, _impl)::trait_impl < Lhs, Rhs, Ret >::value)>{};
+
+} // namespace boost
+
+#if defined(BOOST_MSVC)
+# pragma warning ( pop )
+#endif
diff --git a/third_party/boost/boost/type_traits/detail/is_function_ptr_helper.hpp b/third_party/boost/boost/type_traits/detail/is_function_ptr_helper.hpp
new file mode 100644
index 0000000..3538e40
--- /dev/null
+++ b/third_party/boost/boost/type_traits/detail/is_function_ptr_helper.hpp
@@ -0,0 +1,176 @@
+
+// Copyright 2000 John Maddock (john@johnmaddock.co.uk)
+// Copyright 2002 Aleksey Gurtovoy (agurtovoy@meta-comm.com)
+//
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#if !defined(BOOST_PP_IS_ITERATING)
+
+///// header body
+
+#ifndef BOOST_TT_DETAIL_IS_FUNCTION_PTR_HELPER_HPP_INCLUDED
+#define BOOST_TT_DETAIL_IS_FUNCTION_PTR_HELPER_HPP_INCLUDED
+
+#if defined(BOOST_TT_PREPROCESSING_MODE)
+//
+// Hide these #include from dependency analysers as
+// these are required in maintenance mode only:
+//
+#define PP1 <boost/preprocessor/iterate.hpp>
+#include PP1
+#undef PP1
+#define PP1 <boost/preprocessor/enum_params.hpp>
+#include PP1
+#undef PP1
+#define PP1 <boost/preprocessor/comma_if.hpp>
+#include PP1
+#undef PP1
+#endif
+
+namespace boost {
+namespace type_traits {
+
+template <class R>
+struct is_function_ptr_helper
+{
+ BOOST_STATIC_CONSTANT(bool, value = false);
+};
+
+#if !defined(BOOST_TT_PREPROCESSING_MODE)
+// preprocessor-generated part, don't edit by hand!
+
+template <class R >
+struct is_function_ptr_helper<R (*)()> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R >
+struct is_function_ptr_helper<R (*)( ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0>
+struct is_function_ptr_helper<R (*)( T0)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0>
+struct is_function_ptr_helper<R (*)( T0 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1>
+struct is_function_ptr_helper<R (*)( T0 , T1)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1>
+struct is_function_ptr_helper<R (*)( T0 , T1 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22 , class T23>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22 , class T23>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22 , class T23 , class T24>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22 , class T23 , class T24>
+struct is_function_ptr_helper<R (*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+#else
+
+#undef BOOST_STATIC_CONSTANT
+#define BOOST_PP_ITERATION_PARAMS_1 \
+ (3, (0, 25, "boost/type_traits/detail/is_function_ptr_helper.hpp"))
+#include BOOST_PP_ITERATE()
+
+#endif // BOOST_TT_PREPROCESSING_MODE
+
+} // namespace type_traits
+} // namespace boost
+
+#endif // BOOST_TT_DETAIL_IS_FUNCTION_PTR_HELPER_HPP_INCLUDED
+
+///// iteration
+
+#else
+#define BOOST_PP_COUNTER BOOST_PP_FRAME_ITERATION(1)
+
+template <class R BOOST_PP_COMMA_IF(BOOST_PP_COUNTER) BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,class T)>
+struct is_function_ptr_helper<R (*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,T))> { BOOST_STATIC_CONSTANT(bool, value = true); };
+@#ifndef BOOST_TT_NO_ELLIPSIS_IN_FUNC_TESTING
+template <class R BOOST_PP_COMMA_IF(BOOST_PP_COUNTER) BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,class T)>
+struct is_function_ptr_helper<R (*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,T) ...)> { BOOST_STATIC_CONSTANT(bool, value = true); };
+@#endif
+#undef BOOST_PP_COUNTER
+#endif // BOOST_PP_IS_ITERATING
diff --git a/third_party/boost/boost/type_traits/detail/is_mem_fun_pointer_impl.hpp b/third_party/boost/boost/type_traits/detail/is_mem_fun_pointer_impl.hpp
new file mode 100644
index 0000000..4dfb9c5
--- /dev/null
+++ b/third_party/boost/boost/type_traits/detail/is_mem_fun_pointer_impl.hpp
@@ -0,0 +1,722 @@
+
+// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes,
+// Aleksey Gurtovoy, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#if !defined(BOOST_PP_IS_ITERATING)
+
+///// header body
+
+#ifndef BOOST_TT_DETAIL_IS_MEM_FUN_POINTER_IMPL_HPP_INCLUDED
+#define BOOST_TT_DETAIL_IS_MEM_FUN_POINTER_IMPL_HPP_INCLUDED
+
+#include <boost/config.hpp>
+
+#if defined(BOOST_TT_PREPROCESSING_MODE)
+//
+// Maintenance mode, hide include dependencies
+// from trackers:
+//
+#define PPI <boost/preprocessor/iterate.hpp>
+#include PPI
+#undef PPI
+#define PPI <boost/preprocessor/enum_params.hpp>
+#include PPI
+#undef PPI
+#define PPI <boost/preprocessor/comma_if.hpp>
+#include PPI
+#undef PPI
+#endif
+
+namespace boost {
+namespace type_traits {
+
+template <typename T>
+struct is_mem_fun_pointer_impl
+{
+ BOOST_STATIC_CONSTANT(bool, value = false);
+};
+
+#if !defined(BOOST_TT_PREPROCESSING_MODE)
+// pre-processed code, don't edit, try GNU cpp with
+// cpp -I../../../ -DBOOST_TT_PREPROCESSING_MODE -x c++ -P filename
+
+template <class R, class T >
+struct is_mem_fun_pointer_impl<R (T::*)() > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T >
+struct is_mem_fun_pointer_impl<R (T::*)( ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T >
+struct is_mem_fun_pointer_impl<R (T::*)() const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T >
+struct is_mem_fun_pointer_impl<R (T::*)() volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T >
+struct is_mem_fun_pointer_impl<R (T::*)() const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T >
+struct is_mem_fun_pointer_impl<R (T::*)( ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T >
+struct is_mem_fun_pointer_impl<R (T::*)( ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T >
+struct is_mem_fun_pointer_impl<R (T::*)( ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0>
+struct is_mem_fun_pointer_impl<R (T::*)( T0) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0>
+struct is_mem_fun_pointer_impl<R (T::*)( T0) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0>
+struct is_mem_fun_pointer_impl<R (T::*)( T0) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0>
+struct is_mem_fun_pointer_impl<R (T::*)( T0) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0 , class T1>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0 , class T1>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0 , class T1>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0 , class T1 , class T2>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0 , class T1 , class T2>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0 , class T1 , class T2>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0 , class T1 , class T2 , class T3>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0 , class T1 , class T2 , class T3>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0 , class T1 , class T2 , class T3>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22 , class T23>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22 , class T23>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22 , class T23>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22 , class T23>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22 , class T23>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22 , class T23>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22 , class T23>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22 , class T23>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22 , class T23 , class T24>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22 , class T23 , class T24>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22 , class T23 , class T24>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22 , class T23 , class T24>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22 , class T23 , class T24>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22 , class T23 , class T24>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22 , class T23 , class T24>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T , class T0 , class T1 , class T2 , class T3 , class T4 , class T5 , class T6 , class T7 , class T8 , class T9 , class T10 , class T11 , class T12 , class T13 , class T14 , class T15 , class T16 , class T17 , class T18 , class T19 , class T20 , class T21 , class T22 , class T23 , class T24>
+struct is_mem_fun_pointer_impl<R (T::*)( T0 , T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T11 , T12 , T13 , T14 , T15 , T16 , T17 , T18 , T19 , T20 , T21 , T22 , T23 , T24 ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+#endif
+
+#else
+
+#undef BOOST_STATIC_CONSTANT
+#define BOOST_PP_ITERATION_PARAMS_1 \
+ (3, (0, 25, "boost/type_traits/detail/is_mem_fun_pointer_impl.hpp"))
+#include BOOST_PP_ITERATE()
+
+#endif // BOOST_TT_PREPROCESSING_MODE
+
+} // namespace type_traits
+} // namespace boost
+
+#endif // BOOST_TT_DETAIL_IS_MEM_FUN_POINTER_IMPL_HPP_INCLUDED
+
+///// iteration
+
+#else
+#define BOOST_PP_COUNTER BOOST_PP_FRAME_ITERATION(1)
+
+template <class R, class T BOOST_PP_COMMA_IF(BOOST_PP_COUNTER) BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,class T)>
+struct is_mem_fun_pointer_impl<R (T::*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,T)) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+@#ifndef BOOST_TT_NO_ELLIPSIS_IN_FUNC_TESTING
+template <class R, class T BOOST_PP_COMMA_IF(BOOST_PP_COUNTER) BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,class T)>
+struct is_mem_fun_pointer_impl<R (T::*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,T) ...) > { BOOST_STATIC_CONSTANT(bool, value = true); };
+@#endif
+
+@#if !defined(BOOST_TT_NO_CV_FUNC_TEST)
+template <class R, class T BOOST_PP_COMMA_IF(BOOST_PP_COUNTER) BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,class T)>
+struct is_mem_fun_pointer_impl<R (T::*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,T)) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T BOOST_PP_COMMA_IF(BOOST_PP_COUNTER) BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,class T)>
+struct is_mem_fun_pointer_impl<R (T::*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,T)) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T BOOST_PP_COMMA_IF(BOOST_PP_COUNTER) BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,class T)>
+struct is_mem_fun_pointer_impl<R (T::*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,T)) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+@#ifndef BOOST_TT_NO_ELLIPSIS_IN_FUNC_TESTING
+template <class R, class T BOOST_PP_COMMA_IF(BOOST_PP_COUNTER) BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,class T)>
+struct is_mem_fun_pointer_impl<R (T::*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,T) ...) const > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T BOOST_PP_COMMA_IF(BOOST_PP_COUNTER) BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,class T)>
+struct is_mem_fun_pointer_impl<R (T::*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,T) ...) volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+
+template <class R, class T BOOST_PP_COMMA_IF(BOOST_PP_COUNTER) BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,class T)>
+struct is_mem_fun_pointer_impl<R (T::*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_COUNTER,T) ...) const volatile > { BOOST_STATIC_CONSTANT(bool, value = true); };
+@#endif
+@#endif
+
+#undef BOOST_PP_COUNTER
+#endif // BOOST_PP_IS_ITERATING
diff --git a/third_party/boost/boost/type_traits/detail/yes_no_type.hpp b/third_party/boost/boost/type_traits/detail/yes_no_type.hpp
new file mode 100644
index 0000000..f583730
--- /dev/null
+++ b/third_party/boost/boost/type_traits/detail/yes_no_type.hpp
@@ -0,0 +1,26 @@
+
+// (C) Copyright John Maddock and Steve Cleary 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+//
+// macros and helpers for working with integral-constant-expressions.
+
+#ifndef BOOST_TT_DETAIL_YES_NO_TYPE_HPP_INCLUDED
+#define BOOST_TT_DETAIL_YES_NO_TYPE_HPP_INCLUDED
+
+namespace boost {
+namespace type_traits {
+
+typedef char yes_type;
+struct no_type
+{
+ char padding[8];
+};
+
+} // namespace type_traits
+} // namespace boost
+
+#endif // BOOST_TT_DETAIL_YES_NO_TYPE_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/function_traits.hpp b/third_party/boost/boost/type_traits/function_traits.hpp
new file mode 100644
index 0000000..a01d372
--- /dev/null
+++ b/third_party/boost/boost/type_traits/function_traits.hpp
@@ -0,0 +1,174 @@
+
+// Copyright 2000 John Maddock (john@johnmaddock.co.uk)
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_FUNCTION_TRAITS_HPP_INCLUDED
+#define BOOST_TT_FUNCTION_TRAITS_HPP_INCLUDED
+
+#include <boost/config.hpp>
+#include <boost/type_traits/is_function.hpp>
+#include <boost/type_traits/add_pointer.hpp>
+
+namespace boost {
+
+namespace detail {
+
+template<typename Function> struct function_traits_helper;
+
+template<typename R>
+struct function_traits_helper<R (*)(void)>
+{
+ BOOST_STATIC_CONSTANT(unsigned, arity = 0);
+ typedef R result_type;
+};
+
+template<typename R, typename T1>
+struct function_traits_helper<R (*)(T1)>
+{
+ BOOST_STATIC_CONSTANT(unsigned, arity = 1);
+ typedef R result_type;
+ typedef T1 arg1_type;
+ typedef T1 argument_type;
+};
+
+template<typename R, typename T1, typename T2>
+struct function_traits_helper<R (*)(T1, T2)>
+{
+ BOOST_STATIC_CONSTANT(unsigned, arity = 2);
+ typedef R result_type;
+ typedef T1 arg1_type;
+ typedef T2 arg2_type;
+ typedef T1 first_argument_type;
+ typedef T2 second_argument_type;
+};
+
+template<typename R, typename T1, typename T2, typename T3>
+struct function_traits_helper<R (*)(T1, T2, T3)>
+{
+ BOOST_STATIC_CONSTANT(unsigned, arity = 3);
+ typedef R result_type;
+ typedef T1 arg1_type;
+ typedef T2 arg2_type;
+ typedef T3 arg3_type;
+};
+
+template<typename R, typename T1, typename T2, typename T3, typename T4>
+struct function_traits_helper<R (*)(T1, T2, T3, T4)>
+{
+ BOOST_STATIC_CONSTANT(unsigned, arity = 4);
+ typedef R result_type;
+ typedef T1 arg1_type;
+ typedef T2 arg2_type;
+ typedef T3 arg3_type;
+ typedef T4 arg4_type;
+};
+
+template<typename R, typename T1, typename T2, typename T3, typename T4,
+ typename T5>
+struct function_traits_helper<R (*)(T1, T2, T3, T4, T5)>
+{
+ BOOST_STATIC_CONSTANT(unsigned, arity = 5);
+ typedef R result_type;
+ typedef T1 arg1_type;
+ typedef T2 arg2_type;
+ typedef T3 arg3_type;
+ typedef T4 arg4_type;
+ typedef T5 arg5_type;
+};
+
+template<typename R, typename T1, typename T2, typename T3, typename T4,
+ typename T5, typename T6>
+struct function_traits_helper<R (*)(T1, T2, T3, T4, T5, T6)>
+{
+ BOOST_STATIC_CONSTANT(unsigned, arity = 6);
+ typedef R result_type;
+ typedef T1 arg1_type;
+ typedef T2 arg2_type;
+ typedef T3 arg3_type;
+ typedef T4 arg4_type;
+ typedef T5 arg5_type;
+ typedef T6 arg6_type;
+};
+
+template<typename R, typename T1, typename T2, typename T3, typename T4,
+ typename T5, typename T6, typename T7>
+struct function_traits_helper<R (*)(T1, T2, T3, T4, T5, T6, T7)>
+{
+ BOOST_STATIC_CONSTANT(unsigned, arity = 7);
+ typedef R result_type;
+ typedef T1 arg1_type;
+ typedef T2 arg2_type;
+ typedef T3 arg3_type;
+ typedef T4 arg4_type;
+ typedef T5 arg5_type;
+ typedef T6 arg6_type;
+ typedef T7 arg7_type;
+};
+
+template<typename R, typename T1, typename T2, typename T3, typename T4,
+ typename T5, typename T6, typename T7, typename T8>
+struct function_traits_helper<R (*)(T1, T2, T3, T4, T5, T6, T7, T8)>
+{
+ BOOST_STATIC_CONSTANT(unsigned, arity = 8);
+ typedef R result_type;
+ typedef T1 arg1_type;
+ typedef T2 arg2_type;
+ typedef T3 arg3_type;
+ typedef T4 arg4_type;
+ typedef T5 arg5_type;
+ typedef T6 arg6_type;
+ typedef T7 arg7_type;
+ typedef T8 arg8_type;
+};
+
+template<typename R, typename T1, typename T2, typename T3, typename T4,
+ typename T5, typename T6, typename T7, typename T8, typename T9>
+struct function_traits_helper<R (*)(T1, T2, T3, T4, T5, T6, T7, T8, T9)>
+{
+ BOOST_STATIC_CONSTANT(unsigned, arity = 9);
+ typedef R result_type;
+ typedef T1 arg1_type;
+ typedef T2 arg2_type;
+ typedef T3 arg3_type;
+ typedef T4 arg4_type;
+ typedef T5 arg5_type;
+ typedef T6 arg6_type;
+ typedef T7 arg7_type;
+ typedef T8 arg8_type;
+ typedef T9 arg9_type;
+};
+
+template<typename R, typename T1, typename T2, typename T3, typename T4,
+ typename T5, typename T6, typename T7, typename T8, typename T9,
+ typename T10>
+struct function_traits_helper<R (*)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)>
+{
+ BOOST_STATIC_CONSTANT(unsigned, arity = 10);
+ typedef R result_type;
+ typedef T1 arg1_type;
+ typedef T2 arg2_type;
+ typedef T3 arg3_type;
+ typedef T4 arg4_type;
+ typedef T5 arg5_type;
+ typedef T6 arg6_type;
+ typedef T7 arg7_type;
+ typedef T8 arg8_type;
+ typedef T9 arg9_type;
+ typedef T10 arg10_type;
+};
+
+} // end namespace detail
+
+template<typename Function>
+struct function_traits :
+ public boost::detail::function_traits_helper<typename boost::add_pointer<Function>::type>
+{
+};
+
+}
+
+#endif // BOOST_TT_FUNCTION_TRAITS_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/has_minus.hpp b/third_party/boost/boost/type_traits/has_minus.hpp
new file mode 100644
index 0000000..5e13c16
--- /dev/null
+++ b/third_party/boost/boost/type_traits/has_minus.hpp
@@ -0,0 +1,60 @@
+// (C) Copyright 2009-2011 Frederic Bron.
+//
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_HAS_MINUS_HPP_INCLUDED
+#define BOOST_TT_HAS_MINUS_HPP_INCLUDED
+
+#define BOOST_TT_TRAIT_NAME has_minus
+#define BOOST_TT_TRAIT_OP -
+#define BOOST_TT_FORBIDDEN_IF\
+ (\
+ /* Lhs==pointer and Rhs==fundamental and Rhs!=integral */\
+ (\
+ ::boost::is_pointer< Lhs_noref >::value && \
+ ::boost::is_fundamental< Rhs_nocv >::value && \
+ (! ::boost::is_integral< Rhs_noref >::value )\
+ ) || \
+ /* Lhs==void* and (Rhs==fundamental or Rhs==pointer) */\
+ (\
+ ::boost::is_pointer< Lhs_noref >::value && \
+ ::boost::is_void< Lhs_noptr >::value && \
+ ( \
+ ::boost::is_fundamental< Rhs_nocv >::value || \
+ ::boost::is_pointer< Rhs_noref >::value\
+ )\
+ ) || \
+ /* Rhs==void* and (Lhs==fundamental or Lhs==pointer) */\
+ (\
+ ::boost::is_pointer< Rhs_noref >::value && \
+ ::boost::is_void< Rhs_noptr >::value && \
+ (\
+ ::boost::is_fundamental< Lhs_nocv >::value || \
+ ::boost::is_pointer< Lhs_noref >::value\
+ )\
+ ) ||\
+ /* Lhs=fundamental and Rhs=pointer */\
+ (\
+ ::boost::is_fundamental< Lhs_nocv >::value && \
+ ::boost::is_pointer< Rhs_noref >::value\
+ ) ||\
+ /* two different pointers */\
+ (\
+ ::boost::is_pointer< Lhs_noref >::value && \
+ ::boost::is_pointer< Rhs_noref >::value && \
+ (! ::boost::is_same< Lhs_nocv, Rhs_nocv >::value )\
+ )\
+ )
+
+
+#include <boost/type_traits/detail/has_binary_operator.hpp>
+
+#undef BOOST_TT_TRAIT_NAME
+#undef BOOST_TT_TRAIT_OP
+#undef BOOST_TT_FORBIDDEN_IF
+
+#endif
diff --git a/third_party/boost/boost/type_traits/has_minus_assign.hpp b/third_party/boost/boost/type_traits/has_minus_assign.hpp
new file mode 100644
index 0000000..b53474e
--- /dev/null
+++ b/third_party/boost/boost/type_traits/has_minus_assign.hpp
@@ -0,0 +1,65 @@
+// (C) Copyright 2009-2011 Frederic Bron.
+//
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_HAS_MINUS_ASSIGN_HPP_INCLUDED
+#define BOOST_TT_HAS_MINUS_ASSIGN_HPP_INCLUDED
+
+#define BOOST_TT_TRAIT_NAME has_minus_assign
+#define BOOST_TT_TRAIT_OP -=
+#define BOOST_TT_FORBIDDEN_IF\
+ (\
+ /* Lhs==pointer and Rhs==fundamental and Rhs!=integral */\
+ (\
+ ::boost::is_pointer< Lhs_noref >::value && \
+ ::boost::is_fundamental< Rhs_nocv >::value && \
+ (! ::boost::is_integral< Rhs_noref >::value )\
+ ) || \
+ /* Lhs==void* and Rhs==fundamental */\
+ (\
+ ::boost::is_pointer< Lhs_noref >::value && \
+ ::boost::is_void< Lhs_noptr >::value && \
+ ::boost::is_fundamental< Rhs_nocv >::value\
+ ) || \
+ /* Rhs==void* and Lhs==fundamental */\
+ (\
+ ::boost::is_pointer< Rhs_noref >::value && \
+ ::boost::is_void< Rhs_noptr >::value && \
+ ::boost::is_fundamental< Lhs_nocv >::value\
+ ) || \
+ /* Lhs=fundamental and Rhs=pointer */\
+ (\
+ ::boost::is_fundamental< Lhs_nocv >::value && \
+ ::boost::is_pointer< Rhs_noref >::value\
+ ) || \
+ /* Lhs==pointer and Rhs==pointer */\
+ (\
+ ::boost::is_pointer< Lhs_noref >::value && \
+ ::boost::is_pointer< Rhs_noref >::value\
+ ) || \
+ /* (Lhs==fundamental or Lhs==pointer) and (Rhs==fundamental or Rhs==pointer) and (Lhs==const) */\
+ (\
+ (\
+ ::boost::is_fundamental< Lhs_nocv >::value || \
+ ::boost::is_pointer< Lhs_noref >::value\
+ ) && \
+ (\
+ ::boost::is_fundamental< Rhs_nocv >::value || \
+ ::boost::is_pointer< Rhs_noref >::value\
+ ) && \
+ ::boost::is_const< Lhs_noref >::value\
+ )\
+ )
+
+
+#include <boost/type_traits/detail/has_binary_operator.hpp>
+
+#undef BOOST_TT_TRAIT_NAME
+#undef BOOST_TT_TRAIT_OP
+#undef BOOST_TT_FORBIDDEN_IF
+
+#endif
diff --git a/third_party/boost/boost/type_traits/has_nothrow_assign.hpp b/third_party/boost/boost/type_traits/has_nothrow_assign.hpp
new file mode 100644
index 0000000..8d82230
--- /dev/null
+++ b/third_party/boost/boost/type_traits/has_nothrow_assign.hpp
@@ -0,0 +1,83 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_HAS_NOTHROW_ASSIGN_HPP_INCLUDED
+#define BOOST_TT_HAS_NOTHROW_ASSIGN_HPP_INCLUDED
+
+#include <boost/type_traits/integral_constant.hpp>
+#include <boost/type_traits/intrinsics.hpp>
+
+#if !defined(BOOST_HAS_NOTHROW_ASSIGN) || defined(BOOST_MSVC) || defined(BOOST_INTEL)
+#include <boost/type_traits/has_trivial_assign.hpp>
+#if !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+#include <boost/type_traits/declval.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/is_volatile.hpp>
+#include <boost/type_traits/is_reference.hpp>
+#include <boost/type_traits/is_assignable.hpp>
+#include <boost/type_traits/add_reference.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#endif
+#endif
+#if defined(__GNUC__) || defined(__SUNPRO_CC)
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/is_volatile.hpp>
+#include <boost/type_traits/is_assignable.hpp>
+#include <boost/type_traits/is_array.hpp>
+#ifdef BOOST_INTEL
+#include <boost/type_traits/is_pod.hpp>
+#endif
+#endif
+
+namespace boost {
+
+#if !defined(BOOST_HAS_NOTHROW_ASSIGN) && !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+ namespace detail
+ {
+ template <class T, bool b1, bool b2> struct has_nothrow_assign_imp{ static const bool value = false; };
+ template <class T> struct has_nothrow_assign_imp<T, false, true>{ static const bool value = noexcept(boost::declval<typename add_reference<T>::type>() = boost::declval<typename add_reference<T const>::type>()); };
+ template <class T, std::size_t N> struct has_nothrow_assign_imp<T[N], false, true>{ static const bool value = has_nothrow_assign_imp<T, false, true>::value; };
+ template <class T> struct has_nothrow_assign_imp<T[], false, true>{ static const bool value = has_nothrow_assign_imp<T, false, true>::value; };
+ }
+
+#endif
+
+ template <class T>
+ struct has_nothrow_assign : public integral_constant < bool,
+#ifndef BOOST_HAS_NOTHROW_ASSIGN
+#if !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ // Portable C++11 version:
+ detail::has_nothrow_assign_imp<T,
+ (is_const<typename remove_reference<T>::type>::value || is_volatile<typename remove_reference<T>::type>::value || is_reference<T>::value),
+ is_assignable<typename add_reference<T>::type, typename add_reference<const T>::type>::value
+ >::value
+#else
+ ::boost::has_trivial_assign<T>::value
+#endif
+#else
+ BOOST_HAS_NOTHROW_ASSIGN(T)
+#endif
+ > {};
+
+template <class T, std::size_t N> struct has_nothrow_assign <T[N]> : public has_nothrow_assign<T> {};
+template <> struct has_nothrow_assign<void> : public false_type{};
+template <class T> struct has_nothrow_assign<T volatile> : public false_type{};
+template <class T> struct has_nothrow_assign<T&> : public false_type{};
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+template <class T> struct has_nothrow_assign<T&&> : public false_type{};
+#endif
+#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
+template <> struct has_nothrow_assign<void const> : public false_type{};
+template <> struct has_nothrow_assign<void const volatile> : public false_type{};
+template <> struct has_nothrow_assign<void volatile> : public false_type{};
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TT_HAS_NOTHROW_ASSIGN_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/has_nothrow_constructor.hpp b/third_party/boost/boost/type_traits/has_nothrow_constructor.hpp
new file mode 100644
index 0000000..e5af89f
--- /dev/null
+++ b/third_party/boost/boost/type_traits/has_nothrow_constructor.hpp
@@ -0,0 +1,72 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_HAS_NOTHROW_CONSTRUCTOR_HPP_INCLUDED
+#define BOOST_TT_HAS_NOTHROW_CONSTRUCTOR_HPP_INCLUDED
+
+#include <boost/type_traits/intrinsics.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+
+#ifdef BOOST_HAS_NOTHROW_CONSTRUCTOR
+
+#if defined(BOOST_MSVC) || defined(BOOST_INTEL)
+#include <boost/type_traits/has_trivial_constructor.hpp>
+#endif
+#if defined(__GNUC__ ) || defined(__SUNPRO_CC)
+#include <boost/type_traits/is_default_constructible.hpp>
+#endif
+
+namespace boost {
+
+template <class T> struct has_nothrow_constructor : public integral_constant<bool, BOOST_HAS_NOTHROW_CONSTRUCTOR(T)>{};
+
+#elif !defined(BOOST_NO_CXX11_NOEXCEPT)
+
+#include <boost/type_traits/is_default_constructible.hpp>
+#include <boost/type_traits/remove_all_extents.hpp>
+
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable:4197) // top-level volatile in cast is ignored
+#endif
+
+namespace boost { namespace detail{
+
+ template <class T, bool b> struct has_nothrow_constructor_imp : public boost::integral_constant<bool, false>{};
+ template <class T> struct has_nothrow_constructor_imp<T, true> : public boost::integral_constant<bool, noexcept(T())>{};
+ template <class T, std::size_t N> struct has_nothrow_constructor_imp<T[N], true> : public has_nothrow_constructor_imp<T, true> {};
+}
+
+template <class T> struct has_nothrow_constructor : public detail::has_nothrow_constructor_imp<T, is_default_constructible<T>::value>{};
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#else
+
+#include <boost/type_traits/has_trivial_constructor.hpp>
+
+namespace boost {
+
+template <class T> struct has_nothrow_constructor : public ::boost::has_trivial_constructor<T> {};
+
+#endif
+
+template<> struct has_nothrow_constructor<void> : public false_type {};
+#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
+template<> struct has_nothrow_constructor<void const> : public false_type{};
+template<> struct has_nothrow_constructor<void const volatile> : public false_type{};
+template<> struct has_nothrow_constructor<void volatile> : public false_type{};
+#endif
+
+template <class T> struct has_nothrow_default_constructor : public has_nothrow_constructor<T>{};
+
+} // namespace boost
+
+#endif // BOOST_TT_HAS_NOTHROW_CONSTRUCTOR_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/has_nothrow_copy.hpp b/third_party/boost/boost/type_traits/has_nothrow_copy.hpp
new file mode 100644
index 0000000..8810abc
--- /dev/null
+++ b/third_party/boost/boost/type_traits/has_nothrow_copy.hpp
@@ -0,0 +1,82 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_HAS_NOTHROW_COPY_HPP_INCLUDED
+#define BOOST_TT_HAS_NOTHROW_COPY_HPP_INCLUDED
+
+#include <boost/type_traits/intrinsics.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+
+#ifdef BOOST_HAS_NOTHROW_COPY
+
+#if defined(BOOST_CLANG) || defined(__GNUC__) || defined(__ghs__) || defined(__CODEGEARC__) || defined(__SUNPRO_CC)
+#include <boost/type_traits/is_volatile.hpp>
+#include <boost/type_traits/is_copy_constructible.hpp>
+#include <boost/type_traits/is_reference.hpp>
+#include <boost/type_traits/is_array.hpp>
+#ifdef BOOST_INTEL
+#include <boost/type_traits/is_pod.hpp>
+#endif
+#elif defined(BOOST_MSVC) || defined(BOOST_INTEL)
+#include <boost/type_traits/has_trivial_copy.hpp>
+#include <boost/type_traits/is_array.hpp>
+#ifdef BOOST_INTEL
+#include <boost/type_traits/add_lvalue_reference.hpp>
+#include <boost/type_traits/add_const.hpp>
+#endif
+#endif
+
+namespace boost {
+
+template <class T> struct has_nothrow_copy_constructor : public integral_constant<bool, BOOST_HAS_NOTHROW_COPY(T)>{};
+
+#elif !defined(BOOST_NO_CXX11_NOEXCEPT)
+
+#include <boost/type_traits/declval.hpp>
+#include <boost/type_traits/is_copy_constructible.hpp>
+
+namespace boost{
+
+namespace detail{
+
+template <class T, bool b>
+struct has_nothrow_copy_constructor_imp : public boost::integral_constant<bool, false>{};
+template <class T>
+struct has_nothrow_copy_constructor_imp<T, true> : public boost::integral_constant<bool, noexcept(T(boost::declval<const T&>()))>{};
+
+}
+
+template <class T> struct has_nothrow_copy_constructor : public detail::has_nothrow_copy_constructor_imp<T, boost::is_copy_constructible<T>::value>{};
+
+#else
+
+#include <boost/type_traits/has_trivial_copy.hpp>
+
+namespace boost{
+
+template <class T> struct has_nothrow_copy_constructor : public integral_constant<bool, ::boost::has_trivial_copy<T>::value>{};
+
+#endif
+
+template <> struct has_nothrow_copy_constructor<void> : public false_type{};
+template <class T> struct has_nothrow_copy_constructor<T volatile> : public false_type{};
+template <class T> struct has_nothrow_copy_constructor<T&> : public false_type{};
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+template <class T> struct has_nothrow_copy_constructor<T&&> : public false_type{};
+#endif
+#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
+template <> struct has_nothrow_copy_constructor<void const> : public false_type{};
+template <> struct has_nothrow_copy_constructor<void volatile> : public false_type{};
+template <> struct has_nothrow_copy_constructor<void const volatile> : public false_type{};
+#endif
+
+template <class T> struct has_nothrow_copy : public has_nothrow_copy_constructor<T>{};
+
+} // namespace boost
+
+#endif // BOOST_TT_HAS_NOTHROW_COPY_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/has_plus.hpp b/third_party/boost/boost/type_traits/has_plus.hpp
new file mode 100644
index 0000000..2d79328
--- /dev/null
+++ b/third_party/boost/boost/type_traits/has_plus.hpp
@@ -0,0 +1,54 @@
+// (C) Copyright 2009-2011 Frederic Bron.
+//
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_HAS_PLUS_HPP_INCLUDED
+#define BOOST_TT_HAS_PLUS_HPP_INCLUDED
+
+#define BOOST_TT_TRAIT_NAME has_plus
+#define BOOST_TT_TRAIT_OP +
+#define BOOST_TT_FORBIDDEN_IF\
+ (\
+ /* Lhs==pointer and Rhs==pointer */\
+ (\
+ ::boost::is_pointer< Lhs_noref >::value && \
+ ::boost::is_pointer< Rhs_noref >::value\
+ ) || \
+ /* Lhs==void* and Rhs==fundamental */\
+ (\
+ ::boost::is_pointer< Lhs_noref >::value && \
+ ::boost::is_void< Lhs_noptr >::value && \
+ ::boost::is_fundamental< Rhs_nocv >::value\
+ ) || \
+ /* Rhs==void* and Lhs==fundamental */\
+ (\
+ ::boost::is_pointer< Rhs_noref >::value && \
+ ::boost::is_void< Rhs_noptr >::value && \
+ ::boost::is_fundamental< Lhs_nocv >::value\
+ ) || \
+ /* Lhs==pointer and Rhs==fundamental and Rhs!=integral */\
+ (\
+ ::boost::is_pointer< Lhs_noref >::value && \
+ ::boost::is_fundamental< Rhs_nocv >::value && \
+ (! ::boost::is_integral< Rhs_noref >::value )\
+ ) || \
+ /* Rhs==pointer and Lhs==fundamental and Lhs!=integral */\
+ (\
+ ::boost::is_pointer< Rhs_noref >::value && \
+ ::boost::is_fundamental< Lhs_nocv >::value && \
+ (! ::boost::is_integral< Lhs_noref >::value )\
+ )\
+ )
+
+
+#include <boost/type_traits/detail/has_binary_operator.hpp>
+
+#undef BOOST_TT_TRAIT_NAME
+#undef BOOST_TT_TRAIT_OP
+#undef BOOST_TT_FORBIDDEN_IF
+
+#endif
diff --git a/third_party/boost/boost/type_traits/has_plus_assign.hpp b/third_party/boost/boost/type_traits/has_plus_assign.hpp
new file mode 100644
index 0000000..5ef6f23
--- /dev/null
+++ b/third_party/boost/boost/type_traits/has_plus_assign.hpp
@@ -0,0 +1,66 @@
+// (C) Copyright 2009-2011 Frederic Bron.
+//
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_HAS_PLUS_ASSIGN_HPP_INCLUDED
+#define BOOST_TT_HAS_PLUS_ASSIGN_HPP_INCLUDED
+
+#define BOOST_TT_TRAIT_NAME has_plus_assign
+#define BOOST_TT_TRAIT_OP +=
+#define BOOST_TT_FORBIDDEN_IF\
+ (\
+ /* Lhs==pointer and Rhs==pointer */\
+ (\
+ ::boost::is_pointer< Lhs_noref >::value && \
+ ::boost::is_pointer< Rhs_noref >::value\
+ ) || \
+ /* Lhs==void* and Rhs==fundamental */\
+ (\
+ ::boost::is_pointer< Lhs_noref >::value && \
+ ::boost::is_void< Lhs_noptr >::value && \
+ ::boost::is_fundamental< Rhs_nocv >::value\
+ ) || \
+ /* Rhs==void* and Lhs==fundamental */\
+ (\
+ ::boost::is_pointer< Rhs_noref >::value && \
+ ::boost::is_void< Rhs_noptr >::value && \
+ ::boost::is_fundamental< Lhs_nocv >::value\
+ ) || \
+ /* Lhs==pointer and Rhs==fundamental and Rhs!=integral */\
+ (\
+ ::boost::is_pointer< Lhs_noref >::value && \
+ ::boost::is_fundamental< Rhs_nocv >::value && \
+ (! ::boost::is_integral< Rhs_noref >::value )\
+ ) || \
+ /* Rhs==pointer and Lhs==fundamental and Lhs!=bool */\
+ (\
+ ::boost::is_pointer< Rhs_noref >::value && \
+ ::boost::is_fundamental< Lhs_nocv >::value && \
+ (! ::boost::is_same< Lhs_nocv, bool >::value )\
+ ) || \
+ /* (Lhs==fundamental or Lhs==pointer) and (Rhs==fundamental or Rhs==pointer) and (Lhs==const) */\
+ (\
+ (\
+ ::boost::is_fundamental< Lhs_nocv >::value || \
+ ::boost::is_pointer< Lhs_noref >::value\
+ ) && \
+ ( \
+ ::boost::is_fundamental< Rhs_nocv >::value || \
+ ::boost::is_pointer< Rhs_noref >::value\
+ ) && \
+ ::boost::is_const< Lhs_noref >::value\
+ )\
+ )
+
+
+#include <boost/type_traits/detail/has_binary_operator.hpp>
+
+#undef BOOST_TT_TRAIT_NAME
+#undef BOOST_TT_TRAIT_OP
+#undef BOOST_TT_FORBIDDEN_IF
+
+#endif
diff --git a/third_party/boost/boost/type_traits/has_trivial_assign.hpp b/third_party/boost/boost/type_traits/has_trivial_assign.hpp
new file mode 100644
index 0000000..a5e625d
--- /dev/null
+++ b/third_party/boost/boost/type_traits/has_trivial_assign.hpp
@@ -0,0 +1,51 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_HAS_TRIVIAL_ASSIGN_HPP_INCLUDED
+#define BOOST_TT_HAS_TRIVIAL_ASSIGN_HPP_INCLUDED
+
+#include <boost/type_traits/detail/config.hpp>
+#include <boost/type_traits/intrinsics.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+
+#if !defined(BOOST_HAS_TRIVIAL_ASSIGN) || defined(BOOST_MSVC) || defined(__GNUC__) || defined(BOOST_INTEL) || defined(__SUNPRO_CC) || defined(__clang)
+#include <boost/type_traits/is_pod.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/is_volatile.hpp>
+#include <boost/type_traits/is_assignable.hpp>
+#endif
+
+namespace boost {
+
+ template <typename T>
+ struct has_trivial_assign : public integral_constant < bool,
+#ifdef BOOST_HAS_TRIVIAL_ASSIGN
+ BOOST_HAS_TRIVIAL_ASSIGN(T)
+#else
+ ::boost::is_pod<T>::value && !::boost::is_const<T>::value && !::boost::is_volatile<T>::value
+#endif
+ > {};
+
+ template<> struct has_trivial_assign<void> : public false_type{};
+#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
+ template<> struct has_trivial_assign<void const> : public false_type{};
+ template<> struct has_trivial_assign<void const volatile> : public false_type{};
+ template<> struct has_trivial_assign<void volatile> : public false_type{};
+#endif
+ template <class T> struct has_trivial_assign<T volatile> : public false_type{};
+ template <class T> struct has_trivial_assign<T&> : public false_type{};
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template <class T> struct has_trivial_assign<T&&> : public false_type{};
+#endif
+ // Arrays are not explictly assignable:
+ template <typename T, std::size_t N> struct has_trivial_assign<T[N]> : public false_type{};
+ template <typename T> struct has_trivial_assign<T[]> : public false_type{};
+
+} // namespace boost
+
+#endif // BOOST_TT_HAS_TRIVIAL_ASSIGN_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/has_trivial_constructor.hpp b/third_party/boost/boost/type_traits/has_trivial_constructor.hpp
new file mode 100644
index 0000000..06c137d
--- /dev/null
+++ b/third_party/boost/boost/type_traits/has_trivial_constructor.hpp
@@ -0,0 +1,57 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_HAS_TRIVIAL_CONSTRUCTOR_HPP_INCLUDED
+#define BOOST_TT_HAS_TRIVIAL_CONSTRUCTOR_HPP_INCLUDED
+
+#include <boost/type_traits/intrinsics.hpp>
+#include <boost/type_traits/is_pod.hpp>
+#include <boost/type_traits/is_default_constructible.hpp>
+
+#ifdef BOOST_HAS_TRIVIAL_CONSTRUCTOR
+#ifdef BOOST_HAS_SGI_TYPE_TRAITS
+#include <boost/type_traits/is_same.hpp>
+#elif defined(__GNUC__) || defined(__SUNPRO_CC)
+#include <boost/type_traits/is_volatile.hpp>
+#ifdef BOOST_INTEL
+#include <boost/type_traits/is_pod.hpp>
+#endif
+#endif
+#endif
+
+
+#if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)) || defined(BOOST_CLANG) || (defined(__SUNPRO_CC) && defined(BOOST_HAS_TRIVIAL_CONSTRUCTOR))
+#include <boost/type_traits/is_default_constructible.hpp>
+#define BOOST_TT_TRIVIAL_CONSTRUCT_FIX && is_default_constructible<T>::value
+#else
+//
+// Mot all compilers, particularly older GCC versions can handle the fix above.
+#define BOOST_TT_TRIVIAL_CONSTRUCT_FIX
+#endif
+
+namespace boost {
+
+template <typename T> struct has_trivial_constructor
+#ifdef BOOST_HAS_TRIVIAL_CONSTRUCTOR
+ : public integral_constant <bool, ((::boost::is_pod<T>::value || BOOST_HAS_TRIVIAL_CONSTRUCTOR(T)) BOOST_TT_TRIVIAL_CONSTRUCT_FIX)>{};
+#else
+ : public integral_constant <bool, ::boost::is_pod<T>::value>{};
+#endif
+
+template <> struct has_trivial_constructor<void> : public boost::false_type{};
+template <> struct has_trivial_constructor<void const> : public boost::false_type{};
+template <> struct has_trivial_constructor<void const volatile> : public boost::false_type{};
+template <> struct has_trivial_constructor<void volatile> : public boost::false_type{};
+
+template <class T> struct has_trivial_default_constructor : public has_trivial_constructor<T> {};
+
+#undef BOOST_TT_TRIVIAL_CONSTRUCT_FIX
+
+} // namespace boost
+
+#endif // BOOST_TT_HAS_TRIVIAL_CONSTRUCTOR_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/has_trivial_copy.hpp b/third_party/boost/boost/type_traits/has_trivial_copy.hpp
new file mode 100644
index 0000000..bc55de3
--- /dev/null
+++ b/third_party/boost/boost/type_traits/has_trivial_copy.hpp
@@ -0,0 +1,62 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_HAS_TRIVIAL_COPY_HPP_INCLUDED
+#define BOOST_TT_HAS_TRIVIAL_COPY_HPP_INCLUDED
+
+#include <boost/type_traits/intrinsics.hpp>
+#include <boost/type_traits/is_pod.hpp>
+#include <boost/type_traits/is_reference.hpp>
+
+#if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)) || defined(BOOST_CLANG) || (defined(__SUNPRO_CC) && defined(BOOST_HAS_TRIVIAL_COPY))
+#include <boost/type_traits/is_copy_constructible.hpp>
+#define BOOST_TT_TRIVIAL_CONSTRUCT_FIX && is_copy_constructible<T>::value
+#else
+#define BOOST_TT_TRIVIAL_CONSTRUCT_FIX
+#endif
+
+#ifdef BOOST_INTEL
+#include <boost/type_traits/add_const.hpp>
+#include <boost/type_traits/add_lvalue_reference.hpp>
+#endif
+
+namespace boost {
+
+template <typename T> struct has_trivial_copy
+: public integral_constant<bool,
+#ifdef BOOST_HAS_TRIVIAL_COPY
+ BOOST_HAS_TRIVIAL_COPY(T) BOOST_TT_TRIVIAL_CONSTRUCT_FIX
+#else
+ ::boost::is_pod<T>::value
+#endif
+>{};
+// Arrays are not explicitly copyable:
+template <typename T, std::size_t N> struct has_trivial_copy<T[N]> : public false_type{};
+template <typename T> struct has_trivial_copy<T[]> : public false_type{};
+// Are volatile types ever trivial? We don't really know, so assume not:
+template <typename T> struct has_trivial_copy<T volatile> : public false_type{};
+
+template <> struct has_trivial_copy<void> : public false_type{};
+#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
+template <> struct has_trivial_copy<void const> : public false_type{};
+template <> struct has_trivial_copy<void volatile> : public false_type{};
+template <> struct has_trivial_copy<void const volatile> : public false_type{};
+#endif
+
+template <class T> struct has_trivial_copy<T&> : public false_type{};
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+template <class T> struct has_trivial_copy<T&&> : public false_type{};
+#endif
+
+template <class T> struct has_trivial_copy_constructor : public has_trivial_copy<T>{};
+
+#undef BOOST_TT_TRIVIAL_CONSTRUCT_FIX
+
+} // namespace boost
+
+#endif // BOOST_TT_HAS_TRIVIAL_COPY_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/has_trivial_destructor.hpp b/third_party/boost/boost/type_traits/has_trivial_destructor.hpp
new file mode 100644
index 0000000..763283d
--- /dev/null
+++ b/third_party/boost/boost/type_traits/has_trivial_destructor.hpp
@@ -0,0 +1,48 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_HAS_TRIVIAL_DESTRUCTOR_HPP_INCLUDED
+#define BOOST_TT_HAS_TRIVIAL_DESTRUCTOR_HPP_INCLUDED
+
+#include <boost/type_traits/intrinsics.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+
+#ifdef BOOST_HAS_TRIVIAL_DESTRUCTOR
+
+#if defined(BOOST_INTEL) || defined(BOOST_MSVC)
+#include <boost/type_traits/is_pod.hpp>
+#endif
+#ifdef BOOST_HAS_SGI_TYPE_TRAITS
+#include <boost/type_traits/is_same.hpp>
+#endif
+
+#if defined(__GNUC__) || defined(__clang) || defined(__SUNPRO_CC)
+#include <boost/type_traits/is_destructible.hpp>
+#endif
+
+namespace boost {
+
+template <typename T> struct has_trivial_destructor : public integral_constant<bool, BOOST_HAS_TRIVIAL_DESTRUCTOR(T)>{};
+#else
+#include <boost/type_traits/is_pod.hpp>
+
+namespace boost{
+
+template <typename T> struct has_trivial_destructor : public integral_constant<bool, ::boost::is_pod<T>::value>{};
+#endif
+
+template <> struct has_trivial_destructor<void> : public false_type{};
+#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
+template <> struct has_trivial_destructor<void const> : public false_type{};
+template <> struct has_trivial_destructor<void const volatile> : public false_type{};
+template <> struct has_trivial_destructor<void volatile> : public false_type{};
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TT_HAS_TRIVIAL_DESTRUCTOR_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/has_trivial_move_assign.hpp b/third_party/boost/boost/type_traits/has_trivial_move_assign.hpp
new file mode 100644
index 0000000..f7bb198
--- /dev/null
+++ b/third_party/boost/boost/type_traits/has_trivial_move_assign.hpp
@@ -0,0 +1,72 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// (C) Copyright Eric Friedman 2002-2003.
+// (C) Copyright Antony Polukhin 2013.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_HAS_TRIVIAL_MOVE_ASSIGN_HPP_INCLUDED
+#define BOOST_TT_HAS_TRIVIAL_MOVE_ASSIGN_HPP_INCLUDED
+
+#include <boost/type_traits/intrinsics.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+
+#if !defined(BOOST_HAS_TRIVIAL_MOVE_ASSIGN) || defined(BOOST_MSVC) || defined(BOOST_INTEL)
+#include <boost/type_traits/is_pod.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/is_volatile.hpp>
+#ifdef BOOST_MSVC
+#include <boost/type_traits/is_reference.hpp>
+#endif
+#endif
+
+#if defined(__GNUC__) || defined(__clang)
+#include <boost/type_traits/is_assignable.hpp>
+#include <boost/type_traits/is_volatile.hpp>
+#endif
+
+#ifdef __SUNPRO_CC
+#include <boost/type_traits/is_assignable.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#if __cplusplus >= 201103
+#define SOLARIS_EXTRA_CHECK && is_assignable<typename remove_const<T>::type&, typename remove_const<T>::type&&>::value
+#endif
+#endif
+
+#ifndef SOLARIS_EXTRA_CHECK
+#define SOLARIS_EXTRA_CHECK
+#endif
+
+namespace boost{
+
+template <typename T>
+struct has_trivial_move_assign : public integral_constant<bool,
+#ifdef BOOST_HAS_TRIVIAL_MOVE_ASSIGN
+ BOOST_HAS_TRIVIAL_MOVE_ASSIGN(T)
+#else
+ ::boost::is_pod<T>::value && !::boost::is_const<T>::value && !::boost::is_volatile<T>::value SOLARIS_EXTRA_CHECK
+#endif
+ > {};
+
+template <> struct has_trivial_move_assign<void> : public false_type{};
+#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
+template <> struct has_trivial_move_assign<void const> : public false_type{};
+template <> struct has_trivial_move_assign<void const volatile> : public false_type{};
+template <> struct has_trivial_move_assign<void volatile> : public false_type{};
+#endif
+template <class T> struct has_trivial_move_assign<T&> : public false_type{};
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+template <class T> struct has_trivial_move_assign<T&&> : public false_type{};
+#endif
+// Array types are not assignable:
+template <class T, std::size_t N> struct has_trivial_move_assign<T[N]> : public false_type{};
+template <class T> struct has_trivial_move_assign<T[]> : public false_type{};
+
+} // namespace boost
+
+#undef SOLARIS_EXTRA_CHECK
+
+#endif // BOOST_TT_HAS_TRIVIAL_MOVE_ASSIGN_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/has_trivial_move_constructor.hpp b/third_party/boost/boost/type_traits/has_trivial_move_constructor.hpp
new file mode 100644
index 0000000..a2d76b5
--- /dev/null
+++ b/third_party/boost/boost/type_traits/has_trivial_move_constructor.hpp
@@ -0,0 +1,77 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// (C) Copyright Eric Friedman 2002-2003.
+// (C) Copyright Antony Polukhin 2013.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_HAS_TRIVIAL_MOVE_CONSTRUCTOR_HPP_INCLUDED
+#define BOOST_TT_HAS_TRIVIAL_MOVE_CONSTRUCTOR_HPP_INCLUDED
+
+#include <boost/type_traits/intrinsics.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+
+#ifdef BOOST_HAS_TRIVIAL_MOVE_CONSTRUCTOR
+
+#if defined(BOOST_MSVC) || defined(BOOST_INTEL)
+#include <boost/type_traits/is_pod.hpp>
+#include <boost/type_traits/is_volatile.hpp>
+#endif
+
+#if defined(__GNUC__) || defined(__clang)
+#include <boost/type_traits/is_constructible.hpp>
+#include <boost/type_traits/is_volatile.hpp>
+#endif
+
+
+namespace boost {
+
+template <typename T> struct has_trivial_move_constructor : public integral_constant<bool, BOOST_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T)>{};
+
+#else
+
+#ifdef __SUNPRO_CC
+#include <boost/type_traits/is_constructible.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#if __cplusplus >= 201103
+#define SOLARIS_EXTRA_CHECK && is_constructible<typename remove_const<T>::type, typename remove_const<T>::type&&>::value
+#endif
+#endif
+
+#ifndef SOLARIS_EXTRA_CHECK
+#define SOLARIS_EXTRA_CHECK
+#endif
+
+#include <boost/type_traits/is_pod.hpp>
+#include <boost/type_traits/is_volatile.hpp>
+
+namespace boost {
+
+template <typename T> struct has_trivial_move_constructor
+ : public integral_constant<bool, ::boost::is_pod<T>::value && !::boost::is_volatile<T>::value SOLARIS_EXTRA_CHECK>{};
+
+#undef SOLARIS_EXTRA_CHECK
+
+#endif
+
+template <> struct has_trivial_move_constructor<void> : public false_type{};
+#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
+template <> struct has_trivial_move_constructor<void const> : public false_type{};
+template <> struct has_trivial_move_constructor<void volatile> : public false_type{};
+template <> struct has_trivial_move_constructor<void const volatile> : public false_type{};
+#endif
+// What should we do with reference types??? The standard seems to suggest these are trivial, even if the thing they reference is not:
+template <class T> struct has_trivial_move_constructor<T&> : public true_type{};
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+template <class T> struct has_trivial_move_constructor<T&&> : public true_type{};
+#endif
+// Arrays can not be explicitly copied:
+template <class T, std::size_t N> struct has_trivial_move_constructor<T[N]> : public false_type{};
+template <class T> struct has_trivial_move_constructor<T[]> : public false_type{};
+
+} // namespace boost
+
+#endif // BOOST_TT_HAS_TRIVIAL_MOVE_CONSTRUCTOR_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/integral_constant.hpp b/third_party/boost/boost/type_traits/integral_constant.hpp
new file mode 100644
index 0000000..5b66a8a
--- /dev/null
+++ b/third_party/boost/boost/type_traits/integral_constant.hpp
@@ -0,0 +1,106 @@
+// (C) Copyright John Maddock 2015.
+// Use, modification and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_TYPE_TRAITS_INTEGRAL_CONSTANT_HPP
+#define BOOST_TYPE_TRAITS_INTEGRAL_CONSTANT_HPP
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+
+#if (BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \
+ || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610)) \
+ || BOOST_WORKAROUND(__DMC__, BOOST_TESTED_AT(0x840)) \
+ || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3202)) \
+ || BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, BOOST_TESTED_AT(810)) )
+
+
+namespace boost{
+ namespace mpl
+ {
+ template <bool B> struct bool_;
+ template <class I, I val> struct integral_c;
+ struct integral_c_tag;
+ }
+}
+
+#else
+
+namespace mpl_{
+
+ template <bool B> struct bool_;
+ template <class I, I val> struct integral_c;
+ struct integral_c_tag;
+}
+
+namespace boost
+{
+ namespace mpl
+ {
+ using ::mpl_::bool_;
+ using ::mpl_::integral_c;
+ using ::mpl_::integral_c_tag;
+ }
+}
+
+#endif
+
+namespace boost{
+
+ template <class T, T val>
+ struct integral_constant
+ {
+ typedef mpl::integral_c_tag tag;
+ typedef T value_type;
+ typedef integral_constant<T, val> type;
+ static const T value = val;
+ //
+ // This helper function is just to disable type-punning
+ // warnings from GCC:
+ //
+ template <class U>
+ static U& dereference(U* p) { return *p; }
+
+ operator const mpl::integral_c<T, val>& ()const
+ {
+ static const char data[sizeof(long)] = { 0 };
+ return dereference(reinterpret_cast<const mpl::integral_c<T, val>*>(&data));
+ }
+ BOOST_CONSTEXPR operator T()const { return val; }
+ };
+
+ template <class T, T val>
+ T const integral_constant<T, val>::value;
+
+ template <bool val>
+ struct integral_constant<bool, val>
+ {
+ typedef mpl::integral_c_tag tag;
+ typedef bool value_type;
+ typedef integral_constant<bool, val> type;
+ static const bool value = val;
+ //
+ // This helper function is just to disable type-punning
+ // warnings from GCC:
+ //
+ template <class T>
+ static T& dereference(T* p) { return *p; }
+
+ operator const mpl::bool_<val>& ()const
+ {
+ static const char data = 0;
+ return dereference(reinterpret_cast<const mpl::bool_<val>*>(&data));
+ }
+ BOOST_CONSTEXPR operator bool()const { return val; }
+ };
+
+ template <bool val>
+ bool const integral_constant<bool, val>::value;
+
+ typedef integral_constant<bool, true> true_type;
+ typedef integral_constant<bool, false> false_type;
+
+}
+
+#endif
diff --git a/third_party/boost/boost/type_traits/integral_promotion.hpp b/third_party/boost/boost/type_traits/integral_promotion.hpp
new file mode 100644
index 0000000..9a542b7
--- /dev/null
+++ b/third_party/boost/boost/type_traits/integral_promotion.hpp
@@ -0,0 +1,180 @@
+// Copyright 2005 Alexander Nasonov.
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef FILE_boost_type_traits_integral_promotion_hpp_INCLUDED
+#define FILE_boost_type_traits_integral_promotion_hpp_INCLUDED
+
+#include <boost/config.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/is_enum.hpp>
+#include <boost/type_traits/is_volatile.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+
+namespace boost {
+
+namespace type_traits { namespace detail {
+
+// 4.5/2
+template <class T> struct need_promotion : public boost::is_enum<T> {};
+
+// 4.5/1
+template<> struct need_promotion<char > : public true_type {};
+template<> struct need_promotion<signed char > : public true_type {};
+template<> struct need_promotion<unsigned char > : public true_type {};
+template<> struct need_promotion<signed short int > : public true_type {};
+template<> struct need_promotion<unsigned short int> : public true_type {};
+
+
+// Specializations for non-standard types.
+// Type is promoted if it's smaller then int.
+
+#define BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(T) \
+ template<> struct need_promotion<T> \
+ : public integral_constant<bool, (sizeof(T) < sizeof(int))> {};
+
+// Same set of integral types as in boost/type_traits/is_integral.hpp.
+// Please, keep in sync.
+#if (defined(BOOST_INTEL_CXX_VERSION) && defined(_MSC_VER) && (BOOST_INTEL_CXX_VERSION <= 600)) \
+ || (defined(__BORLANDC__) && (__BORLANDC__ == 0x600) && (_MSC_VER < 1300))
+// TODO: common macro for this #if. Or better yet, PP SEQ of non-standard types.
+BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(__int8 )
+BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(unsigned __int8 )
+BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(__int16 )
+BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(unsigned __int16)
+BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(__int32 )
+BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(unsigned __int32)
+#ifdef __BORLANDC__
+BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(unsigned __int64)
+BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE( __int64)
+#endif
+#endif
+
+#if defined(BOOST_HAS_LONG_LONG)
+BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(boost::ulong_long_type)
+BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(boost::long_long_type )
+#elif defined(BOOST_HAS_MS_INT64)
+BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE(unsigned __int64)
+BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE( __int64)
+#endif
+
+#undef BOOST_TT_AUX_PROMOTE_NONSTANDARD_TYPE
+
+
+#ifndef BOOST_NO_INTRINSIC_WCHAR_T
+// 4.5/2
+template<> struct need_promotion<wchar_t> : public true_type {};
+#endif
+
+// 4.5/3 (integral bit-field) is not supported.
+
+// 4.5/4
+template<> struct need_promotion<bool> : public true_type {};
+
+
+// Get promoted type by index and cv qualifiers.
+
+template<int Index, int IsConst, int IsVolatile> struct promote_from_index;
+
+#define BOOST_TT_AUX_PROMOTE_FROM_INDEX(N,T) \
+ template<> struct promote_from_index<N,0,0> { typedef T type; }; \
+ template<> struct promote_from_index<N,0,1> { typedef T volatile type; }; \
+ template<> struct promote_from_index<N,1,0> { typedef T const type; }; \
+ template<> struct promote_from_index<N,1,1> { typedef T const volatile type; };
+
+
+BOOST_TT_AUX_PROMOTE_FROM_INDEX(1, int )
+BOOST_TT_AUX_PROMOTE_FROM_INDEX(2, unsigned int )
+BOOST_TT_AUX_PROMOTE_FROM_INDEX(3, long )
+BOOST_TT_AUX_PROMOTE_FROM_INDEX(4, unsigned long)
+
+
+// WARNING: integral promotions to non-standard types
+// long long and __int64 are not defined by the standard.
+// Additional specialisations and overloads shouldn't
+// introduce ambiguity, though.
+
+#if defined(BOOST_HAS_LONG_LONG)
+BOOST_TT_AUX_PROMOTE_FROM_INDEX(5, boost::long_long_type )
+BOOST_TT_AUX_PROMOTE_FROM_INDEX(6, boost::ulong_long_type)
+#elif defined(BOOST_HAS_MS_INT64)
+BOOST_TT_AUX_PROMOTE_FROM_INDEX(7, __int64 )
+BOOST_TT_AUX_PROMOTE_FROM_INDEX(8, unsigned __int64)
+#endif
+
+#undef BOOST_TT_AUX_PROMOTE_FROM_INDEX
+
+
+// Define BOOST_TT_AUX_PROMOTED_INDEX_TESTER:
+#if !defined(BOOST_MSVC)
+
+template<int N>
+struct sized_type_for_promotion
+{
+ typedef char (&type)[N];
+};
+
+#define BOOST_TT_AUX_PROMOTED_INDEX_TESTER(I,T) \
+ sized_type_for_promotion<I>::type promoted_index_tester(T);
+
+#else
+
+#define BOOST_TT_AUX_PROMOTED_INDEX_TESTER(I,T) \
+ char (&promoted_index_tester(T))[I];
+
+#endif
+
+BOOST_TT_AUX_PROMOTED_INDEX_TESTER(1, int )
+BOOST_TT_AUX_PROMOTED_INDEX_TESTER(2, unsigned int )
+BOOST_TT_AUX_PROMOTED_INDEX_TESTER(3, long )
+BOOST_TT_AUX_PROMOTED_INDEX_TESTER(4, unsigned long)
+
+#if defined(BOOST_HAS_LONG_LONG)
+BOOST_TT_AUX_PROMOTED_INDEX_TESTER(5, boost::long_long_type )
+BOOST_TT_AUX_PROMOTED_INDEX_TESTER(6, boost::ulong_long_type)
+#elif defined(BOOST_HAS_MS_INT64)
+BOOST_TT_AUX_PROMOTED_INDEX_TESTER(7, __int64 )
+BOOST_TT_AUX_PROMOTED_INDEX_TESTER(8, unsigned __int64)
+#endif
+
+#undef BOOST_TT_AUX_PROMOTED_INDEX_TESTER
+
+
+// Get an index of promoted type for type T.
+// Precondition: need_promotion<T>
+template<class T>
+struct promoted_index
+{
+ static T testee; // undefined
+ BOOST_STATIC_CONSTANT(int, value = sizeof(promoted_index_tester(+testee)) );
+ // Unary plus promotes testee LOOK HERE ---> ^
+};
+
+template<class T>
+struct integral_promotion_impl
+{
+ typedef BOOST_DEDUCED_TYPENAME promote_from_index<
+ (boost::type_traits::detail::promoted_index<T>::value)
+ , (boost::is_const<T>::value)
+ , (boost::is_volatile<T>::value)
+ >::type type;
+};
+
+template<class T, bool b> struct integral_promotion { typedef T type; };
+template<class T> struct integral_promotion<T, true> : public integral_promotion_impl<T>{};
+
+} }
+
+template <class T> struct integral_promotion
+{
+private:
+ typedef boost::type_traits::detail::need_promotion<typename remove_cv<T>::type> tag_type;
+public:
+ typedef typename boost::type_traits::detail::integral_promotion<T, tag_type::value>::type type;
+};
+
+}
+
+#endif // #ifndef FILE_boost_type_traits_integral_promotion_hpp_INCLUDED
diff --git a/third_party/boost/boost/type_traits/intrinsics.hpp b/third_party/boost/boost/type_traits/intrinsics.hpp
new file mode 100644
index 0000000..610f7f9
--- /dev/null
+++ b/third_party/boost/boost/type_traits/intrinsics.hpp
@@ -0,0 +1,379 @@
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_INTRINSICS_HPP_INCLUDED
+#define BOOST_TT_INTRINSICS_HPP_INCLUDED
+
+#ifndef BOOST_TT_DISABLE_INTRINSICS
+
+#include <boost/config.hpp>
+
+#ifndef BOOST_TT_CONFIG_HPP_INCLUDED
+#include <boost/type_traits/detail/config.hpp>
+#endif
+
+//
+// Helper macros for builtin compiler support.
+// If your compiler has builtin support for any of the following
+// traits concepts, then redefine the appropriate macros to pick
+// up on the compiler support:
+//
+// (these should largely ignore cv-qualifiers)
+// BOOST_IS_UNION(T) should evaluate to true if T is a union type
+// BOOST_IS_POD(T) should evaluate to true if T is a POD type
+// BOOST_IS_EMPTY(T) should evaluate to true if T is an empty class type (and not a union)
+// BOOST_HAS_TRIVIAL_CONSTRUCTOR(T) should evaluate to true if "T x;" has no effect
+// BOOST_HAS_TRIVIAL_COPY(T) should evaluate to true if T(t) <==> memcpy
+// BOOST_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) should evaluate to true if T(boost::move(t)) <==> memcpy
+// BOOST_HAS_TRIVIAL_ASSIGN(T) should evaluate to true if t = u <==> memcpy
+// BOOST_HAS_TRIVIAL_MOVE_ASSIGN(T) should evaluate to true if t = boost::move(u) <==> memcpy
+// BOOST_HAS_TRIVIAL_DESTRUCTOR(T) should evaluate to true if ~T() has no effect
+// BOOST_HAS_NOTHROW_CONSTRUCTOR(T) should evaluate to true if "T x;" can not throw
+// BOOST_HAS_NOTHROW_COPY(T) should evaluate to true if T(t) can not throw
+// BOOST_HAS_NOTHROW_ASSIGN(T) should evaluate to true if t = u can not throw
+// BOOST_HAS_VIRTUAL_DESTRUCTOR(T) should evaluate to true T has a virtual destructor
+// BOOST_IS_NOTHROW_MOVE_CONSTRUCT(T) should evaluate to true if T has a non-throwing move constructor.
+// BOOST_IS_NOTHROW_MOVE_ASSIGN(T) should evaluate to true if T has a non-throwing move assignment operator.
+//
+// The following can also be defined: when detected our implementation is greatly simplified.
+//
+// BOOST_IS_ABSTRACT(T) true if T is an abstract type
+// BOOST_IS_BASE_OF(T,U) true if T is a base class of U
+// BOOST_IS_CLASS(T) true if T is a class type (and not a union)
+// BOOST_IS_CONVERTIBLE(T,U) true if T is convertible to U
+// BOOST_IS_ENUM(T) true is T is an enum
+// BOOST_IS_POLYMORPHIC(T) true if T is a polymorphic type
+// BOOST_ALIGNMENT_OF(T) should evaluate to the alignment requirements of type T.
+//
+// define BOOST_TT_DISABLE_INTRINSICS to prevent any intrinsics being used (mostly used when testing)
+//
+
+#ifdef BOOST_HAS_SGI_TYPE_TRAITS
+ // Hook into SGI's __type_traits class, this will pick up user supplied
+ // specializations as well as SGI - compiler supplied specializations.
+# include <boost/type_traits/is_same.hpp>
+# ifdef __NetBSD__
+ // There are two different versions of type_traits.h on NetBSD on Spark
+ // use an implicit include via algorithm instead, to make sure we get
+ // the same version as the std lib:
+# include <algorithm>
+# else
+# include <type_traits.h>
+# endif
+# define BOOST_IS_POD(T) ::boost::is_same< typename ::__type_traits<T>::is_POD_type, ::__true_type>::value
+# define BOOST_HAS_TRIVIAL_CONSTRUCTOR(T) ::boost::is_same< typename ::__type_traits<T>::has_trivial_default_constructor, ::__true_type>::value
+# define BOOST_HAS_TRIVIAL_COPY(T) ::boost::is_same< typename ::__type_traits<T>::has_trivial_copy_constructor, ::__true_type>::value
+# define BOOST_HAS_TRIVIAL_ASSIGN(T) ::boost::is_same< typename ::__type_traits<T>::has_trivial_assignment_operator, ::__true_type>::value
+# define BOOST_HAS_TRIVIAL_DESTRUCTOR(T) ::boost::is_same< typename ::__type_traits<T>::has_trivial_destructor, ::__true_type>::value
+
+# ifdef __sgi
+# define BOOST_HAS_TYPE_TRAITS_INTRINSICS
+# endif
+#endif
+
+#if defined(__MSL_CPP__) && (__MSL_CPP__ >= 0x8000)
+ // Metrowerks compiler is acquiring intrinsic type traits support
+ // post version 8. We hook into the published interface to pick up
+ // user defined specializations as well as compiler intrinsics as
+ // and when they become available:
+# include <msl_utility>
+# define BOOST_IS_UNION(T) BOOST_STD_EXTENSION_NAMESPACE::is_union<T>::value
+# define BOOST_IS_POD(T) BOOST_STD_EXTENSION_NAMESPACE::is_POD<T>::value
+# define BOOST_HAS_TRIVIAL_CONSTRUCTOR(T) BOOST_STD_EXTENSION_NAMESPACE::has_trivial_default_ctor<T>::value
+# define BOOST_HAS_TRIVIAL_COPY(T) BOOST_STD_EXTENSION_NAMESPACE::has_trivial_copy_ctor<T>::value
+# define BOOST_HAS_TRIVIAL_ASSIGN(T) BOOST_STD_EXTENSION_NAMESPACE::has_trivial_assignment<T>::value
+# define BOOST_HAS_TRIVIAL_DESTRUCTOR(T) BOOST_STD_EXTENSION_NAMESPACE::has_trivial_dtor<T>::value
+# define BOOST_HAS_TYPE_TRAITS_INTRINSICS
+#endif
+
+#if (defined(BOOST_MSVC) && defined(BOOST_MSVC_FULL_VER) && (BOOST_MSVC_FULL_VER >=140050215))\
+ || (defined(BOOST_INTEL) && defined(_MSC_VER) && (_MSC_VER >= 1500))
+//
+// Note that even though these intrinsics rely on other type traits classes
+// we do not #include those here as it produces cyclic dependencies and
+// can cause the intrinsics to not even be used at all!
+//
+# define BOOST_IS_UNION(T) __is_union(T)
+# define BOOST_IS_POD(T) (__is_pod(T) && __has_trivial_constructor(T))
+# define BOOST_IS_EMPTY(T) __is_empty(T)
+# define BOOST_HAS_TRIVIAL_CONSTRUCTOR(T) __has_trivial_constructor(T)
+# define BOOST_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T) || ( ::boost::is_pod<T>::value && ! ::boost::is_const<T>::value && !::boost::is_volatile<T>::value))
+# define BOOST_HAS_TRIVIAL_DESTRUCTOR(T) (__has_trivial_destructor(T) || ::boost::is_pod<T>::value)
+# define BOOST_HAS_NOTHROW_CONSTRUCTOR(T) (__has_nothrow_constructor(T) || ::boost::has_trivial_constructor<T>::value)
+#if !defined(BOOST_INTEL)
+# define BOOST_HAS_NOTHROW_COPY(T) ((__has_nothrow_copy(T) || ::boost::has_trivial_copy<T>::value) && !is_array<T>::value)
+# define BOOST_HAS_TRIVIAL_COPY(T) (__has_trivial_copy(T) || ::boost::is_pod<T>::value)
+#elif (_MSC_VER >= 1900)
+# define BOOST_HAS_NOTHROW_COPY(T) ((__is_nothrow_constructible(T, typename add_lvalue_reference<typename add_const<T>::type>::type)) && !is_array<T>::value)
+# define BOOST_HAS_TRIVIAL_COPY(T) (__is_trivially_constructible(T, typename add_lvalue_reference<typename add_const<T>::type>::type))
+#endif
+# define BOOST_HAS_NOTHROW_ASSIGN(T) (__has_nothrow_assign(T) || ::boost::has_trivial_assign<T>::value)
+# define BOOST_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T)
+
+# define BOOST_IS_ABSTRACT(T) __is_abstract(T)
+# define BOOST_IS_BASE_OF(T,U) (__is_base_of(T,U) && !is_same<T,U>::value)
+# define BOOST_IS_CLASS(T) __is_class(T)
+# define BOOST_IS_CONVERTIBLE(T,U) ((__is_convertible_to(T,U) || (is_same<T,U>::value && !is_function<U>::value)) && !__is_abstract(U))
+# define BOOST_IS_ENUM(T) __is_enum(T)
+// This one fails if the default alignment has been changed with /Zp:
+// # define BOOST_ALIGNMENT_OF(T) __alignof(T)
+
+# if defined(_MSC_VER) && (_MSC_VER >= 1700)
+# define BOOST_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) ((__has_trivial_move_constructor(T) || boost::is_pod<T>::value) && ! ::boost::is_volatile<T>::value && ! ::boost::is_reference<T>::value)
+# define BOOST_HAS_TRIVIAL_MOVE_ASSIGN(T) ((__has_trivial_move_assign(T) || boost::is_pod<T>::value) && ! ::boost::is_const<T>::value && !::boost::is_volatile<T>::value && ! ::boost::is_reference<T>::value)
+# endif
+#ifndef BOOST_NO_CXX11_FINAL
+// This one doesn't quite always do the right thing on older VC++ versions
+// we really need it when the final keyword is supporyted though:
+# define BOOST_IS_POLYMORPHIC(T) __is_polymorphic(T)
+#endif
+#if _MSC_FULL_VER >= 180020827
+# define BOOST_IS_NOTHROW_MOVE_ASSIGN(T) (__is_nothrow_assignable(T&, T&&))
+# define BOOST_IS_NOTHROW_MOVE_CONSTRUCT(T) (__is_nothrow_constructible(T, T&&))
+#endif
+# define BOOST_HAS_TYPE_TRAITS_INTRINSICS
+#endif
+
+#if defined(__DMC__) && (__DMC__ >= 0x848)
+// For Digital Mars C++, www.digitalmars.com
+# define BOOST_IS_UNION(T) (__typeinfo(T) & 0x400)
+# define BOOST_IS_POD(T) (__typeinfo(T) & 0x800)
+# define BOOST_IS_EMPTY(T) (__typeinfo(T) & 0x1000)
+# define BOOST_HAS_TRIVIAL_CONSTRUCTOR(T) (__typeinfo(T) & 0x10)
+# define BOOST_HAS_TRIVIAL_COPY(T) (__typeinfo(T) & 0x20)
+# define BOOST_HAS_TRIVIAL_ASSIGN(T) (__typeinfo(T) & 0x40)
+# define BOOST_HAS_TRIVIAL_DESTRUCTOR(T) (__typeinfo(T) & 0x8)
+# define BOOST_HAS_NOTHROW_CONSTRUCTOR(T) (__typeinfo(T) & 0x80)
+# define BOOST_HAS_NOTHROW_COPY(T) (__typeinfo(T) & 0x100)
+# define BOOST_HAS_NOTHROW_ASSIGN(T) (__typeinfo(T) & 0x200)
+# define BOOST_HAS_VIRTUAL_DESTRUCTOR(T) (__typeinfo(T) & 0x4)
+# define BOOST_HAS_TYPE_TRAITS_INTRINSICS
+#endif
+
+#if defined(BOOST_CLANG) && defined(__has_feature) && !defined(__CUDACC__)
+//
+// Note that these intrinsics are disabled for the CUDA meta-compiler as it appears
+// to not support them, even though the underlying clang compiler does so.
+// This is a rubbish fix as it basically stops type traits from working correctly,
+// but maybe the best we can do for now. See https://svn.boost.org/trac/boost/ticket/10694
+//
+//
+// Note that even though these intrinsics rely on other type traits classes
+// we do not #include those here as it produces cyclic dependencies and
+// can cause the intrinsics to not even be used at all!
+//
+# include <cstddef>
+
+# if __has_feature(is_union)
+# define BOOST_IS_UNION(T) __is_union(T)
+# endif
+# if (!defined(__GLIBCXX__) || (__GLIBCXX__ >= 20080306 && __GLIBCXX__ != 20080519)) && __has_feature(is_pod)
+# define BOOST_IS_POD(T) __is_pod(T)
+# endif
+# if (!defined(__GLIBCXX__) || (__GLIBCXX__ >= 20080306 && __GLIBCXX__ != 20080519)) && __has_feature(is_empty)
+# define BOOST_IS_EMPTY(T) __is_empty(T)
+# endif
+# if __has_feature(has_trivial_constructor)
+# define BOOST_HAS_TRIVIAL_CONSTRUCTOR(T) __has_trivial_constructor(T)
+# endif
+# if __has_feature(has_trivial_copy)
+# define BOOST_HAS_TRIVIAL_COPY(T) (__has_trivial_copy(T) && !is_reference<T>::value)
+# endif
+# if __has_feature(has_trivial_assign)
+# define BOOST_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T) && !is_volatile<T>::value && is_assignable<T&, const T&>::value)
+# endif
+# if __has_feature(has_trivial_destructor)
+# define BOOST_HAS_TRIVIAL_DESTRUCTOR(T) (__has_trivial_destructor(T) && is_destructible<T>::value)
+# endif
+# if __has_feature(has_nothrow_constructor)
+# define BOOST_HAS_NOTHROW_CONSTRUCTOR(T) (__has_nothrow_constructor(T) && is_default_constructible<T>::value)
+# endif
+# if __has_feature(has_nothrow_copy)
+# define BOOST_HAS_NOTHROW_COPY(T) (__has_nothrow_copy(T) && !is_volatile<T>::value && !is_reference<T>::value && is_copy_constructible<T>::value)
+# endif
+# if __has_feature(has_nothrow_assign)
+# define BOOST_HAS_NOTHROW_ASSIGN(T) (__has_nothrow_assign(T) && !is_volatile<T>::value && is_assignable<T&, const T&>::value)
+# endif
+# if __has_feature(has_virtual_destructor)
+# define BOOST_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T)
+# endif
+# if __has_feature(is_abstract)
+# define BOOST_IS_ABSTRACT(T) __is_abstract(T)
+# endif
+# if __has_feature(is_base_of)
+# define BOOST_IS_BASE_OF(T,U) (__is_base_of(T,U) && !is_same<T,U>::value)
+# endif
+# if __has_feature(is_class)
+# define BOOST_IS_CLASS(T) __is_class(T)
+# endif
+# if __has_feature(is_convertible_to)
+# define BOOST_IS_CONVERTIBLE(T,U) __is_convertible_to(T,U)
+# endif
+# if __has_feature(is_enum)
+# define BOOST_IS_ENUM(T) __is_enum(T)
+# endif
+# if __has_feature(is_polymorphic)
+# define BOOST_IS_POLYMORPHIC(T) __is_polymorphic(T)
+# endif
+# if __has_feature(has_trivial_move_constructor)
+# define BOOST_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) (__has_trivial_move_constructor(T) && is_constructible<T, T&&>::value && !::boost::is_volatile<T>::value)
+# endif
+# if __has_feature(has_trivial_move_assign)
+# define BOOST_HAS_TRIVIAL_MOVE_ASSIGN(T) (__has_trivial_move_assign(T) && is_assignable<T&, T&&>::value && !::boost::is_volatile<T>::value)
+# endif
+# if (!defined(unix) && !defined(__unix__)) || defined(__LP64__) || !defined(__GNUC__)
+// GCC sometimes lies about alignment requirements
+// of type double on 32-bit unix platforms, use the
+// old implementation instead in that case:
+# define BOOST_ALIGNMENT_OF(T) __alignof(T)
+# endif
+# if __has_feature(is_final)
+# define BOOST_IS_FINAL(T) __is_final(T)
+# endif
+
+# define BOOST_HAS_TYPE_TRAITS_INTRINSICS
+#endif
+
+#if defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3) && !defined(__GCCXML__))) && !defined(BOOST_CLANG)
+//
+// Note that even though these intrinsics rely on other type traits classes
+// we do not #include those here as it produces cyclic dependencies and
+// can cause the intrinsics to not even be used at all!
+//
+
+#ifdef BOOST_INTEL
+# define BOOST_INTEL_TT_OPTS || is_pod<T>::value
+#else
+# define BOOST_INTEL_TT_OPTS
+#endif
+
+# define BOOST_IS_UNION(T) __is_union(T)
+# define BOOST_IS_POD(T) __is_pod(T)
+# define BOOST_IS_EMPTY(T) __is_empty(T)
+# define BOOST_HAS_TRIVIAL_CONSTRUCTOR(T) ((__has_trivial_constructor(T) BOOST_INTEL_TT_OPTS) && ! ::boost::is_volatile<T>::value)
+# define BOOST_HAS_TRIVIAL_COPY(T) ((__has_trivial_copy(T) BOOST_INTEL_TT_OPTS) && !is_reference<T>::value)
+#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 409
+# define BOOST_HAS_TRIVIAL_ASSIGN(T) ((__has_trivial_assign(T) BOOST_INTEL_TT_OPTS) && ! ::boost::is_volatile<T>::value && ! ::boost::is_const<T>::value && is_assignable<T&, const T&>::value)
+# define BOOST_HAS_TRIVIAL_DESTRUCTOR(T) (__has_trivial_destructor(T) BOOST_INTEL_TT_OPTS && is_destructible<T>::value)
+# define BOOST_HAS_NOTHROW_CONSTRUCTOR(T) (__has_nothrow_constructor(T) && is_default_constructible<T>::value BOOST_INTEL_TT_OPTS)
+# define BOOST_HAS_NOTHROW_COPY(T) ((__has_nothrow_copy(T) BOOST_INTEL_TT_OPTS) && !is_volatile<T>::value && !is_reference<T>::value && is_copy_constructible<T>::value)
+# define BOOST_HAS_NOTHROW_ASSIGN(T) ((__has_nothrow_assign(T) BOOST_INTEL_TT_OPTS) && !is_volatile<T>::value && !is_const<T>::value && is_assignable<T&, const T&>::value)
+#else
+# define BOOST_HAS_TRIVIAL_ASSIGN(T) ((__has_trivial_assign(T) BOOST_INTEL_TT_OPTS) && ! ::boost::is_volatile<T>::value && ! ::boost::is_const<T>::value)
+# define BOOST_HAS_TRIVIAL_DESTRUCTOR(T) (__has_trivial_destructor(T) BOOST_INTEL_TT_OPTS)
+# define BOOST_HAS_NOTHROW_CONSTRUCTOR(T) (__has_nothrow_constructor(T) BOOST_INTEL_TT_OPTS)
+# define BOOST_HAS_NOTHROW_COPY(T) ((__has_nothrow_copy(T) BOOST_INTEL_TT_OPTS) && !is_volatile<T>::value && !is_reference<T>::value && !is_array<T>::value)
+# define BOOST_HAS_NOTHROW_ASSIGN(T) ((__has_nothrow_assign(T) BOOST_INTEL_TT_OPTS) && !is_volatile<T>::value && !is_const<T>::value && !is_array<T>::value)
+#endif
+# define BOOST_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T)
+
+# define BOOST_IS_ABSTRACT(T) __is_abstract(T)
+# define BOOST_IS_BASE_OF(T,U) (__is_base_of(T,U) && !is_same<T,U>::value)
+# define BOOST_IS_CLASS(T) __is_class(T)
+# define BOOST_IS_ENUM(T) __is_enum(T)
+# define BOOST_IS_POLYMORPHIC(T) __is_polymorphic(T)
+# if (!defined(unix) && !defined(__unix__)) || defined(__LP64__)
+ // GCC sometimes lies about alignment requirements
+ // of type double on 32-bit unix platforms, use the
+ // old implementation instead in that case:
+# define BOOST_ALIGNMENT_OF(T) __alignof__(T)
+# endif
+# if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7))
+# define BOOST_IS_FINAL(T) __is_final(T)
+# endif
+
+# if (__GNUC__ >= 5) && (__cplusplus >= 201103)
+# define BOOST_HAS_TRIVIAL_MOVE_ASSIGN(T) (__is_trivially_assignable(T&, T&&) && is_assignable<T&, T&&>::value && !::boost::is_volatile<T>::value)
+# define BOOST_HAS_TRIVIAL_MOVE_CONSTRUCTOR(T) (__is_trivially_constructible(T, T&&) && is_constructible<T, T&&>::value && !::boost::is_volatile<T>::value)
+# endif
+
+# define BOOST_HAS_TYPE_TRAITS_INTRINSICS
+#endif
+
+#if defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5130)
+# define BOOST_IS_UNION(T) __oracle_is_union(T)
+# define BOOST_IS_POD(T) (__oracle_is_pod(T) && !is_function<T>::value)
+# define BOOST_IS_EMPTY(T) __oracle_is_empty(T)
+# define BOOST_HAS_TRIVIAL_CONSTRUCTOR(T) (__oracle_has_trivial_constructor(T) && ! ::boost::is_volatile<T>::value)
+# define BOOST_HAS_TRIVIAL_COPY(T) (__oracle_has_trivial_copy(T) && !is_reference<T>::value)
+# define BOOST_HAS_TRIVIAL_ASSIGN(T) ((__oracle_has_trivial_assign(T) || __oracle_is_trivial(T)) && ! ::boost::is_volatile<T>::value && ! ::boost::is_const<T>::value && is_assignable<T&, const T&>::value)
+# define BOOST_HAS_TRIVIAL_DESTRUCTOR(T) (__oracle_has_trivial_destructor(T) && is_destructible<T>::value)
+# define BOOST_HAS_NOTHROW_CONSTRUCTOR(T) ((__oracle_has_nothrow_constructor(T) || __oracle_has_trivial_constructor(T) || __oracle_is_trivial(T)) && is_default_constructible<T>::value)
+// __oracle_has_nothrow_copy appears to behave the same as __oracle_has_nothrow_assign, disabled for now:
+//# define BOOST_HAS_NOTHROW_COPY(T) ((__oracle_has_nothrow_copy(T) || __oracle_has_trivial_copy(T) || __oracle_is_trivial(T)) && !is_volatile<T>::value && !is_reference<T>::value && is_copy_constructible<T>::value)
+# define BOOST_HAS_NOTHROW_ASSIGN(T) ((__oracle_has_nothrow_assign(T) || __oracle_has_trivial_assign(T) || __oracle_is_trivial(T)) && !is_volatile<T>::value && !is_const<T>::value && is_assignable<T&, const T&>::value)
+# define BOOST_HAS_VIRTUAL_DESTRUCTOR(T) __oracle_has_virtual_destructor(T)
+
+# define BOOST_IS_ABSTRACT(T) __oracle_is_abstract(T)
+//# define BOOST_IS_BASE_OF(T,U) (__is_base_of(T,U) && !is_same<T,U>::value)
+# define BOOST_IS_CLASS(T) __oracle_is_class(T)
+# define BOOST_IS_ENUM(T) __oracle_is_enum(T)
+# define BOOST_IS_POLYMORPHIC(T) __oracle_is_polymorphic(T)
+# define BOOST_ALIGNMENT_OF(T) __alignof__(T)
+# define BOOST_IS_FINAL(T) __oracle_is_final(T)
+
+# define BOOST_HAS_TYPE_TRAITS_INTRINSICS
+#endif
+
+#if defined(__ghs__) && (__GHS_VERSION_NUMBER >= 600)
+# include <boost/type_traits/is_same.hpp>
+# include <boost/type_traits/is_reference.hpp>
+# include <boost/type_traits/is_volatile.hpp>
+
+# define BOOST_IS_UNION(T) __is_union(T)
+# define BOOST_IS_POD(T) __is_pod(T)
+# define BOOST_IS_EMPTY(T) __is_empty(T)
+# define BOOST_HAS_TRIVIAL_CONSTRUCTOR(T) __has_trivial_constructor(T)
+# define BOOST_HAS_TRIVIAL_COPY(T) (__has_trivial_copy(T) && !is_reference<T>::value)
+# define BOOST_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T) && !is_volatile<T>::value)
+# define BOOST_HAS_TRIVIAL_DESTRUCTOR(T) __has_trivial_destructor(T)
+# define BOOST_HAS_NOTHROW_CONSTRUCTOR(T) __has_nothrow_constructor(T)
+# define BOOST_HAS_NOTHROW_COPY(T) (__has_nothrow_copy(T) && !is_volatile<T>::value && !is_reference<T>::value)
+# define BOOST_HAS_NOTHROW_ASSIGN(T) (__has_nothrow_assign(T) && !is_volatile<T>::value)
+# define BOOST_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T)
+
+# define BOOST_IS_ABSTRACT(T) __is_abstract(T)
+# define BOOST_IS_BASE_OF(T,U) (__is_base_of(T,U) && !is_same<T,U>::value)
+# define BOOST_IS_CLASS(T) __is_class(T)
+# define BOOST_IS_ENUM(T) __is_enum(T)
+# define BOOST_IS_POLYMORPHIC(T) __is_polymorphic(T)
+# define BOOST_ALIGNMENT_OF(T) __alignof__(T)
+# define BOOST_HAS_TYPE_TRAITS_INTRINSICS
+#endif
+
+# if defined(__CODEGEARC__)
+# include <boost/type_traits/is_same.hpp>
+# include <boost/type_traits/is_reference.hpp>
+# include <boost/type_traits/is_volatile.hpp>
+# include <boost/type_traits/is_void.hpp>
+
+# define BOOST_IS_UNION(T) __is_union(T)
+# define BOOST_IS_POD(T) __is_pod(T)
+# define BOOST_IS_EMPTY(T) __is_empty(T)
+# define BOOST_HAS_TRIVIAL_CONSTRUCTOR(T) (__has_trivial_default_constructor(T))
+# define BOOST_HAS_TRIVIAL_COPY(T) (__has_trivial_copy_constructor(T) && !is_reference<T>::value)
+# define BOOST_HAS_TRIVIAL_ASSIGN(T) (__has_trivial_assign(T) && !is_volatile<T>::value)
+# define BOOST_HAS_TRIVIAL_DESTRUCTOR(T) (__has_trivial_destructor(T))
+# define BOOST_HAS_NOTHROW_CONSTRUCTOR(T) (__has_nothrow_default_constructor(T))
+# define BOOST_HAS_NOTHROW_COPY(T) (__has_nothrow_copy_constructor(T) && !is_volatile<T>::value && !is_reference<T>::value)
+# define BOOST_HAS_NOTHROW_ASSIGN(T) (__has_nothrow_assign(T) && !is_volatile<T>::value)
+# define BOOST_HAS_VIRTUAL_DESTRUCTOR(T) __has_virtual_destructor(T)
+
+# define BOOST_IS_ABSTRACT(T) __is_abstract(T)
+# define BOOST_IS_BASE_OF(T,U) (__is_base_of(T,U) && !is_void<T>::value && !is_void<U>::value)
+# define BOOST_IS_CLASS(T) __is_class(T)
+# define BOOST_IS_CONVERTIBLE(T,U) (__is_convertible(T,U) || is_void<U>::value)
+# define BOOST_IS_ENUM(T) __is_enum(T)
+# define BOOST_IS_POLYMORPHIC(T) __is_polymorphic(T)
+# define BOOST_ALIGNMENT_OF(T) alignof(T)
+
+# define BOOST_HAS_TYPE_TRAITS_INTRINSICS
+#endif
+
+#endif // BOOST_TT_DISABLE_INTRINSICS
+
+#endif // BOOST_TT_INTRINSICS_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_abstract.hpp b/third_party/boost/boost/type_traits/is_abstract.hpp
new file mode 100644
index 0000000..225b0f7
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_abstract.hpp
@@ -0,0 +1,149 @@
+#ifndef BOOST_TT_IS_ABSTRACT_CLASS_HPP
+#define BOOST_TT_IS_ABSTRACT_CLASS_HPP
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// is_abstract_class.hpp:
+//
+// (C) Copyright 2002 Rani Sharoni (rani_sharoni@hotmail.com) and Robert Ramey
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org for updates, documentation, and revision history.
+//
+
+// Compile type discovery whether given type is abstract class or not.
+//
+// Requires DR 337 to be supported by compiler
+// (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#337).
+//
+//
+// Believed (Jan 2004) to work on:
+// - GCC 3.4
+// - VC++ 7.1
+// - compilers with new EDG frontend (Intel C++ 7, Comeau 4.3.2)
+//
+// Doesn't work on:
+// - VC++6, VC++7.0 and less
+// - GCC 3.3.X and less
+// - Borland C++ 6 and less
+//
+//
+// History:
+// - Originally written by Rani Sharoni, see
+// http://groups.google.com/groups?selm=df893da6.0207110613.75b2fe90%40posting.google.com
+// At this time supported by EDG (Intel C++ 7, Comeau 4.3.2) and VC7.1.
+// - Adapted and added into Boost.Serialization library by Robert Ramey
+// (starting with submission #10).
+// - Jan 2004: GCC 3.4 fixed to support DR337 (Giovanni Bajo).
+// - Jan 2004: modified to be part of Boost.TypeTraits (Pavel Vozenilek).
+// - Nov 2004: Christoph Ludwig found that the implementation did not work with
+// template types and gcc-3.4 or VC7.1, fix due to Christoph Ludwig
+// and John Maddock.
+// - Dec 2004: Added new config macro BOOST_NO_IS_ABSTRACT which causes the template
+// to degrade gracefully, rather than trash the compiler (John Maddock).
+//
+
+#include <boost/type_traits/intrinsics.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+#ifndef BOOST_IS_ABSTRACT
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/detail/yes_no_type.hpp>
+#include <boost/type_traits/is_class.hpp>
+#ifdef BOOST_NO_IS_ABSTRACT
+#include <boost/type_traits/is_polymorphic.hpp>
+#endif
+#endif
+
+namespace boost {
+
+namespace detail{
+
+#ifdef BOOST_IS_ABSTRACT
+template <class T>
+struct is_abstract_imp
+{
+ BOOST_STATIC_CONSTANT(bool, value = BOOST_IS_ABSTRACT(T));
+};
+#elif !defined(BOOST_NO_IS_ABSTRACT)
+template<class T>
+struct is_abstract_imp2
+{
+ // Deduction fails if T is void, function type,
+ // reference type (14.8.2/2)or an abstract class type
+ // according to review status issue #337
+ //
+ template<class U>
+ static type_traits::no_type check_sig(U (*)[1]);
+ template<class U>
+ static type_traits::yes_type check_sig(...);
+ //
+ // T must be a complete type, further if T is a template then
+ // it must be instantiated in order for us to get the right answer:
+ //
+ BOOST_STATIC_ASSERT(sizeof(T) != 0);
+
+ // GCC2 won't even parse this template if we embed the computation
+ // of s1 in the computation of value.
+#ifdef __GNUC__
+ BOOST_STATIC_CONSTANT(std::size_t, s1 = sizeof(is_abstract_imp2<T>::template check_sig<T>(0)));
+#else
+#if BOOST_WORKAROUND(BOOST_MSVC_FULL_VER, >= 140050000)
+#pragma warning(push)
+#pragma warning(disable:6334)
+#endif
+ BOOST_STATIC_CONSTANT(std::size_t, s1 = sizeof(check_sig<T>(0)));
+#if BOOST_WORKAROUND(BOOST_MSVC_FULL_VER, >= 140050000)
+#pragma warning(pop)
+#endif
+#endif
+
+ BOOST_STATIC_CONSTANT(bool, value =
+ (s1 == sizeof(type_traits::yes_type)));
+};
+
+template <bool v>
+struct is_abstract_select
+{
+ template <class T>
+ struct rebind
+ {
+ typedef is_abstract_imp2<T> type;
+ };
+};
+template <>
+struct is_abstract_select<false>
+{
+ template <class T>
+ struct rebind
+ {
+ typedef false_type type;
+ };
+};
+
+template <class T>
+struct is_abstract_imp
+{
+ typedef is_abstract_select< ::boost::is_class<T>::value> selector;
+ typedef typename selector::template rebind<T> binder;
+ typedef typename binder::type type;
+
+ BOOST_STATIC_CONSTANT(bool, value = type::value);
+};
+
+#endif
+}
+
+#ifndef BOOST_NO_IS_ABSTRACT
+template <class T> struct is_abstract : public integral_constant<bool, ::boost::detail::is_abstract_imp<T>::value> {};
+#else
+template <class T> struct is_abstract : public integral_constant<bool, ::boost::detail::is_polymorphic_imp<T>::value> {};
+#endif
+
+} // namespace boost
+
+#endif //BOOST_TT_IS_ABSTRACT_CLASS_HPP
diff --git a/third_party/boost/boost/type_traits/is_arithmetic.hpp b/third_party/boost/boost/type_traits/is_arithmetic.hpp
new file mode 100644
index 0000000..c23811e
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_arithmetic.hpp
@@ -0,0 +1,22 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_IS_ARITHMETIC_HPP_INCLUDED
+#define BOOST_TT_IS_ARITHMETIC_HPP_INCLUDED
+
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/is_floating_point.hpp>
+
+namespace boost {
+
+template <class T>
+struct is_arithmetic : public integral_constant<bool, is_integral<T>::value || is_floating_point<T>::value> {};
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_ARITHMETIC_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_array.hpp b/third_party/boost/boost/type_traits/is_array.hpp
new file mode 100644
index 0000000..717a28f
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_array.hpp
@@ -0,0 +1,43 @@
+
+// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes, Howard
+// Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+
+// Some fixes for is_array are based on a newsgroup posting by Jonathan Lundquist.
+
+
+#ifndef BOOST_TT_IS_ARRAY_HPP_INCLUDED
+#define BOOST_TT_IS_ARRAY_HPP_INCLUDED
+
+#include <boost/type_traits/integral_constant.hpp>
+#include <cstddef>
+
+namespace boost {
+
+#if defined( __CODEGEARC__ )
+ template <class T> struct is_array : public integral_constant<bool, __is_array(T)> {};
+#else
+ template <class T> struct is_array : public false_type {};
+#if !defined(BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS)
+ template <class T, std::size_t N> struct is_array<T[N]> : public true_type {};
+ template <class T, std::size_t N> struct is_array<T const[N]> : public true_type{};
+ template <class T, std::size_t N> struct is_array<T volatile[N]> : public true_type{};
+ template <class T, std::size_t N> struct is_array<T const volatile[N]> : public true_type{};
+#if !BOOST_WORKAROUND(__BORLANDC__, < 0x600) && !defined(__IBMCPP__) && !BOOST_WORKAROUND(__DMC__, BOOST_TESTED_AT(0x840))
+ template <class T> struct is_array<T[]> : public true_type{};
+ template <class T> struct is_array<T const[]> : public true_type{};
+ template <class T> struct is_array<T const volatile[]> : public true_type{};
+ template <class T> struct is_array<T volatile[]> : public true_type{};
+#endif
+#endif
+
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_ARRAY_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_assignable.hpp b/third_party/boost/boost/type_traits/is_assignable.hpp
new file mode 100644
index 0000000..9cf681d
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_assignable.hpp
@@ -0,0 +1,76 @@
+
+// (C) Copyright John Maddock 2015.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_IS_ASSIGNABLE_HPP_INCLUDED
+#define BOOST_TT_IS_ASSIGNABLE_HPP_INCLUDED
+
+#include <boost/type_traits/integral_constant.hpp>
+#include <boost/detail/workaround.hpp>
+
+namespace boost{
+
+ template <class T, class U = T> struct is_assignable;
+
+}
+
+#if !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800)
+
+#include <boost/type_traits/detail/yes_no_type.hpp>
+#include <boost/type_traits/declval.hpp>
+
+namespace boost{
+
+ namespace detail{
+
+ struct is_assignable_imp
+ {
+ template<typename T, typename U, typename = decltype(boost::declval<T>() = boost::declval<U>())>
+ static boost::type_traits::yes_type test(int);
+
+ template<typename, typename>
+ static boost::type_traits::no_type test(...);
+ };
+
+ }
+
+ template <class T, class U> struct is_assignable : public integral_constant<bool, sizeof(detail::is_assignable_imp::test<T, U>(0)) == sizeof(boost::type_traits::yes_type)>{};
+ template <class T, std::size_t N, class U> struct is_assignable<T[N], U> : public is_assignable<T, U>{};
+ template <class T, std::size_t N, class U> struct is_assignable<T(&)[N], U> : public is_assignable<T&, U>{};
+ template <class T, class U> struct is_assignable<T[], U> : public is_assignable<T, U>{};
+ template <class T, class U> struct is_assignable<T(&)[], U> : public is_assignable<T&, U>{};
+ template <class U> struct is_assignable<void, U> : public integral_constant<bool, false>{};
+ template <class U> struct is_assignable<void const, U> : public integral_constant<bool, false>{};
+ template <class U> struct is_assignable<void volatile, U> : public integral_constant<bool, false>{};
+ template <class U> struct is_assignable<void const volatile, U> : public integral_constant<bool, false>{};
+
+#else
+
+#include <boost/type_traits/has_trivial_assign.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+
+namespace boost{
+
+ // We don't know how to implement this:
+ template <class T, class U> struct is_assignable : public integral_constant<bool, false>{};
+ template <class T, class U> struct is_assignable<T&, U> : public integral_constant<bool, is_pod<T>::value && is_pod<typename remove_reference<U>::type>::value>{};
+ template <class T, class U> struct is_assignable<const T&, U> : public integral_constant<bool, false>{};
+ template <class U> struct is_assignable<void, U> : public integral_constant<bool, false>{};
+ template <class U> struct is_assignable<void const, U> : public integral_constant<bool, false>{};
+ template <class U> struct is_assignable<void volatile, U> : public integral_constant<bool, false>{};
+ template <class U> struct is_assignable<void const volatile, U> : public integral_constant<bool, false>{};
+ /*
+ template <> struct is_assignable<void, void> : public integral_constant<bool, false>{};
+ template <> struct is_assignable<void const, void const> : public integral_constant<bool, false>{};
+ template <> struct is_assignable<void volatile, void volatile> : public integral_constant<bool, false>{};
+ template <> struct is_assignable<void const volatile, void const volatile> : public integral_constant<bool, false>{};
+ */
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_ASSIGNABLE_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_base_and_derived.hpp b/third_party/boost/boost/type_traits/is_base_and_derived.hpp
new file mode 100644
index 0000000..a2cbbbc
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_base_and_derived.hpp
@@ -0,0 +1,244 @@
+
+// (C) Copyright Rani Sharoni 2003.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_IS_BASE_AND_DERIVED_HPP_INCLUDED
+#define BOOST_TT_IS_BASE_AND_DERIVED_HPP_INCLUDED
+
+#include <boost/type_traits/intrinsics.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+#ifndef BOOST_IS_BASE_OF
+#include <boost/type_traits/is_class.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/config.hpp>
+#include <boost/static_assert.hpp>
+#endif
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+namespace boost {
+
+namespace detail {
+
+#ifndef BOOST_IS_BASE_OF
+#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581)) \
+ && !BOOST_WORKAROUND(__SUNPRO_CC , <= 0x540) \
+ && !BOOST_WORKAROUND(__EDG_VERSION__, <= 243) \
+ && !BOOST_WORKAROUND(__DMC__, BOOST_TESTED_AT(0x840))
+
+ // The EDG version number is a lower estimate.
+ // It is not currently known which EDG version
+ // exactly fixes the problem.
+
+/*************************************************************************
+
+This version detects ambiguous base classes and private base classes
+correctly, and was devised by Rani Sharoni.
+
+Explanation by Terje Slettebo and Rani Sharoni.
+
+Let's take the multiple base class below as an example, and the following
+will also show why there's not a problem with private or ambiguous base
+class:
+
+struct B {};
+struct B1 : B {};
+struct B2 : B {};
+struct D : private B1, private B2 {};
+
+is_base_and_derived<B, D>::value;
+
+First, some terminology:
+
+SC - Standard conversion
+UDC - User-defined conversion
+
+A user-defined conversion sequence consists of an SC, followed by an UDC,
+followed by another SC. Either SC may be the identity conversion.
+
+When passing the default-constructed Host object to the overloaded check_sig()
+functions (initialization 8.5/14/4/3), we have several viable implicit
+conversion sequences:
+
+For "static no_type check_sig(B const volatile *, int)" we have the conversion
+sequences:
+
+C -> C const (SC - Qualification Adjustment) -> B const volatile* (UDC)
+C -> D const volatile* (UDC) -> B1 const volatile* / B2 const volatile* ->
+ B const volatile* (SC - Conversion)
+
+For "static yes_type check_sig(D const volatile *, T)" we have the conversion
+sequence:
+
+C -> D const volatile* (UDC)
+
+According to 13.3.3.1/4, in context of user-defined conversion only the
+standard conversion sequence is considered when selecting the best viable
+function, so it only considers up to the user-defined conversion. For the
+first function this means choosing between C -> C const and C -> C, and it
+chooses the latter, because it's a proper subset (13.3.3.2/3/2) of the
+former. Therefore, we have:
+
+C -> D const volatile* (UDC) -> B1 const volatile* / B2 const volatile* ->
+ B const volatile* (SC - Conversion)
+C -> D const volatile* (UDC)
+
+Here, the principle of the "shortest subsequence" applies again, and it
+chooses C -> D const volatile*. This shows that it doesn't even need to
+consider the multiple paths to B, or accessibility, as that possibility is
+eliminated before it could possibly cause ambiguity or access violation.
+
+If D is not derived from B, it has to choose between C -> C const -> B const
+volatile* for the first function, and C -> D const volatile* for the second
+function, which are just as good (both requires a UDC, 13.3.3.2), had it not
+been for the fact that "static no_type check_sig(B const volatile *, int)" is
+not templated, which makes C -> C const -> B const volatile* the best choice
+(13.3.3/1/4), resulting in "no".
+
+Also, if Host::operator B const volatile* hadn't been const, the two
+conversion sequences for "static no_type check_sig(B const volatile *, int)", in
+the case where D is derived from B, would have been ambiguous.
+
+See also
+http://groups.google.com/groups?selm=df893da6.0301280859.522081f7%40posting.
+google.com and links therein.
+
+*************************************************************************/
+
+template <typename B, typename D>
+struct bd_helper
+{
+ //
+ // This VC7.1 specific workaround stops the compiler from generating
+ // an internal compiler error when compiling with /vmg (thanks to
+ // Aleksey Gurtovoy for figuring out the workaround).
+ //
+#if !BOOST_WORKAROUND(BOOST_MSVC, == 1310)
+ template <typename T>
+ static type_traits::yes_type check_sig(D const volatile *, T);
+ static type_traits::no_type check_sig(B const volatile *, int);
+#else
+ static type_traits::yes_type check_sig(D const volatile *, long);
+ static type_traits::no_type check_sig(B const volatile * const&, int);
+#endif
+};
+
+template<typename B, typename D>
+struct is_base_and_derived_impl2
+{
+#if BOOST_WORKAROUND(BOOST_MSVC_FULL_VER, >= 140050000)
+#pragma warning(push)
+#pragma warning(disable:6334)
+#endif
+ //
+ // May silently do the wrong thing with incomplete types
+ // unless we trap them here:
+ //
+ BOOST_STATIC_ASSERT(sizeof(B) != 0);
+ BOOST_STATIC_ASSERT(sizeof(D) != 0);
+
+ struct Host
+ {
+#if !BOOST_WORKAROUND(BOOST_MSVC, == 1310)
+ operator B const volatile *() const;
+#else
+ operator B const volatile * const&() const;
+#endif
+ operator D const volatile *();
+ };
+
+ BOOST_STATIC_CONSTANT(bool, value =
+ sizeof(bd_helper<B,D>::check_sig(Host(), 0)) == sizeof(type_traits::yes_type));
+#if BOOST_WORKAROUND(BOOST_MSVC_FULL_VER, >= 140050000)
+#pragma warning(pop)
+#endif
+};
+
+#else
+
+//
+// broken version:
+//
+template<typename B, typename D>
+struct is_base_and_derived_impl2
+{
+ BOOST_STATIC_CONSTANT(bool, value =
+ (::boost::is_convertible<D*,B*>::value));
+};
+
+#define BOOST_BROKEN_IS_BASE_AND_DERIVED
+
+#endif
+
+template <typename B, typename D>
+struct is_base_and_derived_impl3
+{
+ BOOST_STATIC_CONSTANT(bool, value = false);
+};
+
+template <bool ic1, bool ic2, bool iss>
+struct is_base_and_derived_select
+{
+ template <class T, class U>
+ struct rebind
+ {
+ typedef is_base_and_derived_impl3<T,U> type;
+ };
+};
+
+template <>
+struct is_base_and_derived_select<true,true,false>
+{
+ template <class T, class U>
+ struct rebind
+ {
+ typedef is_base_and_derived_impl2<T,U> type;
+ };
+};
+
+template <typename B, typename D>
+struct is_base_and_derived_impl
+{
+ typedef typename remove_cv<B>::type ncvB;
+ typedef typename remove_cv<D>::type ncvD;
+
+ typedef is_base_and_derived_select<
+ ::boost::is_class<B>::value,
+ ::boost::is_class<D>::value,
+ ::boost::is_same<ncvB,ncvD>::value> selector;
+ typedef typename selector::template rebind<ncvB,ncvD> binder;
+ typedef typename binder::type bound_type;
+
+ BOOST_STATIC_CONSTANT(bool, value = bound_type::value);
+};
+#else
+template <typename B, typename D>
+struct is_base_and_derived_impl
+{
+ typedef typename remove_cv<B>::type ncvB;
+ typedef typename remove_cv<D>::type ncvD;
+
+ BOOST_STATIC_CONSTANT(bool, value = (BOOST_IS_BASE_OF(B,D) && ! ::boost::is_same<ncvB,ncvD>::value));
+};
+#endif
+} // namespace detail
+
+template <class Base, class Derived> struct is_base_and_derived
+ : public integral_constant<bool, (::boost::detail::is_base_and_derived_impl<Base, Derived>::value)> {};
+
+template <class Base, class Derived> struct is_base_and_derived<Base&, Derived> : public false_type{};
+template <class Base, class Derived> struct is_base_and_derived<Base, Derived&> : public false_type{};
+template <class Base, class Derived> struct is_base_and_derived<Base&, Derived&> : public false_type{};
+
+#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x610))
+template <class Base> struct is_base_and_derived<Base, Base> : public true_type{};
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_BASE_AND_DERIVED_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_base_of.hpp b/third_party/boost/boost/type_traits/is_base_of.hpp
new file mode 100644
index 0000000..e4c6ca9
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_base_of.hpp
@@ -0,0 +1,39 @@
+
+// (C) Copyright Rani Sharoni 2003-2005.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_IS_BASE_OF_HPP_INCLUDED
+#define BOOST_TT_IS_BASE_OF_HPP_INCLUDED
+
+#include <boost/type_traits/is_base_and_derived.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/is_class.hpp>
+
+namespace boost {
+
+ namespace detail{
+ template <class B, class D>
+ struct is_base_of_imp
+ {
+ typedef typename remove_cv<B>::type ncvB;
+ typedef typename remove_cv<D>::type ncvD;
+ BOOST_STATIC_CONSTANT(bool, value = (
+ (::boost::detail::is_base_and_derived_impl<ncvB,ncvD>::value) ||
+ (::boost::is_same<ncvB,ncvD>::value && ::boost::is_class<ncvB>::value)));
+ };
+ }
+
+ template <class Base, class Derived> struct is_base_of
+ : public integral_constant<bool, (::boost::detail::is_base_of_imp<Base, Derived>::value)> {};
+
+ template <class Base, class Derived> struct is_base_of<Base, Derived&> : false_type{};
+ template <class Base, class Derived> struct is_base_of<Base&, Derived&> : false_type{};
+ template <class Base, class Derived> struct is_base_of<Base&, Derived> : false_type{};
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_BASE_AND_DERIVED_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_class.hpp b/third_party/boost/boost/type_traits/is_class.hpp
new file mode 100644
index 0000000..aa35dbb
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_class.hpp
@@ -0,0 +1,114 @@
+// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes, Howard
+// Hinnant & John Maddock 2000-2003.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+
+#ifndef BOOST_TT_IS_CLASS_HPP_INCLUDED
+#define BOOST_TT_IS_CLASS_HPP_INCLUDED
+
+#include <boost/type_traits/detail/config.hpp>
+#include <boost/type_traits/intrinsics.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+#ifndef BOOST_IS_CLASS
+# include <boost/type_traits/is_union.hpp>
+
+#ifdef BOOST_TT_HAS_CONFORMING_IS_CLASS_IMPLEMENTATION
+# include <boost/type_traits/detail/yes_no_type.hpp>
+#else
+# include <boost/type_traits/is_scalar.hpp>
+# include <boost/type_traits/is_array.hpp>
+# include <boost/type_traits/is_reference.hpp>
+# include <boost/type_traits/is_void.hpp>
+# include <boost/type_traits/is_function.hpp>
+#endif
+
+#endif // BOOST_IS_CLASS
+
+namespace boost {
+
+namespace detail {
+
+#ifndef BOOST_IS_CLASS
+#ifdef BOOST_TT_HAS_CONFORMING_IS_CLASS_IMPLEMENTATION
+
+// This is actually the conforming implementation which works with
+// abstract classes. However, enough compilers have trouble with
+// it that most will use the one in
+// boost/type_traits/object_traits.hpp. This implementation
+// actually works with VC7.0, but other interactions seem to fail
+// when we use it.
+
+// is_class<> metafunction due to Paul Mensonides
+// (leavings@attbi.com). For more details:
+// http://groups.google.com/groups?hl=en&selm=000001c1cc83%24e154d5e0%247772e50c%40c161550a&rnum=1
+#if defined(__GNUC__) && !defined(__EDG_VERSION__)
+
+template <class U> ::boost::type_traits::yes_type is_class_tester(void(U::*)(void));
+template <class U> ::boost::type_traits::no_type is_class_tester(...);
+
+template <typename T>
+struct is_class_impl
+{
+
+ BOOST_STATIC_CONSTANT(bool, value =
+ sizeof(is_class_tester<T>(0)) == sizeof(::boost::type_traits::yes_type)
+ && ! ::boost::is_union<T>::value
+ );
+};
+
+#else
+
+template <typename T>
+struct is_class_impl
+{
+ template <class U> static ::boost::type_traits::yes_type is_class_tester(void(U::*)(void));
+ template <class U> static ::boost::type_traits::no_type is_class_tester(...);
+
+ BOOST_STATIC_CONSTANT(bool, value =
+ sizeof(is_class_tester<T>(0)) == sizeof(::boost::type_traits::yes_type)
+ && ! ::boost::is_union<T>::value
+ );
+};
+
+#endif
+
+#else
+
+template <typename T>
+struct is_class_impl
+{
+ BOOST_STATIC_CONSTANT(bool, value =
+ ! ::boost::is_union<T>::value >::value
+ && ! ::boost::is_scalar<T>::value
+ && ! ::boost::is_array<T>::value
+ && ! ::boost::is_reference<T>::value
+ && ! ::boost::is_void<T>::value
+ && ! ::boost::is_function<T>::value
+ );
+};
+
+# endif // BOOST_TT_HAS_CONFORMING_IS_CLASS_IMPLEMENTATION
+# else // BOOST_IS_CLASS
+template <typename T>
+struct is_class_impl
+{
+ BOOST_STATIC_CONSTANT(bool, value = BOOST_IS_CLASS(T));
+};
+# endif // BOOST_IS_CLASS
+
+} // namespace detail
+
+template <class T> struct is_class : public integral_constant<bool, ::boost::detail::is_class_impl<T>::value> {};
+# ifdef __EDG_VERSION__
+template <class T> struct is_class<const T> : public is_class<T>{};
+template <class T> struct is_class<const volatile T> : public is_class<T>{};
+template <class T> struct is_class<volatile T> : public is_class<T>{};
+# endif
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_CLASS_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_const.hpp b/third_party/boost/boost/type_traits/is_const.hpp
new file mode 100644
index 0000000..6cbeef8
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_const.hpp
@@ -0,0 +1,45 @@
+
+// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes,
+// Howard Hinnant and John Maddock 2000.
+// (C) Copyright Mat Marcus, Jesse Jones and Adobe Systems Inc 2001
+
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+// Fixed is_pointer, is_reference, is_const, is_volatile, is_same,
+// is_member_pointer based on the Simulated Partial Specialization work
+// of Mat Marcus and Jesse Jones. See http://opensource.adobe.com or
+// http://groups.yahoo.com/group/boost/message/5441
+// Some workarounds in here use ideas suggested from "Generic<Programming>:
+// Mappings between Types and Values"
+// by Andrei Alexandrescu (see http://www.cuj.com/experts/1810/alexandr.html).
+
+
+#ifndef BOOST_TT_IS_CONST_HPP_INCLUDED
+#define BOOST_TT_IS_CONST_HPP_INCLUDED
+
+#include <boost/type_traits/integral_constant.hpp>
+
+namespace boost {
+
+#if defined( __CODEGEARC__ )
+
+ template <class T>
+ struct is_const : public integral_constant<bool, __is_const(T)> {};
+
+#else
+
+ template <class T>
+ struct is_const : public false_type {};
+ template <class T> struct is_const<T const> : public true_type{};
+ template <class T, size_t N> struct is_const<T const[N]> : public true_type{};
+ template <class T> struct is_const<T const[]> : public true_type{};
+
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_CONST_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_convertible.hpp b/third_party/boost/boost/type_traits/is_convertible.hpp
new file mode 100644
index 0000000..a1e642c
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_convertible.hpp
@@ -0,0 +1,488 @@
+
+// Copyright 2000 John Maddock (john@johnmaddock.co.uk)
+// Copyright 2000 Jeremy Siek (jsiek@lsc.nd.edu)
+// Copyright 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
+//
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED
+#define BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED
+
+#include <boost/type_traits/intrinsics.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+#ifndef BOOST_IS_CONVERTIBLE
+#include <boost/type_traits/detail/yes_no_type.hpp>
+#include <boost/type_traits/detail/config.hpp>
+#include <boost/type_traits/is_array.hpp>
+#include <boost/type_traits/is_arithmetic.hpp>
+#include <boost/type_traits/is_void.hpp>
+#if !defined(BOOST_NO_IS_ABSTRACT)
+#include <boost/type_traits/is_abstract.hpp>
+#endif
+#include <boost/type_traits/add_lvalue_reference.hpp>
+#include <boost/type_traits/add_rvalue_reference.hpp>
+#include <boost/type_traits/is_function.hpp>
+
+#if defined(__MWERKS__)
+#include <boost/type_traits/remove_reference.hpp>
+#endif
+#if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+# include <boost/type_traits/declval.hpp>
+#endif
+#elif defined(BOOST_MSVC) || defined(BOOST_INTEL)
+#include <boost/type_traits/is_function.hpp>
+#include <boost/type_traits/is_same.hpp>
+#endif // BOOST_IS_CONVERTIBLE
+
+namespace boost {
+
+#ifndef BOOST_IS_CONVERTIBLE
+
+// is one type convertible to another?
+//
+// there are multiple versions of the is_convertible
+// template, almost every compiler seems to require its
+// own version.
+//
+// Thanks to Andrei Alexandrescu for the original version of the
+// conversion detection technique!
+//
+
+namespace detail {
+
+#if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !(defined(BOOST_GCC) && (BOOST_GCC < 40700))
+
+ // This is a C++11 conforming version, place this first and use it wherever possible:
+
+# define BOOST_TT_CXX11_IS_CONVERTIBLE
+
+ template <class A, class B, class C>
+ struct or_helper
+ {
+ static const bool value = (A::value || B::value || C::value);
+ };
+
+ template<typename From, typename To, bool b = or_helper<boost::is_void<From>, boost::is_function<To>, boost::is_array<To> >::value>
+ struct is_convertible_basic_impl
+ {
+ // Nothing converts to function or array, but void converts to void:
+ static const bool value = is_void<To>::value;
+ };
+
+ template<typename From, typename To>
+ class is_convertible_basic_impl<From, To, false>
+ {
+ typedef char one;
+ typedef int two;
+
+ template<typename To1>
+ static void test_aux(To1);
+
+ template<typename From1, typename To1>
+ static decltype(test_aux<To1>(boost::declval<From1>()), one()) test(int);
+
+ template<typename, typename>
+ static two test(...);
+
+ public:
+ static const bool value = sizeof(test<From, To>(0)) == 1;
+ };
+
+#elif defined(__BORLANDC__) && (__BORLANDC__ < 0x560)
+//
+// special version for Borland compilers
+// this version breaks when used for some
+// UDT conversions:
+//
+template <typename From, typename To>
+struct is_convertible_impl
+{
+#pragma option push -w-8074
+ // This workaround for Borland breaks the EDG C++ frontend,
+ // so we only use it for Borland.
+ template <typename T> struct checker
+ {
+ static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(...);
+ static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(T);
+ };
+
+ static typename add_lvalue_reference<From>::type _m_from;
+ static bool const value = sizeof( checker<To>::_m_check(_m_from) )
+ == sizeof(::boost::type_traits::yes_type);
+#pragma option pop
+};
+
+#elif defined(__GNUC__) || defined(__BORLANDC__) && (__BORLANDC__ < 0x600)
+// special version for gcc compiler + recent Borland versions
+// note that this does not pass UDT's through (...)
+
+struct any_conversion
+{
+ template <typename T> any_conversion(const volatile T&);
+ template <typename T> any_conversion(const T&);
+ template <typename T> any_conversion(volatile T&);
+ template <typename T> any_conversion(T&);
+};
+
+template <typename T> struct checker
+{
+ static boost::type_traits::no_type _m_check(any_conversion ...);
+ static boost::type_traits::yes_type _m_check(T, int);
+};
+
+template <typename From, typename To>
+struct is_convertible_basic_impl
+{
+ typedef typename add_lvalue_reference<From>::type lvalue_type;
+ typedef typename add_rvalue_reference<From>::type rvalue_type;
+ static lvalue_type _m_from;
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 6)))
+ static bool const value =
+ sizeof( boost::detail::checker<To>::_m_check(static_cast<rvalue_type>(_m_from), 0) )
+ == sizeof(::boost::type_traits::yes_type);
+#else
+ static bool const value =
+ sizeof( boost::detail::checker<To>::_m_check(_m_from, 0) )
+ == sizeof(::boost::type_traits::yes_type);
+#endif
+};
+
+#elif (defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 245) && !defined(__ICL)) \
+ || defined(__IBMCPP__) || defined(__HP_aCC)
+//
+// This is *almost* an ideal world implementation as it doesn't rely
+// on undefined behaviour by passing UDT's through (...).
+// Unfortunately it doesn't quite pass all the tests for most compilers (sigh...)
+// Enable this for your compiler if is_convertible_test.cpp will compile it...
+//
+// Note we do not enable this for VC7.1, because even though it passes all the
+// type_traits tests it is known to cause problems when instantiation occurs
+// deep within the instantiation tree :-(
+//
+struct any_conversion
+{
+ template <typename T> any_conversion(const volatile T&);
+ template <typename T> any_conversion(const T&);
+ template <typename T> any_conversion(volatile T&);
+ // we need this constructor to catch references to functions
+ // (which can not be cv-qualified):
+ template <typename T> any_conversion(T&);
+};
+
+template <typename From, typename To>
+struct is_convertible_basic_impl
+{
+ static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(any_conversion ...);
+ static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To, int);
+ typedef typename add_lvalue_reference<From>::type lvalue_type;
+ typedef typename add_rvalue_reference<From>::type rvalue_type;
+ static lvalue_type _m_from;
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ BOOST_STATIC_CONSTANT(bool, value =
+ sizeof( _m_check(static_cast<rvalue_type>(_m_from), 0) ) == sizeof(::boost::type_traits::yes_type)
+ );
+#else
+ BOOST_STATIC_CONSTANT(bool, value =
+ sizeof( _m_check(_m_from, 0) ) == sizeof(::boost::type_traits::yes_type)
+ );
+#endif
+};
+
+#elif defined(__DMC__)
+
+struct any_conversion
+{
+ template <typename T> any_conversion(const volatile T&);
+ template <typename T> any_conversion(const T&);
+ template <typename T> any_conversion(volatile T&);
+ // we need this constructor to catch references to functions
+ // (which can not be cv-qualified):
+ template <typename T> any_conversion(T&);
+};
+
+template <typename From, typename To>
+struct is_convertible_basic_impl
+{
+ // Using '...' doesn't always work on Digital Mars. This version seems to.
+ template <class T>
+ static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(any_conversion, float, T);
+ static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To, int, int);
+ typedef typename add_lvalue_reference<From>::type lvalue_type;
+ typedef typename add_rvalue_reference<From>::type rvalue_type;
+ static lvalue_type _m_from;
+
+ // Static constants sometime cause the conversion of _m_from to To to be
+ // called. This doesn't happen with an enum.
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ enum { value =
+ sizeof( _m_check(static_cast<rvalue_type>(_m_from), 0, 0) ) == sizeof(::boost::type_traits::yes_type)
+ };
+#else
+ enum { value =
+ sizeof( _m_check(_m_from, 0, 0) ) == sizeof(::boost::type_traits::yes_type)
+ };
+#endif
+};
+
+#elif defined(__MWERKS__)
+//
+// CW works with the technique implemented above for EDG, except when From
+// is a function type (or a reference to such a type), in which case
+// any_conversion won't be accepted as a valid conversion. We detect this
+// exceptional situation and channel it through an alternative algorithm.
+//
+
+template <typename From, typename To,bool FromIsFunctionRef>
+struct is_convertible_basic_impl_aux;
+
+struct any_conversion
+{
+ template <typename T> any_conversion(const volatile T&);
+ template <typename T> any_conversion(const T&);
+ template <typename T> any_conversion(volatile T&);
+ template <typename T> any_conversion(T&);
+};
+
+template <typename From, typename To>
+struct is_convertible_basic_impl_aux<From,To,false /*FromIsFunctionRef*/>
+{
+ static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(any_conversion ...);
+ static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To, int);
+ typedef typename add_lvalue_reference<From>::type lvalue_type;
+ typedef typename add_rvalue_reference<From>::type rvalue_type;
+ static lvalue_type _m_from;
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ BOOST_STATIC_CONSTANT(bool, value =
+ sizeof( _m_check(static_cast<rvalue_type>(_m_from), 0) ) == sizeof(::boost::type_traits::yes_type)
+ );
+#else
+ BOOST_STATIC_CONSTANT(bool, value =
+ sizeof( _m_check(_m_from, 0) ) == sizeof(::boost::type_traits::yes_type)
+ );
+#endif
+};
+
+template <typename From, typename To>
+struct is_convertible_basic_impl_aux<From,To,true /*FromIsFunctionRef*/>
+{
+ static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(...);
+ static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To);
+ typedef typename add_lvalue_reference<From>::type lvalue_type;
+ typedef typename add_rvalue_reference<From>::type rvalue_type;
+ static lvalue_type _m_from;
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ BOOST_STATIC_CONSTANT(bool, value =
+ sizeof( _m_check(static_cast<rvalue_type>(_m_from)) ) == sizeof(::boost::type_traits::yes_type)
+ );
+#else
+ BOOST_STATIC_CONSTANT(bool, value =
+ sizeof( _m_check(_m_from) ) == sizeof(::boost::type_traits::yes_type)
+ );
+#endif
+};
+
+template <typename From, typename To>
+struct is_convertible_basic_impl:
+ is_convertible_basic_impl_aux<
+ From,To,
+ ::boost::is_function<typename ::boost::remove_reference<From>::type>::value
+ >
+{};
+
+#else
+//
+// This version seems to work pretty well for a wide spectrum of compilers,
+// however it does rely on undefined behaviour by passing UDT's through (...).
+//
+
+//Workaround for old compilers like MSVC 7.1 to avoid
+//forming a reference to an array of unknown bound
+template <typename From>
+struct is_convertible_basic_impl_add_lvalue_reference
+ : add_lvalue_reference<From>
+{};
+
+template <typename From>
+struct is_convertible_basic_impl_add_lvalue_reference<From[]>
+{
+ typedef From type [];
+};
+
+template <typename From, typename To>
+struct is_convertible_basic_impl
+{
+ static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(...);
+ static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To);
+ typedef typename is_convertible_basic_impl_add_lvalue_reference<From>::type lvalue_type;
+ static lvalue_type _m_from;
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable:4244)
+#if BOOST_WORKAROUND(BOOST_MSVC_FULL_VER, >= 140050000)
+#pragma warning(disable:6334)
+#endif
+#endif
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ typedef typename add_rvalue_reference<From>::type rvalue_type;
+ BOOST_STATIC_CONSTANT(bool, value =
+ sizeof( _m_check(static_cast<rvalue_type>(_m_from)) ) == sizeof(::boost::type_traits::yes_type)
+ );
+#else
+ BOOST_STATIC_CONSTANT(bool, value =
+ sizeof( _m_check(_m_from) ) == sizeof(::boost::type_traits::yes_type)
+ );
+#endif
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+};
+
+#endif // is_convertible_impl
+
+#if defined(__DMC__)
+// As before, a static constant sometimes causes errors on Digital Mars.
+template <typename From, typename To>
+struct is_convertible_impl
+{
+ enum {
+ value = ( ::boost::detail::is_convertible_basic_impl<From,To>::value && ! ::boost::is_array<To>::value && ! ::boost::is_function<To>::value)
+ };
+};
+#elif !defined(__BORLANDC__) || __BORLANDC__ > 0x551
+template <typename From, typename To>
+struct is_convertible_impl
+{
+ BOOST_STATIC_CONSTANT(bool, value = ( ::boost::detail::is_convertible_basic_impl<From, To>::value && !::boost::is_array<To>::value && !::boost::is_function<To>::value));
+};
+#endif
+
+template <bool trivial1, bool trivial2, bool abstract_target>
+struct is_convertible_impl_select
+{
+ template <class From, class To>
+ struct rebind
+ {
+ typedef is_convertible_impl<From, To> type;
+ };
+};
+
+template <>
+struct is_convertible_impl_select<true, true, false>
+{
+ template <class From, class To>
+ struct rebind
+ {
+ typedef true_type type;
+ };
+};
+
+template <>
+struct is_convertible_impl_select<false, false, true>
+{
+ template <class From, class To>
+ struct rebind
+ {
+ typedef false_type type;
+ };
+};
+
+template <>
+struct is_convertible_impl_select<true, false, true>
+{
+ template <class From, class To>
+ struct rebind
+ {
+ typedef false_type type;
+ };
+};
+
+template <typename From, typename To>
+struct is_convertible_impl_dispatch_base
+{
+#if !BOOST_WORKAROUND(__HP_aCC, < 60700)
+ typedef is_convertible_impl_select<
+ ::boost::is_arithmetic<From>::value,
+ ::boost::is_arithmetic<To>::value,
+#if !defined(BOOST_NO_IS_ABSTRACT) && !defined(BOOST_TT_CXX11_IS_CONVERTIBLE)
+ // We need to filter out abstract types, only if we don't have a strictly conforming C++11 version:
+ ::boost::is_abstract<To>::value
+#else
+ false
+#endif
+ > selector;
+#else
+ typedef is_convertible_impl_select<false, false, false> selector;
+#endif
+ typedef typename selector::template rebind<From, To> isc_binder;
+ typedef typename isc_binder::type type;
+};
+
+template <typename From, typename To>
+struct is_convertible_impl_dispatch
+ : public is_convertible_impl_dispatch_base<From, To>::type
+{};
+
+//
+// Now add the full and partial specialisations
+// for void types, these are common to all the
+// implementation above:
+//
+#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
+
+template <> struct is_convertible_impl_dispatch<void, void> : public true_type{};
+template <> struct is_convertible_impl_dispatch<void, void const> : public true_type{};
+template <> struct is_convertible_impl_dispatch<void, void const volatile> : public true_type{};
+template <> struct is_convertible_impl_dispatch<void, void volatile> : public true_type{};
+
+template <> struct is_convertible_impl_dispatch<void const, void> : public true_type{};
+template <> struct is_convertible_impl_dispatch<void const, void const> : public true_type{};
+template <> struct is_convertible_impl_dispatch<void const, void const volatile> : public true_type{};
+template <> struct is_convertible_impl_dispatch<void const, void volatile> : public true_type{};
+
+template <> struct is_convertible_impl_dispatch<void const volatile, void> : public true_type{};
+template <> struct is_convertible_impl_dispatch<void const volatile, void const> : public true_type{};
+template <> struct is_convertible_impl_dispatch<void const volatile, void const volatile> : public true_type{};
+template <> struct is_convertible_impl_dispatch<void const volatile, void volatile> : public true_type{};
+
+template <> struct is_convertible_impl_dispatch<void volatile, void> : public true_type{};
+template <> struct is_convertible_impl_dispatch<void volatile, void const> : public true_type{};
+template <> struct is_convertible_impl_dispatch<void volatile, void const volatile> : public true_type{};
+template <> struct is_convertible_impl_dispatch<void volatile, void volatile> : public true_type{};
+
+#else
+template <> struct is_convertible_impl_dispatch<void, void> : public true_type{};
+#endif // BOOST_NO_CV_VOID_SPECIALIZATIONS
+
+template <class To> struct is_convertible_impl_dispatch<void, To> : public false_type{};
+template <class From> struct is_convertible_impl_dispatch<From, void> : public false_type{};
+
+#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
+template <class To> struct is_convertible_impl_dispatch<void const, To> : public false_type{};
+template <class From> struct is_convertible_impl_dispatch<From, void const> : public false_type{};
+template <class To> struct is_convertible_impl_dispatch<void const volatile, To> : public false_type{};
+template <class From> struct is_convertible_impl_dispatch<From, void const volatile> : public false_type{};
+template <class To> struct is_convertible_impl_dispatch<void volatile, To> : public false_type{};
+template <class From> struct is_convertible_impl_dispatch<From, void volatile> : public false_type{};
+#endif
+
+} // namespace detail
+
+template <class From, class To>
+struct is_convertible : public integral_constant<bool, ::boost::detail::is_convertible_impl_dispatch<From, To>::value> {};
+
+#else
+
+template <class From, class To>
+struct is_convertible : public integral_constant<bool, BOOST_IS_CONVERTIBLE(From, To)> {};
+
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_copy_constructible.hpp b/third_party/boost/boost/type_traits/is_copy_constructible.hpp
new file mode 100644
index 0000000..b6e7ae3
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_copy_constructible.hpp
@@ -0,0 +1,187 @@
+// (C) Copyright Antony Polukhin 2013.
+//
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_IS_COPY_CONSTRUCTIBLE_HPP_INCLUDED
+#define BOOST_TT_IS_COPY_CONSTRUCTIBLE_HPP_INCLUDED
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800) && !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40900)
+
+#include <boost/type_traits/is_constructible.hpp>
+
+#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1800)
+
+namespace boost {
+
+template <class T> struct is_copy_constructible : public boost::is_constructible<T, const T&>{};
+
+template <> struct is_copy_constructible<void> : public false_type{};
+template <> struct is_copy_constructible<void const> : public false_type{};
+template <> struct is_copy_constructible<void const volatile> : public false_type{};
+template <> struct is_copy_constructible<void volatile> : public false_type{};
+
+} // namespace boost
+
+#else
+//
+// Special version for VC12 which has a problem when a base class (such as non_copyable) has a deleted
+// copy constructor. In this case the compiler thinks there really is a copy-constructor and tries to
+// instantiate the deleted member. std::is_copy_constructible has the same issue (or at least returns
+// an incorrect value, which just defers the issue into the users code) as well. We can at least fix
+// boost::non_copyable as a base class as a special case:
+//
+#include <boost/type_traits/is_base_and_derived.hpp>
+#include <boost/noncopyable.hpp>
+
+namespace boost {
+
+ namespace detail
+ {
+
+ template <class T, bool b> struct is_copy_constructible_imp : public boost::is_constructible<T, const T&>{};
+ template <class T> struct is_copy_constructible_imp<T, true> : public false_type{};
+
+ }
+
+ template <class T> struct is_copy_constructible : public detail::is_copy_constructible_imp<T, is_base_and_derived<boost::noncopyable, T>::value>{};
+
+ template <> struct is_copy_constructible<void> : public false_type{};
+ template <> struct is_copy_constructible<void const> : public false_type{};
+ template <> struct is_copy_constructible<void const volatile> : public false_type{};
+ template <> struct is_copy_constructible<void volatile> : public false_type{};
+
+} // namespace boost
+
+#endif
+
+#else
+
+#include <boost/type_traits/detail/yes_no_type.hpp>
+#include <boost/type_traits/is_base_and_derived.hpp>
+#include <boost/type_traits/add_reference.hpp>
+#include <boost/type_traits/is_rvalue_reference.hpp>
+#include <boost/type_traits/declval.hpp>
+#include <boost/type_traits/is_array.hpp>
+#include <boost/type_traits/declval.hpp>
+#include <boost/noncopyable.hpp>
+
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable:4181)
+#endif
+
+namespace boost {
+
+ namespace detail{
+
+ template <bool DerivedFromNoncopyable, class T>
+ struct is_copy_constructible_impl2 {
+
+ // Intel compiler has problems with SFINAE for copy constructors and deleted functions:
+ //
+ // error: function *function_name* cannot be referenced -- it is a deleted function
+ // static boost::type_traits::yes_type test(T1&, decltype(T1(boost::declval<T1&>()))* = 0);
+ // ^
+ //
+ // MSVC 12.0 (Visual 2013) has problems when the copy constructor has been deleted. See:
+ // https://connect.microsoft.com/VisualStudio/feedback/details/800328/std-is-copy-constructible-is-broken
+#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) && !defined(BOOST_INTEL_CXX_VERSION) && !(defined(BOOST_MSVC) && _MSC_VER == 1800)
+
+#ifdef BOOST_NO_CXX11_DECLTYPE
+ template <class T1>
+ static boost::type_traits::yes_type test(const T1&, boost::mpl::int_<sizeof(T1(boost::declval<const T1&>()))>* = 0);
+#else
+ template <class T1>
+ static boost::type_traits::yes_type test(const T1&, decltype(T1(boost::declval<const T1&>()))* = 0);
+#endif
+
+ static boost::type_traits::no_type test(...);
+#else
+ template <class T1>
+ static boost::type_traits::no_type test(const T1&, typename T1::boost_move_no_copy_constructor_or_assign* = 0);
+ static boost::type_traits::yes_type test(...);
+#endif
+
+ // If you see errors like this:
+ //
+ // `'T::T(const T&)' is private`
+ // `boost/type_traits/is_copy_constructible.hpp:68:5: error: within this context`
+ //
+ // then you are trying to call that macro for a structure defined like that:
+ //
+ // struct T {
+ // ...
+ // private:
+ // T(const T &);
+ // ...
+ // };
+ //
+ // To fix that you must modify your structure:
+ //
+ // // C++03 and C++11 version
+ // struct T: private boost::noncopyable {
+ // ...
+ // private:
+ // T(const T &);
+ // ...
+ // };
+ //
+ // // C++11 version
+ // struct T {
+ // ...
+ // private:
+ // T(const T &) = delete;
+ // ...
+ // };
+ BOOST_STATIC_CONSTANT(bool, value = (
+ sizeof(test(
+ boost::declval<BOOST_DEDUCED_TYPENAME boost::add_reference<T const>::type>()
+ )) == sizeof(boost::type_traits::yes_type)
+ &&
+ !boost::is_rvalue_reference<T>::value
+ && !boost::is_array<T>::value
+ ));
+ };
+
+ template <class T>
+ struct is_copy_constructible_impl2<true, T> {
+ BOOST_STATIC_CONSTANT(bool, value = false);
+ };
+
+ template <class T>
+ struct is_copy_constructible_impl {
+
+ BOOST_STATIC_CONSTANT(bool, value = (
+ boost::detail::is_copy_constructible_impl2<
+ boost::is_base_and_derived<boost::noncopyable, T>::value,
+ T
+ >::value
+ ));
+ };
+
+ } // namespace detail
+
+ template <class T> struct is_copy_constructible : public integral_constant<bool, ::boost::detail::is_copy_constructible_impl<T>::value>{};
+ template <> struct is_copy_constructible<void> : public false_type{};
+#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
+ template <> struct is_copy_constructible<void const> : public false_type{};
+ template <> struct is_copy_constructible<void volatile> : public false_type{};
+ template <> struct is_copy_constructible<void const volatile> : public false_type{};
+#endif
+
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#endif
+
+#endif // BOOST_TT_IS_COPY_CONSTRUCTIBLE_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_default_constructible.hpp b/third_party/boost/boost/type_traits/is_default_constructible.hpp
new file mode 100644
index 0000000..74bddb7
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_default_constructible.hpp
@@ -0,0 +1,64 @@
+
+// (C) Copyright John Maddock 2015.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_IS_DEFAULT_CONSTRUCTIBLE_HPP_INCLUDED
+#define BOOST_TT_IS_DEFAULT_CONSTRUCTIBLE_HPP_INCLUDED
+
+#include <boost/type_traits/integral_constant.hpp>
+#include <boost/detail/workaround.hpp>
+
+#if !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800) && !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40500)
+
+#include <boost/type_traits/detail/yes_no_type.hpp>
+
+namespace boost{
+
+ namespace detail{
+
+ struct is_default_constructible_imp
+ {
+ template<typename _Tp, typename = decltype(_Tp())>
+ static boost::type_traits::yes_type test(int);
+
+ template<typename>
+ static boost::type_traits::no_type test(...);
+ };
+
+ }
+
+ template <class T> struct is_default_constructible : public integral_constant<bool, sizeof(detail::is_default_constructible_imp::test<T>(0)) == sizeof(boost::type_traits::yes_type)>{};
+ template <class T, std::size_t N> struct is_default_constructible<T[N]> : public is_default_constructible<T>{};
+ template <class T> struct is_default_constructible<T[]> : public is_default_constructible<T>{};
+ template <class T> struct is_default_constructible<T&> : public integral_constant<bool, false>{};
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+ template <class T> struct is_default_constructible<T&&> : public integral_constant<bool, false>{};
+#endif
+ template <> struct is_default_constructible<void> : public integral_constant<bool, false>{};
+ template <> struct is_default_constructible<void const> : public integral_constant<bool, false>{};
+ template <> struct is_default_constructible<void volatile> : public integral_constant<bool, false>{};
+ template <> struct is_default_constructible<void const volatile> : public integral_constant<bool, false>{};
+
+#else
+
+#include <boost/type_traits/is_pod.hpp>
+
+namespace boost{
+
+ // We don't know how to implement this, note we can not use has_trivial_constructor here
+ // because the correct implementation of that trait requires this one:
+ template <class T> struct is_default_constructible : public is_pod<T>{};
+ template <> struct is_default_constructible<void> : public integral_constant<bool, false>{};
+ template <> struct is_default_constructible<void const> : public integral_constant<bool, false>{};
+ template <> struct is_default_constructible<void volatile> : public integral_constant<bool, false>{};
+ template <> struct is_default_constructible<void const volatile> : public integral_constant<bool, false>{};
+
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_DEFAULT_CONSTRUCTIBLE_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_destructible.hpp b/third_party/boost/boost/type_traits/is_destructible.hpp
new file mode 100644
index 0000000..9f1e5d9
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_destructible.hpp
@@ -0,0 +1,60 @@
+
+// (C) Copyright John Maddock 2015.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_IS_DESTRUCTIBLE_HPP_INCLUDED
+#define BOOST_TT_IS_DESTRUCTIBLE_HPP_INCLUDED
+
+#include <boost/type_traits/integral_constant.hpp>
+#include <boost/detail/workaround.hpp>
+
+#if !defined(BOOST_NO_CXX11_DECLTYPE) && !BOOST_WORKAROUND(BOOST_MSVC, < 1800)
+
+#include <boost/type_traits/detail/yes_no_type.hpp>
+#include <boost/type_traits/declval.hpp>
+
+namespace boost{
+
+ namespace detail{
+
+ struct is_destructible_imp
+ {
+ template<typename T, typename = decltype(boost::declval<T&>().~T())>
+ static boost::type_traits::yes_type test(int);
+ template<typename>
+ static boost::type_traits::no_type test(...);
+ };
+
+ }
+
+ template <class T> struct is_destructible : public integral_constant<bool, sizeof(detail::is_destructible_imp::test<T>(0)) == sizeof(boost::type_traits::yes_type)>{};
+
+#else
+
+#include <boost/type_traits/is_pod.hpp>
+#include <boost/type_traits/is_class.hpp>
+
+namespace boost{
+
+ // We don't know how to implement this:
+ template <class T> struct is_destructible : public integral_constant<bool, is_pod<T>::value || is_class<T>::value>{};
+#endif
+
+ template <> struct is_destructible<void> : public false_type{};
+ template <> struct is_destructible<void const> : public false_type{};
+ template <> struct is_destructible<void volatile> : public false_type{};
+ template <> struct is_destructible<void const volatile> : public false_type{};
+ template <class T> struct is_destructible<T&> : public is_destructible<T>{};
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <class T> struct is_destructible<T&&> : public is_destructible<T>{};
+#endif
+ template <class T, std::size_t N> struct is_destructible<T[N]> : public is_destructible<T>{};
+ template <class T> struct is_destructible<T[]> : public is_destructible<T>{};
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_DESTRUCTIBLE_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_empty.hpp b/third_party/boost/boost/type_traits/is_empty.hpp
new file mode 100644
index 0000000..f57b82a
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_empty.hpp
@@ -0,0 +1,119 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_IS_EMPTY_HPP_INCLUDED
+#define BOOST_TT_IS_EMPTY_HPP_INCLUDED
+
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/detail/config.hpp>
+#include <boost/type_traits/intrinsics.hpp>
+
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/is_class.hpp>
+#include <boost/type_traits/add_reference.hpp>
+
+#ifndef BOOST_INTERNAL_IS_EMPTY
+#define BOOST_INTERNAL_IS_EMPTY(T) false
+#else
+#define BOOST_INTERNAL_IS_EMPTY(T) BOOST_IS_EMPTY(T)
+#endif
+
+namespace boost {
+
+namespace detail {
+
+
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable:4624) // destructor could not be generated
+#endif
+
+template <typename T>
+struct empty_helper_t1 : public T
+{
+ empty_helper_t1(); // hh compiler bug workaround
+ int i[256];
+private:
+ // suppress compiler warnings:
+ empty_helper_t1(const empty_helper_t1&);
+ empty_helper_t1& operator=(const empty_helper_t1&);
+};
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+struct empty_helper_t2 { int i[256]; };
+
+#if !BOOST_WORKAROUND(__BORLANDC__, < 0x600)
+
+template <typename T, bool is_a_class = false>
+struct empty_helper
+{
+ BOOST_STATIC_CONSTANT(bool, value = false);
+};
+
+template <typename T>
+struct empty_helper<T, true>
+{
+ BOOST_STATIC_CONSTANT(
+ bool, value = (sizeof(empty_helper_t1<T>) == sizeof(empty_helper_t2))
+ );
+};
+
+template <typename T>
+struct is_empty_impl
+{
+ typedef typename remove_cv<T>::type cvt;
+ BOOST_STATIC_CONSTANT(
+ bool,
+ value = ( ::boost::detail::empty_helper<cvt,::boost::is_class<T>::value>::value || BOOST_INTERNAL_IS_EMPTY(cvt)));
+};
+
+#else // __BORLANDC__
+
+template <typename T, bool is_a_class, bool convertible_to_int>
+struct empty_helper
+{
+ BOOST_STATIC_CONSTANT(bool, value = false);
+};
+
+template <typename T>
+struct empty_helper<T, true, false>
+{
+ BOOST_STATIC_CONSTANT(bool, value = (
+ sizeof(empty_helper_t1<T>) == sizeof(empty_helper_t2)
+ ));
+};
+
+template <typename T>
+struct is_empty_impl
+{
+ typedef typename remove_cv<T>::type cvt;
+ typedef typename add_reference<T>::type r_type;
+
+ BOOST_STATIC_CONSTANT(
+ bool, value = (
+ ::boost::detail::empty_helper<
+ cvt
+ , ::boost::is_class<T>::value
+ , ::boost::is_convertible< r_type,int>::value
+ >::value || BOOST_INTERNAL_IS_EMPTY(cvt));
+};
+
+#endif // __BORLANDC__
+
+} // namespace detail
+
+template <class T> struct is_empty : integral_constant<bool, ::boost::detail::is_empty_impl<T>::value> {};
+
+} // namespace boost
+
+#undef BOOST_INTERNAL_IS_EMPTY
+
+#endif // BOOST_TT_IS_EMPTY_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_enum.hpp b/third_party/boost/boost/type_traits/is_enum.hpp
new file mode 100644
index 0000000..73f162d
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_enum.hpp
@@ -0,0 +1,166 @@
+
+// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes, Howard
+// Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+
+#ifndef BOOST_TT_IS_ENUM_HPP_INCLUDED
+#define BOOST_TT_IS_ENUM_HPP_INCLUDED
+
+#include <boost/type_traits/intrinsics.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+#ifndef BOOST_IS_ENUM
+#include <boost/type_traits/add_reference.hpp>
+#include <boost/type_traits/is_arithmetic.hpp>
+#include <boost/type_traits/is_reference.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/is_array.hpp>
+#ifdef __GNUC__
+#include <boost/type_traits/is_function.hpp>
+#endif
+#include <boost/type_traits/detail/config.hpp>
+#if defined(BOOST_TT_HAS_CONFORMING_IS_CLASS_IMPLEMENTATION)
+# include <boost/type_traits/is_class.hpp>
+# include <boost/type_traits/is_union.hpp>
+#endif
+#endif
+
+namespace boost {
+
+#ifndef BOOST_IS_ENUM
+#if !(defined(__BORLANDC__) && (__BORLANDC__ <= 0x551))
+
+namespace detail {
+
+#if defined(BOOST_TT_HAS_CONFORMING_IS_CLASS_IMPLEMENTATION)
+
+template <typename T>
+struct is_class_or_union
+{
+ BOOST_STATIC_CONSTANT(bool, value = ::boost::is_class<T>::value || ::boost::is_union<T>::value);
+};
+
+#else
+
+template <typename T>
+struct is_class_or_union
+{
+# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x581))// we simply can't detect it this way.
+ BOOST_STATIC_CONSTANT(bool, value = false);
+# else
+ template <class U> static ::boost::type_traits::yes_type is_class_or_union_tester(void(U::*)(void));
+
+# if BOOST_WORKAROUND(__MWERKS__, <= 0x3000) // no SFINAE
+ static ::boost::type_traits::no_type is_class_or_union_tester(...);
+ BOOST_STATIC_CONSTANT(
+ bool, value = sizeof(is_class_or_union_tester(0)) == sizeof(::boost::type_traits::yes_type));
+# else
+ template <class U>
+ static ::boost::type_traits::no_type is_class_or_union_tester(...);
+ BOOST_STATIC_CONSTANT(
+ bool, value = sizeof(is_class_or_union_tester<T>(0)) == sizeof(::boost::type_traits::yes_type));
+# endif
+# endif
+};
+#endif
+
+struct int_convertible
+{
+ int_convertible(int);
+};
+
+// Don't evaluate convertibility to int_convertible unless the type
+// is non-arithmetic. This suppresses warnings with GCC.
+template <bool is_typename_arithmetic_or_reference = true>
+struct is_enum_helper
+{
+ template <typename T> struct type
+ {
+ BOOST_STATIC_CONSTANT(bool, value = false);
+ };
+};
+
+template <>
+struct is_enum_helper<false>
+{
+ template <typename T> struct type
+ {
+ static const bool value = ::boost::is_convertible<typename boost::add_reference<T>::type, ::boost::detail::int_convertible>::value;
+ };
+};
+
+template <typename T> struct is_enum_impl
+{
+ //typedef ::boost::add_reference<T> ar_t;
+ //typedef typename ar_t::type r_type;
+
+#if defined(__GNUC__)
+
+#ifdef BOOST_TT_HAS_CONFORMING_IS_CLASS_IMPLEMENTATION
+
+ // We MUST check for is_class_or_union on conforming compilers in
+ // order to correctly deduce that noncopyable types are not enums
+ // (dwa 2002/04/15)...
+ BOOST_STATIC_CONSTANT(bool, selector =
+ ::boost::is_arithmetic<T>::value
+ || ::boost::is_reference<T>::value
+ || ::boost::is_function<T>::value
+ || is_class_or_union<T>::value
+ || is_array<T>::value);
+#else
+ // ...however, not checking is_class_or_union on non-conforming
+ // compilers prevents a dependency recursion.
+ BOOST_STATIC_CONSTANT(bool, selector =
+ ::boost::is_arithmetic<T>::value
+ || ::boost::is_reference<T>::value
+ || ::boost::is_function<T>::value
+ || is_array<T>::value);
+#endif // BOOST_TT_HAS_CONFORMING_IS_CLASS_IMPLEMENTATION
+
+#else // !defined(__GNUC__):
+
+ BOOST_STATIC_CONSTANT(bool, selector =
+ ::boost::is_arithmetic<T>::value
+ || ::boost::is_reference<T>::value
+ || is_class_or_union<T>::value
+ || is_array<T>::value);
+
+#endif
+
+#if BOOST_WORKAROUND(__BORLANDC__, < 0x600)
+ typedef ::boost::detail::is_enum_helper<
+ ::boost::detail::is_enum_impl<T>::selector
+ > se_t;
+#else
+ typedef ::boost::detail::is_enum_helper<selector> se_t;
+#endif
+
+ typedef typename se_t::template type<T> helper;
+ BOOST_STATIC_CONSTANT(bool, value = helper::value);
+};
+
+} // namespace detail
+
+template <class T> struct is_enum : public integral_constant<bool, ::boost::detail::is_enum_impl<T>::value> {};
+
+#else // __BORLANDC__
+//
+// buggy is_convertible prevents working
+// implementation of is_enum:
+template <class T> struct is_enum : public integral_constant<bool, false> {};
+
+#endif
+
+#else // BOOST_IS_ENUM
+
+template <class T> struct is_enum : public integral_constant<bool, BOOST_IS_ENUM(T)> {};
+
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_ENUM_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_floating_point.hpp b/third_party/boost/boost/type_traits/is_floating_point.hpp
new file mode 100644
index 0000000..fef7fd7
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_floating_point.hpp
@@ -0,0 +1,30 @@
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000-2005.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TYPE_TRAITS_IS_FLOATING_HPP_INCLUDED
+#define BOOST_TYPE_TRAITS_IS_FLOATING_HPP_INCLUDED
+
+#include <boost/type_traits/integral_constant.hpp>
+
+namespace boost {
+
+//* is a type T a floating-point type described in the standard (3.9.1p8)
+ template <class T> struct is_floating_point : public false_type{};
+ template <class T> struct is_floating_point<const T> : public is_floating_point<T>{};
+ template <class T> struct is_floating_point<volatile const T> : public is_floating_point<T>{};
+ template <class T> struct is_floating_point<volatile T> : public is_floating_point<T>{};
+ template<> struct is_floating_point<float> : public true_type{};
+ template<> struct is_floating_point<double> : public true_type{};
+ template<> struct is_floating_point<long double> : public true_type{};
+
+#if defined(BOOST_HAS_FLOAT128)
+ template<> struct is_floating_point<__float128> : public true_type{};
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TYPE_TRAITS_IS_FLOAT_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_function.hpp b/third_party/boost/boost/type_traits/is_function.hpp
new file mode 100644
index 0000000..f77c1f0
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_function.hpp
@@ -0,0 +1,102 @@
+
+// Copyright 2000 John Maddock (john@johnmaddock.co.uk)
+// Copyright 2002 Aleksey Gurtovoy (agurtovoy@meta-comm.com)
+//
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_IS_FUNCTION_HPP_INCLUDED
+#define BOOST_TT_IS_FUNCTION_HPP_INCLUDED
+
+#include <boost/type_traits/is_reference.hpp>
+#include <boost/type_traits/detail/config.hpp>
+
+#if !defined(BOOST_TT_TEST_MS_FUNC_SIGS)
+# include <boost/type_traits/detail/is_function_ptr_helper.hpp>
+#else
+# include <boost/type_traits/detail/is_function_ptr_tester.hpp>
+# include <boost/type_traits/detail/yes_no_type.hpp>
+#endif
+
+// is a type a function?
+// Please note that this implementation is unnecessarily complex:
+// we could just use !is_convertible<T*, const volatile void*>::value,
+// except that some compilers erroneously allow conversions from
+// function pointers to void*.
+
+namespace boost {
+
+#if !defined( __CODEGEARC__ )
+
+namespace detail {
+
+#if !defined(BOOST_TT_TEST_MS_FUNC_SIGS)
+template<bool is_ref = true>
+struct is_function_chooser
+{
+ template< typename T > struct result_
+ : public false_type {};
+};
+
+template <>
+struct is_function_chooser<false>
+{
+ template< typename T > struct result_
+ : public ::boost::type_traits::is_function_ptr_helper<T*> {};
+};
+
+template <typename T>
+struct is_function_impl
+ : public is_function_chooser< ::boost::is_reference<T>::value >
+ ::BOOST_NESTED_TEMPLATE result_<T>
+{
+};
+
+#else
+
+template <typename T>
+struct is_function_impl
+{
+#if BOOST_WORKAROUND(BOOST_MSVC_FULL_VER, >= 140050000)
+#pragma warning(push)
+#pragma warning(disable:6334)
+#endif
+ static T* t;
+ BOOST_STATIC_CONSTANT(
+ bool, value = sizeof(::boost::type_traits::is_function_ptr_tester(t))
+ == sizeof(::boost::type_traits::yes_type)
+ );
+#if BOOST_WORKAROUND(BOOST_MSVC_FULL_VER, >= 140050000)
+#pragma warning(pop)
+#endif
+};
+
+template <typename T>
+struct is_function_impl<T&> : public false_type
+{};
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+template <typename T>
+struct is_function_impl<T&&> : public false_type
+{};
+#endif
+
+#endif
+
+} // namespace detail
+
+#endif // !defined( __CODEGEARC__ )
+
+#if defined( __CODEGEARC__ )
+template <class T> struct is_function : integral_constant<bool, __is_function(T)> {};
+#else
+template <class T> struct is_function : integral_constant<bool, ::boost::detail::is_function_impl<T>::value> {};
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+template <class T> struct is_function<T&&> : public false_type {};
+#endif
+#endif
+} // namespace boost
+
+#endif // BOOST_TT_IS_FUNCTION_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_fundamental.hpp b/third_party/boost/boost/type_traits/is_fundamental.hpp
new file mode 100644
index 0000000..f58767a
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_fundamental.hpp
@@ -0,0 +1,26 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_IS_FUNDAMENTAL_HPP_INCLUDED
+#define BOOST_TT_IS_FUNDAMENTAL_HPP_INCLUDED
+
+#include <boost/type_traits/is_arithmetic.hpp>
+#include <boost/type_traits/is_void.hpp>
+
+namespace boost {
+
+//* is a type T a fundamental type described in the standard (3.9.1)
+#if defined( __CODEGEARC__ )
+template <class T> struct is_fundamental : public integral_constant<bool, __is_fundamental(T)> {};
+#else
+template <class T> struct is_fundamental : public integral_constant<bool, ::boost::is_arithmetic<T>::value || ::boost::is_void<T>::value> {};
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_FUNDAMENTAL_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_integral.hpp b/third_party/boost/boost/type_traits/is_integral.hpp
new file mode 100644
index 0000000..691cfad
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_integral.hpp
@@ -0,0 +1,89 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_IS_INTEGRAL_HPP_INCLUDED
+#define BOOST_TT_IS_INTEGRAL_HPP_INCLUDED
+
+#include <boost/config.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+
+namespace boost {
+
+#if defined( __CODEGEARC__ )
+ template <class T>
+ struct is_integral : public integral_constant<bool, __is_integral(T)> {};
+#else
+
+template <class T> struct is_integral : public false_type {};
+template <class T> struct is_integral<const T> : public is_integral<T> {};
+template <class T> struct is_integral<volatile const T> : public is_integral<T>{};
+template <class T> struct is_integral<volatile T> : public is_integral<T>{};
+
+//* is a type T an [cv-qualified-] integral type described in the standard (3.9.1p3)
+// as an extension we include long long, as this is likely to be added to the
+// standard at a later date
+template<> struct is_integral<unsigned char> : public true_type {};
+template<> struct is_integral<unsigned short> : public true_type{};
+template<> struct is_integral<unsigned int> : public true_type{};
+template<> struct is_integral<unsigned long> : public true_type{};
+
+template<> struct is_integral<signed char> : public true_type{};
+template<> struct is_integral<short> : public true_type{};
+template<> struct is_integral<int> : public true_type{};
+template<> struct is_integral<long> : public true_type{};
+
+template<> struct is_integral<char> : public true_type{};
+template<> struct is_integral<bool> : public true_type{};
+
+#ifndef BOOST_NO_INTRINSIC_WCHAR_T
+// If the following line fails to compile and you're using the Intel
+// compiler, see http://lists.boost.org/MailArchives/boost-users/msg06567.php,
+// and define BOOST_NO_INTRINSIC_WCHAR_T on the command line.
+template<> struct is_integral<wchar_t> : public true_type{};
+#endif
+
+// Same set of integral types as in boost/type_traits/integral_promotion.hpp.
+// Please, keep in sync. -- Alexander Nasonov
+#if (defined(BOOST_INTEL_CXX_VERSION) && defined(_MSC_VER) && (BOOST_INTEL_CXX_VERSION <= 600)) \
+ || (defined(__BORLANDC__) && (__BORLANDC__ == 0x600) && (_MSC_VER < 1300))
+template<> struct is_integral<unsigned __int8> : public true_type{};
+template<> struct is_integral<unsigned __int16> : public true_type{};
+template<> struct is_integral<unsigned __int32> : public true_type{};
+template<> struct is_integral<__int8> : public true_type{};
+template<> struct is_integral<__int16> : public true_type{};
+template<> struct is_integral<__int32> : public true_type{};
+#ifdef __BORLANDC__
+template<> struct is_integral<unsigned __int64> : public true_type{};
+template<> struct is_integral<__int64> : public true_type{};
+#endif
+#endif
+
+# if defined(BOOST_HAS_LONG_LONG)
+template<> struct is_integral< ::boost::ulong_long_type> : public true_type{};
+template<> struct is_integral< ::boost::long_long_type> : public true_type{};
+#elif defined(BOOST_HAS_MS_INT64)
+template<> struct is_integral<unsigned __int64> : public true_type{};
+template<> struct is_integral<__int64> : public true_type{};
+#endif
+
+#ifdef BOOST_HAS_INT128
+template<> struct is_integral<boost::int128_type> : public true_type{};
+template<> struct is_integral<boost::uint128_type> : public true_type{};
+#endif
+#ifndef BOOST_NO_CXX11_CHAR16_T
+template<> struct is_integral<char16_t> : public true_type{};
+#endif
+#ifndef BOOST_NO_CXX11_CHAR32_T
+template<> struct is_integral<char32_t> : public true_type{};
+#endif
+
+#endif // non-CodeGear implementation
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_INTEGRAL_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_lvalue_reference.hpp b/third_party/boost/boost/type_traits/is_lvalue_reference.hpp
new file mode 100644
index 0000000..39e12ce
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_lvalue_reference.hpp
@@ -0,0 +1,49 @@
+
+// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes,
+// Howard Hinnant and John Maddock 2000.
+// (C) Copyright Mat Marcus, Jesse Jones and Adobe Systems Inc 2001
+
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+// Fixed is_pointer, is_lvalue_reference, is_const, is_volatile, is_same,
+// is_member_pointer based on the Simulated Partial Specialization work
+// of Mat Marcus and Jesse Jones. See http://opensource.adobe.com or
+// http://groups.yahoo.com/group/boost/message/5441
+// Some workarounds in here use ideas suggested from "Generic<Programming>:
+// Mappings between Types and Values"
+// by Andrei Alexandrescu (see http://www.cuj.com/experts/1810/alexandr.html).
+
+
+#ifndef BOOST_TT_IS_LVALUE_REFERENCE_HPP_INCLUDED
+#define BOOST_TT_IS_LVALUE_REFERENCE_HPP_INCLUDED
+
+#include <boost/type_traits/integral_constant.hpp>
+
+namespace boost {
+
+#if defined( __CODEGEARC__ )
+ template <class T> struct is_lvalue_reference : public integral_constant<bool, __is_reference(T)>{};
+#else
+
+ template <class T> struct is_lvalue_reference : public false_type{};
+ template <class T> struct is_lvalue_reference<T&> : public true_type{};
+
+#if defined(BOOST_ILLEGAL_CV_REFERENCES)
+// these are illegal specialisations; cv-qualifies applied to
+// references have no effect according to [8.3.2p1],
+// C++ Builder requires them though as it treats cv-qualified
+// references as distinct types...
+ template <class T> struct is_lvalue_reference<T&const> : public true_type{};
+ template <class T> struct is_lvalue_reference<T&volatile> : public true_type{};
+ template <class T> struct is_lvalue_reference<T&const volatile> : public true_type{};
+#endif
+
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_REFERENCE_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_member_function_pointer.hpp b/third_party/boost/boost/type_traits/is_member_function_pointer.hpp
new file mode 100644
index 0000000..c278f71
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_member_function_pointer.hpp
@@ -0,0 +1,120 @@
+
+// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes, Howard
+// Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+
+#ifndef BOOST_TT_IS_MEMBER_FUNCTION_POINTER_HPP_INCLUDED
+#define BOOST_TT_IS_MEMBER_FUNCTION_POINTER_HPP_INCLUDED
+
+#include <boost/type_traits/detail/config.hpp>
+#include <boost/detail/workaround.hpp>
+
+#if !BOOST_WORKAROUND(__BORLANDC__, < 0x600) && !defined(BOOST_TT_TEST_MS_FUNC_SIGS)
+ //
+ // Note: we use the "workaround" version for MSVC because it works for
+ // __stdcall etc function types, where as the partial specialisation
+ // version does not do so.
+ //
+# include <boost/type_traits/detail/is_mem_fun_pointer_impl.hpp>
+# include <boost/type_traits/remove_cv.hpp>
+# include <boost/type_traits/integral_constant.hpp>
+#else
+# include <boost/type_traits/is_reference.hpp>
+# include <boost/type_traits/is_array.hpp>
+# include <boost/type_traits/detail/yes_no_type.hpp>
+# include <boost/type_traits/detail/is_mem_fun_pointer_tester.hpp>
+#endif
+
+namespace boost {
+
+#if defined( __CODEGEARC__ )
+template <class T> struct is_member_function_pointer : public integral_constant<bool, __is_member_function_pointer( T )> {};
+#elif !BOOST_WORKAROUND(__BORLANDC__, < 0x600) && !defined(BOOST_TT_TEST_MS_FUNC_SIGS)
+
+template <class T> struct is_member_function_pointer
+ : public ::boost::integral_constant<bool, ::boost::type_traits::is_mem_fun_pointer_impl<typename remove_cv<T>::type>::value>{};
+
+#else
+
+namespace detail {
+
+#ifndef __BORLANDC__
+
+template <bool>
+struct is_mem_fun_pointer_select
+{
+ template <class T> struct result_ : public false_type{};
+};
+
+template <>
+struct is_mem_fun_pointer_select<false>
+{
+ template <typename T> struct result_
+ {
+#if BOOST_WORKAROUND(BOOST_MSVC_FULL_VER, >= 140050000)
+#pragma warning(push)
+#pragma warning(disable:6334)
+#endif
+ static T* make_t;
+ typedef result_<T> self_type;
+
+ BOOST_STATIC_CONSTANT(
+ bool, value = (
+ 1 == sizeof(::boost::type_traits::is_mem_fun_pointer_tester(self_type::make_t))
+ ));
+#if BOOST_WORKAROUND(BOOST_MSVC_FULL_VER, >= 140050000)
+#pragma warning(pop)
+#endif
+ };
+};
+
+template <typename T>
+struct is_member_function_pointer_impl
+ : public is_mem_fun_pointer_select<
+ ::boost::is_reference<T>::value || ::boost::is_array<T>::value>::template result_<T>{};
+
+template <typename T>
+struct is_member_function_pointer_impl<T&> : public false_type{};
+
+#else // Borland C++
+
+template <typename T>
+struct is_member_function_pointer_impl
+{
+ static T* m_t;
+ BOOST_STATIC_CONSTANT(
+ bool, value =
+ (1 == sizeof(type_traits::is_mem_fun_pointer_tester(m_t))) );
+};
+
+template <typename T>
+struct is_member_function_pointer_impl<T&>
+{
+ BOOST_STATIC_CONSTANT(bool, value = false);
+};
+
+#endif
+
+template<> struct is_member_function_pointer_impl<void> : public false_type{};
+#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
+template<> struct is_member_function_pointer_impl<void const> : public false_type{};
+template<> struct is_member_function_pointer_impl<void const volatile> : public false_type{};
+template<> struct is_member_function_pointer_impl<void volatile> : public false_type{};
+#endif
+
+} // namespace detail
+
+template <class T>
+struct is_member_function_pointer
+ : public integral_constant<bool, ::boost::detail::is_member_function_pointer_impl<T>::value>{};
+
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_MEMBER_FUNCTION_POINTER_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_member_pointer.hpp b/third_party/boost/boost/type_traits/is_member_pointer.hpp
new file mode 100644
index 0000000..80e9b44
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_member_pointer.hpp
@@ -0,0 +1,45 @@
+
+// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes,
+// Howard Hinnant and John Maddock 2000.
+// (C) Copyright Mat Marcus, Jesse Jones and Adobe Systems Inc 2001
+
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+// Fixed is_pointer, is_reference, is_const, is_volatile, is_same,
+// is_member_pointer based on the Simulated Partial Specialization work
+// of Mat Marcus and Jesse Jones. See http://opensource.adobe.com or
+// http://groups.yahoo.com/group/boost/message/5441
+// Some workarounds in here use ideas suggested from "Generic<Programming>:
+// Mappings between Types and Values"
+// by Andrei Alexandrescu (see http://www.cuj.com/experts/1810/alexandr.html).
+
+
+#ifndef BOOST_TT_IS_MEMBER_POINTER_HPP_INCLUDED
+#define BOOST_TT_IS_MEMBER_POINTER_HPP_INCLUDED
+
+#include <boost/detail/workaround.hpp>
+#include <boost/type_traits/is_member_function_pointer.hpp>
+
+namespace boost {
+
+#if defined( __CODEGEARC__ )
+template <class T> struct is_member_pointer : public integral_constant<bool, __is_member_pointer(T)>{};
+#else
+template <class T> struct is_member_pointer : public integral_constant<bool, ::boost::is_member_function_pointer<T>::value>{};
+template <class T, class U> struct is_member_pointer<U T::* > : public true_type{};
+
+#if !BOOST_WORKAROUND(__MWERKS__,<=0x3003) && !BOOST_WORKAROUND(__IBMCPP__, <=600)
+template <class T, class U> struct is_member_pointer<U T::*const> : public true_type{};
+template <class T, class U> struct is_member_pointer<U T::*const volatile> : public true_type{};
+template <class T, class U> struct is_member_pointer<U T::*volatile> : public true_type{};
+#endif
+
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_MEMBER_POINTER_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_nothrow_move_assignable.hpp b/third_party/boost/boost/type_traits/is_nothrow_move_assignable.hpp
new file mode 100644
index 0000000..96db1a0
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_nothrow_move_assignable.hpp
@@ -0,0 +1,81 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// (C) Copyright Eric Friedman 2002-2003.
+// (C) Copyright Antony Polukhin 2013.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_IS_NOTHROW_MOVE_ASSIGNABLE_HPP_INCLUDED
+#define BOOST_TT_IS_NOTHROW_MOVE_ASSIGNABLE_HPP_INCLUDED
+
+#include <boost/config.hpp>
+#include <boost/type_traits/has_trivial_move_assign.hpp>
+#include <boost/type_traits/has_nothrow_assign.hpp>
+#include <boost/type_traits/is_array.hpp>
+#include <boost/type_traits/is_reference.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/type_traits/declval.hpp>
+
+namespace boost {
+
+#ifdef BOOST_IS_NOTHROW_MOVE_ASSIGN
+
+template <class T>
+struct is_nothrow_move_assignable : public integral_constant<bool, BOOST_IS_NOTHROW_MOVE_ASSIGN(T)>{};
+template <class T> struct is_nothrow_move_assignable<T const> : public false_type{};
+template <class T> struct is_nothrow_move_assignable<T volatile> : public false_type{};
+template <class T> struct is_nothrow_move_assignable<T const volatile> : public false_type{};
+template <class T> struct is_nothrow_move_assignable<T&> : public false_type{};
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+template <class T> struct is_nothrow_move_assignable<T&&> : public false_type{};
+#endif
+
+#elif !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_SFINAE_EXPR)
+
+namespace detail{
+
+template <class T, class Enable = void>
+struct false_or_cpp11_noexcept_move_assignable: public ::boost::false_type {};
+
+template <class T>
+struct false_or_cpp11_noexcept_move_assignable <
+ T,
+ typename ::boost::enable_if_c<sizeof(T) && BOOST_NOEXCEPT_EXPR(::boost::declval<T&>() = ::boost::declval<T>())>::type
+ > : public ::boost::integral_constant<bool, BOOST_NOEXCEPT_EXPR(::boost::declval<T&>() = ::boost::declval<T>())>
+{};
+
+}
+
+template <class T>
+struct is_nothrow_move_assignable : public integral_constant<bool, ::boost::detail::false_or_cpp11_noexcept_move_assignable<T>::value>{};
+
+template <class T> struct is_nothrow_move_assignable<T const> : public ::boost::false_type {};
+template <class T> struct is_nothrow_move_assignable<T const volatile> : public ::boost::false_type{};
+template <class T> struct is_nothrow_move_assignable<T volatile> : public ::boost::false_type{};
+template <class T> struct is_nothrow_move_assignable<T&> : public ::boost::false_type{};
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+template <class T> struct is_nothrow_move_assignable<T&&> : public ::boost::false_type{};
+#endif
+
+#else
+
+template <class T>
+struct is_nothrow_move_assignable : public integral_constant<bool,
+ (::boost::has_trivial_move_assign<T>::value || ::boost::has_nothrow_assign<T>::value) && ! ::boost::is_array<T>::value>{};
+
+#endif
+
+
+template <> struct is_nothrow_move_assignable<void> : public false_type{};
+#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
+template <> struct is_nothrow_move_assignable<void const> : public false_type{};
+template <> struct is_nothrow_move_assignable<void const volatile> : public false_type{};
+template <> struct is_nothrow_move_assignable<void volatile> : public false_type{};
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_NOTHROW_MOVE_ASSIGNABLE_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_nothrow_move_constructible.hpp b/third_party/boost/boost/type_traits/is_nothrow_move_constructible.hpp
new file mode 100644
index 0000000..8f4cee2
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_nothrow_move_constructible.hpp
@@ -0,0 +1,86 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// (C) Copyright Eric Friedman 2002-2003.
+// (C) Copyright Antony Polukhin 2013.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_IS_NOTHROW_MOVE_CONSTRUCTIBLE_HPP_INCLUDED
+#define BOOST_TT_IS_NOTHROW_MOVE_CONSTRUCTIBLE_HPP_INCLUDED
+
+#include <boost/config.hpp>
+#include <boost/type_traits/intrinsics.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+#include <boost/detail/workaround.hpp>
+
+#ifdef BOOST_IS_NOTHROW_MOVE_CONSTRUCT
+
+namespace boost {
+
+template <class T>
+struct is_nothrow_move_constructible : public integral_constant<bool, BOOST_IS_NOTHROW_MOVE_CONSTRUCT(T)>{};
+
+template <class T> struct is_nothrow_move_constructible<volatile T> : public ::boost::false_type {};
+template <class T> struct is_nothrow_move_constructible<const volatile T> : public ::boost::false_type{};
+
+#elif !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_SFINAE_EXPR) && !BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40700)
+
+#include <boost/type_traits/declval.hpp>
+#include <boost/utility/enable_if.hpp>
+
+namespace boost{ namespace detail{
+
+template <class T, class Enable = void>
+struct false_or_cpp11_noexcept_move_constructible: public ::boost::false_type {};
+
+template <class T>
+struct false_or_cpp11_noexcept_move_constructible <
+ T,
+ typename ::boost::enable_if_c<sizeof(T) && BOOST_NOEXCEPT_EXPR(T(::boost::declval<T>()))>::type
+ > : public ::boost::integral_constant<bool, BOOST_NOEXCEPT_EXPR(T(::boost::declval<T>()))>
+{};
+
+}
+
+template <class T> struct is_nothrow_move_constructible
+ : public integral_constant<bool, ::boost::detail::false_or_cpp11_noexcept_move_constructible<T>::value>{};
+
+template <class T> struct is_nothrow_move_constructible<volatile T> : public ::boost::false_type {};
+template <class T> struct is_nothrow_move_constructible<const volatile T> : public ::boost::false_type{};
+template <class T, std::size_t N> struct is_nothrow_move_constructible<T[N]> : public ::boost::false_type{};
+template <class T> struct is_nothrow_move_constructible<T[]> : public ::boost::false_type{};
+
+#else
+
+#include <boost/type_traits/has_trivial_move_constructor.hpp>
+#include <boost/type_traits/has_nothrow_copy.hpp>
+#include <boost/type_traits/is_array.hpp>
+
+namespace boost{
+
+template <class T>
+struct is_nothrow_move_constructible
+ : public integral_constant<bool,
+ (::boost::has_trivial_move_constructor<T>::value || ::boost::has_nothrow_copy<T>::value) && !::boost::is_array<T>::value>
+{};
+
+#endif
+
+template <> struct is_nothrow_move_constructible<void> : false_type{};
+#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
+template <> struct is_nothrow_move_constructible<void const> : false_type{};
+template <> struct is_nothrow_move_constructible<void volatile> : false_type{};
+template <> struct is_nothrow_move_constructible<void const volatile> : false_type{};
+#endif
+// References are always trivially constructible, even if the thing they reference is not:
+template <class T> struct is_nothrow_move_constructible<T&> : public ::boost::true_type{};
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+template <class T> struct is_nothrow_move_constructible<T&&> : public ::boost::true_type{};
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_NOTHROW_MOVE_CONSTRUCTIBLE_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_pod.hpp b/third_party/boost/boost/type_traits/is_pod.hpp
new file mode 100644
index 0000000..9204c93
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_pod.hpp
@@ -0,0 +1,58 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_IS_POD_HPP_INCLUDED
+#define BOOST_TT_IS_POD_HPP_INCLUDED
+
+#include <boost/type_traits/detail/config.hpp>
+#include <boost/type_traits/is_void.hpp>
+#include <boost/type_traits/is_scalar.hpp>
+#include <boost/type_traits/intrinsics.hpp>
+
+#ifdef __SUNPRO_CC
+#include <boost/type_traits/is_function.hpp>
+#endif
+
+#include <cstddef>
+
+#ifndef BOOST_IS_POD
+#define BOOST_INTERNAL_IS_POD(T) false
+#else
+#define BOOST_INTERNAL_IS_POD(T) BOOST_IS_POD(T)
+#endif
+
+namespace boost {
+
+// forward declaration, needed by 'is_pod_array_helper' template below
+template< typename T > struct is_POD;
+
+template <typename T> struct is_pod
+: public integral_constant<bool, ::boost::is_scalar<T>::value || ::boost::is_void<T>::value || BOOST_INTERNAL_IS_POD(T)>
+{};
+
+#if !defined(BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS)
+template <typename T, std::size_t sz> struct is_pod<T[sz]> : public is_pod<T>{};
+#endif
+
+
+// the following help compilers without partial specialization support:
+template<> struct is_pod<void> : public true_type{};
+
+#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
+template<> struct is_pod<void const> : public true_type{};
+template<> struct is_pod<void const volatile> : public true_type{};
+template<> struct is_pod<void volatile> : public true_type{};
+#endif
+
+template<class T> struct is_POD : public is_pod<T>{};
+
+} // namespace boost
+
+#undef BOOST_INTERNAL_IS_POD
+
+#endif // BOOST_TT_IS_POD_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_pointer.hpp b/third_party/boost/boost/type_traits/is_pointer.hpp
new file mode 100644
index 0000000..55f8a3e
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_pointer.hpp
@@ -0,0 +1,47 @@
+
+// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes,
+// Howard Hinnant and John Maddock 2000.
+// (C) Copyright Mat Marcus, Jesse Jones and Adobe Systems Inc 2001
+
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+// Fixed is_pointer, is_reference, is_const, is_volatile, is_same,
+// is_member_pointer based on the Simulated Partial Specialization work
+// of Mat Marcus and Jesse Jones. See http://opensource.adobe.com or
+// http://groups.yahoo.com/group/boost/message/5441
+// Some workarounds in here use ideas suggested from "Generic<Programming>:
+// Mappings between Types and Values"
+// by Andrei Alexandrescu (see http://www.cuj.com/experts/1810/alexandr.html).
+
+
+#ifndef BOOST_TT_IS_POINTER_HPP_INCLUDED
+#define BOOST_TT_IS_POINTER_HPP_INCLUDED
+
+#include <boost/type_traits/integral_constant.hpp>
+
+namespace boost {
+
+#if defined( __CODEGEARC__ )
+template <class T> struct is_pointer : public integral_constant<bool, __is_pointer(T)>{};
+#else
+template <class T> struct is_pointer : public false_type{};
+template <class T> struct is_pointer<T*> : public true_type{};
+template <class T> struct is_pointer<T*const> : public true_type{};
+template <class T> struct is_pointer<T*const volatile> : public true_type{};
+template <class T> struct is_pointer<T*volatile> : public true_type{};
+
+#ifdef BOOST_MSVC
+template <class T> struct is_pointer<T const> : public is_pointer<T>{};
+template <class T> struct is_pointer<T const volatile> : public is_pointer<T>{};
+template <class T> struct is_pointer<T volatile> : public is_pointer<T>{};
+#endif
+
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_POINTER_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_reference.hpp b/third_party/boost/boost/type_traits/is_reference.hpp
new file mode 100644
index 0000000..4584a2d
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_reference.hpp
@@ -0,0 +1,29 @@
+
+// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes,
+// Howard Hinnant and John Maddock 2000, 2010.
+// (C) Copyright Mat Marcus, Jesse Jones and Adobe Systems Inc 2001
+
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_IS_REFERENCE_HPP_INCLUDED
+#define BOOST_TT_IS_REFERENCE_HPP_INCLUDED
+
+#include <boost/type_traits/is_lvalue_reference.hpp>
+#include <boost/type_traits/is_rvalue_reference.hpp>
+
+namespace boost {
+
+template <class T> struct is_reference
+ : public
+ integral_constant<
+ bool,
+ ::boost::is_lvalue_reference<T>::value || ::boost::is_rvalue_reference<T>::value>
+{};
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_REFERENCE_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_rvalue_reference.hpp b/third_party/boost/boost/type_traits/is_rvalue_reference.hpp
new file mode 100644
index 0000000..df7a1af
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_rvalue_reference.hpp
@@ -0,0 +1,24 @@
+
+// (C) John Maddock 2010.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_IS_RVALUE_REFERENCE_HPP_INCLUDED
+#define BOOST_TT_IS_RVALUE_REFERENCE_HPP_INCLUDED
+
+#include <boost/config.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+
+namespace boost {
+
+template <class T> struct is_rvalue_reference : public false_type {};
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+template <class T> struct is_rvalue_reference<T&&> : public true_type {};
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_REFERENCE_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_same.hpp b/third_party/boost/boost/type_traits/is_same.hpp
new file mode 100644
index 0000000..6a0bd7c
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_same.hpp
@@ -0,0 +1,40 @@
+
+// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes,
+// Howard Hinnant and John Maddock 2000.
+// (C) Copyright Mat Marcus, Jesse Jones and Adobe Systems Inc 2001
+
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+// Fixed is_pointer, is_reference, is_const, is_volatile, is_same,
+// is_member_pointer based on the Simulated Partial Specialization work
+// of Mat Marcus and Jesse Jones. See http://opensource.adobe.com or
+// http://groups.yahoo.com/group/boost/message/5441
+// Some workarounds in here use ideas suggested from "Generic<Programming>:
+// Mappings between Types and Values"
+// by Andrei Alexandrescu (see http://www.cuj.com/experts/1810/alexandr.html).
+
+
+#ifndef BOOST_TT_IS_SAME_HPP_INCLUDED
+#define BOOST_TT_IS_SAME_HPP_INCLUDED
+
+#include <boost/type_traits/integral_constant.hpp>
+
+namespace boost {
+
+
+ template <class T, class U> struct is_same : public false_type {};
+ template <class T> struct is_same<T,T> : public true_type {};
+#if BOOST_WORKAROUND(__BORLANDC__, < 0x600)
+// without this, Borland's compiler gives the wrong answer for
+// references to arrays:
+ template <class T> struct is_same<T&, T&> : public true_type{};
+#endif
+
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_SAME_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_scalar.hpp b/third_party/boost/boost/type_traits/is_scalar.hpp
new file mode 100644
index 0000000..3031440
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_scalar.hpp
@@ -0,0 +1,27 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_IS_SCALAR_HPP_INCLUDED
+#define BOOST_TT_IS_SCALAR_HPP_INCLUDED
+
+#include <boost/type_traits/is_arithmetic.hpp>
+#include <boost/type_traits/is_enum.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/type_traits/is_member_pointer.hpp>
+#include <boost/config.hpp>
+
+namespace boost {
+
+template <typename T>
+struct is_scalar
+ : public integral_constant<bool, ::boost::is_arithmetic<T>::value || ::boost::is_enum<T>::value || ::boost::is_pointer<T>::value || ::boost::is_member_pointer<T>::value>
+{};
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_SCALAR_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_signed.hpp b/third_party/boost/boost/type_traits/is_signed.hpp
new file mode 100644
index 0000000..93d7285
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_signed.hpp
@@ -0,0 +1,163 @@
+
+// (C) Copyright John Maddock 2005.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+
+#ifndef BOOST_TT_IS_SIGNED_HPP_INCLUDED
+#define BOOST_TT_IS_SIGNED_HPP_INCLUDED
+
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/is_enum.hpp>
+#include <climits>
+
+namespace boost {
+
+#if !defined( __CODEGEARC__ )
+
+#if !(defined(BOOST_MSVC) && BOOST_MSVC <= 1310) && \
+ !(defined(__EDG_VERSION__) && __EDG_VERSION__ <= 238) &&\
+ !defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION)
+
+namespace detail{
+
+template <class T>
+struct is_signed_values
+{
+ //
+ // Note that we cannot use BOOST_STATIC_CONSTANT here, using enum's
+ // rather than "real" static constants simply doesn't work or give
+ // the correct answer.
+ //
+ typedef typename remove_cv<T>::type no_cv_t;
+ static const no_cv_t minus_one = (static_cast<no_cv_t>(-1));
+ static const no_cv_t zero = (static_cast<no_cv_t>(0));
+};
+
+template <class T>
+struct is_signed_helper
+{
+ typedef typename remove_cv<T>::type no_cv_t;
+ BOOST_STATIC_CONSTANT(bool, value = (!(::boost::detail::is_signed_values<T>::minus_one > boost::detail::is_signed_values<T>::zero)));
+};
+
+template <bool integral_type>
+struct is_signed_select_helper
+{
+ template <class T>
+ struct rebind
+ {
+ typedef is_signed_helper<T> type;
+ };
+};
+
+template <>
+struct is_signed_select_helper<false>
+{
+ template <class T>
+ struct rebind
+ {
+ typedef false_type type;
+ };
+};
+
+template <class T>
+struct is_signed_impl
+{
+ typedef ::boost::detail::is_signed_select_helper< ::boost::is_integral<T>::value || ::boost::is_enum<T>::value> selector;
+ typedef typename selector::template rebind<T> binder;
+ typedef typename binder::type type;
+ BOOST_STATIC_CONSTANT(bool, value = type::value);
+};
+
+}
+
+template <class T> struct is_signed : public integral_constant<bool, boost::detail::is_signed_impl<T>::value> {};
+
+#else
+
+template <class T> struct is_signed : public false_type{};
+
+#endif
+
+#else //defined( __CODEGEARC__ )
+ template <class T> struct is_signed : public integral_constant<bool, __is_signed(T)>{};
+#endif
+
+template <> struct is_signed<signed char> : public true_type{};
+template <> struct is_signed<const signed char> : public true_type{};
+template <> struct is_signed<volatile signed char> : public true_type{};
+template <> struct is_signed<const volatile signed char> : public true_type{};
+template <> struct is_signed<short> : public true_type{};
+template <> struct is_signed<const short> : public true_type{};
+template <> struct is_signed<volatile short> : public true_type{};
+template <> struct is_signed<const volatile short> : public true_type{};
+template <> struct is_signed<int> : public true_type{};
+template <> struct is_signed<const int> : public true_type{};
+template <> struct is_signed<volatile int> : public true_type{};
+template <> struct is_signed<const volatile int> : public true_type{};
+template <> struct is_signed<long> : public true_type{};
+template <> struct is_signed<const long> : public true_type{};
+template <> struct is_signed<volatile long> : public true_type{};
+template <> struct is_signed<const volatile long> : public true_type{};
+
+template <> struct is_signed<unsigned char> : public false_type{};
+template <> struct is_signed<const unsigned char> : public false_type{};
+template <> struct is_signed<volatile unsigned char> : public false_type{};
+template <> struct is_signed<const volatile unsigned char> : public false_type{};
+template <> struct is_signed<unsigned short> : public false_type{};
+template <> struct is_signed<const unsigned short> : public false_type{};
+template <> struct is_signed<volatile unsigned short> : public false_type{};
+template <> struct is_signed<const volatile unsigned short> : public false_type{};
+template <> struct is_signed<unsigned int> : public false_type{};
+template <> struct is_signed<const unsigned int> : public false_type{};
+template <> struct is_signed<volatile unsigned int> : public false_type{};
+template <> struct is_signed<const volatile unsigned int> : public false_type{};
+template <> struct is_signed<unsigned long> : public false_type{};
+template <> struct is_signed<const unsigned long> : public false_type{};
+template <> struct is_signed<volatile unsigned long> : public false_type{};
+template <> struct is_signed<const volatile unsigned long> : public false_type{};
+#ifdef BOOST_HAS_LONG_LONG
+template <> struct is_signed< ::boost::long_long_type> : public true_type{};
+template <> struct is_signed<const ::boost::long_long_type> : public true_type{};
+template <> struct is_signed<volatile ::boost::long_long_type> : public true_type{};
+template <> struct is_signed<const volatile ::boost::long_long_type> : public true_type{};
+
+template <> struct is_signed< ::boost::ulong_long_type> : public false_type{};
+template <> struct is_signed<const ::boost::ulong_long_type> : public false_type{};
+template <> struct is_signed<volatile ::boost::ulong_long_type> : public false_type{};
+template <> struct is_signed<const volatile ::boost::ulong_long_type> : public false_type{};
+#endif
+#if defined(CHAR_MIN)
+#if CHAR_MIN != 0
+template <> struct is_signed<char> : public true_type{};
+template <> struct is_signed<const char> : public true_type{};
+template <> struct is_signed<volatile char> : public true_type{};
+template <> struct is_signed<const volatile char> : public true_type{};
+#else
+template <> struct is_signed<char> : public false_type{};
+template <> struct is_signed<const char> : public false_type{};
+template <> struct is_signed<volatile char> : public false_type{};
+template <> struct is_signed<const volatile char> : public false_type{};
+#endif
+#endif
+#if defined(WCHAR_MIN) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
+#if WCHAR_MIN != 0
+template <> struct is_signed<wchar_t> : public true_type{};
+template <> struct is_signed<const wchar_t> : public true_type{};
+template <> struct is_signed<volatile wchar_t> : public true_type{};
+template <> struct is_signed<const volatile wchar_t> : public true_type{};
+#else
+template <> struct is_signed<wchar_t> : public false_type{};
+template <> struct is_signed<const wchar_t> : public false_type{};
+template <> struct is_signed<volatile wchar_t> : public false_type{};
+template <> struct is_signed<const volatile wchar_t> : public false_type{};
+#endif
+#endif
+} // namespace boost
+
+#endif // BOOST_TT_IS_MEMBER_FUNCTION_POINTER_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_stateless.hpp b/third_party/boost/boost/type_traits/is_stateless.hpp
new file mode 100644
index 0000000..8a008ca
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_stateless.hpp
@@ -0,0 +1,33 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_IS_STATELESS_HPP_INCLUDED
+#define BOOST_TT_IS_STATELESS_HPP_INCLUDED
+
+#include <boost/type_traits/has_trivial_constructor.hpp>
+#include <boost/type_traits/has_trivial_copy.hpp>
+#include <boost/type_traits/has_trivial_destructor.hpp>
+#include <boost/type_traits/is_class.hpp>
+#include <boost/type_traits/is_empty.hpp>
+#include <boost/config.hpp>
+
+namespace boost {
+
+template <typename T>
+struct is_stateless
+ : public integral_constant<bool,
+ (::boost::has_trivial_constructor<T>::value
+ && ::boost::has_trivial_copy<T>::value
+ && ::boost::has_trivial_destructor<T>::value
+ && ::boost::is_class<T>::value
+ && ::boost::is_empty<T>::value)>
+{};
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_STATELESS_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_union.hpp b/third_party/boost/boost/type_traits/is_union.hpp
new file mode 100644
index 0000000..da8b4b2
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_union.hpp
@@ -0,0 +1,31 @@
+
+// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes, Howard
+// Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+
+#ifndef BOOST_TT_IS_UNION_HPP_INCLUDED
+#define BOOST_TT_IS_UNION_HPP_INCLUDED
+
+#include <boost/type_traits/intrinsics.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+
+namespace boost {
+
+#ifdef BOOST_IS_UNION
+template <class T> struct is_union : public integral_constant<bool, BOOST_IS_UNION(T)> {};
+#else
+template <class T> struct is_union : public integral_constant<bool, false> {};
+#endif
+
+template <class T> struct is_union<T const> : public is_union<T>{};
+template <class T> struct is_union<T volatile const> : public is_union<T>{};
+template <class T> struct is_union<T volatile> : public is_union<T>{};
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_UNION_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_unsigned.hpp b/third_party/boost/boost/type_traits/is_unsigned.hpp
new file mode 100644
index 0000000..b97e474
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_unsigned.hpp
@@ -0,0 +1,163 @@
+
+// (C) Copyright John Maddock 2005.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+
+#ifndef BOOST_TT_IS_UNSIGNED_HPP_INCLUDED
+#define BOOST_TT_IS_UNSIGNED_HPP_INCLUDED
+
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/is_enum.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+
+#include <climits>
+
+namespace boost {
+
+#if !defined( __CODEGEARC__ )
+
+#if !(defined(BOOST_MSVC) && BOOST_MSVC <= 1310) &&\
+ !(defined(__EDG_VERSION__) && __EDG_VERSION__ <= 238) &&\
+ !defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION)
+
+namespace detail{
+
+template <class T>
+struct is_unsigned_values
+{
+ //
+ // Note that we cannot use BOOST_STATIC_CONSTANT here, using enum's
+ // rather than "real" static constants simply doesn't work or give
+ // the correct answer.
+ //
+ typedef typename remove_cv<T>::type no_cv_t;
+ static const no_cv_t minus_one = (static_cast<no_cv_t>(-1));
+ static const no_cv_t zero = (static_cast<no_cv_t>(0));
+};
+
+template <class T>
+struct is_ununsigned_helper
+{
+ BOOST_STATIC_CONSTANT(bool, value = (::boost::detail::is_unsigned_values<T>::minus_one > ::boost::detail::is_unsigned_values<T>::zero));
+};
+
+template <bool integral_type>
+struct is_unsigned_select_helper
+{
+ template <class T>
+ struct rebind
+ {
+ typedef is_ununsigned_helper<T> type;
+ };
+};
+
+template <>
+struct is_unsigned_select_helper<false>
+{
+ template <class T>
+ struct rebind
+ {
+ typedef false_type type;
+ };
+};
+
+template <class T>
+struct is_unsigned
+{
+ typedef ::boost::detail::is_unsigned_select_helper< ::boost::is_integral<T>::value || ::boost::is_enum<T>::value > selector;
+ typedef typename selector::template rebind<T> binder;
+ typedef typename binder::type type;
+ BOOST_STATIC_CONSTANT(bool, value = type::value);
+};
+
+} // namespace detail
+
+template <class T> struct is_unsigned : public integral_constant<bool, boost::detail::is_unsigned<T>::value> {};
+
+#else
+
+template <class T> struct is_unsigned : public false_type{};
+
+#endif
+
+#else // defined( __CODEGEARC__ )
+template <class T> struct is_unsigned : public integral_constant<bool, __is_unsigned(T)> {};
+#endif
+
+template <> struct is_unsigned<unsigned char> : public true_type{};
+template <> struct is_unsigned<const unsigned char> : public true_type{};
+template <> struct is_unsigned<volatile unsigned char> : public true_type{};
+template <> struct is_unsigned<const volatile unsigned char> : public true_type{};
+template <> struct is_unsigned<unsigned short> : public true_type{};
+template <> struct is_unsigned<const unsigned short> : public true_type{};
+template <> struct is_unsigned<volatile unsigned short> : public true_type{};
+template <> struct is_unsigned<const volatile unsigned short> : public true_type{};
+template <> struct is_unsigned<unsigned int> : public true_type{};
+template <> struct is_unsigned<const unsigned int> : public true_type{};
+template <> struct is_unsigned<volatile unsigned int> : public true_type{};
+template <> struct is_unsigned<const volatile unsigned int> : public true_type{};
+template <> struct is_unsigned<unsigned long> : public true_type{};
+template <> struct is_unsigned<const unsigned long> : public true_type{};
+template <> struct is_unsigned<volatile unsigned long> : public true_type{};
+template <> struct is_unsigned<const volatile unsigned long> : public true_type{};
+
+template <> struct is_unsigned<signed char> : public false_type{};
+template <> struct is_unsigned<const signed char> : public false_type{};
+template <> struct is_unsigned<volatile signed char> : public false_type{};
+template <> struct is_unsigned<const volatile signed char> : public false_type{};
+template <> struct is_unsigned< short> : public false_type{};
+template <> struct is_unsigned<const short> : public false_type{};
+template <> struct is_unsigned<volatile short> : public false_type{};
+template <> struct is_unsigned<const volatile short> : public false_type{};
+template <> struct is_unsigned< int> : public false_type{};
+template <> struct is_unsigned<const int> : public false_type{};
+template <> struct is_unsigned<volatile int> : public false_type{};
+template <> struct is_unsigned<const volatile int> : public false_type{};
+template <> struct is_unsigned< long> : public false_type{};
+template <> struct is_unsigned<const long> : public false_type{};
+template <> struct is_unsigned<volatile long> : public false_type{};
+template <> struct is_unsigned<const volatile long> : public false_type{};
+#ifdef BOOST_HAS_LONG_LONG
+template <> struct is_unsigned< ::boost::ulong_long_type> : public true_type{};
+template <> struct is_unsigned<const ::boost::ulong_long_type> : public true_type{};
+template <> struct is_unsigned<volatile ::boost::ulong_long_type> : public true_type{};
+template <> struct is_unsigned<const volatile ::boost::ulong_long_type> : public true_type{};
+
+template <> struct is_unsigned< ::boost::long_long_type> : public false_type{};
+template <> struct is_unsigned<const ::boost::long_long_type> : public false_type{};
+template <> struct is_unsigned<volatile ::boost::long_long_type> : public false_type{};
+template <> struct is_unsigned<const volatile ::boost::long_long_type> : public false_type{};
+#endif
+#if defined(CHAR_MIN)
+#if CHAR_MIN == 0
+template <> struct is_unsigned<char> : public true_type{};
+template <> struct is_unsigned<const char> : public true_type{};
+template <> struct is_unsigned<volatile char> : public true_type{};
+template <> struct is_unsigned<const volatile char> : public true_type{};
+#else
+template <> struct is_unsigned<char> : public false_type{};
+template <> struct is_unsigned<const char> : public false_type{};
+template <> struct is_unsigned<volatile char> : public false_type{};
+template <> struct is_unsigned<const volatile char> : public false_type{};
+#endif
+#endif
+#if !defined(BOOST_NO_INTRINSIC_WCHAR_T) && defined(WCHAR_MIN)
+#if WCHAR_MIN == 0
+template <> struct is_unsigned<wchar_t> : public true_type{};
+template <> struct is_unsigned<const wchar_t> : public true_type{};
+template <> struct is_unsigned<volatile wchar_t> : public true_type{};
+template <> struct is_unsigned<const volatile wchar_t> : public true_type{};
+#else
+template <> struct is_unsigned<wchar_t> : public false_type{};
+template <> struct is_unsigned<const wchar_t> : public false_type{};
+template <> struct is_unsigned<volatile wchar_t> : public false_type{};
+template <> struct is_unsigned<const volatile wchar_t> : public false_type{};
+#endif
+#endif
+} // namespace boost
+
+#endif // BOOST_TT_IS_MEMBER_FUNCTION_POINTER_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_void.hpp b/third_party/boost/boost/type_traits/is_void.hpp
new file mode 100644
index 0000000..183f8ab
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_void.hpp
@@ -0,0 +1,26 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_IS_VOID_HPP_INCLUDED
+#define BOOST_TT_IS_VOID_HPP_INCLUDED
+
+#include <boost/type_traits/integral_constant.hpp>
+
+namespace boost {
+
+template <class T>
+struct is_void : public false_type {};
+
+template<> struct is_void<void> : public true_type {};
+template<> struct is_void<const void> : public true_type{};
+template<> struct is_void<const volatile void> : public true_type{};
+template<> struct is_void<volatile void> : public true_type{};
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_VOID_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/is_volatile.hpp b/third_party/boost/boost/type_traits/is_volatile.hpp
new file mode 100644
index 0000000..2181821
--- /dev/null
+++ b/third_party/boost/boost/type_traits/is_volatile.hpp
@@ -0,0 +1,45 @@
+
+// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes,
+// Howard Hinnant and John Maddock 2000.
+// (C) Copyright Mat Marcus, Jesse Jones and Adobe Systems Inc 2001
+
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+// Fixed is_pointer, is_reference, is_const, is_volatile, is_same,
+// is_member_pointer based on the Simulated Partial Specialization work
+// of Mat Marcus and Jesse Jones. See http://opensource.adobe.com or
+// http://groups.yahoo.com/group/boost/message/5441
+// Some workarounds in here use ideas suggested from "Generic<Programming>:
+// Mappings between Types and Values"
+// by Andrei Alexandrescu (see http://www.cuj.com/experts/1810/alexandr.html).
+
+
+#ifndef BOOST_TT_IS_VOLATILE_HPP_INCLUDED
+#define BOOST_TT_IS_VOLATILE_HPP_INCLUDED
+
+#include <boost/type_traits/integral_constant.hpp>
+
+namespace boost {
+
+#if defined( __CODEGEARC__ )
+
+ template <class T>
+ struct is_volatile : public integral_constant<bool, __is_volatile(T)> {};
+
+#else
+
+ template <class T>
+ struct is_volatile : public false_type {};
+ template <class T> struct is_volatile<T volatile> : public true_type{};
+ template <class T, size_t N> struct is_volatile<T volatile[N]> : public true_type{};
+ template <class T> struct is_volatile<T volatile[]> : public true_type{};
+
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TT_IS_VOLATILE_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/make_signed.hpp b/third_party/boost/boost/type_traits/make_signed.hpp
new file mode 100644
index 0000000..a53771e
--- /dev/null
+++ b/third_party/boost/boost/type_traits/make_signed.hpp
@@ -0,0 +1,130 @@
+
+// (C) Copyright John Maddock 2007.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_MAKE_SIGNED_HPP_INCLUDED
+#define BOOST_TT_MAKE_SIGNED_HPP_INCLUDED
+
+#include <boost/type_traits/conditional.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/is_signed.hpp>
+#include <boost/type_traits/is_unsigned.hpp>
+#include <boost/type_traits/is_enum.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/is_volatile.hpp>
+#include <boost/type_traits/add_const.hpp>
+#include <boost/type_traits/add_volatile.hpp>
+#include <boost/static_assert.hpp>
+
+namespace boost {
+
+template <class T>
+struct make_signed
+{
+private:
+ BOOST_STATIC_ASSERT_MSG(( ::boost::is_integral<T>::value || ::boost::is_enum<T>::value), "The template argument to make_signed must be an integer or enum type.");
+ BOOST_STATIC_ASSERT_MSG(!(::boost::is_same<typename remove_cv<T>::type, bool>::value), "The template argument to make_signed must not be the type bool.");
+
+ typedef typename remove_cv<T>::type t_no_cv;
+ typedef typename conditional<
+ (::boost::is_signed<T>::value
+ && ::boost::is_integral<T>::value
+ && ! ::boost::is_same<t_no_cv, char>::value
+ && ! ::boost::is_same<t_no_cv, wchar_t>::value
+ && ! ::boost::is_same<t_no_cv, bool>::value),
+ T,
+ typename conditional<
+ (::boost::is_integral<T>::value
+ && ! ::boost::is_same<t_no_cv, char>::value
+ && ! ::boost::is_same<t_no_cv, wchar_t>::value
+ && ! ::boost::is_same<t_no_cv, bool>::value),
+ typename conditional<
+ is_same<t_no_cv, unsigned char>::value,
+ signed char,
+ typename conditional<
+ is_same<t_no_cv, unsigned short>::value,
+ signed short,
+ typename conditional<
+ is_same<t_no_cv, unsigned int>::value,
+ int,
+ typename conditional<
+ is_same<t_no_cv, unsigned long>::value,
+ long,
+#if defined(BOOST_HAS_LONG_LONG)
+#ifdef BOOST_HAS_INT128
+ typename conditional<
+ sizeof(t_no_cv) == sizeof(boost::long_long_type),
+ boost::long_long_type,
+ boost::int128_type
+ >::type
+#else
+ boost::long_long_type
+#endif
+#elif defined(BOOST_HAS_MS_INT64)
+ __int64
+#else
+ long
+#endif
+ >::type
+ >::type
+ >::type
+ >::type,
+ // Not a regular integer type:
+ typename conditional<
+ sizeof(t_no_cv) == sizeof(unsigned char),
+ signed char,
+ typename conditional<
+ sizeof(t_no_cv) == sizeof(unsigned short),
+ signed short,
+ typename conditional<
+ sizeof(t_no_cv) == sizeof(unsigned int),
+ int,
+ typename conditional<
+ sizeof(t_no_cv) == sizeof(unsigned long),
+ long,
+#if defined(BOOST_HAS_LONG_LONG)
+#ifdef BOOST_HAS_INT128
+ typename conditional<
+ sizeof(t_no_cv) == sizeof(boost::long_long_type),
+ boost::long_long_type,
+ boost::int128_type
+ >::type
+#else
+ boost::long_long_type
+#endif
+#elif defined(BOOST_HAS_MS_INT64)
+ __int64
+#else
+ long
+#endif
+ >::type
+ >::type
+ >::type
+ >::type
+ >::type
+ >::type base_integer_type;
+
+ // Add back any const qualifier:
+ typedef typename conditional<
+ is_const<T>::value,
+ typename add_const<base_integer_type>::type,
+ base_integer_type
+ >::type const_base_integer_type;
+public:
+ // Add back any volatile qualifier:
+ typedef typename conditional<
+ is_volatile<T>::value,
+ typename add_volatile<const_base_integer_type>::type,
+ const_base_integer_type
+ >::type type;
+};
+
+} // namespace boost
+
+#endif // BOOST_TT_ADD_REFERENCE_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/remove_bounds.hpp b/third_party/boost/boost/type_traits/remove_bounds.hpp
new file mode 100644
index 0000000..7de49d9
--- /dev/null
+++ b/third_party/boost/boost/type_traits/remove_bounds.hpp
@@ -0,0 +1,21 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_REMOVE_BOUNDS_HPP_INCLUDED
+#define BOOST_TT_REMOVE_BOUNDS_HPP_INCLUDED
+
+#include <boost/type_traits/remove_extent.hpp>
+
+namespace boost
+{
+
+template <class T> struct remove_bounds : public remove_extent<T> {};
+
+} // namespace boost
+
+#endif // BOOST_TT_REMOVE_BOUNDS_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/remove_const.hpp b/third_party/boost/boost/type_traits/remove_const.hpp
new file mode 100644
index 0000000..901cb15
--- /dev/null
+++ b/third_party/boost/boost/type_traits/remove_const.hpp
@@ -0,0 +1,33 @@
+
+// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes, Howard
+// Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+
+#ifndef BOOST_TT_REMOVE_CONST_HPP_INCLUDED
+#define BOOST_TT_REMOVE_CONST_HPP_INCLUDED
+
+#include <boost/config.hpp>
+#include <cstddef>
+#include <boost/detail/workaround.hpp>
+
+namespace boost {
+
+ // convert a type T to a non-cv-qualified type - remove_const<T>
+ template <class T> struct remove_const{ typedef T type; };
+ template <class T> struct remove_const<T const>{ typedef T type; };
+
+#if !defined(BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS)
+ template <class T, std::size_t N> struct remove_const<T const[N]>{ typedef T type[N]; };
+#if !BOOST_WORKAROUND(__BORLANDC__, < 0x600) && !defined(__IBMCPP__) && !BOOST_WORKAROUND(__DMC__, BOOST_TESTED_AT(0x840))
+ template <class T> struct remove_const<T const[]>{ typedef T type[]; };
+#endif
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TT_REMOVE_CONST_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/remove_cv.hpp b/third_party/boost/boost/type_traits/remove_cv.hpp
new file mode 100644
index 0000000..8d8c5ef
--- /dev/null
+++ b/third_party/boost/boost/type_traits/remove_cv.hpp
@@ -0,0 +1,40 @@
+
+// (C) Copyright Dave Abrahams, Steve Cleary, Beman Dawes, Howard
+// Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+
+#ifndef BOOST_TT_REMOVE_CV_HPP_INCLUDED
+#define BOOST_TT_REMOVE_CV_HPP_INCLUDED
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#include <cstddef>
+
+namespace boost {
+
+ // convert a type T to a non-cv-qualified type - remove_cv<T>
+template <class T> struct remove_cv{ typedef T type; };
+template <class T> struct remove_cv<T const>{ typedef T type; };
+template <class T> struct remove_cv<T volatile>{ typedef T type; };
+template <class T> struct remove_cv<T const volatile>{ typedef T type; };
+
+#if !defined(BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS)
+template <class T, std::size_t N> struct remove_cv<T const[N]>{ typedef T type[N]; };
+template <class T, std::size_t N> struct remove_cv<T const volatile[N]>{ typedef T type[N]; };
+template <class T, std::size_t N> struct remove_cv<T volatile[N]>{ typedef T type[N]; };
+#if !BOOST_WORKAROUND(__BORLANDC__, < 0x600) && !defined(__IBMCPP__) && !BOOST_WORKAROUND(__DMC__, BOOST_TESTED_AT(0x840))
+template <class T> struct remove_cv<T const[]>{ typedef T type[]; };
+template <class T> struct remove_cv<T const volatile[]>{ typedef T type[]; };
+template <class T> struct remove_cv<T volatile[]>{ typedef T type[]; };
+#endif
+#endif
+
+
+} // namespace boost
+
+#endif // BOOST_TT_REMOVE_CV_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/remove_extent.hpp b/third_party/boost/boost/type_traits/remove_extent.hpp
new file mode 100644
index 0000000..0b50a07
--- /dev/null
+++ b/third_party/boost/boost/type_traits/remove_extent.hpp
@@ -0,0 +1,35 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000-2005.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_REMOVE_EXTENT_HPP_INCLUDED
+#define BOOST_TT_REMOVE_EXTENT_HPP_INCLUDED
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#include <cstddef>
+
+namespace boost {
+
+template <class T> struct remove_extent{ typedef T type; };
+
+#if !defined(BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS)
+template <typename T, std::size_t N> struct remove_extent<T[N]> { typedef T type; };
+template <typename T, std::size_t N> struct remove_extent<T const[N]> { typedef T const type; };
+template <typename T, std::size_t N> struct remove_extent<T volatile [N]> { typedef T volatile type; };
+template <typename T, std::size_t N> struct remove_extent<T const volatile [N]> { typedef T const volatile type; };
+#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610)) && !defined(__IBMCPP__) && !BOOST_WORKAROUND(__DMC__, BOOST_TESTED_AT(0x840))
+template <typename T> struct remove_extent<T[]> { typedef T type; };
+template <typename T> struct remove_extent<T const[]> { typedef T const type; };
+template <typename T> struct remove_extent<T volatile[]> { typedef T volatile type; };
+template <typename T> struct remove_extent<T const volatile[]> { typedef T const volatile type; };
+#endif
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TT_REMOVE_BOUNDS_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/remove_pointer.hpp b/third_party/boost/boost/type_traits/remove_pointer.hpp
new file mode 100644
index 0000000..7e8af96
--- /dev/null
+++ b/third_party/boost/boost/type_traits/remove_pointer.hpp
@@ -0,0 +1,77 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_REMOVE_POINTER_HPP_INCLUDED
+#define BOOST_TT_REMOVE_POINTER_HPP_INCLUDED
+
+#include <boost/config.hpp>
+
+#if defined(BOOST_MSVC)
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+#endif
+
+namespace boost {
+
+#ifdef BOOST_MSVC
+
+namespace detail{
+
+ //
+ // We need all this crazy indirection because a type such as:
+ //
+ // T (*const)(U)
+ //
+ // Does not bind to a <T*> or <T*const> partial specialization with VC10 and earlier
+ //
+ template <class T>
+ struct remove_pointer_imp
+ {
+ typedef T type;
+ };
+
+ template <class T>
+ struct remove_pointer_imp<T*>
+ {
+ typedef T type;
+ };
+
+ template <class T, bool b>
+ struct remove_pointer_imp3
+ {
+ typedef typename remove_pointer_imp<typename boost::remove_cv<T>::type>::type type;
+ };
+
+ template <class T>
+ struct remove_pointer_imp3<T, false>
+ {
+ typedef T type;
+ };
+
+ template <class T>
+ struct remove_pointer_imp2
+ {
+ typedef typename remove_pointer_imp3<T, ::boost::is_pointer<T>::value>::type type;
+ };
+}
+
+template <class T> struct remove_pointer{ typedef typename boost::detail::remove_pointer_imp2<T>::type type; };
+
+#else
+
+template <class T> struct remove_pointer{ typedef T type; };
+template <class T> struct remove_pointer<T*>{ typedef T type; };
+template <class T> struct remove_pointer<T*const>{ typedef T type; };
+template <class T> struct remove_pointer<T*volatile>{ typedef T type; };
+template <class T> struct remove_pointer<T*const volatile>{ typedef T type; };
+
+#endif
+
+} // namespace boost
+
+#endif // BOOST_TT_REMOVE_POINTER_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/remove_reference.hpp b/third_party/boost/boost/type_traits/remove_reference.hpp
new file mode 100644
index 0000000..f75e677
--- /dev/null
+++ b/third_party/boost/boost/type_traits/remove_reference.hpp
@@ -0,0 +1,54 @@
+
+// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_REMOVE_REFERENCE_HPP_INCLUDED
+#define BOOST_TT_REMOVE_REFERENCE_HPP_INCLUDED
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+
+namespace boost {
+
+
+namespace detail{
+//
+// We can't filter out rvalue_references at the same level as
+// references or we get ambiguities from msvc:
+//
+template <class T>
+struct remove_rvalue_ref
+{
+ typedef T type;
+};
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+template <class T>
+struct remove_rvalue_ref<T&&>
+{
+ typedef T type;
+};
+#endif
+
+} // namespace detail
+
+template <class T> struct remove_reference{ typedef typename boost::detail::remove_rvalue_ref<T>::type type; };
+template <class T> struct remove_reference<T&>{ typedef T type; };
+
+#if defined(BOOST_ILLEGAL_CV_REFERENCES)
+// these are illegal specialisations; cv-qualifies applied to
+// references have no effect according to [8.3.2p1],
+// C++ Builder requires them though as it treats cv-qualified
+// references as distinct types...
+template <class T> struct remove_reference<T&const>{ typedef T type; };
+template <class T> struct remove_reference<T&volatile>{ typedef T type; };
+template <class T> struct remove_reference<T&const volatile>{ typedef T type; };
+#endif
+
+
+} // namespace boost
+
+#endif // BOOST_TT_REMOVE_REFERENCE_HPP_INCLUDED
diff --git a/third_party/boost/boost/type_traits/type_with_alignment.hpp b/third_party/boost/boost/type_traits/type_with_alignment.hpp
new file mode 100644
index 0000000..b592edd
--- /dev/null
+++ b/third_party/boost/boost/type_traits/type_with_alignment.hpp
@@ -0,0 +1,259 @@
+// (C) Copyright John Maddock 2000.
+// Use, modification and distribution are subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt).
+//
+// See http://www.boost.org/libs/type_traits for most recent version including documentation.
+
+#ifndef BOOST_TT_TYPE_WITH_ALIGNMENT_INCLUDED
+#define BOOST_TT_TYPE_WITH_ALIGNMENT_INCLUDED
+
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/type_traits/is_pod.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/config.hpp>
+#include <cstddef>
+#include <boost/detail/workaround.hpp>
+
+#ifdef BOOST_MSVC
+# pragma warning(push)
+# pragma warning(disable: 4121) // alignment is sensitive to packing
+#endif
+
+#ifdef _MSC_VER
+#include <boost/type_traits/conditional.hpp>
+#endif
+
+namespace boost {
+ namespace detail{
+
+#ifndef __BORLANDC__
+
+ union max_align
+ {
+ char c;
+ short s;
+ int i;
+ long l;
+#ifndef BOOST_NO_LONG_LONG
+ boost::long_long_type ll;
+#endif
+#ifdef BOOST_HAS_INT128
+ boost::int128_type i128;
+#endif
+ float f;
+ double d;
+ long double ld;
+#ifdef BOOST_HAS_FLOAT128
+ __float128 f128;
+#endif
+ };
+
+template <std::size_t Target, bool check> struct long_double_alignment{ typedef long double type; };
+template <std::size_t Target> struct long_double_alignment<Target, false>{ typedef boost::detail::max_align type; };
+
+template <std::size_t Target, bool check> struct double_alignment{ typedef double type; };
+template <std::size_t Target> struct double_alignment<Target, false>{ typedef typename long_double_alignment<Target, boost::alignment_of<long double>::value >= Target>::type type; };
+
+#ifndef BOOST_NO_LONG_LONG
+template <std::size_t Target, bool check> struct long_long_alignment{ typedef boost::long_long_type type; };
+template <std::size_t Target> struct long_long_alignment<Target, false>{ typedef typename double_alignment<Target, boost::alignment_of<double>::value >= Target>::type type; };
+#endif
+
+template <std::size_t Target, bool check> struct long_alignment{ typedef long type; };
+#ifndef BOOST_NO_LONG_LONG
+template <std::size_t Target> struct long_alignment<Target, false>{ typedef typename long_long_alignment<Target, boost::alignment_of<boost::long_long_type>::value >= Target>::type type; };
+#else
+template <std::size_t Target> struct long_alignment<Target, false>{ typedef typename double_alignment<Target, boost::alignment_of<double>::value >= Target>::type type; };
+#endif
+
+template <std::size_t Target, bool check> struct int_alignment{ typedef int type; };
+template <std::size_t Target> struct int_alignment<Target, false>{ typedef typename long_alignment<Target, boost::alignment_of<long>::value >= Target>::type type; };
+
+template <std::size_t Target, bool check> struct short_alignment{ typedef short type; };
+template <std::size_t Target> struct short_alignment<Target, false>{ typedef typename int_alignment<Target, boost::alignment_of<int>::value >= Target>::type type; };
+
+template <std::size_t Target, bool check> struct char_alignment{ typedef char type; };
+template <std::size_t Target> struct char_alignment<Target, false>{ typedef typename short_alignment<Target, boost::alignment_of<short>::value >= Target>::type type; };
+
+}
+
+template <std::size_t Align>
+struct type_with_alignment
+{
+ typedef typename boost::detail::char_alignment<Align, boost::alignment_of<char>::value >= Align>::type type;
+};
+
+#if (defined(__GNUC__) || (defined (__SUNPRO_CC) && (__SUNPRO_CC >= 0x5130)) || defined(__clang__)) && !defined(BOOST_TT_DISABLE_INTRINSICS)
+namespace tt_align_ns {
+struct __attribute__((__aligned__(2))) a2 {};
+struct __attribute__((__aligned__(4))) a4 {};
+struct __attribute__((__aligned__(8))) a8 {};
+struct __attribute__((__aligned__(16))) a16 {};
+struct __attribute__((__aligned__(32))) a32 {};
+struct __attribute__((__aligned__(64))) a64 {};
+struct __attribute__((__aligned__(128))) a128 {};
+}
+
+template<> struct type_with_alignment<1> { public: typedef char type; };
+template<> struct type_with_alignment<2> { public: typedef tt_align_ns::a2 type; };
+template<> struct type_with_alignment<4> { public: typedef tt_align_ns::a4 type; };
+template<> struct type_with_alignment<8> { public: typedef tt_align_ns::a8 type; };
+template<> struct type_with_alignment<16> { public: typedef tt_align_ns::a16 type; };
+template<> struct type_with_alignment<32> { public: typedef tt_align_ns::a32 type; };
+template<> struct type_with_alignment<64> { public: typedef tt_align_ns::a64 type; };
+template<> struct type_with_alignment<128> { public: typedef tt_align_ns::a128 type; };
+
+template<> struct is_pod< ::boost::tt_align_ns::a2> : public true_type{};
+template<> struct is_pod< ::boost::tt_align_ns::a4> : public true_type{};
+template<> struct is_pod< ::boost::tt_align_ns::a8> : public true_type{};
+template<> struct is_pod< ::boost::tt_align_ns::a16> : public true_type{};
+template<> struct is_pod< ::boost::tt_align_ns::a32> : public true_type{};
+template<> struct is_pod< ::boost::tt_align_ns::a64> : public true_type{};
+template<> struct is_pod< ::boost::tt_align_ns::a128> : public true_type{};
+
+#endif
+#if (defined(BOOST_MSVC) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && !defined(BOOST_TT_DISABLE_INTRINSICS)
+//
+// MSVC supports types which have alignments greater than the normal
+// maximum: these are used for example in the types __m64 and __m128
+// to provide types with alignment requirements which match the SSE
+// registers. Therefore we extend type_with_alignment<> to support
+// such types, however, we have to be careful to use a builtin type
+// whenever possible otherwise we break previously working code:
+// see http://article.gmane.org/gmane.comp.lib.boost.devel/173011
+// for an example and test case. Thus types like a8 below will
+// be used *only* if the existing implementation can't provide a type
+// with suitable alignment. This does mean however, that type_with_alignment<>
+// may return a type which cannot be passed through a function call
+// by value (and neither can any type containing such a type like
+// Boost.Optional). However, this only happens when we have no choice
+// in the matter because no other "ordinary" type is available.
+//
+namespace tt_align_ns {
+struct __declspec(align(8)) a8 {
+ char m[8];
+ typedef a8 type;
+};
+struct __declspec(align(16)) a16 {
+ char m[16];
+ typedef a16 type;
+};
+struct __declspec(align(32)) a32 {
+ char m[32];
+ typedef a32 type;
+};
+struct __declspec(align(64)) a64
+{
+ char m[64];
+ typedef a64 type;
+};
+struct __declspec(align(128)) a128 {
+ char m[128];
+ typedef a128 type;
+};
+}
+
+template<> struct type_with_alignment<8>
+{
+ typedef boost::conditional<
+ ::boost::alignment_of<boost::detail::max_align>::value < 8,
+ tt_align_ns::a8,
+ boost::detail::char_alignment<8, false> >::type t1;
+public:
+ typedef t1::type type;
+};
+template<> struct type_with_alignment<16>
+{
+ typedef boost::conditional<
+ ::boost::alignment_of<boost::detail::max_align>::value < 16,
+ tt_align_ns::a16,
+ boost::detail::char_alignment<16, false> >::type t1;
+public:
+ typedef t1::type type;
+};
+template<> struct type_with_alignment<32>
+{
+ typedef boost::conditional<
+ ::boost::alignment_of<boost::detail::max_align>::value < 32,
+ tt_align_ns::a32,
+ boost::detail::char_alignment<32, false> >::type t1;
+public:
+ typedef t1::type type;
+};
+template<> struct type_with_alignment<64> {
+ typedef boost::conditional<
+ ::boost::alignment_of<boost::detail::max_align>::value < 64,
+ tt_align_ns::a64,
+ boost::detail::char_alignment<64, false> >::type t1;
+public:
+ typedef t1::type type;
+};
+template<> struct type_with_alignment<128> {
+ typedef boost::conditional<
+ ::boost::alignment_of<boost::detail::max_align>::value < 128,
+ tt_align_ns::a128,
+ boost::detail::char_alignment<128, false> >::type t1;
+public:
+ typedef t1::type type;
+};
+
+template<> struct is_pod< ::boost::tt_align_ns::a8> : public true_type{};
+template<> struct is_pod< ::boost::tt_align_ns::a16> : public true_type{};
+template<> struct is_pod< ::boost::tt_align_ns::a32> : public true_type{};
+template<> struct is_pod< ::boost::tt_align_ns::a64> : public true_type{};
+template<> struct is_pod< ::boost::tt_align_ns::a128> : public true_type{};
+
+#endif
+
+#else
+
+//
+// Borland specific version, we have this for two reasons:
+// 1) The version above doesn't always compile (with the new test cases for example)
+// 2) Because of Borlands #pragma option we can create types with alignments that are
+// greater that the largest aligned builtin type.
+
+namespace tt_align_ns{
+#pragma option push -a16
+struct a2{ short s; };
+struct a4{ int s; };
+struct a8{ double s; };
+struct a16{ long double s; };
+#pragma option pop
+}
+
+namespace detail {
+
+typedef ::boost::tt_align_ns::a16 max_align;
+
+}
+//#if ! BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x610))
+template <> struct is_pod< ::boost::tt_align_ns::a2> : public true_type{};
+template <> struct is_pod< ::boost::tt_align_ns::a4> : public true_type{};
+template <> struct is_pod< ::boost::tt_align_ns::a8> : public true_type{};
+template <> struct is_pod< ::boost::tt_align_ns::a16> : public true_type{};
+//#endif
+
+template <std::size_t N> struct type_with_alignment
+{
+ // We should never get to here, but if we do use the maximally
+ // aligned type:
+ // BOOST_STATIC_ASSERT(0);
+ typedef tt_align_ns::a16 type;
+};
+template <> struct type_with_alignment<1>{ typedef char type; };
+template <> struct type_with_alignment<2>{ typedef tt_align_ns::a2 type; };
+template <> struct type_with_alignment<4>{ typedef tt_align_ns::a4 type; };
+template <> struct type_with_alignment<8>{ typedef tt_align_ns::a8 type; };
+template <> struct type_with_alignment<16>{ typedef tt_align_ns::a16 type; };
+
+#endif
+
+} // namespace boost
+
+#ifdef BOOST_MSVC
+# pragma warning(pop)
+#endif
+
+#endif // BOOST_TT_TYPE_WITH_ALIGNMENT_INCLUDED
diff --git a/third_party/boost/boost/utility/addressof.hpp b/third_party/boost/boost/utility/addressof.hpp
new file mode 100644
index 0000000..db4da80
--- /dev/null
+++ b/third_party/boost/boost/utility/addressof.hpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2014 Glen Fernandes
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_UTILITY_ADDRESSOF_HPP
+#define BOOST_UTILITY_ADDRESSOF_HPP
+
+// The header file at this path is deprecated;
+// use boost/core/addressof.hpp instead.
+
+#include <boost/core/addressof.hpp>
+
+#endif
diff --git a/third_party/boost/boost/utility/compare_pointees.hpp b/third_party/boost/boost/utility/compare_pointees.hpp
new file mode 100644
index 0000000..31b05c2
--- /dev/null
+++ b/third_party/boost/boost/utility/compare_pointees.hpp
@@ -0,0 +1,67 @@
+// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
+//
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/optional for documentation.
+//
+// You are welcome to contact the author at:
+// fernando_cacciola@hotmail.com
+//
+#ifndef BOOST_UTILITY_COMPARE_POINTEES_25AGO2003_HPP
+#define BOOST_UTILITY_COMPARE_POINTEES_25AGO2003_HPP
+
+#include<functional>
+
+namespace boost {
+
+// template<class OP> bool equal_pointees(OP const& x, OP const& y);
+// template<class OP> struct equal_pointees_t;
+//
+// Being OP a model of OptionalPointee (either a pointer or an optional):
+//
+// If both x and y have valid pointees, returns the result of (*x == *y)
+// If only one has a valid pointee, returns false.
+// If none have valid pointees, returns true.
+// No-throw
+template<class OptionalPointee>
+inline
+bool equal_pointees ( OptionalPointee const& x, OptionalPointee const& y )
+{
+ return (!x) != (!y) ? false : ( !x ? true : (*x) == (*y) ) ;
+}
+
+template<class OptionalPointee>
+struct equal_pointees_t : std::binary_function<OptionalPointee,OptionalPointee,bool>
+{
+ bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const
+ { return equal_pointees(x,y) ; }
+} ;
+
+// template<class OP> bool less_pointees(OP const& x, OP const& y);
+// template<class OP> struct less_pointees_t;
+//
+// Being OP a model of OptionalPointee (either a pointer or an optional):
+//
+// If y has not a valid pointee, returns false.
+// ElseIf x has not a valid pointee, returns true.
+// ElseIf both x and y have valid pointees, returns the result of (*x < *y)
+// No-throw
+template<class OptionalPointee>
+inline
+bool less_pointees ( OptionalPointee const& x, OptionalPointee const& y )
+{
+ return !y ? false : ( !x ? true : (*x) < (*y) ) ;
+}
+
+template<class OptionalPointee>
+struct less_pointees_t : std::binary_function<OptionalPointee,OptionalPointee,bool>
+{
+ bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const
+ { return less_pointees(x,y) ; }
+} ;
+
+} // namespace boost
+
+#endif
diff --git a/third_party/boost/boost/utility/declval.hpp b/third_party/boost/boost/utility/declval.hpp
new file mode 100644
index 0000000..229e9a3
--- /dev/null
+++ b/third_party/boost/boost/utility/declval.hpp
@@ -0,0 +1,13 @@
+// declval.hpp -------------------------------------------------------------//
+
+// Copyright 2010 Vicente J. Botet Escriba
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_UTILITY_DECLVAL_HPP
+#define BOOST_UTILITY_DECLVAL_HPP
+
+#include <boost/type_traits/declval.hpp>
+
+#endif // BOOST_UTILITY_DECLVAL_HPP
diff --git a/third_party/boost/boost/utility/enable_if.hpp b/third_party/boost/boost/utility/enable_if.hpp
new file mode 100644
index 0000000..803bfca
--- /dev/null
+++ b/third_party/boost/boost/utility/enable_if.hpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2014 Glen Fernandes
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_UTILITY_ENABLE_IF_HPP
+#define BOOST_UTILITY_ENABLE_IF_HPP
+
+// The header file at this path is deprecated;
+// use boost/core/enable_if.hpp instead.
+
+#include <boost/core/enable_if.hpp>
+
+#endif
diff --git a/third_party/boost/boost/utility/swap.hpp b/third_party/boost/boost/utility/swap.hpp
new file mode 100644
index 0000000..dd9ecd9
--- /dev/null
+++ b/third_party/boost/boost/utility/swap.hpp
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2014 Glen Fernandes
+ *
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#ifndef BOOST_UTILITY_SWAP_HPP
+#define BOOST_UTILITY_SWAP_HPP
+
+// The header file at this path is deprecated;
+// use boost/core/swap.hpp instead.
+
+#include <boost/core/swap.hpp>
+
+#endif
diff --git a/third_party/boost/boost/variant/apply_visitor.hpp b/third_party/boost/boost/variant/apply_visitor.hpp
new file mode 100644
index 0000000..53bada0
--- /dev/null
+++ b/third_party/boost/boost/variant/apply_visitor.hpp
@@ -0,0 +1,20 @@
+//-----------------------------------------------------------------------------
+// boost variant/apply_visitor.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2003
+// Eric Friedman
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_VARIANT_APPLY_VISITOR_HPP
+#define BOOST_VARIANT_APPLY_VISITOR_HPP
+
+#include "boost/variant/detail/apply_visitor_unary.hpp"
+#include "boost/variant/detail/apply_visitor_binary.hpp"
+#include "boost/variant/detail/apply_visitor_delayed.hpp"
+
+#endif // BOOST_VARIANT_APPLY_VISITOR_HPP
diff --git a/third_party/boost/boost/variant/detail/apply_visitor_binary.hpp b/third_party/boost/boost/variant/detail/apply_visitor_binary.hpp
new file mode 100644
index 0000000..e5e22e1
--- /dev/null
+++ b/third_party/boost/boost/variant/detail/apply_visitor_binary.hpp
@@ -0,0 +1,280 @@
+//-----------------------------------------------------------------------------
+// boost variant/detail/apply_visitor_binary.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2002-2003 Eric Friedman
+// Copyright (c) 2014 Antony Polukhin
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP
+#define BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP
+
+#include "boost/config.hpp"
+#include "boost/detail/workaround.hpp"
+#include "boost/variant/detail/generic_result_type.hpp"
+
+#include "boost/variant/detail/apply_visitor_unary.hpp"
+
+#if BOOST_WORKAROUND(__EDG__, BOOST_TESTED_AT(302))
+#include "boost/utility/enable_if.hpp"
+#include "boost/mpl/not.hpp"
+#include "boost/type_traits/is_const.hpp"
+#endif
+
+
+#if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
+# include "boost/variant/detail/has_result_type.hpp"
+#endif
+
+namespace boost {
+
+//////////////////////////////////////////////////////////////////////////
+// function template apply_visitor(visitor, visitable1, visitable2)
+//
+// Visits visitable1 and visitable2 such that their values (which we
+// shall call x and y, respectively) are used as arguments in the
+// expression visitor(x, y).
+//
+
+namespace detail { namespace variant {
+
+template <typename Visitor, typename Value1>
+class apply_visitor_binary_invoke
+{
+public: // visitor typedefs
+
+ typedef typename Visitor::result_type
+ result_type;
+
+private: // representation
+
+ Visitor& visitor_;
+ Value1& value1_;
+
+public: // structors
+
+ apply_visitor_binary_invoke(Visitor& visitor, Value1& value1) BOOST_NOEXCEPT
+ : visitor_(visitor)
+ , value1_(value1)
+ {
+ }
+
+public: // visitor interfaces
+
+ template <typename Value2>
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
+ operator()(Value2& value2)
+ {
+ return visitor_(value1_, value2);
+ }
+
+private:
+ apply_visitor_binary_invoke& operator=(const apply_visitor_binary_invoke&);
+};
+
+template <typename Visitor, typename Visitable2>
+class apply_visitor_binary_unwrap
+{
+public: // visitor typedefs
+
+ typedef typename Visitor::result_type
+ result_type;
+
+private: // representation
+
+ Visitor& visitor_;
+ Visitable2& visitable2_;
+
+public: // structors
+
+ apply_visitor_binary_unwrap(Visitor& visitor, Visitable2& visitable2) BOOST_NOEXCEPT
+ : visitor_(visitor)
+ , visitable2_(visitable2)
+ {
+ }
+
+public: // visitor interfaces
+
+ template <typename Value1>
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
+ operator()(Value1& value1)
+ {
+ apply_visitor_binary_invoke<
+ Visitor
+ , Value1
+ > invoker(visitor_, value1);
+
+ return boost::apply_visitor(invoker, visitable2_);
+ }
+
+private:
+ apply_visitor_binary_unwrap& operator=(const apply_visitor_binary_unwrap&);
+
+};
+
+}} // namespace detail::variant
+
+//
+// nonconst-visitor version:
+//
+
+#if !BOOST_WORKAROUND(__EDG__, BOOST_TESTED_AT(302))
+
+# define BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(V) \
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename V::result_type) \
+ /**/
+
+#else // EDG-based compilers
+
+# define BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(V) \
+ typename enable_if< \
+ mpl::not_< is_const< V > > \
+ , BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename V::result_type) \
+ >::type \
+ /**/
+
+#endif // EDG-based compilers workaround
+
+template <typename Visitor, typename Visitable1, typename Visitable2>
+inline
+ BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(Visitor)
+apply_visitor(
+ Visitor& visitor
+ , Visitable1& visitable1, Visitable2& visitable2
+ )
+{
+ ::boost::detail::variant::apply_visitor_binary_unwrap<
+ Visitor, Visitable2
+ > unwrapper(visitor, visitable2);
+
+ return boost::apply_visitor(unwrapper, visitable1);
+}
+
+#undef BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE
+
+//
+// const-visitor version:
+//
+
+template <typename Visitor, typename Visitable1, typename Visitable2>
+inline
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
+ typename Visitor::result_type
+ )
+apply_visitor(
+ const Visitor& visitor
+ , Visitable1& visitable1, Visitable2& visitable2
+ )
+{
+ ::boost::detail::variant::apply_visitor_binary_unwrap<
+ const Visitor, Visitable2
+ > unwrapper(visitor, visitable2);
+
+ return boost::apply_visitor(unwrapper, visitable1);
+}
+
+
+#if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
+
+//////////////////////////////////////////////////////////////////////////
+// function template apply_visitor(visitor, visitable1, visitable2)
+//
+// C++14 part.
+//
+
+namespace detail { namespace variant {
+
+template <typename Visitor, typename Value1>
+class apply_visitor_binary_invoke_cpp14
+{
+ Visitor& visitor_;
+ Value1& value1_;
+
+public: // structors
+
+ apply_visitor_binary_invoke_cpp14(Visitor& visitor, Value1& value1) BOOST_NOEXCEPT
+ : visitor_(visitor)
+ , value1_(value1)
+ {
+ }
+
+public: // visitor interfaces
+
+ template <typename Value2>
+ decltype(auto) operator()(Value2& value2)
+ {
+ return visitor_(value1_, value2);
+ }
+
+private:
+ apply_visitor_binary_invoke_cpp14& operator=(const apply_visitor_binary_invoke_cpp14&);
+};
+
+template <typename Visitor, typename Visitable2>
+class apply_visitor_binary_unwrap_cpp14
+{
+ Visitor& visitor_;
+ Visitable2& visitable2_;
+
+public: // structors
+
+ apply_visitor_binary_unwrap_cpp14(Visitor& visitor, Visitable2& visitable2) BOOST_NOEXCEPT
+ : visitor_(visitor)
+ , visitable2_(visitable2)
+ {
+ }
+
+public: // visitor interfaces
+
+ template <typename Value1>
+ decltype(auto) operator()(Value1& value1)
+ {
+ apply_visitor_binary_invoke_cpp14<
+ Visitor
+ , Value1
+ > invoker(visitor_, value1);
+
+ return boost::apply_visitor(invoker, visitable2_);
+ }
+
+private:
+ apply_visitor_binary_unwrap_cpp14& operator=(const apply_visitor_binary_unwrap_cpp14&);
+};
+
+}} // namespace detail::variant
+
+template <typename Visitor, typename Visitable1, typename Visitable2>
+inline decltype(auto) apply_visitor(Visitor& visitor, Visitable1& visitable1, Visitable2& visitable2,
+ typename boost::disable_if<
+ boost::detail::variant::has_result_type<Visitor>
+ >::type* = 0)
+{
+ ::boost::detail::variant::apply_visitor_binary_unwrap_cpp14<
+ Visitor, Visitable2
+ > unwrapper(visitor, visitable2);
+
+ return boost::apply_visitor(unwrapper, visitable1);
+}
+
+template <typename Visitor, typename Visitable1, typename Visitable2>
+inline decltype(auto) apply_visitor(const Visitor& visitor, Visitable1& visitable1, Visitable2& visitable2,
+ typename boost::disable_if<
+ boost::detail::variant::has_result_type<Visitor>
+ >::type* = 0)
+{
+ ::boost::detail::variant::apply_visitor_binary_unwrap_cpp14<
+ const Visitor, Visitable2
+ > unwrapper(visitor, visitable2);
+
+ return boost::apply_visitor(unwrapper, visitable1);
+}
+
+#endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
+
+} // namespace boost
+
+#endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_BINARY_HPP
diff --git a/third_party/boost/boost/variant/detail/apply_visitor_delayed.hpp b/third_party/boost/boost/variant/detail/apply_visitor_delayed.hpp
new file mode 100644
index 0000000..29f4614
--- /dev/null
+++ b/third_party/boost/boost/variant/detail/apply_visitor_delayed.hpp
@@ -0,0 +1,151 @@
+//-----------------------------------------------------------------------------
+// boost variant/detail/apply_visitor_delayed.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2002-2003
+// Eric Friedman
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_VARIANT_DETAIL_APPLY_VISITOR_DELAYED_HPP
+#define BOOST_VARIANT_DETAIL_APPLY_VISITOR_DELAYED_HPP
+
+#include "boost/variant/detail/generic_result_type.hpp"
+
+#include "boost/variant/detail/apply_visitor_unary.hpp"
+#include "boost/variant/detail/apply_visitor_binary.hpp"
+#include "boost/variant/variant_fwd.hpp" // for BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
+
+
+#include "boost/variant/detail/has_result_type.hpp"
+#include <boost/core/enable_if.hpp>
+
+namespace boost {
+
+//////////////////////////////////////////////////////////////////////////
+// function template apply_visitor(visitor)
+//
+// Returns a function object, overloaded for unary and binary usage, that
+// visits its arguments using visitor (or a copy of visitor) via
+// * apply_visitor( visitor, [argument] )
+// under unary invocation, or
+// * apply_visitor( visitor, [argument1], [argument2] )
+// under binary invocation.
+//
+// NOTE: Unlike other apply_visitor forms, the visitor object must be
+// non-const; this prevents user from giving temporary, to disastrous
+// effect (i.e., returned function object would have dead reference).
+//
+
+template <typename Visitor>
+class apply_visitor_delayed_t
+{
+public: // visitor typedefs
+
+ typedef typename Visitor::result_type
+ result_type;
+
+private: // representation
+
+ Visitor& visitor_;
+
+public: // structors
+
+ explicit apply_visitor_delayed_t(Visitor& visitor) BOOST_NOEXCEPT
+ : visitor_(visitor)
+ {
+ }
+
+#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
+
+public: // N-ary visitor interface
+ template <typename... Visitables>
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
+ operator()(Visitables&... visitables) const
+ {
+ return apply_visitor(visitor_, visitables...);
+ }
+
+#else // !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
+
+public: // unary visitor interface
+
+ template <typename Visitable>
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
+ operator()(Visitable& visitable) const
+ {
+ return apply_visitor(visitor_, visitable);
+ }
+
+public: // binary visitor interface
+
+ template <typename Visitable1, typename Visitable2>
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
+ operator()(Visitable1& visitable1, Visitable2& visitable2) const
+ {
+ return apply_visitor(visitor_, visitable1, visitable2);
+ }
+
+#endif // !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
+
+private:
+ apply_visitor_delayed_t& operator=(const apply_visitor_delayed_t&);
+
+};
+
+template <typename Visitor>
+inline typename boost::enable_if<
+ boost::detail::variant::has_result_type<Visitor>,
+ apply_visitor_delayed_t<Visitor>
+ >::type apply_visitor(Visitor& visitor)
+{
+ return apply_visitor_delayed_t<Visitor>(visitor);
+}
+
+#if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276) \
+ && !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
+
+template <typename Visitor>
+class apply_visitor_delayed_cpp14_t
+{
+private: // representation
+ Visitor& visitor_;
+
+public: // structors
+
+ explicit apply_visitor_delayed_cpp14_t(Visitor& visitor) BOOST_NOEXCEPT
+ : visitor_(visitor)
+ {
+ }
+
+public: // N-ary visitor interface
+ template <typename... Visitables>
+ decltype(auto) operator()(Visitables&... visitables) const
+ {
+ return apply_visitor(visitor_, visitables...);
+ }
+
+private:
+ apply_visitor_delayed_cpp14_t& operator=(const apply_visitor_delayed_cpp14_t&);
+
+};
+
+template <typename Visitor>
+inline typename boost::disable_if<
+ boost::detail::variant::has_result_type<Visitor>,
+ apply_visitor_delayed_cpp14_t<Visitor>
+ >::type apply_visitor(Visitor& visitor)
+{
+ return apply_visitor_delayed_cpp14_t<Visitor>(visitor);
+}
+
+#endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
+ // && !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
+
+
+} // namespace boost
+
+#endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_DELAYED_HPP
diff --git a/third_party/boost/boost/variant/detail/apply_visitor_unary.hpp b/third_party/boost/boost/variant/detail/apply_visitor_unary.hpp
new file mode 100644
index 0000000..63c21a3
--- /dev/null
+++ b/third_party/boost/boost/variant/detail/apply_visitor_unary.hpp
@@ -0,0 +1,173 @@
+//-----------------------------------------------------------------------------
+// boost variant/detail/apply_visitor_unary.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2002-2003 Eric Friedman
+// Copyright (c) 2014 Antony Polukhin
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP
+#define BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP
+
+#include "boost/config.hpp"
+#include "boost/detail/workaround.hpp"
+#include "boost/variant/detail/generic_result_type.hpp"
+
+#if BOOST_WORKAROUND(__EDG__, BOOST_TESTED_AT(302))
+#include "boost/core/enable_if.hpp"
+#include "boost/mpl/not.hpp"
+#include "boost/type_traits/is_const.hpp"
+#endif
+
+#if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
+# include <boost/mpl/distance.hpp>
+# include <boost/mpl/advance.hpp>
+# include <boost/mpl/deref.hpp>
+# include <boost/mpl/size.hpp>
+# include <boost/utility/declval.hpp>
+# include <boost/core/enable_if.hpp>
+# include "boost/variant/detail/has_result_type.hpp"
+#endif
+
+namespace boost {
+
+//////////////////////////////////////////////////////////////////////////
+// function template apply_visitor(visitor, visitable)
+//
+// Visits visitable with visitor.
+//
+
+//
+// nonconst-visitor version:
+//
+
+#if !BOOST_WORKAROUND(__EDG__, BOOST_TESTED_AT(302))
+
+# define BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(V) \
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename V::result_type) \
+ /**/
+
+#else // EDG-based compilers
+
+# define BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(V) \
+ typename enable_if< \
+ mpl::not_< is_const< V > > \
+ , BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename V::result_type) \
+ >::type \
+ /**/
+
+#endif // EDG-based compilers workaround
+
+template <typename Visitor, typename Visitable>
+inline
+ BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE(Visitor)
+apply_visitor(Visitor& visitor, Visitable& visitable)
+{
+ return visitable.apply_visitor(visitor);
+}
+
+#undef BOOST_VARIANT_AUX_APPLY_VISITOR_NON_CONST_RESULT_TYPE
+
+//
+// const-visitor version:
+//
+
+template <typename Visitor, typename Visitable>
+inline
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
+apply_visitor(const Visitor& visitor, Visitable& visitable)
+{
+ return visitable.apply_visitor(visitor);
+}
+
+
+#if !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
+
+// C++14
+namespace detail { namespace variant {
+
+// This class serves only metaprogramming purposes. none of its methods must be called at runtime!
+template <class Visitor, class Variant>
+struct result_multideduce1 {
+ typedef typename Variant::types types;
+ typedef typename boost::mpl::begin<types>::type begin_it;
+ typedef typename boost::mpl::advance<
+ begin_it, boost::mpl::int_<boost::mpl::size<types>::type::value - 1>
+ >::type last_it;
+
+ // For metaprogramming purposes ONLY! Do not use this method (and class) at runtime!
+ static Visitor& vis() BOOST_NOEXCEPT {
+ // Functions that work with lambdas must be defined in same translation unit.
+ // Because of that, we can not use `boost::decval<Visitor&>()` here.
+ Visitor&(*f)() = 0; // pointer to function
+ return f();
+ }
+
+ static decltype(auto) deduce_impl(last_it, unsigned /*helper*/) {
+ typedef typename boost::mpl::deref<last_it>::type value_t;
+ return vis()( boost::declval< value_t& >() );
+ }
+
+ template <class It>
+ static decltype(auto) deduce_impl(It, unsigned helper) {
+ typedef typename boost::mpl::next<It>::type next_t;
+ typedef typename boost::mpl::deref<It>::type value_t;
+ if (helper == boost::mpl::distance<begin_it, It>::type::value) {
+ return deduce_impl(next_t(), ++helper);
+ }
+
+ return vis()( boost::declval< value_t& >() );
+ }
+
+ static decltype(auto) deduce() {
+ return deduce_impl(begin_it(), 0);
+ }
+};
+
+template <class Visitor, class Variant>
+struct result_wrapper1
+{
+ typedef decltype(result_multideduce1<Visitor, Variant>::deduce()) result_type;
+
+ Visitor& visitor_;
+ explicit result_wrapper1(Visitor& visitor) BOOST_NOEXCEPT
+ : visitor_(visitor)
+ {}
+
+ template <class T>
+ result_type operator()(T& val) const {
+ return visitor_(val);
+ }
+};
+
+}} // namespace detail::variant
+
+template <typename Visitor, typename Visitable>
+inline decltype(auto) apply_visitor(Visitor& visitor, Visitable& visitable,
+ typename boost::disable_if<
+ boost::detail::variant::has_result_type<Visitor>
+ >::type* = 0)
+{
+ boost::detail::variant::result_wrapper1<Visitor, Visitable> cpp14_vis(visitor);
+ return visitable.apply_visitor(cpp14_vis);
+}
+
+template <typename Visitor, typename Visitable>
+inline decltype(auto) apply_visitor(const Visitor& visitor, Visitable& visitable,
+ typename boost::disable_if<
+ boost::detail::variant::has_result_type<Visitor>
+ >::type* = 0)
+{
+ boost::detail::variant::result_wrapper1<const Visitor, Visitable> cpp14_vis(visitor);
+ return visitable.apply_visitor(cpp14_vis);
+}
+
+#endif // !defined(BOOST_NO_CXX14_DECLTYPE_AUTO) && !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
+
+} // namespace boost
+
+#endif // BOOST_VARIANT_DETAIL_APPLY_VISITOR_UNARY_HPP
diff --git a/third_party/boost/boost/variant/detail/backup_holder.hpp b/third_party/boost/boost/variant/detail/backup_holder.hpp
new file mode 100644
index 0000000..1ccf160
--- /dev/null
+++ b/third_party/boost/boost/variant/detail/backup_holder.hpp
@@ -0,0 +1,95 @@
+//-----------------------------------------------------------------------------
+// boost variant/detail/backup_holder.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2003
+// Eric Friedman
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_VARIANT_DETAIL_BACKUP_HOLDER_HPP
+#define BOOST_VARIANT_DETAIL_BACKUP_HOLDER_HPP
+
+#include "boost/config.hpp"
+#include "boost/assert.hpp"
+
+namespace boost {
+namespace detail { namespace variant {
+
+template <typename T>
+class backup_holder
+{
+private: // representation
+
+ T* backup_;
+
+public: // structors
+
+ ~backup_holder() BOOST_NOEXCEPT
+ {
+ delete backup_;
+ }
+
+ explicit backup_holder(T* backup) BOOST_NOEXCEPT
+ : backup_(backup)
+ {
+ }
+
+ backup_holder(const backup_holder&);
+
+public: // modifiers
+
+ backup_holder& operator=(const backup_holder& rhs)
+ {
+ *backup_ = rhs.get();
+ return *this;
+ }
+
+ backup_holder& operator=(const T& rhs)
+ {
+ *backup_ = rhs;
+ return *this;
+ }
+
+ void swap(backup_holder& rhs) BOOST_NOEXCEPT
+ {
+ T* tmp = rhs.backup_;
+ rhs.backup_ = this->backup_;
+ this->backup_ = tmp;
+ }
+
+public: // queries
+
+ T& get() BOOST_NOEXCEPT
+ {
+ return *backup_;
+ }
+
+ const T& get() const BOOST_NOEXCEPT
+ {
+ return *backup_;
+ }
+
+};
+
+template <typename T>
+backup_holder<T>::backup_holder(const backup_holder&)
+ : backup_(0)
+{
+ // not intended for copy, but do not want to prohibit syntactically
+ BOOST_ASSERT(false);
+}
+
+template <typename T>
+void swap(backup_holder<T>& lhs, backup_holder<T>& rhs) BOOST_NOEXCEPT
+{
+ lhs.swap(rhs);
+}
+
+}} // namespace detail::variant
+} // namespace boost
+
+#endif // BOOST_VARIANT_DETAIL_BACKUP_HOLDER_HPP
diff --git a/third_party/boost/boost/variant/detail/cast_storage.hpp b/third_party/boost/boost/variant/detail/cast_storage.hpp
new file mode 100644
index 0000000..24feed6
--- /dev/null
+++ b/third_party/boost/boost/variant/detail/cast_storage.hpp
@@ -0,0 +1,42 @@
+//-----------------------------------------------------------------------------
+// boost variant/detail/cast_storage.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2003
+// Eric Friedman
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_VARIANT_DETAIL_CAST_STORAGE_HPP
+#define BOOST_VARIANT_DETAIL_CAST_STORAGE_HPP
+
+#include "boost/config.hpp"
+
+namespace boost {
+namespace detail { namespace variant {
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) function template cast_storage
+//
+// Casts the given storage to the specified type, but with qualification.
+//
+
+template <typename T>
+inline T& cast_storage(void* storage)
+{
+ return *static_cast<T*>(storage);
+}
+
+template <typename T>
+inline const T& cast_storage(const void* storage)
+{
+ return *static_cast<const T*>(storage);
+}
+
+}} // namespace detail::variant
+} // namespace boost
+
+#endif // BOOST_VARIANT_DETAIL_CAST_STORAGE_HPP
diff --git a/third_party/boost/boost/variant/detail/config.hpp b/third_party/boost/boost/variant/detail/config.hpp
new file mode 100644
index 0000000..84564a4
--- /dev/null
+++ b/third_party/boost/boost/variant/detail/config.hpp
@@ -0,0 +1,37 @@
+//-----------------------------------------------------------------------------
+// boost variant/detail/config.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2003
+// Eric Friedman
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_VARIANT_DETAIL_CONFIG_HPP
+#define BOOST_VARIANT_DETAIL_CONFIG_HPP
+
+#include "boost/config.hpp"
+#include "boost/detail/workaround.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+// macro BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING
+//
+#if BOOST_WORKAROUND(__MWERKS__, <= 0x3201) \
+ || BOOST_WORKAROUND(BOOST_INTEL, <= 700) \
+ && !defined(BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING)
+# define BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// macro BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND
+//
+#if !defined(BOOST_NO_SFINAE) \
+ && !BOOST_WORKAROUND(BOOST_INTEL, <= 700) \
+ && !defined(BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND)
+# define BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND
+#endif
+
+#endif // BOOST_VARIANT_DETAIL_CONFIG_HPP
diff --git a/third_party/boost/boost/variant/detail/enable_recursive_fwd.hpp b/third_party/boost/boost/variant/detail/enable_recursive_fwd.hpp
new file mode 100644
index 0000000..39a6b71
--- /dev/null
+++ b/third_party/boost/boost/variant/detail/enable_recursive_fwd.hpp
@@ -0,0 +1,87 @@
+//-----------------------------------------------------------------------------
+// boost variant/detail/enable_recursive_fwd.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2003
+// Eric Friedman
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_VARIANT_DETAIL_ENABLE_RECURSIVE_FWD_HPP
+#define BOOST_VARIANT_DETAIL_ENABLE_RECURSIVE_FWD_HPP
+
+#include "boost/mpl/aux_/config/ctps.hpp"
+
+#include "boost/mpl/bool_fwd.hpp"
+
+# include "boost/mpl/bool.hpp"
+
+namespace boost {
+namespace detail { namespace variant {
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) tag recursive_flag
+//
+// Signifies that the variant should perform recursive substituion.
+//
+
+
+template <typename T>
+struct recursive_flag
+{
+ typedef T type;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) metafunction is_recursive_flag
+//
+// Signifies that the variant should perform recursive substituion.
+//
+
+
+template <typename T>
+struct is_recursive_flag
+ : mpl::false_
+{
+};
+
+template <typename T>
+struct is_recursive_flag< recursive_flag<T> >
+ : mpl::true_
+{
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) metafunction enable_recursive
+//
+// Attempts recursive_variant_ tag substitution, wrapping with
+// boost::recursive_wrapper if substituion occurs w/ non-indirect result
+// (i.e., not a reference or pointer) *and* NoWrapper is false_.
+//
+template <
+ typename T
+ , typename RecursiveVariant
+ , typename NoWrapper = mpl::false_
+ >
+struct enable_recursive;
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) metafunction class quoted_enable_recursive
+//
+// Same behavior as enable_recursive metafunction (see above).
+//
+template <
+ typename RecursiveVariant
+ , typename NoWrapper = mpl::false_
+ >
+struct quoted_enable_recursive;
+
+}} // namespace detail::variant
+} // namespace boost
+
+#endif // BOOST_VARIANT_DETAIL_ENABLE_RECURSIVE_FWD_HPP
diff --git a/third_party/boost/boost/variant/detail/forced_return.hpp b/third_party/boost/boost/variant/detail/forced_return.hpp
new file mode 100644
index 0000000..522b796
--- /dev/null
+++ b/third_party/boost/boost/variant/detail/forced_return.hpp
@@ -0,0 +1,102 @@
+//-----------------------------------------------------------------------------
+// boost variant/detail/forced_return.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2003
+// Eric Friedman
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_VARIANT_DETAIL_FORCED_RETURN_HPP
+#define BOOST_VARIANT_DETAIL_FORCED_RETURN_HPP
+
+#include "boost/config.hpp"
+#include "boost/variant/detail/generic_result_type.hpp"
+#include "boost/assert.hpp"
+
+namespace boost {
+namespace detail { namespace variant {
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) function template forced_return
+//
+// Logical error to permit invocation at runtime, but (artificially) satisfies
+// compile-time requirement of returning a result value.
+//
+
+#if !defined(BOOST_MSVC) \
+ && !defined(BOOST_NO_VOID_RETURNS)
+
+// "standard" implementation:
+
+template <typename T>
+inline T forced_return()
+{
+ // logical error: should never be here! (see above)
+ BOOST_ASSERT(false);
+
+ T (*dummy_function_ptr)() = 0;
+ return dummy_function_ptr();
+}
+
+template <>
+inline void forced_return<void>()
+{
+ // logical error: should never be here! (see above)
+ BOOST_ASSERT(false);
+}
+
+#elif !defined(BOOST_MSVC)
+
+// workaround implementation
+//
+// TODO: Determine the most efficient way to handle this -- as below? by
+// throwing? by recursive call to forced_return itself? etc.
+//
+
+template <typename T>
+inline
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(T)
+forced_return()
+{
+ // logical error: should never be here! (see above)
+ BOOST_ASSERT(false);
+
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(T) (*dummy)() = 0;
+ return dummy();
+}
+
+#else // defined(BOOST_MSVC)
+
+# pragma warning( push )
+# pragma warning( disable : 4702 ) // unreachable code
+// msvc-specific implementation
+//
+// Leverages __declspec(noreturn) for optimized implementation.
+//
+
+__declspec(noreturn)
+inline void forced_return_no_return() {};
+
+template <typename T>
+inline
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(T)
+forced_return()
+{
+ // logical error: should never be here! (see above)
+ BOOST_ASSERT(false);
+
+ forced_return_no_return();
+}
+
+# pragma warning( pop )
+
+#endif // BOOST_MSVC optimization
+
+}} // namespace detail::variant
+} // namespace boost
+
+#endif // BOOST_VARIANT_DETAIL_FORCED_RETURN_HPP
diff --git a/third_party/boost/boost/variant/detail/generic_result_type.hpp b/third_party/boost/boost/variant/detail/generic_result_type.hpp
new file mode 100644
index 0000000..b3fbb19
--- /dev/null
+++ b/third_party/boost/boost/variant/detail/generic_result_type.hpp
@@ -0,0 +1,88 @@
+//-----------------------------------------------------------------------------
+// boost variant/detail/generic_result_type.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2003
+// Eric Friedman
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_VARIANT_DETAIL_GENERIC_RESULT_TYPE_HPP
+#define BOOST_VARIANT_DETAIL_GENERIC_RESULT_TYPE_HPP
+
+#include "boost/config.hpp"
+
+//////////////////////////////////////////////////////////////////////////
+// (workaround) macro BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE
+//
+// On compilers with BOOST_NO_VOID_RETURNS, this macro provides a route
+// to a single syntax for dealing with template functions that may (but
+// not necessarily) return nothing (i.e. void).
+//
+// BOOST_VARIANT_AUX_RETURN_VOID provided for compilers w/ (erroneous?)
+// warnings about non-void functions not returning a value.
+//
+
+#if !defined(BOOST_NO_VOID_RETURNS)
+
+#define BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(T) \
+ T \
+ /**/
+
+#define BOOST_VARIANT_AUX_RETURN_VOID \
+ /**/
+
+#define BOOST_VARIANT_AUX_RETURN_VOID_TYPE \
+ void \
+ /**/
+
+#else // defined(BOOST_NO_VOID_RETURNS)
+
+namespace boost {
+namespace detail { namespace variant {
+
+struct fake_return_void
+{
+ fake_return_void()
+ {
+ }
+
+ template <typename T>
+ fake_return_void(const T&)
+ {
+ }
+};
+
+template <typename T>
+struct no_void_returns_helper
+{
+ typedef T type;
+};
+
+template <>
+struct no_void_returns_helper<void>
+{
+ typedef fake_return_void type;
+};
+
+}} // namespace detail::variant
+} // namespace boost
+
+#define BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(T) \
+ BOOST_DEDUCED_TYPENAME \
+ ::boost::detail::variant::no_void_returns_helper< T >::type \
+ /**/
+
+#define BOOST_VARIANT_AUX_RETURN_VOID \
+ return ::boost::detail::variant::fake_return_void() \
+ /**/
+
+#define BOOST_VARIANT_AUX_RETURN_VOID_TYPE \
+ ::boost::detail::variant::fake_return_void
+
+#endif // BOOST_NO_VOID_RETURNS workaround
+
+#endif // BOOST_VARIANT_DETAIL_GENERIC_RESULT_TYPE_HPP
diff --git a/third_party/boost/boost/variant/detail/has_result_type.hpp b/third_party/boost/boost/variant/detail/has_result_type.hpp
new file mode 100644
index 0000000..18f6490
--- /dev/null
+++ b/third_party/boost/boost/variant/detail/has_result_type.hpp
@@ -0,0 +1,36 @@
+//-----------------------------------------------------------------------------
+// boost variant/detail/has_result_type.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2014-2015 Antony Polukhin
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_VARIANT_DETAIL_HAS_RESULT_TYPE_HPP
+#define BOOST_VARIANT_DETAIL_HAS_RESULT_TYPE_HPP
+
+#include "boost/config.hpp"
+#include "boost/type_traits/remove_reference.hpp"
+
+
+namespace boost { namespace detail { namespace variant {
+
+template <typename T >
+struct has_result_type {
+private:
+ typedef char yes;
+ typedef struct { char array[2]; } no;
+
+ template<typename C> static yes test(typename boost::remove_reference<typename C::result_type>::type*);
+ template<typename C> static no test(...);
+
+public:
+ BOOST_STATIC_CONSTANT(bool, value = sizeof(test<T>(0)) == sizeof(yes));
+};
+
+}}} // namespace boost::detail::variant
+
+#endif // BOOST_VARIANT_DETAIL_HAS_RESULT_TYPE_HPP
diff --git a/third_party/boost/boost/variant/detail/hash_variant.hpp b/third_party/boost/boost/variant/detail/hash_variant.hpp
new file mode 100644
index 0000000..6ba73ae
--- /dev/null
+++ b/third_party/boost/boost/variant/detail/hash_variant.hpp
@@ -0,0 +1,46 @@
+//-----------------------------------------------------------------------------
+// boost variant/detail/hash_variant.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2011
+// Antony Polukhin
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_HASH_VARIANT_FUNCTION_HPP
+#define BOOST_HASH_VARIANT_FUNCTION_HPP
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/variant/variant_fwd.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/functional/hash_fwd.hpp>
+
+namespace boost {
+
+ namespace detail { namespace variant {
+ struct variant_hasher: public boost::static_visitor<std::size_t> {
+ template <class T>
+ std::size_t operator()(T const& val) const {
+ boost::hash<T> hasher;
+ return hasher(val);
+ }
+ };
+ }}
+
+ template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
+ std::size_t hash_value(variant< BOOST_VARIANT_ENUM_PARAMS(T) > const& val) {
+ std::size_t seed = boost::apply_visitor(detail::variant::variant_hasher(), val);
+ hash_combine(seed, val.which());
+ return seed;
+ }
+}
+
+#endif
diff --git a/third_party/boost/boost/variant/detail/initializer.hpp b/third_party/boost/boost/variant/detail/initializer.hpp
new file mode 100644
index 0000000..98c9c22
--- /dev/null
+++ b/third_party/boost/boost/variant/detail/initializer.hpp
@@ -0,0 +1,249 @@
+//-----------------------------------------------------------------------------
+// boost variant/detail/initializer.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_VARIANT_DETAIL_INITIALIZER_HPP
+#define BOOST_VARIANT_DETAIL_INITIALIZER_HPP
+
+#include <new> // for placement new
+
+#include "boost/config.hpp"
+
+#include "boost/call_traits.hpp"
+#include "boost/detail/reference_content.hpp"
+#include "boost/variant/recursive_wrapper_fwd.hpp"
+#include "boost/variant/detail/move.hpp"
+
+#if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
+# include "boost/mpl/aux_/value_wknd.hpp"
+# include "boost/mpl/int.hpp"
+# include "boost/mpl/iter_fold.hpp"
+# include "boost/mpl/next.hpp"
+# include "boost/mpl/deref.hpp"
+# include "boost/mpl/pair.hpp"
+# include "boost/mpl/protect.hpp"
+#else
+# include "boost/variant/variant_fwd.hpp"
+# include "boost/preprocessor/cat.hpp"
+# include "boost/preprocessor/enum.hpp"
+# include "boost/preprocessor/repeat.hpp"
+#endif
+
+namespace boost {
+namespace detail { namespace variant {
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) support to simulate standard overload resolution rules
+//
+// The below initializers allows variant to follow standard overload
+// resolution rules over the specified set of bounded types.
+//
+// On compilers where using declarations in class templates can correctly
+// avoid name hiding, use an optimal solution based on the variant's typelist.
+//
+// Otherwise, use a preprocessor workaround based on knowledge of the fixed
+// size of the variant's psuedo-variadic template parameter list.
+//
+
+#if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
+
+// (detail) quoted metafunction make_initializer_node
+//
+// Exposes a pair whose first type is a node in the initializer hierarchy.
+//
+struct make_initializer_node
+{
+ template <typename BaseIndexPair, typename Iterator>
+ struct apply
+ {
+ private: // helpers, for metafunction result (below)
+
+ typedef typename BaseIndexPair::first
+ base;
+ typedef typename BaseIndexPair::second
+ index;
+
+ class initializer_node
+ : public base
+ {
+ private: // helpers, for static functions (below)
+
+ typedef typename mpl::deref<Iterator>::type
+ recursive_enabled_T;
+ typedef typename unwrap_recursive<recursive_enabled_T>::type
+ public_T;
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ typedef boost::is_reference<public_T>
+ is_reference_content_t;
+
+ typedef typename boost::mpl::if_<is_reference_content_t, public_T, const public_T& >::type
+ param_T;
+
+ template <class T> struct disable_overload{};
+
+ typedef typename boost::mpl::if_<is_reference_content_t, disable_overload<public_T>, public_T&& >::type
+ param2_T;
+#else
+ typedef typename call_traits<public_T>::param_type
+ param_T;
+#endif
+
+ public: // static functions
+
+ using base::initialize;
+
+ static int initialize(void* dest, param_T operand)
+ {
+ typedef typename boost::detail::make_reference_content<
+ recursive_enabled_T
+ >::type internal_T;
+
+ new(dest) internal_T(operand);
+ return BOOST_MPL_AUX_VALUE_WKND(index)::value; // which
+ }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ static int initialize(void* dest, param2_T operand)
+ {
+ // This assert must newer trigger, because all the reference contents are
+ // handled by the initilize(void* dest, param_T operand) function above
+ BOOST_ASSERT(!is_reference_content_t::value);
+
+ typedef typename boost::mpl::if_<is_reference_content_t, param2_T, recursive_enabled_T>::type value_T;
+ new(dest) value_T( boost::detail::variant::move(operand) );
+ return BOOST_MPL_AUX_VALUE_WKND(index)::value; // which
+ }
+#endif
+ };
+
+ friend class initializer_node;
+
+ public: // metafunction result
+
+ typedef mpl::pair<
+ initializer_node
+ , typename mpl::next< index >::type
+ > type;
+
+ };
+};
+
+// (detail) class initializer_root
+//
+// Every level of the initializer hierarchy must expose the name
+// "initialize," so initializer_root provides a dummy function:
+//
+class initializer_root
+{
+public: // static functions
+
+ static void initialize();
+
+};
+
+#else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
+
+ // Obsolete. Remove.
+ #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_PARAMS \
+ BOOST_VARIANT_ENUM_PARAMS(typename recursive_enabled_T) \
+ /**/
+
+ // Obsolete. Remove.
+ #define BOOST_VARIANT_AUX_PP_INITIALIZER_DEFINE_PARAM_T(N) \
+ typedef typename unwrap_recursive< \
+ BOOST_PP_CAT(recursive_enabled_T,N) \
+ >::type BOOST_PP_CAT(public_T,N); \
+ typedef typename call_traits< \
+ BOOST_PP_CAT(public_T,N) \
+ >::param_type BOOST_PP_CAT(param_T,N); \
+ /**/
+
+template < BOOST_VARIANT_ENUM_PARAMS(typename recursive_enabled_T) >
+struct preprocessor_list_initializer
+{
+public: // static functions
+
+ #define BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION(z,N,_) \
+ typedef typename unwrap_recursive< \
+ BOOST_PP_CAT(recursive_enabled_T,N) \
+ >::type BOOST_PP_CAT(public_T,N); \
+ typedef typename call_traits< \
+ BOOST_PP_CAT(public_T,N) \
+ >::param_type BOOST_PP_CAT(param_T,N); \
+ static int initialize( \
+ void* dest \
+ , BOOST_PP_CAT(param_T,N) operand \
+ ) \
+ { \
+ typedef typename boost::detail::make_reference_content< \
+ BOOST_PP_CAT(recursive_enabled_T,N) \
+ >::type internal_T; \
+ \
+ new(dest) internal_T(operand); \
+ return (N); /*which*/ \
+ } \
+ /**/
+
+ BOOST_PP_REPEAT(
+ BOOST_VARIANT_LIMIT_TYPES
+ , BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION
+ , _
+ )
+
+ #undef BOOST_VARIANT_AUX_PP_INITIALIZE_FUNCTION
+
+};
+
+#endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround
+
+}} // namespace detail::variant
+} // namespace boost
+
+///////////////////////////////////////////////////////////////////////////////
+// macro BOOST_VARIANT_AUX_INITIALIZER_T
+//
+// Given both the variant's typelist and a basename for forming the list of
+// bounded types (i.e., T becomes T1, T2, etc.), exposes the initializer
+// most appropriate to the current compiler.
+//
+
+#if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
+
+#define BOOST_VARIANT_AUX_INITIALIZER_T( mpl_seq, typename_base ) \
+ ::boost::mpl::iter_fold< \
+ mpl_seq \
+ , ::boost::mpl::pair< \
+ ::boost::detail::variant::initializer_root \
+ , ::boost::mpl::int_<0> \
+ > \
+ , ::boost::mpl::protect< \
+ ::boost::detail::variant::make_initializer_node \
+ > \
+ >::type::first \
+ /**/
+
+#else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
+
+ // Obsolete. Remove.
+ #define BOOST_VARIANT_AUX_PP_INITIALIZER_TEMPLATE_ARGS(typename_base) \
+ BOOST_VARIANT_ENUM_PARAMS(typename_base) \
+ /**/
+
+#define BOOST_VARIANT_AUX_INITIALIZER_T( mpl_seq, typename_base ) \
+ ::boost::detail::variant::preprocessor_list_initializer< \
+ BOOST_VARIANT_ENUM_PARAMS(typename_base) \
+ > \
+ /**/
+
+#endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround
+
+#endif // BOOST_VARIANT_DETAIL_INITIALIZER_HPP
diff --git a/third_party/boost/boost/variant/detail/make_variant_list.hpp b/third_party/boost/boost/variant/detail/make_variant_list.hpp
new file mode 100644
index 0000000..9bc2e69
--- /dev/null
+++ b/third_party/boost/boost/variant/detail/make_variant_list.hpp
@@ -0,0 +1,73 @@
+//-----------------------------------------------------------------------------
+// boost variant/detail/make_variant_list.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2002-2003 Eric Friedman, Itay Maman
+// Copyright (c) 2013 Antony Polukhin
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_VARIANT_DETAIL_MAKE_VARIANT_LIST_HPP
+#define BOOST_VARIANT_DETAIL_MAKE_VARIANT_LIST_HPP
+
+#include "boost/variant/variant_fwd.hpp"
+
+#include "boost/mpl/list.hpp"
+#include "boost/preprocessor/cat.hpp"
+#include "boost/preprocessor/enum.hpp"
+
+namespace boost {
+namespace detail { namespace variant {
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) metafunction make_variant_list
+//
+// Provides a MPL-compatible sequence with the specified non-void types
+// as arguments.
+//
+// Rationale: see class template convert_void (variant_fwd.hpp) and using-
+// declaration workaround (below).
+//
+
+#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
+
+template < typename... T >
+struct make_variant_list
+{
+ typedef typename mpl::list< T... >::type type;
+};
+
+#else // defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
+
+template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
+struct make_variant_list
+{
+public: // metafunction result
+
+ // [Define a macro to convert any void(NN) tags to mpl::void...]
+# define BOOST_VARIANT_AUX_CONVERT_VOID(z, N,_) \
+ typename convert_void< BOOST_PP_CAT(T,N) >::type
+
+ // [...so that the specified types can be passed to mpl::list...]
+ typedef typename mpl::list<
+ BOOST_PP_ENUM(
+ BOOST_VARIANT_LIMIT_TYPES
+ , BOOST_VARIANT_AUX_CONVERT_VOID
+ , _
+ )
+ >::type type;
+
+ // [...and, finally, the conversion macro can be undefined:]
+# undef BOOST_VARIANT_AUX_CONVERT_VOID
+
+};
+
+#endif // BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES workaround
+
+}} // namespace detail::variant
+} // namespace boost
+
+#endif // BOOST_VARIANT_DETAIL_MAKE_VARIANT_LIST_HPP
diff --git a/third_party/boost/boost/variant/detail/move.hpp b/third_party/boost/boost/variant/detail/move.hpp
new file mode 100644
index 0000000..e605b92
--- /dev/null
+++ b/third_party/boost/boost/variant/detail/move.hpp
@@ -0,0 +1,50 @@
+//-----------------------------------------------------------------------------
+// boost variant/detail/move.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2002-2003 Eric Friedman
+// Copyright (c) 2002 by Andrei Alexandrescu
+// Copyright (c) 2013-2014 Antony Polukhin
+//
+// 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 file derivative of MoJO. Much thanks to Andrei for his initial work.
+// See <http://www.cuj.com/experts/2102/alexandr.htm> for information on MOJO.
+// Re-issued here under the Boost Software License, with permission of the original
+// author (Andrei Alexandrescu).
+
+
+#ifndef BOOST_VARIANT_DETAIL_MOVE_HPP
+#define BOOST_VARIANT_DETAIL_MOVE_HPP
+
+#include <iterator> // for iterator_traits
+#include <new> // for placement new
+
+#include "boost/config.hpp"
+#include "boost/detail/workaround.hpp"
+#include "boost/move/move.hpp"
+#include "boost/move/adl_move_swap.hpp"
+
+namespace boost { namespace detail { namespace variant {
+
+using boost::move;
+
+//////////////////////////////////////////////////////////////////////////
+// function template move_swap
+//
+// Swaps using Koenig lookup but falls back to move-swap for primitive
+// types and on non-conforming compilers.
+//
+
+template <typename T>
+inline void move_swap(T& lhs, T& rhs)
+{
+ ::boost::adl_move_swap(lhs, rhs);
+}
+
+}}} // namespace boost::detail::variant
+
+#endif // BOOST_VARIANT_DETAIL_MOVE_HPP
diff --git a/third_party/boost/boost/variant/detail/over_sequence.hpp b/third_party/boost/boost/variant/detail/over_sequence.hpp
new file mode 100644
index 0000000..ff20a01
--- /dev/null
+++ b/third_party/boost/boost/variant/detail/over_sequence.hpp
@@ -0,0 +1,58 @@
+//-----------------------------------------------------------------------------
+// boost variant/detail/over_sequence.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2003
+// Eric Friedman
+//
+// Portions Copyright (C) 2002 David Abrahams
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_VARIANT_DETAIL_OVER_SEQUENCE_HPP
+#define BOOST_VARIANT_DETAIL_OVER_SEQUENCE_HPP
+
+#include "boost/mpl/aux_/config/ctps.hpp"
+
+
+namespace boost {
+namespace detail { namespace variant {
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) class over_sequence
+//
+// Wrapper used to indicate bounded types for variant are from type sequence.
+//
+template <typename Types>
+struct over_sequence
+{
+ typedef Types type;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) metafunction is_over_sequence (modeled on code by David Abrahams)
+//
+// Indicates whether the specified type is of form over_sequence<...> or not.
+//
+
+
+template <typename T>
+struct is_over_sequence
+ : mpl::false_
+{
+};
+
+template <typename Types>
+struct is_over_sequence< over_sequence<Types> >
+ : mpl::true_
+{
+};
+
+
+}} // namespace detail::variant
+} // namespace boost
+
+#endif // BOOST_VARIANT_DETAIL_OVER_SEQUENCE_HPP
diff --git a/third_party/boost/boost/variant/detail/substitute_fwd.hpp b/third_party/boost/boost/variant/detail/substitute_fwd.hpp
new file mode 100644
index 0000000..8084cb8
--- /dev/null
+++ b/third_party/boost/boost/variant/detail/substitute_fwd.hpp
@@ -0,0 +1,58 @@
+//-----------------------------------------------------------------------------
+// boost variant/detail/substitute_fwd.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2003
+// Eric Friedman
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_VARIANT_DETAIL_SUBSTITUTE_FWD_HPP
+#define BOOST_VARIANT_DETAIL_SUBSTITUTE_FWD_HPP
+
+#include "boost/mpl/aux_/lambda_arity_param.hpp"
+#include "boost/mpl/aux_/template_arity.hpp"
+#include "boost/mpl/int_fwd.hpp"
+
+
+///////////////////////////////////////////////////////////////////////////////
+// BOOST_VARIANT_DETAIL_NO_SUBSTITUTE
+//
+// Defined if 'substitute' is not implementable on the current compiler.
+//
+
+#include "boost/mpl/aux_/config/ctps.hpp"
+#include "boost/mpl/aux_/config/ttp.hpp"
+
+#if defined(BOOST_NO_TEMPLATE_TEMPLATE_PARAMETERS) \
+ && !defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE)
+# define BOOST_VARIANT_DETAIL_NO_SUBSTITUTE
+#endif
+
+namespace boost {
+namespace detail { namespace variant {
+
+#if !defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE)
+
+///////////////////////////////////////////////////////////////////////////////
+// metafunction substitute
+//
+// Substitutes one type for another in the given type expression.
+//
+template <
+ typename T, typename Dest, typename Source
+ BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(
+ typename Arity = mpl::int_< mpl::aux::template_arity<T>::value >
+ )
+ >
+struct substitute;
+
+#endif // !defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE)
+
+}} // namespace detail::variant
+} // namespace boost
+
+#endif // BOOST_VARIANT_DETAIL_SUBSTITUTE_FWD_HPP
diff --git a/third_party/boost/boost/variant/detail/variant_io.hpp b/third_party/boost/boost/variant/detail/variant_io.hpp
new file mode 100644
index 0000000..192a3de
--- /dev/null
+++ b/third_party/boost/boost/variant/detail/variant_io.hpp
@@ -0,0 +1,95 @@
+//-----------------------------------------------------------------------------
+// boost variant/detail/variant_io.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_VARIANT_DETAIL_VARIANT_IO_HPP
+#define BOOST_VARIANT_DETAIL_VARIANT_IO_HPP
+
+#include <iosfwd> // for std::basic_ostream forward declare
+
+#include "boost/variant/variant_fwd.hpp"
+
+#include "boost/detail/templated_streams.hpp"
+#include "boost/variant/static_visitor.hpp"
+
+namespace boost {
+
+///////////////////////////////////////////////////////////////////////////////
+// function template operator<<
+//
+// Outputs the content of the given variant to the given ostream.
+//
+
+// forward declare (allows output of embedded variant< variant< ... >, ... >)
+template <
+ BOOST_TEMPLATED_STREAM_ARGS(E,T)
+ BOOST_TEMPLATED_STREAM_COMMA
+ BOOST_VARIANT_ENUM_PARAMS(typename U)
+ >
+inline BOOST_TEMPLATED_STREAM(ostream, E,T)& operator<<(
+ BOOST_TEMPLATED_STREAM(ostream, E,T)& out
+ , const variant< BOOST_VARIANT_ENUM_PARAMS(U) >& rhs
+ );
+
+namespace detail { namespace variant {
+
+template <typename OStream>
+class printer
+ : public boost::static_visitor<>
+{
+private: // representation
+
+ OStream& out_;
+
+public: // structors
+
+ explicit printer(OStream& out)
+ : out_( out )
+ {
+ }
+
+public: // visitor interface
+
+ template <typename T>
+ void operator()(const T& operand) const
+ {
+ out_ << operand;
+ }
+
+private:
+ printer& operator=(const printer&);
+
+};
+
+}} // namespace detail::variant
+
+template <
+ BOOST_TEMPLATED_STREAM_ARGS(E,T)
+ BOOST_TEMPLATED_STREAM_COMMA
+ BOOST_VARIANT_ENUM_PARAMS(typename U)
+ >
+inline BOOST_TEMPLATED_STREAM(ostream, E,T)& operator<<(
+ BOOST_TEMPLATED_STREAM(ostream, E,T)& out
+ , const variant< BOOST_VARIANT_ENUM_PARAMS(U) >& rhs
+ )
+{
+ detail::variant::printer<
+ BOOST_TEMPLATED_STREAM(ostream, E,T)
+ > visitor(out);
+
+ rhs.apply_visitor(visitor);
+
+ return out;
+}
+
+} // namespace boost
+
+#endif // BOOST_VARIANT_DETAIL_VARIANT_IO_HPP
diff --git a/third_party/boost/boost/variant/detail/visitation_impl.hpp b/third_party/boost/boost/variant/detail/visitation_impl.hpp
new file mode 100644
index 0000000..3e9ad5f
--- /dev/null
+++ b/third_party/boost/boost/variant/detail/visitation_impl.hpp
@@ -0,0 +1,277 @@
+//-----------------------------------------------------------------------------
+// boost variant/detail/visitation_impl.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2003
+// Eric Friedman
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_VARIANT_DETAIL_VISITATION_IMPL_HPP
+#define BOOST_VARIANT_DETAIL_VISITATION_IMPL_HPP
+
+#include "boost/config.hpp"
+
+#include "boost/variant/detail/backup_holder.hpp"
+#include "boost/variant/detail/cast_storage.hpp"
+#include "boost/variant/detail/forced_return.hpp"
+#include "boost/variant/detail/generic_result_type.hpp"
+#include "boost/variant/variant_fwd.hpp" // for BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
+
+#include "boost/mpl/eval_if.hpp"
+#include "boost/mpl/bool.hpp"
+#include "boost/mpl/identity.hpp"
+#include "boost/mpl/int.hpp"
+#include "boost/mpl/next.hpp"
+#include "boost/mpl/deref.hpp"
+#include "boost/mpl/or.hpp"
+#include "boost/preprocessor/cat.hpp"
+#include "boost/preprocessor/inc.hpp"
+#include "boost/preprocessor/repeat.hpp"
+#include "boost/type_traits/is_same.hpp"
+#include "boost/type_traits/has_nothrow_copy.hpp"
+#include "boost/type_traits/is_nothrow_move_constructible.hpp"
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+# pragma warning (push)
+# pragma warning (disable : 4702) //unreachable code
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
+//
+// Unrolls variant's visitation mechanism to reduce template instantiation
+// and potentially increase runtime performance. (TODO: Investigate further.)
+//
+#if !defined(BOOST_VARIANT_VISITATION_UNROLLING_LIMIT)
+
+#ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
+# include "boost/mpl/limits/list.hpp"
+# define BOOST_VARIANT_VISITATION_UNROLLING_LIMIT \
+ BOOST_MPL_LIMIT_LIST_SIZE
+#else
+# define BOOST_VARIANT_VISITATION_UNROLLING_LIMIT \
+ BOOST_VARIANT_LIMIT_TYPES
+#endif
+
+#endif
+
+namespace boost {
+namespace detail { namespace variant {
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) class apply_visitor_unrolled
+//
+// Tag type indicates when visitation_impl is unrolled.
+//
+struct apply_visitor_unrolled {};
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) class template visitation_impl_step
+//
+// "Never ending" iterator range facilitates visitation_impl unrolling.
+//
+
+
+template <typename Iter, typename LastIter>
+struct visitation_impl_step
+{
+ typedef typename mpl::deref<Iter>::type type;
+
+ typedef typename mpl::next<Iter>::type next_iter;
+ typedef visitation_impl_step<
+ next_iter, LastIter
+ > next;
+};
+
+template <typename LastIter>
+struct visitation_impl_step< LastIter,LastIter >
+{
+ typedef apply_visitor_unrolled type;
+ typedef visitation_impl_step next;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) function template visitation_impl_invoke
+//
+// Invokes the given visitor on the specified type in the given storage.
+//
+
+template <typename Visitor, typename VoidPtrCV, typename T>
+inline
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
+visitation_impl_invoke_impl(
+ int, Visitor& visitor, VoidPtrCV storage, T*
+ , mpl::true_// never_uses_backup
+ )
+{
+ return visitor.internal_visit(
+ cast_storage<T>(storage), 1L
+ );
+}
+
+template <typename Visitor, typename VoidPtrCV, typename T>
+inline
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
+visitation_impl_invoke_impl(
+ int internal_which, Visitor& visitor, VoidPtrCV storage, T*
+ , mpl::false_// never_uses_backup
+ )
+{
+ if (internal_which >= 0)
+ {
+ return visitor.internal_visit(
+ cast_storage<T>(storage), 1L
+ );
+ }
+ else
+ {
+ return visitor.internal_visit(
+ cast_storage< backup_holder<T> >(storage), 1L
+ );
+ }
+}
+
+template <typename Visitor, typename VoidPtrCV, typename T, typename NoBackupFlag>
+inline
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
+visitation_impl_invoke(
+ int internal_which, Visitor& visitor, VoidPtrCV storage, T* t
+ , NoBackupFlag
+ , int
+ )
+{
+ typedef typename mpl::or_<
+ NoBackupFlag
+ , is_nothrow_move_constructible<T>
+ , has_nothrow_copy<T>
+ >::type never_uses_backup;
+
+ return (visitation_impl_invoke_impl)(
+ internal_which, visitor, storage, t
+ , never_uses_backup()
+ );
+}
+
+template <typename Visitor, typename VoidPtrCV, typename NBF>
+inline
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
+visitation_impl_invoke(int, Visitor&, VoidPtrCV, apply_visitor_unrolled*, NBF, long)
+{
+ // should never be here at runtime!
+ typedef typename Visitor::result_type result_type;
+ return ::boost::detail::variant::forced_return< result_type >();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) function template visitation_impl
+//
+// Invokes the given visitor on the type in the given variant storage.
+//
+
+template <
+ typename W, typename S
+ , typename Visitor, typename VPCV
+ , typename NBF
+ >
+inline
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
+visitation_impl(
+ int, int, Visitor&, VPCV
+ , mpl::true_ // is_apply_visitor_unrolled
+ , NBF, W* = 0, S* = 0
+ )
+{
+ // should never be here at runtime!
+ typedef typename Visitor::result_type result_type;
+ return ::boost::detail::variant::forced_return< result_type >();
+}
+
+template <
+ typename Which, typename step0
+ , typename Visitor, typename VoidPtrCV
+ , typename NoBackupFlag
+ >
+inline
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(typename Visitor::result_type)
+visitation_impl(
+ const int internal_which, const int logical_which
+ , Visitor& visitor, VoidPtrCV storage
+ , mpl::false_ // is_apply_visitor_unrolled
+ , NoBackupFlag no_backup_flag
+ , Which* = 0, step0* = 0
+ )
+{
+ // Typedef apply_visitor_unrolled steps and associated types...
+# define BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF(z, N, _) \
+ typedef typename BOOST_PP_CAT(step,N)::type BOOST_PP_CAT(T,N); \
+ typedef typename BOOST_PP_CAT(step,N)::next \
+ BOOST_PP_CAT(step, BOOST_PP_INC(N)); \
+ /**/
+
+ BOOST_PP_REPEAT(
+ BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
+ , BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF
+ , _
+ )
+
+# undef BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_TYPEDEF
+
+ // ...switch on the target which-index value...
+ switch (logical_which)
+ {
+
+ // ...applying the appropriate case:
+# define BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE(z, N, _) \
+ case (Which::value + (N)): \
+ return (visitation_impl_invoke)( \
+ internal_which, visitor, storage \
+ , static_cast<BOOST_PP_CAT(T,N)*>(0) \
+ , no_backup_flag, 1L \
+ ); \
+ /**/
+
+ BOOST_PP_REPEAT(
+ BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
+ , BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE
+ , _
+ )
+
+# undef BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE
+
+ default: break;
+ }
+
+ // If not handled in this iteration, continue unrolling:
+ typedef mpl::int_<
+ Which::value + (BOOST_VARIANT_VISITATION_UNROLLING_LIMIT)
+ > next_which;
+
+ typedef BOOST_PP_CAT(step, BOOST_VARIANT_VISITATION_UNROLLING_LIMIT)
+ next_step;
+
+ typedef typename next_step::type next_type;
+ typedef typename is_same< next_type,apply_visitor_unrolled >::type
+ is_apply_visitor_unrolled;
+
+ return visitation_impl(
+ internal_which, logical_which
+ , visitor, storage
+ , is_apply_visitor_unrolled()
+ , no_backup_flag
+ , static_cast<next_which*>(0), static_cast<next_step*>(0)
+ );
+}
+
+}} // namespace detail::variant
+} // namespace boost
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+# pragma warning(pop)
+#endif
+
+#endif // BOOST_VARIANT_DETAIL_VISITATION_IMPL_HPP
diff --git a/third_party/boost/boost/variant/recursive_wrapper_fwd.hpp b/third_party/boost/boost/variant/recursive_wrapper_fwd.hpp
new file mode 100644
index 0000000..b46774d
--- /dev/null
+++ b/third_party/boost/boost/variant/recursive_wrapper_fwd.hpp
@@ -0,0 +1,99 @@
+//-----------------------------------------------------------------------------
+// boost variant/recursive_wrapper_fwd.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2002
+// Eric Friedman, Itay Maman
+//
+// Portions Copyright (C) 2002 David Abrahams
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_VARIANT_RECURSIVE_WRAPPER_FWD_HPP
+#define BOOST_VARIANT_RECURSIVE_WRAPPER_FWD_HPP
+
+#include "boost/mpl/aux_/config/ctps.hpp"
+#include "boost/mpl/aux_/lambda_support.hpp"
+#include <boost/type_traits/integral_constant.hpp>
+
+namespace boost {
+
+//////////////////////////////////////////////////////////////////////////
+// class template recursive_wrapper
+//
+// Enables recursive types in templates by breaking cyclic dependencies.
+//
+// For example:
+//
+// class my;
+//
+// typedef variant< int, recursive_wrapper<my> > var;
+//
+// class my {
+// var var_;
+// ...
+// };
+//
+template <typename T> class recursive_wrapper;
+
+///////////////////////////////////////////////////////////////////////////////
+// metafunction is_recursive_wrapper (modeled on code by David Abrahams)
+//
+// True iff specified type matches recursive_wrapper<T>.
+//
+
+namespace detail {
+
+
+template <typename T>
+struct is_recursive_wrapper_impl
+ : mpl::false_
+{
+};
+
+template <typename T>
+struct is_recursive_wrapper_impl< recursive_wrapper<T> >
+ : mpl::true_
+{
+};
+
+
+} // namespace detail
+
+template< typename T > struct is_recursive_wrapper
+ : public ::boost::integral_constant<bool,(::boost::detail::is_recursive_wrapper_impl<T>::value)>
+{
+public:
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_recursive_wrapper,(T))
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// metafunction unwrap_recursive
+//
+// If specified type T matches recursive_wrapper<U>, then U; else T.
+//
+
+
+template <typename T>
+struct unwrap_recursive
+{
+ typedef T type;
+
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1,unwrap_recursive,(T))
+};
+
+template <typename T>
+struct unwrap_recursive< recursive_wrapper<T> >
+{
+ typedef T type;
+
+ BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(1,unwrap_recursive,(T))
+};
+
+
+} // namespace boost
+
+#endif // BOOST_VARIANT_RECURSIVE_WRAPPER_FWD_HPP
diff --git a/third_party/boost/boost/variant/static_visitor.hpp b/third_party/boost/boost/variant/static_visitor.hpp
new file mode 100644
index 0000000..7fe9ca6
--- /dev/null
+++ b/third_party/boost/boost/variant/static_visitor.hpp
@@ -0,0 +1,95 @@
+//-----------------------------------------------------------------------------
+// boost variant/static_visitor.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2002-2003
+// Eric Friedman
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_VARIANT_STATIC_VISITOR_HPP
+#define BOOST_VARIANT_STATIC_VISITOR_HPP
+
+#include "boost/config.hpp"
+#include "boost/detail/workaround.hpp"
+
+#include "boost/mpl/if.hpp"
+#include "boost/type_traits/is_base_and_derived.hpp"
+
+#include <boost/type_traits/integral_constant.hpp>
+#include <boost/mpl/aux_/lambda_support.hpp>
+
+namespace boost {
+
+//////////////////////////////////////////////////////////////////////////
+// class template static_visitor
+//
+// An empty base class that typedefs the return type of a deriving static
+// visitor. The class is analogous to std::unary_function in this role.
+//
+
+namespace detail {
+
+ struct is_static_visitor_tag { };
+
+ typedef void static_visitor_default_return;
+
+} // namespace detail
+
+template <typename R = ::boost::detail::static_visitor_default_return>
+class static_visitor
+ : public detail::is_static_visitor_tag
+{
+public: // typedefs
+
+ typedef R result_type;
+
+protected: // for use as base class only
+#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) && !defined(BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS)
+ static_visitor() = default;
+ ~static_visitor() = default;
+#else
+ static_visitor() BOOST_NOEXCEPT { }
+ ~static_visitor() BOOST_NOEXCEPT { }
+#endif
+};
+
+//////////////////////////////////////////////////////////////////////////
+// metafunction is_static_visitor
+//
+// Value metafunction indicates whether the specified type derives from
+// static_visitor<...>.
+//
+// NOTE #1: This metafunction does NOT check whether the specified type
+// fulfills the requirements of the StaticVisitor concept.
+//
+// NOTE #2: This template never needs to be specialized!
+//
+
+namespace detail {
+
+template <typename T>
+struct is_static_visitor_impl
+{
+ BOOST_STATIC_CONSTANT(bool, value =
+ (::boost::is_base_and_derived<
+ detail::is_static_visitor_tag,
+ T
+ >::value));
+};
+
+} // namespace detail
+
+template< typename T > struct is_static_visitor
+ : public ::boost::integral_constant<bool,(::boost::detail::is_static_visitor_impl<T>::value)>
+{
+public:
+ BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_static_visitor,(T))
+};
+
+} // namespace boost
+
+#endif // BOOST_VARIANT_STATIC_VISITOR_HPP
diff --git a/third_party/boost/boost/variant/variant.hpp b/third_party/boost/boost/variant/variant.hpp
new file mode 100644
index 0000000..ba74588
--- /dev/null
+++ b/third_party/boost/boost/variant/variant.hpp
@@ -0,0 +1,2418 @@
+//-----------------------------------------------------------------------------
+// boost variant/variant.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2002-2003 Eric Friedman, Itay Maman
+// Copyright (c) 2012-2014 Antony Polukhin
+//
+// Distributed under the 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 Adam Romanek for providing patches for exception-disabled env.
+
+#ifndef BOOST_VARIANT_VARIANT_HPP
+#define BOOST_VARIANT_VARIANT_HPP
+
+#include <cstddef> // for std::size_t
+#include <new> // for placement new
+
+#include "boost/type_index.hpp"
+
+#include "boost/variant/detail/config.hpp"
+#include "boost/mpl/aux_/value_wknd.hpp"
+
+#include "boost/variant/variant_fwd.hpp"
+#include "boost/variant/detail/backup_holder.hpp"
+#include "boost/variant/detail/enable_recursive_fwd.hpp"
+#include "boost/variant/detail/forced_return.hpp"
+#include "boost/variant/detail/initializer.hpp"
+#include "boost/variant/detail/make_variant_list.hpp"
+#include "boost/variant/detail/over_sequence.hpp"
+#include "boost/variant/detail/visitation_impl.hpp"
+#include "boost/variant/detail/hash_variant.hpp"
+
+#include "boost/variant/detail/generic_result_type.hpp"
+#include "boost/variant/detail/move.hpp"
+
+#include "boost/detail/no_exceptions_support.hpp"
+#include "boost/detail/reference_content.hpp"
+#include "boost/aligned_storage.hpp"
+#include "boost/blank.hpp"
+#include "boost/math/common_factor_ct.hpp"
+#include "boost/static_assert.hpp"
+#include "boost/preprocessor/cat.hpp"
+#include "boost/preprocessor/repeat.hpp"
+#include "boost/type_traits/alignment_of.hpp"
+#include "boost/type_traits/add_const.hpp"
+#include "boost/type_traits/has_nothrow_constructor.hpp"
+#include "boost/type_traits/has_nothrow_copy.hpp"
+#include "boost/type_traits/is_nothrow_move_assignable.hpp"
+#include "boost/type_traits/is_nothrow_move_constructible.hpp"
+#include "boost/type_traits/is_const.hpp"
+#include "boost/type_traits/is_same.hpp"
+#include "boost/type_traits/is_rvalue_reference.hpp"
+#include "boost/utility/enable_if.hpp"
+#include "boost/utility/declval.hpp"
+#include "boost/variant/recursive_wrapper_fwd.hpp"
+#include "boost/variant/static_visitor.hpp"
+
+#include "boost/mpl/assert.hpp"
+#include "boost/mpl/begin_end.hpp"
+#include "boost/mpl/bool.hpp"
+#include "boost/mpl/deref.hpp"
+#include "boost/mpl/empty.hpp"
+#include "boost/mpl/eval_if.hpp"
+#include "boost/mpl/find_if.hpp"
+#include "boost/mpl/fold.hpp"
+#include "boost/mpl/front.hpp"
+#include "boost/mpl/identity.hpp"
+#include "boost/mpl/if.hpp"
+#include "boost/mpl/int.hpp"
+#include "boost/mpl/is_sequence.hpp"
+#include "boost/mpl/iterator_range.hpp"
+#include "boost/mpl/iter_fold_if.hpp"
+#include "boost/mpl/logical.hpp"
+#include "boost/mpl/max_element.hpp"
+#include "boost/mpl/next.hpp"
+#include "boost/mpl/not.hpp"
+#include "boost/mpl/pair.hpp"
+#include "boost/mpl/protect.hpp"
+#include "boost/mpl/push_front.hpp"
+#include "boost/mpl/same_as.hpp"
+#include "boost/mpl/size_t.hpp"
+#include "boost/mpl/sizeof.hpp"
+#include "boost/mpl/transform.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+// Implementation Macros:
+//
+// BOOST_VARIANT_VISITATION_UNROLLING_LIMIT
+// Defined in boost/variant/detail/visitation_impl.hpp.
+//
+// BOOST_VARIANT_MINIMIZE_SIZE
+// When #defined, implementation employs all known means to minimize the
+// size of variant obje cts. However, often unsuccessful due to alignment
+// issues, and potentially harmful to runtime speed, so not enabled by
+// default. (TODO: Investigate further.)
+
+#if defined(BOOST_VARIANT_MINIMIZE_SIZE)
+# include <climits> // for SCHAR_MAX
+# include "boost/mpl/eval_if.hpp"
+# include "boost/mpl/equal_to.hpp"
+# include "boost/mpl/identity.hpp"
+# include "boost/mpl/int.hpp"
+# include "boost/mpl/if.hpp"
+# include "boost/mpl/less.hpp"
+# include "boost/mpl/long.hpp"
+# include "boost/mpl/O1_size.hpp"
+#endif
+
+
+namespace boost {
+
+namespace detail { namespace variant {
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) metafunction max_value
+//
+// Finds the maximum value of the unary metafunction F over Sequence.
+//
+template <typename Sequence, typename F>
+struct max_value
+{
+private: // helpers, for metafunction result (below)
+
+ typedef typename mpl::transform1<Sequence, F>::type transformed_;
+ typedef typename mpl::max_element<transformed_
+
+ >::type max_it;
+
+public: // metafunction result
+
+ typedef typename mpl::deref<max_it>::type
+ type;
+
+};
+
+struct add_alignment
+{
+ template <typename State, typename Item>
+ struct apply
+ : mpl::size_t<
+ ::boost::math::static_lcm<
+ BOOST_MPL_AUX_VALUE_WKND(State)::value
+ , ::boost::alignment_of<Item>::value
+ >::value
+ >
+ {};
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) metafunction find_fallback_type
+//
+// Provides a fallback (i.e., nothrow default-constructible) type from the
+// specified sequence, or no_fallback_type if not found.
+//
+// This implementation is designed to prefer boost::blank over other potential
+// fallback types, regardless of its position in the specified sequence.
+//
+
+class no_fallback_type;
+
+struct find_fallback_type_pred
+{
+ template <typename Iterator>
+ struct apply
+ {
+ private:
+ typedef typename mpl::deref<Iterator>::type t_;
+
+ public:
+ typedef mpl::not_< has_nothrow_constructor<t_> > type;
+ };
+};
+
+template <typename Types>
+struct find_fallback_type
+{
+private: // helpers, for metafunction result (below)
+
+ typedef typename mpl::end<Types>::type end_it;
+
+ // [Find the first suitable fallback type...]
+
+ typedef typename mpl::iter_fold_if<
+ Types
+ , mpl::int_<0>, mpl::protect< mpl::next<> >
+ , mpl::protect< find_fallback_type_pred >
+ >::type first_result_;
+
+ typedef typename first_result_::first first_result_index;
+ typedef typename first_result_::second first_result_it;
+
+ // [...now search the rest of the sequence for boost::blank...]
+
+ typedef typename mpl::iter_fold_if<
+ mpl::iterator_range< first_result_it,end_it >
+ , first_result_index, mpl::protect< mpl::next<> >
+ , mpl::protect< mpl::not_same_as<boost::blank> >
+ >::type second_result_;
+
+ typedef typename second_result_::second second_result_it;
+
+public: // metafunction result
+
+ // [...and return the results of the search:]
+ typedef typename mpl::eval_if<
+ is_same< second_result_it,end_it >
+ , mpl::if_<
+ is_same< first_result_it,end_it >
+ , mpl::pair< no_fallback_type,no_fallback_type >
+ , first_result_
+ >
+ , mpl::identity< second_result_ >
+ >::type type;
+
+};
+
+#ifndef BOOST_NO_CXX11_NOEXCEPT
+///////////////////////////////////////////////////////////////////////////////
+// (detail) metafunction is_variant_move_noexcept_constructible
+//
+// Returns true_type if all the types are nothrow move constructible.
+//
+template <class Types>
+struct is_variant_move_noexcept_constructible {
+ typedef typename boost::mpl::find_if<
+ Types, mpl::not_<boost::is_nothrow_move_constructible<boost::mpl::_1> >
+ >::type iterator_t;
+
+ typedef typename boost::mpl::end<Types>::type end_t;
+ typedef typename boost::is_same<
+ iterator_t, end_t
+ >::type type;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) metafunction is_variant_move_noexcept_assignable
+//
+// Returns true_type if all the types are nothrow move constructible.
+//
+template <class Types>
+struct is_variant_move_noexcept_assignable {
+ typedef typename boost::mpl::find_if<
+ Types, mpl::not_<boost::is_nothrow_move_assignable<boost::mpl::_1> >
+ >::type iterator_t;
+
+ typedef typename boost::mpl::end<Types>::type end_t;
+ typedef typename boost::is_same<
+ iterator_t, end_t
+ >::type type;
+};
+#endif // BOOST_NO_CXX11_NOEXCEPT
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) metafunction make_storage
+//
+// Provides an aligned storage type capable of holding any of the types
+// specified in the given type-sequence.
+//
+
+template <typename Types, typename NeverUsesBackupFlag>
+struct make_storage
+{
+private: // helpers, for metafunction result (below)
+
+ typedef typename mpl::eval_if<
+ NeverUsesBackupFlag
+ , mpl::identity< Types >
+ , mpl::push_front<
+ Types, backup_holder<void*>
+ >
+ >::type types;
+
+ typedef typename max_value<
+ types, mpl::sizeof_<mpl::_1>
+ >::type max_size;
+
+#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551))
+
+ typedef typename mpl::fold<
+ types
+ , mpl::size_t<1>
+ , add_alignment
+ >::type max_alignment;
+
+#else // borland
+
+ // temporary workaround -- use maximal alignment
+ typedef mpl::size_t< -1 > max_alignment;
+
+#endif // borland workaround
+
+public: // metafunction result
+
+ typedef ::boost::aligned_storage<
+ BOOST_MPL_AUX_VALUE_WKND(max_size)::value
+ , BOOST_MPL_AUX_VALUE_WKND(max_alignment)::value
+ > type;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) class destroyer
+//
+// Internal visitor that destroys the value it visits.
+//
+struct destroyer
+ : public static_visitor<>
+{
+public: // visitor interfaces
+
+ template <typename T>
+ BOOST_VARIANT_AUX_RETURN_VOID_TYPE
+ internal_visit(T& operand, int) const BOOST_NOEXCEPT
+ {
+ operand.~T(); // must be noexcept
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551)) || \
+ BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
+ operand; // suppresses warnings
+#endif
+
+ BOOST_VARIANT_AUX_RETURN_VOID;
+ }
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) class template known_get
+//
+// Visitor that returns a reference to content of the specified type.
+//
+// Precondition: visited variant MUST contain logical content of type T.
+//
+template <typename T>
+class known_get
+ : public static_visitor<T&>
+{
+
+public: // visitor interface
+
+ T& operator()(T& operand) const BOOST_NOEXCEPT
+ {
+ return operand;
+ }
+
+ template <typename U>
+ T& operator()(U&) const
+ {
+ // logical error to be here: see precondition above
+ return ::boost::detail::variant::forced_return< T& >();
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) class copy_into
+//
+// Internal visitor that copies the value it visits into the given buffer.
+//
+class copy_into
+ : public static_visitor<>
+{
+private: // representation
+
+ void* storage_;
+
+public: // structors
+
+ explicit copy_into(void* storage) BOOST_NOEXCEPT
+ : storage_(storage)
+ {
+ }
+
+public: // internal visitor interface
+
+ template <typename T>
+ BOOST_VARIANT_AUX_RETURN_VOID_TYPE
+ internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
+ {
+ new(storage_) T( operand.get() );
+ BOOST_VARIANT_AUX_RETURN_VOID;
+ }
+
+ template <typename T>
+ BOOST_VARIANT_AUX_RETURN_VOID_TYPE
+ internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
+ {
+ new(storage_) T( operand.get() );
+ BOOST_VARIANT_AUX_RETURN_VOID;
+ }
+
+ template <typename T>
+ BOOST_VARIANT_AUX_RETURN_VOID_TYPE
+ internal_visit(const T& operand, int) const
+ {
+ new(storage_) T(operand);
+ BOOST_VARIANT_AUX_RETURN_VOID;
+ }
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) class move_into
+//
+// Internal visitor that moves the value it visits into the given buffer.
+//
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+class move_into
+ : public static_visitor<>
+{
+private: // representation
+
+ void* storage_;
+
+public: // structors
+
+ explicit move_into(void* storage) BOOST_NOEXCEPT
+ : storage_(storage)
+ {
+ }
+
+public: // internal visitor interface
+
+ template <typename T>
+ BOOST_VARIANT_AUX_RETURN_VOID_TYPE
+ internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
+ {
+ new(storage_) T( ::boost::detail::variant::move(operand.get()) );
+ BOOST_VARIANT_AUX_RETURN_VOID;
+ }
+
+ template <typename T>
+ BOOST_VARIANT_AUX_RETURN_VOID_TYPE
+ internal_visit(T& operand, int) const BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T(boost::declval<T>())))
+ {
+ new(storage_) T(::boost::detail::variant::move(operand));
+ BOOST_VARIANT_AUX_RETURN_VOID;
+ }
+};
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) class assign_storage
+//
+// Internal visitor that assigns the given storage (which must be a
+// constructed value of the same type) to the value it visits.
+//
+struct assign_storage
+ : public static_visitor<>
+{
+private: // representation
+
+ const void* rhs_storage_;
+
+public: // structors
+
+ explicit assign_storage(const void* rhs_storage) BOOST_NOEXCEPT
+ : rhs_storage_(rhs_storage)
+ {
+ }
+
+public: // internal visitor interfaces
+
+ template <typename T>
+ BOOST_VARIANT_AUX_RETURN_VOID_TYPE
+ internal_visit(backup_holder<T>& lhs_content, long) const
+ {
+ lhs_content.get()
+ = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
+ BOOST_VARIANT_AUX_RETURN_VOID;
+ }
+
+ template <typename T>
+ BOOST_VARIANT_AUX_RETURN_VOID_TYPE
+ internal_visit(const backup_holder<T>& lhs_content, long) const
+ {
+ lhs_content.get()
+ = static_cast< const backup_holder<T>* >(rhs_storage_)->get();
+ BOOST_VARIANT_AUX_RETURN_VOID;
+ }
+
+ template <typename T>
+ BOOST_VARIANT_AUX_RETURN_VOID_TYPE
+ internal_visit(T& lhs_content, int) const
+ {
+ // NOTE TO USER :
+ // Compile error here indicates one of variant's bounded types does
+ // not meet the requirements of the Assignable concept. Thus,
+ // variant is not Assignable.
+ //
+ // Hint: Are any of the bounded types const-qualified or references?
+ //
+ lhs_content = *static_cast< const T* >(rhs_storage_);
+ BOOST_VARIANT_AUX_RETURN_VOID;
+ }
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) class move_storage
+//
+// Internal visitor that moves the given storage (which must be a
+// constructed value of the same type) to the value it visits.
+//
+struct move_storage
+ : public static_visitor<>
+{
+private: // representation
+
+ void* rhs_storage_;
+
+public: // structors
+
+ explicit move_storage(void* rhs_storage) BOOST_NOEXCEPT
+ : rhs_storage_(rhs_storage)
+ {
+ }
+
+public: // internal visitor interfaces
+
+ template <typename T>
+ BOOST_VARIANT_AUX_RETURN_VOID_TYPE
+ internal_visit(backup_holder<T>& lhs_content, long) const
+ {
+ lhs_content.get()
+ = ::boost::detail::variant::move(static_cast<backup_holder<T>* >(rhs_storage_)->get());
+ BOOST_VARIANT_AUX_RETURN_VOID;
+ }
+
+ template <typename T>
+ BOOST_VARIANT_AUX_RETURN_VOID_TYPE
+ internal_visit(const backup_holder<T>& lhs_content, long) const
+ {
+ lhs_content.get()
+ = ::boost::detail::variant::move(static_cast<backup_holder<T>* >(rhs_storage_)->get());
+ BOOST_VARIANT_AUX_RETURN_VOID;
+ }
+
+ template <typename T>
+ BOOST_VARIANT_AUX_RETURN_VOID_TYPE
+ internal_visit(T& lhs_content, int) const
+ {
+ // NOTE TO USER :
+ // Compile error here indicates one of variant's bounded types does
+ // not meet the requirements of the Assignable concept. Thus,
+ // variant is not Assignable.
+ //
+ // Hint: Are any of the bounded types const-qualified or references?
+ //
+ lhs_content = ::boost::detail::variant::move(*static_cast<T* >(rhs_storage_));
+ BOOST_VARIANT_AUX_RETURN_VOID;
+ }
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) class direct_assigner
+//
+// Generic static visitor that: if and only if the visited value is of the
+// specified type, assigns the given value to the visited value and returns
+// true; else returns false.
+//
+template <typename T>
+class direct_assigner
+ : public static_visitor<bool>
+{
+private: // representation
+
+ const T& rhs_;
+
+public: // structors
+
+ explicit direct_assigner(const T& rhs) BOOST_NOEXCEPT
+ : rhs_(rhs)
+ {
+ }
+
+public: // visitor interface
+
+ bool operator()(T& lhs)
+ {
+ lhs = rhs_;
+ return true;
+ }
+
+ template <typename U>
+ bool operator()(U&) BOOST_NOEXCEPT
+ {
+ return false;
+ }
+
+#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
+private:
+ // silence MSVC warning C4512: assignment operator could not be generated
+ direct_assigner& operator= (direct_assigner const&);
+#endif
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) class direct_mover
+//
+// Generic static visitor that: if and only if the visited value is of the
+// specified type, move assigns the given value to the visited value and returns
+// true; else returns false.
+//
+template <typename T>
+class direct_mover
+ : public static_visitor<bool>
+{
+private: // representation
+
+ T& rhs_;
+
+public: // structors
+
+ explicit direct_mover(T& rhs) BOOST_NOEXCEPT
+ : rhs_(rhs)
+ {
+ }
+
+public: // visitor interface
+
+ bool operator()(T& lhs)
+ {
+ lhs = ::boost::detail::variant::move(rhs_);
+ return true;
+ }
+
+ template <typename U>
+ bool operator()(U&) BOOST_NOEXCEPT
+ {
+ return false;
+ }
+
+#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
+private:
+ // silence MSVC warning C4512: assignment operator could not be generated
+ direct_mover& operator= (direct_mover const&);
+#endif
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) class backup_assigner
+//
+// Internal visitor that "assigns" the given value to the visited value,
+// using backup to recover if the destroy-copy sequence fails.
+//
+// NOTE: This needs to be a friend of variant, as it needs access to
+// indicate_which, indicate_backup_which, etc.
+//
+template <typename Variant>
+class backup_assigner
+ : public static_visitor<>
+{
+private: // representation
+
+ Variant& lhs_;
+ int rhs_which_;
+ const void* rhs_content_;
+ void (*copy_rhs_content_)(void*, const void*);
+
+public: // structors
+
+ template<class RhsT>
+ backup_assigner(Variant& lhs, int rhs_which, const RhsT& rhs_content)
+ : lhs_(lhs)
+ , rhs_which_(rhs_which)
+ , rhs_content_(&rhs_content)
+ , copy_rhs_content_(&construct_impl<RhsT>)
+ {
+ }
+
+private: // helpers, for visitor interface (below)
+
+ template<class RhsT>
+ static void construct_impl(void* addr, const void* obj)
+ {
+ new(addr) RhsT(*static_cast<const RhsT*>(obj));
+ }
+
+ template <typename LhsT>
+ void backup_assign_impl(
+ backup_holder<LhsT>& lhs_content
+ , mpl::false_ // is_nothrow_move_constructible
+ , long
+ )
+ {
+ // Move lhs content to backup...
+ backup_holder<LhsT> backup_lhs_content(0);
+ backup_lhs_content.swap(lhs_content); // nothrow
+
+ // ...destroy lhs content...
+ lhs_content.~backup_holder<LhsT>(); // nothrow
+
+ BOOST_TRY
+ {
+ // ...and attempt to copy rhs content into lhs storage:
+ copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
+ }
+ BOOST_CATCH (...)
+ {
+ // In case of failure, copy backup pointer to lhs storage...
+ new(lhs_.storage_.address())
+ backup_holder<LhsT>( 0 ); // nothrow
+
+ static_cast<backup_holder<LhsT>* >(lhs_.storage_.address())
+ ->swap(backup_lhs_content); // nothrow
+
+ // ...and rethrow:
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+
+ // In case of success, indicate new content type:
+ lhs_.indicate_which(rhs_which_); // nothrow
+ }
+
+ template <typename LhsT>
+ void backup_assign_impl(
+ LhsT& lhs_content
+ , mpl::true_ // is_nothrow_move_constructible
+ , int
+ )
+ {
+ // Move lhs content to backup...
+ LhsT backup_lhs_content(
+ ::boost::detail::variant::move(lhs_content)
+ ); // nothrow
+
+ // ...destroy lhs content...
+ lhs_content.~LhsT(); // nothrow
+
+ BOOST_TRY
+ {
+ // ...and attempt to copy rhs content into lhs storage:
+ copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
+ }
+ BOOST_CATCH (...)
+ {
+ // In case of failure, restore backup content to lhs storage...
+ new(lhs_.storage_.address())
+ LhsT(
+ ::boost::detail::variant::move(backup_lhs_content)
+ ); // nothrow
+
+ // ...and rethrow:
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+
+ // In case of success, indicate new content type:
+ lhs_.indicate_which(rhs_which_); // nothrow
+ }
+
+ template <typename LhsT>
+ void backup_assign_impl(
+ LhsT& lhs_content
+ , mpl::false_ // is_nothrow_move_constructible
+ , int
+ )
+ {
+ // Backup lhs content...
+ LhsT* backup_lhs_ptr = new LhsT(lhs_content);
+
+ // ...destroy lhs content...
+ lhs_content.~LhsT(); // nothrow
+
+ BOOST_TRY
+ {
+ // ...and attempt to copy rhs content into lhs storage:
+ copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
+ }
+ BOOST_CATCH (...)
+ {
+ // In case of failure, copy backup pointer to lhs storage...
+ new(lhs_.storage_.address())
+ backup_holder<LhsT>( backup_lhs_ptr ); // nothrow
+
+ // ...indicate now using backup...
+ lhs_.indicate_backup_which( lhs_.which() ); // nothrow
+
+ // ...and rethrow:
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+
+ // In case of success, indicate new content type...
+ lhs_.indicate_which(rhs_which_); // nothrow
+
+ // ...and delete backup:
+ delete backup_lhs_ptr; // nothrow
+ }
+
+public: // visitor interface
+
+ template <typename LhsT>
+ BOOST_VARIANT_AUX_RETURN_VOID_TYPE
+ internal_visit(LhsT& lhs_content, int)
+ {
+ typedef typename is_nothrow_move_constructible<LhsT>::type
+ nothrow_move;
+
+ backup_assign_impl( lhs_content, nothrow_move(), 1L);
+
+ BOOST_VARIANT_AUX_RETURN_VOID;
+ }
+
+#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
+private:
+ // silence MSVC warning C4512: assignment operator could not be generated
+ backup_assigner& operator= (backup_assigner const&);
+#endif
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) class swap_with
+//
+// Visitor that swaps visited value with content of given variant.
+//
+// Precondition: Given variant MUST have same logical type as visited value.
+//
+template <typename Variant>
+struct swap_with
+ : public static_visitor<>
+{
+private: // representation
+
+ Variant& toswap_;
+
+public: // structors
+
+ explicit swap_with(Variant& toswap) BOOST_NOEXCEPT
+ : toswap_(toswap)
+ {
+ }
+
+public: // internal visitor interfaces
+
+ template <typename T>
+ void operator()(T& operand) const
+ {
+ // Since the precondition ensures types are same, get T...
+ known_get<T> getter;
+ T& other = toswap_.apply_visitor(getter);
+
+ // ...and swap:
+ ::boost::detail::variant::move_swap( operand, other );
+ }
+
+private:
+ swap_with& operator=(const swap_with&);
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) class reflect
+//
+// Generic static visitor that performs a typeid on the value it visits.
+//
+
+class reflect
+ : public static_visitor<const boost::typeindex::type_info&>
+{
+public: // visitor interfaces
+
+ template <typename T>
+ const boost::typeindex::type_info& operator()(const T&) const BOOST_NOEXCEPT
+ {
+ return boost::typeindex::type_id<T>().type_info();
+ }
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) class comparer
+//
+// Generic static visitor that compares the content of the given lhs variant
+// with the visited rhs content using Comp.
+//
+// Precondition: lhs.which() == rhs.which()
+//
+template <typename Variant, typename Comp>
+class comparer
+ : public static_visitor<bool>
+{
+private: // representation
+
+ const Variant& lhs_;
+
+public: // structors
+
+ explicit comparer(const Variant& lhs) BOOST_NOEXCEPT
+ : lhs_(lhs)
+ {
+ }
+
+public: // visitor interfaces
+
+ template <typename T>
+ bool operator()(const T& rhs_content) const
+ {
+ // Since the precondition ensures lhs and rhs types are same, get T...
+ known_get<const T> getter;
+ const T& lhs_content = lhs_.apply_visitor(getter);
+
+ // ...and compare lhs and rhs contents:
+ return Comp()(lhs_content, rhs_content);
+ }
+
+private:
+ comparer& operator=(const comparer&);
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) class equal_comp
+//
+// Generic function object compares lhs with rhs using operator==.
+//
+struct equal_comp
+{
+ template <typename T>
+ bool operator()(const T& lhs, const T& rhs) const
+ {
+ return lhs == rhs;
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) class less_comp
+//
+// Generic function object compares lhs with rhs using operator<.
+//
+struct less_comp
+{
+ template <typename T>
+ bool operator()(const T& lhs, const T& rhs) const
+ {
+ return lhs < rhs;
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) class template invoke_visitor
+//
+// Internal visitor that invokes the given visitor using:
+// * for wrappers (e.g., recursive_wrapper), the wrapper's held value.
+// * for all other values, the value itself.
+//
+template <typename Visitor>
+class invoke_visitor
+{
+private: // representation
+
+ Visitor& visitor_;
+
+public: // visitor typedefs
+
+ typedef typename Visitor::result_type
+ result_type;
+
+public: // structors
+
+ explicit invoke_visitor(Visitor& visitor) BOOST_NOEXCEPT
+ : visitor_(visitor)
+ {
+ }
+
+#if !defined(BOOST_NO_VOID_RETURNS)
+
+public: // internal visitor interfaces
+
+ template <typename T>
+ result_type internal_visit(T& operand, int)
+ {
+ return visitor_(operand);
+ }
+
+# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
+ template <typename T>
+ result_type internal_visit(const T& operand, int)
+ {
+ return visitor_(operand);
+ }
+# endif
+
+#else // defined(BOOST_NO_VOID_RETURNS)
+
+private: // helpers, for internal visitor interfaces (below)
+
+ template <typename T>
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
+ visit_impl(T& operand, mpl::false_)
+ {
+ return visitor_(operand);
+ }
+
+ template <typename T>
+ BOOST_VARIANT_AUX_RETURN_VOID_TYPE
+ visit_impl(T& operand, mpl::true_)
+ {
+ visitor_(operand);
+ BOOST_VARIANT_AUX_RETURN_VOID;
+ }
+
+public: // internal visitor interfaces
+
+ template <typename T>
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
+ internal_visit(T& operand, int)
+ {
+ typedef typename is_same<result_type, void>::type
+ has_void_result_type;
+
+ return visit_impl(operand, has_void_result_type());
+ }
+
+#endif // BOOST_NO_VOID_RETURNS) workaround
+
+public: // internal visitor interfaces, cont.
+
+ template <typename T>
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
+ internal_visit(boost::recursive_wrapper<T>& operand, long)
+ {
+ return internal_visit( operand.get(), 1L );
+ }
+
+ template <typename T>
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
+ internal_visit(const boost::recursive_wrapper<T>& operand, long)
+ {
+ return internal_visit( operand.get(), 1L );
+ }
+
+ template <typename T>
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
+ internal_visit(boost::detail::reference_content<T>& operand, long)
+ {
+ return internal_visit( operand.get(), 1L );
+ }
+
+ template <typename T>
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
+ internal_visit(const boost::detail::reference_content<T>& operand, long)
+ {
+ return internal_visit( operand.get(), 1L );
+ }
+
+ template <typename T>
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
+ internal_visit(boost::detail::variant::backup_holder<T>& operand, long)
+ {
+ return internal_visit( operand.get(), 1L );
+ }
+
+ template <typename T>
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
+ internal_visit(const boost::detail::variant::backup_holder<T>& operand, long)
+ {
+ return internal_visit( operand.get(), 1L );
+ }
+
+#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
+private:
+ // silence MSVC warning C4512: assignment operator could not be generated
+ invoke_visitor& operator= (invoke_visitor const&);
+#endif
+};
+
+}} // namespace detail::variant
+
+///////////////////////////////////////////////////////////////////////////////
+// class template variant (concept inspired by Andrei Alexandrescu)
+//
+// See docs and boost/variant/variant_fwd.hpp for more information.
+//
+template <
+ typename T0_
+ , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)
+ >
+class variant
+{
+private: // helpers, for typedefs (below)
+
+ typedef variant wknd_self_t;
+
+ struct is_recursive_
+ : detail::variant::is_recursive_flag<T0_>
+ {
+ };
+
+ typedef typename mpl::eval_if<
+ is_recursive_
+ , T0_
+ , mpl::identity< T0_ >
+ >::type unwrapped_T0_;
+
+ struct is_sequence_based_
+ : detail::variant::is_over_sequence<unwrapped_T0_>
+ {
+ };
+
+#if !defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
+
+private: // helpers, for typedefs (below)
+
+ typedef typename mpl::eval_if<
+ is_sequence_based_
+ , unwrapped_T0_ // over_sequence<...>::type
+ , detail::variant::make_variant_list<
+ unwrapped_T0_
+ , BOOST_VARIANT_ENUM_SHIFTED_PARAMS(T)
+ >
+ >::type specified_types;
+
+ BOOST_STATIC_ASSERT((
+ ::boost::mpl::not_< mpl::empty<specified_types> >::value
+ ));
+
+ typedef typename mpl::eval_if<
+ is_recursive_
+ , mpl::transform<
+ specified_types
+ , mpl::protect<
+ detail::variant::quoted_enable_recursive<wknd_self_t>
+ >
+ >
+ , mpl::identity< specified_types >
+ >::type recursive_enabled_types;
+
+public: // public typedefs
+
+ typedef typename mpl::transform<
+ recursive_enabled_types
+ , unwrap_recursive<mpl::_1>
+ >::type types;
+
+private: // internal typedefs
+
+ typedef typename mpl::transform<
+ recursive_enabled_types
+ , mpl::protect< detail::make_reference_content<> >
+ >::type internal_types;
+
+ typedef typename mpl::front<
+ internal_types
+ >::type internal_T0;
+
+#else // defined(BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
+
+private: // helpers, for typedefs (below)
+
+ typedef unwrapped_T0_ T0;
+
+ #define BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS(z,N,_) \
+ typedef typename mpl::eval_if< \
+ is_recursive_ \
+ , detail::variant::enable_recursive< \
+ BOOST_PP_CAT(T,N) \
+ , wknd_self_t \
+ > \
+ , mpl::identity< BOOST_PP_CAT(T,N) > \
+ >::type BOOST_PP_CAT(recursive_enabled_T,N); \
+ /**/
+
+ BOOST_PP_REPEAT(
+ BOOST_VARIANT_LIMIT_TYPES
+ , BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
+ , _
+ )
+
+ #undef BOOST_VARIANT_AUX_ENABLE_RECURSIVE_TYPEDEFS
+
+ #define BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS(z,N,_) \
+ typedef typename unwrap_recursive< \
+ BOOST_PP_CAT(recursive_enabled_T,N) \
+ >::type BOOST_PP_CAT(public_T,N); \
+ /**/
+
+ BOOST_PP_REPEAT(
+ BOOST_VARIANT_LIMIT_TYPES
+ , BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
+ , _
+ )
+
+ #undef BOOST_VARIANT_AUX_UNWRAP_RECURSIVE_TYPEDEFS
+
+public: // public typedefs
+
+ typedef typename detail::variant::make_variant_list<
+ BOOST_VARIANT_ENUM_PARAMS(public_T)
+ >::type types;
+
+private: // helpers, for internal typedefs (below)
+
+ #define BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS(z,N,_) \
+ typedef detail::make_reference_content< \
+ BOOST_PP_CAT(recursive_enabled_T,N) \
+ >::type BOOST_PP_CAT(internal_T,N); \
+ /**/
+
+ BOOST_PP_REPEAT(
+ BOOST_VARIANT_LIMIT_TYPES
+ , BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
+ , _
+ )
+
+ #undef BOOST_VARIANT_AUX_MAKE_REFERENCE_CONTENT_TYPEDEFS
+
+private: // internal typedefs
+
+ typedef typename detail::variant::make_variant_list<
+ BOOST_VARIANT_ENUM_PARAMS(internal_T)
+ >::type internal_types;
+
+private: // static precondition assertions
+
+ // NOTE TO USER :
+ // variant< type-sequence > syntax is not supported on this compiler!
+ //
+ BOOST_MPL_ASSERT_NOT(( is_sequence_based_ ));
+
+#endif // BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT workaround
+
+private: // helpers, for representation (below)
+
+ typedef typename detail::variant::find_fallback_type<
+ internal_types
+ >::type fallback_type_result_;
+
+ typedef typename fallback_type_result_::first
+ fallback_type_index_;
+ typedef typename fallback_type_result_::second
+ fallback_type_;
+
+ struct has_fallback_type_
+ : mpl::not_<
+ is_same< fallback_type_, detail::variant::no_fallback_type >
+ >
+ {
+ };
+
+ typedef has_fallback_type_
+ never_uses_backup_flag;
+
+ typedef typename detail::variant::make_storage<
+ internal_types, never_uses_backup_flag
+ >::type storage_t;
+
+#ifndef BOOST_NO_CXX11_NOEXCEPT
+ typedef typename detail::variant::is_variant_move_noexcept_constructible<
+ internal_types
+ > variant_move_noexcept_constructible;
+
+ typedef typename detail::variant::is_variant_move_noexcept_assignable<
+ internal_types
+ > variant_move_noexcept_assignable;
+
+#endif
+
+private: // helpers, for representation (below)
+
+ // which_ on:
+ // * [0, size<internal_types>) indicates stack content
+ // * [-size<internal_types>, 0) indicates pointer to heap backup
+ // if which_ >= 0:
+ // * then which() -> which_
+ // * else which() -> -(which_ + 1)
+
+#if !defined(BOOST_VARIANT_MINIMIZE_SIZE)
+
+ typedef int which_t;
+
+#else // defined(BOOST_VARIANT_MINIMIZE_SIZE)
+
+ // [if O1_size available, then attempt which_t size optimization...]
+ // [select signed char if fewer than SCHAR_MAX types, else signed int:]
+ typedef typename mpl::eval_if<
+ mpl::equal_to< mpl::O1_size<internal_types>, mpl::long_<-1> >
+ , mpl::identity< int >
+ , mpl::if_<
+ mpl::less< mpl::O1_size<internal_types>, mpl::int_<SCHAR_MAX> >
+ , signed char
+ , int
+ >
+ >::type which_t;
+
+#endif // BOOST_VARIANT_MINIMIZE_SIZE switch
+
+// representation -- private when possible
+#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
+ private:
+#else
+ public:
+#endif
+
+ which_t which_;
+ storage_t storage_;
+
+ void indicate_which(int which_arg) BOOST_NOEXCEPT
+ {
+ which_ = static_cast<which_t>( which_arg );
+ }
+
+ void indicate_backup_which(int which_arg) BOOST_NOEXCEPT
+ {
+ which_ = static_cast<which_t>( -(which_arg + 1) );
+ }
+
+private: // helpers, for queries (below)
+
+ bool using_backup() const BOOST_NOEXCEPT
+ {
+ return which_ < 0;
+ }
+
+public: // queries
+
+ int which() const BOOST_NOEXCEPT
+ {
+ // If using heap backup...
+ if (using_backup())
+ // ...then return adjusted which_:
+ return -(which_ + 1);
+
+ // Otherwise, return which_ directly:
+ return which_;
+ }
+
+private: // helpers, for structors (below)
+
+ struct initializer
+ : BOOST_VARIANT_AUX_INITIALIZER_T(
+ recursive_enabled_types, recursive_enabled_T
+ )
+ {
+ };
+
+ void destroy_content() BOOST_NOEXCEPT
+ {
+ detail::variant::destroyer visitor;
+ this->internal_apply_visitor(visitor);
+ }
+
+public: // structors
+
+ ~variant() BOOST_NOEXCEPT
+ {
+ destroy_content();
+ }
+
+ variant()
+#if !(defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5130))
+ BOOST_NOEXCEPT_IF(boost::has_nothrow_constructor<internal_T0>::value)
+#endif
+ {
+#ifdef _MSC_VER
+#pragma warning( push )
+// behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized
+#pragma warning( disable : 4345 )
+#endif
+ // NOTE TO USER :
+ // Compile error from here indicates that the first bound
+ // type is not default-constructible, and so variant cannot
+ // support its own default-construction.
+ //
+ new( storage_.address() ) internal_T0();
+ indicate_which(0); // zero is the index of the first bounded type
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+ }
+
+private: // helpers, for structors, cont. (below)
+
+ class convert_copy_into
+ : public static_visitor<int>
+ {
+ private: // representation
+
+ void* storage_;
+
+ public: // structors
+
+ explicit convert_copy_into(void* storage) BOOST_NOEXCEPT
+ : storage_(storage)
+ {
+ }
+
+ public: // internal visitor interfaces (below)
+
+ template <typename T>
+ int internal_visit(T& operand, int) const
+ {
+ // NOTE TO USER :
+ // Compile error here indicates one of the source variant's types
+ // cannot be unambiguously converted to the destination variant's
+ // types (or that no conversion exists).
+ //
+ return initializer::initialize(storage_, operand);
+ }
+
+# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
+ template <typename T>
+ result_type internal_visit(const T& operand, int) const
+ {
+ return initializer::initialize(storage_, operand);
+ }
+# endif
+
+ template <typename T>
+ int internal_visit(boost::detail::reference_content<T>& operand, long) const
+ {
+ return internal_visit( operand.get(), 1L );
+ }
+
+ template <typename T>
+ int internal_visit(const boost::detail::reference_content<T>& operand, long) const
+ {
+ return internal_visit( operand.get(), 1L );
+ }
+
+ template <typename T>
+ int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
+ {
+ return internal_visit( operand.get(), 1L );
+ }
+
+ template <typename T>
+ int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
+ {
+ return internal_visit( operand.get(), 1L );
+ }
+
+ template <typename T>
+ int internal_visit(boost::recursive_wrapper<T>& operand, long) const
+ {
+ return internal_visit( operand.get(), 1L );
+ }
+
+ template <typename T>
+ int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
+ {
+ return internal_visit( operand.get(), 1L );
+ }
+
+ };
+
+ friend class convert_copy_into;
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ class convert_move_into
+ : public static_visitor<int>
+ {
+ private: // representation
+
+ void* storage_;
+
+ public: // structors
+
+ explicit convert_move_into(void* storage) BOOST_NOEXCEPT
+ : storage_(storage)
+ {
+ }
+
+ public: // internal visitor interfaces (below)
+
+ template <typename T>
+ int internal_visit(T& operand, int) const
+ {
+ // NOTE TO USER :
+ // Compile error here indicates one of the source variant's types
+ // cannot be unambiguously converted to the destination variant's
+ // types (or that no conversion exists).
+ //
+ return initializer::initialize(storage_, detail::variant::move(operand) );
+ }
+
+ template <typename T>
+ int internal_visit(boost::detail::reference_content<T>& operand, long) const
+ {
+ return internal_visit( operand.get(), 1L );
+ }
+
+ template <typename T>
+ int internal_visit(const boost::detail::reference_content<T>& operand, long) const
+ {
+ return internal_visit( operand.get(), 1L );
+ }
+
+ template <typename T>
+ int internal_visit(boost::detail::variant::backup_holder<T>& operand, long) const
+ {
+ return internal_visit( operand.get(), 1L );
+ }
+
+ template <typename T>
+ int internal_visit(const boost::detail::variant::backup_holder<T>& operand, long) const
+ {
+ return internal_visit( operand.get(), 1L );
+ }
+
+ template <typename T>
+ int internal_visit(boost::recursive_wrapper<T>& operand, long) const
+ {
+ return internal_visit( operand.get(), 1L );
+ }
+
+ template <typename T>
+ int internal_visit(const boost::recursive_wrapper<T>& operand, long) const
+ {
+ return internal_visit( operand.get(), 1L );
+ }
+ };
+
+ friend class convert_move_into;
+#endif
+
+private: // helpers, for structors, below
+
+ template <typename T>
+ void convert_construct(
+ T& operand
+ , int
+ , mpl::false_ = mpl::false_() // is_foreign_variant
+ )
+ {
+ // NOTE TO USER :
+ // Compile error here indicates that the given type is not
+ // unambiguously convertible to one of the variant's types
+ // (or that no conversion exists).
+ //
+ indicate_which(
+ initializer::initialize(
+ storage_.address()
+ , operand
+ )
+ );
+ }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <typename T>
+ typename boost::enable_if<boost::is_rvalue_reference<T&&> >::type convert_construct(
+ T&& operand
+ , int
+ , mpl::false_ = mpl::false_() // is_foreign_variant
+ )
+ {
+ // NOTE TO USER :
+ // Compile error here indicates that the given type is not
+ // unambiguously convertible to one of the variant's types
+ // (or that no conversion exists).
+ //
+ indicate_which(
+ initializer::initialize(
+ storage_.address()
+ , detail::variant::move(operand)
+ )
+ );
+ }
+#endif
+
+ template <typename Variant>
+ void convert_construct(
+ Variant& operand
+ , long
+ , mpl::true_// is_foreign_variant
+ )
+ {
+ convert_copy_into visitor(storage_.address());
+ indicate_which(
+ operand.internal_apply_visitor(visitor)
+ );
+ }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <typename Variant>
+ typename boost::enable_if<boost::is_rvalue_reference<Variant&&> >::type convert_construct(
+ Variant&& operand
+ , long
+ , mpl::true_// is_foreign_variant
+ )
+ {
+ convert_move_into visitor(storage_.address());
+ indicate_which(
+ operand.internal_apply_visitor(visitor)
+ );
+ }
+#endif
+
+ template <typename Variant>
+ void convert_construct_variant(Variant& operand)
+ {
+ // [Determine if the given variant is itself a bounded type, or if its
+ // content needs to be converted (i.e., it is a 'foreign' variant):]
+ //
+
+ typedef typename mpl::find_if<
+ types
+ , is_same<
+ add_const<mpl::_1>
+ , const Variant
+ >
+ >::type found_it;
+
+ typedef typename mpl::end<types>::type not_found;
+ typedef typename is_same<
+ found_it, not_found
+ >::type is_foreign_variant;
+
+ // Convert construct from operand:
+ convert_construct(
+ operand, 1L
+ , is_foreign_variant()
+ );
+ }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <typename Variant>
+ typename boost::enable_if<boost::is_rvalue_reference<Variant&&> >::type convert_construct_variant(Variant&& operand)
+ {
+ // [Determine if the given variant is itself a bounded type, or if its
+ // content needs to be converted (i.e., it is a 'foreign' variant):]
+ //
+
+ typedef typename mpl::find_if<
+ types
+ , is_same<
+ add_const<mpl::_1>
+ , const Variant
+ >
+ >::type found_it;
+
+ typedef typename mpl::end<types>::type not_found;
+ typedef typename is_same<
+ found_it, not_found
+ >::type is_foreign_variant;
+
+ // Convert move construct from operand:
+ convert_construct(
+ detail::variant::move(operand), 1L
+ , is_foreign_variant()
+ );
+ }
+#endif
+
+ template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
+ void convert_construct(
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
+ , long
+ )
+ {
+ convert_construct_variant(operand);
+ }
+
+ template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
+ void convert_construct(
+ const boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>& operand
+ , long
+ )
+ {
+ convert_construct_variant(operand);
+ }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <BOOST_VARIANT_ENUM_PARAMS(typename U)>
+ void convert_construct(
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(U)>&& operand
+ , long
+ )
+ {
+ convert_construct_variant( detail::variant::move(operand) );
+ }
+#endif
+
+public: // structors, cont.
+
+#if !defined(BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING)
+
+ template <typename T>
+ variant(const T& operand)
+ {
+ convert_construct(operand, 1L);
+ }
+
+ template <typename T>
+ variant(T& operand)
+ {
+ convert_construct(operand, 1L);
+ }
+
+#elif defined(BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND)
+
+ // For compilers that cannot distinguish between T& and const T& in
+ // template constructors, but do fully support SFINAE, we can workaround:
+
+ template <typename T>
+ variant(const T& operand)
+ {
+ convert_construct(operand, 1L);
+ }
+
+ template <typename T>
+ variant(
+ T& operand
+ , typename enable_if<
+ mpl::not_< is_const<T> >
+ , void
+ >::type* = 0
+ )
+ {
+ convert_construct(operand, 1L);
+ }
+
+#else // !defined(BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND)
+
+ // For compilers that cannot distinguish between T& and const T& in
+ // template constructors, and do NOT support SFINAE, we can't workaround:
+
+ template <typename T>
+ variant(const T& operand)
+ {
+ convert_construct(operand, 1L);
+ }
+#endif // BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING workarounds
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <class T>
+ variant(T&& operand, typename boost::enable_if<boost::is_rvalue_reference<T&&> >::type* = 0,
+ typename boost::disable_if<boost::is_const<T> >::type* = 0)
+ {
+ convert_construct( detail::variant::move(operand), 1L);
+ }
+#endif
+
+public: // structors, cont.
+
+ // [MSVC6 requires copy constructor appear after template constructors]
+ variant(const variant& operand)
+ {
+ // Copy the value of operand into *this...
+ detail::variant::copy_into visitor( storage_.address() );
+ operand.internal_apply_visitor(visitor);
+
+ // ...and activate the *this's primary storage on success:
+ indicate_which(operand.which());
+ }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ variant(variant&& operand) BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value)
+ {
+ // Move the value of operand into *this...
+ detail::variant::move_into visitor( storage_.address() );
+ operand.internal_apply_visitor(visitor);
+
+ // ...and activate the *this's primary storage on success:
+ indicate_which(operand.which());
+ }
+#endif
+
+private: // helpers, for modifiers (below)
+
+# if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
+ template <typename Variant>
+ friend class detail::variant::backup_assigner;
+# endif
+
+ // class assigner
+ //
+ // Internal visitor that "assigns" the visited value to the given variant
+ // by appropriate destruction and copy-construction.
+ //
+
+ class assigner
+ : public static_visitor<>
+ {
+ protected: // representation
+
+ variant& lhs_;
+ const int rhs_which_;
+
+ public: // structors
+
+ assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
+ : lhs_(lhs)
+ , rhs_which_(rhs_which)
+ {
+ }
+
+ protected: // helpers, for internal visitor interface (below)
+
+ template <typename RhsT, typename B1, typename B2>
+ void assign_impl(
+ const RhsT& rhs_content
+ , mpl::true_ // has_nothrow_copy
+ , B1 // is_nothrow_move_constructible
+ , B2 // has_fallback_type
+ ) const BOOST_NOEXCEPT
+ {
+ // Destroy lhs's content...
+ lhs_.destroy_content(); // nothrow
+
+ // ...copy rhs content into lhs's storage...
+ new(lhs_.storage_.address())
+ RhsT( rhs_content ); // nothrow
+
+ // ...and indicate new content type:
+ lhs_.indicate_which(rhs_which_); // nothrow
+ }
+
+ template <typename RhsT, typename B>
+ void assign_impl(
+ const RhsT& rhs_content
+ , mpl::false_ // has_nothrow_copy
+ , mpl::true_ // is_nothrow_move_constructible
+ , B // has_fallback_type
+ ) const
+ {
+ // Attempt to make a temporary copy (so as to move it below)...
+ RhsT temp(rhs_content);
+
+ // ...and upon success destroy lhs's content...
+ lhs_.destroy_content(); // nothrow
+
+ // ...move the temporary copy into lhs's storage...
+ new(lhs_.storage_.address())
+ RhsT( detail::variant::move(temp) ); // nothrow
+
+ // ...and indicate new content type:
+ lhs_.indicate_which(rhs_which_); // nothrow
+ }
+
+ void construct_fallback() const BOOST_NOEXCEPT {
+ // In case of failure, default-construct fallback type in lhs's storage...
+ new (lhs_.storage_.address())
+ fallback_type_; // nothrow
+
+ // ...indicate construction of fallback type...
+ lhs_.indicate_which(
+ BOOST_MPL_AUX_VALUE_WKND(fallback_type_index_)::value
+ ); // nothrow
+ }
+
+ template <typename RhsT>
+ void assign_impl(
+ const RhsT& rhs_content
+ , mpl::false_ // has_nothrow_copy
+ , mpl::false_ // is_nothrow_move_constructible
+ , mpl::true_ // has_fallback_type
+ ) const
+ {
+ // Destroy lhs's content...
+ lhs_.destroy_content(); // nothrow
+
+ BOOST_TRY
+ {
+ // ...and attempt to copy rhs's content into lhs's storage:
+ new(lhs_.storage_.address())
+ RhsT( rhs_content );
+ }
+ BOOST_CATCH (...)
+ {
+ construct_fallback();
+
+ // ...and rethrow:
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+
+ // In the event of success, indicate new content type:
+ lhs_.indicate_which(rhs_which_); // nothrow
+ }
+
+ template <typename RhsT>
+ void assign_impl(
+ const RhsT& rhs_content
+ , mpl::false_ // has_nothrow_copy
+ , mpl::false_ // is_nothrow_move_constructible
+ , mpl::false_ // has_fallback_type
+ ) const
+ {
+ detail::variant::backup_assigner<wknd_self_t>
+ visitor(lhs_, rhs_which_, rhs_content);
+ lhs_.internal_apply_visitor(visitor);
+ }
+
+ public: // internal visitor interfaces
+
+ template <typename RhsT>
+ BOOST_VARIANT_AUX_RETURN_VOID_TYPE
+ internal_visit(const RhsT& rhs_content, int) const
+ {
+ typedef typename has_nothrow_copy<RhsT>::type
+ nothrow_copy;
+ typedef typename mpl::or_< // reduces compile-time
+ nothrow_copy
+ , is_nothrow_move_constructible<RhsT>
+ >::type nothrow_move_constructor;
+
+ assign_impl(
+ rhs_content
+ , nothrow_copy()
+ , nothrow_move_constructor()
+ , has_fallback_type_()
+ );
+
+ BOOST_VARIANT_AUX_RETURN_VOID;
+ }
+
+#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
+ private:
+ // silence MSVC warning C4512: assignment operator could not be generated
+ assigner& operator= (assigner const&);
+#endif
+ };
+
+ friend class assigner;
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ // class move_assigner
+ //
+ // Internal visitor that "move assigns" the visited value to the given variant
+ // by appropriate destruction and move-construction.
+ //
+
+ class move_assigner
+ : public assigner
+ {
+ public: // structors
+
+ move_assigner(variant& lhs, int rhs_which) BOOST_NOEXCEPT
+ : assigner(lhs, rhs_which)
+ {
+ }
+
+ private: // helpers, for internal visitor interface (below)
+
+ template <typename RhsT, typename B2>
+ void assign_impl(
+ RhsT& rhs_content
+ , mpl::true_ // has_nothrow_copy
+ , mpl::false_ // is_nothrow_move_constructible
+ , B2 // has_fallback_type
+ ) const BOOST_NOEXCEPT
+ {
+ assigner::assign_impl(rhs_content, mpl::true_(), mpl::false_(), B2());
+ }
+
+ template <typename RhsT, typename B, typename B2>
+ void assign_impl(
+ RhsT& rhs_content
+ , B // has_nothrow_copy
+ , mpl::true_ // is_nothrow_move_constructible
+ , B2 // has_fallback_type
+ ) const BOOST_NOEXCEPT
+ {
+ // ...destroy lhs's content...
+ assigner::lhs_.destroy_content(); // nothrow
+
+ // ...move the rhs_content into lhs's storage...
+ new(assigner::lhs_.storage_.address())
+ RhsT( detail::variant::move(rhs_content) ); // nothrow
+
+ // ...and indicate new content type:
+ assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow
+ }
+
+ template <typename RhsT>
+ void assign_impl(
+ RhsT& rhs_content
+ , mpl::false_ // has_nothrow_copy
+ , mpl::false_ // is_nothrow_move_constructible
+ , mpl::true_ // has_fallback_type
+ ) const
+ {
+ // Destroy lhs's content...
+ assigner::lhs_.destroy_content(); // nothrow
+
+ BOOST_TRY
+ {
+ // ...and attempt to copy rhs's content into lhs's storage:
+ new(assigner::lhs_.storage_.address())
+ RhsT( detail::variant::move(rhs_content) );
+ }
+ BOOST_CATCH (...)
+ {
+ assigner::construct_fallback();
+
+ // ...and rethrow:
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+
+ // In the event of success, indicate new content type:
+ assigner::lhs_.indicate_which(assigner::rhs_which_); // nothrow
+ }
+
+ template <typename RhsT>
+ void assign_impl(
+ RhsT& rhs_content
+ , mpl::false_ // has_nothrow_copy
+ , mpl::false_ // is_nothrow_move_constructible
+ , mpl::false_ // has_fallback_type
+ ) const
+ {
+ assigner::assign_impl(rhs_content, mpl::false_(), mpl::false_(), mpl::false_());
+ }
+
+ public: // internal visitor interfaces
+
+ template <typename RhsT>
+ BOOST_VARIANT_AUX_RETURN_VOID_TYPE
+ internal_visit(RhsT& rhs_content, int) const
+ {
+ typedef typename is_nothrow_move_constructible<RhsT>::type
+ nothrow_move_constructor;
+ typedef typename mpl::or_< // reduces compile-time
+ nothrow_move_constructor
+ , has_nothrow_copy<RhsT>
+ >::type nothrow_copy;
+
+ assign_impl(
+ rhs_content
+ , nothrow_copy()
+ , nothrow_move_constructor()
+ , has_fallback_type_()
+ );
+
+ BOOST_VARIANT_AUX_RETURN_VOID;
+ }
+
+#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600))
+ private:
+ // silence MSVC warning C4512: assignment operator could not be generated
+ move_assigner& operator= (move_assigner const&);
+#endif
+ };
+
+ friend class move_assigner;
+#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
+
+ void variant_assign(const variant& rhs)
+ {
+ // If the contained types are EXACTLY the same...
+ if (which_ == rhs.which_)
+ {
+ // ...then assign rhs's storage to lhs's content:
+ detail::variant::assign_storage visitor(rhs.storage_.address());
+ this->internal_apply_visitor(visitor);
+ }
+ else
+ {
+ // Otherwise, perform general (copy-based) variant assignment:
+ assigner visitor(*this, rhs.which());
+ rhs.internal_apply_visitor(visitor);
+ }
+ }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ void variant_assign(variant&& rhs)
+ {
+ // If the contained types are EXACTLY the same...
+ if (which_ == rhs.which_)
+ {
+ // ...then move rhs's storage to lhs's content:
+ detail::variant::move_storage visitor(rhs.storage_.address());
+ this->internal_apply_visitor(visitor);
+ }
+ else
+ {
+ // Otherwise, perform general (move-based) variant assignment:
+ move_assigner visitor(*this, rhs.which());
+ rhs.internal_apply_visitor(visitor);
+ }
+ }
+#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
+
+private: // helpers, for modifiers (below)
+
+ template <typename T>
+ void assign(const T& rhs)
+ {
+ // If direct T-to-T assignment is not possible...
+ detail::variant::direct_assigner<T> direct_assign(rhs);
+ if (this->apply_visitor(direct_assign) == false)
+ {
+ // ...then convert rhs to variant and assign:
+ //
+ // While potentially inefficient, the following construction of a
+ // variant allows T as any type convertible to one of the bounded
+ // types without excessive code redundancy.
+ //
+ variant temp(rhs);
+ variant_assign( detail::variant::move(temp) );
+ }
+ }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <typename T>
+ void move_assign(T&& rhs)
+ {
+ // If direct T-to-T move assignment is not possible...
+ detail::variant::direct_mover<T> direct_move(rhs);
+ if (this->apply_visitor(direct_move) == false)
+ {
+ // ...then convert rhs to variant and assign:
+ //
+ // While potentially inefficient, the following construction of a
+ // variant allows T as any type convertible to one of the bounded
+ // types without excessive code redundancy.
+ //
+ variant temp( detail::variant::move(rhs) );
+ variant_assign( detail::variant::move(temp) );
+ }
+ }
+#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
+
+public: // modifiers
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ template <class T>
+ typename boost::enable_if_c<boost::is_rvalue_reference<T&&>::value && !boost::is_const<T>::value, variant& >::type
+ operator=(T&& rhs)
+ {
+ move_assign( detail::variant::move(rhs) );
+ return *this;
+ }
+#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
+
+ template <typename T>
+ variant& operator=(const T& rhs)
+ {
+ assign(rhs);
+ return *this;
+ }
+
+ // [MSVC6 requires copy assign appear after templated operator=]
+ variant& operator=(const variant& rhs)
+ {
+ variant_assign(rhs);
+ return *this;
+ }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ variant& operator=(variant&& rhs)
+#if !defined(__GNUC__) || (__GNUC__ != 4) || (__GNUC_MINOR__ > 6)
+ BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value && variant_move_noexcept_assignable::type::value)
+#endif
+ {
+ variant_assign( detail::variant::move(rhs) );
+ return *this;
+ }
+#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
+
+ void swap(variant& rhs)
+ {
+ // If the contained types are the same...
+ if (which() == rhs.which())
+ {
+ // ...then swap the values directly:
+ detail::variant::swap_with<variant> visitor(rhs);
+ this->apply_visitor(visitor);
+ }
+ else
+ {
+ // ...otherwise, perform general variant swap:
+ variant tmp( detail::variant::move(rhs) );
+ rhs = detail::variant::move(*this);
+ *this = detail::variant::move(tmp);
+ }
+ }
+
+public: // queries
+
+ //
+ // NOTE: member which() defined above.
+ //
+
+ bool empty() const BOOST_NOEXCEPT
+ {
+ return false;
+ }
+
+ const boost::typeindex::type_info& type() const
+ {
+ detail::variant::reflect visitor;
+ return this->apply_visitor(visitor);
+ }
+
+public: // prevent comparison with foreign types
+
+// Obsolete. Remove.
+# define BOOST_VARIANT_AUX_FAIL_COMPARISON_RETURN_TYPE \
+ void
+
+ template <typename U>
+ void operator==(const U&) const
+ {
+ BOOST_STATIC_ASSERT( false && sizeof(U) );
+ }
+
+ template <typename U>
+ void operator<(const U&) const
+ {
+ BOOST_STATIC_ASSERT( false && sizeof(U) );
+ }
+
+ template <typename U>
+ void operator!=(const U&) const
+ {
+ BOOST_STATIC_ASSERT( false && sizeof(U) );
+ }
+
+ template <typename U>
+ void operator>(const U&) const
+ {
+ BOOST_STATIC_ASSERT( false && sizeof(U) );
+ }
+
+ template <typename U>
+ void operator<=(const U&) const
+ {
+ BOOST_STATIC_ASSERT( false && sizeof(U) );
+ }
+
+ template <typename U>
+ void operator>=(const U&) const
+ {
+ BOOST_STATIC_ASSERT( false && sizeof(U) );
+ }
+
+public: // comparison operators
+
+ // [MSVC6 requires these operators appear after template operators]
+
+ bool operator==(const variant& rhs) const
+ {
+ if (this->which() != rhs.which())
+ return false;
+
+ detail::variant::comparer<
+ variant, detail::variant::equal_comp
+ > visitor(*this);
+ return rhs.apply_visitor(visitor);
+ }
+
+ bool operator<(const variant& rhs) const
+ {
+ //
+ // Dirk Schreib suggested this collating order.
+ //
+
+ if (this->which() != rhs.which())
+ return this->which() < rhs.which();
+
+ detail::variant::comparer<
+ variant, detail::variant::less_comp
+ > visitor(*this);
+ return rhs.apply_visitor(visitor);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // comparison operators != > <= >=
+ inline bool operator!=(const variant& rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+ inline bool operator>(const variant& rhs) const
+ {
+ return rhs < *this;
+ }
+
+ inline bool operator<=(const variant& rhs) const
+ {
+ return !(*this > rhs);
+ }
+
+ inline bool operator>=(const variant& rhs) const
+ {
+ return !(*this < rhs);
+ }
+
+// helpers, for visitation support (below) -- private when possible
+#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
+
+ template < BOOST_VARIANT_ENUM_PARAMS(typename U) >
+ friend class variant;
+
+private:
+
+#else// defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
+
+public:
+
+#endif// !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
+
+ template <typename Visitor, typename VoidPtrCV>
+ static
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
+ typename Visitor::result_type
+ )
+ internal_apply_visitor_impl(
+ int internal_which
+ , int logical_which
+ , Visitor& visitor
+ , VoidPtrCV storage
+ )
+ {
+ typedef mpl::int_<0> first_which;
+ typedef typename mpl::begin<internal_types>::type first_it;
+ typedef typename mpl::end<internal_types>::type last_it;
+
+ typedef detail::variant::visitation_impl_step<
+ first_it, last_it
+ > first_step;
+
+ return detail::variant::visitation_impl(
+ internal_which, logical_which
+ , visitor, storage, mpl::false_()
+ , never_uses_backup_flag()
+ , static_cast<first_which*>(0), static_cast<first_step*>(0)
+ );
+ }
+
+ template <typename Visitor>
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
+ typename Visitor::result_type
+ )
+ internal_apply_visitor(Visitor& visitor)
+ {
+ return internal_apply_visitor_impl(
+ which_, which(), visitor, storage_.address()
+ );
+ }
+
+ template <typename Visitor>
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
+ typename Visitor::result_type
+ )
+ internal_apply_visitor(Visitor& visitor) const
+ {
+ return internal_apply_visitor_impl(
+ which_, which(), visitor, storage_.address()
+ );
+ }
+
+public: // visitation support
+
+ template <typename Visitor>
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
+ typename Visitor::result_type
+ )
+ apply_visitor(Visitor& visitor)
+ {
+ detail::variant::invoke_visitor<Visitor> invoker(visitor);
+ return this->internal_apply_visitor(invoker);
+ }
+
+ template <typename Visitor>
+ BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(
+ typename Visitor::result_type
+ )
+ apply_visitor(Visitor& visitor) const
+ {
+ detail::variant::invoke_visitor<Visitor> invoker(visitor);
+ return this->internal_apply_visitor(invoker);
+ }
+
+}; // class variant
+
+///////////////////////////////////////////////////////////////////////////////
+// metafunction make_variant_over
+//
+// See docs and boost/variant/variant_fwd.hpp for more information.
+//
+template <typename Types>
+struct make_variant_over
+{
+private: // precondition assertions
+
+ BOOST_STATIC_ASSERT(( ::boost::mpl::is_sequence<Types>::value ));
+
+public: // metafunction result
+
+ typedef variant<
+ detail::variant::over_sequence< Types >
+ > type;
+
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// function template swap
+//
+// Swaps two variants of the same type (i.e., identical specification).
+//
+template < BOOST_VARIANT_ENUM_PARAMS(typename T) >
+inline void swap(
+ variant< BOOST_VARIANT_ENUM_PARAMS(T) >& lhs
+ , variant< BOOST_VARIANT_ENUM_PARAMS(T) >& rhs
+ )
+{
+ lhs.swap(rhs);
+}
+
+} // namespace boost
+
+// implementation additions
+
+#if !defined(BOOST_NO_IOSTREAM)
+#include "boost/variant/detail/variant_io.hpp"
+#endif // BOOST_NO_IOSTREAM
+
+#endif // BOOST_VARIANT_VARIANT_HPP
diff --git a/third_party/boost/boost/variant/variant_fwd.hpp b/third_party/boost/boost/variant/variant_fwd.hpp
new file mode 100644
index 0000000..381dc92
--- /dev/null
+++ b/third_party/boost/boost/variant/variant_fwd.hpp
@@ -0,0 +1,333 @@
+//-----------------------------------------------------------------------------
+// boost variant/variant_fwd.hpp header file
+// See http://www.boost.org for updates, documentation, and revision history.
+//-----------------------------------------------------------------------------
+//
+// Copyright (c) 2003 Eric Friedman, Itay Maman
+// Copyright (c) 2013 Antony Polukhin
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_VARIANT_VARIANT_FWD_HPP
+#define BOOST_VARIANT_VARIANT_FWD_HPP
+
+#include "boost/variant/detail/config.hpp"
+
+#include "boost/blank_fwd.hpp"
+#include "boost/mpl/arg.hpp"
+#include "boost/mpl/limits/arity.hpp"
+#include "boost/mpl/aux_/na.hpp"
+#include "boost/preprocessor/cat.hpp"
+#include "boost/preprocessor/enum.hpp"
+#include "boost/preprocessor/enum_params.hpp"
+#include "boost/preprocessor/enum_shifted_params.hpp"
+#include "boost/preprocessor/repeat.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+// macro BOOST_VARIANT_NO_REFERENCE_SUPPORT
+//
+// Defined if variant does not support references as bounded types.
+//
+#if defined(BOOST_VARIANT_AUX_BROKEN_CONSTRUCTOR_TEMPLATE_ORDERING) \
+ && !defined(BOOST_VARIANT_AUX_HAS_CONSTRUCTOR_TEMPLATE_ORDERING_SFINAE_WKND) \
+ && !defined(BOOST_VARIANT_NO_REFERENCE_SUPPORT)
+# define BOOST_VARIANT_NO_REFERENCE_SUPPORT
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// macro BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT
+//
+// Defined if variant does not support make_variant_over (see below).
+//
+#if defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
+# define BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// macro BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT
+//
+// Defined if make_recursive_variant cannot be supported as documented.
+//
+// Note: Currently, MPL lambda facility is used as workaround if defined, and
+// so only types declared w/ MPL lambda workarounds will work.
+//
+
+#include "boost/variant/detail/substitute_fwd.hpp"
+
+#if defined(BOOST_VARIANT_DETAIL_NO_SUBSTITUTE) \
+ && !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT)
+# define BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////
+// macro BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
+//
+
+/*
+ GCC before 4.0 had no variadic tempaltes;
+ GCC 4.6 has incomplete implementation of variadic templates.
+
+ MSVC2013 has variadic templates, but they have issues.
+
+ NOTE: Clang compiler defines __GNUC__
+*/
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) \
+ || (!defined(__clang__) && defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7)) \
+ || (defined(_MSC_VER) && (_MSC_VER <= 1900)) \
+ || defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE) \
+ || defined (BOOST_VARIANT_NO_TYPE_SEQUENCE_SUPPORT)
+
+#ifndef BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
+# define BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES
+#endif
+
+#endif
+
+#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
+#include <boost/preprocessor/seq/size.hpp>
+
+#define BOOST_VARIANT_CLASS_OR_TYPENAME_TO_SEQ_class class)(
+#define BOOST_VARIANT_CLASS_OR_TYPENAME_TO_SEQ_typename typename)(
+
+#define BOOST_VARIANT_CLASS_OR_TYPENAME_TO_VARIADIC_class class...
+#define BOOST_VARIANT_CLASS_OR_TYPENAME_TO_VARIADIC_typename typename...
+
+#define ARGS_VARIADER_1(x) x ## N...
+#define ARGS_VARIADER_2(x) BOOST_VARIANT_CLASS_OR_TYPENAME_TO_VARIADIC_ ## x ## N
+
+#define BOOST_VARIANT_MAKE_VARIADIC(sequence, x) BOOST_VARIANT_MAKE_VARIADIC_I(BOOST_PP_SEQ_SIZE(sequence), x)
+#define BOOST_VARIANT_MAKE_VARIADIC_I(argscount, x) BOOST_VARIANT_MAKE_VARIADIC_II(argscount, x)
+#define BOOST_VARIANT_MAKE_VARIADIC_II(argscount, orig) ARGS_VARIADER_ ## argscount(orig)
+
+///////////////////////////////////////////////////////////////////////////////
+// BOOST_VARIANT_ENUM_PARAMS and BOOST_VARIANT_ENUM_SHIFTED_PARAMS
+//
+// Convenience macro for enumeration of variant params.
+// When variadic templates are available expands:
+// BOOST_VARIANT_ENUM_PARAMS(class Something) => class Something0, class... SomethingN
+// BOOST_VARIANT_ENUM_PARAMS(typename Something) => typename Something0, typename... SomethingN
+// BOOST_VARIANT_ENUM_PARAMS(Something) => Something0, SomethingN...
+// BOOST_VARIANT_ENUM_PARAMS(Something) => Something0, SomethingN...
+// BOOST_VARIANT_ENUM_SHIFTED_PARAMS(class Something) => class... SomethingN
+// BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename Something) => typename... SomethingN
+// BOOST_VARIANT_ENUM_SHIFTED_PARAMS(Something) => SomethingN...
+// BOOST_VARIANT_ENUM_SHIFTED_PARAMS(Something) => SomethingN...
+//
+// Rationale: Cleaner, simpler code for clients of variant library. Minimal
+// code modifications to move from C++03 to C++11.
+//
+// With BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES defined
+// will be used BOOST_VARIANT_ENUM_PARAMS and BOOST_VARIANT_ENUM_SHIFTED_PARAMS from below `#else`
+//
+
+#define BOOST_VARIANT_ENUM_PARAMS(x) \
+ x ## 0, \
+ BOOST_VARIANT_MAKE_VARIADIC( (BOOST_VARIANT_CLASS_OR_TYPENAME_TO_SEQ_ ## x), x) \
+ /**/
+
+#define BOOST_VARIANT_ENUM_SHIFTED_PARAMS(x) \
+ BOOST_VARIANT_MAKE_VARIADIC( (BOOST_VARIANT_CLASS_OR_TYPENAME_TO_SEQ_ ## x), x) \
+ /**/
+
+#else // defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
+
+///////////////////////////////////////////////////////////////////////////////
+// macro BOOST_VARIANT_LIMIT_TYPES
+//
+// Implementation-defined preprocessor symbol describing the actual
+// length of variant's pseudo-variadic template parameter list.
+//
+#include "boost/mpl/limits/list.hpp"
+#define BOOST_VARIANT_LIMIT_TYPES \
+ BOOST_MPL_LIMIT_LIST_SIZE
+
+///////////////////////////////////////////////////////////////////////////////
+// macro BOOST_VARIANT_RECURSIVE_VARIANT_MAX_ARITY
+//
+// Exposes maximum allowed arity of class templates with recursive_variant
+// arguments. That is,
+// make_recursive_variant< ..., T<[1], recursive_variant_, ... [N]> >.
+//
+#include "boost/mpl/limits/arity.hpp"
+#define BOOST_VARIANT_RECURSIVE_VARIANT_MAX_ARITY \
+ BOOST_MPL_LIMIT_METAFUNCTION_ARITY
+
+///////////////////////////////////////////////////////////////////////////////
+// macro BOOST_VARIANT_ENUM_PARAMS
+//
+// Convenience macro for enumeration of BOOST_VARIANT_LIMIT_TYPES params.
+//
+// Rationale: Cleaner, simpler code for clients of variant library.
+//
+#define BOOST_VARIANT_ENUM_PARAMS( param ) \
+ BOOST_PP_ENUM_PARAMS(BOOST_VARIANT_LIMIT_TYPES, param)
+
+///////////////////////////////////////////////////////////////////////////////
+// macro BOOST_VARIANT_ENUM_SHIFTED_PARAMS
+//
+// Convenience macro for enumeration of BOOST_VARIANT_LIMIT_TYPES-1 params.
+//
+#define BOOST_VARIANT_ENUM_SHIFTED_PARAMS( param ) \
+ BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_VARIANT_LIMIT_TYPES, param)
+
+#endif // BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES workaround
+
+
+namespace boost {
+
+namespace detail { namespace variant {
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) class void_ and class template convert_void
+//
+// Provides the mechanism by which void(NN) types are converted to
+// mpl::void_ (and thus can be passed to mpl::list).
+//
+// Rationale: This is particularly needed for the using-declarations
+// workaround (below), but also to avoid associating mpl namespace with
+// variant in argument dependent lookups (which used to happen because of
+// defaulting of template parameters to mpl::void_).
+//
+
+struct void_;
+
+template <typename T>
+struct convert_void
+{
+ typedef T type;
+};
+
+template <>
+struct convert_void< void_ >
+{
+ typedef mpl::na type;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// (workaround) BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE
+//
+// Needed to work around compilers that don't support using-declaration
+// overloads. (See the variant::initializer workarounds below.)
+//
+
+#if defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
+// (detail) tags voidNN -- NN defined on [0, BOOST_VARIANT_LIMIT_TYPES)
+//
+// Defines void types that are each unique and specializations of
+// convert_void that yields mpl::na for each voidNN type.
+//
+
+#define BOOST_VARIANT_DETAIL_DEFINE_VOID_N(z,N,_) \
+ struct BOOST_PP_CAT(void,N); \
+ \
+ template <> \
+ struct convert_void< BOOST_PP_CAT(void,N) > \
+ { \
+ typedef mpl::na type; \
+ }; \
+ /**/
+
+BOOST_PP_REPEAT(
+ BOOST_VARIANT_LIMIT_TYPES
+ , BOOST_VARIANT_DETAIL_DEFINE_VOID_N
+ , _
+ )
+
+#undef BOOST_VARIANT_DETAIL_DEFINE_VOID_N
+
+#endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround
+
+}} // namespace detail::variant
+
+#if !defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
+# define BOOST_VARIANT_AUX_DECLARE_PARAMS BOOST_VARIANT_ENUM_PARAMS(typename T)
+#else // defined(BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES)
+
+///////////////////////////////////////////////////////////////////////////////
+// (detail) macro BOOST_VARIANT_AUX_DECLARE_PARAM
+//
+// Template parameter list for variant and recursive_variant declarations.
+//
+
+#if !defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
+
+# define BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL(z, N, T) \
+ typename BOOST_PP_CAT(T,N) = detail::variant::void_ \
+ /**/
+
+#else // defined(BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE)
+
+# define BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL(z, N, T) \
+ typename BOOST_PP_CAT(T,N) = BOOST_PP_CAT(detail::variant::void,N) \
+ /**/
+
+#endif // BOOST_NO_USING_DECLARATION_OVERLOADS_FROM_TYPENAME_BASE workaround
+
+#define BOOST_VARIANT_AUX_DECLARE_PARAMS \
+ BOOST_PP_ENUM( \
+ BOOST_VARIANT_LIMIT_TYPES \
+ , BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL \
+ , T \
+ ) \
+ /**/
+
+#endif // BOOST_VARIANT_DO_NOT_USE_VARIADIC_TEMPLATES workaround
+
+///////////////////////////////////////////////////////////////////////////////
+// class template variant (concept inspired by Andrei Alexandrescu)
+//
+// Efficient, type-safe bounded discriminated union.
+//
+// Preconditions:
+// - Each type must be unique.
+// - No type may be const-qualified.
+//
+// Proper declaration form:
+// variant<types> (where types is a type-sequence)
+// or
+// variant<T0,T1,...,Tn> (where T0 is NOT a type-sequence)
+//
+template < BOOST_VARIANT_AUX_DECLARE_PARAMS > class variant;
+
+///////////////////////////////////////////////////////////////////////////////
+// metafunction make_recursive_variant
+//
+// Exposes a boost::variant with recursive_variant_ tags (below) substituted
+// with the variant itself (wrapped as needed with boost::recursive_wrapper).
+//
+template < BOOST_VARIANT_AUX_DECLARE_PARAMS > struct make_recursive_variant;
+
+#undef BOOST_VARIANT_AUX_DECLARE_PARAMS_IMPL
+#undef BOOST_VARIANT_AUX_DECLARE_PARAMS
+
+///////////////////////////////////////////////////////////////////////////////
+// type recursive_variant_
+//
+// Tag type indicates where recursive variant substitution should occur.
+//
+#if !defined(BOOST_VARIANT_NO_FULL_RECURSIVE_VARIANT_SUPPORT)
+ struct recursive_variant_ {};
+#else
+ typedef mpl::arg<1> recursive_variant_;
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// metafunction make_variant_over
+//
+// Result is a variant w/ types of the specified type sequence.
+//
+template <typename Types> struct make_variant_over;
+
+///////////////////////////////////////////////////////////////////////////////
+// metafunction make_recursive_variant_over
+//
+// Result is a recursive variant w/ types of the specified type sequence.
+//
+template <typename Types> struct make_recursive_variant_over;
+
+} // namespace boost
+
+#endif // BOOST_VARIANT_VARIANT_FWD_HPP
diff --git a/third_party/boost/boost/version.hpp b/third_party/boost/boost/version.hpp
new file mode 100644
index 0000000..fce02ec
--- /dev/null
+++ b/third_party/boost/boost/version.hpp
@@ -0,0 +1,32 @@
+// Boost version.hpp configuration header file ------------------------------//
+
+// (C) Copyright John maddock 1999. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/config for documentation
+
+#ifndef BOOST_VERSION_HPP
+#define BOOST_VERSION_HPP
+
+//
+// Caution: this is the only Boost header that is guaranteed
+// to change with every Boost release. Including this header
+// will cause a recompile every time a new Boost version is
+// used.
+//
+// BOOST_VERSION % 100 is the patch level
+// BOOST_VERSION / 100 % 1000 is the minor version
+// BOOST_VERSION / 100000 is the major version
+
+#define BOOST_VERSION 106000
+
+//
+// BOOST_LIB_VERSION must be defined to be the same as BOOST_VERSION
+// but as a *string* in the form "x_y[_z]" where x is the major version
+// number, y is the minor version number, and z is the patch level if not 0.
+// This is used by <config/auto_link.hpp> to select which library version to link to.
+
+#define BOOST_LIB_VERSION "1_60"
+
+#endif
diff --git a/third_party/boost/boost/visit_each.hpp b/third_party/boost/boost/visit_each.hpp
new file mode 100644
index 0000000..6463ca9
--- /dev/null
+++ b/third_party/boost/boost/visit_each.hpp
@@ -0,0 +1,27 @@
+// Boost.Signals library
+
+// Copyright Douglas Gregor 2001-2003. Use, modification and
+// distribution is subject to the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// For more information, see http://www.boost.org/libs/signals
+
+#ifndef BOOST_VISIT_EACH_HPP
+#define BOOST_VISIT_EACH_HPP
+
+namespace boost {
+ template<typename Visitor, typename T>
+ inline void visit_each(Visitor& visitor, const T& t, long)
+ {
+ visitor(t);
+ }
+
+ template<typename Visitor, typename T>
+ inline void visit_each(Visitor& visitor, const T& t)
+ {
+ visit_each(visitor, t, 0);
+ }
+}
+
+#endif // BOOST_VISIT_EACH_HPP
diff --git a/third_party/boost/boost/weak_ptr.hpp b/third_party/boost/boost/weak_ptr.hpp
new file mode 100644
index 0000000..dd26869
--- /dev/null
+++ b/third_party/boost/boost/weak_ptr.hpp
@@ -0,0 +1,18 @@
+#ifndef BOOST_WEAK_PTR_HPP_INCLUDED
+#define BOOST_WEAK_PTR_HPP_INCLUDED
+
+//
+// weak_ptr.hpp
+//
+// Copyright (c) 2001, 2002, 2003 Peter Dimov
+//
+// Distributed under the Boost Software License, Version 1.0.
+// See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt
+//
+// See http://www.boost.org/libs/smart_ptr/weak_ptr.htm for documentation.
+//
+
+#include <boost/smart_ptr/weak_ptr.hpp>
+
+#endif // #ifndef BOOST_WEAK_PTR_HPP_INCLUDED
diff --git a/third_party/fgetln/LICENSE b/third_party/fgetln/LICENSE
new file mode 100644
index 0000000..5f85958
--- /dev/null
+++ b/third_party/fgetln/LICENSE
@@ -0,0 +1,26 @@
+MIT License
+===========
+
+Copyright (C) 2012 Robert Quattlebaum
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall
+be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/third_party/fgetln/README.google b/third_party/fgetln/README.google
new file mode 100644
index 0000000..c2da529
--- /dev/null
+++ b/third_party/fgetln/README.google
@@ -0,0 +1,12 @@
+URL: https://raw.githubusercontent.com/darconeous/smcp/47e863a8f91458ed01d133dc2a9b913defc56f6b/src/missing/fgetln.h
+Version: 47e863a8f91458ed01d133dc2a9b913defc56f6b
+License: MIT
+License File: LICENSE
+
+Description:
+Provides an implementation of the BSD `fgetln()` call for platforms
+where it is not present (like Linux).
+
+Local Modifications:
+LICENSE file has been created for compliance purposes. Not included
+in original distribution.
diff --git a/third_party/fgetln/fgetln.h b/third_party/fgetln/fgetln.h
new file mode 100644
index 0000000..7048eba
--- /dev/null
+++ b/third_party/fgetln/fgetln.h
@@ -0,0 +1,69 @@
+/* @file fgetln.h
+** @author Robert Quattlebaum <darco@deepdarc.com>
+**
+** Copyright (C) 2012 Robert Quattlebaum
+**
+** Permission is hereby granted, free of charge, to any person
+** obtaining a copy of this software and associated
+** documentation files (the "Software"), to deal in the
+** Software without restriction, including without limitation
+** the rights to use, copy, modify, merge, publish, distribute,
+** sublicense, and/or sell copies of the Software, and to
+** permit persons to whom the Software is furnished to do so,
+** subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall
+** be included in all copies or substantial portions of the
+** Software.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+** KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+** WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+** PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+** OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+** OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+** OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+**
+** -------------------------------------------------------------------
+**
+** This is a simple implementation of the BSD function `fgetln()`,
+** for use on operating systems which do not have a copy.
+**
+** Man page URL: <http://www.openbsd.org/cgi-bin/man.cgi?query=fgetln>
+**
+** NOTE: This implementation is *NOT* thread safe!
+*/
+
+#define _WITH_GETLINE 1
+
+#include <stdio.h>
+
+#if !defined(HAVE_FGETLN)
+#define HAVE_FGETLN \
+ defined(__DARWIN_C_LEVEL) && \
+ (__DARWIN_C_LEVEL >= __DARWIN_C_FULL)
+#endif
+
+#if !defined(fgetln) && !HAVE_FGETLN
+static char *
+fgetln_(
+ FILE *stream, size_t *len
+ )
+{
+ static char* linep = NULL;
+ static size_t linecap = 0;
+ ssize_t length = getline(&linep, &linecap, stream);
+
+ if (length == -1) {
+ free(linep);
+ linep = NULL;
+ linecap = 0;
+ length = 0;
+ }
+ if (len)
+ *len = length;
+ return linep;
+}
+#define fgetln fgetln_
+#endif
diff --git a/third_party/openthread/CONTRIBUTING.md b/third_party/openthread/CONTRIBUTING.md
new file mode 100644
index 0000000..2a78c3b
--- /dev/null
+++ b/third_party/openthread/CONTRIBUTING.md
@@ -0,0 +1,37 @@
+Want to contribute? Great! First, read this page (including the small print at the end).
+
+### Before you contribute
+Before we can use your code, you must sign the
+[Google Individual Contributor License Agreement]
+(https://cla.developers.google.com/about/google-individual)
+(CLA), which you can do online. The CLA is necessary mainly because you own the
+copyright to your changes, even after your contribution becomes part of our
+codebase, so we need your permission to use and distribute your code. We also
+need to be sure of various other things—for instance that you'll tell us if you
+know that your code infringes on other people's patents. You don't have to sign
+the CLA until after you've submitted your code for review and a member has
+approved it, but you must do it before we can put your code into our codebase.
+Before you start working on a larger contribution, you should get in touch with
+us first through the issue tracker with your idea so that we can help out and
+possibly guide you. Coordinating up front makes it much easier to avoid
+frustration later on.
+
+### Code reviews
+All submissions, including submissions by project members, require review. We
+use Github pull requests for this purpose.
+
+### Code style
+Before submitting a pull request make sure to run:
+
+ make pretty
+
+This will format the source code according to the OpenThread code style. This
+command requires the `astyle` tool. Please refer to your operating system
+documentation to find information on how to install `astyle`.
+
+### The small print
+Contributions made by corporations are covered by a different agreement than
+the one above, the
+[Software Grant and Corporate Contributor License Agreement]
+(https://cla.developers.google.com/about/google-corporate).
+
diff --git a/third_party/openthread/LICENSE b/third_party/openthread/LICENSE
new file mode 100644
index 0000000..8417008
--- /dev/null
+++ b/third_party/openthread/LICENSE
@@ -0,0 +1,25 @@
+Copyright (c) 2016, The OpenThread Authors.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of the copyright holder nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/openthread/NOTICE b/third_party/openthread/NOTICE
new file mode 100644
index 0000000..6c1dad8
--- /dev/null
+++ b/third_party/openthread/NOTICE
@@ -0,0 +1,19 @@
+OpenThread is an open source implementation of the Thread 1.0.1 Final Specification.
+The Thread 1.0.1 Final Specification is promulgated by the Thread Group. The Thread
+Group is a non-profit organization formed for the purposes of defining one or
+more specifications, best practices, reference architectures, implementation
+guidelines and certification programs to promote the availability of compliant
+implementations of the Thread protocol. Information on becoming a Member, including
+information about the benefits thereof, can be found at http://threadgroup.org.
+
+OpenThread is not affiliated with or endorsed by the Thread Group. Implementation
+of this OpenThread code does not assure compliance with the Thread 1.0.1 Final
+Specification and does not convey the right to identify any final product as Thread
+certified. Members of the Thread Group may hold patents and other intellectual
+property rights relating to the Thread 1.0.1 Final Specification, ownership and
+licenses of which are subject to the Thread Group’s IP Policies, and not this license.
+
+The included copyright to the OpenThread code is subject to the license in the
+LICENSE file, and all other rights and licenses are expressly reserved.
+No warranty or assurance is made with respect to additional rights that may be
+required to implement this code.
diff --git a/third_party/openthread/README.google b/third_party/openthread/README.google
new file mode 100644
index 0000000..d515d6f
--- /dev/null
+++ b/third_party/openthread/README.google
@@ -0,0 +1,13 @@
+URL: https://github.com/openthread/openthread/tree/b1c19ed091b3faec71d4382a8edbec20b25086d9
+Version: b1c19ed091b3faec71d4382a8edbec20b25086d9
+License: BSD-3
+License File: LICENSE
+
+Description:
+OpenThread is an open-source implementation of the Thread networking
+protocol. With OpenThread, Nest is making the technology used in Nest
+products more broadly available to accelerate the development of
+products for the connected home.
+
+Local Modifications:
+Stripped all unused files.
diff --git a/third_party/openthread/README.md b/third_party/openthread/README.md
new file mode 100644
index 0000000..9052f86
--- /dev/null
+++ b/third_party/openthread/README.md
@@ -0,0 +1,126 @@
+[![OpenThread][ot-logo]][ot-repo]
+[![Build Status][ot-travis-svg]][ot-travis]
+[![Build Status][ot-appveyor-svg]][ot-appveyor]
+[![Coverage Status][ot-codecov-svg]][ot-codecov]
+
+---
+
+OpenThread is an open-source implementation of the [Thread][thread]
+networking protocol. Nest has released OpenThread to make the technology
+used in Nest products more broadly available to developers to accelerate
+the development of products for the connected home.
+
+The Thread specification defines an IPv6-based reliable, secure and
+low-power wireless device-to-device communication protocol for home
+applications. More information about Thread can be found on
+[threadgroup.org](http://threadgroup.org/).
+
+[thread]: http://threadgroup.org/technology/ourtechnology
+[ot-repo]: https://github.com/openthread/openthread
+[ot-logo]: doc/images/openthread_logo.png
+[ot-travis]: https://travis-ci.org/openthread/openthread
+[ot-travis-svg]: https://travis-ci.org/openthread/openthread.svg?branch=master
+[ot-appveyor]: https://ci.appveyor.com/project/jwhui/openthread
+[ot-appveyor-svg]: https://ci.appveyor.com/api/projects/status/r5qwyhn9p26nmfk3?svg=true
+[ot-codecov]: https://codecov.io/gh/openthread/openthread
+[ot-codecov-svg]: https://codecov.io/gh/openthread/openthread/branch/master/graph/badge.svg
+
+## Features ##
+
+ * Highly portable: OS and platform agnostic with a radio
+ abstraction layer
+ * Implements the End Device, Router, Leader and Border Router roles
+ * Small memory footprint
+
+OpenThread implements all Thread networking layers including IPv6,
+6LoWPAN, IEEE 802.15.4 with MAC security, Mesh Link Establishment, and
+Mesh Routing.
+
+
+# Who is supporting OpenThread #
+
+
+
+Nest, along with ARM, Atmel, a subsidiary of Microchip Technology,
+Dialog Semiconductor, Microsoft Corporation, Nordic Semiconductor,
+Qualcomm Technologies, Inc. (a subsidiary of Qualcomm Incorporated),
+and Texas Instruments Incorporated are contributing to the ongoing
+development of OpenThread.
+
+
+# Getting started #
+
+The easiest way to get started is to run the CLI example in
+`/examples/apps/cli`. See the
+[CLI example README](examples/apps/cli/README.md)
+for more details.
+
+
+## What's included ##
+
+In the repo you'll find the following directories and files:
+
+File/Folder | Provides
+--------------|----------------------------------------------------------------
+`doc` | Doxygen docs
+`examples` | Sample applications demonstrating OpenThread
+`include` | Public API header files
+`src` | Core implementation of the Thread standard and related add-ons
+`tests` | Unit and Thread conformance tests
+`third_party` | Third-party code used by OpenThread
+`tools` | Helpful utilities related to the OpenThread project
+
+
+## Documentation ##
+
+The Doxygen reference docs are [hosted online][ot-docs] and generated
+as part of the build.
+
+[ot-docs]: http://openthread.github.io/openthread/
+
+
+# Getting help #
+
+Submit bugs and feature requests to [issue tracker][ot-issues]. Usage
+questions? Post your questions to [Stack Overflow][stackoverflow] using the
+[`openthread` tag][ot-tag]. We also use Google Groups for discussion
+and announcements:
+
+ * [openthread-announce](https://groups.google.com/forum/#!forum/openthread-announce)
+ \- subscribe for release notes and new updates on OpenThread
+ * [openthread-users](https://groups.google.com/forum/#!forum/openthread-users)
+ \- the best place for users to discuss OpenThread and interact with
+ the OpenThread team
+ * [openthread-devel](https://groups.google.com/forum/#!forum/openthread-devel)
+ \- team members discuss the on-going development of OpenThread
+
+[ot-issues]: https://github.com/openthread/openthread/issues
+[stackoverflow]: http://stackoverflow.com/
+[ot-tag]: http://stackoverflow.com/questions/tagged/openthread
+
+
+# Versioning #
+
+OpenThread follows [the Semantic Versioning guidelines][semver] for
+release cycle transparency and to maintain backwards compatibility.
+OpenThread's versioning is independent of the Thread protocol
+specification version but will clearly indicate which version of the
+specification it currently supports.
+
+[semver]: http://semver.org/
+
+
+# Contributing #
+
+See the [`CONTRIBUTING.md`](CONTRIBUTING.md) file for more information.
+
+
+# License #
+
+OpenThread is released under the [BSD 3-Clause license](LICENSE). See
+the [`LICENSE`](LICENSE) file for more information.
+
+Please only use the OpenThread name and marks when accurately
+referencing this software distribution. Do not use the marks in
+a way that suggests you are endorsed by or otherwise affiliated with
+Nest, Google, or The Thread Group.
diff --git a/third_party/openthread/src/ncp/PROTOCOL.md b/third_party/openthread/src/ncp/PROTOCOL.md
new file mode 100644
index 0000000..f5aff68
--- /dev/null
+++ b/third_party/openthread/src/ncp/PROTOCOL.md
@@ -0,0 +1,7 @@
+Spinel NCP Protocol Documentation
+=================================
+
+This document has moved into the top level `doc` folder and renamed
+[`draft-spinel-protocol.txt`](../../doc/draft-spinel-protocol.txt)
+and [`draft-spinel-protocol.html`](../../doc/draft-spinel-protocol.html).
+
diff --git a/third_party/openthread/src/ncp/spinel.c b/third_party/openthread/src/ncp/spinel.c
new file mode 100644
index 0000000..0c1cb85
--- /dev/null
+++ b/third_party/openthread/src/ncp/spinel.c
@@ -0,0 +1,1576 @@
+/*
+ * Copyright (c) 2016, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * -------------------------------------------------------------------
+ *
+ * ## Unit Test ##
+ *
+ * This file includes its own unit test. To compile the unit test,
+ * simply compile this file with the macro SPINEL_SELF_TEST set to 1.
+ * For example:
+ *
+ * cc spinel.c -Wall -DSPINEL_SELF_TEST=1 -o spinel
+ *
+ * -------------------------------------------------------------------
+ */
+
+// ----------------------------------------------------------------------------
+// MARK: -
+// MARK: Headers
+
+#include "spinel.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+// ----------------------------------------------------------------------------
+// MARK: -
+
+// IAR's errno.h apparently doesn't define EOVERFLOW.
+#ifndef EOVERFLOW
+// There is no real good choice for what to set
+// errno to in this case, so we just pick the
+// value '1' somewhat arbitrarily.
+#define EOVERFLOW 1
+#endif
+
+// IAR's errno.h apparently doesn't define EINVAL.
+#ifndef EINVAL
+// There is no real good choice for what to set
+// errno to in this case, so we just pick the
+// value '1' somewhat arbitrarily.
+#define EINVAL 1
+#endif
+
+#ifdef _KERNEL_MODE
+#define va_copy(destination, source) ((destination) = (source))
+#undef errno
+#define assert_printf(fmt, ...)
+#endif
+
+#if defined(errno) && SPINEL_PLATFORM_DOESNT_IMPLEMENT_ERRNO_VAR
+#error "SPINEL_PLATFORM_DOESNT_IMPLEMENT_ERRNO_VAR is set but errno is already defined."
+#endif
+
+// Work-around for platforms that don't implement the `errno` variable.
+#if !defined(errno) && SPINEL_PLATFORM_DOESNT_IMPLEMENT_ERRNO_VAR
+static int spinel_errno_workaround_;
+#define errno spinel_errno_workaround_
+#endif // SPINEL_PLATFORM_DOESNT_IMPLEMENT_ERRNO_VAR
+
+#ifndef assert_printf
+#if SPINEL_PLATFORM_DOESNT_IMPLEMENT_FPRINTF
+#define assert_printf(fmt, ...) \
+ printf(__FILE__ ":%d: " fmt "\n", __LINE__, __VA_ARGS__)
+#else // if SPINEL_PLATFORM_DOESNT_IMPLEMENT_FPRINTF
+#define assert_printf(fmt, ...) \
+ fprintf(stderr, __FILE__ ":%d: " fmt "\n", __LINE__, __VA_ARGS__)
+#endif // else SPINEL_PLATFORM_DOESNT_IMPLEMENT_FPRINTF
+#endif
+
+#if !HAVE_STRNLEN
+// Provide a working strnlen if the platform doesn't have one.
+static size_t spinel_strnlen_(const char *s, size_t maxlen)
+{
+ size_t ret;
+ for (ret = 0; (ret < maxlen) && (s[ret] != 0); ret++)
+ {
+ // Empty loop.
+ }
+ return ret;
+}
+#define strnlen spinel_strnlen_
+#endif
+
+#ifndef require_action
+#if SPINEL_PLATFORM_SHOULD_LOG_ASSERTS
+#define require_action(c, l, a) \
+ do { if (!(c)) { \
+ assert_printf("Requirement Failed (%s)", # c); \
+ a; \
+ goto l; \
+ } } while (0)
+#else // if DEBUG
+#define require_action(c, l, a) \
+ do { if (!(c)) { \
+ a; \
+ goto l; \
+ } } while (0)
+#endif // else DEBUG
+#endif // ifndef require_action
+
+#ifndef require
+#define require(c, l) require_action(c, l, {})
+#endif
+
+
+typedef struct {
+ va_list obj;
+} va_list_obj;
+
+// ----------------------------------------------------------------------------
+// MARK: -
+
+spinel_ssize_t
+spinel_packed_uint_decode(const uint8_t *bytes, spinel_size_t len, unsigned int *value_ptr)
+{
+ spinel_ssize_t ret = 0;
+ unsigned int value = 0;
+
+ int i = 0;
+
+ do
+ {
+ if (len < sizeof(uint8_t))
+ {
+ ret = -1;
+ break;
+ }
+
+ value |= (unsigned int)((bytes[0] & 0x7F) << i);
+ i += 7;
+ ret += sizeof(uint8_t);
+ bytes += sizeof(uint8_t);
+ len -= sizeof(uint8_t);
+ }
+ while ((bytes[-1] & 0x80) == 0x80);
+
+ if ((ret > 0) && (value_ptr != NULL))
+ {
+ *value_ptr = value;
+ }
+
+ return ret;
+}
+
+spinel_ssize_t
+spinel_packed_uint_size(unsigned int value)
+{
+ spinel_ssize_t ret;
+
+ if (value < (1 << 7))
+ {
+ ret = 1;
+ }
+ else if (value < (1 << 14))
+ {
+ ret = 2;
+ }
+ else if (value < (1 << 21))
+ {
+ ret = 3;
+ }
+ else if (value < (1 << 28))
+ {
+ ret = 4;
+ }
+ else
+ {
+ ret = 5;
+ }
+
+ return ret;
+}
+
+spinel_ssize_t
+spinel_packed_uint_encode(uint8_t *bytes, spinel_size_t len, unsigned int value)
+{
+ const spinel_ssize_t encoded_size = spinel_packed_uint_size(value);
+
+ if ((spinel_ssize_t)len >= encoded_size)
+ {
+ spinel_ssize_t i;
+
+ for (i = 0; i != encoded_size - 1; ++i)
+ {
+ *bytes++ = (value & 0x7F) | 0x80;
+ value = (value >> 7);
+ }
+
+ *bytes++ = (value & 0x7F);
+ }
+
+ return encoded_size;
+}
+
+const char *
+spinel_next_packed_datatype(const char *pack_format)
+{
+ int depth = 0;
+
+ do
+ {
+ switch (*++pack_format)
+ {
+ case '(':
+ depth++;
+ break;
+
+ case ')':
+ depth--;
+
+ if (depth == 0)
+ {
+ pack_format++;
+ }
+
+ break;
+ }
+ }
+ while ((depth > 0) && *pack_format != 0);
+
+ return pack_format;
+}
+
+static spinel_ssize_t
+spinel_datatype_vunpack_(const uint8_t *data_ptr, spinel_size_t data_len, const char *pack_format, va_list_obj *args)
+{
+ spinel_ssize_t ret = 0;
+
+ for (; *pack_format != 0; pack_format = spinel_next_packed_datatype(pack_format))
+ {
+ if (*pack_format == ')')
+ {
+ // Don't go past the end of a struct.
+ break;
+ }
+
+ switch ((spinel_datatype_t)pack_format[0])
+ {
+ case SPINEL_DATATYPE_BOOL_C:
+ {
+ bool *arg_ptr = va_arg(args->obj, bool *);
+ require_action(data_len >= sizeof(uint8_t), bail, (ret = -1, errno = EOVERFLOW));
+
+ if (arg_ptr)
+ {
+ *arg_ptr = data_ptr[0];
+ }
+
+ ret += sizeof(uint8_t);
+ data_ptr += sizeof(uint8_t);
+ data_len -= sizeof(uint8_t);
+ break;
+ }
+
+ case SPINEL_DATATYPE_INT8_C:
+ case SPINEL_DATATYPE_UINT8_C:
+ {
+ uint8_t *arg_ptr = va_arg(args->obj, uint8_t *);
+ require_action(data_len >= sizeof(uint8_t), bail, (ret = -1, errno = EOVERFLOW));
+
+ if (arg_ptr)
+ {
+ *arg_ptr = data_ptr[0];
+ }
+
+ ret += sizeof(uint8_t);
+ data_ptr += sizeof(uint8_t);
+ data_len -= sizeof(uint8_t);
+ break;
+ }
+
+ case SPINEL_DATATYPE_INT16_C:
+ case SPINEL_DATATYPE_UINT16_C:
+ {
+ uint16_t *arg_ptr = va_arg(args->obj, uint16_t *);
+ require_action(data_len >= sizeof(uint16_t), bail, (ret = -1, errno = EOVERFLOW));
+
+ if (arg_ptr)
+ {
+ *arg_ptr = (uint16_t)((data_ptr[1] << 8) | data_ptr[0]);
+ }
+
+ ret += sizeof(uint16_t);
+ data_ptr += sizeof(uint16_t);
+ data_len -= sizeof(uint16_t);
+ break;
+ }
+
+ case SPINEL_DATATYPE_INT32_C:
+ case SPINEL_DATATYPE_UINT32_C:
+ {
+ uint32_t *arg_ptr = va_arg(args->obj, uint32_t *);
+ require_action(data_len >= sizeof(uint32_t), bail, (ret = -1, errno = EOVERFLOW));
+
+ if (arg_ptr)
+ {
+ *arg_ptr = (uint32_t)((data_ptr[3] << 24) | (data_ptr[2] << 16) | (data_ptr[1] << 8) | data_ptr[0]);
+ }
+
+ ret += sizeof(uint32_t);
+ data_ptr += sizeof(uint32_t);
+ data_len -= sizeof(uint32_t);
+ break;
+ }
+
+ case SPINEL_DATATYPE_IPv6ADDR_C:
+ {
+ spinel_ipv6addr_t **arg_ptr = va_arg(args->obj, spinel_ipv6addr_t **);
+ require_action(data_len >= sizeof(spinel_ipv6addr_t), bail, (ret = -1, errno = EOVERFLOW));
+
+ if (arg_ptr)
+ {
+ *arg_ptr = (spinel_ipv6addr_t *)data_ptr;
+ }
+
+ ret += sizeof(spinel_ipv6addr_t);
+ data_ptr += sizeof(spinel_ipv6addr_t);
+ data_len -= sizeof(spinel_ipv6addr_t);
+ break;
+ }
+
+ case SPINEL_DATATYPE_EUI64_C:
+ {
+ spinel_eui64_t **arg_ptr = va_arg(args->obj, spinel_eui64_t **);
+ require_action(data_len >= sizeof(spinel_eui64_t), bail, (ret = -1, errno = EOVERFLOW));
+
+ if (arg_ptr)
+ {
+ *arg_ptr = (spinel_eui64_t *)data_ptr;
+ }
+
+ ret += sizeof(spinel_eui64_t);
+ data_ptr += sizeof(spinel_eui64_t);
+ data_len -= sizeof(spinel_eui64_t);
+ break;
+ }
+
+ case SPINEL_DATATYPE_EUI48_C:
+ {
+ spinel_eui48_t **arg_ptr = va_arg(args->obj, spinel_eui48_t **);
+ require_action(data_len >= sizeof(spinel_eui48_t), bail, (ret = -1, errno = EOVERFLOW));
+
+ if (arg_ptr)
+ {
+ *arg_ptr = (spinel_eui48_t *)data_ptr;
+ }
+
+ ret += sizeof(spinel_eui48_t);
+ data_ptr += sizeof(spinel_eui48_t);
+ data_len -= sizeof(spinel_eui48_t);
+ break;
+ }
+
+ case SPINEL_DATATYPE_UINT_PACKED_C:
+ {
+ unsigned int *arg_ptr = va_arg(args->obj, unsigned int *);
+ spinel_ssize_t pui_len = spinel_packed_uint_decode(data_ptr, data_len, arg_ptr);
+
+ require(pui_len > 0, bail);
+
+ require(pui_len <= (spinel_ssize_t)data_len, bail);
+
+ ret += pui_len;
+ data_ptr += pui_len;
+ data_len -= (spinel_size_t)pui_len;
+ break;
+ }
+
+ case SPINEL_DATATYPE_UTF8_C:
+ {
+ const char **arg_ptr = va_arg(args->obj, const char **);
+ size_t len = strnlen((const char *)data_ptr, data_len) + 1;
+
+ require_action((len <= data_len) || (data_ptr[data_len - 1] != 0), bail, (ret = -1, errno = EOVERFLOW));
+
+ if (arg_ptr)
+ {
+ *arg_ptr = (const char *)data_ptr;
+ }
+
+ ret += (spinel_size_t)len;
+ data_ptr += len;
+ data_len -= (spinel_size_t)len;
+ break;
+ }
+
+ case SPINEL_DATATYPE_DATA_C:
+ {
+ spinel_ssize_t pui_len = 0;
+ uint16_t block_len = 0;
+ const uint8_t *block_ptr = data_ptr;
+ const uint8_t **block_ptr_ptr = va_arg(args->obj, const uint8_t **);
+ unsigned int *block_len_ptr = va_arg(args->obj, unsigned int *);
+ char nextformat = *spinel_next_packed_datatype(pack_format);
+
+ if ((nextformat != 0) && (nextformat != ')'))
+ {
+ pui_len = spinel_datatype_unpack(data_ptr, data_len, SPINEL_DATATYPE_UINT16_S, &block_len);
+ //pui_len = spinel_packed_uint_decode(data_ptr, data_len, &block_len);
+ block_ptr += pui_len;
+
+ require(pui_len > 0, bail);
+ require(block_len < SPINEL_FRAME_MAX_SIZE, bail);
+ }
+ else
+ {
+ block_len = (uint16_t)data_len;
+ pui_len = 0;
+ }
+
+ require_action((spinel_ssize_t)data_len >= (block_len + pui_len), bail, (ret = -1, errno = EOVERFLOW));
+
+ if (NULL != block_ptr_ptr)
+ {
+ *block_ptr_ptr = block_ptr;
+ }
+
+ if (NULL != block_len_ptr)
+ {
+ *block_len_ptr = block_len;
+ }
+
+ block_len += (uint16_t)pui_len;
+ ret += block_len;
+ data_ptr += block_len;
+ data_len -= block_len;
+ break;
+ }
+
+ case SPINEL_DATATYPE_STRUCT_C:
+ {
+ spinel_ssize_t pui_len = 0;
+ uint16_t block_len = 0;
+ spinel_ssize_t actual_len = 0;
+ const uint8_t *block_ptr = data_ptr;
+ char nextformat = *spinel_next_packed_datatype(pack_format);
+
+ if ((nextformat != 0) && (nextformat != ')'))
+ {
+ pui_len = spinel_datatype_unpack(data_ptr, data_len, SPINEL_DATATYPE_UINT16_S, &block_len);
+ block_ptr += pui_len;
+
+ require(pui_len > 0, bail);
+ require(block_len < SPINEL_FRAME_MAX_SIZE, bail);
+ }
+ else
+ {
+ block_len = (uint16_t)data_len;
+ pui_len = 0;
+ }
+
+ require_action((spinel_ssize_t)data_len >= (block_len + pui_len), bail, (ret = -1, errno = EOVERFLOW));
+
+ actual_len = spinel_datatype_vunpack_(block_ptr, block_len, pack_format + 2, args);
+
+ require_action(actual_len > -1, bail, (ret = -1, errno = EOVERFLOW));
+
+ if (pui_len)
+ {
+ block_len += (uint16_t)pui_len;
+ }
+ else
+ {
+ block_len = (uint16_t)actual_len;
+ }
+
+ ret += block_len;
+ data_ptr += block_len;
+ data_len -= block_len;
+ break;
+ }
+
+ case '.':
+ // Skip.
+ break;
+
+ case SPINEL_DATATYPE_ARRAY_C:
+ default:
+ // Unsupported Type!
+ ret = -1;
+ errno = EINVAL;
+ goto bail;
+ }
+ }
+
+ return ret;
+
+bail:
+ return ret;
+}
+
+spinel_ssize_t
+spinel_datatype_unpack(const uint8_t *data_ptr, spinel_size_t data_len, const char *pack_format, ...)
+{
+ spinel_ssize_t ret;
+ va_list_obj args;
+ va_start(args.obj, pack_format);
+
+ ret = spinel_datatype_vunpack_(data_ptr, data_len, pack_format, &args);
+
+ va_end(args.obj);
+ return ret;
+}
+
+
+spinel_ssize_t
+spinel_datatype_vunpack(const uint8_t *data_ptr, spinel_size_t data_len, const char *pack_format, va_list args)
+{
+ spinel_ssize_t ret;
+ va_list_obj args_obj;
+ va_copy(args_obj.obj, args);
+
+ ret = spinel_datatype_vunpack_(data_ptr, data_len, pack_format, &args_obj);
+
+ va_end(args_obj.obj);
+ return ret;
+}
+
+static spinel_ssize_t
+spinel_datatype_vpack_(uint8_t *data_ptr, spinel_size_t data_len_max, const char *pack_format, va_list_obj *args)
+{
+ spinel_ssize_t ret = 0;
+
+ for (; *pack_format != 0; pack_format = spinel_next_packed_datatype(pack_format))
+ {
+ if (*pack_format == ')')
+ {
+ // Don't go past the end of a struct.
+ break;
+ }
+
+ switch ((spinel_datatype_t)*pack_format)
+ {
+ case SPINEL_DATATYPE_BOOL_C:
+ {
+ bool arg = (bool)va_arg(args->obj, int);
+ ret += sizeof(uint8_t);
+
+ if (data_len_max >= sizeof(uint8_t))
+ {
+ data_ptr[0] = (arg != false);
+ data_ptr += sizeof(uint8_t);
+ data_len_max -= sizeof(uint8_t);
+ }
+ else
+ {
+ data_len_max = 0;
+ }
+
+ break;
+ }
+
+ case SPINEL_DATATYPE_INT8_C:
+ case SPINEL_DATATYPE_UINT8_C:
+ {
+ uint8_t arg = (uint8_t)va_arg(args->obj, int);
+ ret += sizeof(uint8_t);
+
+ if (data_len_max >= sizeof(uint8_t))
+ {
+ data_ptr[0] = arg;
+ data_ptr += sizeof(uint8_t);
+ data_len_max -= sizeof(uint8_t);
+ }
+ else
+ {
+ data_len_max = 0;
+ }
+
+ break;
+ }
+
+ case SPINEL_DATATYPE_INT16_C:
+ case SPINEL_DATATYPE_UINT16_C:
+ {
+ uint16_t arg = (uint16_t)va_arg(args->obj, int);
+ ret += sizeof(uint16_t);
+
+ if (data_len_max >= sizeof(uint16_t))
+ {
+ data_ptr[1] = (arg >> 8) & 0xff;
+ data_ptr[0] = (arg >> 0) & 0xff;
+ data_ptr += sizeof(uint16_t);
+ data_len_max -= sizeof(uint16_t);
+ }
+ else
+ {
+ data_len_max = 0;
+ }
+
+ break;
+ }
+
+ case SPINEL_DATATYPE_INT32_C:
+ case SPINEL_DATATYPE_UINT32_C:
+ {
+ uint32_t arg = (uint32_t)va_arg(args->obj, int);
+ ret += sizeof(uint32_t);
+
+ if (data_len_max >= sizeof(uint32_t))
+ {
+ data_ptr[3] = (arg >> 24) & 0xff;
+ data_ptr[2] = (arg >> 16) & 0xff;
+ data_ptr[1] = (arg >> 8) & 0xff;
+ data_ptr[0] = (arg >> 0) & 0xff;
+ data_ptr += sizeof(uint32_t);
+ data_len_max -= sizeof(uint32_t);
+ }
+ else
+ {
+ data_len_max = 0;
+ }
+
+ break;
+ }
+
+ case SPINEL_DATATYPE_IPv6ADDR_C:
+ {
+ spinel_ipv6addr_t *arg = va_arg(args->obj, spinel_ipv6addr_t *);
+ ret += sizeof(spinel_ipv6addr_t);
+
+ if (data_len_max >= sizeof(spinel_ipv6addr_t))
+ {
+ *(spinel_ipv6addr_t *)data_ptr = *arg;
+ data_ptr += sizeof(spinel_ipv6addr_t);
+ data_len_max -= sizeof(spinel_ipv6addr_t);
+ }
+ else
+ {
+ data_len_max = 0;
+ }
+
+ break;
+ }
+
+ case SPINEL_DATATYPE_EUI48_C:
+ {
+ spinel_eui48_t *arg = va_arg(args->obj, spinel_eui48_t *);
+ ret += sizeof(spinel_eui48_t);
+
+ if (data_len_max >= sizeof(spinel_eui48_t))
+ {
+ *(spinel_eui48_t *)data_ptr = *arg;
+ data_ptr += sizeof(spinel_eui48_t);
+ data_len_max -= sizeof(spinel_eui48_t);
+ }
+ else
+ {
+ data_len_max = 0;
+ }
+
+ break;
+ }
+
+ case SPINEL_DATATYPE_EUI64_C:
+ {
+ spinel_eui64_t *arg = va_arg(args->obj, spinel_eui64_t *);
+ ret += sizeof(spinel_eui64_t);
+
+ if (data_len_max >= sizeof(spinel_eui64_t))
+ {
+ *(spinel_eui64_t *)data_ptr = *arg;
+ data_ptr += sizeof(spinel_eui64_t);
+ data_len_max -= sizeof(spinel_eui64_t);
+ }
+ else
+ {
+ data_len_max = 0;
+ }
+
+ break;
+ }
+
+ case SPINEL_DATATYPE_UINT_PACKED_C:
+ {
+ uint32_t arg = va_arg(args->obj, uint32_t);
+ spinel_ssize_t encoded_size = spinel_packed_uint_encode(data_ptr, data_len_max, arg);
+ ret += encoded_size;
+
+ if ((spinel_ssize_t)data_len_max >= encoded_size)
+ {
+ data_ptr += encoded_size;
+ data_len_max -= (spinel_size_t)encoded_size;
+ }
+ else
+ {
+ data_len_max = 0;
+ }
+
+ break;
+ }
+
+ case SPINEL_DATATYPE_UTF8_C:
+ {
+ const char *string_arg = va_arg(args->obj, const char *);
+ size_t string_arg_len = 0;
+
+ if (string_arg)
+ {
+ string_arg_len = strlen(string_arg) + 1;
+ }
+ else
+ {
+ string_arg = "";
+ string_arg_len = 1;
+ }
+
+ ret += (spinel_size_t)string_arg_len;
+
+ if (data_len_max >= string_arg_len)
+ {
+ memcpy(data_ptr, string_arg, string_arg_len);
+
+ data_ptr += string_arg_len;
+ data_len_max -= (spinel_size_t)string_arg_len;
+ }
+ else
+ {
+ data_len_max = 0;
+ }
+
+ break;
+ }
+
+ case SPINEL_DATATYPE_DATA_C:
+ {
+ const uint8_t *arg = va_arg(args->obj, const uint8_t *);
+ uint32_t data_size_arg = va_arg(args->obj, uint32_t);
+ spinel_ssize_t size_len = 0;
+ char nextformat = *spinel_next_packed_datatype(pack_format);
+
+ if (nextformat != 0 && nextformat != ')')
+ {
+ size_len = spinel_datatype_pack(data_ptr, data_len_max, SPINEL_DATATYPE_UINT16_S, data_size_arg);
+ require_action(size_len > 0, bail, {ret = -1; errno = EINVAL;});
+ }
+
+ ret += (spinel_size_t)size_len + data_size_arg;
+
+ if (data_len_max >= (spinel_size_t)size_len + data_size_arg)
+ {
+ data_ptr += size_len;
+ data_len_max -= (spinel_size_t)size_len;
+
+ memcpy(data_ptr, arg, data_size_arg);
+
+ data_ptr += data_size_arg;
+ data_len_max -= data_size_arg;
+ }
+ else
+ {
+ data_len_max = 0;
+ }
+
+ break;
+ }
+
+ case SPINEL_DATATYPE_STRUCT_C:
+ {
+ spinel_ssize_t struct_len = 0;
+ spinel_ssize_t size_len = 0;
+ char nextformat = *spinel_next_packed_datatype(pack_format);
+
+ require_action(pack_format[1] == '(', bail, {ret = -1; errno = EINVAL;});
+
+ // First we figure out the size of the struct
+ {
+ va_list_obj subargs;
+ va_copy(subargs.obj, args->obj);
+ struct_len = spinel_datatype_vpack_(NULL, 0, pack_format + 2, &subargs);
+ va_end(subargs.obj);
+ }
+
+ if (nextformat != 0 && nextformat != ')')
+ {
+ size_len = spinel_datatype_pack(data_ptr, data_len_max, SPINEL_DATATYPE_UINT16_S, struct_len);
+ require_action(size_len > 0, bail, {ret = -1; errno = EINVAL;});
+ }
+
+ ret += size_len + struct_len;
+
+ if (struct_len + size_len <= (spinel_ssize_t)data_len_max)
+ {
+ data_ptr += size_len;
+ data_len_max -= (spinel_size_t)size_len;
+
+ struct_len = spinel_datatype_vpack_(data_ptr, data_len_max, pack_format + 2, args);
+
+ data_ptr += struct_len;
+ data_len_max -= (spinel_size_t)struct_len;
+ }
+ else
+ {
+ data_len_max = 0;
+ }
+
+ break;
+ }
+
+ case '.':
+ // Skip.
+ break;
+
+ default:
+ // Unsupported Type!
+ ret = -1;
+ errno = EINVAL;
+ goto bail;
+
+ }
+ }
+
+bail:
+ return ret;
+}
+
+spinel_ssize_t
+spinel_datatype_pack(uint8_t *data_ptr, spinel_size_t data_len_max, const char *pack_format, ...)
+{
+ int ret;
+ va_list_obj args;
+ va_start(args.obj, pack_format);
+
+ ret = spinel_datatype_vpack_(data_ptr, data_len_max, pack_format, &args);
+
+ va_end(args.obj);
+ return ret;
+}
+
+
+spinel_ssize_t
+spinel_datatype_vpack(uint8_t *data_ptr, spinel_size_t data_len_max, const char *pack_format, va_list args)
+{
+ int ret;
+ va_list_obj args_obj;
+ va_copy(args_obj.obj, args);
+
+ ret = spinel_datatype_vpack_(data_ptr, data_len_max, pack_format, &args_obj);
+
+ va_end(args_obj.obj);
+ return ret;
+}
+
+
+// ----------------------------------------------------------------------------
+// MARK: -
+
+// **** LCOV_EXCL_START ****
+
+const char *
+spinel_prop_key_to_cstr(spinel_prop_key_t prop_key)
+{
+ const char *ret = "UNKNOWN";
+
+ switch (prop_key)
+ {
+ case SPINEL_PROP_LAST_STATUS:
+ ret = "PROP_LAST_STATUS";
+ break;
+
+ case SPINEL_PROP_PROTOCOL_VERSION:
+ ret = "PROP_PROTOCOL_VERSION";
+ break;
+
+ case SPINEL_PROP_INTERFACE_TYPE:
+ ret = "PROP_INTERFACE_TYPE";
+ break;
+
+ case SPINEL_PROP_VENDOR_ID:
+ ret = "PROP_VENDOR_ID";
+ break;
+
+ case SPINEL_PROP_CAPS:
+ ret = "PROP_CAPS";
+ break;
+
+ case SPINEL_PROP_NCP_VERSION:
+ ret = "PROP_NCP_VERSION";
+ break;
+
+ case SPINEL_PROP_INTERFACE_COUNT:
+ ret = "PROP_INTERFACE_COUNT";
+ break;
+
+ case SPINEL_PROP_POWER_STATE:
+ ret = "PROP_POWER_STATE";
+ break;
+
+ case SPINEL_PROP_HWADDR:
+ ret = "PROP_HWADDR";
+ break;
+
+ case SPINEL_PROP_LOCK:
+ ret = "PROP_LOCK";
+ break;
+
+ case SPINEL_PROP_HBO_MEM_MAX:
+ ret = "PROP_HBO_MEM_MAX";
+ break;
+
+ case SPINEL_PROP_HBO_BLOCK_MAX:
+ ret = "PROP_HBO_BLOCK_MAX";
+ break;
+
+ case SPINEL_PROP_STREAM_DEBUG:
+ ret = "PROP_STREAM_DEBUG";
+ break;
+
+ case SPINEL_PROP_STREAM_RAW:
+ ret = "PROP_STREAM_RAW";
+ break;
+
+ case SPINEL_PROP_STREAM_NET:
+ ret = "PROP_STREAM_NET";
+ break;
+
+ case SPINEL_PROP_STREAM_NET_INSECURE:
+ ret = "PROP_STREAM_NET_INSECURE";
+ break;
+
+ case SPINEL_PROP_PHY_ENABLED:
+ ret = "PROP_PHY_ENABLED";
+ break;
+
+ case SPINEL_PROP_PHY_CHAN:
+ ret = "PROP_PHY_CHAN";
+ break;
+
+ case SPINEL_PROP_PHY_CHAN_SUPPORTED:
+ ret = "PROP_PHY_CHAN_SUPPORTED";
+ break;
+
+ case SPINEL_PROP_PHY_FREQ:
+ ret = "PROP_PHY_FREQ";
+ break;
+
+ case SPINEL_PROP_PHY_CCA_THRESHOLD:
+ ret = "PROP_PHY_CCA_THRESHOLD";
+ break;
+
+ case SPINEL_PROP_PHY_TX_POWER:
+ ret = "PROP_PHY_TX_POWER";
+ break;
+
+ case SPINEL_PROP_PHY_RSSI:
+ ret = "PROP_PHY_RSSI";
+ break;
+
+ case SPINEL_PROP_MAC_RAW_STREAM_ENABLED:
+ ret = "PROP_MAC_RAW_STREAM_ENABLED";
+ break;
+
+ case SPINEL_PROP_MAC_PROMISCUOUS_MODE:
+ ret = "PROP_MAC_PROMISCUOUS_MODE";
+ break;
+
+ case SPINEL_PROP_MAC_SCAN_STATE:
+ ret = "PROP_MAC_SCAN_STATE";
+ break;
+
+ case SPINEL_PROP_MAC_SCAN_MASK:
+ ret = "PROP_MAC_SCAN_MASK";
+ break;
+
+ case SPINEL_PROP_MAC_SCAN_BEACON:
+ ret = "PROP_MAC_SCAN_BEACON";
+ break;
+
+ case SPINEL_PROP_MAC_ENERGY_SCAN_RESULT:
+ ret = "PROP_MAC_SCAN_ENERGY_SCAN_RESULT";
+ break;
+
+ case SPINEL_PROP_MAC_SCAN_PERIOD:
+ ret = "PROP_MAC_SCAN_PERIOD";
+ break;
+
+ case SPINEL_PROP_MAC_15_4_LADDR:
+ ret = "PROP_MAC_15_4_LADDR";
+ break;
+
+ case SPINEL_PROP_MAC_15_4_SADDR:
+ ret = "PROP_MAC_15_4_SADDR";
+ break;
+
+ case SPINEL_PROP_MAC_15_4_PANID:
+ ret = "PROP_MAC_15_4_PANID";
+ break;
+
+ case SPINEL_PROP_NET_SAVED:
+ ret = "PROP_NET_SAVED";
+ break;
+
+ case SPINEL_PROP_NET_IF_UP:
+ ret = "PROP_NET_IF_UP";
+ break;
+
+ case SPINEL_PROP_NET_STACK_UP:
+ ret = "PROP_NET_STACK_UP";
+ break;
+
+ case SPINEL_PROP_NET_ROLE:
+ ret = "PROP_NET_ROLE";
+ break;
+
+ case SPINEL_PROP_NET_NETWORK_NAME:
+ ret = "PROP_NET_NETWORK_NAME";
+ break;
+
+ case SPINEL_PROP_NET_XPANID:
+ ret = "PROP_NET_XPANID";
+ break;
+
+ case SPINEL_PROP_NET_MASTER_KEY:
+ ret = "PROP_NET_MASTER_KEY";
+ break;
+
+ case SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER:
+ ret = "PROP_NET_KEY_SEQUENCE_COUNTER";
+ break;
+
+ case SPINEL_PROP_NET_PARTITION_ID:
+ ret = "PROP_NET_PARTITION_ID";
+ break;
+
+ case SPINEL_PROP_NET_KEY_SWITCH_GUARDTIME:
+ ret = "PROP_NET_KEY_SWITCH_GUARDTIME";
+ break;
+
+ case SPINEL_PROP_THREAD_LEADER_ADDR:
+ ret = "PROP_THREAD_LEADER_ADDR";
+ break;
+
+ case SPINEL_PROP_THREAD_LEADER_RID:
+ ret = "PROP_THREAD_LEADER_RID";
+ break;
+
+ case SPINEL_PROP_THREAD_LEADER_WEIGHT:
+ ret = "PROP_THREAD_LEADER_WEIGHT";
+ break;
+
+ case SPINEL_PROP_THREAD_LOCAL_LEADER_WEIGHT:
+ ret = "PROP_THREAD_LOCAL_LEADER_WEIGHT";
+ break;
+
+ case SPINEL_PROP_THREAD_NETWORK_DATA_VERSION:
+ ret = "PROP_THREAD_NETWORK_DATA_VERSION";
+ break;
+
+ case SPINEL_PROP_THREAD_STABLE_NETWORK_DATA_VERSION:
+ ret = "PROP_THREAD_STABLE_NETWORK_DATA_VERSION";
+ break;
+
+ case SPINEL_PROP_THREAD_NETWORK_DATA:
+ ret = "PROP_THREAD_NETWORK_DATA";
+ break;
+
+ case SPINEL_PROP_THREAD_CHILD_TABLE:
+ ret = "PROP_THREAD_CHILD_TABLE";
+ break;
+
+ case SPINEL_PROP_IPV6_LL_ADDR:
+ ret = "PROP_IPV6_LL_ADDR";
+ break;
+
+ case SPINEL_PROP_IPV6_ML_ADDR:
+ ret = "PROP_IPV6_ML_ADDR";
+ break;
+
+ case SPINEL_PROP_IPV6_ML_PREFIX:
+ ret = "PROP_IPV6_ML_PREFIX";
+ break;
+
+ case SPINEL_PROP_IPV6_ADDRESS_TABLE:
+ ret = "PROP_IPV6_ADDRESS_TABLE";
+ break;
+
+ case SPINEL_PROP_IPV6_ROUTE_TABLE:
+ ret = "PROP_IPV6_ROUTE_TABLE";
+ break;
+
+ case SPINEL_PROP_IPV6_ICMP_PING_OFFLOAD:
+ ret = "SPINEL_PROP_IPV6_ICMP_PING_OFFLOAD";
+ break;
+
+ case SPINEL_PROP_THREAD_PARENT:
+ ret = "SPINEL_PROP_THREAD_PARENT";
+ break;
+
+ case SPINEL_PROP_THREAD_STABLE_NETWORK_DATA:
+ ret = "SPINEL_PROP_THREAD_STABLE_NETWORK_DATA";
+ break;
+
+ case SPINEL_PROP_THREAD_LEADER_NETWORK_DATA:
+ ret = "SPINEL_PROP_THREAD_LEADER_NETWORK_DATA";
+ break;
+
+ case SPINEL_PROP_THREAD_STABLE_LEADER_NETWORK_DATA:
+ ret = "SPINEL_PROP_THREAD_STABLE_LEADER_NETWORK_DATA";
+ break;
+
+ case SPINEL_PROP_THREAD_ON_MESH_NETS:
+ ret = "SPINEL_PROP_THREAD_ON_MESH_NETS";
+ break;
+
+ case SPINEL_PROP_THREAD_LOCAL_ROUTES:
+ ret = "PROP_THREAD_LOCAL_ROUTES";
+ break;
+
+ case SPINEL_PROP_THREAD_ASSISTING_PORTS:
+ ret = "PROP_THREAD_ASSISTING_PORTS";
+ break;
+
+ case SPINEL_PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE:
+ ret = "SPINEL_PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE";
+ break;
+
+ case SPINEL_PROP_THREAD_RLOC16_DEBUG_PASSTHRU:
+ ret = "SPINEL_PROP_THREAD_RLOC16_DEBUG_PASSTHRU";
+ break;
+
+ case SPINEL_PROP_THREAD_ROUTER_ROLE_ENABLED:
+ ret = "SPINEL_PROP_THREAD_ROUTER_ROLE_ENABLED";
+ break;
+
+ case SPINEL_PROP_THREAD_ROUTER_UPGRADE_THRESHOLD:
+ ret = "PROP_THREAD_ROUTER_UPGRADE_THRESHOLD";
+ break;
+
+ case SPINEL_PROP_THREAD_CONTEXT_REUSE_DELAY:
+ ret = "PROP_THREAD_CONTEXT_REUSE_DELAY";
+ break;
+
+ case SPINEL_PROP_MAC_WHITELIST:
+ ret = "PROP_MAC_WHITELIST";
+ break;
+
+ case SPINEL_PROP_MAC_WHITELIST_ENABLED:
+ ret = "PROP_MAC_WHITELIST_ENABLED";
+ break;
+
+ case SPINEL_PROP_THREAD_MODE:
+ ret = "PROP_THREAD_MODE";
+ break;
+
+ case SPINEL_PROP_THREAD_CHILD_TIMEOUT:
+ ret = "PROP_THREAD_CHILD_TIMEOUT";
+ break;
+
+
+ case SPINEL_PROP_NET_REQUIRE_JOIN_EXISTING:
+ ret = "PROP_NET_REQUIRE_JOIN_EXISTING";
+ break;
+
+ case SPINEL_PROP_NEST_STREAM_MFG:
+ ret = "PROP_NEST_STREAM_MFG";
+ break;
+
+ case SPINEL_PROP_THREAD_NETWORK_ID_TIMEOUT:
+ ret = "PROP_THREAD_NETWORK_ID_TIMEOUT";
+ break;
+
+ case SPINEL_PROP_THREAD_ACTIVE_ROUTER_IDS:
+ ret = "PROP_THREAD_ACTIVE_ROUTER_IDS";
+ break;
+
+ case SPINEL_PROP_THREAD_ROUTER_DOWNGRADE_THRESHOLD:
+ ret = "PROP_THREAD_ROUTER_DOWNGRADE_THRESHOLD";
+ break;
+
+ case SPINEL_PROP_THREAD_ROUTER_SELECTION_JITTER:
+ ret = "PROP_THREAD_ROUTER_SELECTION_JITTER";
+ break;
+
+ case SPINEL_PROP_THREAD_PREFERRED_ROUTER_ID:
+ ret = "PROP_THREAD_PREFERRED_ROUTER_ID";
+ break;
+
+ case SPINEL_PROP_THREAD_NEIGHBOR_TABLE:
+ ret = "PROP_THREAD_NEIGHBOR_TABLE";
+ break;
+
+ case SPINEL_PROP_JAM_DETECT_ENABLE:
+ ret = "PROP_JAM_DETECT_ENABLE";
+ break;
+
+ case SPINEL_PROP_JAM_DETECTED:
+ ret = "PROP_JAM_DETECTED";
+ break;
+
+ case SPINEL_PROP_JAM_DETECT_RSSI_THRESHOLD:
+ ret = "PROP_JAM_DETECT_RSSI_THRESHOLD";
+ break;
+
+ case SPINEL_PROP_JAM_DETECT_WINDOW:
+ ret = "PROP_JAM_DETECT_WINDOW";
+ break;
+
+ case SPINEL_PROP_JAM_DETECT_HISTORY_BITMAP:
+ ret = "SPINEL_PROP_JAM_DETECT_HISTORY_BITMAP";
+ break;
+
+ case SPINEL_PROP_GPIO_CONFIG:
+ ret = "PROP_GPIO_CONFIG";
+ break;
+
+ case SPINEL_PROP_GPIO_STATE:
+ ret = "PROP_GPIO_STATE";
+ break;
+
+ case SPINEL_PROP_GPIO_STATE_SET:
+ ret = "PROP_GPIO_STATE_SET";
+ break;
+
+ case SPINEL_PROP_GPIO_STATE_CLEAR:
+ ret = "PROP_GPIO_STATE_CLEAR";
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+const char *spinel_net_role_to_cstr(uint8_t net_role)
+{
+ const char *ret = "NET_ROLE_UNKNONW";
+
+ switch (net_role)
+ {
+ case SPINEL_NET_ROLE_DETACHED:
+ ret = "NET_ROLE_DETACHED";
+ break;
+
+ case SPINEL_NET_ROLE_CHILD:
+ ret = "NET_ROLE_CHILD";
+ break;
+
+ case SPINEL_NET_ROLE_ROUTER:
+ ret = "NET_ROLE_ROUTER";
+ break;
+
+ case SPINEL_NET_ROLE_LEADER:
+ ret = "NET_ROLE_LEADER";
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+const char *spinel_status_to_cstr(spinel_status_t status)
+{
+ const char *ret = "UNKNOWN";
+
+ switch (status)
+ {
+ case SPINEL_STATUS_OK:
+ ret = "STATUS_OK";
+ break;
+
+ case SPINEL_STATUS_FAILURE:
+ ret = "STATUS_FAILURE";
+ break;
+
+ case SPINEL_STATUS_UNIMPLEMENTED:
+ ret = "STATUS_UNIMPLEMENTED";
+ break;
+
+ case SPINEL_STATUS_INVALID_ARGUMENT:
+ ret = "STATUS_INVALID_ARGUMENT";
+ break;
+
+ case SPINEL_STATUS_INVALID_STATE:
+ ret = "STATUS_INVALID_STATE";
+ break;
+
+ case SPINEL_STATUS_INVALID_COMMAND:
+ ret = "STATUS_INVALID_COMMAND";
+ break;
+
+ case SPINEL_STATUS_INVALID_INTERFACE:
+ ret = "STATUS_INVALID_INTERFACE";
+ break;
+
+ case SPINEL_STATUS_INTERNAL_ERROR:
+ ret = "STATUS_INTERNAL_ERROR";
+ break;
+
+ case SPINEL_STATUS_SECURITY_ERROR:
+ ret = "STATUS_SECURITY_ERROR";
+ break;
+
+ case SPINEL_STATUS_PARSE_ERROR:
+ ret = "STATUS_PARSE_ERROR";
+ break;
+
+ case SPINEL_STATUS_IN_PROGRESS:
+ ret = "STATUS_IN_PROGRESS";
+ break;
+
+ case SPINEL_STATUS_NOMEM:
+ ret = "STATUS_NOMEM";
+ break;
+
+ case SPINEL_STATUS_BUSY:
+ ret = "STATUS_BUSY";
+ break;
+
+ case SPINEL_STATUS_PROP_NOT_FOUND:
+ ret = "STATUS_PROP_NOT_FOUND";
+ break;
+
+ case SPINEL_STATUS_DROPPED:
+ ret = "STATUS_DROPPED";
+ break;
+
+ case SPINEL_STATUS_EMPTY:
+ ret = "STATUS_EMPTY";
+ break;
+
+ case SPINEL_STATUS_CMD_TOO_BIG:
+ ret = "STATUS_CMD_TOO_BIG";
+ break;
+
+ case SPINEL_STATUS_NO_ACK:
+ ret = "STATUS_NO_ACK";
+ break;
+
+ case SPINEL_STATUS_CCA_FAILURE:
+ ret = "STATUS_CCA_FAILURE";
+ break;
+
+ case SPINEL_STATUS_ALREADY:
+ ret = "STATUS_ALREADY";
+ break;
+
+ case SPINEL_STATUS_ITEM_NOT_FOUND:
+ ret = "STATUS_ITEM_NOT_FOUND";
+ break;
+
+ case SPINEL_STATUS_JOIN_FAILURE:
+ ret = "STATUS_JOIN_FAILURE";
+ break;
+
+ case SPINEL_STATUS_JOIN_SECURITY:
+ ret = "STATUS_JOIN_SECURITY";
+ break;
+
+ case SPINEL_STATUS_JOIN_NO_PEERS:
+ ret = "STATUS_JOIN_NO_PEERS";
+ break;
+
+ case SPINEL_STATUS_JOIN_INCOMPATIBLE:
+ ret = "STATUS_JOIN_INCOMPATIBLE";
+ break;
+
+ case SPINEL_STATUS_RESET_POWER_ON:
+ ret = "STATUS_RESET_POWER_ON";
+ break;
+
+ case SPINEL_STATUS_RESET_EXTERNAL:
+ ret = "STATUS_RESET_EXTERNAL";
+ break;
+
+ case SPINEL_STATUS_RESET_SOFTWARE:
+ ret = "STATUS_RESET_SOFTWARE";
+ break;
+
+ case SPINEL_STATUS_RESET_FAULT:
+ ret = "STATUS_RESET_FAULT";
+ break;
+
+ case SPINEL_STATUS_RESET_CRASH:
+ ret = "STATUS_RESET_CRASH";
+ break;
+
+ case SPINEL_STATUS_RESET_ASSERT:
+ ret = "STATUS_RESET_ASSERT";
+ break;
+
+ case SPINEL_STATUS_RESET_OTHER:
+ ret = "STATUS_RESET_OTHER";
+ break;
+
+ case SPINEL_STATUS_RESET_UNKNOWN:
+ ret = "STATUS_RESET_UNKNOWN";
+ break;
+
+ case SPINEL_STATUS_RESET_WATCHDOG:
+ ret = "STATUS_RESET_WATCHDOG";
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+// **** LCOV_EXCL_STOP ****
+
+/* -------------------------------------------------------------------------- */
+
+#if SPINEL_SELF_TEST
+
+#include <stdlib.h>
+#include <string.h>
+
+
+int
+main(void)
+{
+ int ret = -1;
+
+ const char static_string[] = "static_string";
+ uint8_t buffer[1024];
+ ssize_t len;
+
+ len = spinel_datatype_pack(buffer, sizeof(buffer), "CiiLU", 0x88, 9, 0xA3, 0xDEADBEEF, static_string);
+
+ if (len != 22)
+ {
+ printf("error:%d: len != 22; (%d)\n", __LINE__, (int)len);
+ goto bail;
+ }
+
+ {
+ uint8_t c = 0;
+ unsigned int i1 = 0;
+ unsigned int i2 = 0;
+ uint32_t l = 0;
+ const char *str = NULL;
+
+ len = spinel_datatype_unpack(buffer, (spinel_size_t)len, "CiiLU", &c, &i1, &i2, &l, &str);
+
+ if (len != 22)
+ {
+ printf("error:%d: len != 22; (%d)\n", __LINE__, (int)len);
+ goto bail;
+ }
+
+ if (c != 0x88)
+ {
+ printf("error: x != 0x88; (%d)\n", c);
+ goto bail;
+ }
+
+ if (i1 != 9)
+ {
+ printf("error: i1 != 9; (%d)\n", i1);
+ goto bail;
+ }
+
+ if (i2 != 0xA3)
+ {
+ printf("error: i2 != 0xA3; (0x%02X)\n", i2);
+ goto bail;
+ }
+
+ if (l != 0xDEADBEEF)
+ {
+ printf("error: l != 0xDEADBEEF; (0x%08X)\n", (unsigned int)l);
+ goto bail;
+ }
+
+ if (strcmp(str, static_string) != 0)
+ {
+ printf("error:%d: strcmp(str,static_string) != 0\n", __LINE__);
+ goto bail;
+ }
+ }
+
+ // -----------------------------------
+
+ memset(buffer, 0xAA, sizeof(buffer));
+
+ len = spinel_datatype_pack(buffer, sizeof(buffer), "CiT(iL)U", 0x88, 9, 0xA3, 0xDEADBEEF, static_string);
+
+ if (len != 24)
+ {
+ printf("error:%d: len != 24; (%d)\n", __LINE__, (int)len);
+ goto bail;
+ }
+
+
+
+ {
+ uint8_t c = 0;
+ unsigned int i1 = 0;
+ unsigned int i2 = 0;
+ uint32_t l = 0;
+ const char *str = NULL;
+
+ len = spinel_datatype_unpack(buffer, (spinel_size_t)len, "CiT(iL)U", &c, &i1, &i2, &l, &str);
+
+ if (len != 24)
+ {
+ printf("error:%d: len != 24; (%d)\n", __LINE__, (int)len);
+ goto bail;
+ }
+
+ if (c != 0x88)
+ {
+ printf("error: x != 0x88; (%d)\n", c);
+ goto bail;
+ }
+
+ if (i1 != 9)
+ {
+ printf("error: i1 != 9; (%d)\n", i1);
+ goto bail;
+ }
+
+ if (i2 != 0xA3)
+ {
+ printf("error: i2 != 0xA3; (0x%02X)\n", i2);
+ goto bail;
+ }
+
+ if (l != 0xDEADBEEF)
+ {
+ printf("error: l != 0xDEADBEEF; (0x%08X)\n", (unsigned int)l);
+ goto bail;
+ }
+
+ if (strcmp(str, static_string) != 0)
+ {
+ printf("error:%d: strcmp(str,static_string) != 0\n", __LINE__);
+ goto bail;
+ }
+ }
+
+
+
+ printf("OK\n");
+ ret = 0;
+ return ret;
+
+bail:
+ printf("FAILURE\n");
+ return ret;
+}
+
+#endif // #if SPINEL_SELF_TEST
diff --git a/third_party/openthread/src/ncp/spinel.h b/third_party/openthread/src/ncp/spinel.h
new file mode 100644
index 0000000..db5fedc
--- /dev/null
+++ b/third_party/openthread/src/ncp/spinel.h
@@ -0,0 +1,1171 @@
+/*
+ * Copyright (c) 2016, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SPINEL_HEADER_INCLUDED
+#define SPINEL_HEADER_INCLUDED 1
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+// ----------------------------------------------------------------------------
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+# if defined(__GNUC__)
+# define SPINEL_API_EXTERN extern __attribute__ ((visibility ("default")))
+# define SPINEL_API_NONNULL_ALL __attribute__((nonnull))
+# define SPINEL_API_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+# endif // ifdef __GNUC__
+
+# if !defined(__BEGIN_DECLS) || !defined(__END_DECLS)
+# if defined(__cplusplus)
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS }
+# else // if defined(__cplusplus)
+# define __BEGIN_DECLS
+# define __END_DECLS
+# endif // else defined(__cplusplus)
+# endif // if !defined(__BEGIN_DECLS) || !defined(__END_DECLS)
+
+#endif // ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+#ifndef SPINEL_API_EXTERN
+# define SPINEL_API_EXTERN extern
+#endif
+
+#ifndef SPINEL_API_NONNULL_ALL
+# define SPINEL_API_NONNULL_ALL
+#endif
+
+#ifndef SPINEL_API_WARN_UNUSED_RESULT
+# define SPINEL_API_WARN_UNUSED_RESULT
+#endif
+
+// ----------------------------------------------------------------------------
+
+#define SPINEL_PROTOCOL_VERSION_THREAD_MAJOR 4
+#define SPINEL_PROTOCOL_VERSION_THREAD_MINOR 2
+
+#define SPINEL_FRAME_MAX_SIZE 1300
+
+/// Macro for generating bit masks using bit index from the spec
+#define SPINEL_BIT_MASK(bit_index,field_bit_count) \
+ ( (1 << ((field_bit_count) - 1)) >> (bit_index))
+
+// ----------------------------------------------------------------------------
+
+__BEGIN_DECLS
+
+typedef enum
+{
+ SPINEL_STATUS_OK = 0, ///< Operation has completed successfully.
+ SPINEL_STATUS_FAILURE = 1, ///< Operation has failed for some undefined reason.
+
+ SPINEL_STATUS_UNIMPLEMENTED = 2, ///< Given operation has not been implemented.
+ SPINEL_STATUS_INVALID_ARGUMENT = 3, ///< An argument to the operation is invalid.
+ SPINEL_STATUS_INVALID_STATE = 4, ///< This operation is invalid for the current device state.
+ SPINEL_STATUS_INVALID_COMMAND = 5, ///< This command is not recognized.
+ SPINEL_STATUS_INVALID_INTERFACE = 6, ///< This interface is not supported.
+ SPINEL_STATUS_INTERNAL_ERROR = 7, ///< An internal runtime error has occured.
+ SPINEL_STATUS_SECURITY_ERROR = 8, ///< A security/authentication error has occured.
+ SPINEL_STATUS_PARSE_ERROR = 9, ///< A error has occured while parsing the command.
+ SPINEL_STATUS_IN_PROGRESS = 10, ///< This operation is in progress.
+ SPINEL_STATUS_NOMEM = 11, ///< Operation prevented due to memory pressure.
+ SPINEL_STATUS_BUSY = 12, ///< The device is currently performing a mutually exclusive operation
+ SPINEL_STATUS_PROP_NOT_FOUND = 13, ///< The given property is not recognized.
+ SPINEL_STATUS_DROPPED = 14, ///< A/The packet was dropped.
+ SPINEL_STATUS_EMPTY = 15, ///< The result of the operation is empty.
+ SPINEL_STATUS_CMD_TOO_BIG = 16, ///< The command was too large to fit in the internal buffer.
+ SPINEL_STATUS_NO_ACK = 17, ///< The packet was not acknowledged.
+ SPINEL_STATUS_CCA_FAILURE = 18, ///< The packet was not sent due to a CCA failure.
+ SPINEL_STATUS_ALREADY = 19, ///< The operation is already in progress.
+ SPINEL_STATUS_ITEM_NOT_FOUND = 20, ///< The given item could not be found.
+
+ SPINEL_STATUS_JOIN__BEGIN = 104,
+
+ /// Generic failure to associate with other peers.
+ /**
+ * This status error should not be used by implementors if
+ * enough information is available to determine that one of the
+ * later join failure status codes would be more accurate.
+ *
+ * \sa SPINEL_PROP_NET_REQUIRE_JOIN_EXISTING
+ */
+ SPINEL_STATUS_JOIN_FAILURE = SPINEL_STATUS_JOIN__BEGIN + 0,
+
+ /// The node found other peers but was unable to decode their packets.
+ /**
+ * Typically this error code indicates that the network
+ * key has been set incorrectly.
+ *
+ * \sa SPINEL_PROP_NET_REQUIRE_JOIN_EXISTING
+ */
+ SPINEL_STATUS_JOIN_SECURITY = SPINEL_STATUS_JOIN__BEGIN + 1,
+
+ /// The node was unable to find any other peers on the network.
+ /**
+ * \sa SPINEL_PROP_NET_REQUIRE_JOIN_EXISTING
+ */
+ SPINEL_STATUS_JOIN_NO_PEERS = SPINEL_STATUS_JOIN__BEGIN + 2,
+
+ /// The only potential peer nodes found are incompatible.
+ /**
+ * \sa SPINEL_PROP_NET_REQUIRE_JOIN_EXISTING
+ */
+ SPINEL_STATUS_JOIN_INCOMPATIBLE = SPINEL_STATUS_JOIN__BEGIN + 3,
+
+ SPINEL_STATUS_JOIN__END = 112,
+
+ SPINEL_STATUS_RESET__BEGIN = 112,
+ SPINEL_STATUS_RESET_POWER_ON = SPINEL_STATUS_RESET__BEGIN + 0,
+ SPINEL_STATUS_RESET_EXTERNAL = SPINEL_STATUS_RESET__BEGIN + 1,
+ SPINEL_STATUS_RESET_SOFTWARE = SPINEL_STATUS_RESET__BEGIN + 2,
+ SPINEL_STATUS_RESET_FAULT = SPINEL_STATUS_RESET__BEGIN + 3,
+ SPINEL_STATUS_RESET_CRASH = SPINEL_STATUS_RESET__BEGIN + 4,
+ SPINEL_STATUS_RESET_ASSERT = SPINEL_STATUS_RESET__BEGIN + 5,
+ SPINEL_STATUS_RESET_OTHER = SPINEL_STATUS_RESET__BEGIN + 6,
+ SPINEL_STATUS_RESET_UNKNOWN = SPINEL_STATUS_RESET__BEGIN + 7,
+ SPINEL_STATUS_RESET_WATCHDOG = SPINEL_STATUS_RESET__BEGIN + 8,
+ SPINEL_STATUS_RESET__END = 128,
+
+ SPINEL_STATUS_VENDOR__BEGIN = 15360,
+ SPINEL_STATUS_VENDOR__END = 16384,
+
+ SPINEL_STATUS_STACK_NATIVE__BEGIN = 16384,
+ SPINEL_STATUS_STACK_NATIVE__END = 81920,
+
+ SPINEL_STATUS_EXPERIMENTAL__BEGIN = 2000000,
+ SPINEL_STATUS_EXPERIMENTAL__END = 2097152,
+} spinel_status_t;
+
+typedef enum
+{
+ SPINEL_NET_ROLE_DETACHED = 0,
+ SPINEL_NET_ROLE_CHILD = 1,
+ SPINEL_NET_ROLE_ROUTER = 2,
+ SPINEL_NET_ROLE_LEADER = 3,
+} spinel_net_role_t;
+
+typedef enum
+{
+ SPINEL_SCAN_STATE_IDLE = 0,
+ SPINEL_SCAN_STATE_BEACON = 1,
+ SPINEL_SCAN_STATE_ENERGY = 2,
+} spinel_scan_state_t;
+
+typedef enum
+{
+ SPINEL_POWER_STATE_OFFLINE = 0,
+ SPINEL_POWER_STATE_DEEP_SLEEP = 1,
+ SPINEL_POWER_STATE_STANDBY = 2,
+ SPINEL_POWER_STATE_LOW_POWER = 3,
+ SPINEL_POWER_STATE_ONLINE = 4,
+} spinel_power_state_t;
+
+enum {
+ SPINEL_NET_FLAG_ON_MESH = (1 << 0),
+ SPINEL_NET_FLAG_DEFAULT_ROUTE = (1 << 1),
+ SPINEL_NET_FLAG_CONFIGURE = (1 << 2),
+ SPINEL_NET_FLAG_DHCP = (1 << 3),
+ SPINEL_NET_FLAG_SLAAC = (1 << 4),
+ SPINEL_NET_FLAG_PREFERRED = (1 << 5),
+
+ SPINEL_NET_FLAG_PREFERENCE_OFFSET = 6,
+ SPINEL_NET_FLAG_PREFERENCE_MASK = (3 << SPINEL_NET_FLAG_PREFERENCE_OFFSET),
+};
+
+enum {
+ SPINEL_GPIO_FLAG_DIR_INPUT = 0,
+ SPINEL_GPIO_FLAG_DIR_OUTPUT = SPINEL_BIT_MASK(0, 8),
+ SPINEL_GPIO_FLAG_PULL_UP = SPINEL_BIT_MASK(1, 8),
+ SPINEL_GPIO_FLAG_PULL_DOWN = SPINEL_BIT_MASK(2, 8),
+ SPINEL_GPIO_FLAG_OPEN_DRAIN = SPINEL_BIT_MASK(2, 8),
+ SPINEL_GPIO_FLAG_TRIGGER_NONE = 0,
+ SPINEL_GPIO_FLAG_TRIGGER_RISING = SPINEL_BIT_MASK(3, 8),
+ SPINEL_GPIO_FLAG_TRIGGER_FALLING = SPINEL_BIT_MASK(4, 8),
+ SPINEL_GPIO_FLAG_TRIGGER_ANY = SPINEL_GPIO_FLAG_TRIGGER_RISING
+ | SPINEL_GPIO_FLAG_TRIGGER_FALLING,
+};
+
+enum
+{
+ SPINEL_PROTOCOL_TYPE_BOOTLOADER = 0,
+ SPINEL_PROTOCOL_TYPE_ZIGBEE_IP = 2,
+ SPINEL_PROTOCOL_TYPE_THREAD = 3,
+};
+
+enum
+{
+ SPINEL_MAC_PROMISCUOUS_MODE_OFF = 0, ///< Normal MAC filtering is in place.
+ SPINEL_MAC_PROMISCUOUS_MODE_NETWORK = 1, ///< All MAC packets matching network are passed up the stack.
+ SPINEL_MAC_PROMISCUOUS_MODE_FULL = 2, ///< All decoded MAC packets are passed up the stack.
+};
+
+typedef struct
+{
+ uint8_t bytes[8];
+} spinel_eui64_t;
+
+typedef struct
+{
+ uint8_t bytes[8];
+} spinel_net_xpanid_t;
+
+typedef struct
+{
+ uint8_t bytes[6];
+} spinel_eui48_t;
+
+typedef struct
+{
+ uint8_t bytes[16];
+} spinel_ipv6addr_t;
+
+typedef int spinel_ssize_t;
+typedef unsigned int spinel_size_t;
+typedef uint8_t spinel_tid_t;
+typedef unsigned int spinel_cid_t;
+
+enum
+{
+ SPINEL_MD_FLAG_TX = 0x0001, //!< Packet was transmitted, not received.
+ SPINEL_MD_FLAG_BAD_FCS = 0x0004, //!< Packet was received with bad FCS
+ SPINEL_MD_FLAG_DUPE = 0x0008, //!< Packet seems to be a duplicate
+ SPINEL_MD_FLAG_RESERVED = 0xFFF2, //!< Flags reserved for future use.
+};
+
+enum
+{
+ SPINEL_CMD_NOOP = 0,
+ SPINEL_CMD_RESET = 1,
+ SPINEL_CMD_PROP_VALUE_GET = 2,
+ SPINEL_CMD_PROP_VALUE_SET = 3,
+ SPINEL_CMD_PROP_VALUE_INSERT = 4,
+ SPINEL_CMD_PROP_VALUE_REMOVE = 5,
+ SPINEL_CMD_PROP_VALUE_IS = 6,
+ SPINEL_CMD_PROP_VALUE_INSERTED = 7,
+ SPINEL_CMD_PROP_VALUE_REMOVED = 8,
+
+ SPINEL_CMD_NET_SAVE = 9,
+ SPINEL_CMD_NET_CLEAR = 10,
+ SPINEL_CMD_NET_RECALL = 11,
+
+ SPINEL_CMD_HBO_OFFLOAD = 12,
+ SPINEL_CMD_HBO_RECLAIM = 13,
+ SPINEL_CMD_HBO_DROP = 14,
+ SPINEL_CMD_HBO_OFFLOADED = 15,
+ SPINEL_CMD_HBO_RECLAIMED = 16,
+ SPINEL_CMD_HBO_DROPED = 17,
+
+ SPINEL_CMD_PEEK = 18,
+ SPINEL_CMD_PEEK_RET = 19,
+ SPINEL_CMD_POKE = 20,
+
+ SPINEL_CMD_NEST__BEGIN = 15296,
+ SPINEL_CMD_NEST__END = 15360,
+
+ SPINEL_CMD_VENDOR__BEGIN = 15360,
+ SPINEL_CMD_VENDOR__END = 16384,
+
+ SPINEL_CMD_EXPERIMENTAL__BEGIN = 2000000,
+ SPINEL_CMD_EXPERIMENTAL__END = 2097152,
+};
+
+enum
+{
+ SPINEL_CAP_LOCK = 1,
+ SPINEL_CAP_NET_SAVE = 2,
+ SPINEL_CAP_HBO = 3,
+ SPINEL_CAP_POWER_SAVE = 4,
+
+ SPINEL_CAP_COUNTERS = 5,
+ SPINEL_CAP_JAM_DETECT = 6,
+
+ SPINEL_CAP_PEEK_POKE = 7,
+
+ SPINEL_CAP_WRITABLE_RAW_STREAM = 8,
+ SPINEL_CAP_GPIO = 9,
+ SPINEL_CAP_TRNG = 10,
+
+ SPINEL_CAP_802_15_4__BEGIN = 16,
+ SPINEL_CAP_802_15_4_2003 = (SPINEL_CAP_802_15_4__BEGIN + 0),
+ SPINEL_CAP_802_15_4_2006 = (SPINEL_CAP_802_15_4__BEGIN + 1),
+ SPINEL_CAP_802_15_4_2011 = (SPINEL_CAP_802_15_4__BEGIN + 2),
+ SPINEL_CAP_802_15_4_PIB = (SPINEL_CAP_802_15_4__BEGIN + 5),
+ SPINEL_CAP_802_15_4_2450MHZ_OQPSK = (SPINEL_CAP_802_15_4__BEGIN + 8),
+ SPINEL_CAP_802_15_4_915MHZ_OQPSK = (SPINEL_CAP_802_15_4__BEGIN + 9),
+ SPINEL_CAP_802_15_4_868MHZ_OQPSK = (SPINEL_CAP_802_15_4__BEGIN + 10),
+ SPINEL_CAP_802_15_4_915MHZ_BPSK = (SPINEL_CAP_802_15_4__BEGIN + 11),
+ SPINEL_CAP_802_15_4_868MHZ_BPSK = (SPINEL_CAP_802_15_4__BEGIN + 12),
+ SPINEL_CAP_802_15_4_915MHZ_ASK = (SPINEL_CAP_802_15_4__BEGIN + 13),
+ SPINEL_CAP_802_15_4_868MHZ_ASK = (SPINEL_CAP_802_15_4__BEGIN + 14),
+ SPINEL_CAP_802_15_4__END = 32,
+
+ SPINEL_CAP_ROLE__BEGIN = 48,
+ SPINEL_CAP_ROLE_ROUTER = (SPINEL_CAP_ROLE__BEGIN + 0),
+ SPINEL_CAP_ROLE_SLEEPY = (SPINEL_CAP_ROLE__BEGIN + 1),
+ SPINEL_CAP_ROLE__END = 52,
+
+ SPINEL_CAP_NET__BEGIN = 52,
+ SPINEL_CAP_NET_THREAD_1_0 = (SPINEL_CAP_NET__BEGIN + 0),
+ SPINEL_CAP_NET__END = 64,
+
+ SPINEL_CAP_OPENTHREAD__BEGIN = 512,
+ SPINEL_CAP_MAC_WHITELIST = (SPINEL_CAP_OPENTHREAD__BEGIN + 0),
+ SPINEL_CAP_OPENTHREAD__END = 640,
+
+ SPINEL_CAP_NEST__BEGIN = 15296,
+ SPINEL_CAP_NEST_LEGACY_INTERFACE = (SPINEL_CAP_NEST__BEGIN + 0),
+ SPINEL_CAP_NEST_LEGACY_NET_WAKE = (SPINEL_CAP_NEST__BEGIN + 1),
+ SPINEL_CAP_NEST_TRANSMIT_HOOK = (SPINEL_CAP_NEST__BEGIN + 2),
+ SPINEL_CAP_NEST__END = 15360,
+
+ SPINEL_CAP_VENDOR__BEGIN = 15360,
+ SPINEL_CAP_VENDOR__END = 16384,
+
+ SPINEL_CAP_EXPERIMENTAL__BEGIN = 2000000,
+ SPINEL_CAP_EXPERIMENTAL__END = 2097152,
+};
+
+typedef enum
+{
+ SPINEL_PROP_LAST_STATUS = 0, ///< status [i]
+ SPINEL_PROP_PROTOCOL_VERSION = 1, ///< major, minor [i,i]
+ SPINEL_PROP_NCP_VERSION = 2, ///< version string [U]
+ SPINEL_PROP_INTERFACE_TYPE = 3, ///< [i]
+ SPINEL_PROP_VENDOR_ID = 4, ///< [i]
+ SPINEL_PROP_CAPS = 5, ///< capability list [A(i)]
+ SPINEL_PROP_INTERFACE_COUNT = 6, ///< Interface count [C]
+ SPINEL_PROP_POWER_STATE = 7, ///< PowerState [C]
+ SPINEL_PROP_HWADDR = 8, ///< PermEUI64 [E]
+ SPINEL_PROP_LOCK = 9, ///< PropLock [b]
+ SPINEL_PROP_HBO_MEM_MAX = 10, ///< Max offload mem [S]
+ SPINEL_PROP_HBO_BLOCK_MAX = 11, ///< Max offload block [S]
+
+ SPINEL_PROP_BASE_EXT__BEGIN = 0x1000,
+
+ /// GPIO Configuration
+ /** Format: `A(CCU)`
+ * Type: Read-Only (Optionally Read-write using `CMD_PROP_VALUE_INSERT`)
+ *
+ * An array of structures which contain the following fields:
+ *
+ * * `C`: GPIO Number
+ * * `C`: GPIO Configuration Flags
+ * * `U`: Human-readable GPIO name
+ *
+ * GPIOs which do not have a corresponding entry are not supported.
+ *
+ * The configuration parameter contains the configuration flags for the
+ * GPIO:
+ *
+ * 0 1 2 3 4 5 6 7
+ * +---+---+---+---+---+---+---+---+
+ * |DIR|PUP|PDN|TRIGGER| RESERVED |
+ * +---+---+---+---+---+---+---+---+
+ * |O/D|
+ * +---+
+ *
+ * * `DIR`: Pin direction. Clear (0) for input, set (1) for output.
+ * * `PUP`: Pull-up enabled flag.
+ * * `PDN`/`O/D`: Flag meaning depends on pin direction:
+ * * Input: Pull-down enabled.
+ * * Output: Output is an open-drain.
+ * * `TRIGGER`: Enumeration describing how pin changes generate
+ * asynchronous notification commands (TBD) from the NCP to the host.
+ * * 0: Feature disabled for this pin
+ * * 1: Trigger on falling edge
+ * * 2: Trigger on rising edge
+ * * 3: Trigger on level change
+ * * `RESERVED`: Bits reserved for future use. Always cleared to zero
+ * and ignored when read.
+ *
+ * As an optional feature, the configuration of individual pins may be
+ * modified using the `CMD_PROP_VALUE_INSERT` command. Only the GPIO
+ * number and flags fields MUST be present, the GPIO name (if present)
+ * would be ignored. This command can only be used to modify the
+ * configuration of GPIOs which are already exposed---it cannot be used
+ * by the host to add addional GPIOs.
+ */
+ SPINEL_PROP_GPIO_CONFIG = SPINEL_PROP_BASE_EXT__BEGIN + 0,
+
+ /// GPIO State Bitmask
+ /** Format: `D`
+ * Type: Read-Write
+ *
+ * Contains a bit field identifying the state of the GPIOs. The length of
+ * the data associated with these properties depends on the number of
+ * GPIOs. If you have 10 GPIOs, you'd have two bytes. GPIOs are numbered
+ * from most significant bit to least significant bit, so 0x80 is GPIO 0,
+ * 0x40 is GPIO 1, etc.
+ *
+ * For GPIOs configured as inputs:
+ *
+ * * `CMD_PROP_VAUE_GET`: The value of the associated bit describes the
+ * logic level read from the pin.
+ * * `CMD_PROP_VALUE_SET`: The value of the associated bit is ignored
+ * for these pins.
+ *
+ * For GPIOs configured as outputs:
+ *
+ * * `CMD_PROP_VAUE_GET`: The value of the associated bit is
+ * implementation specific.
+ * * `CMD_PROP_VALUE_SET`: The value of the associated bit determines
+ * the new logic level of the output. If this pin is configured as an
+ * open-drain, setting the associated bit to 1 will cause the pin to
+ * enter a Hi-Z state.
+ *
+ * For GPIOs which are not specified in `PROP_GPIO_CONFIG`:
+ *
+ * * `CMD_PROP_VAUE_GET`: The value of the associated bit is
+ * implementation specific.
+ * * `CMD_PROP_VALUE_SET`: The value of the associated bit MUST be
+ * ignored by the NCP.
+ *
+ * When writing, unspecified bits are assumed to be zero.
+ */
+ SPINEL_PROP_GPIO_STATE = SPINEL_PROP_BASE_EXT__BEGIN + 2,
+
+ /// GPIO State Set-Only Bitmask
+ /** Format: `D`
+ * Type: Write-Only
+ *
+ * Allows for the state of various output GPIOs to be set without affecting
+ * other GPIO states. Contains a bit field identifying the output GPIOs that
+ * should have their state set to 1.
+ *
+ * When writing, unspecified bits are assumed to be zero. The value of
+ * any bits for GPIOs which are not specified in `PROP_GPIO_CONFIG` MUST
+ * be ignored.
+ */
+ SPINEL_PROP_GPIO_STATE_SET = SPINEL_PROP_BASE_EXT__BEGIN + 3,
+
+ /// GPIO State Clear-Only Bitmask
+ /** Format: `D`
+ * Type: Write-Only
+ *
+ * Allows for the state of various output GPIOs to be cleared without affecting
+ * other GPIO states. Contains a bit field identifying the output GPIOs that
+ * should have their state cleared to 0.
+ *
+ * When writing, unspecified bits are assumed to be zero. The value of
+ * any bits for GPIOs which are not specified in `PROP_GPIO_CONFIG` MUST
+ * be ignored.
+ */
+ SPINEL_PROP_GPIO_STATE_CLEAR = SPINEL_PROP_BASE_EXT__BEGIN + 4,
+
+ /// 32-bit random number from TRNG, ready-to-use.
+ SPINEL_PROP_TRNG_32 = SPINEL_PROP_BASE_EXT__BEGIN + 5,
+
+ /// 16 random bytes from TRNG, ready-to-use.
+ SPINEL_PROP_TRNG_128 = SPINEL_PROP_BASE_EXT__BEGIN + 6,
+
+ /// Raw samples from TRNG entropy source representing 32 bits of entropy.
+ SPINEL_PROP_TRNG_RAW_32 = SPINEL_PROP_BASE_EXT__BEGIN + 7,
+
+ SPINEL_PROP_BASE_EXT__END = 0x1100,
+
+ SPINEL_PROP_PHY__BEGIN = 0x20,
+ SPINEL_PROP_PHY_ENABLED = SPINEL_PROP_PHY__BEGIN + 0, ///< [b]
+ SPINEL_PROP_PHY_CHAN = SPINEL_PROP_PHY__BEGIN + 1, ///< [C]
+ SPINEL_PROP_PHY_CHAN_SUPPORTED = SPINEL_PROP_PHY__BEGIN + 2, ///< [A(C)]
+ SPINEL_PROP_PHY_FREQ = SPINEL_PROP_PHY__BEGIN + 3, ///< kHz [L]
+ SPINEL_PROP_PHY_CCA_THRESHOLD = SPINEL_PROP_PHY__BEGIN + 4, ///< dBm [c]
+ SPINEL_PROP_PHY_TX_POWER = SPINEL_PROP_PHY__BEGIN + 5, ///< [c]
+ SPINEL_PROP_PHY_RSSI = SPINEL_PROP_PHY__BEGIN + 6, ///< dBm [c]
+ SPINEL_PROP_PHY__END = 0x30,
+
+ SPINEL_PROP_PHY_EXT__BEGIN = 0x1200,
+
+ /// Signal Jamming Detection Enable
+ /** Format: `b`
+ *
+ * Indicates if jamming detection is enabled or disabled. Set to true
+ * to enable jamming detection.
+ */
+ SPINEL_PROP_JAM_DETECT_ENABLE = SPINEL_PROP_PHY_EXT__BEGIN + 0,
+
+ /// Signal Jamming Detected Indicator
+ /** Format: `b` (Read-Only)
+ *
+ * Set to true if radio jamming is detected. Set to false otherwise.
+ *
+ * When jamming detection is enabled, changes to the value of this
+ * property are emitted asynchronously via `CMD_PROP_VALUE_IS`.
+ */
+ SPINEL_PROP_JAM_DETECTED = SPINEL_PROP_PHY_EXT__BEGIN + 1,
+
+ /// Jamming detection RSSI threshold
+ /** Format: `c`
+ * Units: dBm
+ *
+ * This parameter describes the threshold RSSI level (measured in
+ * dBm) above which the jamming detection will consider the
+ * channel blocked.
+ */
+ SPINEL_PROP_JAM_DETECT_RSSI_THRESHOLD
+ = SPINEL_PROP_PHY_EXT__BEGIN + 2,
+
+ /// Jamming detection window size
+ /** Format: `C`
+ * Units: Seconds (1-63)
+ *
+ * This parameter describes the window period for signal jamming
+ * detection.
+ */
+ SPINEL_PROP_JAM_DETECT_WINDOW = SPINEL_PROP_PHY_EXT__BEGIN + 3,
+
+ /// Jamming detection busy period
+ /** Format: `C`
+ * Units: Seconds (1-63)
+ *
+ * This parameter describes the number of aggregate seconds within
+ * the detection window where the RSSI must be above
+ * `PROP_JAM_DETECT_RSSI_THRESHOLD` to trigger detection.
+ *
+ * The behavior of the jamming detection feature when `PROP_JAM_DETECT_BUSY`
+ * is larger than `PROP_JAM_DETECT_WINDOW` is undefined.
+ */
+ SPINEL_PROP_JAM_DETECT_BUSY = SPINEL_PROP_PHY_EXT__BEGIN + 4,
+
+ /// Jamming detection history bitmap (for debugging)
+ /** Format: `LL` (read-only)
+ *
+ * This value provides information about current state of jamming detection
+ * module for monitoring/debugging purpose. It returns a 64-bit value where
+ * each bit corresponds to one second interval starting with bit 0 for the
+ * most recent interval and bit 63 for the oldest intervals (63 sec earlier).
+ * The bit is set to 1 if the jamming detection module observed/detected
+ * high signal level during the corresponding one second interval.
+ *
+ * The value is read-only and is encoded as two uint32 values in
+ * little-endian format (first uint32 gives the lower bits corresponding to
+ * more recent history).
+ */
+ SPINEL_PROP_JAM_DETECT_HISTORY_BITMAP
+ = SPINEL_PROP_PHY_EXT__BEGIN + 5,
+
+ SPINEL_PROP_PHY_EXT__END = 0x1300,
+
+ SPINEL_PROP_MAC__BEGIN = 0x30,
+ SPINEL_PROP_MAC_SCAN_STATE = SPINEL_PROP_MAC__BEGIN + 0, ///< [C]
+ SPINEL_PROP_MAC_SCAN_MASK = SPINEL_PROP_MAC__BEGIN + 1, ///< [A(C)]
+ SPINEL_PROP_MAC_SCAN_PERIOD = SPINEL_PROP_MAC__BEGIN + 2, ///< ms-per-channel [S]
+ SPINEL_PROP_MAC_SCAN_BEACON = SPINEL_PROP_MAC__BEGIN + 3, ///< chan,rssi,(laddr,saddr,panid,lqi),(proto,xtra) [CcT(ESSC.)T(i).]
+ SPINEL_PROP_MAC_15_4_LADDR = SPINEL_PROP_MAC__BEGIN + 4, ///< [E]
+ SPINEL_PROP_MAC_15_4_SADDR = SPINEL_PROP_MAC__BEGIN + 5, ///< [S]
+ SPINEL_PROP_MAC_15_4_PANID = SPINEL_PROP_MAC__BEGIN + 6, ///< [S]
+ SPINEL_PROP_MAC_RAW_STREAM_ENABLED = SPINEL_PROP_MAC__BEGIN + 7, ///< [C]
+ SPINEL_PROP_MAC_PROMISCUOUS_MODE = SPINEL_PROP_MAC__BEGIN + 8, ///< [C]
+ SPINEL_PROP_MAC_ENERGY_SCAN_RESULT = SPINEL_PROP_MAC__BEGIN + 9, ///< chan,maxRssi [Cc]
+ SPINEL_PROP_MAC__END = 0x40,
+
+ SPINEL_PROP_MAC_EXT__BEGIN = 0x1300,
+ /// MAC Whitelist
+ /** Format: `A(T(Ec))`
+ *
+ * Structure Parameters:
+ *
+ * * `E`: EUI64 address of node
+ * * `c`: Optional fixed RSSI. 127 means not set.
+ */
+ SPINEL_PROP_MAC_WHITELIST = SPINEL_PROP_MAC_EXT__BEGIN + 0,
+
+ /// MAC Whitelist Enabled Flag
+ /** Format: `b`
+ */
+ SPINEL_PROP_MAC_WHITELIST_ENABLED = SPINEL_PROP_MAC_EXT__BEGIN + 1,
+
+ /// MAC Extended Address
+ /** Format: `E`
+ *
+ * Specified by Thread. Randomly-chosen, but non-volatile EUI-64.
+ */
+ SPINEL_PROP_MAC_EXTENDED_ADDR = SPINEL_PROP_MAC_EXT__BEGIN + 2,
+ SPINEL_PROP_MAC_EXT__END = 0x1400,
+
+ SPINEL_PROP_NET__BEGIN = 0x40,
+ SPINEL_PROP_NET_SAVED = SPINEL_PROP_NET__BEGIN + 0, ///< [b]
+ SPINEL_PROP_NET_IF_UP = SPINEL_PROP_NET__BEGIN + 1, ///< [b]
+ SPINEL_PROP_NET_STACK_UP = SPINEL_PROP_NET__BEGIN + 2, ///< [b]
+ SPINEL_PROP_NET_ROLE = SPINEL_PROP_NET__BEGIN + 3, ///< [C]
+ SPINEL_PROP_NET_NETWORK_NAME = SPINEL_PROP_NET__BEGIN + 4, ///< [U]
+ SPINEL_PROP_NET_XPANID = SPINEL_PROP_NET__BEGIN + 5, ///< [D]
+ SPINEL_PROP_NET_MASTER_KEY = SPINEL_PROP_NET__BEGIN + 6, ///< [D]
+ SPINEL_PROP_NET_KEY_SEQUENCE_COUNTER
+ = SPINEL_PROP_NET__BEGIN + 7, ///< [L]
+ SPINEL_PROP_NET_PARTITION_ID = SPINEL_PROP_NET__BEGIN + 8, ///< [L]
+
+ /// Require Join Existing
+ /** Format: `b`
+ * Default Value: `false`
+ *
+ * This flag is typically used for nodes that are associating with an
+ * existing network for the first time. If this is set to `true` before
+ * `PROP_NET_STACK_UP` is set to `true`, the
+ * creation of a new partition at association is prevented. If the node
+ * cannot associate with an existing partition, `PROP_LAST_STATUS` will
+ * emit a status that indicates why the association failed and
+ * `PROP_NET_STACK_UP` will automatically revert to `false`.
+ *
+ * Once associated with an existing partition, this flag automatically
+ * reverts to `false`.
+ *
+ * The behavior of this property being set to `true` when
+ * `PROP_NET_STACK_UP` is already set to `true` is undefined.
+ */
+ SPINEL_PROP_NET_REQUIRE_JOIN_EXISTING
+ = SPINEL_PROP_NET__BEGIN + 9,
+
+ SPINEL_PROP_NET_KEY_SWITCH_GUARDTIME
+ = SPINEL_PROP_NET__BEGIN + 10, ///< [L]
+
+ SPINEL_PROP_NET__END = 0x50,
+
+ SPINEL_PROP_THREAD__BEGIN = 0x50,
+ SPINEL_PROP_THREAD_LEADER_ADDR = SPINEL_PROP_THREAD__BEGIN + 0, ///< [6]
+ SPINEL_PROP_THREAD_PARENT = SPINEL_PROP_THREAD__BEGIN + 1, ///< LADDR, SADDR [ES]
+ SPINEL_PROP_THREAD_CHILD_TABLE = SPINEL_PROP_THREAD__BEGIN + 2, ///< array(EUI64,rloc16,timeout,age,netDataVer,inLqi,aveRSS,mode) [A(T(ESLLCCcC))]
+ SPINEL_PROP_THREAD_LEADER_RID = SPINEL_PROP_THREAD__BEGIN + 3, ///< [C]
+ SPINEL_PROP_THREAD_LEADER_WEIGHT = SPINEL_PROP_THREAD__BEGIN + 4, ///< [C]
+ SPINEL_PROP_THREAD_LOCAL_LEADER_WEIGHT
+ = SPINEL_PROP_THREAD__BEGIN + 5, ///< [C]
+ SPINEL_PROP_THREAD_NETWORK_DATA = SPINEL_PROP_THREAD__BEGIN + 6, ///< [D]
+ SPINEL_PROP_THREAD_NETWORK_DATA_VERSION
+ = SPINEL_PROP_THREAD__BEGIN + 7, ///< [S]
+ SPINEL_PROP_THREAD_STABLE_NETWORK_DATA
+ = SPINEL_PROP_THREAD__BEGIN + 8, ///< [D]
+ SPINEL_PROP_THREAD_STABLE_NETWORK_DATA_VERSION
+ = SPINEL_PROP_THREAD__BEGIN + 9, ///< [S]
+ SPINEL_PROP_THREAD_ON_MESH_NETS = SPINEL_PROP_THREAD__BEGIN + 10, ///< array(ipv6prefix,prefixlen,stable,flags) [A(T(6CbC))]
+ SPINEL_PROP_THREAD_LOCAL_ROUTES = SPINEL_PROP_THREAD__BEGIN + 11, ///< array(ipv6prefix,prefixlen,stable,flags) [A(T(6CbC))]
+ SPINEL_PROP_THREAD_ASSISTING_PORTS = SPINEL_PROP_THREAD__BEGIN + 12, ///< array(portn) [A(S)]
+ SPINEL_PROP_THREAD_ALLOW_LOCAL_NET_DATA_CHANGE
+ = SPINEL_PROP_THREAD__BEGIN + 13, ///< [b]
+
+ /// Thread Mode
+ /** Format: `C`
+ *
+ * This property contains the value of the mode
+ * TLV for this node. The meaning of the bits in this
+ * bitfield are defined by section 4.5.2 of the Thread
+ * specification.
+ */
+ SPINEL_PROP_THREAD_MODE = SPINEL_PROP_THREAD__BEGIN + 14,
+ SPINEL_PROP_THREAD__END = 0x60,
+
+ SPINEL_PROP_THREAD_EXT__BEGIN = 0x1500,
+
+ /// Thread Child Timeout
+ /** Format: `L`
+ *
+ * Used when operating in the Child role.
+ */
+ SPINEL_PROP_THREAD_CHILD_TIMEOUT = SPINEL_PROP_THREAD_EXT__BEGIN + 0,
+
+ /// Thread RLOC16
+ /** Format: `S`
+ */
+ SPINEL_PROP_THREAD_RLOC16 = SPINEL_PROP_THREAD_EXT__BEGIN + 1,
+
+ /// Thread Router Upgrade Threshold
+ /** Format: `C`
+ */
+ SPINEL_PROP_THREAD_ROUTER_UPGRADE_THRESHOLD
+ = SPINEL_PROP_THREAD_EXT__BEGIN + 2,
+
+ /// Thread Context Reuse Delay
+ /** Format: `L`
+ */
+ SPINEL_PROP_THREAD_CONTEXT_REUSE_DELAY
+ = SPINEL_PROP_THREAD_EXT__BEGIN + 3,
+
+ /// Thread Network ID Timeout
+ /** Format: `C`
+ */
+ SPINEL_PROP_THREAD_NETWORK_ID_TIMEOUT
+ = SPINEL_PROP_THREAD_EXT__BEGIN + 4,
+
+ /// List of active thread router ids
+ /** Format: `A(C)`
+ *
+ * Note that some implementations may not support CMD_GET_VALUE
+ * routerids, but may support CMD_REMOVE_VALUE when the node is
+ * a leader.
+ */
+ SPINEL_PROP_THREAD_ACTIVE_ROUTER_IDS
+ = SPINEL_PROP_THREAD_EXT__BEGIN + 5,
+
+ /// Forward IPv6 packets that use RLOC16 addresses to HOST.
+ /** Format: `b`
+ */
+ SPINEL_PROP_THREAD_RLOC16_DEBUG_PASSTHRU
+ = SPINEL_PROP_THREAD_EXT__BEGIN + 6,
+
+ /// This property indicates whether or not the `Router Role` is enabled.
+ /** Format `b`
+ */
+ SPINEL_PROP_THREAD_ROUTER_ROLE_ENABLED
+ = SPINEL_PROP_THREAD_EXT__BEGIN + 7,
+
+ /// Thread Router Downgrade Threshold
+ /** Format: `C`
+ */
+ SPINEL_PROP_THREAD_ROUTER_DOWNGRADE_THRESHOLD
+ = SPINEL_PROP_THREAD_EXT__BEGIN + 8,
+
+ /// Thread Router Selection Jitter
+ /** Format: `C`
+ */
+ SPINEL_PROP_THREAD_ROUTER_SELECTION_JITTER
+ = SPINEL_PROP_THREAD_EXT__BEGIN + 9,
+
+ /// Thread Preferred Router Id
+ /** Format: `C` - Write only
+ */
+ SPINEL_PROP_THREAD_PREFERRED_ROUTER_ID
+ = SPINEL_PROP_THREAD_EXT__BEGIN + 10,
+
+ /// Thread Neighbor Table
+ /** Format: `A(T(ESLCcCbLL))`
+ * eui64, rloc16, age, inLqi ,aveRSS, mode, isChild. linkFrameCounter, mleCounter
+ */
+ SPINEL_PROP_THREAD_NEIGHBOR_TABLE = SPINEL_PROP_THREAD_EXT__BEGIN + 11,
+
+ /// Thread Max Child Count
+ /** Format: `C`
+ */
+ SPINEL_PROP_THREAD_CHILD_COUNT_MAX = SPINEL_PROP_THREAD_EXT__BEGIN + 12,
+
+ /// Leader network data
+ /** Format: `D` - Read only
+ */
+ SPINEL_PROP_THREAD_LEADER_NETWORK_DATA
+ = SPINEL_PROP_THREAD_EXT__BEGIN + 13,
+
+ /// Stable leader network data
+ /** Format: `D` - Read only
+ */
+ SPINEL_PROP_THREAD_STABLE_LEADER_NETWORK_DATA
+ = SPINEL_PROP_THREAD_EXT__BEGIN + 14,
+
+ SPINEL_PROP_THREAD_EXT__END = 0x1600,
+
+ SPINEL_PROP_IPV6__BEGIN = 0x60,
+ SPINEL_PROP_IPV6_LL_ADDR = SPINEL_PROP_IPV6__BEGIN + 0, ///< [6]
+ SPINEL_PROP_IPV6_ML_ADDR = SPINEL_PROP_IPV6__BEGIN + 1, ///< [6C]
+ SPINEL_PROP_IPV6_ML_PREFIX = SPINEL_PROP_IPV6__BEGIN + 2, ///< [6C]
+ SPINEL_PROP_IPV6_ADDRESS_TABLE = SPINEL_PROP_IPV6__BEGIN + 3, ///< array(ipv6addr,prefixlen,valid,preferred,flags) [A(T(6CLLC))]
+ SPINEL_PROP_IPV6_ROUTE_TABLE = SPINEL_PROP_IPV6__BEGIN + 4, ///< array(ipv6prefix,prefixlen,iface,flags) [A(T(6CCC))]
+
+
+ /// IPv6 ICMP Ping Offload
+ /** Format: `b`
+ *
+ * Allow the NCP to directly respond to ICMP ping requests. If this is
+ * turned on, ping request ICMP packets will not be passed to the host.
+ *
+ * Default value is `false`.
+ */
+ SPINEL_PROP_IPV6_ICMP_PING_OFFLOAD = SPINEL_PROP_IPV6__BEGIN + 5, ///< [b]
+
+ SPINEL_PROP_IPV6__END = 0x70,
+
+ SPINEL_PROP_STREAM__BEGIN = 0x70,
+ SPINEL_PROP_STREAM_DEBUG = SPINEL_PROP_STREAM__BEGIN + 0, ///< [U]
+ SPINEL_PROP_STREAM_RAW = SPINEL_PROP_STREAM__BEGIN + 1, ///< [D]
+ SPINEL_PROP_STREAM_NET = SPINEL_PROP_STREAM__BEGIN + 2, ///< [D]
+ SPINEL_PROP_STREAM_NET_INSECURE = SPINEL_PROP_STREAM__BEGIN + 3, ///< [D]
+ SPINEL_PROP_STREAM__END = 0x80,
+
+
+ /// UART Bitrate
+ /** Format: `L`
+ *
+ * If the NCP is using a UART to communicate with the host,
+ * this property allows the host to change the bitrate
+ * of the serial connection. The value encoding is `L`,
+ * which is a little-endian 32-bit unsigned integer.
+ * The host should not assume that all possible numeric values
+ * are supported.
+ *
+ * If implemented by the NCP, this property should be persistent
+ * across software resets and forgotten upon hardware resets.
+ *
+ * This property is only implemented when a UART is being
+ * used for Spinel. This property is optional.
+ *
+ * When changing the bitrate, all frames will be received
+ * at the previous bitrate until the response frame to this command
+ * is received. Once a successful response frame is received by
+ * the host, all further frames will be transmitted at the new
+ * bitrate.
+ */
+ SPINEL_PROP_UART_BITRATE = 0x100,
+
+ /// UART Software Flow Control
+ /** Format: `b`
+ *
+ * If the NCP is using a UART to communicate with the host,
+ * this property allows the host to determine if software flow
+ * control (XON/XOFF style) should be used and (optionally) to
+ * turn it on or off.
+ *
+ * This property is only implemented when a UART is being
+ * used for Spinel. This property is optional.
+ */
+ SPINEL_PROP_UART_XON_XOFF = 0x101,
+
+ SPINEL_PROP_15_4_PIB__BEGIN = 1024,
+ // For direct access to the 802.15.4 PID.
+ // Individual registers are fetched using
+ // `SPINEL_PROP_15_4_PIB__BEGIN+[PIB_IDENTIFIER]`
+ // Only supported if SPINEL_CAP_15_4_PIB is set.
+ //
+ // For brevity, the entire 802.15.4 PIB space is
+ // not defined here, but a few choice attributes
+ // are defined for illustration and convenience.
+ SPINEL_PROP_15_4_PIB_PHY_CHANNELS_SUPPORTED = SPINEL_PROP_15_4_PIB__BEGIN + 0x01, ///< [A(L)]
+ SPINEL_PROP_15_4_PIB_MAC_PROMISCUOUS_MODE = SPINEL_PROP_15_4_PIB__BEGIN + 0x51, ///< [b]
+ SPINEL_PROP_15_4_PIB_MAC_SECURITY_ENABLED = SPINEL_PROP_15_4_PIB__BEGIN + 0x5d, ///< [b]
+ SPINEL_PROP_15_4_PIB__END = 1280,
+
+ SPINEL_PROP_CNTR__BEGIN = 1280,
+
+ /// Counter reset behavior
+ /** Format: `C`
+ * Writing a '1' to this property will reset
+ * all of the counters to zero. */
+ SPINEL_PROP_CNTR_RESET = SPINEL_PROP_CNTR__BEGIN + 0,
+
+ /// The total number of transmissions.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_TX_PKT_TOTAL = SPINEL_PROP_CNTR__BEGIN + 1,
+
+ /// The number of transmissions with ack request.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_TX_PKT_ACK_REQ = SPINEL_PROP_CNTR__BEGIN + 2,
+
+ /// The number of transmissions that were acked.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_TX_PKT_ACKED = SPINEL_PROP_CNTR__BEGIN + 3,
+
+ /// The number of transmissions without ack request.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_TX_PKT_NO_ACK_REQ = SPINEL_PROP_CNTR__BEGIN + 4,
+
+ /// The number of transmitted data.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_TX_PKT_DATA = SPINEL_PROP_CNTR__BEGIN + 5,
+
+ /// The number of transmitted data poll.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_TX_PKT_DATA_POLL = SPINEL_PROP_CNTR__BEGIN + 6,
+
+ /// The number of transmitted beacon.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_TX_PKT_BEACON = SPINEL_PROP_CNTR__BEGIN + 7,
+
+ /// The number of transmitted beacon request.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_TX_PKT_BEACON_REQ = SPINEL_PROP_CNTR__BEGIN + 8,
+
+ /// The number of transmitted other types of frames.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_TX_PKT_OTHER = SPINEL_PROP_CNTR__BEGIN + 9,
+
+ /// The number of retransmission times.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_TX_PKT_RETRY = SPINEL_PROP_CNTR__BEGIN + 10,
+
+ /// The number of CCA failure times.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_TX_ERR_CCA = SPINEL_PROP_CNTR__BEGIN + 11,
+
+ /// The number of unicast packets transmitted.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_TX_PKT_UNICAST = SPINEL_PROP_CNTR__BEGIN + 12,
+
+ /// The number of broadcast packets transmitted.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_TX_PKT_BROADCAST = SPINEL_PROP_CNTR__BEGIN + 13,
+
+ /// The number of frame transmission failures due to abort error.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_TX_ERR_ABORT = SPINEL_PROP_CNTR__BEGIN + 14,
+
+ /// The total number of received packets.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_RX_PKT_TOTAL = SPINEL_PROP_CNTR__BEGIN + 100,
+
+ /// The number of received data.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_RX_PKT_DATA = SPINEL_PROP_CNTR__BEGIN + 101,
+
+ /// The number of received data poll.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_RX_PKT_DATA_POLL = SPINEL_PROP_CNTR__BEGIN + 102,
+
+ /// The number of received beacon.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_RX_PKT_BEACON = SPINEL_PROP_CNTR__BEGIN + 103,
+
+ /// The number of received beacon request.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_RX_PKT_BEACON_REQ = SPINEL_PROP_CNTR__BEGIN + 104,
+
+ /// The number of received other types of frames.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_RX_PKT_OTHER = SPINEL_PROP_CNTR__BEGIN + 105,
+
+ /// The number of received packets filtered by whitelist.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_RX_PKT_FILT_WL = SPINEL_PROP_CNTR__BEGIN + 106,
+
+ /// The number of received packets filtered by destination check.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_RX_PKT_FILT_DA = SPINEL_PROP_CNTR__BEGIN + 107,
+
+ /// The number of received packets that are empty.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_RX_ERR_EMPTY = SPINEL_PROP_CNTR__BEGIN + 108,
+
+ /// The number of received packets from an unknown neighbor.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_RX_ERR_UKWN_NBR = SPINEL_PROP_CNTR__BEGIN + 109,
+
+ /// The number of received packets whose source address is invalid.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_RX_ERR_NVLD_SADDR = SPINEL_PROP_CNTR__BEGIN + 110,
+
+ /// The number of received packets with a security error.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_RX_ERR_SECURITY = SPINEL_PROP_CNTR__BEGIN + 111,
+
+ /// The number of received packets with a checksum error.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_RX_ERR_BAD_FCS = SPINEL_PROP_CNTR__BEGIN + 112,
+
+ /// The number of received packets with other errors.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_RX_ERR_OTHER = SPINEL_PROP_CNTR__BEGIN + 113,
+
+ /// The number of received duplicated.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_RX_PKT_DUP = SPINEL_PROP_CNTR__BEGIN + 114,
+
+ /// The number of unicast packets recived.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_RX_PKT_UNICAST = SPINEL_PROP_CNTR__BEGIN + 115,
+
+ /// The number of broadcast packets recived.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_RX_PKT_BROADCAST = SPINEL_PROP_CNTR__BEGIN + 116,
+
+ /// The total number of secure transmitted IP messages.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_TX_IP_SEC_TOTAL = SPINEL_PROP_CNTR__BEGIN + 200,
+
+ /// The total number of insecure transmitted IP messages.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_TX_IP_INSEC_TOTAL = SPINEL_PROP_CNTR__BEGIN + 201,
+
+ /// The number of dropped (not transmitted) IP messages.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_TX_IP_DROPPED = SPINEL_PROP_CNTR__BEGIN + 202,
+
+ /// The total number of secure received IP message.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_RX_IP_SEC_TOTAL = SPINEL_PROP_CNTR__BEGIN + 203,
+
+ /// The total number of insecure received IP message.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_RX_IP_INSEC_TOTAL = SPINEL_PROP_CNTR__BEGIN + 204,
+
+ /// The number of dropped received IP messages.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_RX_IP_DROPPED = SPINEL_PROP_CNTR__BEGIN + 205,
+
+ /// The number of transmitted spinel frames.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_TX_SPINEL_TOTAL = SPINEL_PROP_CNTR__BEGIN + 300,
+
+ /// The number of received spinel frames.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_RX_SPINEL_TOTAL = SPINEL_PROP_CNTR__BEGIN + 301,
+
+ /// The number of received spinel frames with error.
+ /** Format: `L` (Read-only) */
+ SPINEL_PROP_CNTR_RX_SPINEL_ERR = SPINEL_PROP_CNTR__BEGIN + 302,
+
+
+
+ /// The message buffer counter info
+ /** Format: `T(SSSSSSSSSSSSSSSS)` (Read-only)
+ * `T(`
+ * `S`, (TotalBuffers) The number of buffers in the pool.
+ * `S`, (FreeBuffers) The number of free message buffers.
+ * `S`, (6loSendMessages) The number of messages in the 6lo send queue.
+ * `S`, (6loSendBuffers) The number of buffers in the 6lo send queue.
+ * `S`, (6loReassemblyMessages) The number of messages in the 6LoWPAN reassembly queue.
+ * `S`, (6loReassemblyBuffers) The number of buffers in the 6LoWPAN reassembly queue.
+ * `S`, (Ip6Messages) The number of messages in the IPv6 send queue.
+ * `S`, (Ip6Buffers) The number of buffers in the IPv6 send queue.
+ * `S`, (MplMessages) The number of messages in the MPL send queue.
+ * `S`, (MplBuffers) The number of buffers in the MPL send queue.
+ * `S`, (MleMessages) The number of messages in the MLE send queue.
+ * `S`, (MleBuffers) The number of buffers in the MLE send queue.
+ * `S`, (ArpMessages) The number of messages in the ARP send queue.
+ * `S`, (ArpBuffers) The number of buffers in the ARP send queue.
+ * `S`, (CoapClientMessages) The number of messages in the CoAP client send queue.
+ * `S`, (CoapClientBuffers) The number of buffers in the CoAP client send queue.
+ * `)`
+ */
+ SPINEL_PROP_MSG_BUFFER_COUNTERS = SPINEL_PROP_CNTR__BEGIN + 400,
+
+ SPINEL_PROP_CNTR__END = 2048,
+
+ SPINEL_PROP_NEST__BEGIN = 15296,
+ SPINEL_PROP_NEST_STREAM_MFG = SPINEL_PROP_NEST__BEGIN + 0,
+
+ /// The legacy network ULA prefix (8 bytes)
+ /** Format: 'D' */
+ SPINEL_PROP_NEST_LEGACY_ULA_PREFIX
+ = SPINEL_PROP_NEST__BEGIN + 1,
+
+ /// A (newly) joined legacy node (this is signaled from NCP)
+ /** Format: 'E' */
+ SPINEL_PROP_NEST_LEGACY_JOINED_NODE
+ = SPINEL_PROP_NEST__BEGIN + 2,
+
+ SPINEL_PROP_NEST__END = 15360,
+
+ SPINEL_PROP_VENDOR__BEGIN = 15360,
+ SPINEL_PROP_VENDOR__END = 16384,
+
+ SPINEL_PROP_EXPERIMENTAL__BEGIN = 2000000,
+ SPINEL_PROP_EXPERIMENTAL__END = 2097152,
+} spinel_prop_key_t;
+
+// ----------------------------------------------------------------------------
+
+#define SPINEL_HEADER_FLAG 0x80
+
+#define SPINEL_HEADER_TID_SHIFT 0
+#define SPINEL_HEADER_TID_MASK (15 << SPINEL_HEADER_TID_SHIFT)
+
+#define SPINEL_HEADER_IID_SHIFT 4
+#define SPINEL_HEADER_IID_MASK (3 << SPINEL_HEADER_IID_SHIFT)
+
+#define SPINEL_HEADER_IID_0 (0 << SPINEL_HEADER_IID_SHIFT)
+#define SPINEL_HEADER_IID_1 (1 << SPINEL_HEADER_IID_SHIFT)
+#define SPINEL_HEADER_IID_2 (2 << SPINEL_HEADER_IID_SHIFT)
+#define SPINEL_HEADER_IID_3 (3 << SPINEL_HEADER_IID_SHIFT)
+
+#define SPINEL_HEADER_GET_IID(x) (((x) & SPINEL_HEADER_IID_MASK) >> SPINEL_HEADER_IID_SHIFT)
+#define SPINEL_HEADER_GET_TID(x) (spinel_tid_t)(((x)&SPINEL_HEADER_TID_MASK)>>SPINEL_HEADER_TID_SHIFT)
+
+#define SPINEL_GET_NEXT_TID(x) (spinel_tid_t)((x)>=0xF?1:(x)+1)
+
+#define SPINEL_BEACON_THREAD_FLAG_VERSION_SHIFT 4
+#define SPINEL_BEACON_THREAD_FLAG_VERSION_MASK (0xf << SPINEL_BEACON_THREAD_FLAG_VERSION_SHIFT)
+#define SPINEL_BEACON_THREAD_FLAG_JOINABLE (1 << 0)
+#define SPINEL_BEACON_THREAD_FLAG_NATIVE (1 << 3)
+
+// ----------------------------------------------------------------------------
+
+enum
+{
+ SPINEL_DATATYPE_NULL_C = 0,
+ SPINEL_DATATYPE_VOID_C = '.',
+ SPINEL_DATATYPE_BOOL_C = 'b',
+ SPINEL_DATATYPE_UINT8_C = 'C',
+ SPINEL_DATATYPE_INT8_C = 'c',
+ SPINEL_DATATYPE_UINT16_C = 'S',
+ SPINEL_DATATYPE_INT16_C = 's',
+ SPINEL_DATATYPE_UINT32_C = 'L',
+ SPINEL_DATATYPE_INT32_C = 'l',
+ SPINEL_DATATYPE_UINT_PACKED_C = 'i',
+ SPINEL_DATATYPE_IPv6ADDR_C = '6',
+ SPINEL_DATATYPE_EUI64_C = 'E',
+ SPINEL_DATATYPE_EUI48_C = 'e',
+ SPINEL_DATATYPE_DATA_C = 'D',
+ SPINEL_DATATYPE_UTF8_C = 'U', //!< Zero-Terminated UTF8-Encoded String
+ SPINEL_DATATYPE_STRUCT_C = 'T',
+ SPINEL_DATATYPE_ARRAY_C = 'A',
+};
+
+typedef char spinel_datatype_t;
+
+#define SPINEL_DATATYPE_NULL_S ""
+#define SPINEL_DATATYPE_VOID_S "."
+#define SPINEL_DATATYPE_BOOL_S "b"
+#define SPINEL_DATATYPE_UINT8_S "C"
+#define SPINEL_DATATYPE_INT8_S "c"
+#define SPINEL_DATATYPE_UINT16_S "S"
+#define SPINEL_DATATYPE_INT16_S "s"
+#define SPINEL_DATATYPE_UINT32_S "L"
+#define SPINEL_DATATYPE_INT32_S "l"
+#define SPINEL_DATATYPE_UINT_PACKED_S "i"
+#define SPINEL_DATATYPE_IPv6ADDR_S "6"
+#define SPINEL_DATATYPE_EUI64_S "E"
+#define SPINEL_DATATYPE_EUI48_S "e"
+#define SPINEL_DATATYPE_DATA_S "D"
+#define SPINEL_DATATYPE_UTF8_S "U" //!< Zero-Terminated UTF8-Encoded String
+#define SPINEL_DATATYPE_STRUCT_S "T"
+#define SPINEL_DATATYPE_ARRAY_S "A"
+
+SPINEL_API_EXTERN spinel_ssize_t spinel_datatype_pack(uint8_t *data_out, spinel_size_t data_len,
+ const char *pack_format, ...);
+SPINEL_API_EXTERN spinel_ssize_t spinel_datatype_vpack(uint8_t *data_out, spinel_size_t data_len,
+ const char *pack_format, va_list args);
+SPINEL_API_EXTERN spinel_ssize_t spinel_datatype_unpack(const uint8_t *data_in, spinel_size_t data_len,
+ const char *pack_format, ...);
+SPINEL_API_EXTERN spinel_ssize_t spinel_datatype_vunpack(const uint8_t *data_in, spinel_size_t data_len,
+ const char *pack_format, va_list args);
+
+SPINEL_API_EXTERN spinel_ssize_t spinel_packed_uint_decode(const uint8_t *bytes, spinel_size_t len,
+ unsigned int *value);
+SPINEL_API_EXTERN spinel_ssize_t spinel_packed_uint_encode(uint8_t *bytes, spinel_size_t len, unsigned int value);
+SPINEL_API_EXTERN spinel_ssize_t spinel_packed_uint_size(unsigned int value);
+
+SPINEL_API_EXTERN const char *spinel_next_packed_datatype(const char *pack_format);
+
+// ----------------------------------------------------------------------------
+
+SPINEL_API_EXTERN const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key);
+
+SPINEL_API_EXTERN const char *spinel_net_role_to_cstr(uint8_t net_role);
+
+SPINEL_API_EXTERN const char *spinel_status_to_cstr(spinel_status_t status);
+
+// ----------------------------------------------------------------------------
+
+__END_DECLS
+
+#endif /* defined(SPINEL_HEADER_INCLUDED) */
diff --git a/third_party/openthread/tools/spi-hdlc-adapter/.gitignore b/third_party/openthread/tools/spi-hdlc-adapter/.gitignore
new file mode 100644
index 0000000..38124e8
--- /dev/null
+++ b/third_party/openthread/tools/spi-hdlc-adapter/.gitignore
@@ -0,0 +1 @@
+spi-hdlc-adapter
diff --git a/third_party/openthread/tools/spi-hdlc-adapter/README.md b/third_party/openthread/tools/spi-hdlc-adapter/README.md
new file mode 100644
index 0000000..fe2c4da
--- /dev/null
+++ b/third_party/openthread/tools/spi-hdlc-adapter/README.md
@@ -0,0 +1,60 @@
+SPI/HDLC Adaptor
+================
+
+`spi-hdlc-adapter` is an adapter tool for using a SPI interface as if
+it were an HDLC-lite encoded bidirectional asynchronous serial stream.
+It uses the SPI protocol outlined in [Appendix A.2][1] of the Spinel
+protocol document.
+
+[1]: https://goo.gl/gt18O4
+
+## Syntax ##
+
+ spi-hdlc-adapter [options] <spi-device-path>
+
+## Options ##
+
+* `--stdio`: Use `stdin` and `stdout` for HDLC input/output. Useful
+ when directly started by the program that will be using it.
+* `--pty`: Create a pseudo terminal for HDLC input/output. The path
+ of the newly-created PTY will be written to `stdout`, followed by
+ a newline.
+* `--gpio-int[=gpio-path]`: Specify a path to the Linux
+ sysfs-exported GPIO directory for the `IÌ…NÌ…TÌ…` pin. If not
+ specified, `spi-hdlc-adapter` will fall back to polling, which is
+ inefficient.
+* `--gpio-reset[=gpio-path]`: Specify a path to the Linux
+ sysfs-exported GPIO directory for the `RÌ…EÌ…SÌ…` pin.
+* `--spi-mode[=mode]`: Specify the SPI mode to use (0-3).
+* `--spi-speed[=hertz]`: Specify the SPI speed in hertz.
+* `--spi-cs-delay[=usec]`: Specify the delay after CÌ…SÌ… assertion, in
+ microseconds.
+* `--verbose`: Increase debug verbosity.
+* `--help`: Print out usage information to `stdout` and exit.
+
+`spi-device-path` is a required argument since it indicates which SPI
+device to use. An example path might be `/dev/spidev1.0`.
+
+The GPIO paths are to the top-level directory for that GPIO. They must
+be already be exported before `spi-hdlc-adapter` can use them.
+
+## Behavior ##
+
+If an MCU reset is detected by the reset bit being set on a SPI frame,
+the special vendor-specific HDLC-lite symbol `0xF8` is emitted. If
+`--gpio-reset` is specified, the HDLC client can trigger an MCU reset
+by sending the symbols `0x7E 0x13 0x11 0x7E` or by sending `SIGUSR1`.
+
+When started, `spi-hdlc-adapter` will configure the following
+properties on the GPIOs:
+
+1. Set `IÌ…NÌ…TÌ…/direction` to `in`.
+2. Set `IÌ…NÌ…TÌ…/edge` to `falling`.
+3. Set `RÌ…EÌ…SÌ…/direction` to `high`.
+
+When resetting the slave device, `spi-hdlc` performs the following
+procedure:
+
+1. Set `RÌ…EÌ…SÌ…/direction` to `low`.
+2. Sleep for 30ms.
+3. Set `RÌ…EÌ…SÌ…/direction` to `high`.
diff --git a/third_party/openthread/tools/spi-hdlc-adapter/spi-hdlc-adapter.c b/third_party/openthread/tools/spi-hdlc-adapter/spi-hdlc-adapter.c
new file mode 100644
index 0000000..11e0ad4
--- /dev/null
+++ b/third_party/openthread/tools/spi-hdlc-adapter/spi-hdlc-adapter.c
@@ -0,0 +1,1702 @@
+/*
+ * Copyright (c) 2016, The OpenThread Authors.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define _GNU_SOURCE 1
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <syslog.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/select.h>
+#include <sys/ucontext.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+
+#include <linux/spi/spidev.h>
+
+#if HAVE_EXECINFO_H
+#include <execinfo.h>
+#endif
+
+#if HAVE_PTY_H
+#include <pty.h>
+#endif
+
+#if HAVE_UTIL_H
+#include <util.h>
+#endif
+
+/* ------------------------------------------------------------------------- */
+/* MARK: Macros and Constants */
+
+#define SPI_HDLC_VERSION "0.03"
+
+#define MAX_FRAME_SIZE 2048
+#define HEADER_LEN 5
+#define SPI_HEADER_RESET_FLAG 0x80
+#define SPI_HEADER_CRC_FLAG 0x40
+#define SPI_HEADER_PATTERN_VALUE 0x02
+#define SPI_HEADER_PATTERN_MASK 0x03
+
+#define EXIT_QUIT 65535
+
+#ifndef MSEC_PER_SEC
+#define MSEC_PER_SEC 1000
+#endif
+
+#ifndef USEC_PER_MSEC
+#define USEC_PER_MSEC 1000
+#endif
+
+#ifndef USEC_PER_SEC
+#define USEC_PER_SEC (USEC_PER_MSEC * MSEC_PER_SEC)
+#endif
+
+#define SPI_POLL_PERIOD_MSEC (MSEC_PER_SEC/30)
+
+#define GPIO_INT_ASSERT_STATE 0 // IÌ…NÌ…TÌ… is asserted low
+#define GPIO_RES_ASSERT_STATE 0 // RÌ…EÌ…SÌ… is asserted low
+
+#define SPI_RX_ALIGN_ALLOWANCE_MAX 3
+
+#define SOCKET_DEBUG_BYTES_PER_LINE 16
+
+#ifndef AUTO_PRINT_BACKTRACE
+#define AUTO_PRINT_BACKTRACE (HAVE_EXECINFO_H || __APPLE__)
+#endif
+
+#define AUTO_PRINT_BACKTRACE_STACK_DEPTH 20
+
+static const uint8_t kHdlcResetSignal[] = { 0x7E, 0x13, 0x11, 0x7E };
+static const uint16_t kHdlcCrcCheckValue = 0xf0b8;
+static const uint16_t kHdlcCrcResetValue = 0xffff;
+
+enum {
+ MODE_STDIO = 0,
+ MODE_PTY = 1,
+};
+
+// Ignores return value from function 's'
+#define IGNORE_RETURN_VALUE(s) do { if (s){} } while (0)
+
+/* ------------------------------------------------------------------------- */
+/* MARK: Global State */
+
+#if HAVE_OPENPTY
+static int sMode = MODE_PTY;
+#else
+static int sMode = MODE_STDIO;
+#endif
+
+static const char* sSpiDevPath = NULL;
+static const char* sIntGpioDevPath = NULL;
+static const char* sResGpioDevPath = NULL;
+
+static int sVerbose = LOG_NOTICE;
+
+static int sSpiDevFd = -1;
+static int sResGpioValueFd = -1;
+static int sIntGpioValueFd = -1;
+
+static int sHdlcInputFd = -1;
+static int sHdlcOutputFd = -1;
+
+static int sSpiSpeed = 1000000; // in Hz (default: 1MHz)
+static uint8_t sSpiMode = 0;
+static int sSpiCsDelay = 20; // in microseconds
+static int sSpiTransactionDelay = 200; // in microseconds
+
+static uint16_t sSpiRxPayloadSize;
+static uint8_t sSpiRxFrameBuffer[MAX_FRAME_SIZE + SPI_RX_ALIGN_ALLOWANCE_MAX];
+
+static uint16_t sSpiTxPayloadSize;
+static bool sSpiTxIsReady = false;
+static bool sSpiTxFlowControl = false;
+static uint8_t sSpiTxFrameBuffer[MAX_FRAME_SIZE + SPI_RX_ALIGN_ALLOWANCE_MAX];
+
+static int sSpiRxAlignAllowance = 0;
+
+static uint32_t sSpiFrameCount = 0;
+static uint32_t sSpiValidFrameCount = 0;
+
+static bool sSlaveDidReset = false;
+
+static int sRet = 0;
+
+static sig_t sPreviousHandlerForSIGINT;
+static sig_t sPreviousHandlerForSIGTERM;
+
+/* ------------------------------------------------------------------------- */
+/* MARK: Signal Handlers */
+
+static void signal_SIGINT(int sig)
+{
+ static const char message[] = "\nCaught SIGINT!\n";
+
+ sRet = EXIT_QUIT;
+
+ // Can't use syslog() because it isn't async signal safe.
+ // So we write to stderr
+ IGNORE_RETURN_VALUE(write(STDERR_FILENO, message, sizeof(message)-1));
+
+ // Restore the previous handler so that if we end up getting
+ // this signal again we peform the system default action.
+ signal(SIGINT, sPreviousHandlerForSIGINT);
+ sPreviousHandlerForSIGINT = NULL;
+
+ (void)sig;
+}
+
+static void signal_SIGTERM(int sig)
+{
+ static const char message[] = "\nCaught SIGTERM!\n";
+
+ sRet = EXIT_QUIT;
+
+ // Can't use syslog() because it isn't async signal safe.
+ // So we write to stderr
+ IGNORE_RETURN_VALUE(write(STDERR_FILENO, message, sizeof(message)-1));
+
+ // Restore the previous handler so that if we end up getting
+ // this signal again we perform the system default action.
+ signal(SIGTERM, sPreviousHandlerForSIGTERM);
+ sPreviousHandlerForSIGTERM = NULL;
+ (void) sig;
+}
+
+static void signal_SIGHUP(int sig)
+{
+ static const char message[] = "\nCaught SIGHUP!\n";
+
+ sRet = EXIT_FAILURE;
+
+ // Can't use syslog() because it isn't async signal safe.
+ // So we write to stderr
+ IGNORE_RETURN_VALUE(write(STDERR_FILENO, message, sizeof(message)-1));
+
+ // We don't restore the "previous handler"
+ // because we always want to let the main
+ // loop decide what to do for hangups.
+
+ (void) sig;
+}
+
+#if AUTO_PRINT_BACKTRACE
+static void signal_critical(int sig, siginfo_t * info, void * ucontext)
+{
+ // This is the last hurah for this process.
+ // We dump the stack, because that's all we can do.
+
+ void *stack_mem[AUTO_PRINT_BACKTRACE_STACK_DEPTH];
+ void **stack = stack_mem;
+ char **stack_symbols;
+ int stack_depth, i;
+ ucontext_t *uc = (ucontext_t*)ucontext;
+
+ // Shut up compiler warning.
+ (void)uc;
+ (void)info;
+
+ // We call some functions here which aren't async-signal-safe,
+ // but this function isn't really useful without those calls.
+ // Since we are making a gamble (and we deadlock if we loose),
+ // we are going to set up a two-second watchdog to make sure
+ // we end up terminating like we should. The choice of a two
+ // second timeout is entirely arbitrary, and may be changed
+ // if needs warrant.
+ alarm(2);
+ signal(SIGALRM, SIG_DFL);
+
+ fprintf(stderr, " *** FATAL ERROR: Caught signal %d (%s):\n", sig, strsignal(sig));
+
+ stack_depth = backtrace(stack, AUTO_PRINT_BACKTRACE_STACK_DEPTH);
+
+ // Here are are trying to update the pointer in the backtrace
+ // to be the actual location of the fault.
+#if defined(__x86_64__)
+ stack[1] = (void *) uc->uc_mcontext.gregs[REG_RIP];
+#elif defined(__i386__)
+ stack[1] = (void *) uc->uc_mcontext.gregs[REG_EIP];
+#elif defined(__arm__)
+ stack[1] = (void *) uc->uc_mcontext.arm_ip;
+#else
+#warning TODO: Add this arch to signal_critical
+#endif
+
+ // Now dump the symbols to stderr, in case syslog barfs.
+ backtrace_symbols_fd(stack, stack_depth, STDERR_FILENO);
+
+ // Load up the symbols individually, so we can output to syslog, too.
+ stack_symbols = backtrace_symbols(stack, stack_depth);
+
+ syslog(LOG_CRIT, " *** FATAL ERROR: Caught signal %d (%s):", sig, strsignal(sig));
+
+ for (i = 0; i != stack_depth; i++)
+ {
+ syslog(LOG_CRIT, "[BT] %2d: %s", i, stack_symbols[i]);
+ }
+
+ free(stack_symbols);
+
+ exit(EXIT_FAILURE);
+}
+#endif // if AUTO_PRINT_BACKTRACE
+
+static void log_debug_buffer(const char* desc, const uint8_t* buffer_ptr, int buffer_len)
+{
+ int i = 0;
+
+ if (sVerbose < LOG_DEBUG)
+ {
+ return;
+ }
+
+ while (i < buffer_len)
+ {
+ int j;
+ char dump_string[SOCKET_DEBUG_BYTES_PER_LINE*3+1];
+
+ for (j = 0; i < buffer_len && j < SOCKET_DEBUG_BYTES_PER_LINE; i++, j++)
+ {
+ sprintf(dump_string+j*3, "%02X ", buffer_ptr[i]);
+ }
+
+ syslog(LOG_DEBUG, "%s: %s%s", desc, dump_string, (i < buffer_len)?" ...":"");
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+/* MARK: SPI Transfer Functions */
+
+static void spi_header_set_flag_byte(uint8_t *header, uint8_t value)
+{
+ header[0] = value;
+}
+
+static void spi_header_set_accept_len(uint8_t *header, uint16_t len)
+{
+ header[1] = ((len >> 0) & 0xFF);
+ header[2] = ((len >> 8) & 0xFF);
+}
+
+static void spi_header_set_data_len(uint8_t *header, uint16_t len)
+{
+ header[3] = ((len >> 0) & 0xFF);
+ header[4] = ((len >> 8) & 0xFF);
+}
+
+static uint8_t spi_header_get_flag_byte(const uint8_t *header)
+{
+ return header[0];
+}
+
+static uint16_t spi_header_get_accept_len(const uint8_t *header)
+{
+ return ( header[1] + (uint16_t)(header[2] << 8) );
+}
+
+static uint16_t spi_header_get_data_len(const uint8_t *header)
+{
+ return ( header[3] + (uint16_t)(header[4] << 8) );
+}
+
+static uint8_t* get_real_rx_frame_start(void)
+{
+ uint8_t* ret = sSpiRxFrameBuffer;
+ int i = 0;
+
+ for (i = 0; i < sSpiRxAlignAllowance; i++)
+ {
+ if (ret[0] != 0xFF)
+ {
+ break;
+ }
+ ret++;
+ }
+
+ return ret;
+}
+
+static int do_spi_xfer(int len)
+ {
+ int ret;
+
+ struct spi_ioc_transfer xfer[2] =
+ {
+ { // This part is the delay between CÌ…SÌ… being
+ // asserted and the SPI clock starting. This
+ // is not supported by all Linux SPI drivers.
+ .tx_buf = 0,
+ .rx_buf = 0,
+ .len = 0,
+ .delay_usecs = (uint16_t)sSpiCsDelay,
+ .speed_hz = (uint32_t)sSpiSpeed,
+ .bits_per_word = 8,
+ .cs_change = false,
+ },
+ { // This part is the actual SPI transfer.
+ .tx_buf = (unsigned long)sSpiTxFrameBuffer,
+ .rx_buf = (unsigned long)sSpiRxFrameBuffer,
+ .len = (uint32_t)(len + HEADER_LEN + sSpiRxAlignAllowance),
+ .delay_usecs = 0,
+ .speed_hz = (uint32_t)sSpiSpeed,
+ .bits_per_word = 8,
+ .cs_change = false,
+ }
+ };
+
+ if (sSpiCsDelay > 0)
+ {
+ // A CÌ…SÌ… delay has been specified. Start transactions
+ // with both parts.
+ ret = ioctl(sSpiDevFd, SPI_IOC_MESSAGE(2), &xfer[0]);
+ }
+ else
+ {
+ // No CÌ…SÌ… delay has been specified, so we skip the first
+ // part because it causes some SPI drivers to croak.
+ ret = ioctl(sSpiDevFd, SPI_IOC_MESSAGE(1), &xfer[1]);
+ }
+
+ if (ret != -1)
+ {
+ log_debug_buffer("SPI-TX", sSpiTxFrameBuffer, (int)xfer[1].len);
+ log_debug_buffer("SPI-RX", sSpiRxFrameBuffer, (int)xfer[1].len);
+
+ if (spi_header_get_flag_byte(sSpiRxFrameBuffer) != 0xFF)
+ {
+ if (spi_header_get_flag_byte(sSpiRxFrameBuffer) & SPI_HEADER_RESET_FLAG)
+ {
+ sSlaveDidReset = true;
+ }
+ }
+
+ sSpiFrameCount++;
+ }
+
+ return ret;
+}
+
+static void debug_spi_header(const char* hint)
+{
+ if (sVerbose >= LOG_DEBUG)
+ {
+ const uint8_t* spiRxFrameBuffer = get_real_rx_frame_start();
+
+ syslog(LOG_DEBUG, "%s-TX: H:%02X ACCEPT:%d DATA:%0d\n",
+ hint,
+ spi_header_get_flag_byte(sSpiTxFrameBuffer),
+ spi_header_get_accept_len(sSpiTxFrameBuffer),
+ spi_header_get_data_len(sSpiTxFrameBuffer)
+ );
+
+ syslog(LOG_DEBUG, "%s-RX: H:%02X ACCEPT:%d DATA:%0d\n",
+ hint,
+ spi_header_get_flag_byte(spiRxFrameBuffer),
+ spi_header_get_accept_len(spiRxFrameBuffer),
+ spi_header_get_data_len(spiRxFrameBuffer)
+ );
+ }
+}
+
+static int push_pull_spi(void)
+{
+ int ret;
+ uint8_t slave_header;
+ uint16_t slave_max_rx;
+ uint16_t slave_data_len;
+ uint16_t spi_xfer_bytes = 5;
+ const uint8_t* spiRxFrameBuffer = NULL;
+
+ sSpiTxFlowControl = false;
+
+ /// -- FIRST TRANSACTION --------------------------------------------------
+
+ // The purpose of the first transaction is to attempt to
+ // send any transactions we have queued and fetch the slave's
+ // buffer sizes.
+
+ if (sSpiValidFrameCount == 0)
+ {
+ spi_header_set_flag_byte(sSpiTxFrameBuffer, SPI_HEADER_RESET_FLAG|SPI_HEADER_PATTERN_VALUE);
+ }
+ else
+ {
+ spi_header_set_flag_byte(sSpiTxFrameBuffer, SPI_HEADER_PATTERN_VALUE);
+ }
+
+ // Zero out our max rx and data len
+ // so that the slave doesn't think
+ // we are actually trying to transfer
+ // data.
+ spi_header_set_accept_len(sSpiTxFrameBuffer, 0);
+ spi_header_set_data_len(sSpiTxFrameBuffer, 0);
+
+ if (sSpiTxIsReady)
+ {
+ // Go ahead and try to immediately send a frame if we have it queued up.
+ spi_header_set_data_len(sSpiTxFrameBuffer, sSpiTxPayloadSize);
+
+ if (sSpiTxPayloadSize > spi_xfer_bytes)
+ {
+ spi_xfer_bytes = sSpiTxPayloadSize;
+ }
+ }
+
+ // If we aren't already processing a received frame, we
+ // can also handle receiving the next frame if its length
+ // is equal to or less than the size of what we are
+ // trying to transmit above.
+ if (sSpiRxPayloadSize == 0) {
+ spi_header_set_accept_len(sSpiTxFrameBuffer, spi_xfer_bytes);
+ }
+
+ // Perform the first SPI transaction.
+ ret = do_spi_xfer(spi_xfer_bytes);
+ if (ret < 0)
+ {
+ perror("do_spi_xfer");
+
+ // Print out a helpful error message for
+ // a common error.
+ if ( (sSpiCsDelay != 0)
+ && (errno == EINVAL)
+ ) {
+ syslog(LOG_ERR, "SPI ioctl failed with EINVAL. Try adding `--spi-cs-delay=0` to command line arguments.");
+ }
+ goto bail;
+ }
+
+ // Account for misalignment (0xFF bytes at the start)
+ spiRxFrameBuffer = get_real_rx_frame_start();
+
+ debug_spi_header("push_pull_1");
+
+ slave_header = spi_header_get_flag_byte(spiRxFrameBuffer);
+
+ if ((slave_header == 0xFF) || (slave_header == 0x00))
+ {
+ // Device is off or in a bad state.
+ sSpiTxFlowControl = true;
+
+ syslog(LOG_DEBUG, "Discarded frame. (1)");
+ goto bail;
+ }
+
+ slave_max_rx = spi_header_get_accept_len(spiRxFrameBuffer);
+ slave_data_len = spi_header_get_data_len(spiRxFrameBuffer);
+
+ if ( ((slave_header & SPI_HEADER_PATTERN_MASK) != SPI_HEADER_PATTERN_VALUE)
+ || (slave_max_rx > MAX_FRAME_SIZE)
+ || (slave_data_len > MAX_FRAME_SIZE)
+ )
+ {
+ sSpiTxFlowControl = true;
+ syslog(
+ LOG_INFO,
+ "Gibberish in header (h:0x%02X, max_rx:0x%04X, data_len:0x%04X)",
+ slave_header,
+ slave_max_rx,
+ slave_data_len
+ );
+ goto bail;
+ }
+
+ sSpiValidFrameCount++;
+
+ // Handle received packet, if any.
+ if ( (sSpiRxPayloadSize == 0)
+ && (slave_data_len != 0)
+ && (slave_data_len <= spi_header_get_accept_len(sSpiTxFrameBuffer))
+ ) {
+ // We have received a packet. Set sSpiRxPayloadSize so that
+ // the packet will eventually get queued up by push_hdlc().
+ sSpiRxPayloadSize = slave_data_len;
+
+ slave_data_len = 0;
+ }
+
+ if (sSpiTxIsReady)
+ {
+ // Handle transmitted packet.
+ if (spi_header_get_data_len(sSpiTxFrameBuffer) <= slave_max_rx)
+ {
+ // Outbound packet has been successfully transmitted. Clear
+ // sSpiTxPayloadSize and sSpiTxIsReady so that pull_hdlc() can
+ // pull another packet for us to send.
+ sSpiTxIsReady = false;
+ sSpiTxPayloadSize = 0;
+ spi_header_set_data_len(sSpiTxFrameBuffer, 0);
+ spi_xfer_bytes = 0;
+ } else {
+ // The slave Wasn't ready for what we had to
+ // send them. Turn on rate limiting so that we
+ // don't waste a ton of CPU bombarding them
+ // with useless SPI transfers.
+ sSpiTxFlowControl = true;
+ }
+ }
+
+ if (slave_data_len == 0)
+ {
+ // Nothing else to do.
+ goto bail;
+ }
+
+ /// -- SECOND TRANSACTION ------------------------------------------------
+
+ // The purpose of the second transaction is to attempt to
+ // fetch any packets that the slave has for us that didn't
+ // fit in the first transaction.
+
+ spi_header_set_flag_byte(sSpiTxFrameBuffer, SPI_HEADER_PATTERN_VALUE);
+ spi_header_set_accept_len(sSpiTxFrameBuffer, 0);
+
+ if (sSpiTxIsReady)
+ {
+ spi_xfer_bytes = sSpiTxPayloadSize;
+ spi_header_set_data_len(sSpiTxFrameBuffer, sSpiTxPayloadSize);
+
+ } else {
+ spi_xfer_bytes = 0;
+ }
+
+ if ( (slave_data_len != 0)
+ && (sSpiRxPayloadSize == 0)
+ )
+ {
+ spi_header_set_accept_len(sSpiTxFrameBuffer, slave_data_len);
+ if (slave_data_len > spi_xfer_bytes)
+ {
+ spi_xfer_bytes = slave_data_len;
+ }
+ }
+
+ // Optionally delay a short period to give
+ // the slave time to get its affairs in order.
+ usleep((unsigned int)sSpiTransactionDelay);
+
+ // Perform the second SPI transaction.
+ ret = do_spi_xfer(spi_xfer_bytes);
+ if (ret < 0)
+ {
+ perror("do_spi_xfer");
+
+ // Print out a helpful error message for
+ // a common error.
+ if ( (sSpiCsDelay != 0)
+ && (errno == EINVAL)
+ ) {
+ syslog(LOG_ERR, "SPI ioctl failed with EINVAL. Try adding `--spi-cs-delay=0` to command line arguments.");
+ }
+ goto bail;
+ }
+
+ // Account for misalignment (0xFF bytes at the start)
+ spiRxFrameBuffer = get_real_rx_frame_start();
+
+ debug_spi_header("push_pull_2");
+
+ slave_header = spi_header_get_flag_byte(spiRxFrameBuffer);
+
+ if ((slave_header == 0xFF) || (slave_header == 0x00))
+ {
+ // Device is off or in a bad state.
+ sSpiTxFlowControl = true;
+
+ syslog(LOG_DEBUG, "Discarded frame. (2)");
+ goto bail;
+ }
+
+ slave_max_rx = spi_header_get_accept_len(spiRxFrameBuffer);
+ slave_data_len = spi_header_get_data_len(spiRxFrameBuffer);
+
+ if ( (slave_header != SPI_HEADER_PATTERN_VALUE)
+ || (slave_max_rx > MAX_FRAME_SIZE)
+ || (slave_data_len > MAX_FRAME_SIZE)
+ )
+ {
+ sSpiTxFlowControl = true;
+ syslog(
+ LOG_INFO,
+ "Gibberish in header (h:0x%02X, max_rx:0x%04X, data_len:0x%04X) (2)",
+ slave_header,
+ slave_max_rx,
+ slave_data_len
+ );
+ goto bail;
+ }
+
+ sSpiValidFrameCount++;
+
+ if ( (sSpiRxPayloadSize == 0)
+ && (slave_data_len <= spi_header_get_accept_len(sSpiTxFrameBuffer))
+ ) {
+ // We have received a packet. Set sSpiRxPayloadSize so that
+ // the packet will eventually get queued up by push_hdlc().
+ sSpiRxPayloadSize = slave_data_len;
+ }
+
+ if ( (sSpiTxPayloadSize == spi_header_get_data_len(sSpiTxFrameBuffer))
+ && (spi_header_get_data_len(sSpiTxFrameBuffer) <= slave_max_rx)
+ ) {
+ // Out outbound packet has been successfully transmitted. Clear
+ // sSpiTxPayloadSize and sSpiTxIsReady so that pull_hdlc() can
+ // pull another packet for us to send.
+ sSpiTxIsReady = false;
+ sSpiTxPayloadSize = 0;
+ sSpiTxFlowControl = false;
+ }
+
+bail:
+ return ret;
+}
+
+static bool check_and_clear_interrupt(void)
+{
+ char value[5] = "";
+ ssize_t len;
+
+ lseek(sIntGpioValueFd, 0, SEEK_SET);
+
+ len = read(sIntGpioValueFd, value, sizeof(value)-1);
+
+ if (len < 0)
+ {
+ perror("check_and_clear_interrupt");
+ sRet = EXIT_FAILURE;
+ }
+
+ // The interrupt pin is active low.
+ return GPIO_INT_ASSERT_STATE == atoi(value);
+}
+
+/* ------------------------------------------------------------------------- */
+/* MARK: HDLC Transfer Functions */
+
+#define HDLC_BYTE_FLAG 0x7E
+#define HDLC_BYTE_ESC 0x7D
+#define HDLC_BYTE_XON 0x11
+#define HDLC_BYTE_XOFF 0x13
+#define HDLC_BYTE_SPECIAL 0xF8
+#define HDLC_ESCAPE_XFORM 0x20
+
+static uint16_t hdlc_crc16(uint16_t aFcs, uint8_t aByte)
+{
+#if 1
+ // CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-CCITT
+ // width=16 poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189 name="KERMIT"
+ // http://reveng.sourceforge.net/crc-catalogue/16.htm#crc.cat.kermit
+ static const uint16_t sFcsTable[256] =
+ {
+ 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
+ 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
+ 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
+ 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
+ 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
+ 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
+ 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
+ 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
+ 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
+ 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
+ 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
+ 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
+ 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
+ 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
+ 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
+ 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
+ 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
+ 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
+ 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
+ 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
+ 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
+ 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
+ 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
+ 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
+ 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
+ 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
+ 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
+ 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
+ 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
+ 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
+ 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
+ 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
+ };
+ return (aFcs >> 8) ^ sFcsTable[(aFcs ^ aByte) & 0xff];
+#else
+ // CRC-16/CCITT-FALSE, same CRC as 802.15.4
+ // width=16 poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1 name="CRC-16/CCITT-FALSE"
+ // http://reveng.sourceforge.net/crc-catalogue/16.htm#crc.cat.crc-16-ccitt-false
+ aFcs = (uint16_t)((aFcs >> 8) | (aFcs << 8));
+ aFcs ^= aByte;
+ aFcs ^= ((aFcs & 0xff) >> 4);
+ aFcs ^= (aFcs << 12);
+ aFcs ^= ((aFcs & 0xff) << 5);
+ return aFcs;
+#endif
+}
+
+static bool hdlc_byte_needs_escape(uint8_t byte)
+{
+ switch(byte)
+ {
+ case HDLC_BYTE_SPECIAL:
+ case HDLC_BYTE_ESC:
+ case HDLC_BYTE_FLAG:
+ case HDLC_BYTE_XOFF:
+ case HDLC_BYTE_XON:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static int push_hdlc(void)
+{
+ int ret = 0;
+ const uint8_t* spiRxFrameBuffer = get_real_rx_frame_start();
+ static uint8_t escaped_frame_buffer[MAX_FRAME_SIZE*2];
+ static uint16_t escaped_frame_len;
+ static uint16_t escaped_frame_sent;
+
+ if (escaped_frame_len == 0)
+ {
+ if (sSlaveDidReset)
+ {
+ // Indicate an MCU reset.
+ memcpy(escaped_frame_buffer, kHdlcResetSignal, sizeof(kHdlcResetSignal));
+ escaped_frame_len = sizeof(kHdlcResetSignal);
+ sSlaveDidReset = false;
+ }
+ else if (sSpiRxPayloadSize != 0)
+ {
+ // Escape the frame.
+ uint8_t c;
+ uint16_t fcs = kHdlcCrcResetValue;
+ uint16_t i;
+
+ for (i = 0; i < sSpiRxPayloadSize; i++)
+ {
+ c = spiRxFrameBuffer[i + HEADER_LEN];
+ fcs = hdlc_crc16(fcs, c);
+ if (hdlc_byte_needs_escape(c))
+ {
+ escaped_frame_buffer[escaped_frame_len++] = HDLC_BYTE_ESC;
+ escaped_frame_buffer[escaped_frame_len++] = c ^ HDLC_ESCAPE_XFORM;
+ }
+ else
+ {
+ escaped_frame_buffer[escaped_frame_len++] = c;
+ }
+ }
+
+ fcs ^= 0xFFFF;
+
+ c = fcs & 0xFF;
+ if (hdlc_byte_needs_escape(c))
+ {
+ escaped_frame_buffer[escaped_frame_len++] = HDLC_BYTE_ESC;
+ escaped_frame_buffer[escaped_frame_len++] = c ^ HDLC_ESCAPE_XFORM;
+ }
+ else
+ {
+ escaped_frame_buffer[escaped_frame_len++] = c;
+ }
+
+ c = (fcs >> 8) & 0xFF;
+ if (hdlc_byte_needs_escape(c))
+ {
+ escaped_frame_buffer[escaped_frame_len++] = HDLC_BYTE_ESC;
+ escaped_frame_buffer[escaped_frame_len++] = c ^ HDLC_ESCAPE_XFORM;
+ }
+ else
+ {
+ escaped_frame_buffer[escaped_frame_len++] = c;
+ }
+
+ escaped_frame_buffer[escaped_frame_len++] = HDLC_BYTE_FLAG;
+ escaped_frame_sent = 0;
+ sSpiRxPayloadSize = 0;
+
+ }
+ else
+ {
+ // Nothing to do.
+ goto bail;
+ }
+ }
+
+ ret = (int)write(
+ sHdlcOutputFd,
+ escaped_frame_buffer + escaped_frame_sent,
+ escaped_frame_len - escaped_frame_sent
+ );
+
+ if (ret < 0)
+ {
+ if (errno == EAGAIN)
+ {
+ ret = 0;
+ }
+ else
+ {
+ perror("push_hdlc:write");
+ syslog(LOG_ERR, "push_hdlc:write: errno=%d (%s)", errno, strerror(errno));
+ }
+ goto bail;
+ }
+
+ escaped_frame_sent += ret;
+
+ // Reset state once we have sent the entire frame.
+ if (escaped_frame_len == escaped_frame_sent)
+ {
+ escaped_frame_len = escaped_frame_sent = 0;
+ }
+
+ ret = 0;
+
+bail:
+ return ret;
+}
+
+static int pull_hdlc(void)
+{
+ int ret = 0;
+ static uint16_t fcs;
+ static bool unescape_next_byte = false;
+
+ if (!sSpiTxIsReady)
+ {
+ uint8_t byte;
+ while ((ret = (int)read(sHdlcInputFd, &byte, 1)) == 1)
+ {
+ if (sSpiTxPayloadSize >= (MAX_FRAME_SIZE - HEADER_LEN))
+ {
+ syslog(LOG_WARNING, "HDLC frame was too big");
+ unescape_next_byte = false;
+ sSpiTxPayloadSize = 0;
+ fcs = kHdlcCrcResetValue;
+
+ }
+ else if (byte == HDLC_BYTE_FLAG)
+ {
+ if (sSpiTxPayloadSize <= 2)
+ {
+ unescape_next_byte = false;
+ sSpiTxPayloadSize = 0;
+ fcs = kHdlcCrcResetValue;
+ continue;
+
+ }
+ else if (fcs != kHdlcCrcCheckValue)
+ {
+ syslog(LOG_WARNING, "HDLC frame with bad CRC (LEN:%d, FCS:0x%04X)", sSpiTxPayloadSize, fcs);
+ unescape_next_byte = false;
+ sSpiTxPayloadSize = 0;
+ fcs = kHdlcCrcResetValue;
+ continue;
+ }
+
+ // Clip off the CRC
+ sSpiTxPayloadSize -= 2;
+
+ // Indicate that a frame is ready to go out
+ sSpiTxIsReady = true;
+
+ // Clean up for the next frame
+ unescape_next_byte = false;
+ fcs = kHdlcCrcResetValue;
+ break;
+
+ }
+ else if (byte == HDLC_BYTE_ESC)
+ {
+ unescape_next_byte = true;
+ continue;
+
+ }
+ else if (hdlc_byte_needs_escape(byte))
+ {
+ // Skip all other control codes.
+ continue;
+
+ }
+ else if (unescape_next_byte)
+ {
+ byte = byte ^ HDLC_ESCAPE_XFORM;
+ unescape_next_byte = false;
+ }
+
+ fcs = hdlc_crc16(fcs, byte);
+ sSpiTxFrameBuffer[HEADER_LEN + sSpiTxPayloadSize++] = byte;
+ }
+ }
+
+ if (ret < 0)
+ {
+ if (errno == EAGAIN)
+ {
+ ret = 0;
+ }
+ else
+ {
+ perror("pull_hdlc:read");
+ syslog(LOG_ERR, "pull_hdlc:read: errno=%d (%s)", errno, strerror(errno));
+ }
+ }
+
+ return ret < 0
+ ? ret
+ : 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+/* MARK: Setup Functions */
+
+static bool update_spi_mode(int x)
+{
+ sSpiMode = (uint8_t)x;
+
+ if ( (sSpiDevFd >= 0)
+ && (ioctl(sSpiDevFd, SPI_IOC_WR_MODE, &sSpiMode) < 0)
+ )
+ {
+ perror("ioctl(SPI_IOC_WR_MODE)");
+ return false;
+ }
+
+ return true;
+}
+
+static bool update_spi_speed(int x)
+{
+ sSpiSpeed = x;
+
+ if ( (sSpiDevFd >= 0)
+ && (ioctl(sSpiDevFd, SPI_IOC_WR_MAX_SPEED_HZ, &sSpiSpeed) < 0)
+ )
+ {
+ perror("ioctl(SPI_IOC_WR_MAX_SPEED_HZ)");
+ return false;
+ }
+
+ return true;
+}
+
+
+static bool setup_spi_dev(const char* path)
+{
+ int fd = -1;
+ const uint8_t spi_word_bits = 8;
+ int ret;
+ sSpiDevPath = path;
+
+ fd = open(path, O_RDWR);
+ if (fd < 0)
+ {
+ perror("open");
+ goto bail;
+ }
+
+ // Set the SPI mode.
+ ret = ioctl(fd, SPI_IOC_WR_MODE, &sSpiMode);
+ if (ret < 0)
+ {
+ perror("ioctl(SPI_IOC_WR_MODE)");
+ goto bail;
+ }
+
+ // Set the SPI clock speed.
+ ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &sSpiSpeed);
+ if (ret < 0)
+ {
+ perror("ioctl(SPI_IOC_WR_MAX_SPEED_HZ)");
+ goto bail;
+ }
+
+ // Set the SPI word size.
+ ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &spi_word_bits);
+ if (ret < 0)
+ {
+ perror("ioctl(SPI_IOC_WR_BITS_PER_WORD)");
+ goto bail;
+ }
+
+ // Lock the file descriptor
+ if (flock(fd, LOCK_EX | LOCK_NB) < 0)
+ {
+ perror("flock");
+ goto bail;
+ }
+
+ sSpiDevFd = fd;
+ fd = -1;
+
+bail:
+ if (fd >= 0)
+ {
+ close(fd);
+ }
+ return sSpiDevFd >= 0;
+}
+
+static bool setup_res_gpio(const char* path)
+{
+ int setup_fd = -1;
+ char* dir_path = NULL;
+ char* value_path = NULL;
+ int len;
+
+ sResGpioDevPath = path;
+
+ len = asprintf(&dir_path, "%s/direction", path);
+
+ if (len < 0)
+ {
+ perror("asprintf");
+ goto bail;
+ }
+
+ len = asprintf(&value_path, "%s/value", path);
+
+ if (len < 0)
+ {
+ perror("asprintf");
+ goto bail;
+ }
+
+ setup_fd = open(dir_path, O_WRONLY);
+
+ if (setup_fd >= 0)
+ {
+ if (-1 == write(setup_fd, "high\n", 5))
+ {
+ perror("set_res_direction");
+ goto bail;
+ }
+ }
+
+ sResGpioValueFd = open(value_path, O_WRONLY);
+
+bail:
+
+ if (setup_fd >= 0)
+ {
+ close(setup_fd);
+ }
+
+ if (dir_path)
+ {
+ free(dir_path);
+ }
+
+ if (value_path)
+ {
+ free(value_path);
+ }
+
+ return sResGpioValueFd >= 0;
+}
+
+static void trigger_reset(void)
+{
+ if (sResGpioValueFd >= 0)
+ {
+ char str[] = { '0' + GPIO_RES_ASSERT_STATE, '\n' };
+
+ lseek(sResGpioValueFd, 0, SEEK_SET);
+ if (write(sResGpioValueFd, str, sizeof(str)) == -1)
+ {
+ syslog(LOG_ERR, "trigger_reset(): error on write: %d (%s)", errno, strerror(errno));
+ }
+
+ usleep(10 * USEC_PER_MSEC);
+
+ // Set the string to switch to the not-asserted state.
+ str[0] = '0' + !GPIO_RES_ASSERT_STATE;
+
+ lseek(sResGpioValueFd, 0, SEEK_SET);
+ if (write(sResGpioValueFd, str, sizeof(str)) == -1)
+ {
+ syslog(LOG_ERR, "trigger_reset(): error on write: %d (%s)", errno, strerror(errno));
+ }
+
+ syslog(LOG_NOTICE, "Triggered hardware reset");
+ }
+}
+
+static bool setup_int_gpio(const char* path)
+{
+ char* edge_path = NULL;
+ char* dir_path = NULL;
+ char* value_path = NULL;
+ ssize_t len;
+ int setup_fd = -1;
+
+ sIntGpioValueFd = -1;
+
+ sIntGpioDevPath = path;
+
+ len = asprintf(&dir_path, "%s/direction", path);
+
+ if (len < 0)
+ {
+ perror("asprintf");
+ goto bail;
+ }
+
+ len = asprintf(&edge_path, "%s/edge", path);
+
+ if (len < 0)
+ {
+ perror("asprintf");
+ goto bail;
+ }
+
+ len = asprintf(&value_path, "%s/value", path);
+
+ if (len < 0)
+ {
+ perror("asprintf");
+ goto bail;
+ }
+
+ setup_fd = open(dir_path, O_WRONLY);
+
+ if (setup_fd >= 0)
+ {
+ len = write(setup_fd, "in", 2);
+ if (len < 0)
+ {
+ perror("write");
+ goto bail;
+ }
+
+ close(setup_fd);
+ }
+
+ setup_fd = open(edge_path, O_WRONLY);
+
+ if (setup_fd >= 0)
+ {
+ len = write(setup_fd, "falling", 7);
+
+ if (len < 0)
+ {
+ perror("write");
+ goto bail;
+ }
+
+ close(setup_fd);
+
+ setup_fd = -1;
+ }
+
+ sIntGpioValueFd = open(value_path, O_RDONLY);
+
+bail:
+
+ if (setup_fd >= 0)
+ {
+ close(setup_fd);
+ }
+
+ if (edge_path)
+ {
+ free(edge_path);
+ }
+
+ if (dir_path)
+ {
+ free(dir_path);
+ }
+
+ if (value_path)
+ {
+ free(value_path);
+ }
+
+ return sIntGpioValueFd >= 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+/* MARK: Help */
+
+static void print_version(void)
+{
+ printf("spi-hdlc " SPI_HDLC_VERSION "(" __TIME__ " " __DATE__ ")\n");
+ printf("Copyright (c) 2016 The OpenThread Authors, All Rights Reserved\n");
+}
+
+static void print_help(void)
+{
+ print_version();
+ const char* help =
+ "\n"
+ "Syntax:\n"
+ "\n"
+ " spi-hdlc [options] <spi-device-path>\n"
+ "\n"
+ "Options:\n"
+ "\n"
+ " --stdio ...................... Use `stdin` and `stdout` for HDLC input and\n"
+ " output. Useful when directly started by the\n"
+ " program that will be using it.\n"
+#if HAVE_OPENPTY
+ " --pty ........................ Create a pseudoterminal for HDLC input and\n"
+ " output. The path of the newly-created PTY\n"
+ " will be written to `stdout`, followed by a\n"
+ " newline.\n"
+#endif // HAVE_OPENPTY
+ " -i/--gpio-int[=gpio-path] .... Specify a path to the Linux sysfs-exported\n"
+ " GPIO directory for the `IÌ…NÌ…TÌ…` pin. If not\n"
+ " specified, `spi-hdlc` will fall back to\n"
+ " polling, which is inefficient.\n"
+ " -r/--gpio-reset[=gpio-path] .. Specify a path to the Linux sysfs-exported\n"
+ " GPIO directory for the `RÌ…EÌ…SÌ…` pin.\n"
+ " --spi-mode[=mode] ............ Specify the SPI mode to use (0-3).\n"
+ " --spi-speed[=hertz] .......... Specify the SPI speed in hertz.\n"
+ " --spi-cs-delay[=usec] ........ Specify the delay after CÌ…SÌ… assertion, in usec\n"
+ " --spi-align-allowance[=n] .... Specify the the maximum number of FF bytes to\n"
+ " clip from start of RX frame.\n"
+ " -v/--verbose ................. Increase debug verbosity. (Repeatable)\n"
+ " -h/-?/--help ................. Print out usage information and exit.\n"
+ "\n";
+
+ printf("%s", help);
+}
+
+
+/* ------------------------------------------------------------------------- */
+/* MARK: Main Loop */
+
+int main(int argc, char *argv[])
+{
+ int i = 0;
+ const char* prog = argv[0];
+ static fd_set read_set;
+ static fd_set write_set;
+ static fd_set error_set;
+ struct timeval timeout;
+ int max_fd = -1;
+ bool did_print_rate_limit_log = false;
+
+#if AUTO_PRINT_BACKTRACE
+ struct sigaction sigact;
+#endif // if AUTO_PRINT_BACKTRACE
+
+ enum {
+ ARG_SPI_MODE = 1001,
+ ARG_SPI_SPEED = 1002,
+ ARG_VERBOSE = 1003,
+ ARG_SPI_CS_DELAY = 1004,
+ ARG_SPI_ALIGN_ALLOWANCE = 1005,
+ };
+
+ static struct option options[] = {
+ { "stdio", no_argument, &sMode, MODE_STDIO },
+ { "pty", no_argument, &sMode, MODE_PTY },
+ { "gpio-int", required_argument, NULL, 'i' },
+ { "gpio-res", required_argument, NULL, 'r' },
+ { "verbose", optional_argument, NULL, ARG_VERBOSE },
+ { "version", no_argument, NULL, 'V' },
+ { "help", no_argument, NULL, 'h' },
+ { "spi-mode", required_argument, NULL, ARG_SPI_MODE },
+ { "spi-speed", required_argument, NULL, ARG_SPI_SPEED },
+ { "spi-cs-delay",required_argument,NULL, ARG_SPI_CS_DELAY },
+ { "spi-align-allowance", required_argument, NULL, ARG_SPI_ALIGN_ALLOWANCE },
+ { NULL, 0, NULL, 0 },
+ };
+
+ if (argc < 2)
+ {
+ print_help();
+ exit(EXIT_FAILURE);
+ }
+
+
+ // ========================================================================
+ // INITIALIZATION
+
+ sPreviousHandlerForSIGINT = signal(SIGINT, &signal_SIGINT);
+ sPreviousHandlerForSIGTERM = signal(SIGTERM, &signal_SIGTERM);
+ signal(SIGHUP, &signal_SIGHUP);
+
+#if AUTO_PRINT_BACKTRACE
+ sigact.sa_sigaction = &signal_critical;
+ sigact.sa_flags = SA_RESTART | SA_SIGINFO | SA_NOCLDWAIT;
+
+ sigaction(SIGSEGV, &sigact, (struct sigaction *)NULL);
+ sigaction(SIGBUS, &sigact, (struct sigaction *)NULL);
+ sigaction(SIGILL, &sigact, (struct sigaction *)NULL);
+ sigaction(SIGABRT, &sigact, (struct sigaction *)NULL);
+#endif // if AUTO_PRINT_BACKTRACE
+
+ // ========================================================================
+ // ARGUMENT PARSING
+
+ openlog(basename(prog), LOG_PERROR | LOG_PID | LOG_CONS, LOG_DAEMON);
+
+ setlogmask(setlogmask(0) & LOG_UPTO(sVerbose));
+
+ while (1)
+ {
+ int c = getopt_long(argc, argv, "i:r:vVh?", options, NULL);
+ if (c == -1)
+ {
+ break;
+ }
+ else
+ {
+ switch (c)
+ {
+ case 'i':
+ if (!setup_int_gpio(optarg))
+ {
+ syslog(LOG_ERR, "Unable to setup INT GPIO \"%s\", %s", optarg, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ break;
+
+ case ARG_SPI_ALIGN_ALLOWANCE:
+ errno = 0;
+ sSpiRxAlignAllowance = atoi(optarg);
+ if (errno != 0 || (sSpiRxAlignAllowance > SPI_RX_ALIGN_ALLOWANCE_MAX))
+ {
+ syslog(LOG_ERR, "Invalid SPI RX Align Allowance \"%s\" (MAX: %d)", optarg, SPI_RX_ALIGN_ALLOWANCE_MAX);
+ exit(EXIT_FAILURE);
+ }
+ break;
+
+ case ARG_SPI_MODE:
+ if (!update_spi_mode(atoi(optarg)))
+ {
+ syslog(LOG_ERR, "Unable to set SPI mode to \"%s\", %s", optarg, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ break;
+
+ case ARG_SPI_SPEED:
+ if (!update_spi_speed(atoi(optarg)))
+ {
+ syslog(LOG_ERR, "Unable to set SPI speed to \"%s\", %s", optarg, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ break;
+
+ case ARG_SPI_CS_DELAY:
+ sSpiCsDelay = atoi(optarg);
+ syslog(LOG_NOTICE, "SPI CS Delay set to %d usec", sSpiCsDelay);
+ break;
+
+ case 'r':
+ if (!setup_res_gpio(optarg))
+ {
+ syslog(LOG_ERR, "Unable to setup RES GPIO \"%s\", %s", optarg, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ break;
+
+ case 'v':
+ case ARG_VERBOSE:
+ if (sVerbose < LOG_DEBUG)
+ {
+ if (optarg)
+ {
+ sVerbose += atoi(optarg);
+ }
+ else
+ {
+ sVerbose++;
+ }
+ setlogmask(setlogmask(0) | LOG_UPTO(sVerbose));
+ syslog(sVerbose, "Verbosity set to level %d", sVerbose);
+ }
+ break;
+
+ case 'V':
+ print_version();
+ exit(EXIT_SUCCESS);
+ break;
+
+ case 'h':
+ case '?':
+ print_help();
+ exit(EXIT_SUCCESS);
+ break;
+ }
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc >= 1)
+ {
+ if (!setup_spi_dev(argv[0]))
+ {
+ syslog(LOG_ERR, "%s: Unable to open SPI device \"%s\", %s", prog, argv[0], strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ argc--;
+ argv++;
+ }
+
+ if (argc >= 1)
+ {
+ fprintf(stderr, "%s: Unexpected argument \"%s\"\n", prog, argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ if (sSpiDevPath == NULL)
+ {
+ fprintf(stderr, "%s: Missing SPI device path\n", prog);
+ exit(EXIT_FAILURE);
+ }
+
+ if (sMode == MODE_STDIO)
+ {
+ sHdlcInputFd = dup(STDIN_FILENO);
+ sHdlcOutputFd = dup(STDOUT_FILENO);
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
+
+ }
+ else if (sMode == MODE_PTY)
+ {
+#if HAVE_OPENPTY
+
+ static int pty_slave_fd = -1;
+ char pty_name[1024];
+ sRet = openpty(&sHdlcInputFd, &pty_slave_fd, pty_name, NULL, NULL);
+
+ if (sRet != 0)
+ {
+ perror("openpty");
+ goto bail;
+ }
+
+ sHdlcOutputFd = dup(sHdlcInputFd);
+
+ printf("%s\n", pty_name);
+
+ close(STDOUT_FILENO);
+
+#else // if HAVE_OPENPTY
+
+ syslog(LOG_ERR, "Not built with support for `--pty`.");
+ sRet = EXIT_FAILURE;
+ goto bail;
+
+#endif // else HAVE_OPENPTY
+
+ }
+ else
+ {
+ sRet = EXIT_FAILURE;
+ goto bail;
+ }
+
+ // Set up sHdlcInputFd for non-blocking I/O
+ if (-1 == (i = fcntl(sHdlcInputFd, F_GETFL, 0)))
+ {
+ i = 0;
+ }
+ fcntl(sHdlcInputFd, F_SETFL, i | O_NONBLOCK);
+
+ // Since there are so few file descriptors in
+ // this program, we calcualte `max_fd` once
+ // instead of trying to optimize its value
+ // at every iteration.
+ max_fd = sHdlcInputFd;
+
+ if (max_fd < sHdlcOutputFd)
+ {
+ max_fd = sHdlcOutputFd;
+ }
+
+ if (max_fd < sIntGpioValueFd)
+ {
+ max_fd = sIntGpioValueFd;
+ }
+
+ if (sIntGpioValueFd < 0)
+ {
+ syslog(LOG_WARNING, "Interrupt pin was not set, must poll SPI. Performance will suffer.");
+ }
+
+ trigger_reset();
+
+ // ========================================================================
+ // MAIN LOOP
+
+ while (sRet == 0)
+ {
+ int timeout_ms = MSEC_PER_SEC * 60 * 60 * 24; // 24 hours
+
+ FD_ZERO(&read_set);
+ FD_ZERO(&write_set);
+ FD_ZERO(&error_set);
+
+ if (!sSpiTxIsReady)
+ {
+ FD_SET(sHdlcInputFd, &read_set);
+
+ }
+ else if (sSpiTxFlowControl)
+ {
+ // We are being rate-limited by the NCP. This is
+ // fairly normal behavior. We poll because we
+ // won't get an interrupt unless the NCP happens
+ // to be trying to send us something.
+ timeout_ms = SPI_POLL_PERIOD_MSEC;
+
+ if (!did_print_rate_limit_log) {
+ // Avoid printing out this message over and over.
+ syslog(LOG_INFO, "NCP is rate limiting transactions");
+ did_print_rate_limit_log = true;
+ }
+ }
+ else
+ {
+ // We have data to send to the slave. Since we
+ // are not being rate-limited, proceed immediately.
+ timeout_ms = 0;
+ did_print_rate_limit_log = false;
+ }
+
+ if (sSpiRxPayloadSize != 0)
+ {
+ // We have data that we are waiting to send out
+ // of the HDLC descriptor, so we need to wait
+ // for that to clear out before we can do anything
+ // else.
+ FD_SET(sHdlcOutputFd, &write_set);
+
+ }
+ else if (sIntGpioValueFd >= 0)
+ {
+ if (check_and_clear_interrupt())
+ {
+ // Interrupt pin is asserted,
+ // set the timeout to be 0.
+ timeout_ms = 0;
+
+ syslog(LOG_DEBUG, "Interrupt.");
+ }
+ else
+ {
+ // The interrupt pin was not asserted,
+ // so we wait for the interrupt pin to
+ // be asserted by adding it to the error
+ // set.
+ FD_SET(sIntGpioValueFd, &error_set);
+ }
+
+ }
+ else if (timeout_ms > SPI_POLL_PERIOD_MSEC)
+ {
+ // In this case we don't have an interrupt, so
+ // we revert to SPI polling.
+ timeout_ms = SPI_POLL_PERIOD_MSEC;
+ }
+
+ // Calculate the timeout value.
+ timeout.tv_sec = timeout_ms / MSEC_PER_SEC;
+ timeout.tv_usec = (timeout_ms % MSEC_PER_SEC) * USEC_PER_MSEC;
+
+ // Wait for something to happen.
+ select(max_fd + 1, &read_set, &write_set, &error_set, &timeout);
+
+ // Handle serial input.
+ if (FD_ISSET(sHdlcInputFd, &read_set))
+ {
+ // Read in the data.
+ if (pull_hdlc() < 0)
+ {
+ sRet = EXIT_FAILURE;
+ break;
+ }
+ }
+
+ // Handle serial output.
+ if (FD_ISSET(sHdlcOutputFd, &write_set))
+ {
+ // Write out the data.
+ if (push_hdlc() < 0)
+ {
+ sRet = EXIT_FAILURE;
+ break;
+ }
+ }
+
+ // Service the SPI port if we can receive
+ // a packet or we have a packet to be sent.
+ if ((sSpiRxPayloadSize == 0) || sSpiTxIsReady)
+ {
+ if (push_pull_spi() < 0)
+ {
+ sRet = EXIT_FAILURE;
+ }
+ }
+ }
+
+
+ // ========================================================================
+ // SHUTDOWN
+
+bail:
+ syslog(LOG_NOTICE, "Shutdown. (sRet = %d)", sRet);
+
+ if (sRet == EXIT_QUIT)
+ {
+ sRet = EXIT_SUCCESS;
+ }
+ else if (sRet == -1)
+ {
+ sRet = EXIT_FAILURE;
+ }
+
+ return sRet;
+}
diff --git a/third_party/pt/LICENSE b/third_party/pt/LICENSE
new file mode 100644
index 0000000..4b9d77f
--- /dev/null
+++ b/third_party/pt/LICENSE
@@ -0,0 +1,28 @@
+Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of the Institute nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+Author: Adam Dunkels <adam@sics.se>
diff --git a/third_party/pt/Makefile b/third_party/pt/Makefile
new file mode 100644
index 0000000..ff573ef
--- /dev/null
+++ b/third_party/pt/Makefile
@@ -0,0 +1,9 @@
+CFLAGS=-O -Wuninitialized -Werror
+
+all: example-codelock example-buffer example-small
+
+example-codelock: example-codelock.c pt.h lc.h
+
+example-buffer: example-buffer.c pt.h lc.h
+
+example-small: example-small.c pt.h lc.h
diff --git a/third_party/pt/README b/third_party/pt/README
new file mode 100644
index 0000000..54d8627
--- /dev/null
+++ b/third_party/pt/README
@@ -0,0 +1,51 @@
+Protothreads are extremely lightweight stackless threads designed for
+severely memory constrained systems such as small embedded systems or
+sensor network nodes. Protothreads can be used with or without an
+underlying operating system.
+
+Protothreads provides a blocking context on top of an event-driven
+system, without the overhead of per-thread stacks. The purpose of
+protothreads is to implement sequential flow of control without
+complex state machines or full multi-threading.
+
+Main features:
+
+ * No machine specific code - the protothreads library is pure C
+ * Does not use error-prone functions such as longjmp()
+ * Very small RAM overhead - only two bytes per protothread
+ * Can be used with or without an OS
+ * Provides blocking wait without full multi-threading or
+ stack-switching
+ * Freely available under a BSD-like open source license
+
+Example applications:
+
+ * Memory constrained systems
+ * Event-driven protocol stacks
+ * Small embedded systems
+ * Sensor network nodes
+
+The protothreads library is released under an open source BSD-style
+license that allows for both non-commercial and commercial usage. The
+only requirement is that credit is given.
+
+The protothreads library was written by Adam Dunkels <adam@sics.se>
+with support from Oliver Schmidt <ol.sc@web.de>.
+
+More information and new versions can be found at the protothreads
+homepage:
+ http://www.sics.se/~adam/pt/
+
+Documentation can be found in the doc/ subdirectory.
+
+Two example programs illustrating the use of protothreads can be found
+in this directory:
+
+ example-small.c A small example showing how to use protothreads
+ example-buffer.c The bounded buffer problem with protothreads
+ example-codelock.c A code lock with simulated key input
+
+To compile the examples, simply run "make".
+
+
+Adam Dunkels, 3 June 2006
diff --git a/third_party/pt/README-VISUAL-C++.txt b/third_party/pt/README-VISUAL-C++.txt
new file mode 100644
index 0000000..3b09a69
--- /dev/null
+++ b/third_party/pt/README-VISUAL-C++.txt
@@ -0,0 +1,5 @@
+Protothreads can in some cases fail to compile under Visual C++
+version 6.0 due to a bug in the compiler. See the following page for a
+solution to the problem:
+
+http://support.microsoft.com/default.aspx?scid=kb;en-us;199057
diff --git a/third_party/pt/README.google b/third_party/pt/README.google
new file mode 100644
index 0000000..79082a5
--- /dev/null
+++ b/third_party/pt/README.google
@@ -0,0 +1,17 @@
+URL: http://dunkels.com/adam/download/pt-1.4.tar.gz
+Version: 1.4
+License: BSD-3
+License File: LICENSE
+
+Description:
+Protothreads are extremely lightweight stackless threads designed for severely
+memory constrained systems, such as small embedded systems or wireless sensor
+network nodes. Protothreads provide linear code execution for event-driven
+systems implemented in C. Protothreads can be used with or without an underlying
+operating system to provide blocking event-handlers. Protothreads provide
+sequential flow of control without complex state machines or full
+multi-threading.
+
+Local Modifications:
+LICENSE file has been created for compliance purposes. Not included in original
+distribution. Removed html and pt-refman.pdf from documentation folder.
diff --git a/third_party/pt/doc/Doxyfile b/third_party/pt/doc/Doxyfile
new file mode 100644
index 0000000..27b4b75
--- /dev/null
+++ b/third_party/pt/doc/Doxyfile
@@ -0,0 +1,229 @@
+# Doxyfile 1.4.6
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = "The Protothreads Library 1.4"
+PROJECT_NUMBER =
+OUTPUT_DIRECTORY = .
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+USE_WINDOWS_ENCODING = NO
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ABBREVIATE_BRIEF =
+ALWAYS_DETAILED_SEC = NO
+INLINE_INHERITED_MEMB = NO
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH = ../
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = YES
+JAVADOC_AUTOBRIEF = YES
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP = YES
+INHERIT_DOCS = YES
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 8
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = YES
+OPTIMIZE_OUTPUT_JAVA = NO
+BUILTIN_STL_SUPPORT = NO
+DISTRIBUTE_GROUP_DOC = NO
+SUBGROUPING = YES
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = NO
+EXTRACT_STATIC = NO
+EXTRACT_LOCAL_CLASSES = NO
+EXTRACT_LOCAL_METHODS = NO
+HIDE_UNDOC_MEMBERS = YES
+HIDE_UNDOC_CLASSES = YES
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = YES
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = YES
+SORT_BRIEF_DOCS = NO
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = NO
+GENERATE_DEPRECATEDLIST= NO
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = NO
+SHOW_DIRECTORIES = NO
+FILE_VERSION_FILTER =
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = NO
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = pt-mainpage.txt \
+ pt-doc.txt \
+ ../pt.h \
+ ../pt-sem.h \
+ ../lc.h \
+ ../lc-switch.h \
+ ../lc-addrlabels.h
+FILE_PATTERNS =
+RECURSIVE = NO
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXAMPLE_PATH = ..
+EXAMPLE_PATTERNS =
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = YES
+INLINE_SOURCES = YES
+STRIP_CODE_COMMENTS = NO
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION = YES
+USE_HTAGS = NO
+VERBATIM_HEADERS = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = NO
+COLS_IN_ALPHA_INDEX = 5
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+HTML_HEADER =
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = YES
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = NO
+ENUM_VALUES_PER_LINE = 4
+GENERATE_TREEVIEW = YES
+TREEVIEW_WIDTH = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = YES
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = YES
+PAPER_TYPE = a4
+EXTRA_PACKAGES =
+LATEX_HEADER = header.tex
+PDF_HYPERLINKS = YES
+USE_PDFLATEX = YES
+LATEX_BATCHMODE = NO
+LATEX_HIDE_INDICES = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
+XML_OUTPUT = xml
+XML_SCHEMA =
+XML_DTD =
+XML_PROGRAMLISTING = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD = NO
+PERLMOD_LATEX = NO
+PERLMOD_PRETTY = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = NO
+EXPAND_ONLY_PREDEF = NO
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+PREDEFINED = DOXYGEN
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+TAGFILES =
+GENERATE_TAGFILE =
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+PERL_PATH = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = NO
+HIDE_UNDOC_RELATIONS = NO
+HAVE_DOT = NO
+CLASS_GRAPH = NO
+COLLABORATION_GRAPH = YES
+GROUP_GRAPHS = YES
+UML_LOOK = NO
+TEMPLATE_RELATIONS = NO
+INCLUDE_GRAPH = NO
+INCLUDED_BY_GRAPH = YES
+CALL_GRAPH = YES
+GRAPHICAL_HIERARCHY = YES
+DIRECTORY_GRAPH = YES
+DOT_IMAGE_FORMAT = png
+DOT_PATH =
+DOTFILE_DIRS =
+MAX_DOT_GRAPH_WIDTH = 1024
+MAX_DOT_GRAPH_HEIGHT = 1024
+MAX_DOT_GRAPH_DEPTH = 0
+DOT_TRANSPARENT = NO
+DOT_MULTI_TARGETS = NO
+GENERATE_LEGEND = YES
+DOT_CLEANUP = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
diff --git a/third_party/pt/doc/Makefile b/third_party/pt/doc/Makefile
new file mode 100644
index 0000000..39328b4
--- /dev/null
+++ b/third_party/pt/doc/Makefile
@@ -0,0 +1,7 @@
+dox:
+ doxygen Doxyfile
+
+
+pdf: dox
+ (cd latex; $(MAKE) refman.pdf)
+ mv latex/refman.pdf pt-refman.pdf
diff --git a/third_party/pt/doc/header.tex b/third_party/pt/doc/header.tex
new file mode 100644
index 0000000..5899653
--- /dev/null
+++ b/third_party/pt/doc/header.tex
@@ -0,0 +1,52 @@
+\documentclass[a4paper]{article}
+\usepackage{a4wide}
+\usepackage{makeidx}
+\usepackage{fancyhdr}
+\usepackage{graphicx}
+\usepackage{multicol}
+\usepackage{float}
+\usepackage{textcomp}
+\usepackage{alltt}
+\usepackage{times}
+\usepackage{epsfig}
+\ifx\pdfoutput\undefined
+\usepackage[ps2pdf,
+ pagebackref=true,
+ colorlinks=true,
+ linkcolor=blue
+ ]{hyperref}
+\usepackage{pspicture}
+\else
+\usepackage[pdftex,
+ pagebackref=true,
+ colorlinks=true,
+ linkcolor=blue
+ ]{hyperref}
+\fi
+\usepackage{doxygen}
+\makeindex
+\setcounter{tocdepth}{1}
+\renewcommand{\footrulewidth}{0.4pt}
+\begin{document}
+\begin{titlepage}
+\vspace*{5cm}
+\begin{center}
+{\Huge Protothreads}\\
+\vspace*{1cm}
+{\LARGE The Protothreads Library 1.3 Reference Manual}\\
+\vspace*{3cm}
+{\Large June 2006}\\
+\vspace*{2cm}
+\includegraphics[width=6cm]{../sicslogo.pdf}\\
+\vspace*{1cm}
+{\Large Adam Dunkels}\\
+{\Large \texttt{adam@sics.se}}\\
+\vspace*{1cm}
+{\LARGE Swedish Institute of Computer Science}\\
+\vspace*{0.5cm}
+
+\end{center}
+\end{titlepage}
+\pagenumbering{roman}
+\tableofcontents
+\pagenumbering{arabic}
diff --git a/third_party/pt/doc/pt-doc.txt b/third_party/pt/doc/pt-doc.txt
new file mode 100644
index 0000000..b0885aa
--- /dev/null
+++ b/third_party/pt/doc/pt-doc.txt
@@ -0,0 +1,58 @@
+/**
+\defgroup pt Protothreads
+@{
+Protothreads are implemented in a single header file, pt.h, which
+includes the local continuations header file, lc.h. This file in turn
+includes the actual implementation of local continuations, which
+typically also is contained in a single header file.
+
+*/
+
+/** @} */
+
+/**
+\defgroup examples Examples
+@{
+
+\section example-small A small example
+
+This first example shows a very simple program: two protothreads
+waiting for each other to toggle two flags. The code illustrates how
+to write protothreads code, how to initialize protothreads, and how to
+schedule them.
+
+\include example-small.c
+
+
+\section example-code-lock A code-lock
+This example shows how to implement a simple code lock - the kind of
+device that is placed next to doors and that you have to push a four
+digit number into in order to unlock the door.
+
+The code lock waits for key presses from a numeric keyboard and if the
+correct code is entered, the lock is unlocked. There is a maximum time
+of one second between each key press, and after the correct code has
+been entered, no more keys must be pressed for 0.5 seconds before the
+lock is opened.
+
+\include example-codelock.c
+
+\section example-buffer The bounded buffer with protothread semaphores
+
+The following example shows how to implement the bounded buffer
+problem using the protothreads semaphore library. The example uses
+three protothreads: one producer() protothread that produces items,
+one consumer() protothread that consumes items, and one
+driver_thread() that schedules the producer and consumer protothreads.
+
+Note that there is no need for a mutex to guard the add_to_buffer()
+and get_from_buffer() functions because of the implicit locking
+semantics of protothreads - a protothread will never be preempted and
+will never block except in an explicit PT_WAIT statement.
+
+\include example-buffer.c
+
+*/
+
+
+/** @} */
diff --git a/third_party/pt/doc/pt-mainpage.txt b/third_party/pt/doc/pt-mainpage.txt
new file mode 100644
index 0000000..269570b
--- /dev/null
+++ b/third_party/pt/doc/pt-mainpage.txt
@@ -0,0 +1,156 @@
+/**
+
+\mainpage The Protothreads Library
+
+\author Adam Dunkels <adam@sics.se>
+
+Protothreads are a type of lightweight stackless threads designed for
+severly memory constrained systems such as deeply embedded systems or
+sensor network nodes. Protothreads provides linear code execution for
+event-driven systems implemented in C. Protothreads can be used with
+or without an RTOS.
+
+Protothreads are a extremely lightweight, stackless type of threads
+that provides a blocking context on top of an event-driven system,
+without the overhead of per-thread stacks. The purpose of protothreads
+is to implement sequential flow of control without complex state
+machines or full multi-threading. Protothreads provides conditional
+blocking inside C functions.
+
+Main features:
+
+ - No machine specific code - the protothreads library is pure C
+
+ - Does not use error-prone functions such as longjmp()
+
+ - Very small RAM overhead - only two bytes per protothread
+
+ - Can be used with or without an OS
+
+ - Provides blocking wait without full multi-threading or
+ stack-switching
+
+Examples applications:
+
+ - Memory constrained systems
+
+ - Event-driven protocol stacks
+
+ - Deeply embedded systems
+
+ - Sensor network nodes
+
+
+\sa \ref examples "Example programs"
+\sa \ref pt "Protothreads API documentation"
+
+The protothreads library is released under a BSD-style license that
+allows for both non-commercial and commercial usage. The only
+requirement is that credit is given.
+
+More information and new version of the code can be found at the
+Protothreads homepage:
+
+ http://www.sics.se/~adam/pt/
+
+\section authors Authors
+
+The protothreads library was written by Adam Dunkels <adam@sics.se>
+with support from Oliver Schmidt <ol.sc@web.de>.
+
+\section using Using protothreads
+
+Using protothreads in a project is easy: simply copy the files pt.h,
+lc.h and lc-switch.h into the include files directory of the project,
+and \#include "pt.h" in all files that should use protothreads.
+
+\section pt-desc Protothreads
+
+Protothreads are a extremely lightweight, stackless threads that
+provides a blocking context on top of an event-driven system, without
+the overhead of per-thread stacks. The purpose of protothreads is to
+implement sequential flow of control without using complex state
+machines or full multi-threading. Protothreads provides conditional
+blocking inside a C function.
+
+In memory constrained systems, such as deeply embedded systems,
+traditional multi-threading may have a too large memory overhead. In
+traditional multi-threading, each thread requires its own stack, that
+typically is over-provisioned. The stacks may use large parts of the
+available memory.
+
+The main advantage of protothreads over ordinary threads is that
+protothreads are very lightweight: a protothread does not require its
+own stack. Rather, all protothreads run on the same stack and context
+switching is done by stack rewinding. This is advantageous in memory
+constrained systems, where a stack for a thread might use a large part
+of the available memory. A protothread only requires only two bytes of
+memory per protothread. Moreover, protothreads are implemented in pure
+C and do not require any machine-specific assembler code.
+
+A protothread runs within a single C function and cannot span over
+other functions. A protothread may call normal C functions, but cannot
+block inside a called function. Blocking inside nested function calls
+is instead made by spawning a separate protothread for each
+potentially blocking function. The advantage of this approach is that
+blocking is explicit: the programmer knows exactly which functions
+that block that which functions the never blocks.
+
+Protothreads are similar to asymmetric co-routines. The main
+difference is that co-routines uses a separate stack for each
+co-routine, whereas protothreads are stackless. The most similar
+mechanism to protothreads are Python generators. These are also
+stackless constructs, but have a different purpose. Protothreads
+provides blocking contexts inside a C function, whereas Python
+generators provide multiple exit points from a generator function.
+
+\section pt-autovars Local variables
+
+\note
+Because protothreads do not save the stack context across a blocking
+call, local variables are not preserved when the protothread
+blocks. This means that local variables should be used with utmost
+care - if in doubt, do not use local variables inside a protothread!
+
+\section pt-scheduling Scheduling
+
+A protothread is driven by repeated calls to the function in which the
+protothread is running. Each time the function is called, the
+protothread will run until it blocks or exits. Thus the scheduling of
+protothreads is done by the application that uses protothreads.
+
+\section pt-impl Implementation
+
+Protothreads are implemented using local continuations. A local
+continuation represents the current state of execution at a particular
+place in the program, but does not provide any call history or local
+variables. A local continuation can be set in a specific function to
+capture the state of the function. After a local continuation has been
+set can be resumed in order to restore the state of the function at
+the point where the local continuation was set.
+
+
+Local continuations can be implemented in a variety of ways:
+
+ -# by using machine specific assembler code,
+ -# by using standard C constructs, or
+ -# by using compiler extensions.
+
+The first way works by saving and restoring the processor state,
+except for stack pointers, and requires between 16 and 32 bytes of
+memory per protothread. The exact amount of memory required depends on
+the architecture.
+
+The standard C implementation requires only two bytes of state per
+protothread and utilizes the C switch() statement in a non-obvious way
+that is similar to Duff's device. This implementation does, however,
+impose a slight restriction to the code that uses protothreads: a
+protothread cannot perform a blocking wait (PT_WAIT_UNTIL() or
+PT_YIELD()) inside a switch() statement.
+
+Certain compilers has C extensions that can be used to implement
+protothreads. GCC supports label pointers that can be used for this
+purpose. With this implementation, protothreads require 4 bytes of RAM
+per protothread.
+
+*/
diff --git a/third_party/pt/doc/sicslogo.pdf b/third_party/pt/doc/sicslogo.pdf
new file mode 100644
index 0000000..239a1bf
--- /dev/null
+++ b/third_party/pt/doc/sicslogo.pdf
Binary files differ
diff --git a/third_party/pt/example-buffer.c b/third_party/pt/example-buffer.c
new file mode 100644
index 0000000..3845824
--- /dev/null
+++ b/third_party/pt/example-buffer.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the protothreads library.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: example-buffer.c,v 1.5 2005/10/07 05:21:33 adam Exp $
+ */
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+#include <stdio.h>
+
+#include "pt-sem.h"
+
+#define NUM_ITEMS 32
+#define BUFSIZE 8
+
+static int buffer[BUFSIZE];
+static int bufptr;
+
+static void
+add_to_buffer(int item)
+{
+ printf("Item %d added to buffer at place %d\n", item, bufptr);
+ buffer[bufptr] = item;
+ bufptr = (bufptr + 1) % BUFSIZE;
+}
+static int
+get_from_buffer(void)
+{
+ int item;
+ item = buffer[bufptr];
+ printf("Item %d retrieved from buffer at place %d\n",
+ item, bufptr);
+ bufptr = (bufptr + 1) % BUFSIZE;
+ return item;
+}
+
+static int
+produce_item(void)
+{
+ static int item = 0;
+ printf("Item %d produced\n", item);
+ return item++;
+}
+
+static void
+consume_item(int item)
+{
+ printf("Item %d consumed\n", item);
+}
+
+static struct pt_sem full, empty;
+
+static
+PT_THREAD(producer(struct pt *pt))
+{
+ static int produced;
+
+ PT_BEGIN(pt);
+
+ for(produced = 0; produced < NUM_ITEMS; ++produced) {
+
+ PT_SEM_WAIT(pt, &full);
+
+ add_to_buffer(produce_item());
+
+ PT_SEM_SIGNAL(pt, &empty);
+ }
+
+ PT_END(pt);
+}
+
+static
+PT_THREAD(consumer(struct pt *pt))
+{
+ static int consumed;
+
+ PT_BEGIN(pt);
+
+ for(consumed = 0; consumed < NUM_ITEMS; ++consumed) {
+
+ PT_SEM_WAIT(pt, &empty);
+
+ consume_item(get_from_buffer());
+
+ PT_SEM_SIGNAL(pt, &full);
+ }
+
+ PT_END(pt);
+}
+
+static
+PT_THREAD(driver_thread(struct pt *pt))
+{
+ static struct pt pt_producer, pt_consumer;
+
+ PT_BEGIN(pt);
+
+ PT_SEM_INIT(&empty, 0);
+ PT_SEM_INIT(&full, BUFSIZE);
+
+ PT_INIT(&pt_producer);
+ PT_INIT(&pt_consumer);
+
+ PT_WAIT_THREAD(pt, producer(&pt_producer) &
+ consumer(&pt_consumer));
+
+ PT_END(pt);
+}
+
+
+int
+main(void)
+{
+ struct pt driver_pt;
+
+ PT_INIT(&driver_pt);
+
+ while(PT_SCHEDULE(driver_thread(&driver_pt))) {
+
+ /*
+ * When running this example on a multitasking system, we must
+ * give other processes a chance to run too and therefore we call
+ * usleep() resp. Sleep() here. On a dedicated embedded system,
+ * we usually do not need to do this.
+ */
+#ifdef _WIN32
+ Sleep(0);
+#else
+ usleep(10);
+#endif
+ }
+ return 0;
+}
diff --git a/third_party/pt/example-codelock.c b/third_party/pt/example-codelock.c
new file mode 100644
index 0000000..6df6fb0
--- /dev/null
+++ b/third_party/pt/example-codelock.c
@@ -0,0 +1,414 @@
+/*
+ * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the protothreads library.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: example-codelock.c,v 1.5 2005/10/06 07:57:08 adam Exp $
+ */
+
+/*
+ *
+ * This example shows how to implement a simple code lock. The code
+ * lock waits for key presses from a numeric keyboard and if the
+ * correct code is entered, the lock is unlocked. There is a maximum
+ * time of one second between each key press, and after the correct
+ * code has been entered, no more keys must be pressed for 0.5 seconds
+ * before the lock is opened.
+ *
+ * This is an example that shows two things:
+ * - how to implement a code lock key input mechanism, and
+ * - how to implement a sequential timed routine.
+ *
+ * The program consists of two protothreads, one that implements the
+ * code lock reader and one that implements simulated keyboard input.
+ *
+ *
+ */
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#include <sys/time.h>
+#endif
+#include <stdio.h>
+
+#include "pt.h"
+
+/*---------------------------------------------------------------------------*/
+/*
+ * The following definitions are just for the simple timer library
+ * used in this example. The actual implementation of the functions
+ * can be found at the end of this file.
+ */
+struct timer { int start, interval; };
+static int timer_expired(struct timer *t);
+static void timer_set(struct timer *t, int usecs);
+/*---------------------------------------------------------------------------*/
+/*
+ * This example uses two timers: one for the code lock protothread and
+ * one for the simulated key input protothread.
+ */
+static struct timer codelock_timer, input_timer;
+/*---------------------------------------------------------------------------*/
+/*
+ * This is the code that has to be entered.
+ */
+static const char code[4] = {'1', '4', '2', '3'};
+/*---------------------------------------------------------------------------*/
+/*
+ * This example has two protothread and therefor has two protothread
+ * control structures of type struct pt. These are initialized with
+ * PT_INIT() in the main() function below.
+ */
+static struct pt codelock_pt, input_pt;
+/*---------------------------------------------------------------------------*/
+/*
+ * The following code implements a simple key input. Input is made
+ * with the press_key() function, and the function key_pressed()
+ * checks if a key has been pressed. The variable "key" holds the
+ * latest key that was pressed. The variable "key_pressed_flag" is set
+ * when a key is pressed and cleared when a key press is checked.
+ */
+static char key, key_pressed_flag;
+
+static void
+press_key(char k)
+{
+ printf("--- Key '%c' pressed\n", k);
+ key = k;
+ key_pressed_flag = 1;
+}
+
+static int
+key_pressed(void)
+{
+ if(key_pressed_flag != 0) {
+ key_pressed_flag = 0;
+ return 1;
+ }
+ return 0;
+}
+/*---------------------------------------------------------------------------*/
+/*
+ * Declaration of the protothread function implementing the code lock
+ * logic. The protothread function is declared using the PT_THREAD()
+ * macro. The function is declared with the "static" keyword since it
+ * is local to this file. The name of the function is codelock_thread
+ * and it takes one argument, pt, of the type struct pt.
+ *
+ */
+static
+PT_THREAD(codelock_thread(struct pt *pt))
+{
+ /* This is a local variable that holds the number of keys that have
+ * been pressed. Note that it is declared with the "static" keyword
+ * to make sure that the variable is *not* allocated on the stack.
+ */
+ static int keys;
+
+ /*
+ * Declare the beginning of the protothread.
+ */
+ PT_BEGIN(pt);
+
+ /*
+ * We'll let the protothread loop until the protothread is
+ * expliticly exited with PT_EXIT().
+ */
+ while(1) {
+
+ /*
+ * We'll be reading key presses until we get the right amount of
+ * correct keys.
+ */
+ for(keys = 0; keys < sizeof(code); ++keys) {
+
+ /*
+ * If we haven't gotten any keypresses, we'll simply wait for one.
+ */
+ if(keys == 0) {
+
+ /*
+ * The PT_WAIT_UNTIL() function will block until the condition
+ * key_pressed() is true.
+ */
+ PT_WAIT_UNTIL(pt, key_pressed());
+ } else {
+
+ /*
+ * If the "key" variable was larger than zero, we have already
+ * gotten at least one correct key press. If so, we'll not
+ * only wait for the next key, but we'll also set a timer that
+ * expires in one second. This gives the person pressing the
+ * keys one second to press the next key in the code.
+ */
+ timer_set(&codelock_timer, 1000);
+
+ /*
+ * The following statement shows how complex blocking
+ * conditions can be easily expressed with protothreads and
+ * the PT_WAIT_UNTIL() function.
+ */
+ PT_WAIT_UNTIL(pt, key_pressed() || timer_expired(&codelock_timer));
+
+ /*
+ * If the timer expired, we should break out of the for() loop
+ * and start reading keys from the beginning of the while(1)
+ * loop instead.
+ */
+ if(timer_expired(&codelock_timer)) {
+ printf("Code lock timer expired.\n");
+
+ /*
+ * Break out from the for() loop and start from the
+ * beginning of the while(1) loop.
+ */
+ break;
+ }
+ }
+
+ /*
+ * Check if the pressed key was correct.
+ */
+ if(key != code[keys]) {
+ printf("Incorrect key '%c' found\n", key);
+ /*
+ * Break out of the for() loop since the key was incorrect.
+ */
+ break;
+ } else {
+ printf("Correct key '%c' found\n", key);
+ }
+ }
+
+ /*
+ * Check if we have gotten all keys.
+ */
+ if(keys == sizeof(code)) {
+ printf("Correct code entered, waiting for 500 ms before unlocking.\n");
+
+ /*
+ * Ok, we got the correct code. But to make sure that the code
+ * was not just a fluke of luck by an intruder, but the correct
+ * code entered by a person that knows the correct code, we'll
+ * wait for half a second before opening the lock. If another
+ * key is pressed during this time, we'll assume that it was a
+ * fluke of luck that the correct code was entered the first
+ * time.
+ */
+ timer_set(&codelock_timer, 500);
+ PT_WAIT_UNTIL(pt, key_pressed() || timer_expired(&codelock_timer));
+
+ /*
+ * If we continued from the PT_WAIT_UNTIL() statement without
+ * the timer expired, we don't open the lock.
+ */
+ if(!timer_expired(&codelock_timer)) {
+ printf("Key pressed during final wait, code lock locked again.\n");
+ } else {
+
+ /*
+ * If the timer expired, we'll open the lock and exit from the
+ * protothread.
+ */
+ printf("Code lock unlocked.\n");
+ PT_EXIT(pt);
+ }
+ }
+ }
+
+ /*
+ * Finally, we'll mark the end of the protothread.
+ */
+ PT_END(pt);
+}
+/*---------------------------------------------------------------------------*/
+/*
+ * This is the second protothread in this example. It implements a
+ * simulated user pressing the keys. This illustrates how a linear
+ * sequence of timed instructions can be implemented with
+ * protothreads.
+ */
+static
+PT_THREAD(input_thread(struct pt *pt))
+{
+ PT_BEGIN(pt);
+
+ printf("Waiting 1 second before entering first key.\n");
+
+ timer_set(&input_timer, 1000);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('1');
+
+ timer_set(&input_timer, 100);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('2');
+
+ timer_set(&input_timer, 100);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('3');
+
+ timer_set(&input_timer, 2000);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('1');
+
+ timer_set(&input_timer, 200);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('4');
+
+ timer_set(&input_timer, 200);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('2');
+
+ timer_set(&input_timer, 2000);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('3');
+
+ timer_set(&input_timer, 200);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('1');
+
+ timer_set(&input_timer, 200);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('4');
+
+ timer_set(&input_timer, 200);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('2');
+
+ timer_set(&input_timer, 100);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('3');
+
+ timer_set(&input_timer, 100);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('4');
+
+ timer_set(&input_timer, 1500);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('1');
+
+ timer_set(&input_timer, 300);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('4');
+
+ timer_set(&input_timer, 400);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('2');
+
+ timer_set(&input_timer, 500);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ press_key('3');
+
+ timer_set(&input_timer, 2000);
+ PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+ PT_END(pt);
+}
+/*---------------------------------------------------------------------------*/
+/*
+ * This is the main function. It initializes the two protothread
+ * control structures and schedules the two protothreads. The main
+ * function returns when the protothread the runs the code lock exits.
+ */
+int
+main(void)
+{
+ /*
+ * Initialize the two protothread control structures.
+ */
+ PT_INIT(&input_pt);
+ PT_INIT(&codelock_pt);
+
+ /*
+ * Schedule the two protothreads until the codelock_thread() exits.
+ */
+ while(PT_SCHEDULE(codelock_thread(&codelock_pt))) {
+ PT_SCHEDULE(input_thread(&input_pt));
+
+ /*
+ * When running this example on a multitasking system, we must
+ * give other processes a chance to run too and therefore we call
+ * usleep() resp. Sleep() here. On a dedicated embedded system,
+ * we usually do not need to do this.
+ */
+#ifdef _WIN32
+ Sleep(0);
+#else
+ usleep(10);
+#endif
+ }
+
+ return 0;
+}
+/*---------------------------------------------------------------------------*/
+/*
+ * Finally, the implementation of the simple timer library follows.
+ */
+#ifdef _WIN32
+
+static int clock_time(void)
+{ return (int)GetTickCount(); }
+
+#else /* _WIN32 */
+
+static int clock_time(void)
+{
+ struct timeval tv;
+ struct timezone tz;
+ gettimeofday(&tv, &tz);
+ return tv.tv_sec * 1000 + tv.tv_usec / 1000;
+}
+
+#endif /* _WIN32 */
+
+static int timer_expired(struct timer *t)
+{ return (int)(clock_time() - t->start) >= (int)t->interval; }
+
+static void timer_set(struct timer *t, int interval)
+{ t->interval = interval; t->start = clock_time(); }
+/*---------------------------------------------------------------------------*/
diff --git a/third_party/pt/example-small.c b/third_party/pt/example-small.c
new file mode 100644
index 0000000..f65836c
--- /dev/null
+++ b/third_party/pt/example-small.c
@@ -0,0 +1,97 @@
+/**
+ * This is a very small example that shows how to use
+ * protothreads. The program consists of two protothreads that wait
+ * for each other to toggle a variable.
+ */
+
+/* We must always include pt.h in our protothreads code. */
+#include "pt.h"
+
+#include <stdio.h> /* For printf(). */
+
+/* Two flags that the two protothread functions use. */
+static int protothread1_flag, protothread2_flag;
+
+/**
+ * The first protothread function. A protothread function must always
+ * return an integer, but must never explicitly return - returning is
+ * performed inside the protothread statements.
+ *
+ * The protothread function is driven by the main loop further down in
+ * the code.
+ */
+static int
+protothread1(struct pt *pt)
+{
+ /* A protothread function must begin with PT_BEGIN() which takes a
+ pointer to a struct pt. */
+ PT_BEGIN(pt);
+
+ /* We loop forever here. */
+ while(1) {
+ /* Wait until the other protothread has set its flag. */
+ PT_WAIT_UNTIL(pt, protothread2_flag != 0);
+ printf("Protothread 1 running\n");
+
+ /* We then reset the other protothread's flag, and set our own
+ flag so that the other protothread can run. */
+ protothread2_flag = 0;
+ protothread1_flag = 1;
+
+ /* And we loop. */
+ }
+
+ /* All protothread functions must end with PT_END() which takes a
+ pointer to a struct pt. */
+ PT_END(pt);
+}
+
+/**
+ * The second protothread function. This is almost the same as the
+ * first one.
+ */
+static int
+protothread2(struct pt *pt)
+{
+ PT_BEGIN(pt);
+
+ while(1) {
+ /* Let the other protothread run. */
+ protothread2_flag = 1;
+
+ /* Wait until the other protothread has set its flag. */
+ PT_WAIT_UNTIL(pt, protothread1_flag != 0);
+ printf("Protothread 2 running\n");
+
+ /* We then reset the other protothread's flag. */
+ protothread1_flag = 0;
+
+ /* And we loop. */
+ }
+ PT_END(pt);
+}
+
+/**
+ * Finally, we have the main loop. Here is where the protothreads are
+ * initialized and scheduled. First, however, we define the
+ * protothread state variables pt1 and pt2, which hold the state of
+ * the two protothreads.
+ */
+static struct pt pt1, pt2;
+int
+main(void)
+{
+ /* Initialize the protothread state variables with PT_INIT(). */
+ PT_INIT(&pt1);
+ PT_INIT(&pt2);
+
+ /*
+ * Then we schedule the two protothreads by repeatedly calling their
+ * protothread functions and passing a pointer to the protothread
+ * state variables as arguments.
+ */
+ while(1) {
+ protothread1(&pt1);
+ protothread2(&pt2);
+ }
+}
diff --git a/third_party/pt/lc-addrlabels.h b/third_party/pt/lc-addrlabels.h
new file mode 100644
index 0000000..3e6474e
--- /dev/null
+++ b/third_party/pt/lc-addrlabels.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the Contiki operating system.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: lc-addrlabels.h,v 1.4 2006/06/03 11:29:43 adam Exp $
+ */
+
+/**
+ * \addtogroup lc
+ * @{
+ */
+
+/**
+ * \file
+ * Implementation of local continuations based on the "Labels as
+ * values" feature of gcc
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ * This implementation of local continuations is based on a special
+ * feature of the GCC C compiler called "labels as values". This
+ * feature allows assigning pointers with the address of the code
+ * corresponding to a particular C label.
+ *
+ * For more information, see the GCC documentation:
+ * http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
+ *
+ */
+
+#ifndef __LC_ADDRLABELS_H__
+#define __LC_ADDRLABELS_H__
+
+/** \hideinitializer */
+typedef void * lc_t;
+
+#define LC_INIT(s) s = NULL
+
+#define LC_RESUME(s) \
+ do { \
+ if(s != NULL) { \
+ goto *s; \
+ } \
+ } while(0)
+
+#define LC_CONCAT2(s1, s2) s1##s2
+#define LC_CONCAT(s1, s2) LC_CONCAT2(s1, s2)
+
+#define LC_SET(s) \
+ do { \
+ LC_CONCAT(LC_LABEL, __LINE__): \
+ (s) = &&LC_CONCAT(LC_LABEL, __LINE__); \
+ } while(0)
+
+#define LC_END(s)
+
+#endif /* __LC_ADDRLABELS_H__ */
+/** @} */
diff --git a/third_party/pt/lc-switch.h b/third_party/pt/lc-switch.h
new file mode 100644
index 0000000..dbdde01
--- /dev/null
+++ b/third_party/pt/lc-switch.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the Contiki operating system.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: lc-switch.h,v 1.4 2006/06/03 11:29:43 adam Exp $
+ */
+
+/**
+ * \addtogroup lc
+ * @{
+ */
+
+/**
+ * \file
+ * Implementation of local continuations based on switch() statment
+ * \author Adam Dunkels <adam@sics.se>
+ *
+ * This implementation of local continuations uses the C switch()
+ * statement to resume execution of a function somewhere inside the
+ * function's body. The implementation is based on the fact that
+ * switch() statements are able to jump directly into the bodies of
+ * control structures such as if() or while() statmenets.
+ *
+ * This implementation borrows heavily from Simon Tatham's coroutines
+ * implementation in C:
+ * http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
+ */
+
+#ifndef __LC_SWITCH_H__
+#define __LC_SWITCH_H__
+
+/* WARNING! lc implementation using switch() does not work if an
+ LC_SET() is done within another switch() statement! */
+
+/** \hideinitializer */
+typedef unsigned short lc_t;
+
+#define LC_INIT(s) s = 0;
+
+#define LC_RESUME(s) switch(s) { case 0:
+
+#define LC_SET(s) s = __LINE__; case __LINE__:
+
+#define LC_END(s) }
+
+#endif /* __LC_SWITCH_H__ */
+
+/** @} */
diff --git a/third_party/pt/lc.h b/third_party/pt/lc.h
new file mode 100644
index 0000000..0cf57e0
--- /dev/null
+++ b/third_party/pt/lc.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the protothreads library.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: lc.h,v 1.2 2005/02/24 10:36:59 adam Exp $
+ */
+
+/**
+ * \addtogroup pt
+ * @{
+ */
+
+/**
+ * \defgroup lc Local continuations
+ * @{
+ *
+ * Local continuations form the basis for implementing protothreads. A
+ * local continuation can be <i>set</i> in a specific function to
+ * capture the state of the function. After a local continuation has
+ * been set can be <i>resumed</i> in order to restore the state of the
+ * function at the point where the local continuation was set.
+ *
+ *
+ */
+
+/**
+ * \file lc.h
+ * Local continuations
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#ifdef DOXYGEN
+/**
+ * Initialize a local continuation.
+ *
+ * This operation initializes the local continuation, thereby
+ * unsetting any previously set continuation state.
+ *
+ * \hideinitializer
+ */
+#define LC_INIT(lc)
+
+/**
+ * Set a local continuation.
+ *
+ * The set operation saves the state of the function at the point
+ * where the operation is executed. As far as the set operation is
+ * concerned, the state of the function does <b>not</b> include the
+ * call-stack or local (automatic) variables, but only the program
+ * counter and such CPU registers that needs to be saved.
+ *
+ * \hideinitializer
+ */
+#define LC_SET(lc)
+
+/**
+ * Resume a local continuation.
+ *
+ * The resume operation resumes a previously set local continuation, thus
+ * restoring the state in which the function was when the local
+ * continuation was set. If the local continuation has not been
+ * previously set, the resume operation does nothing.
+ *
+ * \hideinitializer
+ */
+#define LC_RESUME(lc)
+
+/**
+ * Mark the end of local continuation usage.
+ *
+ * The end operation signifies that local continuations should not be
+ * used any more in the function. This operation is not needed for
+ * most implementations of local continuation, but is required by a
+ * few implementations.
+ *
+ * \hideinitializer
+ */
+#define LC_END(lc)
+
+/**
+ * \var typedef lc_t;
+ *
+ * The local continuation type.
+ *
+ * \hideinitializer
+ */
+#endif /* DOXYGEN */
+
+#ifndef __LC_H__
+#define __LC_H__
+
+
+#ifdef LC_INCLUDE
+#include LC_INCLUDE
+#else
+#include "lc-switch.h"
+#endif /* LC_INCLUDE */
+
+#endif /* __LC_H__ */
+
+/** @} */
+/** @} */
diff --git a/third_party/pt/pt-sem.h b/third_party/pt/pt-sem.h
new file mode 100644
index 0000000..5180dc6
--- /dev/null
+++ b/third_party/pt/pt-sem.h
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the protothreads library.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: pt-sem.h,v 1.2 2005/02/24 10:36:59 adam Exp $
+ */
+
+/**
+ * \addtogroup pt
+ * @{
+ */
+
+/**
+ * \defgroup ptsem Protothread semaphores
+ * @{
+ *
+ * This module implements counting semaphores on top of
+ * protothreads. Semaphores are a synchronization primitive that
+ * provide two operations: "wait" and "signal". The "wait" operation
+ * checks the semaphore counter and blocks the thread if the counter
+ * is zero. The "signal" operation increases the semaphore counter but
+ * does not block. If another thread has blocked waiting for the
+ * semaphore that is signalled, the blocked thread will become
+ * runnable again.
+ *
+ * Semaphores can be used to implement other, more structured,
+ * synchronization primitives such as monitors and message
+ * queues/bounded buffers (see below).
+ *
+ * The following example shows how the producer-consumer problem, also
+ * known as the bounded buffer problem, can be solved using
+ * protothreads and semaphores. Notes on the program follow after the
+ * example.
+ *
+ \code
+#include "pt-sem.h"
+
+#define NUM_ITEMS 32
+#define BUFSIZE 8
+
+static struct pt_sem mutex, full, empty;
+
+PT_THREAD(producer(struct pt *pt))
+{
+ static int produced;
+
+ PT_BEGIN(pt);
+
+ for(produced = 0; produced < NUM_ITEMS; ++produced) {
+
+ PT_SEM_WAIT(pt, &full);
+
+ PT_SEM_WAIT(pt, &mutex);
+ add_to_buffer(produce_item());
+ PT_SEM_SIGNAL(pt, &mutex);
+
+ PT_SEM_SIGNAL(pt, &empty);
+ }
+
+ PT_END(pt);
+}
+
+PT_THREAD(consumer(struct pt *pt))
+{
+ static int consumed;
+
+ PT_BEGIN(pt);
+
+ for(consumed = 0; consumed < NUM_ITEMS; ++consumed) {
+
+ PT_SEM_WAIT(pt, &empty);
+
+ PT_SEM_WAIT(pt, &mutex);
+ consume_item(get_from_buffer());
+ PT_SEM_SIGNAL(pt, &mutex);
+
+ PT_SEM_SIGNAL(pt, &full);
+ }
+
+ PT_END(pt);
+}
+
+PT_THREAD(driver_thread(struct pt *pt))
+{
+ static struct pt pt_producer, pt_consumer;
+
+ PT_BEGIN(pt);
+
+ PT_SEM_INIT(&empty, 0);
+ PT_SEM_INIT(&full, BUFSIZE);
+ PT_SEM_INIT(&mutex, 1);
+
+ PT_INIT(&pt_producer);
+ PT_INIT(&pt_consumer);
+
+ PT_WAIT_THREAD(pt, producer(&pt_producer) &
+ consumer(&pt_consumer));
+
+ PT_END(pt);
+}
+ \endcode
+ *
+ * The program uses three protothreads: one protothread that
+ * implements the consumer, one thread that implements the producer,
+ * and one protothread that drives the two other protothreads. The
+ * program uses three semaphores: "full", "empty" and "mutex". The
+ * "mutex" semaphore is used to provide mutual exclusion for the
+ * buffer, the "empty" semaphore is used to block the consumer is the
+ * buffer is empty, and the "full" semaphore is used to block the
+ * producer is the buffer is full.
+ *
+ * The "driver_thread" holds two protothread state variables,
+ * "pt_producer" and "pt_consumer". It is important to note that both
+ * these variables are declared as <i>static</i>. If the static
+ * keyword is not used, both variables are stored on the stack. Since
+ * protothreads do not store the stack, these variables may be
+ * overwritten during a protothread wait operation. Similarly, both
+ * the "consumer" and "producer" protothreads declare their local
+ * variables as static, to avoid them being stored on the stack.
+ *
+ *
+ */
+
+/**
+ * \file
+ * Couting semaphores implemented on protothreads
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#ifndef __PT_SEM_H__
+#define __PT_SEM_H__
+
+#include "pt.h"
+
+struct pt_sem {
+ unsigned int count;
+};
+
+/**
+ * Initialize a semaphore
+ *
+ * This macro initializes a semaphore with a value for the
+ * counter. Internally, the semaphores use an "unsigned int" to
+ * represent the counter, and therefore the "count" argument should be
+ * within range of an unsigned int.
+ *
+ * \param s (struct pt_sem *) A pointer to the pt_sem struct
+ * representing the semaphore
+ *
+ * \param c (unsigned int) The initial count of the semaphore.
+ * \hideinitializer
+ */
+#define PT_SEM_INIT(s, c) (s)->count = c
+
+/**
+ * Wait for a semaphore
+ *
+ * This macro carries out the "wait" operation on the semaphore. The
+ * wait operation causes the protothread to block while the counter is
+ * zero. When the counter reaches a value larger than zero, the
+ * protothread will continue.
+ *
+ * \param pt (struct pt *) A pointer to the protothread (struct pt) in
+ * which the operation is executed.
+ *
+ * \param s (struct pt_sem *) A pointer to the pt_sem struct
+ * representing the semaphore
+ *
+ * \hideinitializer
+ */
+#define PT_SEM_WAIT(pt, s) \
+ do { \
+ PT_WAIT_UNTIL(pt, (s)->count > 0); \
+ --(s)->count; \
+ } while(0)
+
+/**
+ * Signal a semaphore
+ *
+ * This macro carries out the "signal" operation on the semaphore. The
+ * signal operation increments the counter inside the semaphore, which
+ * eventually will cause waiting protothreads to continue executing.
+ *
+ * \param pt (struct pt *) A pointer to the protothread (struct pt) in
+ * which the operation is executed.
+ *
+ * \param s (struct pt_sem *) A pointer to the pt_sem struct
+ * representing the semaphore
+ *
+ * \hideinitializer
+ */
+#define PT_SEM_SIGNAL(pt, s) ++(s)->count
+
+#endif /* __PT_SEM_H__ */
+
+/** @} */
+/** @} */
diff --git a/third_party/pt/pt.h b/third_party/pt/pt.h
new file mode 100644
index 0000000..92856cb
--- /dev/null
+++ b/third_party/pt/pt.h
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the Contiki operating system.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: pt.h,v 1.7 2006/10/02 07:52:56 adam Exp $
+ */
+
+/**
+ * \addtogroup pt
+ * @{
+ */
+
+/**
+ * \file
+ * Protothreads implementation.
+ * \author
+ * Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#ifndef __PT_H__
+#define __PT_H__
+
+#include "lc.h"
+
+struct pt {
+ lc_t lc;
+};
+
+#define PT_WAITING 0
+#define PT_YIELDED 1
+#define PT_EXITED 2
+#define PT_ENDED 3
+
+/**
+ * \name Initialization
+ * @{
+ */
+
+/**
+ * Initialize a protothread.
+ *
+ * Initializes a protothread. Initialization must be done prior to
+ * starting to execute the protothread.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \sa PT_SPAWN()
+ *
+ * \hideinitializer
+ */
+#define PT_INIT(pt) LC_INIT((pt)->lc)
+
+/** @} */
+
+/**
+ * \name Declaration and definition
+ * @{
+ */
+
+/**
+ * Declaration of a protothread.
+ *
+ * This macro is used to declare a protothread. All protothreads must
+ * be declared with this macro.
+ *
+ * \param name_args The name and arguments of the C function
+ * implementing the protothread.
+ *
+ * \hideinitializer
+ */
+#define PT_THREAD(name_args) char name_args
+
+/**
+ * Declare the start of a protothread inside the C function
+ * implementing the protothread.
+ *
+ * This macro is used to declare the starting point of a
+ * protothread. It should be placed at the start of the function in
+ * which the protothread runs. All C statements above the PT_BEGIN()
+ * invokation will be executed each time the protothread is scheduled.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; LC_RESUME((pt)->lc)
+
+/**
+ * Declare the end of a protothread.
+ *
+ * This macro is used for declaring that a protothread ends. It must
+ * always be used together with a matching PT_BEGIN() macro.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; \
+ PT_INIT(pt); return PT_ENDED; }
+
+/** @} */
+
+/**
+ * \name Blocked wait
+ * @{
+ */
+
+/**
+ * Block and wait until condition is true.
+ *
+ * This macro blocks the protothread until the specified condition is
+ * true.
+ *
+ * \param pt A pointer to the protothread control structure.
+ * \param condition The condition.
+ *
+ * \hideinitializer
+ */
+#define PT_WAIT_UNTIL(pt, condition) \
+ do { \
+ LC_SET((pt)->lc); \
+ if(!(condition)) { \
+ return PT_WAITING; \
+ } \
+ } while(0)
+
+/**
+ * Block and wait while condition is true.
+ *
+ * This function blocks and waits while condition is true. See
+ * PT_WAIT_UNTIL().
+ *
+ * \param pt A pointer to the protothread control structure.
+ * \param cond The condition.
+ *
+ * \hideinitializer
+ */
+#define PT_WAIT_WHILE(pt, cond) PT_WAIT_UNTIL((pt), !(cond))
+
+/** @} */
+
+/**
+ * \name Hierarchical protothreads
+ * @{
+ */
+
+/**
+ * Block and wait until a child protothread completes.
+ *
+ * This macro schedules a child protothread. The current protothread
+ * will block until the child protothread completes.
+ *
+ * \note The child protothread must be manually initialized with the
+ * PT_INIT() function before this function is used.
+ *
+ * \param pt A pointer to the protothread control structure.
+ * \param thread The child protothread with arguments
+ *
+ * \sa PT_SPAWN()
+ *
+ * \hideinitializer
+ */
+#define PT_WAIT_THREAD(pt, thread) PT_WAIT_WHILE((pt), PT_SCHEDULE(thread))
+
+/**
+ * Spawn a child protothread and wait until it exits.
+ *
+ * This macro spawns a child protothread and waits until it exits. The
+ * macro can only be used within a protothread.
+ *
+ * \param pt A pointer to the protothread control structure.
+ * \param child A pointer to the child protothread's control structure.
+ * \param thread The child protothread with arguments
+ *
+ * \hideinitializer
+ */
+#define PT_SPAWN(pt, child, thread) \
+ do { \
+ PT_INIT((child)); \
+ PT_WAIT_THREAD((pt), (thread)); \
+ } while(0)
+
+/** @} */
+
+/**
+ * \name Exiting and restarting
+ * @{
+ */
+
+/**
+ * Restart the protothread.
+ *
+ * This macro will block and cause the running protothread to restart
+ * its execution at the place of the PT_BEGIN() call.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_RESTART(pt) \
+ do { \
+ PT_INIT(pt); \
+ return PT_WAITING; \
+ } while(0)
+
+/**
+ * Exit the protothread.
+ *
+ * This macro causes the protothread to exit. If the protothread was
+ * spawned by another protothread, the parent protothread will become
+ * unblocked and can continue to run.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_EXIT(pt) \
+ do { \
+ PT_INIT(pt); \
+ return PT_EXITED; \
+ } while(0)
+
+/** @} */
+
+/**
+ * \name Calling a protothread
+ * @{
+ */
+
+/**
+ * Schedule a protothread.
+ *
+ * This function shedules a protothread. The return value of the
+ * function is non-zero if the protothread is running or zero if the
+ * protothread has exited.
+ *
+ * \param f The call to the C function implementing the protothread to
+ * be scheduled
+ *
+ * \hideinitializer
+ */
+#define PT_SCHEDULE(f) ((f) < PT_EXITED)
+
+/** @} */
+
+/**
+ * \name Yielding from a protothread
+ * @{
+ */
+
+/**
+ * Yield from the current protothread.
+ *
+ * This function will yield the protothread, thereby allowing other
+ * processing to take place in the system.
+ *
+ * \param pt A pointer to the protothread control structure.
+ *
+ * \hideinitializer
+ */
+#define PT_YIELD(pt) \
+ do { \
+ PT_YIELD_FLAG = 0; \
+ LC_SET((pt)->lc); \
+ if(PT_YIELD_FLAG == 0) { \
+ return PT_YIELDED; \
+ } \
+ } while(0)
+
+/**
+ * \brief Yield from the protothread until a condition occurs.
+ * \param pt A pointer to the protothread control structure.
+ * \param cond The condition.
+ *
+ * This function will yield the protothread, until the
+ * specified condition evaluates to true.
+ *
+ *
+ * \hideinitializer
+ */
+#define PT_YIELD_UNTIL(pt, cond) \
+ do { \
+ PT_YIELD_FLAG = 0; \
+ LC_SET((pt)->lc); \
+ if((PT_YIELD_FLAG == 0) || !(cond)) { \
+ return PT_YIELDED; \
+ } \
+ } while(0)
+
+/** @} */
+
+#endif /* __PT_H__ */
+
+/** @} */