summaryrefslogtreecommitdiff
path: root/graphics/asymptote/LspCpp/third_party
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2021-12-28 03:01:00 +0000
committerNorbert Preining <norbert@preining.info>2021-12-28 03:01:00 +0000
commitecdf859b6ce481abfd530425dcf6f0f764bd0001 (patch)
tree13bc161dc046876ac6c92fce5f9f5034ba9aa573 /graphics/asymptote/LspCpp/third_party
parent790995b7e79697514364450bf9c04f1b8d500838 (diff)
CTAN sync 202112280300
Diffstat (limited to 'graphics/asymptote/LspCpp/third_party')
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/CHANGE_LOG88
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/COPYING5
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/Jamfile.v213
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/Jamrules1
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/LICENSE_1_0.txt23
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/Makefile32
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/README10
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/TODO36
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool.hpp28
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/future.hpp215
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/locking_ptr.hpp85
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/pool_core.hpp453
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/scope_guard.hpp65
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/worker_thread.hpp115
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/future.hpp144
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/pool.hpp232
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/pool_adaptors.hpp70
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/scheduling_policies.hpp262
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/shutdown_policies.hpp83
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/size_policies.hpp99
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/task_adaptors.hpp168
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/Makefile36
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/design.dox145
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/design.txt35
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/design_header.htm38
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/examples.dox145
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/examples.txt14
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/examples_header.htm38
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer/common_footer.htm17
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer/overview_footer.htm17
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer_sf/common_footer.htm30
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer_sf/overview_footer.htm29
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/index.html9
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/overview.dox145
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/overview.txt205
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/overview_header.htm36
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/reference.dox220
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/reference_header.htm40
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/threadpool.css331
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/tutorial.dox145
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/tutorial.txt207
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/tutorial_header.htm40
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/example/mergesort/Jamfile.v211
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/example/mergesort/mergesort.cpp200
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/quickstart/Jamfile.v211
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/quickstart/README7
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/quickstart/quickstart.cpp50
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/test/compile_all/Jamfile.v211
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/test/compile_all/compile_all.cpp149
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/tutorial/Jamfile.v211
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/tutorial/tutorial.cpp263
-rw-r--r--graphics/asymptote/LspCpp/third_party/threadpool/project-root.jam2
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/CMakeLists.txt42
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/LICENSE23
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/README.md1503
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/samples/docsample.cpp64
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8.h34
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/checked.h335
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/core.h338
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/cpp11.h103
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/cpp17.h103
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/unchecked.h274
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/tests/CMakeLists.txt47
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/tests/docker/Dockerfile5
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/tests/negative.cpp59
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_checked_api.cpp189
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_checked_iterator.cpp32
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_cpp11.cpp109
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_cpp17.cpp88
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_data/utf8_invalid.txtbin0 -> 20010 bytes
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_unchecked_api.cpp161
-rw-r--r--graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_unchecked_iterator.cpp34
72 files changed, 8407 insertions, 0 deletions
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/CHANGE_LOG b/graphics/asymptote/LspCpp/third_party/threadpool/CHANGE_LOG
new file mode 100644
index 0000000000..635fbcfde5
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/CHANGE_LOG
@@ -0,0 +1,88 @@
+Change Log
+
+0.2.5
+ - Made threadpool compatible to boost::thread 1.37
+ - Fixed hang problem in shutdown method (Thanks to Sohail Somani)
+ - Adapted repository layout to boost (Thanks to Alex Ott)
+
+0.2.4 (Stable)
+ - Made threadpool compatible to boost::thread 1.35.x code base
+ - Fixed compiler warning in scope_guard.hpp
+
+0.2.3 (Development)
+ - Implemented workaround for Sun C++ Pro compiler bug in pool_core
+ - Removed subtask implementation (there was no demand for this feature)
+ - Improved shutdown policies
+
+0.2.2 (Development)
+ - Refactored SizePolicy and added SizePolicyController
+ - Moved policies into separate files
+ - Fixed some compiler problems (GCC)
+ - Implemented size_controller handling
+ - Implemented two size policies: static_size and fixed_size
+ - Refactored worker_thread handling, moved policies from pool_core to pool
+ - Specialized schedule function for usage with futures
+ - Added compile test project
+ - Improved constness in pool core class
+ - Fixed timed wait
+ - Implemented futures (in progress)
+ - Added result_type to all functors
+
+0.2.1 (Development)
+ - Pool base class (thread_pool) has now reference semantics
+ - Large refactorings: Removed scoped_pool, reimplemented worker (now worker_thread)
+ - Fixed odd resize behaviour. Now resize changes the number of threads immediately
+ - Apply pimpl idiom on pool core class (to make the ugly scoped_pool class needless)
+ - Introduced scheduling policies
+ - Switched to policy-based design (PBD), inspired by Scott Meyers C++ workshop
+ - Cosmetic code change: Replaced keyword 'class' with 'typename' in template definitions
+ - Revised tutorials
+ - New requirements: tasks functions should not and schedulers shall not throw exceptions
+
+
+0.2.0 (Development)
+ - Moved threadpool into the boost namespace: boost::threadpool
+ - Used keyword volatile to indicate thread-safe member functions
+ - Used volatile on primitve types were appropriate
+ - Moved worker to detail directory
+ - Fixed thread deletion
+ - Extended wait functionality (waiting for idle threads was implemented)
+ - Renamed 'join()' to 'wait()' as 'join' indicates the termination of thread. That was not the case in pool::join.
+ - Changed internal container of lifo and fifo schedulers to improve efficiency.
+ - Improved code reference documentation (source code browser)
+ - Renamed thread_func into task_func
+ - Added += operator to scoped_pool to ease scheduling of tasks
+ - Refactored file structures and class names
+ - Added a new task concept (named subtask) which allows the combination of sequential and parallel execution
+ - Added new task adaptor for looped or timed tasks: looped_task_func
+ - Introduced function clear() which can be used to remove all tasks from the pool and schedulers
+ - New function pool::active() which returns the number of active tasks
+
+0.1.8 (Development)
+ - Fixed some compile errors which were reported by gcc
+ - Wrote tutorial "Prioritized Tasks"
+
+0.1.7 (Development)
+ - Added Visual Studio 2005 project files for tutorial and examples
+
+0.1.6 (Development)
+ - Replaced task adaptor 'task' with boost::bind
+ - Workers are unregistered from thread_group when they are terminated
+ - Working on example boost::iostreams packet_filter
+
+0.1.5 (Development)
+ - Finished threadpool reference
+ - Class pool_adaptor was replaced by smart_pool
+ - Minor pool improvements
+ - First tutorial page online
+
+0.1.4 (Development)
+ - Created the pool's homepage: http://threadpool.sourceforge.net
+ - Improved documentation
+ - Added build scripts
+
+0.1.3 (Development)
+ - First public release
+ - Added mergesort example
+ - Added tutorial
+ - Implementation of threadpool core and related classes \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/COPYING b/graphics/asymptote/LspCpp/third_party/threadpool/COPYING
new file mode 100644
index 0000000000..06bdc4605a
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/COPYING
@@ -0,0 +1,5 @@
+Copyright (c) 2005-2007 Philipp Henkel
+
+Use, modification, and distribution are subject to the
+Boost Software License, Version 1.0. (See accompanying file
+LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/Jamfile.v2 b/graphics/asymptote/LspCpp/third_party/threadpool/Jamfile.v2
new file mode 100644
index 0000000000..56c8549755
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/Jamfile.v2
@@ -0,0 +1,13 @@
+use-project /boost
+ : $(BOOST_ROOT)
+ ;
+
+project threadpool
+ : requirements <include>.&&$(BOOST_ROOT)
+ # disable auto-linking for all targets here,
+ # primarily because it caused troubles with V2
+ <define>BOOST_ALL_NO_LIB=1
+ : usage-requirements <include>.&&$(BOOST_ROOT)
+ : build-dir bin.v2
+ ;
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/Jamrules b/graphics/asymptote/LspCpp/third_party/threadpool/Jamrules
new file mode 100644
index 0000000000..8571a1461c
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/Jamrules
@@ -0,0 +1 @@
+project boost : $(BOOST_ROOT) ;
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/LICENSE_1_0.txt b/graphics/asymptote/LspCpp/third_party/threadpool/LICENSE_1_0.txt
new file mode 100644
index 0000000000..36b7cd93cd
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/LICENSE_1_0.txt
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/Makefile b/graphics/asymptote/LspCpp/third_party/threadpool/Makefile
new file mode 100644
index 0000000000..9acf23b272
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/Makefile
@@ -0,0 +1,32 @@
+export RELEASE_MANAGER=philipphenkel
+export RELEASE_VERSION=0_2_5
+
+doc: clean
+ make --directory=./libs/threadpool/doc --print-directory doc
+
+release_doc:
+ make --directory=./libs/threadpool/doc --print-directory release_doc
+
+release_src: clean fetch_clean_src
+ mv clean_src threadpool-$(RELEASE_VERSION)-src
+ zip -r9 threadpool-$(RELEASE_VERSION)-src.zip threadpool-$(RELEASE_VERSION)-src
+ rm -rf threadpool-$(RELEASE_VERSION)-src
+
+deploy_website:
+ make --directory=./libs/threadpool/doc --print-directory deploy_sf
+
+clean:
+ rm -rf clean_src
+ rm -rf threadpool-$(RELEASE_VERSION)-src.zip
+ rm -rf threadpool-$(RELEASE_VERSION)-doc.zip
+ make --directory=./libs/threadpool/doc --print-directory clean
+
+fetch_clean_src:
+ rm -rf clean_src
+ mkdir clean_src
+# cvs -d:pserver:anonymous@threadpool.cvs.sourceforge.net:/cvsroot/threadpool login
+ cd clean_src; cvs -z3 -d:pserver:anonymous@threadpool.cvs.sourceforge.net:/cvsroot/threadpool export -r RELEASE_$(RELEASE_VERSION) threadpool
+# cd clean_src; cvs -z3 -d:ext:$(RELEASE_MANAGER)@cvs.sourceforge.net:/cvsroot/threadpool export -r RELEASE_$(RELEASE_VERSION) threadpool
+
+
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/README b/graphics/asymptote/LspCpp/third_party/threadpool/README
new file mode 100644
index 0000000000..c6f1a83d81
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/README
@@ -0,0 +1,10 @@
+threadpool
+
+Copyright (c) 2005-2007 Philipp Henkel
+
+threadpool is a cross-platform C++ thread pool library and released under the Boost Software License.
+
+See doc/index.html for information on:
+ - API documentation and a tutorial
+ - External dependencies
+ - Using threadpool
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/TODO b/graphics/asymptote/LspCpp/third_party/threadpool/TODO
new file mode 100644
index 0000000000..1c5e6e26d6
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/TODO
@@ -0,0 +1,36 @@
+threadpool to-do items
+======================
+
+Documentation
+--------------------------------------------
+- Source code documentation
+- Design rationale
+- Tutorial
+- Finish Quickstart Tutorial/Example
+
+Functionality
+--------------------------------------------
+- Implement a size policy which dynamically
+ increase/decrease the pool's size:
+ - init with min/max threads
+ - auto increase
+ - auto decrease (using timed cleanup tasks)
+- Add some kind of deadline scheduler
+- Add futures to pool
+
+
+Examples
+--------------------------------------------
+- Buffering Client Requests: Handle 'bursty' client traffic
+ Some applications need more buffering than is provided by OS I/O subsystem
+
+ Working on 'active' buffer for boost::iostreams
+ buffer_filter which provides a dynamic amount of buffer objects.
+ buffer_filter uses a threadpool with one thread which provides the buffers to
+ consumer. (TODO Philipp)
+
+ 2nd implemention step:
+ Flexbile configuration: Buffer capacities can be configured according to
+ - maximum number of requests
+ - maximum number of bytes
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool.hpp
new file mode 100644
index 0000000000..7d9ee48010
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool.hpp
@@ -0,0 +1,28 @@
+/*! \file
+* \brief Main include.
+*
+* This is the only file you have to include in order to use the
+* complete threadpool library.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* 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)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+#ifndef THREADPOOL_HPP_INCLUDED
+#define THREADPOOL_HPP_INCLUDED
+
+#include "./threadpool/future.hpp"
+#include "./threadpool/pool.hpp"
+
+#include "./threadpool/pool_adaptors.hpp"
+#include "./threadpool/task_adaptors.hpp"
+
+
+#endif // THREADPOOL_HPP_INCLUDED
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/future.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/future.hpp
new file mode 100644
index 0000000000..4e4b35bebe
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/future.hpp
@@ -0,0 +1,215 @@
+/*! \file
+* \brief TODO.
+*
+* TODO.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* 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)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+
+#ifndef THREADPOOL_DETAIL_FUTURE_IMPL_HPP_INCLUDED
+#define THREADPOOL_DETAIL_FUTURE_IMPL_HPP_INCLUDED
+
+
+#include "locking_ptr.hpp"
+
+#include <boost/smart_ptr.hpp>
+#include <boost/optional.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/thread/xtime.hpp>
+#include <boost/utility/result_of.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits.hpp>
+
+namespace boost { namespace threadpool { namespace detail
+{
+
+template<class Result>
+class future_impl
+{
+public:
+ typedef Result const & result_type; //!< Indicates the functor's result type.
+
+ typedef Result future_result_type; //!< Indicates the future's result type.
+ typedef future_impl<future_result_type> future_type;
+
+private:
+ volatile bool m_ready;
+ volatile future_result_type m_result;
+
+ mutable mutex m_monitor;
+ mutable condition m_condition_ready;
+
+ volatile bool m_is_cancelled;
+ volatile bool m_executing;
+
+public:
+
+
+public:
+
+ future_impl()
+ : m_ready(false)
+ , m_is_cancelled(false)
+ {
+ }
+
+ bool ready() const volatile
+ {
+ return m_ready;
+ }
+
+ void wait() const volatile
+ {
+ const future_type* self = const_cast<const future_type*>(this);
+ mutex::scoped_lock lock(self->m_monitor);
+
+ while(!m_ready)
+ {
+ self->m_condition_ready.wait(lock);
+ }
+ }
+
+
+ bool timed_wait(boost::xtime const & timestamp) const
+ {
+ const future_type* self = const_cast<const future_type*>(this);
+ mutex::scoped_lock lock(self->m_monitor);
+
+ while(!m_ready)
+ {
+ if(!self->m_condition_ready.timed_wait(lock, timestamp)) return false;
+ }
+
+ return true;
+ }
+
+
+ result_type operator()() const volatile
+ {
+ wait();
+/*
+ if( throw_exception_ != 0 )
+ {
+ throw_exception_( this );
+ }
+*/
+
+ return *(const_cast<const future_result_type*>(&m_result));
+ }
+
+
+ void set_value(future_result_type const & r) volatile
+ {
+ locking_ptr<future_type, mutex> lockedThis(*this, m_monitor);
+ if(!m_ready && !m_is_cancelled)
+ {
+ lockedThis->m_result = r;
+ lockedThis->m_ready = true;
+ lockedThis->m_condition_ready.notify_all();
+ }
+ }
+/*
+ template<class E> void set_exception() // throw()
+ {
+ m_impl->template set_exception<E>();
+ }
+
+ template<class E> void set_exception( char const * what ) // throw()
+ {
+ m_impl->template set_exception<E>( what );
+ }
+ */
+
+
+ bool cancel() volatile
+ {
+ if(!m_ready || m_executing)
+ {
+ m_is_cancelled = true;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+
+ bool is_cancelled() const volatile
+ {
+ return m_is_cancelled;
+ }
+
+
+ void set_execution_status(bool executing) volatile
+ {
+ m_executing = executing;
+ }
+};
+
+
+template<
+ template <typename> class Future,
+ typename Function
+>
+class future_impl_task_func
+{
+
+public:
+ typedef void result_type; //!< Indicates the functor's result type.
+
+ typedef Function function_type; //!< Indicates the function's type.
+ typedef typename result_of<function_type()>::type future_result_type; //!< Indicates the future's result type.
+ typedef Future<future_result_type> future_type; //!< Indicates the future's type.
+
+ // The task is required to be a nullary function.
+ BOOST_STATIC_ASSERT(function_traits<function_type()>::arity == 0);
+
+ // The task function's result type is required not to be void.
+ BOOST_STATIC_ASSERT(!is_void<future_result_type>::value);
+
+private:
+ function_type m_function;
+ shared_ptr<future_type> m_future;
+
+public:
+ future_impl_task_func(function_type const & function, shared_ptr<future_type> const & future)
+ : m_function(function)
+ , m_future(future)
+ {
+ }
+
+ void operator()()
+ {
+ if(m_function)
+ {
+ m_future->set_execution_status(true);
+ if(!m_future->is_cancelled())
+ {
+ // TODO future exeception handling
+ m_future->set_value(m_function());
+ }
+ m_future->set_execution_status(false); // TODO consider exceptions
+ }
+ }
+
+};
+
+
+
+
+
+} } } // namespace boost::threadpool::detail
+
+#endif // THREADPOOL_DETAIL_FUTURE_IMPL_HPP_INCLUDED
+
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/locking_ptr.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/locking_ptr.hpp
new file mode 100644
index 0000000000..57ba560b5a
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/locking_ptr.hpp
@@ -0,0 +1,85 @@
+/*! \file
+* \brief The locking_ptr is smart pointer with a scoped locking mechanism.
+*
+* The class is a wrapper for a volatile pointer. It enables synchronized access to the
+* internal pointer by locking the passed mutex.
+* locking_ptr is based on Andrei Alexandrescu's LockingPtr. For more information
+* see article "volatile - Multithreaded Programmer's Best Friend" by A. Alexandrescu.
+*
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* 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)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+
+#ifndef THREADPOOL_DETAIL_LOCKING_PTR_HPP_INCLUDED
+#define THREADPOOL_DETAIL_LOCKING_PTR_HPP_INCLUDED
+
+#include <boost/utility.hpp>
+#include <boost/thread/mutex.hpp>
+
+
+namespace boost { namespace threadpool { namespace detail
+{
+
+/*! \brief Smart pointer with a scoped locking mechanism.
+ *
+ * This class is a wrapper for a volatile pointer. It enables synchronized access to the
+ * internal pointer by locking the passed mutex.
+ */
+ template <typename T, typename Mutex>
+ class locking_ptr
+ : private noncopyable
+ {
+ T* m_obj; //!< The instance pointer.
+ Mutex & m_mutex; //!< Mutex is used for scoped locking.
+
+ public:
+ /// Constructor.
+ locking_ptr(volatile T& obj, const volatile Mutex& mtx)
+ : m_obj(const_cast<T*>(&obj))
+ , m_mutex(*const_cast<Mutex*>(&mtx))
+ {
+ // Lock mutex
+ m_mutex.lock();
+ }
+
+
+ /// Destructor.
+ ~locking_ptr()
+ {
+ // Unlock mutex
+ m_mutex.unlock();
+ }
+
+
+ /*! Returns a reference to the stored instance.
+ * \return The instance's reference.
+ */
+ T& operator*() const
+ {
+ return *m_obj;
+ }
+
+
+ /*! Returns a pointer to the stored instance.
+ * \return The instance's pointer.
+ */
+ T* operator->() const
+ {
+ return m_obj;
+ }
+ };
+
+
+} } } // namespace boost::threadpool::detail
+
+
+#endif // THREADPOOL_DETAIL_LOCKING_PTR_HPP_INCLUDED
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/pool_core.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/pool_core.hpp
new file mode 100644
index 0000000000..a81df87763
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/pool_core.hpp
@@ -0,0 +1,453 @@
+/*! \file
+* \brief Thread pool core.
+*
+* This file contains the threadpool's core class: pool<Task, SchedulingPolicy>.
+*
+* Thread pools are a mechanism for asynchronous and parallel processing
+* within the same process. The pool class provides a convenient way
+* for dispatching asynchronous tasks as functions objects. The scheduling
+* of these tasks can be easily controlled by using customized schedulers.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* 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)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+
+#ifndef THREADPOOL_POOL_CORE_HPP_INCLUDED
+#define THREADPOOL_POOL_CORE_HPP_INCLUDED
+
+
+
+
+#include "locking_ptr.hpp"
+#include "worker_thread.hpp"
+
+#include "../task_adaptors.hpp"
+
+#include <boost/thread.hpp>
+#include <boost/thread/exceptions.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/smart_ptr.hpp>
+#include <boost/bind.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits.hpp>
+
+#include <vector>
+
+
+/// The namespace threadpool contains a thread pool and related utility classes.
+namespace boost { namespace threadpool { namespace detail
+{
+
+ /*! \brief Thread pool.
+ *
+ * Thread pools are a mechanism for asynchronous and parallel processing
+ * within the same process. The pool class provides a convenient way
+ * for dispatching asynchronous tasks as functions objects. The scheduling
+ * of these tasks can be easily controlled by using customized schedulers.
+ * A task must not throw an exception.
+ *
+ * A pool_impl is DefaultConstructible and NonCopyable.
+ *
+ * \param Task A function object which implements the operator 'void operator() (void) const'. The operator () is called by the pool to execute the task. Exceptions are ignored.
+ * \param Scheduler A task container which determines how tasks are scheduled. It is guaranteed that this container is accessed only by one thread at a time. The scheduler shall not throw exceptions.
+ *
+ * \remarks The pool class is thread-safe.
+ *
+ * \see Tasks: task_func, prio_task_func
+ * \see Scheduling policies: fifo_scheduler, lifo_scheduler, prio_scheduler
+ */
+ template <
+ typename Task,
+
+ template <typename> class SchedulingPolicy,
+ template <typename> class SizePolicy,
+ template <typename> class SizePolicyController,
+ template <typename> class ShutdownPolicy
+ >
+ class pool_core
+ : public enable_shared_from_this< pool_core<Task, SchedulingPolicy, SizePolicy, SizePolicyController, ShutdownPolicy > >
+ , private noncopyable
+ {
+
+ public: // Type definitions
+ typedef Task task_type; //!< Indicates the task's type.
+ typedef SchedulingPolicy<task_type> scheduler_type; //!< Indicates the scheduler's type.
+ typedef pool_core<Task,
+ SchedulingPolicy,
+ SizePolicy,
+ SizePolicyController,
+ ShutdownPolicy > pool_type; //!< Indicates the thread pool's type.
+ typedef SizePolicy<pool_type> size_policy_type; //!< Indicates the sizer's type.
+ //typedef typename size_policy_type::size_controller size_controller_type;
+
+ typedef SizePolicyController<pool_type> size_controller_type;
+
+// typedef SizePolicy<pool_type>::size_controller size_controller_type;
+ typedef ShutdownPolicy<pool_type> shutdown_policy_type;//!< Indicates the shutdown policy's type.
+
+ typedef worker_thread<pool_type> worker_type;
+
+ // The task is required to be a nullary function.
+ BOOST_STATIC_ASSERT(function_traits<task_type()>::arity == 0);
+
+ // The task function's result type is required to be void.
+ BOOST_STATIC_ASSERT(is_void<typename result_of<task_type()>::type >::value);
+
+
+ private: // Friends
+ friend class worker_thread<pool_type>;
+
+#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x580) // Tested with CC: Sun C++ 5.8 Patch 121018-08 2006/12/06
+ friend class SizePolicy;
+ friend class ShutdownPolicy;
+#else
+ friend class SizePolicy<pool_type>;
+ friend class ShutdownPolicy<pool_type>;
+#endif
+
+ private: // The following members may be accessed by _multiple_ threads at the same time:
+ volatile size_t m_worker_count;
+ volatile size_t m_target_worker_count;
+ volatile size_t m_active_worker_count;
+
+
+
+ private: // The following members are accessed only by _one_ thread at the same time:
+ scheduler_type m_scheduler;
+ scoped_ptr<size_policy_type> m_size_policy; // is never null
+
+ bool m_terminate_all_workers; // Indicates if termination of all workers was triggered.
+ std::vector<shared_ptr<worker_type> > m_terminated_workers; // List of workers which are terminated but not fully destructed.
+
+ private: // The following members are implemented thread-safe:
+ mutable recursive_mutex m_monitor;
+ mutable condition m_worker_idle_or_terminated_event; // A worker is idle or was terminated.
+ mutable condition m_task_or_terminate_workers_event; // Task is available OR total worker count should be reduced.
+
+ public:
+ /// Constructor.
+ pool_core()
+ : m_worker_count(0)
+ , m_target_worker_count(0)
+ , m_active_worker_count(0)
+ , m_terminate_all_workers(false)
+ {
+ pool_type volatile & self_ref = *this;
+ m_size_policy.reset(new size_policy_type(self_ref));
+
+ m_scheduler.clear();
+ }
+
+
+ /// Destructor.
+ ~pool_core()
+ {
+ }
+
+ /*! Gets the size controller which manages the number of threads in the pool.
+ * \return The size controller.
+ * \see SizePolicy
+ */
+ size_controller_type size_controller()
+ {
+ return size_controller_type(*m_size_policy, this->shared_from_this());
+ }
+
+ /*! Gets the number of threads in the pool.
+ * \return The number of threads.
+ */
+ size_t size() const volatile
+ {
+ return m_worker_count;
+ }
+
+// TODO is only called once
+ void shutdown()
+ {
+ ShutdownPolicy<pool_type>::shutdown(*this);
+ }
+
+ /*! Schedules a task for asynchronous execution. The task will be executed once only.
+ * \param task The task function object. It should not throw execeptions.
+ * \return true, if the task could be scheduled and false otherwise.
+ */
+ bool schedule(task_type const & task) volatile
+ {
+ locking_ptr<pool_type, recursive_mutex> lockedThis(*this, m_monitor);
+
+ if(lockedThis->m_scheduler.push(task))
+ {
+ lockedThis->m_task_or_terminate_workers_event.notify_one();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+
+ /*! Returns the number of tasks which are currently executed.
+ * \return The number of active tasks.
+ */
+ size_t active() const volatile
+ {
+ return m_active_worker_count;
+ }
+
+
+ /*! Returns the number of tasks which are ready for execution.
+ * \return The number of pending tasks.
+ */
+ size_t pending() const volatile
+ {
+ locking_ptr<const pool_type, recursive_mutex> lockedThis(*this, m_monitor);
+ return lockedThis->m_scheduler.size();
+ }
+
+
+ /*! Removes all pending tasks from the pool's scheduler.
+ */
+ void clear() volatile
+ {
+ locking_ptr<pool_type, recursive_mutex> lockedThis(*this, m_monitor);
+ lockedThis->m_scheduler.clear();
+ }
+
+
+ /*! Indicates that there are no tasks pending.
+ * \return true if there are no tasks ready for execution.
+ * \remarks This function is more efficient that the check 'pending() == 0'.
+ */
+ bool empty() const volatile
+ {
+ locking_ptr<const pool_type, recursive_mutex> lockedThis(*this, m_monitor);
+ return lockedThis->m_scheduler.empty();
+ }
+
+
+ /*! The current thread of execution is blocked until the sum of all active
+ * and pending tasks is equal or less than a given threshold.
+ * \param task_threshold The maximum number of tasks in pool and scheduler.
+ */
+ void wait(size_t const task_threshold = 0) const volatile
+ {
+ const pool_type* self = const_cast<const pool_type*>(this);
+ recursive_mutex::scoped_lock lock(self->m_monitor);
+
+ if(0 == task_threshold)
+ {
+ while(0 != self->m_active_worker_count || !self->m_scheduler.empty())
+ {
+ self->m_worker_idle_or_terminated_event.wait(lock);
+ }
+ }
+ else
+ {
+ while(task_threshold < self->m_active_worker_count + self->m_scheduler.size())
+ {
+ self->m_worker_idle_or_terminated_event.wait(lock);
+ }
+ }
+ }
+
+ /*! The current thread of execution is blocked until the timestamp is met
+ * or the sum of all active and pending tasks is equal or less
+ * than a given threshold.
+ * \param timestamp The time when function returns at the latest.
+ * \param task_threshold The maximum number of tasks in pool and scheduler.
+ * \return true if the task sum is equal or less than the threshold, false otherwise.
+ */
+ bool wait(xtime const & timestamp, size_t const task_threshold = 0) const volatile
+ {
+ const pool_type* self = const_cast<const pool_type*>(this);
+ recursive_mutex::scoped_lock lock(self->m_monitor);
+
+ if(0 == task_threshold)
+ {
+ while(0 != self->m_active_worker_count || !self->m_scheduler.empty())
+ {
+ if(!self->m_worker_idle_or_terminated_event.timed_wait(lock, timestamp)) return false;
+ }
+ }
+ else
+ {
+ while(task_threshold < self->m_active_worker_count + self->m_scheduler.size())
+ {
+ if(!self->m_worker_idle_or_terminated_event.timed_wait(lock, timestamp)) return false;
+ }
+ }
+
+ return true;
+ }
+
+
+ private:
+
+
+ void terminate_all_workers(bool const wait) volatile
+ {
+ pool_type* self = const_cast<pool_type*>(this);
+ recursive_mutex::scoped_lock lock(self->m_monitor);
+
+ self->m_terminate_all_workers = true;
+
+ m_target_worker_count = 0;
+ self->m_task_or_terminate_workers_event.notify_all();
+
+ if(wait)
+ {
+ while(m_active_worker_count > 0)
+ {
+ self->m_worker_idle_or_terminated_event.wait(lock);
+ }
+
+ for(typename std::vector<shared_ptr<worker_type> >::iterator it = self->m_terminated_workers.begin();
+ it != self->m_terminated_workers.end();
+ ++it)
+ {
+ (*it)->join();
+ }
+ self->m_terminated_workers.clear();
+ }
+ }
+
+
+ /*! Changes the number of worker threads in the pool. The resizing
+ * is handled by the SizePolicy.
+ * \param threads The new number of worker threads.
+ * \return true, if pool will be resized and false if not.
+ */
+ bool resize(size_t const worker_count) volatile
+ {
+ locking_ptr<pool_type, recursive_mutex> lockedThis(*this, m_monitor);
+
+ if(!m_terminate_all_workers)
+ {
+ m_target_worker_count = worker_count;
+ }
+ else
+ {
+ return false;
+ }
+
+
+ if(m_worker_count <= m_target_worker_count)
+ { // increase worker count
+ while(m_worker_count < m_target_worker_count)
+ {
+ try
+ {
+ worker_thread<pool_type>::create_and_attach(lockedThis->shared_from_this());
+ m_worker_count++;
+ m_active_worker_count++;
+ }
+ catch(thread_resource_error&)
+ {
+ return false;
+ }
+ }
+ }
+ else
+ { // decrease worker count
+ lockedThis->m_task_or_terminate_workers_event.notify_all(); // TODO: Optimize number of notified workers
+ }
+
+ return true;
+ }
+
+
+ // worker died with unhandled exception
+ void worker_died_unexpectedly(shared_ptr<worker_type> worker) volatile
+ {
+ locking_ptr<pool_type, recursive_mutex> lockedThis(*this, m_monitor);
+
+ m_worker_count--;
+ m_active_worker_count--;
+ lockedThis->m_worker_idle_or_terminated_event.notify_all();
+
+ if(m_terminate_all_workers)
+ {
+ lockedThis->m_terminated_workers.push_back(worker);
+ }
+ else
+ {
+ lockedThis->m_size_policy->worker_died_unexpectedly(m_worker_count);
+ }
+ }
+
+ void worker_destructed(shared_ptr<worker_type> worker) volatile
+ {
+ locking_ptr<pool_type, recursive_mutex> lockedThis(*this, m_monitor);
+ m_worker_count--;
+ m_active_worker_count--;
+ lockedThis->m_worker_idle_or_terminated_event.notify_all();
+
+ if(m_terminate_all_workers)
+ {
+ lockedThis->m_terminated_workers.push_back(worker);
+ }
+ }
+
+
+ bool execute_task() volatile
+ {
+ function0<void> task;
+
+ { // fetch task
+ pool_type* lockedThis = const_cast<pool_type*>(this);
+ recursive_mutex::scoped_lock lock(lockedThis->m_monitor);
+
+ // decrease number of threads if necessary
+ if(m_worker_count > m_target_worker_count)
+ {
+ return false; // terminate worker
+ }
+
+
+ // wait for tasks
+ while(lockedThis->m_scheduler.empty())
+ {
+ // decrease number of workers if necessary
+ if(m_worker_count > m_target_worker_count)
+ {
+ return false; // terminate worker
+ }
+ else
+ {
+ m_active_worker_count--;
+ lockedThis->m_worker_idle_or_terminated_event.notify_all();
+ lockedThis->m_task_or_terminate_workers_event.wait(lock);
+ m_active_worker_count++;
+ }
+ }
+
+ task = lockedThis->m_scheduler.top();
+ lockedThis->m_scheduler.pop();
+ }
+
+ // call task function
+ if(task)
+ {
+ task();
+ }
+
+ //guard->disable();
+ return true;
+ }
+ };
+
+
+
+
+} } } // namespace boost::threadpool::detail
+
+#endif // THREADPOOL_POOL_CORE_HPP_INCLUDED
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/scope_guard.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/scope_guard.hpp
new file mode 100644
index 0000000000..68634654ba
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/scope_guard.hpp
@@ -0,0 +1,65 @@
+/*! \file
+* \brief TODO.
+*
+* TODO.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* 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)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+
+#ifndef THREADPOOL_DETAIL_SCOPE_GUARD_HPP_INCLUDED
+#define THREADPOOL_DETAIL_SCOPE_GUARD_HPP_INCLUDED
+
+
+
+#include <boost/function.hpp>
+
+
+namespace boost { namespace threadpool { namespace detail
+{
+
+// TODO documentation
+class scope_guard
+: private boost::noncopyable
+{
+ function0<void> const m_function;
+ bool m_is_active;
+
+public:
+ scope_guard(function0<void> const & call_on_exit)
+ : m_function(call_on_exit)
+ , m_is_active(true)
+ {
+ }
+
+ ~scope_guard()
+ {
+ if(m_is_active && m_function)
+ {
+ m_function();
+ }
+ }
+
+ void disable()
+ {
+ m_is_active = false;
+ }
+};
+
+
+
+
+
+
+} } } // namespace boost::threadpool::detail
+
+#endif // THREADPOOL_DETAIL_SCOPE_GUARD_HPP_INCLUDED
+
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/worker_thread.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/worker_thread.hpp
new file mode 100644
index 0000000000..d33467a527
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/detail/worker_thread.hpp
@@ -0,0 +1,115 @@
+/*! \file
+* \brief Thread pool worker.
+*
+* The worker thread instance is attached to a pool
+* and executes tasks of this pool.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* 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)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+#ifndef THREADPOOL_DETAIL_WORKER_THREAD_HPP_INCLUDED
+#define THREADPOOL_DETAIL_WORKER_THREAD_HPP_INCLUDED
+
+
+#include "scope_guard.hpp"
+
+#include <boost/smart_ptr.hpp>
+#include <boost/thread.hpp>
+#include <boost/thread/exceptions.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/bind.hpp>
+
+
+namespace boost { namespace threadpool { namespace detail
+{
+
+ /*! \brief Thread pool worker.
+ *
+ * A worker_thread represents a thread of execution. The worker is attached to a
+ * thread pool and processes tasks of that pool. The lifetime of the worker and its
+ * internal boost::thread is managed automatically.
+ *
+ * This class is a helper class and cannot be constructed or accessed directly.
+ *
+ * \see pool_core
+ */
+ template <typename Pool>
+ class worker_thread
+ : public enable_shared_from_this< worker_thread<Pool> >
+ , private noncopyable
+ {
+ public:
+ typedef Pool pool_type; //!< Indicates the pool's type.
+
+ private:
+ shared_ptr<pool_type> m_pool; //!< Pointer to the pool which created the worker.
+ shared_ptr<boost::thread> m_thread; //!< Pointer to the thread which executes the run loop.
+
+
+ /*! Constructs a new worker.
+ * \param pool Pointer to it's parent pool.
+ * \see function create_and_attach
+ */
+ worker_thread(shared_ptr<pool_type> const & pool)
+ : m_pool(pool)
+ {
+ assert(pool);
+ }
+
+
+ /*! Notifies that an exception occurred in the run loop.
+ */
+ void died_unexpectedly()
+ {
+ m_pool->worker_died_unexpectedly(this->shared_from_this());
+ }
+
+
+ public:
+ /*! Executes pool's tasks sequentially.
+ */
+ void run()
+ {
+ scope_guard notify_exception(bind(&worker_thread::died_unexpectedly, this));
+
+ while(m_pool->execute_task()) {}
+
+ notify_exception.disable();
+ m_pool->worker_destructed(this->shared_from_this());
+ }
+
+
+ /*! Joins the worker's thread.
+ */
+ void join()
+ {
+ m_thread->join();
+ }
+
+
+ /*! Constructs a new worker thread and attaches it to the pool.
+ * \param pool Pointer to the pool.
+ */
+ static void create_and_attach(shared_ptr<pool_type> const & pool)
+ {
+ shared_ptr<worker_thread> worker(new worker_thread(pool));
+ if(worker)
+ {
+ worker->m_thread.reset(new boost::thread(bind(&worker_thread::run, worker)));
+ }
+ }
+
+ };
+
+
+} } } // namespace boost::threadpool::detail
+
+#endif // THREADPOOL_DETAIL_WORKER_THREAD_HPP_INCLUDED
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/future.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/future.hpp
new file mode 100644
index 0000000000..f4a6e12244
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/future.hpp
@@ -0,0 +1,144 @@
+/*! \file
+* \brief TODO.
+*
+* TODO.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* 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)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+#ifndef THREADPOOL_FUTURE_HPP_INCLUDED
+#define THREADPOOL_FUTURE_HPP_INCLUDED
+
+
+
+#include "./detail/future.hpp"
+#include <boost/utility/enable_if.hpp>
+
+//#include "pool.hpp"
+//#include <boost/utility.hpp>
+
+//#include <boost/thread/mutex.hpp>
+
+
+namespace boost { namespace threadpool
+{
+
+ /*! \brief Experimental. Do not use in production code. TODO.
+ *
+ * TODO Future
+ *
+ * \see TODO
+ *
+ */
+
+
+template<class Result>
+class future
+{
+private:
+ shared_ptr<detail::future_impl<Result> > m_impl;
+
+public:
+ typedef Result const & result_type; //!< Indicates the functor's result type.
+ typedef Result future_result_type; //!< Indicates the future's result type.
+
+
+public:
+
+ future()
+ : m_impl(new detail::future_impl<future_result_type>()) // TODO remove this
+ {
+ }
+
+ // only for internal usage
+ future(shared_ptr<detail::future_impl<Result> > const & impl)
+ : m_impl(impl)
+ {
+ }
+
+ bool ready() const
+ {
+ return m_impl->ready();
+ }
+
+ void wait() const
+ {
+ m_impl->wait();
+ }
+
+ bool timed_wait(boost::xtime const & timestamp) const
+ {
+ return m_impl->timed_wait(timestamp);
+ }
+
+ result_type operator()() // throw( thread::cancelation_exception, ... )
+ {
+ return (*m_impl)();
+ }
+
+ result_type get() // throw( thread::cancelation_exception, ... )
+ {
+ return (*m_impl)();
+ }
+
+ bool cancel()
+ {
+ return m_impl->cancel();
+ }
+
+ bool is_cancelled() const
+ {
+ return m_impl->is_cancelled();
+ }
+};
+
+
+
+
+
+template<class Pool, class Function>
+typename disable_if <
+ is_void< typename result_of< Function() >::type >,
+ future< typename result_of< Function() >::type >
+>::type
+schedule(Pool& pool, const Function& task)
+{
+ typedef typename result_of< Function() >::type future_result_type;
+
+ // create future impl and future
+ shared_ptr<detail::future_impl<future_result_type> > impl(new detail::future_impl<future_result_type>);
+ future <future_result_type> res(impl);
+
+ // schedule future impl
+ pool.schedule(detail::future_impl_task_func<detail::future_impl, Function>(task, impl));
+
+ // return future
+ return res;
+
+/*
+ TODO
+ if(pool->schedule(bind(&Future::run, future)))
+ {
+ return future;
+ }
+ else
+ {
+ // construct empty future
+ return error_future;
+ }
+ */
+}
+
+
+
+} } // namespace boost::threadpool
+
+#endif // THREADPOOL_FUTURE_HPP_INCLUDED
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/pool.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/pool.hpp
new file mode 100644
index 0000000000..a4b6676ea9
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/pool.hpp
@@ -0,0 +1,232 @@
+/*! \file
+* \brief Thread pool core.
+*
+* This file contains the threadpool's core class: pool<Task, SchedulingPolicy>.
+*
+* Thread pools are a mechanism for asynchronous and parallel processing
+* within the same process. The pool class provides a convenient way
+* for dispatching asynchronous tasks as functions objects. The scheduling
+* of these tasks can be easily controlled by using customized schedulers.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* 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)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+
+#ifndef THREADPOOL_POOL_HPP_INCLUDED
+#define THREADPOOL_POOL_HPP_INCLUDED
+
+#include <boost/ref.hpp>
+
+#include "./detail/pool_core.hpp"
+
+#include "task_adaptors.hpp"
+
+#include "./detail/locking_ptr.hpp"
+
+#include "scheduling_policies.hpp"
+#include "size_policies.hpp"
+#include "shutdown_policies.hpp"
+
+
+
+/// The namespace threadpool contains a thread pool and related utility classes.
+namespace boost { namespace threadpool
+{
+
+
+
+ /*! \brief Thread pool.
+ *
+ * Thread pools are a mechanism for asynchronous and parallel processing
+ * within the same process. The pool class provides a convenient way
+ * for dispatching asynchronous tasks as functions objects. The scheduling
+ * of these tasks can be easily controlled by using customized schedulers.
+ * A task must not throw an exception.
+ *
+ * A pool is DefaultConstructible, CopyConstructible and Assignable.
+ * It has reference semantics; all copies of the same pool are equivalent and interchangeable.
+ * All operations on a pool except assignment are strongly thread safe or sequentially consistent;
+ * that is, the behavior of concurrent calls is as if the calls have been issued sequentially in an unspecified order.
+ *
+ * \param Task A function object which implements the operator 'void operator() (void) const'. The operator () is called by the pool to execute the task. Exceptions are ignored.
+ * \param SchedulingPolicy A task container which determines how tasks are scheduled. It is guaranteed that this container is accessed only by one thread at a time. The scheduler shall not throw exceptions.
+ *
+ * \remarks The pool class is thread-safe.
+ *
+ * \see Tasks: task_func, prio_task_func
+ * \see Scheduling policies: fifo_scheduler, lifo_scheduler, prio_scheduler
+ */
+ template <
+ typename Task = task_func,
+ template <typename> class SchedulingPolicy = fifo_scheduler,
+ template <typename> class SizePolicy = static_size,
+ template <typename> class SizePolicyController = resize_controller,
+ template <typename> class ShutdownPolicy = wait_for_all_tasks
+ >
+ class thread_pool
+ {
+ typedef detail::pool_core<Task,
+ SchedulingPolicy,
+ SizePolicy,
+ SizePolicyController,
+ ShutdownPolicy> pool_core_type;
+ shared_ptr<pool_core_type> m_core; // pimpl idiom
+ shared_ptr<void> m_shutdown_controller; // If the last pool holding a pointer to the core is deleted the controller shuts the pool down.
+
+ public: // Type definitions
+ typedef Task task_type; //!< Indicates the task's type.
+ typedef SchedulingPolicy<task_type> scheduler_type; //!< Indicates the scheduler's type.
+ /* typedef thread_pool<Task,
+ SchedulingPolicy,
+ SizePolicy,
+ ShutdownPolicy > pool_type; //!< Indicates the thread pool's type.
+ */
+ typedef SizePolicy<pool_core_type> size_policy_type;
+ typedef SizePolicyController<pool_core_type> size_controller_type;
+
+
+ public:
+ /*! Constructor.
+ * \param initial_threads The pool is immediately resized to set the specified number of threads. The pool's actual number threads depends on the SizePolicy.
+ */
+ thread_pool(size_t initial_threads = 0)
+ : m_core(new pool_core_type)
+ , m_shutdown_controller(static_cast<void*>(0), bind(&pool_core_type::shutdown, m_core))
+ {
+ size_policy_type::init(*m_core, initial_threads);
+ }
+
+
+ /*! Gets the size controller which manages the number of threads in the pool.
+ * \return The size controller.
+ * \see SizePolicy
+ */
+ size_controller_type size_controller()
+ {
+ return m_core->size_controller();
+ }
+
+
+ /*! Gets the number of threads in the pool.
+ * \return The number of threads.
+ */
+ size_t size() const
+ {
+ return m_core->size();
+ }
+
+
+ /*! Schedules a task for asynchronous execution. The task will be executed once only.
+ * \param task The task function object. It should not throw execeptions.
+ * \return true, if the task could be scheduled and false otherwise.
+ */
+ bool schedule(task_type const & task)
+ {
+ return m_core->schedule(task);
+ }
+
+
+ /*! Returns the number of tasks which are currently executed.
+ * \return The number of active tasks.
+ */
+ size_t active() const
+ {
+ return m_core->active();
+ }
+
+
+ /*! Returns the number of tasks which are ready for execution.
+ * \return The number of pending tasks.
+ */
+ size_t pending() const
+ {
+ return m_core->pending();
+ }
+
+
+ /*! Removes all pending tasks from the pool's scheduler.
+ */
+ void clear()
+ {
+ m_core->clear();
+ }
+
+
+ /*! Indicates that there are no tasks pending.
+ * \return true if there are no tasks ready for execution.
+ * \remarks This function is more efficient that the check 'pending() == 0'.
+ */
+ bool empty() const
+ {
+ return m_core->empty();
+ }
+
+
+ /*! The current thread of execution is blocked until the sum of all active
+ * and pending tasks is equal or less than a given threshold.
+ * \param task_threshold The maximum number of tasks in pool and scheduler.
+ */
+ void wait(size_t task_threshold = 0) const
+ {
+ m_core->wait(task_threshold);
+ }
+
+
+ /*! The current thread of execution is blocked until the timestamp is met
+ * or the sum of all active and pending tasks is equal or less
+ * than a given threshold.
+ * \param timestamp The time when function returns at the latest.
+ * \param task_threshold The maximum number of tasks in pool and scheduler.
+ * \return true if the task sum is equal or less than the threshold, false otherwise.
+ */
+ bool wait(xtime const & timestamp, size_t task_threshold = 0) const
+ {
+ return m_core->wait(timestamp, task_threshold);
+ }
+ };
+
+
+
+ /*! \brief Fifo pool.
+ *
+ * The pool's tasks are fifo scheduled task_func functors.
+ *
+ */
+ typedef thread_pool<task_func, fifo_scheduler, static_size, resize_controller, wait_for_all_tasks> fifo_pool;
+
+
+ /*! \brief Lifo pool.
+ *
+ * The pool's tasks are lifo scheduled task_func functors.
+ *
+ */
+ typedef thread_pool<task_func, lifo_scheduler, static_size, resize_controller, wait_for_all_tasks> lifo_pool;
+
+
+ /*! \brief Pool for prioritized task.
+ *
+ * The pool's tasks are prioritized prio_task_func functors.
+ *
+ */
+ typedef thread_pool<prio_task_func, prio_scheduler, static_size, resize_controller, wait_for_all_tasks> prio_pool;
+
+
+ /*! \brief A standard pool.
+ *
+ * The pool's tasks are fifo scheduled task_func functors.
+ *
+ */
+ typedef fifo_pool pool;
+
+
+
+} } // namespace boost::threadpool
+
+#endif // THREADPOOL_POOL_HPP_INCLUDED
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/pool_adaptors.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/pool_adaptors.hpp
new file mode 100644
index 0000000000..6cde152d2a
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/pool_adaptors.hpp
@@ -0,0 +1,70 @@
+/*! \file
+* \brief Pool adaptors.
+*
+* This file contains an easy-to-use adaptor similar to a smart
+* pointer for the pool class.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* 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)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+
+#ifndef THREADPOOL_POOL_ADAPTORS_HPP_INCLUDED
+#define THREADPOOL_POOL_ADAPTORS_HPP_INCLUDED
+
+#include <boost/smart_ptr.hpp>
+
+
+namespace boost { namespace threadpool
+{
+
+
+// TODO convenience scheduling function
+ /*! Schedules a Runnable for asynchronous execution. A Runnable is an arbitrary class with a run()
+ * member function. This a convenience shorthand for pool->schedule(bind(&Runnable::run, task_object)).
+ * \param
+ * \param obj The Runnable object. The member function run() will be exectued and should not throw execeptions.
+ * \return true, if the task could be scheduled and false otherwise.
+ */
+ template<typename Pool, typename Runnable>
+ bool schedule(Pool& pool, shared_ptr<Runnable> const & obj)
+ {
+ return pool->schedule(bind(&Runnable::run, obj));
+ }
+
+ /*! Schedules a task for asynchronous execution. The task will be executed once only.
+ * \param task The task function object.
+ */
+ template<typename Pool>
+ typename enable_if <
+ is_void< typename result_of< typename Pool::task_type() >::type >,
+ bool
+ >::type
+ schedule(Pool& pool, typename Pool::task_type const & task)
+ {
+ return pool.schedule(task);
+ }
+
+
+ template<typename Pool>
+ typename enable_if <
+ is_void< typename result_of< typename Pool::task_type() >::type >,
+ bool
+ >::type
+ schedule(shared_ptr<Pool> const pool, typename Pool::task_type const & task)
+ {
+ return pool->schedule(task);
+ }
+
+
+} } // namespace boost::threadpool
+
+#endif // THREADPOOL_POOL_ADAPTORS_HPP_INCLUDED
+
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/scheduling_policies.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/scheduling_policies.hpp
new file mode 100644
index 0000000000..2d6c7c1bae
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/scheduling_policies.hpp
@@ -0,0 +1,262 @@
+/*! \file
+* \brief Task scheduling policies.
+*
+* This file contains some fundamental scheduling policies for the pool class.
+* A scheduling policy is realized by a task container which controls the access to
+* the tasks. Fundamentally the container determines the order the tasks are processed
+* by the thread pool.
+* The task containers need not to be thread-safe because they are used by the pool
+* in thread-safe way.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* 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)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+
+#ifndef THREADPOOL_SCHEDULING_POLICIES_HPP_INCLUDED
+#define THREADPOOL_SCHEDULING_POLICIES_HPP_INCLUDED
+
+
+#include <queue>
+#include <deque>
+
+#include "task_adaptors.hpp"
+
+namespace boost { namespace threadpool
+{
+
+ /*! \brief SchedulingPolicy which implements FIFO ordering.
+ *
+ * This container implements a FIFO scheduling policy.
+ * The first task to be added to the scheduler will be the first to be removed.
+ * The processing proceeds sequentially in the same order.
+ * FIFO stands for "first in, first out".
+ *
+ * \param Task A function object which implements the operator()(void).
+ *
+ */
+ template <typename Task = task_func>
+ class fifo_scheduler
+ {
+ public:
+ typedef Task task_type; //!< Indicates the scheduler's task type.
+
+ protected:
+ std::deque<task_type> m_container; //!< Internal task container.
+
+
+ public:
+ /*! Adds a new task to the scheduler.
+ * \param task The task object.
+ * \return true, if the task could be scheduled and false otherwise.
+ */
+ bool push(task_type const & task)
+ {
+ m_container.push_back(task);
+ return true;
+ }
+
+ /*! Removes the task which should be executed next.
+ */
+ void pop()
+ {
+ m_container.pop_front();
+ }
+
+ /*! Gets the task which should be executed next.
+ * \return The task object to be executed.
+ */
+ task_type const & top() const
+ {
+ return m_container.front();
+ }
+
+ /*! Gets the current number of tasks in the scheduler.
+ * \return The number of tasks.
+ * \remarks Prefer empty() to size() == 0 to check if the scheduler is empty.
+ */
+ size_t size() const
+ {
+ return m_container.size();
+ }
+
+ /*! Checks if the scheduler is empty.
+ * \return true if the scheduler contains no tasks, false otherwise.
+ * \remarks Is more efficient than size() == 0.
+ */
+ bool empty() const
+ {
+ return m_container.empty();
+ }
+
+ /*! Removes all tasks from the scheduler.
+ */
+ void clear()
+ {
+ m_container.clear();
+ }
+ };
+
+
+
+ /*! \brief SchedulingPolicy which implements LIFO ordering.
+ *
+ * This container implements a LIFO scheduling policy.
+ * The last task to be added to the scheduler will be the first to be removed.
+ * LIFO stands for "last in, first out".
+ *
+ * \param Task A function object which implements the operator()(void).
+ *
+ */
+ template <typename Task = task_func>
+ class lifo_scheduler
+ {
+ public:
+ typedef Task task_type; //!< Indicates the scheduler's task type.
+
+ protected:
+ std::deque<task_type> m_container; //!< Internal task container.
+
+ public:
+ /*! Adds a new task to the scheduler.
+ * \param task The task object.
+ * \return true, if the task could be scheduled and false otherwise.
+ */
+ bool push(task_type const & task)
+ {
+ m_container.push_front(task);
+ return true;
+ }
+
+ /*! Removes the task which should be executed next.
+ */
+ void pop()
+ {
+ m_container.pop_front();
+ }
+
+ /*! Gets the task which should be executed next.
+ * \return The task object to be executed.
+ */
+ task_type const & top() const
+ {
+ return m_container.front();
+ }
+
+ /*! Gets the current number of tasks in the scheduler.
+ * \return The number of tasks.
+ * \remarks Prefer empty() to size() == 0 to check if the scheduler is empty.
+ */
+ size_t size() const
+ {
+ return m_container.size();
+ }
+
+ /*! Checks if the scheduler is empty.
+ * \return true if the scheduler contains no tasks, false otherwise.
+ * \remarks Is more efficient than size() == 0.
+ */
+ bool empty() const
+ {
+ return m_container.empty();
+ }
+
+ /*! Removes all tasks from the scheduler.
+ */
+ void clear()
+ {
+ m_container.clear();
+ }
+
+ };
+
+
+
+ /*! \brief SchedulingPolicy which implements prioritized ordering.
+ *
+ * This container implements a scheduling policy based on task priorities.
+ * The task with highest priority will be the first to be removed.
+ * It must be possible to compare two tasks using operator<.
+ *
+ * \param Task A function object which implements the operator() and operator<. operator< must be a partial ordering.
+ *
+ * \see prio_thread_func
+ *
+ */
+ template <typename Task = prio_task_func>
+ class prio_scheduler
+ {
+ public:
+ typedef Task task_type; //!< Indicates the scheduler's task type.
+
+ protected:
+ std::priority_queue<task_type> m_container; //!< Internal task container.
+
+
+ public:
+ /*! Adds a new task to the scheduler.
+ * \param task The task object.
+ * \return true, if the task could be scheduled and false otherwise.
+ */
+ bool push(task_type const & task)
+ {
+ m_container.push(task);
+ return true;
+ }
+
+ /*! Removes the task which should be executed next.
+ */
+ void pop()
+ {
+ m_container.pop();
+ }
+
+ /*! Gets the task which should be executed next.
+ * \return The task object to be executed.
+ */
+ task_type const & top() const
+ {
+ return m_container.top();
+ }
+
+ /*! Gets the current number of tasks in the scheduler.
+ * \return The number of tasks.
+ * \remarks Prefer empty() to size() == 0 to check if the scheduler is empty.
+ */
+ size_t size() const
+ {
+ return m_container.size();
+ }
+
+ /*! Checks if the scheduler is empty.
+ * \return true if the scheduler contains no tasks, false otherwise.
+ * \remarks Is more efficient than size() == 0.
+ */
+ bool empty() const
+ {
+ return m_container.empty();
+ }
+
+ /*! Removes all tasks from the scheduler.
+ */
+ void clear()
+ {
+ while(!m_container.empty())
+ {
+ m_container.pop();
+ }
+ }
+ };
+
+
+} } // namespace boost::threadpool
+
+
+#endif // THREADPOOL_SCHEDULING_POLICIES_HPP_INCLUDED
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/shutdown_policies.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/shutdown_policies.hpp
new file mode 100644
index 0000000000..047a6eb516
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/shutdown_policies.hpp
@@ -0,0 +1,83 @@
+/*! \file
+* \brief Shutdown policies.
+*
+* This file contains shutdown policies for thread_pool.
+* A shutdown policy controls the pool's behavior from the time
+* when the pool is not referenced any longer.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* 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)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+
+#ifndef THREADPOOL_SHUTDOWN_POLICIES_HPP_INCLUDED
+#define THREADPOOL_SHUTDOWN_POLICIES_HPP_INCLUDED
+
+
+
+/// The namespace threadpool contains a thread pool and related utility classes.
+namespace boost { namespace threadpool
+{
+
+
+/*! \brief ShutdownPolicy which waits for the completion of all tasks
+ * and the worker termination afterwards.
+ *
+ * \param Pool The pool's core type.
+ */
+ template<typename Pool>
+ class wait_for_all_tasks
+ {
+ public:
+ static void shutdown(Pool& pool)
+ {
+ pool.wait();
+ pool.terminate_all_workers(true);
+ }
+ };
+
+
+ /*! \brief ShutdownPolicy which waits for the completion of all active tasks
+ * and the worker termination afterwards.
+ *
+ * \param Pool The pool's core type.
+ */
+ template<typename Pool>
+ class wait_for_active_tasks
+ {
+ public:
+ static void shutdown(Pool& pool)
+ {
+ pool.clear();
+ pool.wait();
+ pool.terminate_all_workers(true);
+ }
+ };
+
+
+ /*! \brief ShutdownPolicy which does not wait for any tasks or worker termination.
+ *
+ * This policy does not wait for any tasks. Nevertheless all active tasks will be processed completely.
+ *
+ * \param Pool The pool's core type.
+ */
+ template<typename Pool>
+ class immediately
+ {
+ public:
+ static void shutdown(Pool& pool)
+ {
+ pool.clear();
+ pool.terminate_all_workers(false);
+ }
+ };
+
+} } // namespace boost::threadpool
+
+#endif // THREADPOOL_SHUTDOWN_POLICIES_HPP_INCLUDED
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/size_policies.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/size_policies.hpp
new file mode 100644
index 0000000000..e3c08038db
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/size_policies.hpp
@@ -0,0 +1,99 @@
+/*! \file
+* \brief Size policies.
+*
+* This file contains size policies for thread_pool. A size
+* policy controls the number of worker threads in the pool.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* 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)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+
+#ifndef THREADPOOL_SIZE_POLICIES_HPP_INCLUDED
+#define THREADPOOL_SIZE_POLICIES_HPP_INCLUDED
+
+
+
+/// The namespace threadpool contains a thread pool and related utility classes.
+namespace boost { namespace threadpool
+{
+
+ /*! \brief SizePolicyController which provides no functionality.
+ *
+ * \param Pool The pool's core type.
+ */
+ template<typename Pool>
+ struct empty_controller
+ {
+ empty_controller(typename Pool::size_policy_type&, shared_ptr<Pool>) {}
+ };
+
+
+ /*! \brief SizePolicyController which allows resizing.
+ *
+ * \param Pool The pool's core type.
+ */
+ template< typename Pool >
+ class resize_controller
+ {
+ typedef typename Pool::size_policy_type size_policy_type;
+ reference_wrapper<size_policy_type> m_policy;
+ shared_ptr<Pool> m_pool; //!< to make sure that the pool is alive (the policy pointer is valid) as long as the controller exists
+
+ public:
+ resize_controller(size_policy_type& policy, shared_ptr<Pool> pool)
+ : m_policy(policy)
+ , m_pool(pool)
+ {
+ }
+
+ bool resize(size_t worker_count)
+ {
+ return m_policy.get().resize(worker_count);
+ }
+ };
+
+
+ /*! \brief SizePolicy which preserves the thread count.
+ *
+ * \param Pool The pool's core type.
+ */
+ template<typename Pool>
+ class static_size
+ {
+ reference_wrapper<Pool volatile> m_pool;
+
+ public:
+ static void init(Pool& pool, size_t const worker_count)
+ {
+ pool.resize(worker_count);
+ }
+
+ static_size(Pool volatile & pool)
+ : m_pool(pool)
+ {}
+
+ bool resize(size_t const worker_count)
+ {
+ return m_pool.get().resize(worker_count);
+ }
+
+ void worker_died_unexpectedly(size_t const new_worker_count)
+ {
+ m_pool.get().resize(new_worker_count + 1);
+ }
+
+ // TODO this functions are not called yet
+ void task_scheduled() {}
+ void task_finished() {}
+ };
+
+} } // namespace boost::threadpool
+
+#endif // THREADPOOL_SIZE_POLICIES_HPP_INCLUDED
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/task_adaptors.hpp b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/task_adaptors.hpp
new file mode 100644
index 0000000000..6b874e3358
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/boost/threadpool/task_adaptors.hpp
@@ -0,0 +1,168 @@
+/*! \file
+* \brief Task adaptors.
+*
+* This file contains adaptors for task function objects.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* 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)
+*
+* http://threadpool.sourceforge.net
+*
+*/
+
+
+#ifndef THREADPOOL_TASK_ADAPTERS_HPP_INCLUDED
+#define THREADPOOL_TASK_ADAPTERS_HPP_INCLUDED
+
+
+#include <boost/smart_ptr.hpp>
+#include <boost/function.hpp>
+#include <boost/thread.hpp>
+
+
+namespace boost { namespace threadpool
+{
+
+ /*! \brief Standard task function object.
+ *
+ * This function object wraps a nullary function which returns void.
+ * The wrapped function is invoked by calling the operator ().
+ *
+ * \see boost function library
+ *
+ */
+ typedef function0<void> task_func;
+
+
+
+
+ /*! \brief Prioritized task function object.
+ *
+ * This function object wraps a task_func object and binds a priority to it.
+ * prio_task_funcs can be compared using the operator < which realises a partial ordering.
+ * The wrapped task function is invoked by calling the operator ().
+ *
+ * \see prio_scheduler
+ *
+ */
+ class prio_task_func
+ {
+ private:
+ unsigned int m_priority; //!< The priority of the task's function.
+ task_func m_function; //!< The task's function.
+
+ public:
+ typedef void result_type; //!< Indicates the functor's result type.
+
+ public:
+ /*! Constructor.
+ * \param priority The priority of the task.
+ * \param function The task's function object.
+ */
+ prio_task_func(unsigned int const priority, task_func const & function)
+ : m_priority(priority)
+ , m_function(function)
+ {
+ }
+
+ /*! Executes the task function.
+ */
+ void operator() (void) const
+ {
+ if(m_function)
+ {
+ m_function();
+ }
+ }
+
+ /*! Comparison operator which realises a partial ordering based on priorities.
+ * \param rhs The object to compare with.
+ * \return true if the priority of *this is less than right hand side's priority, false otherwise.
+ */
+ bool operator< (const prio_task_func& rhs) const
+ {
+ return m_priority < rhs.m_priority;
+ }
+
+ }; // prio_task_func
+
+
+
+
+
+
+
+
+ /*! \brief Looped task function object.
+ *
+ * This function object wraps a boolean thread function object.
+ * The wrapped task function is invoked by calling the operator () and it is executed in regular
+ * time intervals until false is returned. The interval length may be zero.
+ * Please note that a pool's thread is engaged as long as the task is looped.
+ *
+ */
+ class looped_task_func
+ {
+ private:
+ function0<bool> m_function; //!< The task's function.
+ unsigned int m_break_s; //!< Duration of breaks in seconds.
+ unsigned int m_break_ns; //!< Duration of breaks in nano seconds.
+
+ public:
+ typedef void result_type; //!< Indicates the functor's result type.
+
+ public:
+ /*! Constructor.
+ * \param function The task's function object which is looped until false is returned.
+ * \param interval The minimum break time in milli seconds before the first execution of the task function and between the following ones.
+ */
+ looped_task_func(function0<bool> const & function, unsigned int const interval = 0)
+ : m_function(function)
+ {
+ m_break_s = interval / 1000;
+ m_break_ns = (interval - m_break_s * 1000) * 1000 * 1000;
+ }
+
+ /*! Executes the task function.
+ */
+ void operator() (void) const
+ {
+ if(m_function)
+ {
+ if(m_break_s > 0 || m_break_ns > 0)
+ { // Sleep some time before first execution
+ xtime xt;
+ xtime_get(&xt, TIME_UTC);
+ xt.nsec += m_break_ns;
+ xt.sec += m_break_s;
+ thread::sleep(xt);
+ }
+
+ while(m_function())
+ {
+ if(m_break_s > 0 || m_break_ns > 0)
+ {
+ xtime xt;
+ xtime_get(&xt, TIME_UTC);
+ xt.nsec += m_break_ns;
+ xt.sec += m_break_s;
+ thread::sleep(xt);
+ }
+ else
+ {
+ thread::yield(); // Be fair to other threads
+ }
+ }
+ }
+ }
+
+ }; // looped_task_func
+
+
+} } // namespace boost::threadpool
+
+#endif // THREADPOOL_TASK_ADAPTERS_HPP_INCLUDED
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/Makefile b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/Makefile
new file mode 100644
index 0000000000..578ff7e0ba
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/Makefile
@@ -0,0 +1,36 @@
+DOXYGEN=doxygen
+
+doc: clean copy_footer generate_doc
+
+copy_footer:
+ cp footer/*.htm .
+
+copy_footer_sf:
+ cp footer_sf/*.htm .
+
+generate_doc:
+ $(DOXYGEN) overview.dox
+ $(DOXYGEN) reference.dox
+ $(DOXYGEN) tutorial.dox
+ $(DOXYGEN) examples.dox
+ $(DOXYGEN) design.dox
+
+clean:
+ rm -rf ../../../doc
+ rm -rf ../../../threadpool-$(RELEASE_VERSION)-doc
+ rm -rf ../../../threadpool-$(RELEASE_VERSION)-doc.zip
+
+release_doc: clean doc
+ cd ../../..; mv doc threadpool-$(RELEASE_VERSION)-doc
+ cd ../../..; zip -r9 threadpool-$(RELEASE_VERSION)-doc.zip threadpool-$(RELEASE_VERSION)-doc
+ cd ../../..; mv threadpool-$(RELEASE_VERSION)-doc doc
+
+doc_sf: clean copy_footer_sf generate_doc
+
+deploy_sf: doc_sf
+ scp -vr ../../../doc/* $(RELEASE_MANAGER)@shell.sourceforge.net:/home/groups/t/th/threadpool/htdocs
+
+
+
+
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/design.dox b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/design.dox
new file mode 100644
index 0000000000..06b287c7e4
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/design.dox
@@ -0,0 +1,145 @@
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = "threadpool"
+PROJECT_NUMBER =
+OUTPUT_DIRECTORY = ../../../doc/design
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+USE_WINDOWS_ENCODING = NO
+BRIEF_MEMBER_DESC = NO
+REPEAT_BRIEF = NO
+ALWAYS_DETAILED_SEC = YES
+INLINE_INHERITED_MEMB = YES
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH = /../../include/
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = YES
+JAVADOC_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = YES
+DETAILS_AT_TOP = YES
+INHERIT_DOCS = YES
+DISTRIBUTE_GROUP_DOC = NO
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 2
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = 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 = NO
+INLINE_INFO = NO
+SORT_MEMBER_DOCS = NO
+SORT_BRIEF_DOCS = NO
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = NO
+GENERATE_TESTLIST = NO
+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 = design.txt
+FILE_PATTERNS =
+RECURSIVE = NO
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS =
+EXAMPLE_RECURSIVE = YES
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = NO
+REFERENCES_RELATION = NO
+VERBATIM_HEADERS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = NO
+COLS_IN_ALPHA_INDEX = 1
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = .
+HTML_FILE_EXTENSION = .html
+HTML_HEADER = design_header.htm
+HTML_FOOTER = common_footer.htm
+HTML_STYLESHEET = threadpool.css
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = YES
+ENUM_VALUES_PER_LINE = 1
+GENERATE_TREEVIEW = NO
+TREEVIEW_WIDTH = 250
+
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/design.txt b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/design.txt
new file mode 100644
index 0000000000..05cf85e8ac
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/design.txt
@@ -0,0 +1,35 @@
+/*! \page intro TODO5
+
+
+A thread pool manages a homogeneous pool of worker threads. In general worker threads are created once and are used to
+process a sequence of tasks. The re-use of threads reduces the thread creation and teardown overhead. The resource
+consumption is limited as the number of threads can be restricted. This leads to an improved system stability.
+
+Thread-per-task
+
+TODO5
+
+light-weight, no administration/management thread, synchronized scheduler, e.g. queue
+
+
+ */
+
+
+/*! \page pattern Thread Pool Pattern
+
+
+In the thread pool pattern in programming, a number of N threads are created to perform a number of M tasks, usually organized in a queue. Typically, N << M. As soon as a thread completes its task, it will request the next task from the queue until all tasks have been completed. The thread can then terminate, or sleep until there are new tasks available.
+
+The number of threads used (N) is a parameter that can be tuned to provide the best performance.
+
+The advantage of using a Thread Pool over creating a new thread for each task, is that thread creation and destruction overhead is negated, which may result in better performance and better system stability.
+
+<BR>
+<B>From <A HREF="http://en.wikipedia.org/wiki/Thread_pool_pattern"> Wikipedia </A>, the free encyclopedia.</B>
+
+
+
+ */
+
+
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/design_header.htm b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/design_header.htm
new file mode 100644
index 0000000000..006ce09490
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/design_header.htm
@@ -0,0 +1,38 @@
+<HTML>
+ <HEAD>
+ <TITLE>threadpool Documentation</TITLE>
+ <LINK HREF="threadpool.css" REL="stylesheet" TYPE="text/css">
+ </HEAD>
+ <BODY BGCOLOR="#FFFFFF">
+
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+
+ <TD ALIGN="LEFT">
+ <B>$projectname</B>
+ </TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="../index.html">Overview</A> |
+ <A CLASS="qindex" HREF="../reference/annotated.html">Reference</A> |
+ <A CLASS="qindex" HREF="../tutorial/intro.html">Tutorial</A> |
+ <A CLASS="qindex" HREF="../examples/intro.html">Examples</A> |
+ <A CLASS="qindex" HREF="../design/intro.html">Design</A>
+ </TD>
+
+ </TR>
+ </TABLE>
+ </DIV>
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+ <TD ALIGN="LEFT">
+ <B>Design</B>
+ </TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="intro.html">TODO5</A> |
+ <A CLASS="qindex" HREF="pattern.html">Thread Pool Pattern</A>
+ </TD>
+ </TR>
+ </TABLE>
+ </DIV>
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/examples.dox b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/examples.dox
new file mode 100644
index 0000000000..128a4089ad
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/examples.dox
@@ -0,0 +1,145 @@
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = "threadpool"
+PROJECT_NUMBER =
+OUTPUT_DIRECTORY = ../../../doc/examples
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+USE_WINDOWS_ENCODING = NO
+BRIEF_MEMBER_DESC = NO
+REPEAT_BRIEF = NO
+ALWAYS_DETAILED_SEC = YES
+INLINE_INHERITED_MEMB = YES
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH = /../../include
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = YES
+JAVADOC_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = YES
+DETAILS_AT_TOP = YES
+INHERIT_DOCS = YES
+DISTRIBUTE_GROUP_DOC = NO
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 2
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = 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 = NO
+INLINE_INFO = NO
+SORT_MEMBER_DOCS = NO
+SORT_BRIEF_DOCS = NO
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = NO
+GENERATE_TESTLIST = NO
+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 = examples.txt
+FILE_PATTERNS =
+RECURSIVE = NO
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS =
+EXAMPLE_RECURSIVE = YES
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = NO
+REFERENCES_RELATION = NO
+VERBATIM_HEADERS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = NO
+COLS_IN_ALPHA_INDEX = 1
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = .
+HTML_FILE_EXTENSION = .html
+HTML_HEADER = examples_header.htm
+HTML_FOOTER = common_footer.htm
+HTML_STYLESHEET = threadpool.css
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = YES
+ENUM_VALUES_PER_LINE = 1
+GENERATE_TREEVIEW = NO
+TREEVIEW_WIDTH = 250
+
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/examples.txt b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/examples.txt
new file mode 100644
index 0000000000..fbb29f4d33
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/examples.txt
@@ -0,0 +1,14 @@
+
+/*! \page intro TODO3
+
+See src/examples/mergesort/mergesort.cpp
+<BR>
+
+ */
+
+
+/*! \page pattern TODO4
+TODO4
+
+ */
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/examples_header.htm b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/examples_header.htm
new file mode 100644
index 0000000000..d35512cf52
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/examples_header.htm
@@ -0,0 +1,38 @@
+<HTML>
+ <HEAD>
+ <TITLE>threadpool Documentation</TITLE>
+ <LINK HREF="threadpool.css" REL="stylesheet" TYPE="text/css">
+ </HEAD>
+ <BODY BGCOLOR="#FFFFFF">
+
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+
+ <TD ALIGN="LEFT">
+ <B>$projectname</B>
+ </TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="../index.html">Overview</A> |
+ <A CLASS="qindex" HREF="../reference/annotated.html">Reference</A> |
+ <A CLASS="qindex" HREF="../tutorial/intro.html">Tutorial</A> |
+ <A CLASS="qindex" HREF="../examples/intro.html">Examples</A> |
+ <A CLASS="qindex" HREF="../design/intro.html">Design</A>
+ </TD>
+
+ </TR>
+ </TABLE>
+ </DIV>
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+ <TD ALIGN="LEFT">
+ <B>Examples</B>
+ </TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="intro.html">TODO3</A> |
+ <A CLASS="qindex" HREF="pattern.html">TODO4</A>
+ </TD>
+ </TR>
+ </TABLE>
+ </DIV>
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer/common_footer.htm b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer/common_footer.htm
new file mode 100644
index 0000000000..1debd97adf
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer/common_footer.htm
@@ -0,0 +1,17 @@
+ <BR>
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+ <TD CLASS="tiny" ALIGN="LEFT">Copyright &copy 2005-2008 Philipp Henkel</TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="../index.html">Overview</A> |
+ <A CLASS="qindex" HREF="../reference/annotated.html">Reference</A> |
+ <A CLASS="qindex" HREF="../tutorial/intro.html">Tutorial</A> |
+ <A CLASS="qindex" HREF="../examples/intro.html">Examples</A> |
+ <A CLASS="qindex" HREF="../design/intro.html">Design</A>
+ </TD>
+ </TR>
+ </TABLE>
+ </DIV>
+ </BODY>
+</HTML>
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer/overview_footer.htm b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer/overview_footer.htm
new file mode 100644
index 0000000000..75ef22b181
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer/overview_footer.htm
@@ -0,0 +1,17 @@
+ <BR>
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+ <TD CLASS="tiny" ALIGN="LEFT">Copyright &copy 2005-2008 Philipp Henkel</TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="index.html">Overview</A> |
+ <A CLASS="qindex" HREF="reference/annotated.html">Reference</A> |
+ <A CLASS="qindex" HREF="tutorial/intro.html">Tutorial</A> |
+ <A CLASS="qindex" HREF="examples/intro.html">Examples</A> |
+ <A CLASS="qindex" HREF="design/intro.html">Design</A>
+ </TD>
+ </TR>
+ </TABLE>
+ </DIV>
+ </BODY>
+</HTML>
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer_sf/common_footer.htm b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer_sf/common_footer.htm
new file mode 100644
index 0000000000..7c177c9f33
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer_sf/common_footer.htm
@@ -0,0 +1,30 @@
+ <BR>
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+ <TD CLASS="tiny" ALIGN="LEFT">Copyright &copy 2005-2008 Philipp Henkel</TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="../index.html">Overview</A> |
+ <A CLASS="qindex" HREF="../reference/annotated.html">Reference</A> |
+ <A CLASS="qindex" HREF="../tutorial/intro.html">Tutorial</A> |
+ <A CLASS="qindex" HREF="../examples/intro.html">Examples</A> |
+ <A CLASS="qindex" HREF="../design/intro.html">Design</A>
+ </TD>
+ </TR>
+ </TABLE>
+ </DIV>
+
+ <P align="right" valign="top">
+ Hosted by
+ <A HREF="http://sourceforge.net">
+ <IMG src="http://sflogo.sourceforge.net/sflogo.php?group_id=158064&type=2"
+ width="125"
+ height="37"
+ border="0"
+ align="top"
+ alt="SourceForge.net Logo"/>
+ </A>
+ </P>
+
+ </BODY>
+</HTML>
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer_sf/overview_footer.htm b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer_sf/overview_footer.htm
new file mode 100644
index 0000000000..4a6f80c53b
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/footer_sf/overview_footer.htm
@@ -0,0 +1,29 @@
+ <BR>
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+ <TD CLASS="tiny" ALIGN="LEFT">Copyright &copy 2005-2008 Philipp Henkel</TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="index.html">Overview</A> |
+ <A CLASS="qindex" HREF="reference/annotated.html">Reference</A> |
+ <A CLASS="qindex" HREF="tutorial/intro.html">Tutorial</A> |
+ <A CLASS="qindex" HREF="examples/intro.html">Examples</A> |
+ <A CLASS="qindex" HREF="design/intro.html">Design</A>
+ </TD>
+ </TR>
+ </TABLE>
+ </DIV>
+
+ <P align="right" valign="top">
+ Hosted by
+ <A HREF="http://sourceforge.net">
+ <IMG src="http://sflogo.sourceforge.net/sflogo.php?group_id=158064&type=2"
+ width="125"
+ height="37"
+ border="0"
+ align="top"
+ alt="SourceForge.net Logo"/>
+ </A>
+ </P>
+ </BODY>
+</HTML>
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/index.html b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/index.html
new file mode 100644
index 0000000000..f36e87310d
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/index.html
@@ -0,0 +1,9 @@
+<HTML>
+ <HEAD>
+ <TITLE>threadpool Documentation</TITLE>
+ <meta http-equiv="refresh" content="2;url=overview/index.html">
+ </HEAD>
+ <BODY BGCOLOR="#FFFFFF">
+
+ </BODY>
+</HTML>
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/overview.dox b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/overview.dox
new file mode 100644
index 0000000000..3021c3972d
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/overview.dox
@@ -0,0 +1,145 @@
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = "threadpool"
+PROJECT_NUMBER = 0.2.5
+OUTPUT_DIRECTORY = ../../../doc
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+USE_WINDOWS_ENCODING = NO
+BRIEF_MEMBER_DESC = NO
+REPEAT_BRIEF = NO
+ALWAYS_DETAILED_SEC = YES
+INLINE_INHERITED_MEMB = YES
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH = /../../../boost/threadpool
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = YES
+JAVADOC_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = YES
+DETAILS_AT_TOP = YES
+INHERIT_DOCS = YES
+DISTRIBUTE_GROUP_DOC = NO
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 2
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = 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 = NO
+INLINE_INFO = NO
+SORT_MEMBER_DOCS = NO
+SORT_BRIEF_DOCS = NO
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = NO
+GENERATE_TESTLIST = NO
+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 = overview.txt
+FILE_PATTERNS =
+RECURSIVE = NO
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXAMPLE_PATH = ../../..
+EXAMPLE_PATTERNS =
+EXAMPLE_RECURSIVE = YES
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = NO
+REFERENCES_RELATION = NO
+VERBATIM_HEADERS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = NO
+COLS_IN_ALPHA_INDEX = 1
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = .
+HTML_FILE_EXTENSION = .html
+HTML_HEADER = overview_header.htm
+HTML_FOOTER = overview_footer.htm
+HTML_STYLESHEET = threadpool.css
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = YES
+ENUM_VALUES_PER_LINE = 1
+GENERATE_TREEVIEW = NO
+TREEVIEW_WIDTH = 250
+
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/overview.txt b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/overview.txt
new file mode 100644
index 0000000000..3a995fffb9
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/overview.txt
@@ -0,0 +1,205 @@
+/*! \mainpage threadpool
+
+
+\section intro_sec threadpool
+threadpool is a cross-platform C++ thread pool library. In general terms thread pools
+are an efficient mechanism for asynchronous task processing within the same process.
+They realise the <A HREF="design/pattern.html"> thread pool pattern</A>.
+
+A thread pool manages a group of threads in order to process a large number of tasks.
+Since multiple threads can be executed in parallel this approach may be very efficient regarding the overall program performance on many computer systems. By restricting the number of threads and by reusing them resources are saved
+and additionally the system stability is increased.
+
+The threadpool library provides a convenient way for dispatching asynchronous tasks. Pools can be customized, managed dynamically and easily integrated into your software.
+
+
+\section dev_status_sec Development Status & Future Work
+The threadpool core classes are completed and the implemenation can be considered ready for production code. The library is used by several commercial server applications and can handle high workload without problems. I'm currently working on helper and service classes which make the
+usage of the pool more comfortable. A small tutorial introduces the thread pool and
+more example code will be added in the future. The documentation is far away from being finished.
+<BR>
+<BR><A HREF="http://threadpool.cvs.sourceforge.net/threadpool/threadpool">Browse CVS Repository</A>
+<BR>
+
+<P>
+Features
+- Policy-based thread pool implementation<BR>
+- Scheduling policies: fifo, lifo and priority<BR>
+- Size policies: static_size<BR>
+- Size policy controller: empty_controller, resize_controller<BR>
+- Shutdown policies: wait_for_all_tasks, wait_for_active_tasks, immediately<BR>
+- Smooth integration into STL and boost<BR>
+</P>
+
+<P>
+Future Work
+- More policies: deadline_scheduler, ...<BR>
+- Possibility of limiting the number of pending tasks<BR>
+- Futures (handles to results of scheduled functions)<BR>
+- More examples to illustrate the usage of the library<BR>
+- Provide Unit tests<BR>
+</P>
+
+
+
+
+\section down_sec Download Section
+<P>
+threadpool 0.2.5 (Development Snapshot)
+- <A HREF="http://prdownloads.sourceforge.net/threadpool/threadpool-0_2_5-src.zip?download">threadpool-0_2_5-src.zip</A><BR>
+- <A HREF="http://prdownloads.sourceforge.net/threadpool/threadpool-0_2_5-doc.zip?download">threadpool-0_2_5-doc.zip</A><BR>
+</P>
+
+For more information on the revisions see \ref changelog.
+
+
+\section platforms_sec Supported Platforms
+threadpool is highly portable. It runs on any platform on which Boost threads are available: Linux, Windows, Mac OS 9/X, Solaris, etc.
+
+
+\section boost_sec Boost Libraries
+Boost is a collection of high-quality C++ libraries and works on almost any
+modern operating system, including UNIX and Windows variants.
+In fact threadpool is only a small extension to the portable Boost source libraries.
+It incorporates the thread pool concept by using the thread library from William Kempf.
+For more information on this excellent library visit <A HREF="http://www.boost.org">Boost.org</A>.
+
+
+\section installation_sec Installing & Using threadpool
+threadpool consists only of header files, and so there is no need to build the library itself
+before using it in your own applications. You simply need to add the
+following directories to your compiler include path:<BR>
+ - threadpool's include directory<BR>
+ - the boost directory (e.g. the one called boost_1_37_0)<BR>
+
+Furthermore you have to compile boost's thread library and link against it (libboost_thread-*.lib under Windows).
+
+
+
+\section license_sec Software License
+threadpool is released under the \ref license "Boost Software License".
+This license encourages both commercial and non-commercial use.
+
+
+\section acknowledgments_sec Acknowledgments
+This library was written by Philipp Henkel.
+<P>
+I appreciate your suggestions, and would love to know if you
+use threadpool. Hopefully you will enjoy it and find it useful.
+Please post questions, comments, bugs, or contact me at:
+
+</P>
+
+threadpool@googlemail.com<BR>
+or<BR>
+<A HREF="http://www.sourceforge.net/projects/threadpool">www.sourceforge.net/projects/threadpool</A>
+<BR>
+<BR>
+*/
+
+
+
+/*! \page license Software License
+
+\verbinclude LICENSE_1_0.txt
+
+*/
+
+
+
+ /*! \page changelog Change Log
+
+ <B>0.2.5 (Stable)</B>
+ - Made threadpool compatible to boost::thread 1.37
+ - Fixed hang problem in shutdown method (Thanks to Sohail Somani)
+ - Adapted repository layout to boost (Thanks to Alex Ott)
+
+<B>0.2.4 (Stable)</B>
+ - Made threadpool compatible to boost::thread 1.35.x code base
+ - Fixed compiler warning in scope_guard.hpp
+
+<B>0.2.4 (Stable)</B>
+ - Made threadpool compatible to boost::thread 1.35.x code base
+ - Fixed compiler warning in scope_guard.hpp
+
+<B>0.2.3 (Development)</B>
+ - Implemented workaround for Sun C++ Pro compiler bug in pool_core
+ - Removed subtask implementation (there was no demand for this feature)
+ - Improved shutdown policies
+
+<B>0.2.2 (Development)</B>
+ - Refactored SizePolicy and added SizePolicyController
+ - Moved policies into separate files
+ - Fixed some compiler problems (GCC)
+ - Implemented size_controller handling
+ - Implemented two size policies: static_size and fixed_size
+ - Refactored worker_thread handling, moved policies from pool_core to pool
+ - Specialized schedule function for usage with futures
+ - Added compile test project
+ - Improved constness in pool core class
+ - Fixed timed wait
+ - Implemented futures (in progress)
+ - Added result_type to all functors
+
+<B>0.2.1 (Development)</B>
+ - Pool base class (thread_pool) has now reference semantics.
+ - Large refactorings: Removed scoped_pool, reimplemented worker (now worker_thread)
+ - Fixed odd resize behaviour. Now resize changes the number of threads immediately.
+ - Apply pimpl idiom on pool core class (to make the ugly scoped_pool class needless)
+ - Introduced scheduling policies
+ - Switched to policy-based design (PBD), inspired by Scott Meyers C++ workshop
+ - Cosmetic code change: Replaced keyword 'class' with 'typename' in template definitions
+ - Revised tutorials
+ - New requirements: tasks functions should not and schedulers shall not throw exceptions
+
+<B>0.2.0 (Development)</B>
+ - Moved threadpool into the boost namespace: boost::threadpool
+ - Used keyword volatile to indicate thread-safe member functions
+ - Used volatile on primitve types were appropriate
+ - Moved worker to detail directory
+ - Fixed thread deletion
+ - Extended wait functionality (waiting for idle threads was implemented)
+ - Renamed 'join()' to 'wait()' as 'join' indicates the termination of thread. That was not the case in pool::join.
+ - Changed internal container of lifo and fifo schedulers to improve efficiency.
+ - Improved code reference documentation (source code browser)
+ - Renamed thread_func into task_func
+ - Added += operator to scoped_pool to ease scheduling of tasks
+ - Refactored file structures and class names
+ - Added a new task concept (named subtask) which allows the combination of sequential and parallel execution
+ - Added new task adaptor for looped or timed tasks: looped_task_func
+ - Introduced function clear() which can be used to remove all tasks from the pool and schedulers
+ - New function pool::active() which returns the number of active tasks
+
+<B>0.1.8 (Development)</B>
+ - Fixed some compile errors which were reported by gcc
+ - Wrote tutorial "Prioritized Tasks"
+
+<B>0.1.7 (Development)</B>
+ - Added Visual Studio 2005 project files for tutorial and examples
+
+<B>0.1.6 (Development)</B>
+ - Replaced task adaptor 'task' with boost::bind
+ - Workers are unregistered from thread_group when they are terminated
+ - Working on example boost::iostreams packet_filter
+
+<B>0.1.5 (Development)</B>
+ - Finished threadpool reference
+ - Class pool_adaptor was replaced by smart_pool
+ - Minor pool improvements
+ - First tutorial page online
+
+<B>0.1.4 (Development)</B>
+ - Created the pool's homepage: http://threadpool.sourceforge.net
+ - Improved documentation
+ - Added build scripts
+
+<B>0.1.3 (Development)</B>
+ - First public release
+ - Added mergesort example
+ - Added tutorial
+ - Implementation of threadpool core and related classes
+
+ */
+
+
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/overview_header.htm b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/overview_header.htm
new file mode 100644
index 0000000000..dc6e9f6c18
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/overview_header.htm
@@ -0,0 +1,36 @@
+<HTML>
+ <HEAD>
+ <TITLE>threadpool Documentation</TITLE>
+ <LINK HREF="threadpool.css" REL="stylesheet" TYPE="text/css">
+ </HEAD>
+ <BODY BGCOLOR="#FFFFFF">
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+ <TD ALIGN="LEFT">
+ <B>$projectname</B>
+ </TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="index.html">Overview</A> |
+ <A CLASS="qindex" HREF="reference/annotated.html">Reference</A> |
+ <A CLASS="qindex" HREF="tutorial/intro.html">Tutorial</A> |
+ <A CLASS="qindex" HREF="examples/intro.html">Examples</A> |
+ <A CLASS="qindex" HREF="design/intro.html">Design</A>
+ </TD>
+ </TR>
+ </TABLE>
+ </DIV>
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+ <TD ALIGN="LEFT">
+ <B>Overview</B>
+ </TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="index.html">Main Page</A> |
+ <A CLASS="qindex" HREF="changelog.html">Change Log</A> |
+ <A CLASS="qindex" HREF="license.html">Software License</A>
+ </TD>
+ </TR>
+ </TABLE>
+ </DIV>
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/reference.dox b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/reference.dox
new file mode 100644
index 0000000000..d0fb398834
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/reference.dox
@@ -0,0 +1,220 @@
+# Doxyfile 1.4.2
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = "threadpool"
+PROJECT_NUMBER =
+OUTPUT_DIRECTORY = ../../../doc/reference
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+USE_WINDOWS_ENCODING = NO
+BRIEF_MEMBER_DESC = NO
+REPEAT_BRIEF = YES
+ALWAYS_DETAILED_SEC = YES
+INLINE_INHERITED_MEMB = YES
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH = /../../../boost/threadpool
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = YES
+JAVADOC_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = YES
+DETAILS_AT_TOP = YES
+INHERIT_DOCS = YES
+DISTRIBUTE_GROUP_DOC = NO
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 2
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = NO
+SUBGROUPING = YES
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = YES
+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 = NO
+INLINE_INFO = NO
+SORT_MEMBER_DOCS = YES
+SORT_BRIEF_DOCS = YES
+SORT_BY_SCOPE_NAME = YES
+GENERATE_TODOLIST = NO
+GENERATE_TESTLIST = NO
+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 = ../../../boost ../../../boost/threadpool
+FILE_PATTERNS = *.hpp
+RECURSIVE = NO
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXAMPLE_PATH = /../examples
+EXAMPLE_PATTERNS =
+EXAMPLE_RECURSIVE = YES
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = YES
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = NO
+REFERENCES_RELATION = NO
+VERBATIM_HEADERS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = YES
+COLS_IN_ALPHA_INDEX = 1
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = .
+HTML_FILE_EXTENSION = .html
+HTML_HEADER = reference_header.htm
+HTML_FOOTER = common_footer.htm
+HTML_STYLESHEET = threadpool.css
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = YES
+ENUM_VALUES_PER_LINE = 1
+GENERATE_TREEVIEW = NO
+TREEVIEW_WIDTH = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4wide
+EXTRA_PACKAGES =
+LATEX_HEADER =
+PDF_HYPERLINKS = NO
+USE_PDFLATEX = NO
+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 = YES
+EXPAND_ONLY_PREDEF = YES
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+PREDEFINED =
+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 = YES
+HAVE_DOT = YES
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = NO
+GROUP_GRAPHS = YES
+UML_LOOK = NO
+TEMPLATE_RELATIONS = YES
+INCLUDE_GRAPH = NO
+INCLUDED_BY_GRAPH = NO
+CALL_GRAPH = NO
+GRAPHICAL_HIERARCHY = NO
+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 = NO
+DOT_CLEANUP = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/reference_header.htm b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/reference_header.htm
new file mode 100644
index 0000000000..40fd7423aa
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/reference_header.htm
@@ -0,0 +1,40 @@
+<HTML>
+ <HEAD>
+ <TITLE>threadpool Documentation</TITLE>
+ <LINK HREF="threadpool.css" REL="stylesheet" TYPE="text/css">
+ </HEAD>
+ <BODY BGCOLOR="#FFFFFF">
+
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+
+ <TD ALIGN="LEFT">
+ <B>$projectname</B>
+ </TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="../index.html">Overview</A> |
+ <A CLASS="qindex" HREF="../reference/annotated.html">Reference</A> |
+ <A CLASS="qindex" HREF="../tutorial/intro.html">Tutorial</A> |
+ <A CLASS="qindex" HREF="../examples/intro.html">Examples</A> |
+ <A CLASS="qindex" HREF="../design/intro.html">Design</A>
+ </TD>
+
+ </TR>
+ </TABLE>
+ </DIV>
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+ <TD ALIGN="LEFT">
+ <B>Reference</B>
+ </TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="annotated.html">Class List</A> |
+ <A CLASS="qindex" HREF="functions.html">Member Functions</A> |
+ <A CLASS="qindex" HREF="namespacemembers.html">Typedefs</A> |
+ <A CLASS="qindex" HREF="files.html">File List</A>
+ </TD>
+ </TR>
+ </TABLE>
+ </DIV>
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/threadpool.css b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/threadpool.css
new file mode 100644
index 0000000000..8593700905
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/threadpool.css
@@ -0,0 +1,331 @@
+BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+}
+BODY,TD {
+ font-size: 90%;
+}
+H1 {
+ text-align: center;
+ font-size: 160%;
+}
+H2 {
+ font-size: 120%;
+}
+H3 {
+ font-size: 100%;
+}
+CAPTION { font-weight: bold }
+DIV.sidebar {
+ width: 210px;
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
+ margin: 2px;
+ margin-bottom: 20px;
+ padding: 2px;
+ line-height: 140%;
+}
+DIV.sidebar TABLE TR TD {
+ font-size: 80%;
+}
+DIV.sidebar UL {
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+DIV.qindex {
+ width: 100%;
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
+ margin: 2px;
+ padding: 2px;
+ line-height: 140%;
+}
+DIV.nav {
+ width: 100%;
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
+ margin: 2px;
+ padding: 2px;
+ line-height: 140%;
+}
+DIV.navtab {
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
+ margin: 2px;
+ margin-right: 15px;
+ padding: 2px;
+}
+TD.navtab {
+ font-size: 70%;
+}
+A.qindex {
+ text-decoration: none;
+ font-weight: bold;
+ color: #1A419D;
+}
+A.qindex:visited {
+ text-decoration: none;
+ font-weight: bold;
+ color: #1A419D
+}
+A.qindex:hover {
+ text-decoration: none;
+ background-color: #ddddff;
+}
+A.qindexHL {
+ text-decoration: none;
+ font-weight: bold;
+ background-color: #6666cc;
+ color: #ffffff;
+ border: 1px double #9295C2;
+}
+A.qindexHL:hover {
+ text-decoration: none;
+ background-color: #6666cc;
+ color: #ffffff;
+}
+A.anchor {
+ text-decoration: none;
+ color: #000000;
+}
+A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff }
+A.el { text-decoration: none; font-weight: bold }
+A.elRef { text-decoration: none; font-weight: bold }
+A.code:link { text-decoration: none; font-weight: normal; color: #0000FF}
+A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF}
+A.codeRef:link { text-decoration: none; font-weight: normal; color: #0000FF}
+A.codeRef:visited { text-decoration: none; font-weight: normal; color: #0000FF}
+A:hover { text-decoration: none; background-color: #f2f2ff }
+DL.el { margin-left: -1cm }
+.fragment {
+ font-family: Fixed, monospace;
+ font-size: 95%;
+}
+PRE.fragment {
+ border: 1px solid #CCCCCC;
+ background-color: #f5f5f5;
+ margin-top: 4px;
+ margin-bottom: 4px;
+ margin-left: 2px;
+ margin-right: 8px;
+ padding-left: 6px;
+ padding-right: 6px;
+ padding-top: 4px;
+ padding-bottom: 4px;
+}
+DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px }
+TD.md { background-color: #F4F4FB; font-weight: bold; }
+TD.mdPrefix {
+ background-color: #F4F4FB;
+ color: #606060;
+ font-size: 80%;
+}
+TD.mdname1 { background-color: #F4F4FB; font-weight: bold; color: #602020; }
+TD.mdname { background-color: #F4F4FB; font-weight: bold; color: #602020; width: 600px; }
+DIV.groupHeader {
+ margin-left: 16px;
+ margin-top: 12px;
+ margin-bottom: 6px;
+ font-weight: bold;
+}
+DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% }
+BODY {
+ background: white;
+ color: black;
+ margin-right: 20px;
+ margin-left: 20px;
+}
+TD.indexkey {
+ background-color: #e8eef2;
+ font-weight: bold;
+ padding-right : 10px;
+ padding-top : 2px;
+ padding-left : 10px;
+ padding-bottom : 2px;
+ margin-left : 0px;
+ margin-right : 0px;
+ margin-top : 2px;
+ margin-bottom : 2px;
+ border: 1px solid #CCCCCC;
+}
+TD.indexvalue {
+ background-color: #e8eef2;
+ font-style: italic;
+ padding-right : 10px;
+ padding-top : 2px;
+ padding-left : 10px;
+ padding-bottom : 2px;
+ margin-left : 0px;
+ margin-right : 0px;
+ margin-top : 2px;
+ margin-bottom : 2px;
+ border: 1px solid #CCCCCC;
+}
+TR.memlist {
+ background-color: #f0f0f0;
+}
+P.formulaDsp { text-align: center; }
+IMG.formulaDsp { }
+IMG.formulaInl { vertical-align: middle; }
+SPAN.keyword { color: #008000 }
+SPAN.keywordtype { color: #604020 }
+SPAN.keywordflow { color: #e08000 }
+SPAN.comment { color: #800000 }
+SPAN.preprocessor { color: #806020 }
+SPAN.stringliteral { color: #002080 }
+SPAN.charliteral { color: #008080 }
+.mdTable {
+ border: 1px solid #868686;
+ background-color: #F4F4FB;
+}
+.mdRow {
+ padding: 8px 10px;
+}
+.mdescLeft {
+ padding: 0px 8px 4px 8px;
+ font-size: 80%;
+ font-style: italic;
+ background-color: #FAFAFA;
+ border-top: 1px none #E0E0E0;
+ border-right: 1px none #E0E0E0;
+ border-bottom: 1px none #E0E0E0;
+ border-left: 1px none #E0E0E0;
+ margin: 0px;
+}
+.mdescRight {
+ padding: 0px 8px 4px 8px;
+ font-size: 80%;
+ font-style: italic;
+ background-color: #FAFAFA;
+ border-top: 1px none #E0E0E0;
+ border-right: 1px none #E0E0E0;
+ border-bottom: 1px none #E0E0E0;
+ border-left: 1px none #E0E0E0;
+ margin: 0px;
+}
+.memItemLeft {
+ padding: 1px 0px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: solid;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memItemRight {
+ padding: 1px 8px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: solid;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memTemplItemLeft {
+ padding: 1px 0px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: none;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memTemplItemRight {
+ padding: 1px 8px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: none;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memTemplParams {
+ padding: 1px 0px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: solid;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ color: #606060;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.search { color: #003399;
+ font-weight: bold;
+}
+FORM.search {
+ margin-bottom: 0px;
+ margin-top: 0px;
+}
+INPUT.search { font-size: 75%;
+ color: #000080;
+ font-weight: normal;
+ background-color: #e8eef2;
+}
+TD.tiny { font-size: 75%;
+}
+a {
+ color: #1A41A8;
+}
+a:visited {
+ color: #2A3798;
+}
+.dirtab { padding: 4px;
+ border-collapse: collapse;
+ border: 1px solid #84b0c7;
+}
+TH.dirtab { background: #e8eef2;
+ font-weight: bold;
+}
+HR { height: 1px;
+ border: none;
+ border-top: 1px solid black;
+}
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/tutorial.dox b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/tutorial.dox
new file mode 100644
index 0000000000..66a39edf23
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/tutorial.dox
@@ -0,0 +1,145 @@
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = "threadpool"
+PROJECT_NUMBER =
+OUTPUT_DIRECTORY = ../../../doc/tutorial
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+USE_WINDOWS_ENCODING = NO
+BRIEF_MEMBER_DESC = NO
+REPEAT_BRIEF = NO
+ALWAYS_DETAILED_SEC = YES
+INLINE_INHERITED_MEMB = YES
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH = /../../include/
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = YES
+JAVADOC_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = YES
+DETAILS_AT_TOP = YES
+INHERIT_DOCS = YES
+DISTRIBUTE_GROUP_DOC = NO
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 2
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = 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 = NO
+INLINE_INFO = NO
+SORT_MEMBER_DOCS = NO
+SORT_BRIEF_DOCS = NO
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = NO
+GENERATE_TESTLIST = NO
+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 = tutorial.txt
+FILE_PATTERNS =
+RECURSIVE = NO
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS =
+EXAMPLE_RECURSIVE = YES
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = NO
+REFERENCES_RELATION = NO
+VERBATIM_HEADERS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = NO
+COLS_IN_ALPHA_INDEX = 1
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = .
+HTML_FILE_EXTENSION = .html
+HTML_HEADER = tutorial_header.htm
+HTML_FOOTER = common_footer.htm
+HTML_STYLESHEET = threadpool.css
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = YES
+ENUM_VALUES_PER_LINE = 1
+GENERATE_TREEVIEW = NO
+TREEVIEW_WIDTH = 250
+
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/tutorial.txt b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/tutorial.txt
new file mode 100644
index 0000000000..e89c96d9af
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/tutorial.txt
@@ -0,0 +1,207 @@
+/*! \page intro Quick Start
+
+This tutorial introduces the threadpool library by discussing an easy to understand source listing:
+
+\code
+01
+02 #include "threadpool.hpp"
+03
+04 using namespace boost::threadpool;
+05
+06 // Some example tasks
+07 void first_task()
+08 {
+09 ...
+10 }
+11
+13 void second_task()
+14 {
+15 ...
+16 }
+17
+19 void third_task()
+20 {
+21 ...
+22 }
+23
+24 void execute_with_threadpool()
+25 {
+26 // Create a thread pool.
+27 pool tp(2);
+28
+29 // Add some tasks to the pool.
+30 tp.schedule(&first_task);
+31 tp.schedule(&second_task);
+32 tp.schedule(&third_task);
+33
+34 // Leave this function and wait until all tasks are finished.
+35 }
+36
+\endcode
+
+We start by including the necessary header files. The complete threadpool functionality can be used by simply including
+the "threadpool.hpp" header file at line 2.
+
+The three functions first_task(), second_task and third_task() are placeholders
+for tasks that should be executed by our pool.
+
+The thread pool is created at line 27. The argument indicates the number of initial threads.
+The new pool contains two threads that is two tasks can be processed in parallel. The pool's threads
+are sleeping until tasks are added.
+By default it uses a Fifo scheduling strategy.
+Fifo is an abbreviation of "first in, first out"
+and means in this case that the first task which is added is the
+first that will be executed. Generally this is the expected default behaviour
+since the tasks are executed in the order they are added to the pool.
+
+In line 30 to 32 the task functions are scheduled asynchronously using the pool's schedule function.
+A task is registered and it will be executed as soon as one of the pool's threads is idle.
+It is very important to understand that the task is only scheduled for execution.
+Schedule returns immediately and there are no guarantees about when the tasks are executed and how long
+the processing will take. As they are added to a fifo pool with two threads the following is true:
+- the execution of first_task begins first
+- second_task is started after first_task
+- third_task is begun at last
+- a maximum of two tasks may are processed in parallel
+- each scheduled task will be executed once only
+
+
+The pool reference tp is created in the scope of the function execute_with_threadpool(). When this
+function returns at line 35 tp goes out of scope and the pool will be destructed. As the default ShutdownPolicy
+is wait_for_all_tasks it is ensured that all tasks are processed before the pool is destroyed.
+
+\code
+101
+102 ...
+103 execute_with_threadpool(); // execute first_task, second_task and third_task
+104 // When this line is reached all tasks are finished and the pool is destructed.
+105
+\endcode
+
+The small code example clarifies the issue. When the function leaves the pool is shut down
+and waits for the tasks. That means the current thread of execution is blocked
+at the end of the execute_with_threadpool as long as
+the processing of tasks is in progress.
+
+<BR>
+*/
+
+
+/*! \page prioritized Prioritized Tasks
+
+TODO This tutorial is out dated.
+
+It's easy to prioritize asynchronous tasks by using the task adaptor prio_task_func.
+The following source listing illustrates how to setup the pool and add the tasks:
+
+\code
+01
+02 #include "threadpool.hpp"
+03
+04 using namespace boost::threadpool;
+05
+06 // Some example tasks
+07 void normal_task()
+08 {
+09 ...
+10 }
+11
+13 void important_task()
+14 {
+15 ...
+16 }
+17
+18 void execute_prioritized()
+19 {
+20 // Create prioritized thread pool container without any threads.
+21 scoped_pool<prio_pool, 0> tp;
+22
+23 // Add some tasks to the pool.
+24 tp += prio_task_func(5, &normal_task);
+25 tp += prio_task_func(100, &important_task);
+26 tp += prio_task_func(7, &normal_task);
+27
+28 // Add the some threads to the pool. This will start the execution of the tasks.
+29 tp->resize(2);
+30
+31 // The tasks are processed according to their priority: important_task(100), nonrelevant_task(7), nonrelevant_task(5).
+32
+33 tp->wait();
+34
+35 // Now all tasks are finished and the pool will be destroyed safely when tp goes out of scope.
+36 }
+37
+\endcode
+
+Like in the first tutorial we start including the main header file and defining some tasks.
+
+At line 21 a prioritized thread pool is created. That means that the pool's tasks are arranged
+according to their priority before they get executed. Therefore the tasks themselves have to realize a partial ordering based
+on operator<.
+
+The adaptor prio_thread_func satisfies our requirements regarding the order and is just a small wrapper object for
+the task functions. In line 24 to 26 some prioritized tasks are scheduled. This time the pool's schedule function is used and like smart pool's += operator
+this function returns immediately.
+
+At line 29 the first thread is added to the pool and the execution of important_task begins. As we have only one thread
+the tasks are processed sequentially.
+
+Finally wait() is called to ensure that all tasks are finished before our example function returns
+and the pool is destroyed. This is very important since the behavior is undefined if pool's lifetime ends while tasks are executed.
+
+*/
+
+
+/*! \page task_adaptor Arbitrary Task Functions
+
+TODO This tutorial is out dated.
+
+
+\section member_task Member Task Functions
+
+using namespace boost::threadpool;
+
+TODO <BR>
+boost::bind(member_function, shared_ptr)
+26 tp->schedule(boost::bind(task_with_parameter, 42));
+12 // Second example task
+13 void task_with_parameter(int value)
+14 {
+15 ...
+16 }
+
+\section member_task Functions With Arguments
+
+*/
+
+
+/*! \page instantiation Advanced Instantiation
+
+TODO This tutorial is out dated.
+
+TODO <BR>
+Pool instantiation
+\code
+
+ boost::shared_ptr<fifo_pool> tp = fifo_pool::create_pool(5);
+
+ print(" Add tasks ...\n");
+ tp->schedule(&task_1);
+ tp->schedule(&task_2);
+ tp->schedule(&task_3);
+
+ tp->schedule(looped_task_func(&looped_task, 1500));
+
+ print(" Wait until all tasks are finished ...\n");
+ tp->wait();
+ print(" Tasks finished!\n");
+
+\endcode
+
+
+\code
+ typedef threadpool::pool<boost::function0<void>, threadpool::fifo_scheduler<boost::function0<void> > > pool_type;
+ boost::shared_ptr< pool_type > tp = pool_type::create_pool(5);
+\endcode
+
+*/ \ No newline at end of file
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/tutorial_header.htm b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/tutorial_header.htm
new file mode 100644
index 0000000000..b087ec0f9f
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/doc/tutorial_header.htm
@@ -0,0 +1,40 @@
+<HTML>
+ <HEAD>
+ <TITLE>threadpool Documentation</TITLE>
+ <LINK HREF="threadpool.css" REL="stylesheet" TYPE="text/css">
+ </HEAD>
+ <BODY BGCOLOR="#FFFFFF">
+
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+
+ <TD ALIGN="LEFT">
+ <B>$projectname</B>
+ </TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="../index.html">Overview</A> |
+ <A CLASS="qindex" HREF="../reference/annotated.html">Reference</A> |
+ <A CLASS="qindex" HREF="../tutorial/intro.html">Tutorial</A> |
+ <A CLASS="qindex" HREF="../examples/intro.html">Examples</A> |
+ <A CLASS="qindex" HREF="../design/intro.html">Design</A>
+ </TD>
+
+ </TR>
+ </TABLE>
+ </DIV>
+ <DIV CLASS="qindex">
+ <TABLE BORDER="0" WIDTH="100%">
+ <TR>
+ <TD ALIGN="LEFT">
+ <B>Tutorial</B>
+ </TD>
+ <TD ALIGN="RIGHT">
+ <A CLASS="qindex" HREF="intro.html">Quick Start</A> |
+ <A CLASS="qindex" HREF="prioritized.html">Prioritized Tasks</A> |
+ <A CLASS="qindex" HREF="task_adaptor.html">Arbitrary Task Functions</A> |
+ <A CLASS="qindex" HREF="instantiation.html">Advanced Pool Instantiation</A>
+ </TD>
+ </TR>
+ </TABLE>
+ </DIV>
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/example/mergesort/Jamfile.v2 b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/example/mergesort/Jamfile.v2
new file mode 100644
index 0000000000..8ff7fe2dbb
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/example/mergesort/Jamfile.v2
@@ -0,0 +1,11 @@
+
+project
+ : requirements
+ <include>../../../..
+ <library>/boost/thread//boost_thread
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <link>static
+ ;
+
+exe mergesort : mergesort.cpp ;
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/example/mergesort/mergesort.cpp b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/example/mergesort/mergesort.cpp
new file mode 100644
index 0000000000..338153453b
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/example/mergesort/mergesort.cpp
@@ -0,0 +1,200 @@
+/*! \file
+ * \brief Mergesort example.
+ *
+ * This example shows how to use the threadpool library.
+ *
+ * Copyright (c) 2005-2006 Philipp Henkel
+ *
+ * Distributed under the 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://threadpool.sourceforge.net
+ *
+ */
+
+
+#include <boost/threadpool.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/smart_ptr.hpp>
+#include <iostream>
+#include <sstream>
+#include <algorithm>
+
+
+
+using namespace std;
+using namespace boost::threadpool;
+
+//
+// Helpers
+boost::mutex m_io_monitor;
+
+void print(string text)
+{
+ boost::mutex::scoped_lock lock(m_io_monitor);
+ cout << text;
+}
+
+template<class T>
+string to_string(const T& value)
+{
+ ostringstream ost;
+ ost << value;
+ ost.flush();
+ return ost.str();
+}
+
+unsigned long get_ms_diff(boost::xtime& start, boost::xtime& end)
+{
+ boost::xtime::xtime_sec_t start_ms = start.sec * 1000 + start.nsec/1000000;
+ boost::xtime::xtime_sec_t end_ms = end.sec * 1000 + end.nsec/1000000;
+ return static_cast<unsigned long>(end_ms - start_ms);
+}
+
+class image
+{
+public:
+ image() : m_content(0) {}
+ image(int content) : m_content(content) {}
+
+ image(const image& src)
+ {
+ m_content = src.m_content;
+ }
+
+ bool operator<(const image& l) const
+ {
+ { // simulate time needed for image comparision
+ boost::xtime xt;
+ boost::xtime_get(&xt, boost::TIME_UTC);
+ int duration = 1+(m_content % 4);
+ xt.nsec += 250 * 1000 * duration;
+ boost::thread::sleep(xt);
+ print(".");
+ }
+ return m_content < l.m_content;
+ }
+
+protected:
+ int m_content; // represents image data in this example
+};
+
+
+template<class T>
+class merge_job
+{
+public:
+ merge_job(boost::shared_array<T> data, unsigned int position, unsigned int length)
+ : m_data(data)
+ , m_position(position)
+ , m_length(length)
+ {
+ print("merge job created : " + to_string(m_position) +", "+ to_string(m_length) +"\n");
+ }
+
+ void run()
+ {
+ print("merge job running : " + to_string(m_position) +", "+ to_string(m_length) +"\n");
+
+ T* begin = m_data.get();
+ std::advance(begin, m_position);
+
+ T* mid = m_data.get();
+ std::advance(mid, m_position + m_length/2);
+
+ T* end = m_data.get();
+ std::advance(end, m_position + m_length);
+
+ std::inplace_merge(begin, mid, end);
+
+ print("\nmerge job finished: " + to_string(m_position) +", "+ to_string(m_length) +"\n");
+ }
+
+protected:
+ boost::shared_array<T> m_data;
+ unsigned int m_position;
+ unsigned int m_length;
+};
+
+
+
+
+//
+// A demonstration of the thread_pool class
+int main (int argc, char * const argv[])
+{
+ print("MAIN: construct thread pool\n");
+
+
+
+ boost::xtime start;
+ boost::xtime_get(&start, boost::TIME_UTC);
+
+ int exponent = 7;
+ int data_len = 1 << exponent; // = pow(2, exponent)
+
+ print("MAIN: sort array with "+ to_string(data_len) + " elements.\n");
+
+ boost::shared_array<image> data(new image[data_len]);
+
+ // fill array with arbitrary values (not sorted ascendingly)
+ for(int i = 0; i < data_len; i++)
+ {
+ data[i] = image((data_len - i - 1) % 23);
+ }
+
+
+ /***************************/
+ /* Standard implementation */
+ /***************************/
+
+ pool tp;
+ tp.size_controller().resize(5);
+
+// merge data array
+ for(int step = 1; step <= exponent; step++)
+ {
+ print("\nMAIN: merge step "+ to_string(step)+"\n");
+
+ // divide array into partitions
+ int partition_size = 1 << step;
+ for(int partition = 0; partition < data_len/partition_size; partition++)
+ {
+ // sort partition
+ boost::shared_ptr<merge_job<image> > job(new merge_job<image>(data, partition*partition_size, partition_size));
+ //tp->schedule(prio_task_func(5, boost::bind(&merge_job<image>::run, job)));
+ schedule(tp, boost::bind(&merge_job<image>::run, job));
+ // schedule(tp, job);
+ }
+ tp.wait(); // wait until all partitions are sorted
+ }
+
+ boost::xtime end;
+ boost::xtime_get(&end, boost::TIME_UTC);
+
+ print("\nMAIN: duration " + to_string(get_ms_diff(start, end)) + " ms \n");
+
+ print("\nMAIN: check if array is sorted... \n");
+
+ // check if array is sorted ascendingly
+ bool ascending = true;
+ for(int i = 0; i < data_len-1; i++)
+ {
+ if(data[i+1] < data[i])
+ {
+ ascending = false;
+ }
+ }
+
+ if(ascending)
+ {
+ print("\nMAIN: array is sorted\n");
+ }
+ else
+ {
+ print("\nMAIN: array is NOT sorted!\n");
+ }
+
+ return 0;
+}
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/quickstart/Jamfile.v2 b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/quickstart/Jamfile.v2
new file mode 100644
index 0000000000..85b2bcb0fd
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/quickstart/Jamfile.v2
@@ -0,0 +1,11 @@
+
+project
+ : requirements
+ <include>../../..
+ <library>/boost/thread//boost_thread
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <link>static
+ ;
+
+exe quickstart : quickstart.cpp ;
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/quickstart/README b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/quickstart/README
new file mode 100644
index 0000000000..4f97ce51d7
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/quickstart/README
@@ -0,0 +1,7 @@
+Supposing the boost directory is in /usr/local/lib, it is also worth to mention that they need to
+set LD_LIBRARY_PATH as follows:
+export LD_LIBRARY_PATH=$(LD_LIBRARY_PATH):/usr/local/lib
+
+Please adapt threadpool.makefile to your system.
+
+Special thanks to Rudy Prabowo who contributed this example to help linux users.
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/quickstart/quickstart.cpp b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/quickstart/quickstart.cpp
new file mode 100644
index 0000000000..858573a0a8
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/quickstart/quickstart.cpp
@@ -0,0 +1,50 @@
+/*! \file
+ * \brief Quick start example.
+ *
+ * This is a very simple example which can be used to configure the threadpool environment on your system.
+ *
+ * Copyright (c) 2005-2006 Philipp Henkel
+ *
+ * Distributed under the 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://threadpool.sourceforge.net
+ *
+ */
+
+#include <iostream>
+
+#include <boost/threadpool.hpp>
+
+using namespace std;
+using namespace boost::threadpool;
+
+// Some example tasks
+void first_task()
+{
+ cout << "first task is running\n" ;
+}
+
+void second_task()
+{
+ cout << "second task is running\n" ;
+}
+
+int main(int argc,char *argv[])
+{
+ // Create fifo thread pool container with two threads.
+ pool tp(2);
+
+ // Add some tasks to the pool.
+ tp.schedule(&first_task);
+ tp.schedule(&second_task);
+
+ // Wait until all tasks are finished.
+ tp.wait();
+
+ // Now all tasks are finished!
+ return(0);
+}
+
+
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/test/compile_all/Jamfile.v2 b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/test/compile_all/Jamfile.v2
new file mode 100644
index 0000000000..e14c124a8d
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/test/compile_all/Jamfile.v2
@@ -0,0 +1,11 @@
+
+project
+ : requirements
+ <include>../../../..
+ <library>/boost/thread//boost_thread
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <link>static
+ ;
+
+exe compile_all : compile_all.cpp ;
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/test/compile_all/compile_all.cpp b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/test/compile_all/compile_all.cpp
new file mode 100644
index 0000000000..1c349d4406
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/test/compile_all/compile_all.cpp
@@ -0,0 +1,149 @@
+/*! \file
+* \brief threadpool tutorial.
+*
+* This file contains a tutorial for the threadpool library.
+*
+* Copyright (c) 2005-2006 Philipp Henkel
+*
+* Distributed under the 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://threadpool.sourceforge.net
+*
+*/
+
+
+
+
+#include <iostream>
+#include <sstream>
+#include <boost/thread/mutex.hpp>
+#include <boost/bind.hpp>
+
+#include <boost/threadpool.hpp>
+
+using namespace std;
+using namespace boost::threadpool;
+
+
+//
+// Helpers
+boost::mutex m_io_monitor;
+
+void print(string text)
+{
+ boost::mutex::scoped_lock lock(m_io_monitor);
+ cout << text;
+}
+
+template<typename T>
+string to_string(T const & value)
+{
+ ostringstream ost;
+ ost << value;
+ ost.flush();
+ return ost.str();
+}
+
+
+
+//
+// An example task functions
+void task_1()
+{
+ print(" task_1()\n");
+}
+
+void task_2()
+{
+ print(" task_2()\n");
+}
+
+void task_3()
+{
+ print(" task_3()\n");
+}
+
+int task_4()
+{
+ print(" task_4()\n");
+ return 4;
+}
+
+void task_with_parameter(int value)
+{
+ print(" task_with_parameter(" + to_string(value) + ")\n");
+}
+
+int loops = 0;
+bool looped_task()
+{
+ print(" looped_task()\n");
+ return ++loops < 5;
+}
+
+
+int task_int()
+{
+ print(" task_int()\n");
+ return 23;
+}
+
+
+void fifo_pool_test()
+{
+ pool tp;
+
+ tp.schedule(&task_1);
+ tp.schedule(boost::bind(task_with_parameter, 4));
+
+ if(!tp.empty())
+ {
+ tp.clear(); // remove all tasks -> no output in this test
+ }
+
+ size_t active_threads = tp.active();
+ size_t pending_threads = tp.pending();
+ size_t total_threads = tp.size();
+
+ size_t dummy = active_threads + pending_threads + total_threads;
+ dummy++;
+
+ tp.size_controller().resize(5);
+ tp.wait();
+}
+
+void lifo_pool_test()
+{
+ lifo_pool tp;
+ tp.size_controller().resize(0);
+ schedule(tp, &task_1);
+ tp.size_controller().resize(10);
+ tp.wait();
+}
+
+void prio_pool_test()
+{
+ prio_pool tp(2);
+ schedule(tp, prio_task_func(1, &task_1));
+ schedule(tp, prio_task_func(10,&task_2));
+}
+
+
+void future_test()
+{
+ fifo_pool tp(5);
+ future<int> fut = schedule(tp, &task_4);
+ int res = fut();
+}
+
+
+int main (int , char * const [])
+{
+ fifo_pool_test();
+ lifo_pool_test();
+ prio_pool_test();
+ future_test();
+ return 0;
+}
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/tutorial/Jamfile.v2 b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/tutorial/Jamfile.v2
new file mode 100644
index 0000000000..5b9d02b459
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/tutorial/Jamfile.v2
@@ -0,0 +1,11 @@
+
+project
+ : requirements
+ <include>../../..
+ <library>/boost/thread//boost_thread
+ <define>BOOST_ALL_NO_LIB=1
+ <threading>multi
+ <link>static
+ ;
+
+exe tutorial : tutorial.cpp ;
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/tutorial/tutorial.cpp b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/tutorial/tutorial.cpp
new file mode 100644
index 0000000000..4cc688509e
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/libs/threadpool/tutorial/tutorial.cpp
@@ -0,0 +1,263 @@
+/*! \file
+* \brief threadpool tutorial.
+*
+* This file contains a tutorial for the threadpool library.
+*
+* Copyright (c) 2005-2007 Philipp Henkel
+*
+* Distributed under the 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://threadpool.sourceforge.net
+*
+*/
+
+//#define _CRTDBG_MAP_ALLOC
+#include <stdlib.h>
+
+#include <iostream>
+#include <sstream>
+#include <boost/thread/mutex.hpp>
+#include <boost/bind.hpp>
+#include <boost/threadpool.hpp>
+
+using namespace std;
+using namespace boost::threadpool;
+
+//
+// Helpers
+boost::mutex m_io_monitor;
+
+void print(string text)
+{
+ boost::mutex::scoped_lock lock(m_io_monitor);
+ cout << text;
+}
+
+template<typename T>
+string to_string(T const & value)
+{
+ ostringstream ost;
+ ost << value;
+ ost.flush();
+ return ost.str();
+}
+
+
+
+//
+// An example task functions
+void task_1()
+{
+ print(" task_1()\n");
+ throw 5;
+}
+
+void task_2()
+{
+ print(" task_2()\n");
+ throw 5;
+}
+
+void task_3()
+{
+ print(" task_3()\n");
+}
+
+void task_with_parameter(int value)
+{
+ print(" task_with_parameter(" + to_string(value) + ")\n");
+}
+
+int loops = 0;
+bool looped_task()
+{
+ print(" looped_task()\n");
+ return ++loops < 5;
+}
+
+
+int task_int_23()
+{
+ print(" task_int_23()\n");
+ return 23;
+}
+
+int task_int_1()
+{
+ print(" task_int_1()\n");
+ return 1;
+}
+
+
+class CTest
+{
+ pool m_pool;
+public:
+ CTest()
+ : m_pool(pool(1000))
+ {
+ }
+};
+
+
+//
+// A demonstration of the thread_pool class
+int main (int , char * const [])
+{
+ print("\nWelcome to the threadpool tutorial!\n");
+
+ print("\n**************************************\n");
+ print("Section 1: Quick Start\n");
+
+ //void func()
+ {
+ print(" Create a new thread pool\n");
+ pool tp(2); // tp is handle to the pool
+
+ // Add tasks
+ tp.schedule(&task_1);
+ tp.schedule(&task_2);
+ tp.schedule(&task_3);
+ tp.schedule(boost::bind(task_with_parameter, 4));
+
+ // The pool handle tp is allocated on stack and will
+ // be destructed if it gets out of scope. Before the
+ // pool is destroyed it waits for its tasks.
+ // That means the current thread of execution is
+ // blocked at the end of the function
+ // (until all tasks are processed).
+ // while (&tp){int i = 3; ++i;}
+ }
+
+ { // Section Futures
+ print("\n**************************************\n");
+ print("Section 1: Futures\n");
+
+ //typedef thread_pool<task_func, fifo_scheduler, static_size, empty_controller, wait_for_all_tasks> test_pool;
+
+ pool tp;
+
+// tp.resize(0);
+ tp.pending();
+// tp.clear();
+ boost::xtime t;
+ tp.wait(t);
+ bool test = tp.empty();
+ if(test)
+ {
+ test = false;
+ }
+
+ tp.size_controller().resize(2);
+
+ //test_pool::size_controller_type controller = tp.size_controller();
+// controller.resize(5);
+
+ schedule(tp, &task_int_1);
+ future<int> res = schedule(tp, &task_int_23);
+ future<int> res2 = schedule(tp, &task_int_1);
+
+ res.wait();
+ int value = res.get() + res2.get();
+
+ res.cancel();
+ res.is_cancelled();
+value ++;
+
+//thread_pool<boost::function0<int>, fifo_scheduler> test2332;
+
+//TODO runnable comile test
+ }
+
+
+
+ { // Section 2
+ print("\n**************************************\n");
+ print("Section 2: Controlling scheduling\n");
+
+ // Create a lifo_pool: last task in, first task out
+ lifo_pool tp(0);
+
+ print(" Add tasks (using the pool's schedule function)\n");
+ schedule(tp, &task_1);
+ schedule(tp, &task_2);
+ schedule(tp, &task_3);
+
+ // tp.wait(); This would be a deadlock as there are no threads which process the tasks.
+
+ print(" Add some threads ...\n");
+ tp.size_controller().resize(5);
+
+ print(" Wait until all tasks are finished ...\n");
+ tp.wait();
+ print(" Tasks finished!\n");
+ }
+
+
+
+ { // Section 3:
+ print("\n**************************************\n");
+ print("Section 3: Prioritized Tasks\n");
+
+ prio_pool tp(0);
+
+
+ print(" Add prioritized tasks ...\n");
+ schedule(tp, prio_task_func(1, &task_1));
+ schedule(tp, prio_task_func(10,&task_2));
+ schedule(tp, prio_task_func(5,&task_3));
+
+ // Tasks are ordered according to their priority: task_2, task_4, task_3, task_1
+
+ print(" Thread added\n");
+ tp.size_controller().resize(10);
+
+ print(" Wait until all tasks are finished ...\n");
+ tp.wait();
+ print(" Tasks finished!\n");
+ }
+
+
+/* */
+ { // Section 5:
+ print("\n**************************************\n");
+ print("Section 5: Advanced thread pool instantiation\n");
+ // Create the pool directly
+/*
+TODO
+boost::shared_ptr<fifo_pool> tp = fifo_pool::create_pool(5);
+
+ print(" Add tasks ...\n");
+ tp->schedule(&task_1);
+ tp->schedule(&task_2);
+ tp->schedule(&task_3);
+ tp->schedule(looped_task_func(&looped_task, 1500));
+
+ print(" Wait until all tasks are finished ...\n");
+ tp->wait();
+*/
+
+ print(" Tasks finished!\n");
+
+ }
+
+
+ print("\n**************************************\n");
+ print("Tutorial finished!\n");
+
+
+
+ { // Section Compile Tests
+ print("\n**************************************\n");
+ print("Section Compile Tests\n");
+
+
+ fifo_pool tp;
+ tp.size_controller().resize(0);
+ tp.empty();
+ }
+
+ return 0;
+}
diff --git a/graphics/asymptote/LspCpp/third_party/threadpool/project-root.jam b/graphics/asymptote/LspCpp/third_party/threadpool/project-root.jam
new file mode 100644
index 0000000000..e94f7232e0
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/threadpool/project-root.jam
@@ -0,0 +1,2 @@
+import os ;
+path-constant BOOST_ROOT : [ os.environ BOOST_ROOT ] ;
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/CMakeLists.txt b/graphics/asymptote/LspCpp/third_party/utfcpp/CMakeLists.txt
new file mode 100644
index 0000000000..f1a2e1f1e9
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/CMakeLists.txt
@@ -0,0 +1,42 @@
+cmake_minimum_required (VERSION 3.0.2)
+project (utf8cpp VERSION 3.2 LANGUAGES CXX)
+
+if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
+ set(IS_ROOT_PROJECT ON)
+else()
+ set(IS_ROOT_PROJECT OFF)
+endif()
+
+option(UTF8_TESTS "Enable tests for UTF8-CPP" ${IS_ROOT_PROJECT})
+option(UTF8_INSTALL "Enable installation for UTF8-CPP" ${IS_ROOT_PROJECT})
+option(UTF8_SAMPLES "Enable building samples for UTF8-CPP" ${IS_ROOT_PROJECT})
+
+add_library(utf8cpp INTERFACE)
+target_include_directories(utf8cpp INTERFACE
+ "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/source>"
+ $<INSTALL_INTERFACE:include/utf8cpp>
+)
+add_library(utf8::cpp ALIAS utf8cpp)
+
+if(UTF8_INSTALL)
+ if(MSVC)
+ set(DEF_INSTALL_CMAKE_DIR CMake)
+ else()
+ include(GNUInstallDirs) # define CMAKE_INSTALL_*
+ set(DEF_INSTALL_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/utf8cpp)
+ endif()
+
+ install(DIRECTORY source/ DESTINATION include/utf8cpp)
+ install(TARGETS utf8cpp EXPORT utf8cppConfig)
+ install(EXPORT utf8cppConfig DESTINATION ${DEF_INSTALL_CMAKE_DIR})
+endif()
+
+if(UTF8_SAMPLES)
+ add_executable(docsample ${PROJECT_SOURCE_DIR}/samples/docsample.cpp)
+ target_link_libraries(docsample PRIVATE utf8::cpp)
+endif()
+
+if(UTF8_TESTS)
+ enable_testing()
+ add_subdirectory(tests)
+endif()
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/LICENSE b/graphics/asymptote/LspCpp/third_party/utfcpp/LICENSE
new file mode 100644
index 0000000000..36b7cd93cd
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/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/graphics/asymptote/LspCpp/third_party/utfcpp/README.md b/graphics/asymptote/LspCpp/third_party/utfcpp/README.md
new file mode 100644
index 0000000000..a519cdb963
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/README.md
@@ -0,0 +1,1503 @@
+# UTF8-CPP: UTF-8 with C++ in a Portable Way
+
+
+## Introduction
+
+C++ developers miss an easy and portable way of handling Unicode encoded strings. The original C++ Standard (known as C++98 or C++03) is Unicode agnostic. C++11 provides some support for Unicode on core language and library level: u8, u, and U character and string literals, char16_t and char32_t character types, u16string and u32string library classes, and codecvt support for conversions between Unicode encoding forms. In the meantime, developers use third party libraries like ICU, OS specific capabilities, or simply roll out their own solutions.
+
+In order to easily handle UTF-8 encoded Unicode strings, I came up with a small, C++98 compatible generic library. For anybody used to work with STL algorithms and iterators, it should be easy and natural to use. The code is freely available for any purpose - check out the [license](./LICENSE). The library has been used a lot in the past ten years both in commercial and open-source projects and is considered feature-complete now. If you run into bugs or performance issues, please let me know and I'll do my best to address them.
+
+The purpose of this article is not to offer an introduction to Unicode in general, and UTF-8 in particular. If you are not familiar with Unicode, be sure to check out [Unicode Home Page](http://www.unicode.org/) or some other source of information for Unicode. Also, it is not my aim to advocate the use of UTF-8 encoded strings in C++ programs; if you want to handle UTF-8 encoded strings from C++, I am sure you have good reasons for it.
+
+## Examples of use
+
+### Introductionary Sample
+
+To illustrate the use of the library, let's start with a small but complete program that opens a file containing UTF-8 encoded text, reads it line by line, checks each line for invalid UTF-8 byte sequences, and converts it to UTF-16 encoding and back to UTF-8:
+
+```cpp
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+#include "utf8.h"
+using namespace std;
+int main(int argc, char** argv)
+{
+ if (argc != 2) {
+ cout << "\nUsage: docsample filename\n";
+ return 0;
+ }
+ const char* test_file_path = argv[1];
+ // Open the test file (must be UTF-8 encoded)
+ ifstream fs8(test_file_path);
+ if (!fs8.is_open()) {
+ cout << "Could not open " << test_file_path << endl;
+ return 0;
+ }
+
+ unsigned line_count = 1;
+ string line;
+ // Play with all the lines in the file
+ while (getline(fs8, line)) {
+ // check for invalid utf-8 (for a simple yes/no check, there is also utf8::is_valid function)
+#if __cplusplus >= 201103L // C++ 11 or later
+ auto end_it = utf8::find_invalid(line.begin(), line.end());
+#else
+ string::iterator end_it = utf8::find_invalid(line.begin(), line.end());
+#endif // C++ 11
+ if (end_it != line.end()) {
+ cout << "Invalid UTF-8 encoding detected at line " << line_count << "\n";
+ cout << "This part is fine: " << string(line.begin(), end_it) << "\n";
+ }
+ // Get the line length (at least for the valid part)
+ int length = utf8::distance(line.begin(), end_it);
+ cout << "Length of line " << line_count << " is " << length << "\n";
+
+ // Convert it to utf-16
+#if __cplusplus >= 201103L // C++ 11 or later
+ u16string utf16line = utf8::utf8to16(line);
+#else
+ vector<unsigned short> utf16line;
+ utf8::utf8to16(line.begin(), end_it, back_inserter(utf16line));
+#endif // C++ 11
+ // And back to utf-8;
+#if __cplusplus >= 201103L // C++ 11 or later
+ string utf8line = utf8::utf16to8(utf16line);
+#else
+ string utf8line;
+ utf8::utf16to8(utf16line.begin(), utf16line.end(), back_inserter(utf8line));
+#endif // C++ 11
+ // Confirm that the conversion went OK:
+ if (utf8line != string(line.begin(), end_it))
+ cout << "Error in UTF-16 conversion at line: " << line_count << "\n";
+
+ line_count++;
+ }
+
+ return 0;
+}
+```
+
+In the previous code sample, for each line we performed a detection of invalid UTF-8 sequences with `find_invalid`; the number of characters (more precisely - the number of Unicode code points, including the end of line and even BOM if there is one) in each line was determined with a use of `utf8::distance`; finally, we have converted each line to UTF-16 encoding with `utf8to16` and back to UTF-8 with `utf16to8`.
+
+Note a different pattern of usage for old compilers. For instance, this is how we convert
+a UTF-8 encoded string to a UTF-16 encoded one with a pre - C++11 compiler:
+```cpp
+ vector<unsigned short> utf16line;
+ utf8::utf8to16(line.begin(), end_it, back_inserter(utf16line));
+```
+
+With a more modern compiler, the same operation would look like:
+```cpp
+ u16string utf16line = utf8::utf8to16(line);
+```
+If `__cplusplus` macro points to a C++ 11 or later, the library exposes API that takes into
+account C++ standard Unicode strings and move semantics. With an older compiler, it is still
+possible to use the same functionality, just in a little less convenient way
+
+In case you do not trust the `__cplusplus` macro or, for instance, do not want to include
+the C++ 11 helper functions even with a modern compiler, define `UTF_CPP_CPLUSPLUS` macro
+before including `utf8.h` and assign it a value for the standard you want to use - the values are the same as for the `__cplusplus` macro. This can be also useful with compilers that are conservative in setting the `__cplusplus` macro even if they have a good support for a recent standard edition - Microsoft's Visual C++ is one example.
+
+### Checking if a file contains valid UTF-8 text
+
+Here is a function that checks whether the content of a file is valid UTF-8 encoded text without reading the content into the memory:
+
+```cpp
+bool valid_utf8_file(const char* file_name)
+{
+ ifstream ifs(file_name);
+ if (!ifs)
+ return false; // even better, throw here
+
+ istreambuf_iterator<char> it(ifs.rdbuf());
+ istreambuf_iterator<char> eos;
+
+ return utf8::is_valid(it, eos);
+}
+```
+
+Because the function `utf8::is_valid()` works with input iterators, we were able to pass an `istreambuf_iterator` to `it` and read the content of the file directly without loading it to the memory first.
+
+Note that other functions that take input iterator arguments can be used in a similar way. For instance, to read the content of a UTF-8 encoded text file and convert the text to UTF-16, just do something like:
+
+```cpp
+ utf8::utf8to16(it, eos, back_inserter(u16string));
+```
+
+### Ensure that a string contains valid UTF-8 text
+
+If we have some text that "probably" contains UTF-8 encoded text and we want to replace any invalid UTF-8 sequence with a replacement character, something like the following function may be used:
+
+```cpp
+void fix_utf8_string(std::string& str)
+{
+ std::string temp;
+ utf8::replace_invalid(str.begin(), str.end(), back_inserter(temp));
+ str = temp;
+}
+```
+
+The function will replace any invalid UTF-8 sequence with a Unicode replacement character. There is an overloaded function that enables the caller to supply their own replacement character.
+
+
+## Points of interest
+
+#### Design goals and decisions
+
+The library was designed to be:
+
+1. Generic: for better or worse, there are many C++ string classes out there, and the library should work with as many of them as possible.
+2. Portable: the library should be portable both accross different platforms and compilers. The only non-portable code is a small section that declares unsigned integers of different sizes: three typedefs. They can be changed by the users of the library if they don't match their platform. The default setting should work for Windows (both 32 and 64 bit), and most 32 bit and 64 bit Unix derivatives. Support for post C++03 language features is included for modern compilers at API level only, so the library should work even with pretty old compilers.
+3. Lightweight: follow the "pay only for what you use" guideline.
+4. Unintrusive: avoid forcing any particular design or even programming style on the user. This is a library, not a framework.
+
+#### Alternatives
+
+In case you want to look into other means of working with UTF-8 strings from C++, here is the list of solutions I am aware of:
+
+1. [ICU Library](http://icu.sourceforge.net/). It is very powerful, complete, feature-rich, mature, and widely used. Also big, intrusive, non-generic, and doesn't play well with the Standard Library. I definitelly recommend looking at ICU even if you don't plan to use it.
+2. C++11 language and library features. Still far from complete, and not easy to use.
+3. [Glib::ustring](http://www.gtkmm.org/gtkmm2/docs/tutorial/html/ch03s04.html). A class specifically made to work with UTF-8 strings, and also feel like `std::string`. If you prefer to have yet another string class in your code, it may be worth a look. Be aware of the licensing issues, though.
+4. Platform dependent solutions: Windows and POSIX have functions to convert strings from one encoding to another. That is only a subset of what my library offers, but if that is all you need it may be good enough.
+
+
+## Reference
+
+### Functions From utf8 Namespace
+
+#### utf8::append
+
+Available in version 3.0 and later. Requires a C++ 11 compliant compiler.
+
+Encodes a 32 bit code point as a UTF-8 sequence of octets and appends the sequence to a UTF-8 string.
+
+```cpp
+void append(char32_t cp, std::string& s);
+```
+
+`cp`: a code point to append to the string.
+`s`: a utf-8 encoded string to append the code point to.
+
+Example of use:
+
+```cpp
+std::string u;
+append(0x0448, u);
+assert (u[0] == char(0xd1) && u[1] == char(0x88) && u.length() == 2);
+```
+
+In case of an invalid code point, a `utf8::invalid_code_point` exception is thrown.
+
+
+#### utf8::append
+
+Available in version 1.0 and later.
+
+Encodes a 32 bit code point as a UTF-8 sequence of octets and appends the sequence to a UTF-8 string.
+
+```cpp
+template <typename octet_iterator>
+octet_iterator append(uint32_t cp, octet_iterator result);
+```
+
+`octet_iterator`: an output iterator.
+`cp`: a 32 bit integer representing a code point to append to the sequence.
+`result`: an output iterator to the place in the sequence where to append the code point.
+Return value: an iterator pointing to the place after the newly appended sequence.
+
+Example of use:
+
+```cpp
+unsigned char u[5] = {0,0,0,0,0};
+unsigned char* end = append(0x0448, u);
+assert (u[0] == 0xd1 && u[1] == 0x88 && u[2] == 0 && u[3] == 0 && u[4] == 0);
+```
+
+Note that `append` does not allocate any memory - it is the burden of the caller to make sure there is enough memory allocated for the operation. To make things more interesting, `append` can add anywhere between 1 and 4 octets to the sequence. In practice, you would most often want to use `std::back_inserter` to ensure that the necessary memory is allocated.
+
+In case of an invalid code point, a `utf8::invalid_code_point` exception is thrown.
+
+#### utf8::next
+
+Available in version 1.0 and later.
+
+Given the iterator to the beginning of the UTF-8 sequence, it returns the code point and moves the iterator to the next position.
+
+```cpp
+template <typename octet_iterator>
+uint32_t next(octet_iterator& it, octet_iterator end);
+```
+
+`octet_iterator`: an input iterator.
+`it`: a reference to an iterator pointing to the beginning of an UTF-8 encoded code point. After the function returns, it is incremented to point to the beginning of the next code point.
+`end`: end of the UTF-8 sequence to be processed. If `it` gets equal to `end` during the extraction of a code point, an `utf8::not_enough_room` exception is thrown.
+Return value: the 32 bit representation of the processed UTF-8 code point.
+
+Example of use:
+
+```cpp
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars;
+int cp = next(w, twochars + 6);
+assert (cp == 0x65e5);
+assert (w == twochars + 3);
+```
+
+This function is typically used to iterate through a UTF-8 encoded string.
+
+In case of an invalid UTF-8 seqence, a `utf8::invalid_utf8` exception is thrown.
+
+#### utf8::peek_next
+
+Available in version 2.1 and later.
+
+Given the iterator to the beginning of the UTF-8 sequence, it returns the code point for the following sequence without changing the value of the iterator.
+
+```cpp
+template <typename octet_iterator>
+uint32_t peek_next(octet_iterator it, octet_iterator end);
+```
+
+
+`octet_iterator`: an input iterator.
+`it`: an iterator pointing to the beginning of an UTF-8 encoded code point.
+`end`: end of the UTF-8 sequence to be processed. If `it` gets equal to `end` during the extraction of a code point, an `utf8::not_enough_room` exception is thrown.
+Return value: the 32 bit representation of the processed UTF-8 code point.
+
+Example of use:
+
+```cpp
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars;
+int cp = peek_next(w, twochars + 6);
+assert (cp == 0x65e5);
+assert (w == twochars);
+```
+
+In case of an invalid UTF-8 seqence, a `utf8::invalid_utf8` exception is thrown.
+
+#### utf8::prior
+
+Available in version 1.02 and later.
+
+Given a reference to an iterator pointing to an octet in a UTF-8 sequence, it decreases the iterator until it hits the beginning of the previous UTF-8 encoded code point and returns the 32 bits representation of the code point.
+
+```cpp
+template <typename octet_iterator>
+uint32_t prior(octet_iterator& it, octet_iterator start);
+```
+
+`octet_iterator`: a bidirectional iterator.
+`it`: a reference pointing to an octet within a UTF-8 encoded string. After the function returns, it is decremented to point to the beginning of the previous code point.
+`start`: an iterator to the beginning of the sequence where the search for the beginning of a code point is performed. It is a safety measure to prevent passing the beginning of the string in the search for a UTF-8 lead octet.
+ Return value: the 32 bit representation of the previous code point.
+
+Example of use:
+
+```cpp
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+unsigned char* w = twochars + 3;
+int cp = prior (w, twochars);
+assert (cp == 0x65e5);
+assert (w == twochars);
+```
+
+This function has two purposes: one is two iterate backwards through a UTF-8 encoded string. Note that it is usually a better idea to iterate forward instead, since `utf8::next` is faster. The second purpose is to find a beginning of a UTF-8 sequence if we have a random position within a string. Note that in that case `utf8::prior` may not detect an invalid UTF-8 sequence in some scenarios: for instance if there are superfluous trail octets, it will just skip them.
+
+`it` will typically point to the beginning of a code point, and `start` will point to the beginning of the string to ensure we don't go backwards too far. `it` is decreased until it points to a lead UTF-8 octet, and then the UTF-8 sequence beginning with that octet is decoded to a 32 bit representation and returned.
+
+In case `start` is reached before a UTF-8 lead octet is hit, or if an invalid UTF-8 sequence is started by the lead octet, an `invalid_utf8` exception is thrown.
+
+In case `start` equals `it`, a `not_enough_room` exception is thrown.
+
+#### utf8::advance
+Available in version 1.0 and later.
+
+Advances an iterator by the specified number of code points within an UTF-8 sequence.
+
+```cpp
+template <typename octet_iterator, typename distance_type>
+void advance (octet_iterator& it, distance_type n, octet_iterator end);
+```
+
+`octet_iterator`: an input iterator.
+`distance_type`: an integral type convertible to `octet_iterator`'s difference type.
+`it`: a reference to an iterator pointing to the beginning of an UTF-8 encoded code point. After the function returns, it is incremented to point to the nth following code point.
+`n`: number of code points `it` should be advanced. A negative value means decrement.
+`end`: limit of the UTF-8 sequence to be processed. If `n` is positive and `it` gets equal to `end` during the extraction of a code point, an `utf8::not_enough_room` exception is thrown. If `n` is negative and `it` reaches `end` while `it` points t a trail byte of a UTF-8 sequence, a `utf8::invalid_code_point` exception is thrown.
+
+Example of use:
+
+```cpp
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+unsigned char* w = twochars;
+advance (w, 2, twochars + 6);
+assert (w == twochars + 5);
+advance (w, -2, twochars);
+assert (w == twochars);
+```
+
+In case of an invalid code point, a `utf8::invalid_code_point` exception is thrown.
+
+#### utf8::distance
+
+Available in version 1.0 and later.
+
+Given the iterators to two UTF-8 encoded code points in a seqence, returns the number of code points between them.
+
+```cpp
+template <typename octet_iterator>
+typename std::iterator_traits<octet_iterator>::difference_type distance (octet_iterator first, octet_iterator last);
+```
+
+`octet_iterator`: an input iterator.
+`first`: an iterator to a beginning of a UTF-8 encoded code point.
+`last`: an iterator to a "post-end" of the last UTF-8 encoded code point in the sequence we are trying to determine the length. It can be the beginning of a new code point, or not.
+ Return value the distance between the iterators, in code points.
+
+Example of use:
+
+```cpp
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+size_t dist = utf8::distance(twochars, twochars + 5);
+assert (dist == 2);
+```
+
+This function is used to find the length (in code points) of a UTF-8 encoded string. The reason it is called _distance_, rather than, say, _length_ is mainly because developers are used that _length_ is an O(1) function. Computing the length of an UTF-8 string is a linear operation, and it looked better to model it after `std::distance` algorithm.
+
+In case of an invalid UTF-8 seqence, a `utf8::invalid_utf8` exception is thrown. If `last` does not point to the past-of-end of a UTF-8 seqence, a `utf8::not_enough_room` exception is thrown.
+
+#### utf8::utf16to8
+
+Available in version 3.0 and later. Requires a C++ 11 compliant compiler.
+
+Converts a UTF-16 encoded string to UTF-8.
+
+```cpp
+std::string utf16to8(const std::u16string& s);
+```
+
+`s`: a UTF-16 encoded string.
+Return value: A UTF-8 encoded string.
+
+Example of use:
+
+```cpp
+ u16string utf16string = {0x41, 0x0448, 0x65e5, 0xd834, 0xdd1e};
+ string u = utf16to8(utf16string);
+ assert (u.size() == 10);
+```
+
+In case of invalid UTF-16 sequence, a `utf8::invalid_utf16` exception is thrown.
+
+#### utf8::utf16to8
+
+Available in version 3.2 and later. Requires a C++ 17 compliant compiler.
+
+Converts a UTF-16 encoded string to UTF-8.
+
+```cpp
+std::string utf16to8(std::u16string_view s);
+```
+
+`s`: a UTF-16 encoded string.
+Return value: A UTF-8 encoded string.
+
+Example of use:
+
+```cpp
+ u16string utf16string = {0x41, 0x0448, 0x65e5, 0xd834, 0xdd1e};
+ u16string_view utf16stringview(u16string);
+ string u = utf16to8(utf16string);
+ assert (u.size() == 10);
+```
+
+In case of invalid UTF-16 sequence, a `utf8::invalid_utf16` exception is thrown.
+
+
+#### utf8::utf16to8
+
+Available in version 1.0 and later.
+
+Converts a UTF-16 encoded string to UTF-8.
+
+```cpp
+template <typename u16bit_iterator, typename octet_iterator>
+octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result);
+```
+
+`u16bit_iterator`: an input iterator.
+`octet_iterator`: an output iterator.
+`start`: an iterator pointing to the beginning of the UTF-16 encoded string to convert.
+`end`: an iterator pointing to pass-the-end of the UTF-16 encoded string to convert.
+`result`: an output iterator to the place in the UTF-8 string where to append the result of conversion.
+Return value: An iterator pointing to the place after the appended UTF-8 string.
+
+Example of use:
+
+```cpp
+unsigned short utf16string[] = {0x41, 0x0448, 0x65e5, 0xd834, 0xdd1e};
+vector<unsigned char> utf8result;
+utf16to8(utf16string, utf16string + 5, back_inserter(utf8result));
+assert (utf8result.size() == 10);
+```
+
+In case of invalid UTF-16 sequence, a `utf8::invalid_utf16` exception is thrown.
+
+#### utf8::utf8to16
+
+Available in version 3.0 and later. Requires a C++ 11 compliant compiler.
+
+Converts an UTF-8 encoded string to UTF-16.
+
+```cpp
+std::u16string utf8to16(const std::string& s);
+```
+
+`s`: an UTF-8 encoded string to convert.
+Return value: A UTF-16 encoded string
+
+Example of use:
+
+```cpp
+string utf8_with_surrogates = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+u16string utf16result = utf8to16(utf8_with_surrogates);
+assert (utf16result.length() == 4);
+assert (utf16result[2] == 0xd834);
+assert (utf16result[3] == 0xdd1e);
+```
+
+In case of an invalid UTF-8 seqence, a `utf8::invalid_utf8` exception is thrown.
+
+#### utf8::utf8to16
+
+Available in version 3.2 and later. Requires a C++ 17 compliant compiler.
+
+Converts an UTF-8 encoded string to UTF-16.
+
+```cpp
+std::u16string utf8to16(std::string_view s);
+```
+
+`s`: an UTF-8 encoded string to convert.
+Return value: A UTF-16 encoded string
+
+Example of use:
+
+```cpp
+string_view utf8_with_surrogates = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+u16string utf16result = utf8to16(utf8_with_surrogates);
+assert (utf16result.length() == 4);
+assert (utf16result[2] == 0xd834);
+assert (utf16result[3] == 0xdd1e);
+```
+
+In case of an invalid UTF-8 seqence, a `utf8::invalid_utf8` exception is thrown.
+
+
+#### utf8::utf8to16
+
+Available in version 1.0 and later.
+
+Converts an UTF-8 encoded string to UTF-16
+
+```cpp
+template <typename u16bit_iterator, typename octet_iterator>
+u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result);
+```
+
+`octet_iterator`: an input iterator.
+`u16bit_iterator`: an output iterator.
+`start`: an iterator pointing to the beginning of the UTF-8 encoded string to convert. < br /> `end`: an iterator pointing to pass-the-end of the UTF-8 encoded string to convert.
+`result`: an output iterator to the place in the UTF-16 string where to append the result of conversion.
+Return value: An iterator pointing to the place after the appended UTF-16 string.
+
+Example of use:
+
+```cpp
+char utf8_with_surrogates[] = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+vector <unsigned short> utf16result;
+utf8to16(utf8_with_surrogates, utf8_with_surrogates + 9, back_inserter(utf16result));
+assert (utf16result.size() == 4);
+assert (utf16result[2] == 0xd834);
+assert (utf16result[3] == 0xdd1e);
+```
+
+In case of an invalid UTF-8 seqence, a `utf8::invalid_utf8` exception is thrown. If `end` does not point to the past-of-end of a UTF-8 seqence, a `utf8::not_enough_room` exception is thrown.
+
+#### utf8::utf32to8
+
+Available in version 3.0 and later. Requires a C++ 11 compliant compiler.
+
+Converts a UTF-32 encoded string to UTF-8.
+
+```cpp
+std::string utf32to8(const std::u32string& s);
+```
+
+`s`: a UTF-32 encoded string.
+Return value: a UTF-8 encoded string.
+
+Example of use:
+
+```cpp
+u32string utf32string = {0x448, 0x65E5, 0x10346};
+string utf8result = utf32to8(utf32string);
+assert (utf8result.size() == 9);
+```
+
+In case of invalid UTF-32 string, a `utf8::invalid_code_point` exception is thrown.
+
+#### utf8::utf32to8
+
+Available in version 3.2 and later. Requires a C++ 17 compliant compiler.
+
+Converts a UTF-32 encoded string to UTF-8.
+
+```cpp
+std::string utf32to8(std::u32string_view s);
+```
+
+`s`: a UTF-32 encoded string.
+Return value: a UTF-8 encoded string.
+
+Example of use:
+
+```cpp
+u32string utf32string = {0x448, 0x65E5, 0x10346};
+u32string_view utf32stringview(utf32string);
+string utf8result = utf32to8(utf32stringview);
+assert (utf8result.size() == 9);
+```
+
+In case of invalid UTF-32 string, a `utf8::invalid_code_point` exception is thrown.
+
+
+#### utf8::utf32to8
+
+Available in version 1.0 and later.
+
+Converts a UTF-32 encoded string to UTF-8.
+
+```cpp
+template <typename octet_iterator, typename u32bit_iterator>
+octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result);
+```
+
+`octet_iterator`: an output iterator.
+`u32bit_iterator`: an input iterator.
+`start`: an iterator pointing to the beginning of the UTF-32 encoded string to convert.
+`end`: an iterator pointing to pass-the-end of the UTF-32 encoded string to convert.
+`result`: an output iterator to the place in the UTF-8 string where to append the result of conversion.
+Return value: An iterator pointing to the place after the appended UTF-8 string.
+
+Example of use:
+
+```cpp
+int utf32string[] = {0x448, 0x65E5, 0x10346, 0};
+vector<unsigned char> utf8result;
+utf32to8(utf32string, utf32string + 3, back_inserter(utf8result));
+assert (utf8result.size() == 9);
+```
+
+In case of invalid UTF-32 string, a `utf8::invalid_code_point` exception is thrown.
+
+#### utf8::utf8to32
+
+Available in version 3.0 and later. Requires a C++ 11 compliant compiler.
+
+Converts a UTF-8 encoded string to UTF-32.
+
+```cpp
+std::u32string utf8to32(const std::string& s);
+```
+
+`s`: a UTF-8 encoded string.
+Return value: a UTF-32 encoded string.
+
+Example of use:
+
+```cpp
+const char* twochars = "\xe6\x97\xa5\xd1\x88";
+u32string utf32result = utf8to32(twochars);
+assert (utf32result.size() == 2);
+```
+
+In case of an invalid UTF-8 seqence, a `utf8::invalid_utf8` exception is thrown.
+
+#### utf8::utf8to32
+
+Available in version 3.2 and later. Requires a C++ 17 compliant compiler.
+
+Converts a UTF-8 encoded string to UTF-32.
+
+```cpp
+std::u32string utf8to32(std::string_view s);
+```
+
+`s`: a UTF-8 encoded string.
+Return value: a UTF-32 encoded string.
+
+Example of use:
+
+```cpp
+string_view twochars = "\xe6\x97\xa5\xd1\x88";
+u32string utf32result = utf8to32(twochars);
+assert (utf32result.size() == 2);
+```
+
+In case of an invalid UTF-8 seqence, a `utf8::invalid_utf8` exception is thrown.
+
+
+#### utf8::utf8to32
+
+Available in version 1.0 and later.
+
+Converts a UTF-8 encoded string to UTF-32.
+
+```cpp
+template <typename octet_iterator, typename u32bit_iterator>
+u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result);
+```
+
+`octet_iterator`: an input iterator.
+`u32bit_iterator`: an output iterator.
+`start`: an iterator pointing to the beginning of the UTF-8 encoded string to convert.
+`end`: an iterator pointing to pass-the-end of the UTF-8 encoded string to convert.
+`result`: an output iterator to the place in the UTF-32 string where to append the result of conversion.
+Return value: An iterator pointing to the place after the appended UTF-32 string.
+
+Example of use:
+
+```cpp
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+vector<int> utf32result;
+utf8to32(twochars, twochars + 5, back_inserter(utf32result));
+assert (utf32result.size() == 2);
+```
+
+In case of an invalid UTF-8 seqence, a `utf8::invalid_utf8` exception is thrown. If `end` does not point to the past-of-end of a UTF-8 seqence, a `utf8::not_enough_room` exception is thrown.
+
+#### utf8::find_invalid
+
+Available in version 3.0 and later. Requires a C++ 11 compliant compiler.
+
+Detects an invalid sequence within a UTF-8 string.
+
+```cpp
+std::size_t find_invalid(const std::string& s);
+```
+
+`s`: a UTF-8 encoded string.
+Return value: the index of the first invalid octet in the UTF-8 string. In case none were found, equals `std::string::npos`.
+
+Example of use:
+
+```cpp
+string utf_invalid = "\xe6\x97\xa5\xd1\x88\xfa";
+auto invalid = find_invalid(utf_invalid);
+assert (invalid == 5);
+```
+
+This function is typically used to make sure a UTF-8 string is valid before processing it with other functions. It is especially important to call it if before doing any of the _unchecked_ operations on it.
+
+#### utf8::find_invalid
+
+Available in version 3.2 and later. Requires a C++ 17 compliant compiler.
+
+Detects an invalid sequence within a UTF-8 string.
+
+```cpp
+std::size_t find_invalid(std::string_view s);
+```
+
+`s`: a UTF-8 encoded string.
+Return value: the index of the first invalid octet in the UTF-8 string. In case none were found, equals `std::string_view::npos`.
+
+Example of use:
+
+```cpp
+string_view utf_invalid = "\xe6\x97\xa5\xd1\x88\xfa";
+auto invalid = find_invalid(utf_invalid);
+assert (invalid == 5);
+```
+
+This function is typically used to make sure a UTF-8 string is valid before processing it with other functions. It is especially important to call it if before doing any of the _unchecked_ operations on it.
+
+
+#### utf8::find_invalid
+
+Available in version 1.0 and later.
+
+Detects an invalid sequence within a UTF-8 string.
+
+```cpp
+template <typename octet_iterator>
+octet_iterator find_invalid(octet_iterator start, octet_iterator end);
+```
+
+`octet_iterator`: an input iterator.
+`start`: an iterator pointing to the beginning of the UTF-8 string to test for validity.
+`end`: an iterator pointing to pass-the-end of the UTF-8 string to test for validity.
+Return value: an iterator pointing to the first invalid octet in the UTF-8 string. In case none were found, equals `end`.
+
+Example of use:
+
+```cpp
+char utf_invalid[] = "\xe6\x97\xa5\xd1\x88\xfa";
+char* invalid = find_invalid(utf_invalid, utf_invalid + 6);
+assert (invalid == utf_invalid + 5);
+```
+
+This function is typically used to make sure a UTF-8 string is valid before processing it with other functions. It is especially important to call it if before doing any of the _unchecked_ operations on it.
+
+#### utf8::is_valid
+
+Available in version 3.0 and later. Requires a C++ 11 compliant compiler.
+
+Checks whether a string object contains valid UTF-8 encoded text.
+
+```cpp
+bool is_valid(const std::string& s);
+```
+
+`s`: a UTF-8 encoded string.
+Return value: `true` if the string contains valid UTF-8 encoded text; `false` if not.
+
+Example of use:
+
+```cpp
+char utf_invalid[] = "\xe6\x97\xa5\xd1\x88\xfa";
+bool bvalid = is_valid(utf_invalid);
+assert (bvalid == false);
+```
+
+You may want to use `is_valid` to make sure that a string contains valid UTF-8 text without the need to know where it fails if it is not valid.
+
+#### utf8::is_valid
+
+Available in version 3.2 and later. Requires a C++ 17 compliant compiler.
+
+Checks whether a string object contains valid UTF-8 encoded text.
+
+```cpp
+bool is_valid(std::string_view s);
+```
+
+`s`: a UTF-8 encoded string.
+Return value: `true` if the string contains valid UTF-8 encoded text; `false` if not.
+
+Example of use:
+
+```cpp
+string_view utf_invalid = "\xe6\x97\xa5\xd1\x88\xfa";
+bool bvalid = is_valid(utf_invalid);
+assert (bvalid == false);
+```
+
+You may want to use `is_valid` to make sure that a string contains valid UTF-8 text without the need to know where it fails if it is not valid.
+
+
+#### utf8::is_valid
+
+Available in version 1.0 and later.
+
+Checks whether a sequence of octets is a valid UTF-8 string.
+
+```cpp
+template <typename octet_iterator>
+bool is_valid(octet_iterator start, octet_iterator end);
+```
+
+`octet_iterator`: an input iterator.
+`start`: an iterator pointing to the beginning of the UTF-8 string to test for validity.
+`end`: an iterator pointing to pass-the-end of the UTF-8 string to test for validity.
+Return value: `true` if the sequence is a valid UTF-8 string; `false` if not.
+
+Example of use:
+
+```cpp
+char utf_invalid[] = "\xe6\x97\xa5\xd1\x88\xfa";
+bool bvalid = is_valid(utf_invalid, utf_invalid + 6);
+assert (bvalid == false);
+```
+
+`is_valid` is a shorthand for `find_invalid(start, end) == end;`. You may want to use it to make sure that a byte seqence is a valid UTF-8 string without the need to know where it fails if it is not valid.
+
+#### utf8::replace_invalid
+
+Available in version 3.0 and later. Requires a C++ 11 compliant compiler.
+
+Replaces all invalid UTF-8 sequences within a string with a replacement marker.
+
+```cpp
+std::string replace_invalid(const std::string& s, char32_t replacement);
+std::string replace_invalid(const std::string& s);
+```
+
+`s`: a UTF-8 encoded string.
+`replacement`: A Unicode code point for the replacement marker. The version without this parameter assumes the value `0xfffd`
+Return value: A UTF-8 encoded string with replaced invalid sequences.
+
+Example of use:
+
+```cpp
+string invalid_sequence = "a\x80\xe0\xa0\xc0\xaf\xed\xa0\x80z";
+string replace_invalid_result = replace_invalid(invalid_sequence, '?');
+bvalid = is_valid(replace_invalid_result);
+assert (bvalid);
+const string fixed_invalid_sequence = "a????z";
+assert (fixed_invalid_sequence == replace_invalid_result);
+```
+
+#### utf8::replace_invalid
+
+Available in version 3.2 and later. Requires a C++ 17 compliant compiler.
+
+Replaces all invalid UTF-8 sequences within a string with a replacement marker.
+
+```cpp
+std::string replace_invalid(std::string_view s, char32_t replacement);
+std::string replace_invalid(std::string_view s);
+```
+
+`s`: a UTF-8 encoded string.
+`replacement`: A Unicode code point for the replacement marker. The version without this parameter assumes the value `0xfffd`
+Return value: A UTF-8 encoded string with replaced invalid sequences.
+
+Example of use:
+
+```cpp
+string_view invalid_sequence = "a\x80\xe0\xa0\xc0\xaf\xed\xa0\x80z";
+string replace_invalid_result = replace_invalid(invalid_sequence, '?');
+bool bvalid = is_valid(replace_invalid_result);
+assert (bvalid);
+const string fixed_invalid_sequence = "a????z";
+assert(fixed_invalid_sequence, replace_invalid_result);
+```
+
+
+#### utf8::replace_invalid
+
+Available in version 2.0 and later.
+
+Replaces all invalid UTF-8 sequences within a string with a replacement marker.
+
+```cpp
+template <typename octet_iterator, typename output_iterator>
+output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement);
+template <typename octet_iterator, typename output_iterator>
+output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out);
+```
+
+`octet_iterator`: an input iterator.
+`output_iterator`: an output iterator.
+`start`: an iterator pointing to the beginning of the UTF-8 string to look for invalid UTF-8 sequences.
+`end`: an iterator pointing to pass-the-end of the UTF-8 string to look for invalid UTF-8 sequences.
+`out`: An output iterator to the range where the result of replacement is stored.
+`replacement`: A Unicode code point for the replacement marker. The version without this parameter assumes the value `0xfffd`
+Return value: An iterator pointing to the place after the UTF-8 string with replaced invalid sequences.
+
+Example of use:
+
+```cpp
+char invalid_sequence[] = "a\x80\xe0\xa0\xc0\xaf\xed\xa0\x80z";
+vector<char> replace_invalid_result;
+replace_invalid (invalid_sequence, invalid_sequence + sizeof(invalid_sequence), back_inserter(replace_invalid_result), '?');
+bvalid = is_valid(replace_invalid_result.begin(), replace_invalid_result.end());
+assert (bvalid);
+char* fixed_invalid_sequence = "a????z";
+assert (std::equal(replace_invalid_result.begin(), replace_invalid_result.end(), fixed_invalid_sequence));
+```
+
+`replace_invalid` does not perform in-place replacement of invalid sequences. Rather, it produces a copy of the original string with the invalid sequences replaced with a replacement marker. Therefore, `out` must not be in the `[start, end]` range.
+
+#### utf8::starts_with_bom
+
+Available in version 3.0 and later. Requires a C++ 11 compliant compiler.
+
+Checks whether a string starts with a UTF-8 byte order mark (BOM)
+
+```cpp
+bool starts_with_bom(const std::string& s);
+```
+
+`s`: a UTF-8 encoded string.
+Return value: `true` if the string starts with a UTF-8 byte order mark; `false` if not.
+
+Example of use:
+
+```cpp
+string byte_order_mark = {char(0xef), char(0xbb), char(0xbf)};
+bool bbom = starts_with_bom(byte_order_mark);
+assert (bbom == true);
+string threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+bool no_bbom = starts_with_bom(threechars);
+assert (no_bbom == false);
+ ```
+
+The typical use of this function is to check the first three bytes of a file. If they form the UTF-8 BOM, we want to skip them before processing the actual UTF-8 encoded text.
+
+
+#### utf8::starts_with_bom
+
+Available in version 3.2 and later. Requires a C++ 17 compliant compiler.
+
+Checks whether a string starts with a UTF-8 byte order mark (BOM)
+
+```cpp
+bool starts_with_bom(std::string_view s);
+```
+
+`s`: a UTF-8 encoded string.
+Return value: `true` if the string starts with a UTF-8 byte order mark; `false` if not.
+
+Example of use:
+
+```cpp
+string byte_order_mark = {char(0xef), char(0xbb), char(0xbf)};
+string_view byte_order_mark_view(byte_order_mark);
+bool bbom = starts_with_bom(byte_order_mark_view);
+assert (bbom);
+string_view threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+bool no_bbom = starts_with_bom(threechars);
+assert (!no_bbom);
+ ```
+
+The typical use of this function is to check the first three bytes of a file. If they form the UTF-8 BOM, we want to skip them before processing the actual UTF-8 encoded text.
+
+
+#### utf8::starts_with_bom
+
+Available in version 2.3 and later.
+
+Checks whether an octet sequence starts with a UTF-8 byte order mark (BOM)
+
+```cpp
+template <typename octet_iterator>
+bool starts_with_bom (octet_iterator it, octet_iterator end);
+```
+
+`octet_iterator`: an input iterator.
+`it`: beginning of the octet sequence to check
+`end`: pass-end of the sequence to check
+Return value: `true` if the sequence starts with a UTF-8 byte order mark; `false` if not.
+
+Example of use:
+
+```cpp
+unsigned char byte_order_mark[] = {0xef, 0xbb, 0xbf};
+bool bbom = starts_with_bom(byte_order_mark, byte_order_mark + sizeof(byte_order_mark));
+assert (bbom == true);
+```
+
+The typical use of this function is to check the first three bytes of a file. If they form the UTF-8 BOM, we want to skip them before processing the actual UTF-8 encoded text.
+
+### Types From utf8 Namespace
+
+#### utf8::exception
+
+Available in version 2.3 and later.
+
+Base class for the exceptions thrown by UTF CPP library functions.
+
+```cpp
+class exception : public std::exception {};
+```
+
+Example of use:
+
+```cpp
+try {
+ code_that_uses_utf_cpp_library();
+}
+catch(const utf8::exception& utfcpp_ex) {
+ cerr << utfcpp_ex.what();
+}
+```
+
+#### utf8::invalid_code_point
+
+Available in version 1.0 and later.
+
+Thrown by UTF8 CPP functions such as `advance` and `next` if an UTF-8 sequence represents and invalid code point.
+
+```cpp
+class invalid_code_point : public exception {
+public:
+ uint32_t code_point() const;
+};
+```
+
+Member function `code_point()` can be used to determine the invalid code point that caused the exception to be thrown.
+
+#### utf8::invalid_utf8
+
+Available in version 1.0 and later.
+
+Thrown by UTF8 CPP functions such as `next` and `prior` if an invalid UTF-8 sequence is detected during decoding.
+
+```cpp
+class invalid_utf8 : public exception {
+public:
+ uint8_t utf8_octet() const;
+};
+```
+
+Member function `utf8_octet()` can be used to determine the beginning of the byte sequence that caused the exception to be thrown.
+
+#### utf8::invalid_utf16
+
+Available in version 1.0 and later.
+
+Thrown by UTF8 CPP function `utf16to8` if an invalid UTF-16 sequence is detected during decoding.
+
+```cpp
+class invalid_utf16 : public exception {
+public:
+ uint16_t utf16_word() const;
+};
+```
+
+Member function `utf16_word()` can be used to determine the UTF-16 code unit that caused the exception to be thrown.
+
+#### utf8::not_enough_room
+
+Available in version 1.0 and later.
+
+Thrown by UTF8 CPP functions such as `next` if the end of the decoded UTF-8 sequence was reached before the code point was decoded.
+
+```cpp
+class not_enough_room : public exception {};
+```
+
+#### utf8::iterator
+
+Available in version 2.0 and later.
+
+Adapts the underlying octet iterator to iterate over the sequence of code points, rather than raw octets.
+
+```cpp
+template <typename octet_iterator>
+class iterator;
+```
+
+##### Member functions
+
+`iterator();` the deafult constructor; the underlying octet_iterator is constructed with its default constructor.
+
+`explicit iterator (const octet_iterator& octet_it, const octet_iterator& range_start, const octet_iterator& range_end);` a constructor that initializes the underlying octet_iterator with octet_it and sets the range in which the iterator is considered valid.
+
+`octet_iterator base () const;` returns the underlying octet_iterator.
+
+`uint32_t operator * () const;` decodes the utf-8 sequence the underlying octet_iterator is pointing to and returns the code point.
+
+`bool operator == (const iterator& rhs) const;` returns `true` if the two underlaying iterators are equal.
+
+`bool operator != (const iterator& rhs) const;` returns `true` if the two underlaying iterators are not equal.
+
+`iterator& operator ++ ();` the prefix increment - moves the iterator to the next UTF-8 encoded code point.
+
+`iterator operator ++ (int);` the postfix increment - moves the iterator to the next UTF-8 encoded code point and returns the current one.
+
+`iterator& operator -- ();` the prefix decrement - moves the iterator to the previous UTF-8 encoded code point.
+
+`iterator operator -- (int);` the postfix decrement - moves the iterator to the previous UTF-8 encoded code point and returns the current one.
+
+Example of use:
+
+```cpp
+char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+utf8::iterator<char*> it(threechars, threechars, threechars + 9);
+utf8::iterator<char*> it2 = it;
+assert (it2 == it);
+assert (*it == 0x10346);
+assert (*(++it) == 0x65e5);
+assert ((*it++) == 0x65e5);
+assert (*it == 0x0448);
+assert (it != it2);
+utf8::iterator<char*> endit (threechars + 9, threechars, threechars + 9);
+assert (++it == endit);
+assert (*(--it) == 0x0448);
+assert ((*it--) == 0x0448);
+assert (*it == 0x65e5);
+assert (--it == utf8::iterator<char*>(threechars, threechars, threechars + 9));
+assert (*it == 0x10346);
+```
+
+The purpose of `utf8::iterator` adapter is to enable easy iteration as well as the use of STL algorithms with UTF-8 encoded strings. Increment and decrement operators are implemented in terms of `utf8::next()` and `utf8::prior()` functions.
+
+Note that `utf8::iterator` adapter is a checked iterator. It operates on the range specified in the constructor; any attempt to go out of that range will result in an exception. Even the comparison operators require both iterator object to be constructed against the same range - otherwise an exception is thrown. Typically, the range will be determined by sequence container functions `begin` and `end`, i.e.:
+
+```cpp
+std::string s = "example";
+utf8::iterator i (s.begin(), s.begin(), s.end());
+```
+
+### Functions From utf8::unchecked Namespace
+
+#### utf8::unchecked::append
+
+Available in version 1.0 and later.
+
+Encodes a 32 bit code point as a UTF-8 sequence of octets and appends the sequence to a UTF-8 string.
+
+```cpp
+template <typename octet_iterator>
+octet_iterator append(uint32_t cp, octet_iterator result);
+```
+
+`cp`: A 32 bit integer representing a code point to append to the sequence.
+`result`: An output iterator to the place in the sequence where to append the code point.
+Return value: An iterator pointing to the place after the newly appended sequence.
+
+Example of use:
+
+```cpp
+unsigned char u[5] = {0,0,0,0,0};
+unsigned char* end = unchecked::append(0x0448, u);
+assert (u[0] == 0xd1 && u[1] == 0x88 && u[2] == 0 && u[3] == 0 && u[4] == 0);
+```
+
+This is a faster but less safe version of `utf8::append`. It does not check for validity of the supplied code point, and may produce an invalid UTF-8 sequence.
+
+#### utf8::unchecked::next
+
+Available in version 1.0 and later.
+
+Given the iterator to the beginning of a UTF-8 sequence, it returns the code point and moves the iterator to the next position.
+
+```cpp
+template <typename octet_iterator>
+uint32_t next(octet_iterator& it);
+```
+
+`it`: a reference to an iterator pointing to the beginning of an UTF-8 encoded code point. After the function returns, it is incremented to point to the beginning of the next code point.
+ Return value: the 32 bit representation of the processed UTF-8 code point.
+
+Example of use:
+
+```cpp
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars;
+int cp = unchecked::next(w);
+assert (cp == 0x65e5);
+assert (w == twochars + 3);
+```
+
+This is a faster but less safe version of `utf8::next`. It does not check for validity of the supplied UTF-8 sequence.
+
+#### utf8::unchecked::peek_next
+
+Available in version 2.1 and later.
+
+Given the iterator to the beginning of a UTF-8 sequence, it returns the code point.
+
+```cpp
+template <typename octet_iterator>
+uint32_t peek_next(octet_iterator it);
+```
+
+`it`: an iterator pointing to the beginning of an UTF-8 encoded code point.
+Return value: the 32 bit representation of the processed UTF-8 code point.
+
+Example of use:
+
+```cpp
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars;
+int cp = unchecked::peek_next(w);
+assert (cp == 0x65e5);
+assert (w == twochars);
+```
+
+This is a faster but less safe version of `utf8::peek_next`. It does not check for validity of the supplied UTF-8 sequence.
+
+#### utf8::unchecked::prior
+
+Available in version 1.02 and later.
+
+Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it decreases the iterator until it hits the beginning of the previous UTF-8 encoded code point and returns the 32 bits representation of the code point.
+
+```cpp
+template <typename octet_iterator>
+uint32_t prior(octet_iterator& it);
+```
+
+`it`: a reference pointing to an octet within a UTF-8 encoded string. After the function returns, it is decremented to point to the beginning of the previous code point.
+ Return value: the 32 bit representation of the previous code point.
+
+Example of use:
+
+```cpp
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars + 3;
+int cp = unchecked::prior (w);
+assert (cp == 0x65e5);
+assert (w == twochars);
+```
+
+This is a faster but less safe version of `utf8::prior`. It does not check for validity of the supplied UTF-8 sequence and offers no boundary checking.
+
+#### utf8::unchecked::advance
+
+Available in version 1.0 and later.
+
+Advances an iterator by the specified number of code points within an UTF-8 sequence.
+
+```cpp
+template <typename octet_iterator, typename distance_type>
+void advance (octet_iterator& it, distance_type n);
+```
+
+`it`: a reference to an iterator pointing to the beginning of an UTF-8 encoded code point. After the function returns, it is incremented to point to the nth following code point.
+`n`: number of code points `it` should be advanced. A negative value means decrement.
+
+Example of use:
+
+```cpp
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars;
+unchecked::advance (w, 2);
+assert (w == twochars + 5);
+```
+
+This is a faster but less safe version of `utf8::advance`. It does not check for validity of the supplied UTF-8 sequence and offers no boundary checking.
+
+#### utf8::unchecked::distance
+
+Available in version 1.0 and later.
+
+Given the iterators to two UTF-8 encoded code points in a seqence, returns the number of code points between them.
+
+```cpp
+template <typename octet_iterator>
+typename std::iterator_traits<octet_iterator>::difference_type distance (octet_iterator first, octet_iterator last);
+```
+
+`first`: an iterator to a beginning of a UTF-8 encoded code point.
+`last`: an iterator to a "post-end" of the last UTF-8 encoded code point in the sequence we are trying to determine the length. It can be the beginning of a new code point, or not.
+Return value: the distance between the iterators, in code points.
+
+Example of use:
+
+```cpp
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+size_t dist = utf8::unchecked::distance(twochars, twochars + 5);
+assert (dist == 2);
+```
+
+This is a faster but less safe version of `utf8::distance`. It does not check for validity of the supplied UTF-8 sequence.
+
+#### utf8::unchecked::utf16to8
+
+Available in version 1.0 and later.
+
+Converts a UTF-16 encoded string to UTF-8.
+
+```cpp
+template <typename u16bit_iterator, typename octet_iterator>
+octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result);
+```
+
+`start`: an iterator pointing to the beginning of the UTF-16 encoded string to convert.
+`end`: an iterator pointing to pass-the-end of the UTF-16 encoded string to convert.
+`result`: an output iterator to the place in the UTF-8 string where to append the result of conversion.
+Return value: An iterator pointing to the place after the appended UTF-8 string.
+
+Example of use:
+
+```cpp
+unsigned short utf16string[] = {0x41, 0x0448, 0x65e5, 0xd834, 0xdd1e};
+vector<unsigned char> utf8result;
+unchecked::utf16to8(utf16string, utf16string + 5, back_inserter(utf8result));
+assert (utf8result.size() == 10);
+```
+
+This is a faster but less safe version of `utf8::utf16to8`. It does not check for validity of the supplied UTF-16 sequence.
+
+#### utf8::unchecked::utf8to16
+
+Available in version 1.0 and later.
+
+Converts an UTF-8 encoded string to UTF-16
+
+```cpp
+template <typename u16bit_iterator, typename octet_iterator>
+u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result);
+```
+
+`start`: an iterator pointing to the beginning of the UTF-8 encoded string to convert. < br /> `end`: an iterator pointing to pass-the-end of the UTF-8 encoded string to convert.
+`result`: an output iterator to the place in the UTF-16 string where to append the result of conversion.
+Return value: An iterator pointing to the place after the appended UTF-16 string.
+
+Example of use:
+
+```cpp
+char utf8_with_surrogates[] = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+vector <unsigned short> utf16result;
+unchecked::utf8to16(utf8_with_surrogates, utf8_with_surrogates + 9, back_inserter(utf16result));
+assert (utf16result.size() == 4);
+assert (utf16result[2] == 0xd834);
+assert (utf16result[3] == 0xdd1e);
+```
+
+This is a faster but less safe version of `utf8::utf8to16`. It does not check for validity of the supplied UTF-8 sequence.
+
+#### utf8::unchecked::utf32to8
+
+Available in version 1.0 and later.
+
+Converts a UTF-32 encoded string to UTF-8.
+
+```cpp
+template <typename octet_iterator, typename u32bit_iterator>
+octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result);
+```
+
+`start`: an iterator pointing to the beginning of the UTF-32 encoded string to convert.
+`end`: an iterator pointing to pass-the-end of the UTF-32 encoded string to convert.
+`result`: an output iterator to the place in the UTF-8 string where to append the result of conversion.
+Return value: An iterator pointing to the place after the appended UTF-8 string.
+
+Example of use:
+
+```cpp
+int utf32string[] = {0x448, 0x65e5, 0x10346, 0};
+vector<unsigned char> utf8result;
+utf32to8(utf32string, utf32string + 3, back_inserter(utf8result));
+assert (utf8result.size() == 9);
+```
+
+This is a faster but less safe version of `utf8::utf32to8`. It does not check for validity of the supplied UTF-32 sequence.
+
+#### utf8::unchecked::utf8to32
+
+Available in version 1.0 and later.
+
+Converts a UTF-8 encoded string to UTF-32.
+
+```cpp
+template <typename octet_iterator, typename u32bit_iterator>
+u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result);
+```
+
+`start`: an iterator pointing to the beginning of the UTF-8 encoded string to convert.
+`end`: an iterator pointing to pass-the-end of the UTF-8 encoded string to convert.
+`result`: an output iterator to the place in the UTF-32 string where to append the result of conversion.
+Return value: An iterator pointing to the place after the appended UTF-32 string.
+
+Example of use:
+
+```cpp
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+vector<int> utf32result;
+unchecked::utf8to32(twochars, twochars + 5, back_inserter(utf32result));
+assert (utf32result.size() == 2);
+```
+
+This is a faster but less safe version of `utf8::utf8to32`. It does not check for validity of the supplied UTF-8 sequence.
+
+#### utf8::unchecked::replace_invalid
+
+Available in version 3.1 and later.
+
+Replaces all invalid UTF-8 sequences within a string with a replacement marker.
+
+```cpp
+template <typename octet_iterator, typename output_iterator>
+output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement);
+template <typename octet_iterator, typename output_iterator>
+output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out);
+```
+
+`octet_iterator`: an input iterator.
+`output_iterator`: an output iterator.
+`start`: an iterator pointing to the beginning of the UTF-8 string to look for invalid UTF-8 sequences.
+`end`: an iterator pointing to pass-the-end of the UTF-8 string to look for invalid UTF-8 sequences.
+`out`: An output iterator to the range where the result of replacement is stored.
+`replacement`: A Unicode code point for the replacement marker. The version without this parameter assumes the value `0xfffd`
+Return value: An iterator pointing to the place after the UTF-8 string with replaced invalid sequences.
+
+Example of use:
+
+```cpp
+char invalid_sequence[] = "a\x80\xe0\xa0\xc0\xaf\xed\xa0\x80z";
+vector<char> replace_invalid_result;
+unchecked::replace_invalid (invalid_sequence, invalid_sequence + sizeof(invalid_sequence), back_inserter(replace_invalid_result), '?');
+bvalid = utf8::is_valid(replace_invalid_result.begin(), replace_invalid_result.end());
+assert (bvalid);
+char* fixed_invalid_sequence = "a????z";
+assert (std::equal(replace_invalid_result.begin(), replace_invalid_result.end(), fixed_invalid_sequence));
+```
+
+`replace_invalid` does not perform in-place replacement of invalid sequences. Rather, it produces a copy of the original string with the invalid sequences replaced with a replacement marker. Therefore, `out` must not be in the `[start, end]` range.
+
+Unlike `utf8::replace_invalid`, this function does not verify validity of the replacement marker.
+
+### Types From utf8::unchecked Namespace
+
+#### utf8::iterator
+
+Available in version 2.0 and later.
+
+Adapts the underlying octet iterator to iterate over the sequence of code points, rather than raw octets.
+
+```cpp
+template <typename octet_iterator>
+class iterator;
+```
+
+##### Member functions
+
+`iterator();` the deafult constructor; the underlying octet_iterator is constructed with its default constructor.
+
+`explicit iterator (const octet_iterator& octet_it);` a constructor that initializes the underlying octet_iterator with `octet_it`.
+
+`octet_iterator base () const;` returns the underlying octet_iterator.
+
+`uint32_t operator * () const;` decodes the utf-8 sequence the underlying octet_iterator is pointing to and returns the code point.
+
+`bool operator == (const iterator& rhs) const;` returns `true` if the two underlaying iterators are equal.
+
+`bool operator != (const iterator& rhs) const;` returns `true` if the two underlaying iterators are not equal.
+
+`iterator& operator ++ ();` the prefix increment - moves the iterator to the next UTF-8 encoded code point.
+
+`iterator operator ++ (int);` the postfix increment - moves the iterator to the next UTF-8 encoded code point and returns the current one.
+
+`iterator& operator -- ();` the prefix decrement - moves the iterator to the previous UTF-8 encoded code point.
+
+`iterator operator -- (int);` the postfix decrement - moves the iterator to the previous UTF-8 encoded code point and returns the current one.
+
+Example of use:
+
+```cpp
+char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+utf8::unchecked::iterator<char*> un_it(threechars);
+utf8::unchecked::iterator<char*> un_it2 = un_it;
+assert (un_it2 == un_it);
+assert (*un_it == 0x10346);
+assert (*(++un_it) == 0x65e5);
+assert ((*un_it++) == 0x65e5);
+assert (*un_it == 0x0448);
+assert (un_it != un_it2);
+utf8::::unchecked::iterator<char*> un_endit (threechars + 9);
+assert (++un_it == un_endit);
+assert (*(--un_it) == 0x0448);
+assert ((*un_it--) == 0x0448);
+assert (*un_it == 0x65e5);
+assert (--un_it == utf8::unchecked::iterator<char*>(threechars));
+assert (*un_it == 0x10346);
+```
+
+This is an unchecked version of `utf8::iterator`. It is faster in many cases, but offers no validity or range checks.
+
+## Links
+
+1. [The Unicode Consortium](http://www.unicode.org/).
+2. [ICU Library](http://icu.sourceforge.net/).
+3. [UTF-8 at Wikipedia](http://en.wikipedia.org/wiki/UTF-8)
+4. [UTF-8 and Unicode FAQ for Unix/Linux](http://www.cl.cam.ac.uk/~mgk25/unicode.html)
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/samples/docsample.cpp b/graphics/asymptote/LspCpp/third_party/utfcpp/samples/docsample.cpp
new file mode 100644
index 0000000000..6533887253
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/samples/docsample.cpp
@@ -0,0 +1,64 @@
+#include "../source/utf8.h"
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+
+
+using namespace std;
+
+int main(int argc, char** argv)
+{
+ if (argc != 2) {
+ cout << "\nUsage: docsample filename\n";
+ return 0;
+ }
+ const char* test_file_path = argv[1];
+ // Open the test file (must be UTF-8 encoded)
+ ifstream fs8(test_file_path);
+ if (!fs8.is_open()) {
+ cout << "Could not open " << test_file_path << endl;
+ return 0;
+ }
+
+ unsigned line_count = 1;
+ string line;
+ // Play with all the lines in the file
+ while (getline(fs8, line)) {
+ // check for invalid utf-8 (for a simple yes/no check, there is also utf8::is_valid function)
+#if __cplusplus >= 201103L // C++ 11 or later
+ auto end_it = utf8::find_invalid(line.begin(), line.end());
+#else
+ string::iterator end_it = utf8::find_invalid(line.begin(), line.end());
+#endif // C++ 11
+ if (end_it != line.end()) {
+ cout << "Invalid UTF-8 encoding detected at line " << line_count << "\n";
+ cout << "This part is fine: " << string(line.begin(), end_it) << "\n";
+ }
+ // Get the line length (at least for the valid part)
+ ptrdiff_t length = utf8::distance(line.begin(), end_it);
+ cout << "Length of line " << line_count << " is " << length << "\n";
+
+ // Convert it to utf-16
+#if __cplusplus >= 201103L // C++ 11 or later
+ u16string utf16line = utf8::utf8to16(line);
+#else
+ vector<unsigned short> utf16line;
+ utf8::utf8to16(line.begin(), end_it, back_inserter(utf16line));
+#endif // C++ 11
+ // And back to utf-8;
+#if __cplusplus >= 201103L // C++ 11 or later
+ string utf8line = utf8::utf16to8(utf16line);
+#else
+ string utf8line;
+ utf8::utf16to8(utf16line.begin(), utf16line.end(), back_inserter(utf8line));
+#endif // C++ 11
+ // Confirm that the conversion went OK:
+ if (utf8line != string(line.begin(), end_it))
+ cout << "Error in UTF-16 conversion at line: " << line_count << "\n";
+
+ line_count++;
+ }
+
+ return 0;
+}
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8.h b/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8.h
new file mode 100644
index 0000000000..82b13f59f9
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8.h
@@ -0,0 +1,34 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+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.
+*/
+
+
+#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include "utf8/checked.h"
+#include "utf8/unchecked.h"
+
+#endif // header guard
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/checked.h b/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/checked.h
new file mode 100644
index 0000000000..993b7f7c5f
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/checked.h
@@ -0,0 +1,335 @@
+// Copyright 2006-2016 Nemanja Trifunovic
+
+/*
+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.
+*/
+
+
+#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include "core.h"
+#include <stdexcept>
+
+namespace utf8
+{
+ // Base for the exceptions that may be thrown from the library
+ class exception : public ::std::exception {
+ };
+
+ // Exceptions that may be thrown from the library functions.
+ class invalid_code_point : public exception {
+ uint32_t cp;
+ public:
+ invalid_code_point(uint32_t codepoint) : cp(codepoint) {}
+ virtual const char* what() const UTF_CPP_NOEXCEPT UTF_CPP_OVERRIDE { return "Invalid code point"; }
+ uint32_t code_point() const {return cp;}
+ };
+
+ class invalid_utf8 : public exception {
+ uint8_t u8;
+ public:
+ invalid_utf8 (uint8_t u) : u8(u) {}
+ virtual const char* what() const UTF_CPP_NOEXCEPT UTF_CPP_OVERRIDE { return "Invalid UTF-8"; }
+ uint8_t utf8_octet() const {return u8;}
+ };
+
+ class invalid_utf16 : public exception {
+ uint16_t u16;
+ public:
+ invalid_utf16 (uint16_t u) : u16(u) {}
+ virtual const char* what() const UTF_CPP_NOEXCEPT UTF_CPP_OVERRIDE { return "Invalid UTF-16"; }
+ uint16_t utf16_word() const {return u16;}
+ };
+
+ class not_enough_room : public exception {
+ public:
+ virtual const char* what() const UTF_CPP_NOEXCEPT UTF_CPP_OVERRIDE { return "Not enough space"; }
+ };
+
+ /// The library API - functions intended to be called by the users
+
+ template <typename octet_iterator>
+ octet_iterator append(uint32_t cp, octet_iterator result)
+ {
+ if (!utf8::internal::is_code_point_valid(cp))
+ throw invalid_code_point(cp);
+
+ if (cp < 0x80) // one octet
+ *(result++) = static_cast<uint8_t>(cp);
+ else if (cp < 0x800) { // two octets
+ *(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ else if (cp < 0x10000) { // three octets
+ *(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
+ *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ else { // four octets
+ *(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
+ *(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator, typename output_iterator>
+ output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement)
+ {
+ while (start != end) {
+ octet_iterator sequence_start = start;
+ internal::utf_error err_code = utf8::internal::validate_next(start, end);
+ switch (err_code) {
+ case internal::UTF8_OK :
+ for (octet_iterator it = sequence_start; it != start; ++it)
+ *out++ = *it;
+ break;
+ case internal::NOT_ENOUGH_ROOM:
+ out = utf8::append (replacement, out);
+ start = end;
+ break;
+ case internal::INVALID_LEAD:
+ out = utf8::append (replacement, out);
+ ++start;
+ break;
+ case internal::INCOMPLETE_SEQUENCE:
+ case internal::OVERLONG_SEQUENCE:
+ case internal::INVALID_CODE_POINT:
+ out = utf8::append (replacement, out);
+ ++start;
+ // just one replacement mark for the sequence
+ while (start != end && utf8::internal::is_trail(*start))
+ ++start;
+ break;
+ }
+ }
+ return out;
+ }
+
+ template <typename octet_iterator, typename output_iterator>
+ inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out)
+ {
+ static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd);
+ return utf8::replace_invalid(start, end, out, replacement_marker);
+ }
+
+ template <typename octet_iterator>
+ uint32_t next(octet_iterator& it, octet_iterator end)
+ {
+ uint32_t cp = 0;
+ internal::utf_error err_code = utf8::internal::validate_next(it, end, cp);
+ switch (err_code) {
+ case internal::UTF8_OK :
+ break;
+ case internal::NOT_ENOUGH_ROOM :
+ throw not_enough_room();
+ case internal::INVALID_LEAD :
+ case internal::INCOMPLETE_SEQUENCE :
+ case internal::OVERLONG_SEQUENCE :
+ throw invalid_utf8(*it);
+ case internal::INVALID_CODE_POINT :
+ throw invalid_code_point(cp);
+ }
+ return cp;
+ }
+
+ template <typename octet_iterator>
+ uint32_t peek_next(octet_iterator it, octet_iterator end)
+ {
+ return utf8::next(it, end);
+ }
+
+ template <typename octet_iterator>
+ uint32_t prior(octet_iterator& it, octet_iterator start)
+ {
+ // can't do much if it == start
+ if (it == start)
+ throw not_enough_room();
+
+ octet_iterator end = it;
+ // Go back until we hit either a lead octet or start
+ while (utf8::internal::is_trail(*(--it)))
+ if (it == start)
+ throw invalid_utf8(*it); // error - no lead byte in the sequence
+ return utf8::peek_next(it, end);
+ }
+
+ template <typename octet_iterator, typename distance_type>
+ void advance (octet_iterator& it, distance_type n, octet_iterator end)
+ {
+ const distance_type zero(0);
+ if (n < zero) {
+ // backward
+ for (distance_type i = n; i < zero; ++i)
+ utf8::prior(it, end);
+ } else {
+ // forward
+ for (distance_type i = zero; i < n; ++i)
+ utf8::next(it, end);
+ }
+ }
+
+ template <typename octet_iterator>
+ typename std::iterator_traits<octet_iterator>::difference_type
+ distance (octet_iterator first, octet_iterator last)
+ {
+ typename std::iterator_traits<octet_iterator>::difference_type dist;
+ for (dist = 0; first < last; ++dist)
+ utf8::next(first, last);
+ return dist;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
+ {
+ while (start != end) {
+ uint32_t cp = utf8::internal::mask16(*start++);
+ // Take care of surrogate pairs first
+ if (utf8::internal::is_lead_surrogate(cp)) {
+ if (start != end) {
+ uint32_t trail_surrogate = utf8::internal::mask16(*start++);
+ if (utf8::internal::is_trail_surrogate(trail_surrogate))
+ cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
+ else
+ throw invalid_utf16(static_cast<uint16_t>(trail_surrogate));
+ }
+ else
+ throw invalid_utf16(static_cast<uint16_t>(cp));
+
+ }
+ // Lone trail surrogate
+ else if (utf8::internal::is_trail_surrogate(cp))
+ throw invalid_utf16(static_cast<uint16_t>(cp));
+
+ result = utf8::append(cp, result);
+ }
+ return result;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
+ {
+ while (start < end) {
+ uint32_t cp = utf8::next(start, end);
+ if (cp > 0xffff) { //make a surrogate pair
+ *result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
+ *result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
+ }
+ else
+ *result++ = static_cast<uint16_t>(cp);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
+ {
+ while (start != end)
+ result = utf8::append(*(start++), result);
+
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
+ {
+ while (start < end)
+ (*result++) = utf8::next(start, end);
+
+ return result;
+ }
+
+ // The iterator class
+ template <typename octet_iterator>
+ class iterator {
+ octet_iterator it;
+ octet_iterator range_start;
+ octet_iterator range_end;
+ public:
+ typedef uint32_t value_type;
+ typedef uint32_t* pointer;
+ typedef uint32_t& reference;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::bidirectional_iterator_tag iterator_category;
+ iterator () {}
+ explicit iterator (const octet_iterator& octet_it,
+ const octet_iterator& rangestart,
+ const octet_iterator& rangeend) :
+ it(octet_it), range_start(rangestart), range_end(rangeend)
+ {
+ if (it < range_start || it > range_end)
+ throw std::out_of_range("Invalid utf-8 iterator position");
+ }
+ // the default "big three" are OK
+ octet_iterator base () const { return it; }
+ uint32_t operator * () const
+ {
+ octet_iterator temp = it;
+ return utf8::next(temp, range_end);
+ }
+ bool operator == (const iterator& rhs) const
+ {
+ if (range_start != rhs.range_start || range_end != rhs.range_end)
+ throw std::logic_error("Comparing utf-8 iterators defined with different ranges");
+ return (it == rhs.it);
+ }
+ bool operator != (const iterator& rhs) const
+ {
+ return !(operator == (rhs));
+ }
+ iterator& operator ++ ()
+ {
+ utf8::next(it, range_end);
+ return *this;
+ }
+ iterator operator ++ (int)
+ {
+ iterator temp = *this;
+ utf8::next(it, range_end);
+ return temp;
+ }
+ iterator& operator -- ()
+ {
+ utf8::prior(it, range_start);
+ return *this;
+ }
+ iterator operator -- (int)
+ {
+ iterator temp = *this;
+ utf8::prior(it, range_start);
+ return temp;
+ }
+ }; // class iterator
+
+} // namespace utf8
+
+#if UTF_CPP_CPLUSPLUS >= 201703L // C++ 17 or later
+#include "cpp17.h"
+#elif UTF_CPP_CPLUSPLUS >= 201103L // C++ 11 or later
+#include "cpp11.h"
+#endif // C++ 11 or later
+
+#endif //header guard
+
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/core.h b/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/core.h
new file mode 100644
index 0000000000..de6199f2a3
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/core.h
@@ -0,0 +1,338 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+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.
+*/
+
+
+#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include <iterator>
+
+// Determine the C++ standard version.
+// If the user defines UTF_CPP_CPLUSPLUS, use that.
+// Otherwise, trust the unreliable predefined macro __cplusplus
+
+#if !defined UTF_CPP_CPLUSPLUS
+ #define UTF_CPP_CPLUSPLUS __cplusplus
+#endif
+
+#if UTF_CPP_CPLUSPLUS >= 201103L // C++ 11 or later
+ #define UTF_CPP_OVERRIDE override
+ #define UTF_CPP_NOEXCEPT noexcept
+#else // C++ 98/03
+ #define UTF_CPP_OVERRIDE
+ #define UTF_CPP_NOEXCEPT throw()
+#endif // C++ 11 or later
+
+
+namespace utf8
+{
+ // The typedefs for 8-bit, 16-bit and 32-bit unsigned integers
+ // You may need to change them to match your system.
+ // These typedefs have the same names as ones from cstdint, or boost/cstdint
+ typedef unsigned char uint8_t;
+ typedef unsigned short uint16_t;
+ typedef unsigned int uint32_t;
+
+// Helper code - not intended to be directly called by the library users. May be changed at any time
+namespace internal
+{
+ // Unicode constants
+ // Leading (high) surrogates: 0xd800 - 0xdbff
+ // Trailing (low) surrogates: 0xdc00 - 0xdfff
+ const uint16_t LEAD_SURROGATE_MIN = 0xd800u;
+ const uint16_t LEAD_SURROGATE_MAX = 0xdbffu;
+ const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u;
+ const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu;
+ const uint16_t LEAD_OFFSET = 0xd7c0u; // LEAD_SURROGATE_MIN - (0x10000 >> 10)
+ const uint32_t SURROGATE_OFFSET = 0xfca02400u; // 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN
+
+ // Maximum valid value for a Unicode code point
+ const uint32_t CODE_POINT_MAX = 0x0010ffffu;
+
+ template<typename octet_type>
+ inline uint8_t mask8(octet_type oc)
+ {
+ return static_cast<uint8_t>(0xff & oc);
+ }
+ template<typename u16_type>
+ inline uint16_t mask16(u16_type oc)
+ {
+ return static_cast<uint16_t>(0xffff & oc);
+ }
+ template<typename octet_type>
+ inline bool is_trail(octet_type oc)
+ {
+ return ((utf8::internal::mask8(oc) >> 6) == 0x2);
+ }
+
+ template <typename u16>
+ inline bool is_lead_surrogate(u16 cp)
+ {
+ return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX);
+ }
+
+ template <typename u16>
+ inline bool is_trail_surrogate(u16 cp)
+ {
+ return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
+ }
+
+ template <typename u16>
+ inline bool is_surrogate(u16 cp)
+ {
+ return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX);
+ }
+
+ template <typename u32>
+ inline bool is_code_point_valid(u32 cp)
+ {
+ return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp));
+ }
+
+ template <typename octet_iterator>
+ inline typename std::iterator_traits<octet_iterator>::difference_type
+ sequence_length(octet_iterator lead_it)
+ {
+ uint8_t lead = utf8::internal::mask8(*lead_it);
+ if (lead < 0x80)
+ return 1;
+ else if ((lead >> 5) == 0x6)
+ return 2;
+ else if ((lead >> 4) == 0xe)
+ return 3;
+ else if ((lead >> 3) == 0x1e)
+ return 4;
+ else
+ return 0;
+ }
+
+ template <typename octet_difference_type>
+ inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length)
+ {
+ if (cp < 0x80) {
+ if (length != 1)
+ return true;
+ }
+ else if (cp < 0x800) {
+ if (length != 2)
+ return true;
+ }
+ else if (cp < 0x10000) {
+ if (length != 3)
+ return true;
+ }
+
+ return false;
+ }
+
+ enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT};
+
+ /// Helper for get_sequence_x
+ template <typename octet_iterator>
+ utf_error increase_safely(octet_iterator& it, octet_iterator end)
+ {
+ if (++it == end)
+ return NOT_ENOUGH_ROOM;
+
+ if (!utf8::internal::is_trail(*it))
+ return INCOMPLETE_SEQUENCE;
+
+ return UTF8_OK;
+ }
+
+ #define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;}
+
+ /// get_sequence_x functions decode utf-8 sequences of the length x
+ template <typename octet_iterator>
+ utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ return UTF8_OK;
+ }
+
+ template <typename octet_iterator>
+ utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f);
+
+ return UTF8_OK;
+ }
+
+ template <typename octet_iterator>
+ utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point += (*it) & 0x3f;
+
+ return UTF8_OK;
+ }
+
+ template <typename octet_iterator>
+ utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ code_point = utf8::internal::mask8(*it);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point += (utf8::internal::mask8(*it) << 6) & 0xfff;
+
+ UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end)
+
+ code_point += (*it) & 0x3f;
+
+ return UTF8_OK;
+ }
+
+ #undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR
+
+ template <typename octet_iterator>
+ utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point)
+ {
+ if (it == end)
+ return NOT_ENOUGH_ROOM;
+
+ // Save the original value of it so we can go back in case of failure
+ // Of course, it does not make much sense with i.e. stream iterators
+ octet_iterator original_it = it;
+
+ uint32_t cp = 0;
+ // Determine the sequence length based on the lead octet
+ typedef typename std::iterator_traits<octet_iterator>::difference_type octet_difference_type;
+ const octet_difference_type length = utf8::internal::sequence_length(it);
+
+ // Get trail octets and calculate the code point
+ utf_error err = UTF8_OK;
+ switch (length) {
+ case 0:
+ return INVALID_LEAD;
+ case 1:
+ err = utf8::internal::get_sequence_1(it, end, cp);
+ break;
+ case 2:
+ err = utf8::internal::get_sequence_2(it, end, cp);
+ break;
+ case 3:
+ err = utf8::internal::get_sequence_3(it, end, cp);
+ break;
+ case 4:
+ err = utf8::internal::get_sequence_4(it, end, cp);
+ break;
+ }
+
+ if (err == UTF8_OK) {
+ // Decoding succeeded. Now, security checks...
+ if (utf8::internal::is_code_point_valid(cp)) {
+ if (!utf8::internal::is_overlong_sequence(cp, length)){
+ // Passed! Return here.
+ code_point = cp;
+ ++it;
+ return UTF8_OK;
+ }
+ else
+ err = OVERLONG_SEQUENCE;
+ }
+ else
+ err = INVALID_CODE_POINT;
+ }
+
+ // Failure branch - restore the original value of the iterator
+ it = original_it;
+ return err;
+ }
+
+ template <typename octet_iterator>
+ inline utf_error validate_next(octet_iterator& it, octet_iterator end) {
+ uint32_t ignored;
+ return utf8::internal::validate_next(it, end, ignored);
+ }
+
+} // namespace internal
+
+ /// The library API - functions intended to be called by the users
+
+ // Byte order mark
+ const uint8_t bom[] = {0xef, 0xbb, 0xbf};
+
+ template <typename octet_iterator>
+ octet_iterator find_invalid(octet_iterator start, octet_iterator end)
+ {
+ octet_iterator result = start;
+ while (result != end) {
+ utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end);
+ if (err_code != internal::UTF8_OK)
+ return result;
+ }
+ return result;
+ }
+
+ template <typename octet_iterator>
+ inline bool is_valid(octet_iterator start, octet_iterator end)
+ {
+ return (utf8::find_invalid(start, end) == end);
+ }
+
+ template <typename octet_iterator>
+ inline bool starts_with_bom (octet_iterator it, octet_iterator end)
+ {
+ return (
+ ((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) &&
+ ((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) &&
+ ((it != end) && (utf8::internal::mask8(*it)) == bom[2])
+ );
+ }
+} // namespace utf8
+
+#endif // header guard
+
+
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/cpp11.h b/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/cpp11.h
new file mode 100644
index 0000000000..d93961b04f
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/cpp11.h
@@ -0,0 +1,103 @@
+// Copyright 2018 Nemanja Trifunovic
+
+/*
+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.
+*/
+
+
+#ifndef UTF8_FOR_CPP_a184c22c_d012_11e8_a8d5_f2801f1b9fd1
+#define UTF8_FOR_CPP_a184c22c_d012_11e8_a8d5_f2801f1b9fd1
+
+#include "checked.h"
+#include <string>
+
+namespace utf8
+{
+
+ inline void append(char32_t cp, std::string& s)
+ {
+ append(uint32_t(cp), std::back_inserter(s));
+ }
+
+ inline std::string utf16to8(const std::u16string& s)
+ {
+ std::string result;
+ utf16to8(s.begin(), s.end(), std::back_inserter(result));
+ return result;
+ }
+
+ inline std::u16string utf8to16(const std::string& s)
+ {
+ std::u16string result;
+ utf8to16(s.begin(), s.end(), std::back_inserter(result));
+ return result;
+ }
+
+ inline std::string utf32to8(const std::u32string& s)
+ {
+ std::string result;
+ utf32to8(s.begin(), s.end(), std::back_inserter(result));
+ return result;
+ }
+
+ inline std::u32string utf8to32(const std::string& s)
+ {
+ std::u32string result;
+ utf8to32(s.begin(), s.end(), std::back_inserter(result));
+ return result;
+ }
+
+ inline std::size_t find_invalid(const std::string& s)
+ {
+ std::string::const_iterator invalid = find_invalid(s.begin(), s.end());
+ return (invalid == s.end()) ? std::string::npos : (invalid - s.begin());
+ }
+
+ inline bool is_valid(const std::string& s)
+ {
+ return is_valid(s.begin(), s.end());
+ }
+
+ inline std::string replace_invalid(const std::string& s, char32_t replacement)
+ {
+ std::string result;
+ replace_invalid(s.begin(), s.end(), std::back_inserter(result), replacement);
+ return result;
+ }
+
+ inline std::string replace_invalid(const std::string& s)
+ {
+ std::string result;
+ replace_invalid(s.begin(), s.end(), std::back_inserter(result));
+ return result;
+ }
+
+ inline bool starts_with_bom(const std::string& s)
+ {
+ return starts_with_bom(s.begin(), s.end());
+ }
+
+} // namespace utf8
+
+#endif // header guard
+
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/cpp17.h b/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/cpp17.h
new file mode 100644
index 0000000000..7bfa869942
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/cpp17.h
@@ -0,0 +1,103 @@
+// Copyright 2018 Nemanja Trifunovic
+
+/*
+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.
+*/
+
+
+#ifndef UTF8_FOR_CPP_7e906c01_03a3_4daf_b420_ea7ea952b3c9
+#define UTF8_FOR_CPP_7e906c01_03a3_4daf_b420_ea7ea952b3c9
+
+#include "checked.h"
+#include <string>
+
+namespace utf8
+{
+
+ inline void append(char32_t cp, std::string& s)
+ {
+ append(uint32_t(cp), std::back_inserter(s));
+ }
+
+ inline std::string utf16to8(std::u16string_view s)
+ {
+ std::string result;
+ utf16to8(s.begin(), s.end(), std::back_inserter(result));
+ return result;
+ }
+
+ inline std::u16string utf8to16(std::string_view s)
+ {
+ std::u16string result;
+ utf8to16(s.begin(), s.end(), std::back_inserter(result));
+ return result;
+ }
+
+ inline std::string utf32to8(std::u32string_view s)
+ {
+ std::string result;
+ utf32to8(s.begin(), s.end(), std::back_inserter(result));
+ return result;
+ }
+
+ inline std::u32string utf8to32(std::string_view s)
+ {
+ std::u32string result;
+ utf8to32(s.begin(), s.end(), std::back_inserter(result));
+ return result;
+ }
+
+ inline std::size_t find_invalid(std::string_view s)
+ {
+ std::string_view::const_iterator invalid = find_invalid(s.begin(), s.end());
+ return (invalid == s.end()) ? std::string_view::npos : (invalid - s.begin());
+ }
+
+ inline bool is_valid(std::string_view s)
+ {
+ return is_valid(s.begin(), s.end());
+ }
+
+ inline std::string replace_invalid(std::string_view s, char32_t replacement)
+ {
+ std::string result;
+ replace_invalid(s.begin(), s.end(), std::back_inserter(result), replacement);
+ return result;
+ }
+
+ inline std::string replace_invalid(std::string_view s)
+ {
+ std::string result;
+ replace_invalid(s.begin(), s.end(), std::back_inserter(result));
+ return result;
+ }
+
+ inline bool starts_with_bom(std::string_view s)
+ {
+ return starts_with_bom(s.begin(), s.end());
+ }
+
+} // namespace utf8
+
+#endif // header guard
+
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/unchecked.h b/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/unchecked.h
new file mode 100644
index 0000000000..0e1b51cc7d
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/source/utf8/unchecked.h
@@ -0,0 +1,274 @@
+// Copyright 2006 Nemanja Trifunovic
+
+/*
+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.
+*/
+
+
+#ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+#define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731
+
+#include "core.h"
+
+namespace utf8
+{
+ namespace unchecked
+ {
+ template <typename octet_iterator>
+ octet_iterator append(uint32_t cp, octet_iterator result)
+ {
+ if (cp < 0x80) // one octet
+ *(result++) = static_cast<uint8_t>(cp);
+ else if (cp < 0x800) { // two octets
+ *(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ else if (cp < 0x10000) { // three octets
+ *(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0);
+ *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ else { // four octets
+ *(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0);
+ *(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f)| 0x80);
+ *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80);
+ *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator, typename output_iterator>
+ output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement)
+ {
+ while (start != end) {
+ octet_iterator sequence_start = start;
+ internal::utf_error err_code = utf8::internal::validate_next(start, end);
+ switch (err_code) {
+ case internal::UTF8_OK :
+ for (octet_iterator it = sequence_start; it != start; ++it)
+ *out++ = *it;
+ break;
+ case internal::NOT_ENOUGH_ROOM:
+ out = utf8::unchecked::append (replacement, out);
+ start = end;
+ break;
+ case internal::INVALID_LEAD:
+ out = utf8::unchecked::append (replacement, out);
+ ++start;
+ break;
+ case internal::INCOMPLETE_SEQUENCE:
+ case internal::OVERLONG_SEQUENCE:
+ case internal::INVALID_CODE_POINT:
+ out = utf8::unchecked::append (replacement, out);
+ ++start;
+ // just one replacement mark for the sequence
+ while (start != end && utf8::internal::is_trail(*start))
+ ++start;
+ break;
+ }
+ }
+ return out;
+ }
+
+ template <typename octet_iterator, typename output_iterator>
+ inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out)
+ {
+ static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd);
+ return utf8::unchecked::replace_invalid(start, end, out, replacement_marker);
+ }
+
+ template <typename octet_iterator>
+ uint32_t next(octet_iterator& it)
+ {
+ uint32_t cp = utf8::internal::mask8(*it);
+ typename std::iterator_traits<octet_iterator>::difference_type length = utf8::internal::sequence_length(it);
+ switch (length) {
+ case 1:
+ break;
+ case 2:
+ it++;
+ cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f);
+ break;
+ case 3:
+ ++it;
+ cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff);
+ ++it;
+ cp += (*it) & 0x3f;
+ break;
+ case 4:
+ ++it;
+ cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff);
+ ++it;
+ cp += (utf8::internal::mask8(*it) << 6) & 0xfff;
+ ++it;
+ cp += (*it) & 0x3f;
+ break;
+ }
+ ++it;
+ return cp;
+ }
+
+ template <typename octet_iterator>
+ uint32_t peek_next(octet_iterator it)
+ {
+ return utf8::unchecked::next(it);
+ }
+
+ template <typename octet_iterator>
+ uint32_t prior(octet_iterator& it)
+ {
+ while (utf8::internal::is_trail(*(--it))) ;
+ octet_iterator temp = it;
+ return utf8::unchecked::next(temp);
+ }
+
+ template <typename octet_iterator, typename distance_type>
+ void advance (octet_iterator& it, distance_type n)
+ {
+ const distance_type zero(0);
+ if (n < zero) {
+ // backward
+ for (distance_type i = n; i < zero; ++i)
+ utf8::unchecked::prior(it);
+ } else {
+ // forward
+ for (distance_type i = zero; i < n; ++i)
+ utf8::unchecked::next(it);
+ }
+ }
+
+ template <typename octet_iterator>
+ typename std::iterator_traits<octet_iterator>::difference_type
+ distance (octet_iterator first, octet_iterator last)
+ {
+ typename std::iterator_traits<octet_iterator>::difference_type dist;
+ for (dist = 0; first < last; ++dist)
+ utf8::unchecked::next(first);
+ return dist;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result)
+ {
+ while (start != end) {
+ uint32_t cp = utf8::internal::mask16(*start++);
+ // Take care of surrogate pairs first
+ if (utf8::internal::is_lead_surrogate(cp)) {
+ uint32_t trail_surrogate = utf8::internal::mask16(*start++);
+ cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET;
+ }
+ result = utf8::unchecked::append(cp, result);
+ }
+ return result;
+ }
+
+ template <typename u16bit_iterator, typename octet_iterator>
+ u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result)
+ {
+ while (start < end) {
+ uint32_t cp = utf8::unchecked::next(start);
+ if (cp > 0xffff) { //make a surrogate pair
+ *result++ = static_cast<uint16_t>((cp >> 10) + internal::LEAD_OFFSET);
+ *result++ = static_cast<uint16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN);
+ }
+ else
+ *result++ = static_cast<uint16_t>(cp);
+ }
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result)
+ {
+ while (start != end)
+ result = utf8::unchecked::append(*(start++), result);
+
+ return result;
+ }
+
+ template <typename octet_iterator, typename u32bit_iterator>
+ u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result)
+ {
+ while (start < end)
+ (*result++) = utf8::unchecked::next(start);
+
+ return result;
+ }
+
+ // The iterator class
+ template <typename octet_iterator>
+ class iterator {
+ octet_iterator it;
+ public:
+ typedef uint32_t value_type;
+ typedef uint32_t* pointer;
+ typedef uint32_t& reference;
+ typedef std::ptrdiff_t difference_type;
+ typedef std::bidirectional_iterator_tag iterator_category;
+ iterator () {}
+ explicit iterator (const octet_iterator& octet_it): it(octet_it) {}
+ // the default "big three" are OK
+ octet_iterator base () const { return it; }
+ uint32_t operator * () const
+ {
+ octet_iterator temp = it;
+ return utf8::unchecked::next(temp);
+ }
+ bool operator == (const iterator& rhs) const
+ {
+ return (it == rhs.it);
+ }
+ bool operator != (const iterator& rhs) const
+ {
+ return !(operator == (rhs));
+ }
+ iterator& operator ++ ()
+ {
+ ::std::advance(it, utf8::internal::sequence_length(it));
+ return *this;
+ }
+ iterator operator ++ (int)
+ {
+ iterator temp = *this;
+ ::std::advance(it, utf8::internal::sequence_length(it));
+ return temp;
+ }
+ iterator& operator -- ()
+ {
+ utf8::unchecked::prior(it);
+ return *this;
+ }
+ iterator operator -- (int)
+ {
+ iterator temp = *this;
+ utf8::unchecked::prior(it);
+ return temp;
+ }
+ }; // class iterator
+
+ } // namespace utf8::unchecked
+} // namespace utf8
+
+
+#endif // header guard
+
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/tests/CMakeLists.txt b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/CMakeLists.txt
new file mode 100644
index 0000000000..4063df7c67
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/CMakeLists.txt
@@ -0,0 +1,47 @@
+add_executable(negative ${PROJECT_SOURCE_DIR}/tests/negative.cpp)
+add_executable(cpp11 ${PROJECT_SOURCE_DIR}/tests/test_cpp11.cpp)
+add_executable(cpp17 ${PROJECT_SOURCE_DIR}/tests/test_cpp17.cpp)
+add_executable(apitests
+ ${PROJECT_SOURCE_DIR}/tests/test_checked_api.cpp
+ ${PROJECT_SOURCE_DIR}/tests/test_unchecked_api.cpp
+ ${PROJECT_SOURCE_DIR}/tests/test_checked_iterator.cpp
+ ${PROJECT_SOURCE_DIR}/tests/test_unchecked_iterator.cpp
+)
+
+add_executable(noexceptionstests
+ ${PROJECT_SOURCE_DIR}/tests/test_unchecked_api.cpp
+ ${PROJECT_SOURCE_DIR}/tests/test_unchecked_iterator.cpp
+)
+
+target_link_libraries(negative PRIVATE utf8::cpp)
+target_link_libraries(cpp11 PRIVATE utf8::cpp)
+target_link_libraries(cpp17 PRIVATE utf8::cpp)
+target_link_libraries(apitests PRIVATE utf8::cpp)
+target_link_libraries(noexceptionstests PRIVATE utf8::cpp)
+
+target_compile_options(noexceptionstests PUBLIC -fno-exceptions)
+
+set_target_properties(negative apitests noexceptionstests
+ PROPERTIES
+ CXX_STANDARD 98
+ CXX_STANDARD_REQUIRED YES
+ CXX_EXTENSIONS NO)
+
+set_target_properties(cpp11
+ PROPERTIES
+ CXX_STANDARD 11
+ CXX_STANDARD_REQUIRED YES
+ CXX_EXTENSIONS NO)
+
+set_target_properties(cpp17
+ PROPERTIES
+ CXX_STANDARD 17
+ CXX_STANDARD_REQUIRED YES
+ CXX_EXTENSIONS NO)
+
+add_test(negative_test negative ${PROJECT_SOURCE_DIR}/tests/test_data/utf8_invalid.txt)
+add_test(cpp11_test cpp11)
+add_test(cpp17_test cpp17)
+add_test(api_test apitests)
+add_test(noexceptions_test noexceptionstests)
+
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/tests/docker/Dockerfile b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/docker/Dockerfile
new file mode 100644
index 0000000000..9df3717a1d
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/docker/Dockerfile
@@ -0,0 +1,5 @@
+FROM debian:buster-slim
+
+RUN apt-get update \
+ && apt-get install -y make g++ cmake git \
+ && rm -rf /var/lib/apt/lists/*
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/tests/negative.cpp b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/negative.cpp
new file mode 100644
index 0000000000..f1bcc993e0
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/negative.cpp
@@ -0,0 +1,59 @@
+#include "utf8.h"
+using namespace utf8;
+
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <algorithm>
+using namespace std;
+
+const unsigned INVALID_LINES[] = { 75, 76, 83, 84, 85, 93, 102, 103, 105, 106, 107, 108, 109, 110, 114, 115, 116, 117, 124, 125, 130, 135, 140, 145, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 169, 175, 176, 177, 207, 208, 209, 210, 211, 220, 221, 222, 223, 224, 232, 233, 234, 235, 236, 247, 248, 249, 250, 251, 252, 253, 257, 258, 259, 260, 261, 262, 263, 264};
+const unsigned* INVALID_LINES_END = INVALID_LINES + sizeof(INVALID_LINES)/sizeof(unsigned);
+
+int main(int argc, char** argv)
+{
+ string test_file_path;
+ if (argc == 2)
+ test_file_path = argv[1];
+ else {
+ cout << "Wrong number of arguments" << endl;
+ return 1;
+ }
+ // Open the test file
+ ifstream fs8(test_file_path.c_str());
+ if (!fs8.is_open()) {
+ cout << "Could not open " << test_file_path << endl;
+ return 1;
+ }
+
+ // Read it line by line
+ unsigned int line_count = 0;
+ char byte;
+ while (!fs8.eof()) {
+ string line;
+ while ((byte = static_cast<char>(fs8.get())) != '\n' && !fs8.eof())
+ line.push_back(byte);
+
+ line_count++;
+ bool expected_valid = (find(INVALID_LINES, INVALID_LINES_END, line_count) == INVALID_LINES_END);
+ // Print out lines that contain unexpected invalid UTF-8
+ if (!is_valid(line.begin(), line.end())) {
+ if (expected_valid) {
+ cout << "Unexpected invalid utf-8 at line " << line_count << '\n';
+ return 1;
+ }
+
+ // try fixing it:
+ string fixed_line;
+ replace_invalid(line.begin(), line.end(), back_inserter(fixed_line));
+ if (!is_valid(fixed_line.begin(), fixed_line.end())) {
+ cout << "replace_invalid() resulted in an invalid utf-8 at line " << line_count << '\n';
+ return 1;
+ }
+ }
+ else if (!expected_valid) {
+ cout << "Invalid utf-8 NOT detected at line " << line_count << '\n';
+ return 1;
+ }
+ }
+}
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_checked_api.cpp b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_checked_api.cpp
new file mode 100644
index 0000000000..b57e1bc894
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_checked_api.cpp
@@ -0,0 +1,189 @@
+#define F_TEST_NO_MAIN
+#include "../extern/ftest/ftest.h"
+#include "utf8.h"
+
+#include <string>
+#include <vector>
+using namespace utf8;
+using namespace std;
+
+
+TEST(CheckedAPITests, test_append)
+{
+ unsigned char u[5] = {0,0,0,0,0};
+ append(0x0448, u);
+ EXPECT_EQ (u[0], 0xd1);
+ EXPECT_EQ (u[1], 0x88);
+ EXPECT_EQ (u[2], 0);
+ EXPECT_EQ (u[3], 0);
+ EXPECT_EQ (u[4], 0);
+
+ append(0x65e5, u);
+ EXPECT_EQ (u[0], 0xe6);
+ EXPECT_EQ (u[1], 0x97);
+ EXPECT_EQ (u[2], 0xa5);
+ EXPECT_EQ (u[3], 0);
+ EXPECT_EQ (u[4], 0);
+
+ append(0x3044, u);
+ EXPECT_EQ (u[0], 0xe3);
+ EXPECT_EQ (u[1], 0x81);
+ EXPECT_EQ (u[2], 0x84);
+ EXPECT_EQ (u[3], 0);
+ EXPECT_EQ (u[4], 0);
+
+ append(0x10346, u);
+ EXPECT_EQ (u[0], 0xf0);
+ EXPECT_EQ (u[1], 0x90);
+ EXPECT_EQ (u[2], 0x8d);
+ EXPECT_EQ (u[3], 0x86);
+ EXPECT_EQ (u[4], 0);
+}
+
+TEST(CheckedAPITests, test_next)
+{
+ const char* twochars = "\xe6\x97\xa5\xd1\x88";
+ const char* w = twochars;
+ int cp = next(w, twochars + 6);
+ EXPECT_EQ (cp, 0x65e5);
+ EXPECT_EQ (w, twochars + 3);
+
+ const char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ w = threechars;
+
+ cp = next(w, threechars + 9);
+ EXPECT_EQ (cp, 0x10346);
+ EXPECT_EQ (w, threechars + 4);
+
+ cp = next(w, threechars + 9);
+ EXPECT_EQ (cp, 0x65e5);
+ EXPECT_EQ (w, threechars + 7);
+
+ cp = next(w, threechars + 9);
+ EXPECT_EQ (cp, 0x0448);
+ EXPECT_EQ (w, threechars + 9);
+}
+
+TEST(CheckedAPITests, test_peek_next)
+{
+ const char* const cw = "\xe6\x97\xa5\xd1\x88";
+ int cp = peek_next(cw, cw + 6);
+ EXPECT_EQ (cp, 0x65e5);
+}
+
+TEST(CheckedAPITests, test_prior)
+{
+ const char* twochars = "\xe6\x97\xa5\xd1\x88";
+ const char* w = twochars + 3;
+ int cp = prior (w, twochars);
+ EXPECT_EQ (cp, 0x65e5);
+ EXPECT_EQ (w, twochars);
+
+ const char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ w = threechars + 9;
+ cp = prior(w, threechars);
+ EXPECT_EQ (cp, 0x0448);
+ EXPECT_EQ (w, threechars + 7);
+ cp = prior(w, threechars);
+ EXPECT_EQ (cp, 0x65e5);
+ EXPECT_EQ (w, threechars + 4);
+ cp = prior(w, threechars);
+ EXPECT_EQ (cp, 0x10346);
+ EXPECT_EQ (w, threechars);
+}
+
+TEST(CheckedAPITests, test_advance)
+{
+ const char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ const char* w = threechars;
+ advance(w, 2, threechars + 9);
+ EXPECT_EQ(w, threechars + 7);
+ advance(w, -2, threechars);
+ EXPECT_EQ(w, threechars);
+ advance(w, 3, threechars + 9);
+ EXPECT_EQ(w, threechars + 9);
+ advance(w, -2, threechars);
+ EXPECT_EQ(w, threechars + 4);
+ advance(w, -1, threechars);
+ EXPECT_EQ(w, threechars);
+}
+
+TEST(CheckedAPITests, test_distance)
+{
+ const char* twochars = "\xe6\x97\xa5\xd1\x88";
+ size_t dist = utf8::distance(twochars, twochars + 5);
+ EXPECT_EQ (dist, 2);
+}
+
+TEST(CheckedAPITests, test_utf32to8)
+{
+ int utf32string[] = {0x448, 0x65E5, 0x10346, 0};
+ string utf8result;
+ utf32to8(utf32string, utf32string + 3, back_inserter(utf8result));
+ EXPECT_EQ (utf8result.size(), 9);
+}
+
+TEST(CheckedAPITests, test_utf8to32)
+{
+ const char* twochars = "\xe6\x97\xa5\xd1\x88";
+ vector<int> utf32result;
+ utf8to32(twochars, twochars + 5, back_inserter(utf32result));
+ EXPECT_EQ (utf32result.size(), 2);
+}
+
+TEST(CheckedAPITests, test_utf16to8)
+{
+ unsigned short utf16string[] = {0x41, 0x0448, 0x65e5, 0xd834, 0xdd1e};
+ string utf8result;
+ utf16to8(utf16string, utf16string + 5, back_inserter(utf8result));
+ EXPECT_EQ (utf8result.size(), 10);
+}
+
+TEST(CheckedAPITests, test_utf8to16)
+{
+ char utf8_with_surrogates[] = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+ vector <unsigned short> utf16result;
+ utf8to16(utf8_with_surrogates, utf8_with_surrogates + 9, back_inserter(utf16result));
+ EXPECT_EQ (utf16result.size(), 4);
+ EXPECT_EQ (utf16result[2], 0xd834);
+ EXPECT_EQ (utf16result[3], 0xdd1e);
+}
+
+TEST(CheckedAPITests, test_replace_invalid)
+{
+ char invalid_sequence[] = "a\x80\xe0\xa0\xc0\xaf\xed\xa0\x80z";
+ vector<char> replace_invalid_result;
+ replace_invalid (invalid_sequence, invalid_sequence + sizeof(invalid_sequence), std::back_inserter(replace_invalid_result), '?');
+ bool bvalid = is_valid(replace_invalid_result.begin(), replace_invalid_result.end());
+ EXPECT_TRUE (bvalid);
+ const char fixed_invalid_sequence[] = "a????z";
+ EXPECT_EQ (sizeof(fixed_invalid_sequence), replace_invalid_result.size());
+ EXPECT_TRUE (std::equal(replace_invalid_result.begin(), replace_invalid_result.begin() + sizeof(fixed_invalid_sequence), fixed_invalid_sequence));
+}
+
+TEST(CheckedAPITests, test_find_invalid)
+{
+ char utf_invalid[] = "\xe6\x97\xa5\xd1\x88\xfa";
+ char* invalid = find_invalid(utf_invalid, utf_invalid + 6);
+ EXPECT_EQ (invalid, utf_invalid + 5);
+}
+
+TEST(CheckedAPITests, test_is_valid)
+{
+ char utf_invalid[] = "\xe6\x97\xa5\xd1\x88\xfa";
+ bool bvalid = is_valid(utf_invalid, utf_invalid + 6);
+ EXPECT_FALSE (bvalid);
+ char utf8_with_surrogates[] = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+ bvalid = is_valid(utf8_with_surrogates, utf8_with_surrogates + 9);
+ EXPECT_TRUE (bvalid);
+}
+
+TEST(CheckedAPITests, test_starts_with_bom)
+{
+ unsigned char byte_order_mark[] = {0xef, 0xbb, 0xbf};
+ bool bbom = starts_with_bom(byte_order_mark, byte_order_mark + sizeof(byte_order_mark));
+ EXPECT_TRUE (bbom);
+ const char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ bool no_bbom = starts_with_bom(threechars, threechars + sizeof(threechars));
+ EXPECT_FALSE (no_bbom);
+}
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_checked_iterator.cpp b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_checked_iterator.cpp
new file mode 100644
index 0000000000..3f9bfe96a2
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_checked_iterator.cpp
@@ -0,0 +1,32 @@
+#define F_TEST_NO_MAIN
+#include "../extern/ftest/ftest.h"
+#include "utf8.h"
+
+using namespace utf8;
+
+
+TEST(CheckedIteratrTests, test_increment)
+{
+ const char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ utf8::iterator<const char*> it(threechars, threechars, threechars + 9);
+ utf8::iterator<const char*> it2 = it;
+ EXPECT_EQ (it2, it);
+ EXPECT_EQ (*it, 0x10346);
+ EXPECT_EQ (*(++it), 0x65e5);
+ EXPECT_EQ ((*it++), 0x65e5);
+ EXPECT_EQ (*it, 0x0448);
+ EXPECT_NE (it, it2);
+ utf8::iterator<const char*> endit (threechars + 9, threechars, threechars + 9);
+ EXPECT_EQ (++it, endit);
+}
+
+TEST(CheckedIteratrTests, test_decrement)
+{
+ const char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ utf8::iterator<const char*> it(threechars+9, threechars, threechars + 9);
+ EXPECT_EQ (*(--it), 0x0448);
+ EXPECT_EQ ((*it--), 0x0448);
+ EXPECT_EQ (*it, 0x65e5);
+ EXPECT_EQ (--it, utf8::iterator<const char*>(threechars, threechars, threechars + 9));
+ EXPECT_EQ (*it, 0x10346);
+}
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_cpp11.cpp b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_cpp11.cpp
new file mode 100644
index 0000000000..ee4ddd8fd6
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_cpp11.cpp
@@ -0,0 +1,109 @@
+#include "../extern/ftest/ftest.h"
+#include "utf8.h"
+#include <string>
+using namespace utf8;
+using namespace std;
+
+#if __cplusplus >= 201103L // C++ 11 or later
+
+TEST(CPP11APITests, test_append)
+{
+ string u;
+ append(0x0448, u);
+ EXPECT_EQ (u[0], char(0xd1));
+ EXPECT_EQ (u[1], char(0x88));
+ EXPECT_EQ (u.length(), 2);
+
+ u.clear();
+ append(0x65e5, u);
+ EXPECT_EQ (u[0], char(0xe6));
+ EXPECT_EQ (u[1], char(0x97));
+ EXPECT_EQ (u[2], char(0xa5));
+ EXPECT_EQ (u.length(), 3);
+
+ u.clear();
+ append(0x3044, u);
+ EXPECT_EQ (u[0], char(0xe3));
+ EXPECT_EQ (u[1], char(0x81));
+ EXPECT_EQ (u[2], char(0x84));
+ EXPECT_EQ (u.length(), 3);
+
+ u.clear();
+ append(0x10346, u);
+ EXPECT_EQ (u[0], char(0xf0));
+ EXPECT_EQ (u[1], char(0x90));
+ EXPECT_EQ (u[2], char(0x8d));
+ EXPECT_EQ (u[3], char(0x86));
+ EXPECT_EQ (u.length(), 4);
+}
+
+TEST(CPP11APITests, test_utf16to8)
+{
+ u16string utf16string = {0x41, 0x0448, 0x65e5, 0xd834, 0xdd1e};
+ string u = utf16to8(utf16string);
+ EXPECT_EQ (u.size(), 10);
+}
+
+TEST(CPP11APITests, test_utf8to16)
+{
+ string utf8_with_surrogates = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+ u16string utf16result = utf8to16(utf8_with_surrogates);
+ EXPECT_EQ (utf16result.size(), 4);
+ EXPECT_EQ (utf16result[2], 0xd834);
+ EXPECT_EQ (utf16result[3], 0xdd1e);
+ // Just to make sure it compiles with string literals
+ utf8to16(u8"simple");
+ utf8to16("simple");
+}
+
+TEST(CPP11APITests, test_utf32to8)
+{
+ u32string utf32string = {0x448, 0x65E5, 0x10346};
+ string utf8result = utf32to8(utf32string);
+ EXPECT_EQ (utf8result.size(), 9);
+}
+
+TEST(CPP11APITests, test_utf8to32)
+{
+ const char* twochars = "\xe6\x97\xa5\xd1\x88";
+ u32string utf32result = utf8to32(twochars);
+ EXPECT_EQ (utf32result.size(), 2);
+}
+
+TEST(CPP11APITests, test_find_invalid)
+{
+ string utf_invalid = "\xe6\x97\xa5\xd1\x88\xfa";
+ auto invalid = find_invalid(utf_invalid);
+ EXPECT_EQ (invalid, 5);
+}
+
+TEST(CPP11APITests, test_is_valid)
+{
+ string utf_invalid = "\xe6\x97\xa5\xd1\x88\xfa";
+ bool bvalid = is_valid(utf_invalid);
+ EXPECT_FALSE (bvalid);
+ string utf8_with_surrogates = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+ bvalid = is_valid(utf8_with_surrogates);
+ EXPECT_TRUE (bvalid);
+}
+
+TEST(CPP11APITests, test_replace_invalid)
+{
+ string invalid_sequence = "a\x80\xe0\xa0\xc0\xaf\xed\xa0\x80z";
+ string replace_invalid_result = replace_invalid(invalid_sequence, '?');
+ bool bvalid = is_valid(replace_invalid_result);
+ EXPECT_TRUE (bvalid);
+ const string fixed_invalid_sequence = "a????z";
+ EXPECT_EQ(fixed_invalid_sequence, replace_invalid_result);
+}
+
+TEST(CPP11APITests, test_starts_with_bom)
+{
+ string byte_order_mark = {char(0xef), char(0xbb), char(0xbf)};
+ bool bbom = starts_with_bom(byte_order_mark);
+ EXPECT_TRUE (bbom);
+ string threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ bool no_bbom = starts_with_bom(threechars);
+ EXPECT_FALSE (no_bbom);
+}
+#endif // C++ 11 or later
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_cpp17.cpp b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_cpp17.cpp
new file mode 100644
index 0000000000..4b87816b1c
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_cpp17.cpp
@@ -0,0 +1,88 @@
+#include "../extern/ftest/ftest.h"
+#include "utf8.h"
+#include <string>
+using namespace utf8;
+using namespace std;
+
+#if __cplusplus >= 201703L // C++ 17 or later
+
+
+TEST(CPP17APITests, test_utf16to8)
+{
+ u16string utf16string = {0x41, 0x0448, 0x65e5, 0xd834, 0xdd1e};
+ u16string_view utf16stringview(u16string);
+ string u = utf16to8(utf16string);
+ EXPECT_EQ (u.size(), 10);
+}
+
+TEST(CPP17APITests, test_utf8to16)
+{
+ string_view utf8_with_surrogates = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+ u16string utf16result = utf8to16(utf8_with_surrogates);
+ EXPECT_EQ (utf16result.size(), 4);
+ EXPECT_EQ (utf16result[2], 0xd834);
+ EXPECT_EQ (utf16result[3], 0xdd1e);
+}
+
+TEST(CPP17APITests, test_utf32to8)
+{
+ u32string utf32string = {0x448, 0x65E5, 0x10346};
+ u32string_view utf32stringview(utf32string);
+ string utf8result = utf32to8(utf32stringview);
+ EXPECT_EQ (utf8result.size(), 9);
+}
+
+TEST(CPP17APITests, test_utf8to32)
+{
+ string_view twochars = "\xe6\x97\xa5\xd1\x88";
+ u32string utf32result = utf8to32(twochars);
+ EXPECT_EQ (utf32result.size(), 2);
+}
+
+TEST(CPP17APITests, test_find_invalid)
+{
+ string_view utf_invalid = "\xe6\x97\xa5\xd1\x88\xfa";
+ auto invalid = find_invalid(utf_invalid);
+ EXPECT_EQ (invalid, 5);
+}
+
+TEST(CPP17APITests, test_is_valid)
+{
+ string_view utf_invalid = "\xe6\x97\xa5\xd1\x88\xfa";
+ bool bvalid = is_valid(utf_invalid);
+ EXPECT_FALSE (bvalid);
+ string_view utf8_with_surrogates = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+ bvalid = is_valid(utf8_with_surrogates);
+ EXPECT_TRUE (bvalid);
+}
+
+TEST(CPP17APITests, test_replace_invalid)
+{
+ string_view invalid_sequence = "a\x80\xe0\xa0\xc0\xaf\xed\xa0\x80z";
+ string replace_invalid_result = replace_invalid(invalid_sequence, '?');
+ bool bvalid = is_valid(replace_invalid_result);
+ EXPECT_TRUE (bvalid);
+ const string fixed_invalid_sequence = "a????z";
+ EXPECT_EQ(fixed_invalid_sequence, replace_invalid_result);
+}
+
+TEST(CPP17APITests, test_starts_with_bom)
+{
+ string byte_order_mark = {char(0xef), char(0xbb), char(0xbf)};
+ string_view byte_order_mark_view(byte_order_mark);
+ bool bbom = starts_with_bom(byte_order_mark_view);
+ EXPECT_TRUE (bbom);
+ string_view threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ bool no_bbom = starts_with_bom(threechars);
+ EXPECT_FALSE (no_bbom);
+}
+
+TEST(CPP17APITests, string_class_and_literals)
+{
+ const char* twochars = u8"ab";
+ EXPECT_TRUE (is_valid(twochars));
+ const string two_chars_string(twochars);
+ EXPECT_TRUE (is_valid(two_chars_string));
+}
+
+#endif // C++ 11 or later
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_data/utf8_invalid.txt b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_data/utf8_invalid.txt
new file mode 100644
index 0000000000..ae83159328
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_data/utf8_invalid.txt
Binary files differ
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_unchecked_api.cpp b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_unchecked_api.cpp
new file mode 100644
index 0000000000..c400ada0d2
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_unchecked_api.cpp
@@ -0,0 +1,161 @@
+#include "../extern/ftest/ftest.h"
+#include "utf8/unchecked.h"
+
+#include <string>
+#include <vector>
+using namespace utf8::unchecked;
+using namespace std;
+
+TEST(UnCheckedAPITests, test_append)
+{
+ unsigned char u[5] = {0,0,0,0,0};
+ append(0x0448, u);
+ EXPECT_EQ (u[0], 0xd1);
+ EXPECT_EQ (u[1], 0x88);
+ EXPECT_EQ (u[2], 0);
+ EXPECT_EQ (u[3], 0);
+ EXPECT_EQ (u[4], 0);
+
+ append(0x65e5, u);
+ EXPECT_EQ (u[0], 0xe6);
+ EXPECT_EQ (u[1], 0x97);
+ EXPECT_EQ (u[2], 0xa5);
+ EXPECT_EQ (u[3], 0);
+ EXPECT_EQ (u[4], 0);
+
+ append(0x3044, u);
+ EXPECT_EQ (u[0], 0xe3);
+ EXPECT_EQ (u[1], 0x81);
+ EXPECT_EQ (u[2], 0x84);
+ EXPECT_EQ (u[3], 0);
+ EXPECT_EQ (u[4], 0);
+
+ append(0x10346, u);
+ EXPECT_EQ (u[0], 0xf0);
+ EXPECT_EQ (u[1], 0x90);
+ EXPECT_EQ (u[2], 0x8d);
+ EXPECT_EQ (u[3], 0x86);
+ EXPECT_EQ (u[4], 0);
+}
+
+TEST(UnCheckedAPITests, test_next)
+{
+ const char* twochars = "\xe6\x97\xa5\xd1\x88";
+ const char* w = twochars;
+ int cp = utf8::unchecked::next(w);
+ EXPECT_EQ (cp, 0x65e5);
+ EXPECT_EQ (w, twochars + 3);
+
+ const char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ w = threechars;
+
+ cp = utf8::unchecked::next(w);
+ EXPECT_EQ (cp, 0x10346);
+ EXPECT_EQ (w, threechars + 4);
+
+ cp = utf8::unchecked::next(w);
+ EXPECT_EQ (cp, 0x65e5);
+ EXPECT_EQ (w, threechars + 7);
+
+ cp = utf8::unchecked::next(w);
+ EXPECT_EQ (cp, 0x0448);
+ EXPECT_EQ (w, threechars + 9);
+}
+
+TEST(UnCheckedAPITests, test_peek_next)
+{
+ const char* const cw = "\xe6\x97\xa5\xd1\x88";
+ int cp = peek_next(cw);
+ EXPECT_EQ (cp, 0x65e5);
+}
+
+TEST(UnCheckedAPITests, test_prior)
+{
+ const char* twochars = "\xe6\x97\xa5\xd1\x88";
+ const char* w = twochars + 3;
+ int cp = prior (w);
+ EXPECT_EQ (cp, 0x65e5);
+ EXPECT_EQ (w, twochars);
+
+ const char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ w = threechars + 9;
+ cp = prior(w);
+ EXPECT_EQ (cp, 0x0448);
+ EXPECT_EQ (w, threechars + 7);
+ cp = prior(w);
+ EXPECT_EQ (cp, 0x65e5);
+ EXPECT_EQ (w, threechars + 4);
+ cp = prior(w);
+ EXPECT_EQ (cp, 0x10346);
+ EXPECT_EQ (w, threechars);
+}
+
+TEST(UnCheckedAPITests, test_advance)
+{
+ const char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ const char* w = threechars;
+ utf8::unchecked::advance(w, 2);
+ EXPECT_EQ(w, threechars + 7);
+ utf8::unchecked::advance(w, -2);
+ EXPECT_EQ(w, threechars);
+ utf8::unchecked::advance(w, 3);
+ EXPECT_EQ(w, threechars + 9);
+ utf8::unchecked::advance(w, -2);
+ EXPECT_EQ(w, threechars + 4);
+ utf8::unchecked::advance(w, -1);
+ EXPECT_EQ(w, threechars);
+}
+
+TEST(UnCheckedAPITests, test_distance)
+{
+ const char* twochars = "\xe6\x97\xa5\xd1\x88";
+ size_t dist = utf8::unchecked::distance(twochars, twochars + 5);
+ EXPECT_EQ (dist, 2);
+}
+
+TEST(UnCheckedAPITests, test_utf32to8)
+{
+ int utf32string[] = {0x448, 0x65E5, 0x10346, 0};
+ string utf8result;
+ utf32to8(utf32string, utf32string + 3, back_inserter(utf8result));
+ EXPECT_EQ (utf8result.size(), 9);
+}
+
+TEST(UnCheckedAPITests, test_utf8to32)
+{
+ const char* twochars = "\xe6\x97\xa5\xd1\x88";
+ vector<int> utf32result;
+ utf8to32(twochars, twochars + 5, back_inserter(utf32result));
+ EXPECT_EQ (utf32result.size(), 2);
+}
+
+TEST(UnCheckedAPITests, test_utf16to8)
+{
+ unsigned short utf16string[] = {0x41, 0x0448, 0x65e5, 0xd834, 0xdd1e};
+ string utf8result;
+ utf16to8(utf16string, utf16string + 5, back_inserter(utf8result));
+ EXPECT_EQ (utf8result.size(), 10);
+}
+
+TEST(UnCheckedAPITests, test_utf8to16)
+{
+ char utf8_with_surrogates[] = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+ vector <unsigned short> utf16result;
+ utf8to16(utf8_with_surrogates, utf8_with_surrogates + 9, back_inserter(utf16result));
+ EXPECT_EQ (utf16result.size(), 4);
+ EXPECT_EQ (utf16result[2], 0xd834);
+ EXPECT_EQ (utf16result[3], 0xdd1e);
+}
+
+TEST(UnCheckedAPITests, test_replace_invalid)
+{
+ char invalid_sequence[] = "a\x80\xe0\xa0\xc0\xaf\xed\xa0\x80z";
+ vector<char> replace_invalid_result;
+ replace_invalid (invalid_sequence, invalid_sequence + sizeof(invalid_sequence), std::back_inserter(replace_invalid_result), '?');
+ bool bvalid = utf8::is_valid(replace_invalid_result.begin(), replace_invalid_result.end());
+ EXPECT_TRUE (bvalid);
+ const char fixed_invalid_sequence[] = "a????z";
+ EXPECT_EQ (sizeof(fixed_invalid_sequence), replace_invalid_result.size());
+ EXPECT_TRUE (std::equal(replace_invalid_result.begin(), replace_invalid_result.begin() + sizeof(fixed_invalid_sequence), fixed_invalid_sequence));
+}
+
diff --git a/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_unchecked_iterator.cpp b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_unchecked_iterator.cpp
new file mode 100644
index 0000000000..68943bf94c
--- /dev/null
+++ b/graphics/asymptote/LspCpp/third_party/utfcpp/tests/test_unchecked_iterator.cpp
@@ -0,0 +1,34 @@
+#define F_TEST_NO_MAIN
+#include "../extern/ftest/ftest.h"
+
+#include "utf8/unchecked.h"
+
+using namespace utf8::unchecked;
+
+
+TEST(UnCheckedIteratrTests, test_increment)
+{
+ const char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ utf8::unchecked::iterator<const char*> it(threechars);
+ utf8::unchecked::iterator<const char*> it2 = it;
+ EXPECT_EQ (it2, it);
+ EXPECT_EQ (*it, 0x10346);
+ EXPECT_EQ (*(++it), 0x65e5);
+ EXPECT_EQ ((*it++), 0x65e5);
+ EXPECT_EQ (*it, 0x0448);
+ EXPECT_NE (it, it2);
+ utf8::unchecked::iterator<const char*> endit (threechars + 9);
+ EXPECT_EQ (++it, endit);
+}
+
+TEST(UnCheckedIteratrTests, test_decrement)
+{
+ const char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+ utf8::unchecked::iterator<const char*> it(threechars+9);
+ EXPECT_EQ (*(--it), 0x0448);
+ EXPECT_EQ ((*it--), 0x0448);
+ EXPECT_EQ (*it, 0x65e5);
+ EXPECT_EQ (--it, utf8::unchecked::iterator<const char*>(threechars));
+ EXPECT_EQ (*it, 0x10346);
+
+}