summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/nowide
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
commit19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch)
tree42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/boost/libs/nowide
parentInitial commit. (diff)
downloadceph-6d07fdb6bb33b1af39833b850bb6cf8af79fe293.tar.xz
ceph-6d07fdb6bb33b1af39833b850bb6cf8af79fe293.zip
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/nowide')
-rw-r--r--src/boost/libs/nowide/CMakeLists.txt73
-rw-r--r--src/boost/libs/nowide/Config.cmake.in20
-rw-r--r--src/boost/libs/nowide/LICENSE23
-rw-r--r--src/boost/libs/nowide/README.md82
-rw-r--r--src/boost/libs/nowide/build/Jamfile.v224
-rw-r--r--src/boost/libs/nowide/cmake/BoostAddOptions.cmake14
-rw-r--r--src/boost/libs/nowide/cmake/BoostAddWarnings.cmake43
-rw-r--r--src/boost/libs/nowide/cmake/InstallTargets.cmake73
-rw-r--r--src/boost/libs/nowide/codecov.yml10
-rw-r--r--src/boost/libs/nowide/index.html16
-rw-r--r--src/boost/libs/nowide/meta/libraries.json11
-rw-r--r--src/boost/libs/nowide/src/cstdio.cpp74
-rw-r--r--src/boost/libs/nowide/src/cstdlib.cpp121
-rw-r--r--src/boost/libs/nowide/src/iostream.cpp270
-rw-r--r--src/boost/libs/nowide/standalone/config.hpp81
-rw-r--r--src/boost/libs/nowide/standalone/cstdint.hpp12
-rw-r--r--src/boost/libs/nowide/standalone/scoped_ptr.hpp87
-rw-r--r--src/boost/libs/nowide/standalone/static_assert.hpp7
-rw-r--r--src/boost/libs/nowide/test/CMakeLists.txt38
-rw-r--r--src/boost/libs/nowide/test/Jamfile.v239
-rw-r--r--src/boost/libs/nowide/test/benchmark_fstream.cpp273
-rw-r--r--src/boost/libs/nowide/test/exampleProject/CMakeLists.txt10
-rw-r--r--src/boost/libs/nowide/test/exampleProject/example_main.cpp20
-rw-r--r--src/boost/libs/nowide/test/test.hpp109
-rw-r--r--src/boost/libs/nowide/test/test_codecvt.cpp328
-rw-r--r--src/boost/libs/nowide/test/test_convert.cpp118
-rw-r--r--src/boost/libs/nowide/test/test_env.cpp57
-rw-r--r--src/boost/libs/nowide/test/test_fs.cpp61
-rw-r--r--src/boost/libs/nowide/test/test_fstream.cpp513
-rw-r--r--src/boost/libs/nowide/test/test_fstream_cxx11.cpp201
-rw-r--r--src/boost/libs/nowide/test/test_iostream.cpp87
-rw-r--r--src/boost/libs/nowide/test/test_sets.hpp135
-rw-r--r--src/boost/libs/nowide/test/test_stackstring.cpp256
-rw-r--r--src/boost/libs/nowide/test/test_stdio.cpp144
-rw-r--r--src/boost/libs/nowide/test/test_system.cpp178
-rw-r--r--src/boost/libs/nowide/tools/create_standalone.sh66
36 files changed, 3674 insertions, 0 deletions
diff --git a/src/boost/libs/nowide/CMakeLists.txt b/src/boost/libs/nowide/CMakeLists.txt
new file mode 100644
index 000000000..aec107828
--- /dev/null
+++ b/src/boost/libs/nowide/CMakeLists.txt
@@ -0,0 +1,73 @@
+# Builds the libraries for Boost.Nowide
+#
+# Options:
+# Boost_NOWIDE_INSTALL
+# Boost_NOWIDE_WERROR
+# BUILD_TESTING
+#
+# Created target: Boost::nowide
+#
+# When not using CMake to link against the shared library on windows define -DBOOST_NOWIDE_DYN_LINK
+
+cmake_minimum_required(VERSION 3.9)
+# Version number starts at 10 to avoid conflicts with Boost version
+set(_version 10.0.1)
+if(BOOST_SUPERPROJECT_SOURCE_DIR)
+ set(_version ${BOOST_SUPERPROJECT_VERSION})
+endif()
+project(boost_nowide VERSION ${_version} LANGUAGES CXX)
+
+if(POLICY CMP0074)
+ cmake_policy(SET CMP0074 NEW)
+endif()
+
+list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
+
+if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
+ # Make sure all binarys (especially exe/dll) are in one directory for tests to work
+ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+endif()
+
+include(BoostAddOptions)
+include(BoostAddWarnings)
+if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
+ include(CTest)
+endif()
+
+# Using glob here is ok as it is only for headers
+file(GLOB_RECURSE headers include/*.hpp)
+add_library(boost_nowide src/cstdio.cpp src/cstdlib.cpp src/iostream.cpp ${headers})
+add_library(Boost::nowide ALIAS boost_nowide)
+set_target_properties(boost_nowide PROPERTIES
+ CXX_VISIBILITY_PRESET hidden
+ VISIBILITY_INLINES_HIDDEN ON
+ VERSION ${PROJECT_VERSION}
+ EXPORT_NAME nowide
+)
+if(BUILD_SHARED_LIBS)
+ target_compile_definitions(boost_nowide PUBLIC BOOST_NOWIDE_DYN_LINK)
+endif()
+target_compile_definitions(boost_nowide PUBLIC BOOST_NOWIDE_NO_LIB)
+target_include_directories(boost_nowide PUBLIC include)
+boost_add_warnings(boost_nowide pedantic ${Boost_NOWIDE_WERROR})
+
+if(BOOST_SUPERPROJECT_SOURCE_DIR)
+ target_link_libraries(boost_nowide PUBLIC Boost::config Boost::smart_ptr Boost::static_assert)
+ set(Boost_NOWIDE_INSTALL OFF) # smart_ptr does not support installation
+else()
+ # Default boost libs are static on windows and dynamic on linux
+ if(WIN32 AND NOT DEFINED Boost_USE_STATIC_LIBS)
+ set(Boost_USE_STATIC_LIBS ON)
+ endif()
+ find_package(Boost 1.56 REQUIRED)
+ target_link_libraries(boost_nowide PUBLIC Boost::boost)
+endif()
+
+if(BUILD_TESTING)
+ add_subdirectory(test)
+endif()
+
+if(Boost_NOWIDE_INSTALL)
+ include(InstallTargets)
+ install_targets(TARGETS boost_nowide NAMESPACE Boost CONFIG_FILE ${PROJECT_SOURCE_DIR}/Config.cmake.in)
+endif()
diff --git a/src/boost/libs/nowide/Config.cmake.in b/src/boost/libs/nowide/Config.cmake.in
new file mode 100644
index 000000000..05dcc7bda
--- /dev/null
+++ b/src/boost/libs/nowide/Config.cmake.in
@@ -0,0 +1,20 @@
+@PACKAGE_INIT@
+
+set(_boost_nowide_superproject "@BOOST_SUPERPROJECT_SOURCE_DIR@")
+
+include(CMakeFindDependencyMacro)
+if(_boost_nowide_superproject)
+foreach(dep IN ITEMS boost_config boost_smart_ptr boost_static_assert)
+ find_dependency(${dep})
+endforeach()
+else()
+# Default boost libs are static on windows and dynamic on linux
+if(WIN32 AND "${Boost_USE_STATIC_LIBS}" STREQUAL "")
+ set(Boost_USE_STATIC_LIBS ON)
+endif()
+find_dependency(Boost 1.56)
+endif()
+
+include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
+
+check_required_components("@PROJECT_NAME@")
diff --git a/src/boost/libs/nowide/LICENSE b/src/boost/libs/nowide/LICENSE
new file mode 100644
index 000000000..36b7cd93c
--- /dev/null
+++ b/src/boost/libs/nowide/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/src/boost/libs/nowide/README.md b/src/boost/libs/nowide/README.md
new file mode 100644
index 000000000..7ac024f04
--- /dev/null
+++ b/src/boost/libs/nowide/README.md
@@ -0,0 +1,82 @@
+# Boost.Nowide
+
+Branch | Travis | Appveyor | Github | codecov.io | Documentation
+------------|--------|----------|--------|------------|--------------
+[master](https://github.com/boostorg/nowide/tree/master) | [![Build Status](https://travis-ci.com/boostorg/nowide.svg?branch=master)](https://travis-ci.com/boostorg/nowide) | [![Build status](https://ci.appveyor.com/api/projects/status/w5sywrekwd66say4/branch/master?svg=true)](https://ci.appveyor.com/project/Flamefire/nowide-fr98b/branch/master) | ![](https://github.com/boostorg/nowide/workflows/CI%20Tests/badge.svg?branch=master) | [![codecov](https://codecov.io/gh/boostorg/nowide/branch/master/graph/badge.svg)](https://codecov.io/gh/boostorg/nowide/branch/master) | [![Documentation](https://img.shields.io/badge/documentation-master-brightgreen.svg)](https://www.boost.org/doc/libs/master/libs/nowide/index.html)
+[develop](https://github.com/boostorg/nowide/tree/develop) | [![Build Status](https://travis-ci.com/boostorg/nowide.svg?branch=develop)](https://travis-ci.com/boostorg/nowide) | [![Build status](https://ci.appveyor.com/api/projects/status/w5sywrekwd66say4/branch/develop?svg=true)](https://ci.appveyor.com/project/Flamefire/nowide-fr98b/branch/develop) | ![](https://github.com/boostorg/nowide/workflows/CI%20Tests/badge.svg?branch=develop) | [![codecov](https://codecov.io/gh/boostorg/nowide/branch/develop/graph/badge.svg)](https://codecov.io/gh/boostorg/nowide/branch/develop) | [![Documentation](https://img.shields.io/badge/documentation-develop-brightgreen.svg)](https://www.boost.org/doc/libs/develop/libs/nowide/index.html)
+
+Coverity Scan: [![Coverity Scan Build Status](https://scan.coverity.com/projects/20464/badge.svg)](https://scan.coverity.com/projects/boostorg-nowide)
+
+Library for cross-platform, unicode aware programming.
+
+The library provides an implementation of standard C and C++ library functions, such that their inputs are UTF-8 aware on Windows without requiring to use the Wide API.
+
+### License
+
+Distributed under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt).
+
+### Properties
+
+* C++03 **(will be raised to C++11 by mid 2020)**
+* optional C++11/17 support
+* Usable outside of Boost via CMake
+
+# Quickstart
+
+Instead of using the standard library functions use the corresponding member of Boost.Nowide with the same name.
+On Linux those are (mostly) aliases for the `std` ones, but on Windows they accept UTF-8 as input and use the wide API for the underlying functionality.
+
+Examples:
+- `std::ifstream -> boost::nowide::ifstream`
+- `std::fopen -> boost::nowide::fopen`
+- `std::fclose -> boost::nowide::fclose`
+- `std::getenv -> boost::nowide::getenv`
+- `std::putenv -> boost::nowide::putenv`
+- `std::cout -> boost::nowide::cout`
+
+To also convert your input arguments to UTF-8 on Windows use:
+
+```
+int main(int argc, char **argv)
+{
+ boost::nowide::args _(argc, argv); // Must use an instance!
+ ...
+}
+```
+
+See the [Documentation](https://www.boost.org/doc/libs/master/libs/nowide/index.html) for details.
+
+# Compile
+
+## With Boost
+
+Compile and install the Boost super project the usual way via `./b2`.
+The headers and library will then be available together with all other Boost libraries.
+From within CMake you can then use `find_package(boost_nowide)` and link against `Boost::nowide`.
+
+## With CMake
+
+Boost.Nowide fully supports CMake.
+So you can use `add_subdirectory("path-to-boost-nowide-repo")` and link your project against the target `Boost::nowide`.
+
+You can also pre-compile and install Boost.Nowide via the usual workflow:
+```
+mkdir build && cd build
+cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local
+make install
+```
+
+A CMake-Config file will be installed alongside Boost.Nowide so `find_package(boost_nowide)` does work out-of the box
+(provided it was installed into a "standard" location or its `INSTALL_PREFIX` was added to `CMAKE_PREFIX_PATH`).
+
+# Boost.Filesystem integration
+
+Boost.Nowide integrates with Boost.Filesystem:
+- Call `boost::nowide::nowide_filesystem()` to imbue UTF-8 into Boost.Filesystem (for use by `boost::filesystem::path`) such that narrow strings passed into Boost.Filesystem are treated as UTF-8 on Windows
+
+### More information
+
+* [Ask questions](http://stackoverflow.com/questions/ask?tags=c%2B%2B,boost,boost-nowide)
+* [Report bugs](https://github.com/boostorg/nowide/issues): Be sure to mention Boost version, platform and compiler you're using. A small compilable code sample to reproduce the problem is always good as well.
+* Submit your patches as pull requests against **develop** branch. Note that by submitting patches you agree to license your modifications under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt).
+* Discussions about the library are held on the [Boost developers mailing list](http://www.boost.org/community/groups.html#main). Be sure to read the [discussion policy](http://www.boost.org/community/policy.html) before posting and add the `[nowide]` tag at the beginning of the subject line.
diff --git a/src/boost/libs/nowide/build/Jamfile.v2 b/src/boost/libs/nowide/build/Jamfile.v2
new file mode 100644
index 000000000..639492d41
--- /dev/null
+++ b/src/boost/libs/nowide/build/Jamfile.v2
@@ -0,0 +1,24 @@
+# Boost Nowide Library Build Jamfile
+
+# (C) Copyright Beman Dawes 2002, 2006, Artyom Beilis 2012
+#
+
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or www.boost.org/LICENSE_1_0.txt)
+
+# See library home page at http://www.boost.org/libs/nowide
+
+project boost/nowide
+ : source-location ../src
+ : usage-requirements # pass these requirement to dependents (i.e. users)
+ <link>shared:<define>BOOST_NOWIDE_DYN_LINK=1
+ ;
+
+SOURCES = cstdio cstdlib iostream ;
+
+lib boost_nowide
+ : $(SOURCES).cpp
+ : <link>shared:<define>BOOST_NOWIDE_DYN_LINK=1
+ ;
+
+boost-install boost_nowide ;
diff --git a/src/boost/libs/nowide/cmake/BoostAddOptions.cmake b/src/boost/libs/nowide/cmake/BoostAddOptions.cmake
new file mode 100644
index 000000000..079b21283
--- /dev/null
+++ b/src/boost/libs/nowide/cmake/BoostAddOptions.cmake
@@ -0,0 +1,14 @@
+# Add common options for the current library project
+if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR BOOST_SUPERPROJECT_SOURCE_DIR)
+ set(def_INSTALL ON)
+ set(def_WERROR ON)
+else()
+ set(def_INSTALL OFF)
+ set(def_WERROR OFF)
+endif()
+
+string(TOUPPER ${PROJECT_NAME} name)
+string(REPLACE BOOST_ Boost_ name ${name})
+
+option(${name}_INSTALL "Install library" "${def_INSTALL}")
+option(${name}_WERROR "Treat warnings as errors" "${def_WERROR}")
diff --git a/src/boost/libs/nowide/cmake/BoostAddWarnings.cmake b/src/boost/libs/nowide/cmake/BoostAddWarnings.cmake
new file mode 100644
index 000000000..12d185447
--- /dev/null
+++ b/src/boost/libs/nowide/cmake/BoostAddWarnings.cmake
@@ -0,0 +1,43 @@
+# Enable warnings for the given target
+# Arguments:
+# target: Non-interface library or executable
+# level: Which warnings to add. Valid values: off, on, all, extra
+# warningsAsErrors: Optional, ON to treat warnings as errors
+# Optionally can pass a bool as warnings-as-errors
+function(boost_add_warnings target level)
+ if(ARGC GREATER 2)
+ set(warningsAsErrors ${ARGV2})
+ else()
+ set(warningsAsErrors OFF)
+ endif()
+ set(allowed_levels off on all extra pedantic)
+ if(NOT level IN_LIST allowed_levels)
+ message(FATAL_ERROR "${level} is not a valid warning level (${allowed_levels})")
+ endif()
+ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+ set(supression -Wno-long-long)
+ set(warn_off -w)
+ set(warn_on -Wall ${supression})
+ set(warn_all -Wall ${supression})
+ set(warn_extra -Wall -Wextra ${supression})
+ set(warn_pedantic -Wall -Wextra -pedantic ${supression})
+ set(werror -Werror)
+ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
+ set(warn_off -w0)
+ foreach(_lvl IN ITEMS on all extra pedantic)
+ set(warn_${_lvl} -w1)
+ endforeach()
+ set(werror "")
+ elseif(MSVC)
+ set(warn_off /W0)
+ set(warn_on /W3)
+ foreach(_lvl IN ITEMS all extra pedantic)
+ set(warn_${_lvl} /W4)
+ endforeach()
+ set(werror /WX)
+ endif()
+ target_compile_options(${target} PRIVATE ${warn_${level}})
+ if(warningsAsErrors)
+ target_compile_options(${target} PRIVATE ${werror})
+ endif()
+endfunction()
diff --git a/src/boost/libs/nowide/cmake/InstallTargets.cmake b/src/boost/libs/nowide/cmake/InstallTargets.cmake
new file mode 100644
index 000000000..9022b325d
--- /dev/null
+++ b/src/boost/libs/nowide/cmake/InstallTargets.cmake
@@ -0,0 +1,73 @@
+include(GNUInstallDirs)
+include(CMakePackageConfigHelpers)
+
+# Install all passed libraries including <PROJECT_NAME>Config.cmake and <PROJECT_NAME>ConfigVersion.cmake
+# Assumes that your headers are in 'include/'
+# Uses GNUInstallDirs to determine install locations
+# Note: Use of BUILD_INTERFACE for headers is not required as it will be fixed up
+# Arguments:
+# - TARGETS: List of targets to install
+# - NAMESPACE: Namespace to use (Installed libraries will be available as "Namespace::Name")
+# - CONFIG_FILE: If passed, this will be used to configure the *Config.cmake,
+# else a reasonable default will be used which is enough if there are no dependencies
+# - VERSION_COMPATIBILITY: Compatibility with requested version. Defaults to SemVer semantics (SameMajorVersion)
+function(install_targets)
+ cmake_parse_arguments(PARSE_ARGV 0 ARG "" "NAMESPACE;CONFIG_FILE;VERSION_COMPATIBILITY" "TARGETS")
+ if(ARG_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Invalid argument(s): ${ARG_UNPARSED_ARGUMENTS}")
+ endif()
+ if(ARG_NAMESPACE)
+ string(APPEND ARG_NAMESPACE "::")
+ endif()
+ if(NOT ARG_CONFIG_FILE)
+ set(ARG_CONFIG_FILE "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake.in")
+ file(WRITE ${ARG_CONFIG_FILE}
+ "@PACKAGE_INIT@\n"
+ "include(\"\${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake\")\n"
+ "check_required_components(\"@PROJECT_NAME@\")\n"
+ )
+ endif()
+ if(NOT ARG_VERSION_COMPATIBILITY)
+ set(ARG_VERSION_COMPATIBILITY SameMajorVersion)
+ endif()
+
+ # Fixup INTERFACE_INCLUDE_DIRECTORIES:
+ # Wrap source includes into BUILD_INTERFACE
+ foreach(tgt IN LISTS ARG_TARGETS)
+ get_target_property(old_inc_dirs ${tgt} INTERFACE_INCLUDE_DIRECTORIES)
+ set(inc_dirs "")
+ foreach(dir IN LISTS old_inc_dirs)
+ string(FIND "${dir}" "${PROJECT_SOURCE_DIR}" pos)
+ string(FIND "${dir}" "${PROJECT_BINARY_DIR}" pos2)
+ if(pos EQUAL 0 OR pos2 EQUAL 0)
+ set(dir "$<BUILD_INTERFACE:${dir}>")
+ endif()
+ list(APPEND inc_dirs "${dir}")
+ endforeach()
+ set_target_properties(${tgt} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${inc_dirs}")
+ endforeach()
+
+ install(TARGETS ${ARG_TARGETS}
+ EXPORT ${PROJECT_NAME}Targets
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
+ )
+ install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+
+ set(configFile ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake)
+ set(versionFile ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake)
+ set(configInstallDestination lib/cmake/${PROJECT_NAME})
+
+ configure_package_config_file(${ARG_CONFIG_FILE} ${configFile} INSTALL_DESTINATION ${configInstallDestination})
+ write_basic_package_version_file(${versionFile} COMPATIBILITY ${ARG_VERSION_COMPATIBILITY})
+
+ install(FILES ${configFile} ${versionFile} DESTINATION ${configInstallDestination})
+
+ install(
+ EXPORT ${PROJECT_NAME}Targets
+ NAMESPACE ${ARG_NAMESPACE}
+ DESTINATION ${configInstallDestination}
+ )
+endfunction()
diff --git a/src/boost/libs/nowide/codecov.yml b/src/boost/libs/nowide/codecov.yml
new file mode 100644
index 000000000..d0a05c07e
--- /dev/null
+++ b/src/boost/libs/nowide/codecov.yml
@@ -0,0 +1,10 @@
+codecov:
+ max_report_age: off
+ require_ci_to_pass: yes
+ notify:
+ after_n_builds: 2
+ wait_for_ci: yes
+comment:
+ layout: "diff, files"
+ignore:
+ - "test/test.hpp"
diff --git a/src/boost/libs/nowide/index.html b/src/boost/libs/nowide/index.html
new file mode 100644
index 000000000..d94330dd0
--- /dev/null
+++ b/src/boost/libs/nowide/index.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head>
+ <title>Boost.Nowide Documentation</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />
+ <meta http-equiv="refresh" content="0; URL=doc/html/index.html" />
+</head>
+
+<body>
+ Automatic redirection failed, please go to <a href=
+ "doc/html/index.html">doc/html/index.html</a>
+</body>
+</html>
+<!-- Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) Distributed under the Boost Software License, Version 1.0 -->
diff --git a/src/boost/libs/nowide/meta/libraries.json b/src/boost/libs/nowide/meta/libraries.json
new file mode 100644
index 000000000..70bf0af2c
--- /dev/null
+++ b/src/boost/libs/nowide/meta/libraries.json
@@ -0,0 +1,11 @@
+{
+ "key": "nowide",
+ "name": "Nowide",
+ "authors": [
+ "Artyom Beilis"
+ ],
+ "description": "Standard library functions with UTF-8 API on Windows.",
+ "category": [
+ "System"
+ ]
+}
diff --git a/src/boost/libs/nowide/src/cstdio.cpp b/src/boost/libs/nowide/src/cstdio.cpp
new file mode 100644
index 000000000..0b0e75c9b
--- /dev/null
+++ b/src/boost/libs/nowide/src/cstdio.cpp
@@ -0,0 +1,74 @@
+//
+// Copyright (c) 2012 Artyom Beilis (Tonkikh)
+// Copyright (c) 2020 Alexander Grund
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#define BOOST_NOWIDE_SOURCE
+
+#ifdef _MSC_VER
+#define _CRT_SECURE_NO_WARNINGS
+#elif(defined(__MINGW32__) || defined(__CYGWIN__)) && defined(__STRICT_ANSI__)
+// Need the _w* functions which are extensions on MinGW/Cygwin
+#undef __STRICT_ANSI__
+#endif
+
+#include <boost/nowide/cstdio.hpp>
+#include <boost/nowide/stackstring.hpp>
+
+namespace boost {
+namespace nowide {
+ namespace detail {
+ FILE* wfopen(const wchar_t* filename, const wchar_t* mode)
+ {
+#ifdef BOOST_WINDOWS
+ return ::_wfopen(filename, mode);
+#else
+ const stackstring name(filename);
+ const short_stackstring smode2(mode);
+ return std::fopen(name.get(), smode2.get());
+#endif
+ }
+ } // namespace detail
+
+#ifdef BOOST_WINDOWS
+ ///
+ /// \brief Same as freopen but file_name and mode are UTF-8 strings
+ ///
+ FILE* freopen(const char* file_name, const char* mode, FILE* stream)
+ {
+ const wstackstring wname(file_name);
+ const wshort_stackstring wmode(mode);
+ return _wfreopen(wname.get(), wmode.get(), stream);
+ }
+ ///
+ /// \brief Same as fopen but file_name and mode are UTF-8 strings
+ ///
+ FILE* fopen(const char* file_name, const char* mode)
+ {
+ const wstackstring wname(file_name);
+ const wshort_stackstring wmode(mode);
+ return _wfopen(wname.get(), wmode.get());
+ }
+ ///
+ /// \brief Same as rename but old_name and new_name are UTF-8 strings
+ ///
+ int rename(const char* old_name, const char* new_name)
+ {
+ const wstackstring wold(old_name), wnew(new_name);
+ return _wrename(wold.get(), wnew.get());
+ }
+ ///
+ /// \brief Same as rename but name is UTF-8 string
+ ///
+ int remove(const char* name)
+ {
+ const wstackstring wname(name);
+ return _wremove(wname.get());
+ }
+#endif
+} // namespace nowide
+} // namespace boost
diff --git a/src/boost/libs/nowide/src/cstdlib.cpp b/src/boost/libs/nowide/src/cstdlib.cpp
new file mode 100644
index 000000000..52540d0c4
--- /dev/null
+++ b/src/boost/libs/nowide/src/cstdlib.cpp
@@ -0,0 +1,121 @@
+//
+// Copyright (c) 2012 Artyom Beilis (Tonkikh)
+// Copyright (c) 2020 Alexander Grund
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#define BOOST_NOWIDE_SOURCE
+
+#ifdef _MSC_VER
+#define _CRT_SECURE_NO_WARNINGS
+#elif(defined(__MINGW32__) || defined(__CYGWIN__)) && defined(__STRICT_ANSI__)
+// Need the _w* functions which are extensions on MinGW/Cygwin
+#undef __STRICT_ANSI__
+#endif
+
+#include <boost/nowide/cstdlib.hpp>
+
+#if !defined(BOOST_WINDOWS)
+namespace boost {
+namespace nowide {
+ int setenv(const char* key, const char* value, int overwrite)
+ {
+ return ::setenv(key, value, overwrite);
+ }
+
+ int unsetenv(const char* key)
+ {
+ return ::unsetenv(key);
+ }
+
+ int putenv(char* string)
+ {
+ return ::putenv(string);
+ }
+} // namespace nowide
+} // namespace boost
+#else
+#include <boost/nowide/stackstring.hpp>
+#include <vector>
+#include <windows.h>
+
+namespace boost {
+namespace nowide {
+ char* getenv(const char* key)
+ {
+ static stackstring value;
+
+ const wshort_stackstring name(key);
+
+ static const size_t buf_size = 64;
+ wchar_t buf[buf_size];
+ std::vector<wchar_t> tmp;
+ wchar_t* ptr = buf;
+ size_t n = GetEnvironmentVariableW(name.get(), buf, buf_size);
+ if(n == 0 && GetLastError() == 203) // ERROR_ENVVAR_NOT_FOUND
+ return 0;
+ if(n >= buf_size)
+ {
+ tmp.resize(n + 1, L'\0');
+ n = GetEnvironmentVariableW(name.get(), &tmp[0], static_cast<unsigned>(tmp.size() - 1));
+ // The size may have changed
+ if(n >= tmp.size() - 1)
+ return 0;
+ ptr = &tmp[0];
+ }
+ value.convert(ptr);
+ return value.get();
+ }
+
+ int setenv(const char* key, const char* value, int overwrite)
+ {
+ const wshort_stackstring name(key);
+ if(!overwrite)
+ {
+ wchar_t unused[2];
+ if(GetEnvironmentVariableW(name.get(), unused, 2) != 0 || GetLastError() != 203) // ERROR_ENVVAR_NOT_FOUND
+ return 0;
+ }
+ const wstackstring wval(value);
+ if(SetEnvironmentVariableW(name.get(), wval.get()))
+ return 0;
+ return -1;
+ }
+
+ int unsetenv(const char* key)
+ {
+ const wshort_stackstring name(key);
+ if(SetEnvironmentVariableW(name.get(), 0))
+ return 0;
+ return -1;
+ }
+
+ int putenv(char* string)
+ {
+ const char* key = string;
+ const char* key_end = string;
+ while(*key_end != '=' && *key_end != '\0')
+ key_end++;
+ if(*key_end == '\0')
+ return -1;
+ const wshort_stackstring wkey(key, key_end);
+ const wstackstring wvalue(key_end + 1);
+
+ if(SetEnvironmentVariableW(wkey.get(), wvalue.get()))
+ return 0;
+ return -1;
+ }
+
+ int system(const char* cmd)
+ {
+ if(!cmd)
+ return _wsystem(0);
+ const wstackstring wcmd(cmd);
+ return _wsystem(wcmd.get());
+ }
+} // namespace nowide
+} // namespace boost
+#endif
diff --git a/src/boost/libs/nowide/src/iostream.cpp b/src/boost/libs/nowide/src/iostream.cpp
new file mode 100644
index 000000000..0acd04e0b
--- /dev/null
+++ b/src/boost/libs/nowide/src/iostream.cpp
@@ -0,0 +1,270 @@
+//
+// Copyright (c) 2012 Artyom Beilis (Tonkikh)
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+#define BOOST_NOWIDE_SOURCE
+#include <boost/nowide/iostream.hpp>
+
+#ifndef BOOST_WINDOWS
+
+namespace boost {
+namespace nowide {
+ /// Avoid empty compilation unit warnings
+ /// \internal
+ BOOST_NOWIDE_DECL void dummy_exported_function()
+ {}
+} // namespace nowide
+} // namespace boost
+
+#else
+
+#include <boost/nowide/convert.hpp>
+#include <cassert>
+#include <cstring>
+#include <iostream>
+#include <vector>
+
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+
+#include <windows.h>
+
+namespace boost {
+namespace nowide {
+ namespace detail {
+
+ namespace {
+ bool is_atty_handle(HANDLE h)
+ {
+ if(h)
+ {
+ DWORD dummy;
+ return GetConsoleMode(h, &dummy) != FALSE;
+ }
+ return false;
+ }
+ } // namespace
+
+ class console_output_buffer : public std::streambuf
+ {
+ public:
+ console_output_buffer(HANDLE h) : handle_(h)
+ {}
+
+ protected:
+ int sync()
+ {
+ return overflow(traits_type::eof());
+ }
+ int overflow(int c)
+ {
+ if(!handle_)
+ return -1;
+ int n = static_cast<int>(pptr() - pbase());
+ int r = 0;
+
+ if(n > 0 && (r = write(pbase(), n)) < 0)
+ return -1;
+ if(r < n)
+ {
+ std::memmove(pbase(), pbase() + r, n - r);
+ }
+ setp(buffer_, buffer_ + buffer_size);
+ pbump(n - r);
+ if(c != traits_type::eof())
+ sputc(traits_type::to_char_type(c));
+ return 0;
+ }
+
+ private:
+ typedef detail::utf::utf_traits<char> decoder;
+ typedef detail::utf::utf_traits<wchar_t> encoder;
+
+ int write(const char* p, int n)
+ {
+ namespace uf = detail::utf;
+ const char* b = p;
+ const char* e = p + n;
+ DWORD size = 0;
+ if(n > buffer_size)
+ return -1;
+ wchar_t* out = wbuffer_;
+ uf::code_point c;
+ size_t decoded = 0;
+ while((c = decoder::decode(p, e)) != uf::incomplete)
+ {
+ if(c == uf::illegal)
+ c = BOOST_NOWIDE_REPLACEMENT_CHARACTER;
+ assert(out - wbuffer_ + encoder::width(c) <= static_cast<int>(wbuffer_size));
+ out = encoder::encode(c, out);
+ decoded = p - b;
+ }
+ if(!WriteConsoleW(handle_, wbuffer_, static_cast<DWORD>(out - wbuffer_), &size, 0))
+ return -1;
+ return static_cast<int>(decoded);
+ }
+
+ static const int buffer_size = 1024;
+ static const int wbuffer_size = buffer_size * encoder::max_width;
+ char buffer_[buffer_size];
+ wchar_t wbuffer_[wbuffer_size];
+ HANDLE handle_;
+ };
+
+ class console_input_buffer : public std::streambuf
+ {
+ public:
+ console_input_buffer(HANDLE h) : handle_(h), wsize_(0)
+ {}
+
+ protected:
+ int pbackfail(int c)
+ {
+ if(c == traits_type::eof())
+ return traits_type::eof();
+
+ if(gptr() != eback())
+ {
+ gbump(-1);
+ *gptr() = traits_type::to_char_type(c);
+ return 0;
+ }
+
+ if(pback_buffer_.empty())
+ {
+ pback_buffer_.resize(4);
+ char* b = &pback_buffer_[0];
+ char* e = b + pback_buffer_.size();
+ setg(b, e - 1, e);
+ *gptr() = traits_type::to_char_type(c);
+ } else
+ {
+ size_t n = pback_buffer_.size();
+ std::vector<char> tmp;
+ tmp.resize(n * 2);
+ memcpy(&tmp[n], &pback_buffer_[0], n);
+ tmp.swap(pback_buffer_);
+ char* b = &pback_buffer_[0];
+ char* e = b + n * 2;
+ char* p = b + n - 1;
+ *p = traits_type::to_char_type(c);
+ setg(b, p, e);
+ }
+
+ return 0;
+ }
+
+ int underflow()
+ {
+ if(!handle_)
+ return -1;
+ if(!pback_buffer_.empty())
+ pback_buffer_.clear();
+
+ size_t n = read();
+ setg(buffer_, buffer_, buffer_ + n);
+ if(n == 0)
+ return traits_type::eof();
+ return std::char_traits<char>::to_int_type(*gptr());
+ }
+
+ private:
+ typedef detail::utf::utf_traits<wchar_t> decoder;
+ typedef detail::utf::utf_traits<char> encoder;
+
+ size_t read()
+ {
+ namespace uf = detail::utf;
+ DWORD read_wchars = 0;
+ size_t n = wbuffer_size - wsize_;
+ if(!ReadConsoleW(handle_, wbuffer_ + wsize_, static_cast<DWORD>(n), &read_wchars, 0))
+ return 0;
+ wsize_ += read_wchars;
+ char* out = buffer_;
+ wchar_t* p = wbuffer_;
+ wchar_t* e = wbuffer_ + wsize_;
+ uf::code_point c = 0;
+ while((c = decoder::decode(p, e)) != uf::incomplete)
+ {
+ if(c == uf::illegal)
+ c = BOOST_NOWIDE_REPLACEMENT_CHARACTER;
+ assert(out - buffer_ + encoder::width(c) <= static_cast<int>(buffer_size));
+ out = encoder::encode(c, out);
+ wsize_ = e - p;
+ }
+
+ if(wsize_ > 0)
+ std::memmove(wbuffer_, e - wsize_, sizeof(wchar_t) * wsize_);
+
+ return out - buffer_;
+ }
+
+ static const size_t wbuffer_size = 1024;
+ static const size_t buffer_size = wbuffer_size * encoder::max_width;
+ char buffer_[buffer_size];
+ wchar_t wbuffer_[wbuffer_size];
+ HANDLE handle_;
+ size_t wsize_;
+ std::vector<char> pback_buffer_;
+ };
+
+ winconsole_ostream::winconsole_ostream(int fd, winconsole_ostream* tieStream) : std::ostream(0)
+ {
+ HANDLE h = 0;
+ switch(fd)
+ {
+ case 1: h = GetStdHandle(STD_OUTPUT_HANDLE); break;
+ case 2: h = GetStdHandle(STD_ERROR_HANDLE); break;
+ }
+ if(is_atty_handle(h))
+ {
+ d.reset(new console_output_buffer(h));
+ std::ostream::rdbuf(d.get());
+ } else
+ {
+ std::ostream::rdbuf(fd == 1 ? std::cout.rdbuf() : std::cerr.rdbuf());
+ }
+ if(tieStream)
+ tie(tieStream);
+ }
+ winconsole_ostream::~winconsole_ostream()
+ {
+ try
+ {
+ flush();
+ } catch(...)
+ {}
+ }
+
+ winconsole_istream::winconsole_istream(winconsole_ostream* tieStream) : std::istream(0)
+ {
+ HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
+ if(is_atty_handle(h))
+ {
+ d.reset(new console_input_buffer(h));
+ std::istream::rdbuf(d.get());
+ } else
+ {
+ std::istream::rdbuf(std::cin.rdbuf());
+ }
+ if(tieStream)
+ tie(tieStream);
+ }
+
+ winconsole_istream::~winconsole_istream()
+ {}
+
+ } // namespace detail
+
+ detail::winconsole_ostream cout(1, NULL);
+ detail::winconsole_istream cin(&cout);
+ detail::winconsole_ostream cerr(2, &cout);
+ detail::winconsole_ostream clog(2, &cout);
+} // namespace nowide
+} // namespace boost
+
+#endif
diff --git a/src/boost/libs/nowide/standalone/config.hpp b/src/boost/libs/nowide/standalone/config.hpp
new file mode 100644
index 000000000..8a07e20d4
--- /dev/null
+++ b/src/boost/libs/nowide/standalone/config.hpp
@@ -0,0 +1,81 @@
+//
+// Copyright (c) 2012 Artyom Beilis (Tonkikh)
+// Copyright (c) 2020 Alexander Grund
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+#ifndef NOWIDE_CONFIG_HPP_INCLUDED
+#define NOWIDE_CONFIG_HPP_INCLUDED
+
+#include <boost/nowide/replacement.hpp>
+
+#if(defined(__WIN32) || defined(_WIN32) || defined(WIN32)) && !defined(__CYGWIN__)
+#define NOWIDE_WINDOWS
+#endif
+
+#ifdef _MSC_VER
+#define NOWIDE_MSVC _MSC_VER
+#endif
+
+#ifdef __GNUC__
+#define BOOST_SYMBOL_VISIBLE __attribute__((__visibility__("default")))
+#endif
+
+#ifndef BOOST_SYMBOL_VISIBLE
+#define BOOST_SYMBOL_VISIBLE
+#endif
+
+#ifdef NOWIDE_WINDOWS
+#define BOOST_SYMBOL_EXPORT __declspec(dllexport)
+#define BOOST_SYMBOL_IMPORT __declspec(dllimport)
+#else
+#define BOOST_SYMBOL_EXPORT BOOST_SYMBOL_VISIBLE
+#define BOOST_SYMBOL_IMPORT
+#endif
+
+#if defined(BOOST_NOWIDE_DYN_LINK)
+#ifdef BOOST_NOWIDE_SOURCE
+#define BOOST_NOWIDE_DECL BOOST_SYMBOL_EXPORT
+#else
+#define BOOST_NOWIDE_DECL BOOST_SYMBOL_IMPORT
+#endif // BOOST_NOWIDE_SOURCE
+#else
+#define BOOST_NOWIDE_DECL
+#endif // BOOST_NOWIDE_DYN_LINK
+
+#ifndef NOWIDE_DECL
+#define NOWIDE_DECL
+#endif
+
+#if defined(NOWIDE_WINDOWS)
+#ifdef BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT
+#undef BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT
+#endif
+#define BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT 1
+#elif !defined(BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT)
+#define BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT 0
+#endif
+
+#if defined(__GNUC__) && __GNUC__ >= 7
+#define BOOST_NOWIDE_FALLTHROUGH __attribute__((fallthrough))
+#else
+#define BOOST_NOWIDE_FALLTHROUGH
+#endif
+
+// MSVC 2015 (1900) has reasonable C++11 support (especially auto-generated move ctors)
+#if __cplusplus >= 201103L || (defined(NOWIDE_MSVC) && NOWIDE_MSVC >= 1900)
+#define BOOST_NOWIDE_CXX11 1
+#else
+#define BOOST_NOWIDE_CXX11 0
+#endif
+
+#if !defined(BOOST_LIKELY)
+#define BOOST_LIKELY(x) x
+#endif
+#if !defined(BOOST_UNLIKELY)
+#define BOOST_UNLIKELY(x) x
+#endif
+
+#endif
diff --git a/src/boost/libs/nowide/standalone/cstdint.hpp b/src/boost/libs/nowide/standalone/cstdint.hpp
new file mode 100644
index 000000000..7dacb5af6
--- /dev/null
+++ b/src/boost/libs/nowide/standalone/cstdint.hpp
@@ -0,0 +1,12 @@
+#ifndef NOWIDE_CSTDINT_HPP
+#define NOWIDE_CSTDINT_HPP
+
+#include <cstdint>
+
+namespace nowide {
+typedef std::uint32_t uint32_t;
+typedef std::uint16_t uint16_t;
+typedef std::uint8_t uint8_t;
+} // namespace nowide
+
+#endif
diff --git a/src/boost/libs/nowide/standalone/scoped_ptr.hpp b/src/boost/libs/nowide/standalone/scoped_ptr.hpp
new file mode 100644
index 000000000..37761a9d1
--- /dev/null
+++ b/src/boost/libs/nowide/standalone/scoped_ptr.hpp
@@ -0,0 +1,87 @@
+#ifndef NOWIDE_SCOPED_PTR_HPP
+#define NOWIDE_SCOPED_PTR_HPP
+
+// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
+// Copyright (c) 2001, 2002 Peter Dimov,
+// Copyright (C) 2012 Artyom Beilis
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// http://www.boost.org/libs/smart_ptr/scoped_ptr.htm
+//
+
+#include <cassert>
+
+namespace nowide {
+
+// scoped_ptr mimics a built-in pointer except that it guarantees deletion
+// of the object pointed to, either on destruction of the scoped_ptr or via
+// an explicit reset(). scoped_ptr is a simple solution for simple needs;
+// use shared_ptr or std::auto_ptr if your needs are more complex.
+
+template<class T>
+class scoped_ptr // noncopyable
+{
+private:
+ T* px;
+
+ scoped_ptr(scoped_ptr const&);
+ scoped_ptr& operator=(scoped_ptr const&);
+
+ typedef scoped_ptr<T> this_type;
+
+ void operator==(scoped_ptr const&) const;
+ void operator!=(scoped_ptr const&) const;
+
+public:
+ typedef T element_type;
+
+ explicit scoped_ptr(T* p = 0) : px(p) // never throws
+ {}
+
+ ~scoped_ptr() // never throws
+ {
+ delete px;
+ }
+
+ void reset(T* p = 0) // never throws
+ {
+ assert(p == 0 || p != px); // catch self-reset errors
+ this_type(p).swap(*this);
+ }
+
+ T& operator*() const // never throws
+ {
+ assert(px != 0);
+ return *px;
+ }
+
+ T* operator->() const // never throws
+ {
+ assert(px != 0);
+ return px;
+ }
+
+ T* get() const // never throws
+ {
+ return px;
+ }
+
+ operator bool() const
+ {
+ return px != 0;
+ }
+
+ void swap(scoped_ptr& b) // never throws
+ {
+ T* tmp = b.px;
+ b.px = px;
+ px = tmp;
+ }
+};
+
+} // namespace nowide
+
+#endif
diff --git a/src/boost/libs/nowide/standalone/static_assert.hpp b/src/boost/libs/nowide/standalone/static_assert.hpp
new file mode 100644
index 000000000..b772f30e0
--- /dev/null
+++ b/src/boost/libs/nowide/standalone/static_assert.hpp
@@ -0,0 +1,7 @@
+#ifndef NOWIDE_STATIC_ASSERT_HPP
+#define NOWIDE_STATIC_ASSERT_HPP
+
+#define NOWIDE_STATIC_ASSERT(c) static_assert(c, #c)
+#define NOWIDE_STATIC_ASSERT_MSG(c, msg) static_assert(c, msg)
+
+#endif
diff --git a/src/boost/libs/nowide/test/CMakeLists.txt b/src/boost/libs/nowide/test/CMakeLists.txt
new file mode 100644
index 000000000..4f7c4976b
--- /dev/null
+++ b/src/boost/libs/nowide/test/CMakeLists.txt
@@ -0,0 +1,38 @@
+function(boost_nowide_add_test name)
+ cmake_parse_arguments(PARSE_ARGV 1 ARG "COMPILE_ONLY" "SRC" "LIBRARIES;DEFINITIONS;ARGS")
+ if(NOT ARG_SRC)
+ set(ARG_SRC ${name}.cpp)
+ endif()
+ set(name ${PROJECT_NAME}-${name})
+
+ add_executable(${name} ${ARG_SRC})
+ target_link_libraries(${name} PRIVATE Boost::nowide ${ARG_LIBRARIES})
+ boost_add_warnings(${name} pedantic ${Boost_NOWIDE_WERROR})
+ target_compile_definitions(${name} PRIVATE BOOST_ALL_NO_LIB ${ARG_DEFINITIONS})
+ if(NOT ARG_COMPILE_ONLY)
+ add_test(NAME ${name} COMMAND ${name} ${ARG_ARGS})
+ endif()
+endfunction()
+
+boost_nowide_add_test(test_codecvt)
+boost_nowide_add_test(test_convert)
+boost_nowide_add_test(test_env)
+boost_nowide_add_test(test_env_win SRC test_env.cpp DEFINITIONS BOOST_NOWIDE_TEST_INCLUDE_WINDOWS)
+boost_nowide_add_test(test_fstream)
+boost_nowide_add_test(test_fstream_cxx11)
+boost_nowide_add_test(test_iostream)
+boost_nowide_add_test(test_stackstring)
+boost_nowide_add_test(test_stdio)
+boost_nowide_add_test(test_system_n SRC test_system.cpp DEFINITIONS BOOST_NOWIDE_TEST_USE_NARROW=1)
+if(WIN32)
+ boost_nowide_add_test(test_system_w SRC test_system.cpp DEFINITIONS BOOST_NOWIDE_TEST_USE_NARROW=0)
+else()
+ boost_nowide_add_test(test_internal_fstream SRC test_fstream.cpp DEFINITIONS BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT=1)
+ boost_nowide_add_test(test_internal_fstream_cxx11 SRC test_fstream_cxx11.cpp DEFINITIONS BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT=1)
+endif()
+
+if(NOT BOOST_SUPERPROJECT_SOURCE_DIR)
+ find_package(Boost 1.56 REQUIRED COMPONENTS filesystem system chrono)
+endif()
+boost_nowide_add_test(test_fs LIBRARIES Boost::filesystem)
+boost_nowide_add_test(benchmark_fstream COMPILE_ONLY DEFINITIONS BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT=1 LIBRARIES Boost::chrono)
diff --git a/src/boost/libs/nowide/test/Jamfile.v2 b/src/boost/libs/nowide/test/Jamfile.v2
new file mode 100644
index 000000000..738dc0e59
--- /dev/null
+++ b/src/boost/libs/nowide/test/Jamfile.v2
@@ -0,0 +1,39 @@
+# Boost Nowide Library test Jamfile
+
+# Copyright Beman Dawes 2003, 2006, Artyom Beilis 2012
+
+# Distributed under the Boost Software License, Version 1.0.
+# See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt
+
+# See library home page at http://www.boost.org/libs/nowide
+
+import testing ;
+
+project : requirements
+ <library>/boost/nowide//boost_nowide
+ <warnings>pedantic
+ <warnings-as-errors>on
+ <toolset>gcc:<cxxflags>-Wno-long-long
+ <toolset>darwin:<cxxflags>-Wno-long-long
+ <toolset>pathscale:<cxxflags>-Wno-long-long
+ <toolset>clang:<cxxflags>-Wno-long-long
+ ;
+
+lib shell32 ;
+
+run test_codecvt.cpp ;
+run test_convert.cpp ;
+run test_env.cpp ;
+run test_env.cpp : : : <define>BOOST_NOWIDE_TEST_INCLUDE_WINDOWS=1 : test_env_win ;
+run test_fs.cpp : : : <library>/boost/filesystem//boost_filesystem/<warnings-as-errors>off : ;
+run test_fstream.cpp ;
+run test_fstream.cpp : : : <define>BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT=1 <target-os>windows:<build>no : test_internal_fstream ;
+run test_fstream_cxx11.cpp ;
+run test_fstream_cxx11.cpp : : : <define>BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT=1 <target-os>windows:<build>no : test_internal_fstream_cxx11 ;
+run test_iostream.cpp ;
+run test_stackstring.cpp ;
+run test_stdio.cpp ;
+run test_system.cpp : : : <define>BOOST_NOWIDE_TEST_USE_NARROW=1 <target-os>windows:<library>shell32 <target-os>darwin,<link>shared:<build>no : test_system_n ;
+run test_system.cpp : : : <define>BOOST_NOWIDE_TEST_USE_NARROW=0 <target-os>windows:<library>shell32 <build>no <target-os>windows:<build>yes : test_system_w ;
+
+compile benchmark_fstream.cpp : <define>BOOST_NOWIDE_USE_WIN_FSTREAM=1 <library>/boost/chrono//boost_chrono/ ;
diff --git a/src/boost/libs/nowide/test/benchmark_fstream.cpp b/src/boost/libs/nowide/test/benchmark_fstream.cpp
new file mode 100644
index 000000000..7ebcfcb72
--- /dev/null
+++ b/src/boost/libs/nowide/test/benchmark_fstream.cpp
@@ -0,0 +1,273 @@
+//
+// Copyright (c) 2012 Artyom Beilis (Tonkikh)
+// Copyright (c) 2019 Alexander Grund
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#define BOOST_NOWIDE_TEST_NO_MAIN
+
+#include <boost/nowide/convert.hpp>
+#include <boost/nowide/cstdio.hpp>
+#include <boost/nowide/fstream.hpp>
+#define BOOST_CHRONO_HEADER_ONLY
+#include <boost/chrono.hpp>
+#include <algorithm>
+#include <cstdio>
+#include <fstream>
+#include <iomanip>
+#include <iostream>
+#include <map>
+#include <stdexcept>
+#include <vector>
+
+#include "test.hpp"
+
+template<typename Key, typename Value, typename Key2>
+Value get(const std::map<Key, Value>& map, const Key2& key)
+{
+ typename std::map<Key, Value>::const_iterator it = map.find(key);
+ if(it == map.end())
+ throw std::runtime_error("Key not found");
+ return it->second;
+}
+
+namespace nw = boost::nowide;
+template<typename FStream>
+class io_fstream
+{
+public:
+ explicit io_fstream(const char* file, bool read)
+ {
+ f_.open(file, read ? std::fstream::in : std::fstream::out | std::fstream::trunc);
+ TEST(f_);
+ }
+ // coverity[exn_spec_violation]
+ ~io_fstream()
+ {
+ f_.close();
+ }
+ void write(const char* buf, int size)
+ {
+ TEST(f_.write(buf, size));
+ }
+ void read(char* buf, int size)
+ {
+ TEST(f_.read(buf, size));
+ }
+ void rewind()
+ {
+ f_.seekg(0);
+ f_.seekp(0);
+ }
+ void flush()
+ {
+ f_ << std::flush;
+ }
+
+private:
+ FStream f_;
+};
+
+class io_stdio
+{
+public:
+ io_stdio(const char* file, bool read)
+ {
+ f_ = nw::fopen(file, read ? "r" : "w+");
+ TEST(f_);
+ }
+ ~io_stdio()
+ {
+ std::fclose(f_);
+ f_ = 0;
+ }
+ void write(const char* buf, int size)
+ {
+ TEST(std::fwrite(buf, 1, size, f_) == static_cast<size_t>(size));
+ }
+ void read(char* buf, int size)
+ {
+ TEST(std::fread(buf, 1, size, f_) == static_cast<size_t>(size));
+ }
+ void rewind()
+ {
+ std::rewind(f_);
+ }
+ void flush()
+ {
+ std::fflush(f_);
+ }
+
+private:
+ FILE* f_;
+};
+
+#if defined(_MSC_VER)
+extern "C" void _ReadWriteBarrier(void);
+#pragma intrinsic(_ReadWriteBarrier)
+#define BOOST_NOWIDE_READ_WRITE_BARRIER() _ReadWriteBarrier()
+#elif defined(__GNUC__)
+#if(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
+#define BOOST_NOWIDE_READ_WRITE_BARRIER() __sync_synchronize()
+#else
+#define BOOST_NOWIDE_READ_WRITE_BARRIER() __asm__ __volatile__("" : : : "memory")
+#endif
+#else
+#define BOOST_NOWIDE_READ_WRITE_BARRIER() (void)
+#endif
+
+struct perf_data
+{
+ // Block-size to read/write performance in MB/s
+ std::map<size_t, double> read, write;
+};
+
+char rand_char()
+{
+ // coverity[dont_call]
+ return static_cast<char>(std::rand());
+}
+
+std::vector<char> get_rand_data(int size)
+{
+ std::vector<char> data(size);
+ std::generate(data.begin(), data.end(), rand_char);
+ return data;
+}
+
+static const int MIN_BLOCK_SIZE = 32;
+static const int MAX_BLOCK_SIZE = 8192;
+
+template<typename FStream>
+perf_data test_io(const char* file)
+{
+ namespace chrono = boost::chrono;
+ typedef chrono::high_resolution_clock clock;
+ typedef chrono::duration<double, boost::milli> milliseconds;
+ perf_data results;
+ // Use vector to force write to memory and avoid possible reordering
+ std::vector<clock::time_point> start_and_end(2);
+ const int data_size = 64 * 1024 * 1024;
+ for(int block_size = MIN_BLOCK_SIZE / 2; block_size <= MAX_BLOCK_SIZE; block_size *= 2)
+ {
+ std::vector<char> buf = get_rand_data(block_size);
+ FStream tmp(file, false);
+ tmp.rewind();
+ start_and_end[0] = clock::now();
+ BOOST_NOWIDE_READ_WRITE_BARRIER();
+ for(int size = 0; size < data_size; size += block_size)
+ {
+ tmp.write(&buf[0], block_size);
+ BOOST_NOWIDE_READ_WRITE_BARRIER();
+ }
+ tmp.flush();
+ start_and_end[1] = clock::now();
+ // heatup
+ if(block_size >= MIN_BLOCK_SIZE)
+ {
+ const milliseconds duration = chrono::duration_cast<milliseconds>(start_and_end[1] - start_and_end[0]);
+ const double speed = data_size / duration.count() / 1024; // MB/s
+ results.write[block_size] = speed;
+ std::cout << " write block size " << std::setw(8) << block_size << " " << std::fixed
+ << std::setprecision(3) << speed << " MB/s" << std::endl;
+ }
+ }
+ for(int block_size = MIN_BLOCK_SIZE; block_size <= MAX_BLOCK_SIZE; block_size *= 2)
+ {
+ std::vector<char> buf = get_rand_data(block_size);
+ FStream tmp(file, true);
+ tmp.rewind();
+ start_and_end[0] = clock::now();
+ BOOST_NOWIDE_READ_WRITE_BARRIER();
+ for(int size = 0; size < data_size; size += block_size)
+ {
+ tmp.read(&buf[0], block_size);
+ BOOST_NOWIDE_READ_WRITE_BARRIER();
+ }
+ start_and_end[1] = clock::now();
+ const milliseconds duration = chrono::duration_cast<milliseconds>(start_and_end[1] - start_and_end[0]);
+ const double speed = data_size / duration.count() / 1024; // MB/s
+ results.read[block_size] = speed;
+ std::cout << " read block size " << std::setw(8) << block_size << " " << std::fixed << std::setprecision(3)
+ << speed << " MB/s" << std::endl;
+ }
+ TEST(std::remove(file) == 0);
+ return results;
+}
+
+template<typename FStream>
+perf_data test_io_driver(const char* file, const char* type)
+{
+ std::cout << "Testing I/O performance for " << type << std::endl;
+ const int repeats = 5;
+ std::vector<perf_data> results(repeats);
+
+ for(int i = 0; i < repeats; i++)
+ results[i] = test_io<FStream>(file);
+ for(int block_size = MIN_BLOCK_SIZE; block_size <= MAX_BLOCK_SIZE; block_size *= 2)
+ {
+ double read_speed = 0, write_speed = 0;
+ for(int i = 0; i < repeats; i++)
+ {
+ read_speed += get(results[i].read, block_size);
+ write_speed += get(results[i].write, block_size);
+ }
+ results[0].read[block_size] = read_speed / repeats;
+ results[0].write[block_size] = write_speed / repeats;
+ }
+ return results[0];
+}
+
+void print_perf_data(const std::map<size_t, double>& stdio_data,
+ const std::map<size_t, double>& std_data,
+ const std::map<size_t, double>& nowide_data)
+{
+ std::cout << "block size"
+ << " stdio "
+ << " std::fstream "
+ << "nowide::fstream" << std::endl;
+ for(int block_size = MIN_BLOCK_SIZE; block_size <= MAX_BLOCK_SIZE; block_size *= 2)
+ {
+ std::cout << std::setw(8) << block_size << " ";
+ std::cout << std::fixed << std::setprecision(3) << std::setw(8) << get(stdio_data, block_size) << " MB/s ";
+ std::cout << std::fixed << std::setprecision(3) << std::setw(8) << get(std_data, block_size) << " MB/s ";
+ std::cout << std::fixed << std::setprecision(3) << std::setw(8) << get(nowide_data, block_size) << " MB/s ";
+ std::cout << std::endl;
+ }
+}
+
+void test_perf(const char* file)
+{
+ perf_data stdio_data = test_io_driver<io_stdio>(file, "stdio");
+ perf_data std_data = test_io_driver<io_fstream<std::fstream> >(file, "std::fstream");
+ perf_data nowide_data = test_io_driver<io_fstream<nw::fstream> >(file, "nowide::fstream");
+ std::cout << "================== Read performance ==================" << std::endl;
+ print_perf_data(stdio_data.read, std_data.read, nowide_data.read);
+ std::cout << "================== Write performance =================" << std::endl;
+ print_perf_data(stdio_data.write, std_data.write, nowide_data.write);
+}
+
+int main(int argc, char** argv)
+{
+ std::string filename = "perf_test_file.dat";
+ if(argc == 2)
+ {
+ filename = argv[1];
+ } else if(argc != 1)
+ {
+ std::cerr << "Usage: " << argv[0] << " [test_filepath]" << std::endl;
+ return 1;
+ }
+ try
+ {
+ test_perf(filename.c_str());
+ } catch(const std::runtime_error& err)
+ {
+ std::cerr << "Benchmarking failed: " << err.what() << std::endl;
+ return 1;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/nowide/test/exampleProject/CMakeLists.txt b/src/boost/libs/nowide/test/exampleProject/CMakeLists.txt
new file mode 100644
index 000000000..9aa5ec40d
--- /dev/null
+++ b/src/boost/libs/nowide/test/exampleProject/CMakeLists.txt
@@ -0,0 +1,10 @@
+# Project testing to consume Boost.Nowide
+cmake_minimum_required(VERSION 3.8.0)
+project(nowide_example_project)
+
+find_package(boost_nowide 10.0 REQUIRED)
+
+add_executable(example example_main.cpp)
+target_link_libraries(example PRIVATE Boost::nowide)
+enable_testing()
+add_test(NAME example COMMAND example)
diff --git a/src/boost/libs/nowide/test/exampleProject/example_main.cpp b/src/boost/libs/nowide/test/exampleProject/example_main.cpp
new file mode 100644
index 000000000..91245985a
--- /dev/null
+++ b/src/boost/libs/nowide/test/exampleProject/example_main.cpp
@@ -0,0 +1,20 @@
+//
+// Copyright (c) 2019 Alexander Grund
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/nowide/args.hpp>
+#include <boost/nowide/convert.hpp>
+
+int main(int argc, char** argv, char** env)
+{
+ boost::nowide::args _(argc, argv, env);
+ if(argc < 1)
+ return 1;
+ if(boost::nowide::narrow(boost::nowide::widen(argv[0])) != argv[0])
+ return 1;
+ return 0;
+}
diff --git a/src/boost/libs/nowide/test/test.hpp b/src/boost/libs/nowide/test/test.hpp
new file mode 100644
index 000000000..a8f96622d
--- /dev/null
+++ b/src/boost/libs/nowide/test/test.hpp
@@ -0,0 +1,109 @@
+//
+// Copyright (c) 2012 Artyom Beilis (Tonkikh)
+// Copyright (c) 2019-2020 Alexander Grund
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+#ifndef BOOST_NOWIDE_LIB_TEST_H_INCLUDED
+#define BOOST_NOWIDE_LIB_TEST_H_INCLUDED
+
+#include <cstdlib>
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+
+#if defined(_MSC_VER) && defined(_CPPLIB_VER) && defined(_DEBUG)
+#include <crtdbg.h>
+#endif
+
+namespace boost {
+namespace nowide {
+ struct test_monitor
+ {
+ test_monitor()
+ {
+#if defined(_MSC_VER) && (_MSC_VER > 1310)
+ // disable message boxes on assert(), abort()
+ ::_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
+#endif
+#if defined(_MSC_VER) && defined(_CPPLIB_VER) && defined(_DEBUG)
+ // disable message boxes on iterator debugging violations
+ _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
+ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
+#endif
+ }
+ };
+} // namespace nowide
+} // namespace boost
+
+inline boost::nowide::test_monitor& test_mon()
+{
+ static boost::nowide::test_monitor instance;
+ return instance;
+}
+
+/// Function called when a test failed to be able set a breakpoint for debugging
+inline void test_failed(const char* expr, const char* file, const int line, const char* function)
+{
+ std::ostringstream ss;
+ ss << "Error " << expr << " at " << file << ':' << line << " in " << function;
+ throw std::runtime_error(ss.str());
+}
+
+template<typename T, typename U>
+inline void test_equal_impl(const T& lhs, const U& rhs, const char* file, const int line, const char* function)
+{
+ if(lhs == rhs)
+ return;
+ std::ostringstream ss;
+ ss << "[" << lhs << "!=" << rhs << "]";
+ test_failed(ss.str().c_str(), file, line, function);
+}
+
+#ifdef _MSC_VER
+#define DISABLE_CONST_EXPR_DETECTED __pragma(warning(push)) __pragma(warning(disable : 4127))
+#define DISABLE_CONST_EXPR_DETECTED_POP __pragma(warning(pop))
+#else
+#define DISABLE_CONST_EXPR_DETECTED
+#define DISABLE_CONST_EXPR_DETECTED_POP
+#endif
+
+#define TEST(x) \
+ do \
+ { \
+ test_mon(); \
+ if(x) \
+ break; \
+ test_failed(#x, __FILE__, __LINE__, __FUNCTION__); \
+ DISABLE_CONST_EXPR_DETECTED \
+ } while(0) DISABLE_CONST_EXPR_DETECTED_POP
+#define TEST_EQ(lhs, rhs) \
+ do \
+ { \
+ test_mon(); \
+ test_equal_impl((lhs), (rhs), __FILE__, __LINE__, __FUNCTION__); \
+ break; \
+ DISABLE_CONST_EXPR_DETECTED \
+ } while(0) DISABLE_CONST_EXPR_DETECTED_POP
+
+#endif // #ifndef BOOST_NOWIDE_LIB_TEST_H_INCLUDED
+
+#ifndef BOOST_NOWIDE_TEST_NO_MAIN
+// Tests should implement this
+void test_main(int argc, char** argv, char** env);
+
+int main(int argc, char** argv, char** env)
+{
+ try
+ {
+ test_main(argc, argv, env);
+ } catch(const std::exception& e)
+ {
+ std::cerr << "Failed " << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+}
+#endif
diff --git a/src/boost/libs/nowide/test/test_codecvt.cpp b/src/boost/libs/nowide/test/test_codecvt.cpp
new file mode 100644
index 000000000..7acc0f1fa
--- /dev/null
+++ b/src/boost/libs/nowide/test/test_codecvt.cpp
@@ -0,0 +1,328 @@
+//
+// Copyright (c) 2015 Artyom Beilis (Tonkikh)
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/nowide/utf8_codecvt.hpp>
+
+#include <boost/nowide/convert.hpp>
+#include <cstring>
+#include <iomanip>
+#include <iostream>
+#include <locale>
+#include <vector>
+
+#include "test.hpp"
+#include "test_sets.hpp"
+
+static const char* utf8_name =
+ "\xf0\x9d\x92\x9e-\xD0\xBF\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD1\x82-\xE3\x82\x84\xE3\x81\x82.txt";
+static const std::wstring wide_name_str = boost::nowide::widen(utf8_name);
+static const wchar_t* wide_name = wide_name_str.c_str();
+
+typedef std::codecvt<wchar_t, char, std::mbstate_t> cvt_type;
+
+void test_codecvt_in_n_m(const cvt_type& cvt, size_t n, size_t m)
+{
+ const wchar_t* wptr = wide_name;
+ size_t wlen = std::wcslen(wide_name);
+ size_t u8len = std::strlen(utf8_name);
+ const char* from = utf8_name;
+ const char* end = from;
+ const char* real_end = utf8_name + u8len;
+ const char* from_next = from;
+ std::mbstate_t mb = std::mbstate_t();
+ while(from_next < real_end)
+ {
+ if(from == end)
+ {
+ end = from + n;
+ if(end > real_end)
+ end = real_end;
+ }
+
+ wchar_t buf[128];
+ wchar_t* to = buf;
+ wchar_t* to_end = to + m;
+ wchar_t* to_next = to;
+
+ std::mbstate_t mb2 = mb;
+ std::codecvt_base::result r = cvt.in(mb, from, end, from_next, to, to_end, to_next);
+
+ int count = cvt.length(mb2, from, end, to_end - to);
+#ifndef BOOST_NOWIDE_DO_LENGTH_MBSTATE_CONST
+ TEST(std::memcmp(&mb, &mb2, sizeof(mb)) == 0);
+ if(count != from_next - from)
+ {
+ std::cout << count << " " << from_next - from << std::endl;
+ }
+ TEST(count == from_next - from);
+#else
+ TEST(count == to_next - to);
+#endif
+
+ if(r == cvt_type::partial)
+ {
+ end += n;
+ if(end > real_end)
+ end = real_end;
+ } else
+ TEST(r == cvt_type::ok);
+ while(to != to_next)
+ {
+ TEST(*wptr == *to);
+ wptr++;
+ to++;
+ }
+ to = to_next;
+ from = from_next;
+ }
+ TEST(wptr == wide_name + wlen);
+ TEST(from == real_end);
+}
+
+void test_codecvt_out_n_m(const cvt_type& cvt, size_t n, size_t m)
+{
+ const char* nptr = utf8_name;
+ size_t wlen = std::wcslen(wide_name);
+ size_t u8len = std::strlen(utf8_name);
+
+ std::mbstate_t mb = std::mbstate_t();
+
+ const wchar_t* from_next = wide_name;
+ const wchar_t* real_from_end = wide_name + wlen;
+
+ char buf[256];
+ char* to = buf;
+ char* to_next = to;
+ char* to_end = to + n;
+ char* real_to_end = buf + sizeof(buf);
+
+ while(from_next < real_from_end)
+ {
+ const wchar_t* from = from_next;
+ const wchar_t* from_end = from + m;
+ if(from_end > real_from_end)
+ from_end = real_from_end;
+ if(to_end == to)
+ {
+ to_end = to + n;
+ }
+
+ std::codecvt_base::result r = cvt.out(mb, from, from_end, from_next, to, to_end, to_next);
+ if(r == cvt_type::partial)
+ {
+ // If those are equal, then "partial" probably means: Need more input
+ // Otherwise "Need more output"
+ if(from_next != from_end)
+ {
+ TEST(to_end - to_next < cvt.max_length());
+ to_end += n;
+ if(to_end > real_to_end)
+ to_end = real_to_end;
+ }
+ } else
+ {
+ TEST(r == cvt_type::ok);
+ }
+
+ while(to != to_next)
+ {
+ TEST(*nptr == *to);
+ nptr++;
+ to++;
+ }
+ from = from_next;
+ }
+ TEST(nptr == utf8_name + u8len);
+ TEST(from_next == real_from_end);
+ TEST(cvt.unshift(mb, to, to + n, to_next) == cvt_type::ok);
+ TEST(to_next == to);
+}
+
+void test_codecvt_conv()
+{
+ std::cout << "Conversions " << std::endl;
+ std::locale l(std::locale::classic(), new boost::nowide::utf8_codecvt<wchar_t>());
+
+ const cvt_type& cvt = std::use_facet<cvt_type>(l);
+ const size_t utf8_len = std::strlen(utf8_name);
+ const size_t wide_len = std::wcslen(wide_name);
+
+ for(size_t i = 1; i <= utf8_len + 1; i++)
+ {
+ for(size_t j = 1; j <= wide_len + 1; j++)
+ {
+ try
+ {
+ test_codecvt_in_n_m(cvt, i, j);
+ test_codecvt_out_n_m(cvt, i, j);
+ } catch(...)
+ {
+ std::cerr << "Wlen=" << j << " Nlen=" << i << std::endl;
+ throw;
+ }
+ }
+ }
+}
+
+void test_codecvt_err()
+{
+ std::cout << "Errors " << std::endl;
+ std::locale l(std::locale::classic(), new boost::nowide::utf8_codecvt<wchar_t>());
+
+ const cvt_type& cvt = std::use_facet<cvt_type>(l);
+
+ std::cout << "- UTF-8" << std::endl;
+ {
+ {
+ wchar_t buf[4];
+ wchar_t* const to = buf;
+ wchar_t* const to_end = buf + 4;
+ const char* err_utf = "1\xFF\xFF\xd7\xa9";
+ std::mbstate_t mb = std::mbstate_t();
+ const char* from = err_utf;
+ const char* from_end = from + std::strlen(from);
+ const char* from_next = from;
+ wchar_t* to_next = to;
+ TEST(cvt.in(mb, from, from_end, from_next, to, to_end, to_next) == cvt_type::ok);
+ TEST(from_next == from + 5);
+ TEST(to_next == to + 4);
+ TEST(std::wstring(to, to_end) == boost::nowide::widen(err_utf));
+ }
+ {
+ wchar_t buf[4];
+ wchar_t* const to = buf;
+ wchar_t* const to_end = buf + 4;
+ const char* err_utf = "1\xd7"; // 1 valid, 1 incomplete UTF-8 char
+ std::mbstate_t mb = std::mbstate_t();
+ const char* from = err_utf;
+ const char* from_end = from + std::strlen(from);
+ const char* from_next = from;
+ wchar_t* to_next = to;
+ TEST(cvt.in(mb, from, from_end, from_next, to, to_end, to_next) == cvt_type::partial);
+ TEST(from_next == from + 1);
+ TEST(to_next == to + 1);
+ TEST(std::wstring(to, to_next) == std::wstring(L"1"));
+ }
+ {
+ char buf[4] = {};
+ char* const to = buf;
+ char* const to_end = buf + 4;
+ char* to_next = to;
+ const wchar_t* err_utf = L"\xD800"; // Trailing UTF-16 surrogate
+ std::mbstate_t mb = std::mbstate_t();
+ const wchar_t* from = err_utf;
+ const wchar_t* from_end = from + 1;
+ const wchar_t* from_next = from;
+ cvt_type::result res = cvt.out(mb, from, from_end, from_next, to, to_end, to_next);
+#ifdef BOOST_MSVC
+#pragma warning(disable : 4127) // Constant expression detected
+#endif
+ if(sizeof(wchar_t) == 2)
+ {
+ TEST(res == cvt_type::partial);
+ TEST(from_next == from_end);
+ TEST(to_next == to);
+ TEST(buf[0] == 0);
+ } else
+ {
+ TEST(res == cvt_type::ok);
+ TEST(from_next == from_end);
+ TEST(to_next == to + 3);
+ // surrogate is invalid
+ TEST(std::string(to, to_next) == boost::nowide::narrow(wreplacement_str));
+ }
+ }
+ }
+
+ std::cout << "- UTF-16/32" << std::endl;
+ {
+ char buf[32];
+ char* to = buf;
+ char* to_end = buf + 32;
+ char* to_next = to;
+ wchar_t err_buf[3] = {'1', 0xDC9E, 0}; // second surrogate not works both for UTF-16 and 32
+ const wchar_t* err_utf = err_buf;
+ {
+ std::mbstate_t mb = std::mbstate_t();
+ const wchar_t* from = err_utf;
+ const wchar_t* from_end = from + std::wcslen(from);
+ const wchar_t* from_next = from;
+ TEST(cvt.out(mb, from, from_end, from_next, to, to_end, to_next) == cvt_type::ok);
+ TEST(from_next == from + 2);
+ TEST(to_next == to + 4);
+ TEST(std::string(to, to_next) == "1" + boost::nowide::narrow(wreplacement_str));
+ }
+ }
+}
+
+std::wstring codecvt_to_wide(const std::string& s)
+{
+ std::locale l(std::locale::classic(), new boost::nowide::utf8_codecvt<wchar_t>());
+
+ const cvt_type& cvt = std::use_facet<cvt_type>(l);
+
+ std::mbstate_t mb = std::mbstate_t();
+ const char* const from = s.c_str();
+ const char* const from_end = from + s.size();
+ const char* from_next = from;
+
+ std::vector<wchar_t> buf(s.size() + 2); // +1 for possible incomplete char, +1 for NULL
+ wchar_t* const to = &buf[0];
+ wchar_t* const to_end = to + buf.size();
+ wchar_t* to_next = to;
+
+ cvt_type::result res = cvt.in(mb, from, from_end, from_next, to, to_end, to_next);
+ if(res == cvt_type::partial)
+ {
+ TEST(to_next < to_end);
+ *(to_next++) = BOOST_NOWIDE_REPLACEMENT_CHARACTER;
+ } else
+ TEST(res == cvt_type::ok);
+
+ return std::wstring(to, to_next);
+}
+
+std::string codecvt_to_narrow(const std::wstring& s)
+{
+ std::locale l(std::locale::classic(), new boost::nowide::utf8_codecvt<wchar_t>());
+
+ const cvt_type& cvt = std::use_facet<cvt_type>(l);
+
+ std::mbstate_t mb = std::mbstate_t();
+ const wchar_t* const from = s.c_str();
+ const wchar_t* const from_end = from + s.size();
+ const wchar_t* from_next = from;
+
+ std::vector<char> buf((s.size() + 1) * 4 + 1); // +1 for possible incomplete char, +1 for NULL
+ char* const to = &buf[0];
+ char* const to_end = to + buf.size();
+ char* to_next = to;
+
+ cvt_type::result res = cvt.out(mb, from, from_end, from_next, to, to_end, to_next);
+ if(res == cvt_type::partial)
+ {
+ TEST(to_next < to_end);
+ return std::string(to, to_next) + boost::nowide::narrow(wreplacement_str);
+ } else
+ TEST(res == cvt_type::ok);
+
+ return std::string(to, to_next);
+}
+
+void test_codecvt_subst()
+{
+ std::cout << "Substitutions " << std::endl;
+ run_all(codecvt_to_wide, codecvt_to_narrow);
+}
+
+void test_main(int, char**, char**)
+{
+ test_codecvt_conv();
+ test_codecvt_err();
+ test_codecvt_subst();
+}
diff --git a/src/boost/libs/nowide/test/test_convert.cpp b/src/boost/libs/nowide/test/test_convert.cpp
new file mode 100644
index 000000000..788689c97
--- /dev/null
+++ b/src/boost/libs/nowide/test/test_convert.cpp
@@ -0,0 +1,118 @@
+//
+// Copyright (c) 2012 Artyom Beilis (Tonkikh)
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/nowide/convert.hpp>
+#include <iostream>
+
+#include "test.hpp"
+#include "test_sets.hpp"
+
+#if defined(BOOST_MSVC) && BOOST_MSVC < 1700
+#pragma warning(disable : 4428) // universal-character-name encountered in source
+#endif
+
+std::wstring widen_buf_ptr(const std::string& s)
+{
+ wchar_t buf[50];
+ TEST(boost::nowide::widen(buf, 50, s.c_str()) == buf);
+ return buf;
+}
+
+std::string narrow_buf_ptr(const std::wstring& s)
+{
+ char buf[50];
+ TEST(boost::nowide::narrow(buf, 50, s.c_str()) == buf);
+ return buf;
+}
+
+std::wstring widen_buf_range(const std::string& s)
+{
+ wchar_t buf[50];
+ TEST(boost::nowide::widen(buf, 50, s.c_str(), s.c_str() + s.size()) == buf);
+ return buf;
+}
+
+std::string narrow_buf_range(const std::wstring& s)
+{
+ char buf[50];
+ TEST(boost::nowide::narrow(buf, 50, s.c_str(), s.c_str() + s.size()) == buf);
+ return buf;
+}
+
+std::wstring widen_raw_string(const std::string& s)
+{
+ return boost::nowide::widen(s.c_str());
+}
+
+std::string narrow_raw_string(const std::wstring& s)
+{
+ return boost::nowide::narrow(s.c_str());
+}
+
+std::wstring widen_raw_string_and_size(const std::string& s)
+{
+ // Remove NULL
+ const std::string s2 = s + "DummyData";
+ return boost::nowide::widen(s2.c_str(), s.size());
+}
+
+std::string narrow_raw_string_and_size(const std::wstring& s)
+{
+ // Remove NULL
+ const std::wstring s2 = s + L"DummyData";
+ return boost::nowide::narrow(s2.c_str(), s.size());
+}
+
+void test_main(int, char**, char**)
+{
+ std::string hello = "\xd7\xa9\xd7\x9c\xd7\x95\xd7\x9d";
+ std::wstring whello = L"\u05e9\u05dc\u05d5\u05dd";
+ std::wstring whello_3e = L"\u05e9\u05dc\u05d5\ufffd";
+ std::wstring whello_3 = L"\u05e9\u05dc\u05d5";
+
+ std::cout << "- boost::nowide::widen" << std::endl;
+ {
+ const char* b = hello.c_str();
+ const char* e = b + hello.size();
+ wchar_t buf[6] = {0, 0, 0, 0, 0, 1};
+ TEST(boost::nowide::widen(buf, 5, b, e) == buf);
+ TEST(buf == whello);
+ TEST(buf[5] == 1);
+ TEST(boost::nowide::widen(buf, 4, b, e) == 0);
+ TEST(boost::nowide::widen(buf, 5, b, e - 1) == buf);
+ TEST(buf == whello_3e);
+ TEST(boost::nowide::widen(buf, 5, b, e - 2) == buf);
+ TEST(buf == whello_3);
+ TEST(boost::nowide::widen(buf, 5, b, b) == buf && buf[0] == 0);
+ TEST(boost::nowide::widen(buf, 5, b, b + 2) == buf && buf[1] == 0 && buf[0] == whello[0]);
+ }
+ std::cout << "- boost::nowide::narrow" << std::endl;
+ {
+ const wchar_t* b = whello.c_str();
+ const wchar_t* e = b + whello.size(); //-V594
+ char buf[10] = {0};
+ buf[9] = 1;
+ TEST(boost::nowide::narrow(buf, 9, b, e) == buf);
+ TEST(buf == hello);
+ TEST(buf[9] == 1);
+ TEST(boost::nowide::narrow(buf, 8, b, e) == 0);
+ TEST(boost::nowide::narrow(buf, 7, b, e - 1) == buf);
+ TEST(buf == hello.substr(0, 6));
+ }
+
+ std::cout << "- (output_buffer, buffer_size, input_raw_string)" << std::endl;
+ run_all(widen_buf_ptr, narrow_buf_ptr);
+ std::cout << "- (output_buffer, buffer_size, input_raw_string, string_len)" << std::endl;
+ run_all(widen_buf_range, narrow_buf_range);
+ std::cout << "- (input_raw_string)" << std::endl;
+ run_all(widen_raw_string, narrow_raw_string);
+ std::cout << "- (input_raw_string, size)" << std::endl;
+ run_all(widen_raw_string_and_size, narrow_raw_string_and_size);
+ std::cout << "- (const std::string&)" << std::endl;
+ run_all(boost::nowide::widen, boost::nowide::narrow);
+}
diff --git a/src/boost/libs/nowide/test/test_env.cpp b/src/boost/libs/nowide/test/test_env.cpp
new file mode 100644
index 000000000..f9de36a5e
--- /dev/null
+++ b/src/boost/libs/nowide/test/test_env.cpp
@@ -0,0 +1,57 @@
+//
+// Copyright (c) 2012 Artyom Beilis (Tonkikh)
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/nowide/cstdlib.hpp>
+#include <cstring>
+
+#if defined(BOOST_NOWIDE_TEST_INCLUDE_WINDOWS) && defined(BOOST_WINDOWS)
+#include <windows.h>
+#endif
+
+#include "test.hpp"
+
+// "Safe" strcpy version with NULL termination to make MSVC runtime happy
+// which warns when using strncpy
+template<size_t size>
+void strcpy_safe(char (&dest)[size], const char* src)
+{
+ size_t len = std::strlen(src);
+ if(len >= size)
+ len = size - 1u;
+ std::memcpy(dest, src, len);
+ dest[len] = 0;
+}
+
+void test_main(int, char**, char**)
+{
+ std::string example = "\xd7\xa9-\xd0\xbc-\xce\xbd";
+ char penv[256] = {0};
+ strcpy_safe(penv, ("BOOST_TEST2=" + example + "x").c_str());
+
+ TEST(boost::nowide::setenv("BOOST_TEST1", example.c_str(), 1) == 0);
+ TEST(boost::nowide::getenv("BOOST_TEST1"));
+ TEST(boost::nowide::getenv("BOOST_TEST1") == example);
+ TEST(boost::nowide::setenv("BOOST_TEST1", "xx", 0) == 0);
+ TEST(boost::nowide::getenv("BOOST_TEST1") == example);
+ TEST(boost::nowide::putenv(penv) == 0);
+ TEST(boost::nowide::getenv("BOOST_TEST2"));
+ TEST(boost::nowide::getenv("BOOST_TEST_INVALID") == 0);
+ TEST(boost::nowide::getenv("BOOST_TEST2") == example + "x");
+#ifdef BOOST_WINDOWS
+ // Passing a variable without an equals sign (before \0) is an error
+ // But GLIBC has an extension that unsets the env var instead
+ char penv2[256] = {0};
+ const char* sPenv2 = "BOOST_TEST1SOMEGARBAGE=";
+ strcpy_safe(penv2, sPenv2);
+ // End the string before the equals sign -> Expect fail
+ penv2[strlen("BOOST_TEST1")] = '\0';
+ TEST(boost::nowide::putenv(penv2) == -1);
+ TEST(boost::nowide::getenv("BOOST_TEST1"));
+ TEST(boost::nowide::getenv("BOOST_TEST1") == example);
+#endif
+}
diff --git a/src/boost/libs/nowide/test/test_fs.cpp b/src/boost/libs/nowide/test/test_fs.cpp
new file mode 100644
index 000000000..1859bd8d1
--- /dev/null
+++ b/src/boost/libs/nowide/test/test_fs.cpp
@@ -0,0 +1,61 @@
+//
+// Copyright (c) 2015 Artyom Beilis (Tonkikh)
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/nowide/filesystem.hpp>
+
+#include <boost/nowide/convert.hpp>
+#include <boost/nowide/cstdio.hpp>
+#include <boost/nowide/fstream.hpp>
+#include <boost/filesystem/operations.hpp>
+
+#include "test.hpp"
+
+void test_main(int, char**, char**)
+{
+ boost::nowide::nowide_filesystem();
+ const std::string prefix = boost::filesystem::unique_path("nowide-%%%%-%%%%-").string();
+ const std::string utf8_name =
+ prefix + "\xf0\x9d\x92\x9e-\xD0\xBF\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD1\x82-\xE3\x82\x84\xE3\x81\x82.txt";
+
+ {
+ boost::nowide::ofstream f(utf8_name.c_str());
+ TEST(f);
+ f << "Test" << std::endl;
+ }
+
+ TEST(boost::filesystem::is_regular_file(boost::nowide::widen(utf8_name)));
+ TEST(boost::filesystem::is_regular_file(utf8_name));
+
+ TEST(boost::nowide::remove(utf8_name.c_str()) == 0);
+
+ TEST(!boost::filesystem::is_regular_file(boost::nowide::widen(utf8_name)));
+ TEST(!boost::filesystem::is_regular_file(utf8_name));
+
+ const boost::filesystem::path path = utf8_name;
+ {
+ boost::nowide::ofstream f(path);
+ TEST(f);
+ f << "Test" << std::endl;
+ TEST(is_regular_file(path));
+ }
+ {
+ boost::nowide::ifstream f(path);
+ TEST(f);
+ std::string test;
+ f >> test;
+ TEST(test == "Test");
+ }
+ {
+ boost::nowide::fstream f(path);
+ TEST(f);
+ std::string test;
+ f >> test;
+ TEST(test == "Test");
+ }
+ boost::filesystem::remove(path);
+}
diff --git a/src/boost/libs/nowide/test/test_fstream.cpp b/src/boost/libs/nowide/test/test_fstream.cpp
new file mode 100644
index 000000000..9fdd1f87b
--- /dev/null
+++ b/src/boost/libs/nowide/test/test_fstream.cpp
@@ -0,0 +1,513 @@
+//
+// Copyright (c) 2015 Artyom Beilis (Tonkikh)
+// Copyright (c) 2019 Alexander Grund
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/nowide/fstream.hpp>
+
+#include <boost/nowide/convert.hpp>
+#include <boost/nowide/cstdio.hpp>
+#include <fstream>
+#include <iostream>
+#include <string>
+
+#include "test.hpp"
+
+namespace nw = boost::nowide;
+
+void make_empty_file(const char* filepath)
+{
+ nw::ofstream f(filepath, std::ios_base::out | std::ios::trunc);
+ TEST(f);
+}
+
+bool file_exists(const char* filepath)
+{
+ FILE* f = nw::fopen(filepath, "r");
+ if(f)
+ {
+ std::fclose(f);
+ return true;
+ } else
+ return false;
+}
+
+std::string read_file(const char* filepath, bool binary_mode = false)
+{
+ FILE* f = nw::fopen(filepath, binary_mode ? "rb" : "r");
+ TEST(f);
+ std::string content;
+ int c;
+ while((c = std::fgetc(f)) != EOF)
+ content.push_back(static_cast<char>(c));
+ std::fclose(f);
+ return content;
+}
+
+void test_with_different_buffer_sizes(const char* filepath)
+{
+ /* Important part of the standard for mixing input with output:
+ However, output shall not be directly followed by input without an intervening call to the fflush function
+ or to a file positioning function (fseek, fsetpos, or rewind),
+ and input shall not be directly followed by output without an intervening call to a file positioning function,
+ unless the input operation encounters end-of-file.
+ */
+ for(int i = -1; i < 16; i++)
+ {
+ std::cout << "Buffer size = " << i << std::endl;
+ char buf[16];
+ nw::fstream f;
+ // Different conditions when setbuf might be called: Usually before opening a file is OK
+ if(i >= 0)
+ f.rdbuf()->pubsetbuf((i == 0) ? NULL : buf, i);
+ f.open(filepath, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary);
+ TEST(f);
+ // Add 'abcdefg'
+ TEST(f.put('a'));
+ TEST(f.put('b'));
+ TEST(f.put('c'));
+ TEST(f.put('d'));
+ TEST(f.put('e'));
+ TEST(f.put('f'));
+ TEST(f.put('g'));
+ // Read first char
+ TEST(f.seekg(0));
+ TEST(f.get() == 'a');
+ TEST(f.gcount() == 1u);
+ // Skip next char
+ TEST(f.seekg(1, std::ios::cur));
+ TEST(f.get() == 'c');
+ TEST(f.gcount() == 1u);
+ // Go back 1 char
+ TEST(f.seekg(-1, std::ios::cur));
+ TEST(f.get() == 'c');
+ TEST(f.gcount() == 1u);
+
+ // Test switching between read->write->read
+ // case 1) overwrite, flush, read
+ TEST(f.seekg(1));
+ TEST(f.put('B'));
+ TEST(f.flush()); // Flush when changing out->in
+ TEST(f.get() == 'c');
+ TEST(f.gcount() == 1u);
+ TEST(f.seekg(1));
+ TEST(f.get() == 'B');
+ TEST(f.gcount() == 1u);
+ // case 2) overwrite, seek, read
+ TEST(f.seekg(2));
+ TEST(f.put('C'));
+ TEST(f.seekg(3)); // Seek when changing out->in
+ TEST(f.get() == 'd');
+ TEST(f.gcount() == 1u);
+
+ // Check that sequence from start equals expected
+ TEST(f.seekg(0));
+ TEST(f.get() == 'a');
+ TEST(f.get() == 'B');
+ TEST(f.get() == 'C');
+ TEST(f.get() == 'd');
+ TEST(f.get() == 'e');
+
+ // Putback after flush is implementation defined
+ // Boost.Nowide: Works
+#if BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT
+ TEST(f << std::flush);
+ TEST(f.putback('e'));
+ TEST(f.putback('d'));
+ TEST(f.get() == 'd');
+ TEST(f.get() == 'e');
+#endif
+ // Rest of sequence
+ TEST(f.get() == 'f');
+ TEST(f.get() == 'g');
+ TEST(f.get() == EOF);
+
+ // Put back until front of file is reached
+ f.clear();
+ TEST(f.seekg(1));
+ TEST(f.get() == 'B');
+ TEST(f.putback('B'));
+ // Putting back multiple chars is not possible on all implementations after a seek/flush
+#if BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT
+ TEST(f.putback('a'));
+ TEST(!f.putback('x')); // At beginning of file -> No putback possible
+ // Get characters that were putback to avoid MSVC bug https://github.com/microsoft/STL/issues/342
+ f.clear();
+ TEST(f.get() == 'a');
+#endif
+ TEST(f.get() == 'B');
+ f.close();
+ TEST(nw::remove(filepath) == 0);
+ }
+}
+
+void test_close(const char* filepath)
+{
+ const std::string filepath2 = std::string(filepath) + ".2";
+ // Make sure file does not exist yet
+ TEST(!file_exists(filepath2.c_str()) || nw::remove(filepath2.c_str()) == 0);
+ TEST(!file_exists(filepath2.c_str()));
+ nw::filebuf buf;
+ TEST(buf.open(filepath, std::ios_base::out) == &buf);
+ TEST(buf.is_open());
+ // Opening when already open fails
+ TEST(buf.open(filepath2.c_str(), std::ios_base::out) == NULL);
+ // Still open
+ TEST(buf.is_open());
+ TEST(buf.close() == &buf);
+ // Failed opening did not create file
+ TEST(!file_exists(filepath2.c_str()));
+ // But it should work now:
+ TEST(buf.open(filepath2.c_str(), std::ios_base::out) == &buf);
+ TEST(buf.close() == &buf);
+ TEST(file_exists(filepath2.c_str()));
+ TEST(nw::remove(filepath) == 0);
+ TEST(nw::remove(filepath2.c_str()) == 0);
+}
+
+template<typename IFStream, typename OFStream>
+void test_flush(const char* filepath)
+{
+ OFStream fo(filepath, std::ios_base::out | std::ios::trunc);
+ TEST(fo);
+ std::string curValue;
+ for(int repeat = 0; repeat < 2; repeat++)
+ {
+ for(size_t len = 1; len <= 1024; len *= 2)
+ {
+ char c = static_cast<char>(len % 13 + repeat + 'a'); // semi-random char
+ std::string input(len, c);
+ fo << input;
+ curValue += input;
+ TEST(fo.flush());
+ std::string s;
+ // Note: Flush on read area is implementation defined, so check whole file instead
+ IFStream fi(filepath);
+ TEST(fi >> s);
+ // coverity[tainted_data]
+ TEST(s == curValue);
+ }
+ }
+}
+
+void test_ofstream_creates_file(const char* filename)
+{
+ TEST(!file_exists(filename) || nw::remove(filename) == 0);
+ TEST(!file_exists(filename));
+ // Ctor
+ {
+ nw::ofstream fo(filename);
+ TEST(fo);
+ }
+ TEST(file_exists(filename));
+ TEST(read_file(filename).empty());
+ TEST(nw::remove(filename) == 0);
+ // Open
+ {
+ nw::ofstream fo;
+ fo.open(filename);
+ TEST(fo);
+ }
+ TEST(file_exists(filename));
+ TEST(read_file(filename).empty());
+ TEST(nw::remove(filename) == 0);
+}
+
+// Create filename file with content "test\n"
+void test_ofstream_write(const char* filename)
+{
+ // char* ctor
+ {
+ nw::ofstream fo(filename);
+ TEST(fo << "test" << 2 << std::endl);
+ }
+ // char* open
+ TEST(read_file(filename) == "test2\n");
+ TEST(nw::remove(filename) == 0);
+ {
+ nw::ofstream fo;
+ fo.open(filename);
+ TEST(fo << "test" << 2 << std::endl);
+ }
+ TEST(read_file(filename) == "test2\n");
+ TEST(nw::remove(filename) == 0);
+ // string ctor
+ {
+ std::string name = filename;
+ nw::ofstream fo(name);
+ TEST(fo << "test" << 2 << std::endl);
+ }
+ TEST(read_file(filename) == "test2\n");
+ TEST(nw::remove(filename) == 0);
+ // string open
+ {
+ nw::ofstream fo;
+ fo.open(std::string(filename));
+ TEST(fo << "test" << 2 << std::endl);
+ }
+ TEST(read_file(filename) == "test2\n");
+ TEST(nw::remove(filename) == 0);
+ // Binary mode
+ {
+ nw::ofstream fo(filename, std::ios::binary);
+ TEST(fo << "test" << 2 << std::endl);
+ }
+ TEST(read_file(filename, true) == "test2\n");
+ TEST(nw::remove(filename) == 0);
+ // At end
+ {
+ {
+ nw::ofstream fo(filename);
+ TEST(fo << "test" << 2 << std::endl);
+ }
+ nw::ofstream fo(filename, std::ios::ate | std::ios::in);
+ fo << "second" << 2 << std::endl;
+ }
+ TEST(read_file(filename) == "test2\nsecond2\n");
+ TEST(nw::remove(filename) == 0);
+}
+
+void test_ifstream_open_read(const char* filename)
+{
+ // Create test file
+ {
+ nw::ofstream fo(filename);
+ TEST(fo << "test" << std::endl);
+ }
+
+ // char* Ctor
+ {
+ nw::ifstream fi(filename);
+ TEST(fi);
+ std::string tmp;
+ TEST(fi >> tmp);
+ TEST(tmp == "test");
+ }
+ // char* open
+ {
+ nw::ifstream fi;
+ fi.open(filename);
+ TEST(fi);
+ std::string tmp;
+ TEST(fi >> tmp);
+ TEST(tmp == "test");
+ }
+ // string ctor
+ {
+ std::string name = filename;
+ nw::ifstream fi(name);
+ TEST(fi);
+ std::string tmp;
+ TEST(fi >> tmp);
+ TEST(tmp == "test");
+ }
+ // string open
+ {
+ nw::ifstream fi;
+ fi.open(std::string(filename));
+ TEST(fi);
+ std::string tmp;
+ TEST(fi >> tmp);
+ TEST(tmp == "test");
+ }
+ // Binary mode
+ {
+ nw::ifstream fi(filename, std::ios::binary);
+ TEST(fi);
+ std::string tmp;
+ TEST(fi >> tmp);
+ TEST(tmp == "test");
+ }
+ // At end
+ {
+ // Need binary file or position check might be throw off by newline conversion
+ {
+ nw::ofstream fo(filename, nw::fstream::binary);
+ TEST(fo << "test");
+ }
+ nw::ifstream fi(filename, nw::fstream::ate | nw::fstream::binary);
+ TEST(fi);
+ TEST(fi.tellg() == std::streampos(4));
+ fi.seekg(-2, std::ios_base::cur);
+ std::string tmp;
+ TEST(fi >> tmp);
+ TEST(tmp == "st");
+ }
+ // Fail on non-existing file
+ TEST(nw::remove(filename) == 0);
+ {
+ nw::ifstream fi(filename);
+ TEST(!fi);
+ }
+}
+
+void test_fstream(const char* filename)
+{
+ const std::string sFilename = filename;
+ TEST(!file_exists(filename) || nw::remove(filename) == 0);
+ TEST(!file_exists(filename));
+ // Fail on non-existing file
+ {
+ nw::fstream f(filename);
+ TEST(!f);
+ nw::fstream f2(sFilename);
+ TEST(!f2);
+ }
+ {
+ nw::fstream f;
+ f.open(filename);
+ TEST(!f);
+ f.open(sFilename);
+ TEST(!f);
+ }
+ TEST(!file_exists(filename));
+ // Create empty file (Ctor)
+ {
+ nw::fstream f(filename, std::ios::out);
+ TEST(f);
+ }
+ TEST(read_file(filename).empty());
+ // Char* ctor
+ {
+ nw::fstream f(filename);
+ TEST(f);
+ TEST(f << "test");
+ std::string tmp;
+ TEST(f.seekg(0));
+ TEST(f >> tmp);
+ TEST(tmp == "test");
+ }
+ TEST(read_file(filename) == "test");
+ // String ctor
+ {
+ nw::fstream f(sFilename);
+ TEST(f);
+ TEST(f << "string_ctor");
+ std::string tmp;
+ TEST(f.seekg(0));
+ TEST(f >> tmp);
+ TEST(tmp == "string_ctor");
+ }
+ TEST(read_file(filename) == "string_ctor");
+ TEST(nw::remove(filename) == 0);
+ // Create empty file (open)
+ {
+ nw::fstream f;
+ f.open(filename, std::ios::out);
+ TEST(f);
+ }
+ TEST(read_file(filename).empty());
+ // Open
+ {
+ nw::fstream f;
+ f.open(filename);
+ TEST(f);
+ TEST(f << "test");
+ std::string tmp;
+ TEST(f.seekg(0));
+ TEST(f >> tmp);
+ TEST(tmp == "test");
+ }
+ TEST(read_file(filename) == "test");
+ // Ctor existing file
+ {
+ nw::fstream f(filename);
+ TEST(f);
+ std::string tmp;
+ TEST(f >> tmp);
+ TEST(tmp == "test");
+ TEST(f.eof());
+ f.clear();
+ TEST(f << "second");
+ }
+ TEST(read_file(filename) == "testsecond");
+ // Trunc & binary
+ {
+ nw::fstream f(filename, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary);
+ TEST(f);
+ TEST(f << "test2");
+ std::string tmp;
+ TEST(f.seekg(0));
+ TEST(f >> tmp);
+ TEST(tmp == "test2");
+ }
+ TEST(read_file(filename) == "test2");
+ // Reading in write mode fails (existing file!)
+ {
+ nw::fstream f(filename, std::ios::out);
+ std::string tmp;
+ TEST(!(f >> tmp));
+ f.clear();
+ TEST(f << "foo");
+ TEST(f.seekg(0));
+ TEST(!(f >> tmp));
+ }
+ TEST(read_file(filename) == "foo");
+ // Writing in read mode fails (existing file!)
+ {
+ nw::fstream f(filename, std::ios::in);
+ TEST(!(f << "bar"));
+ f.clear();
+ std::string tmp;
+ TEST(f >> tmp);
+ TEST(tmp == "foo");
+ }
+ TEST(read_file(filename) == "foo");
+ TEST(nw::remove(filename) == 0);
+}
+
+template<typename T>
+bool is_open(T& stream)
+{
+ // There are const and non const versions of is_open, so test both
+ TEST(stream.is_open() == const_cast<const T&>(stream).is_open());
+ return stream.is_open();
+}
+
+template<typename T>
+void do_test_is_open(const char* filename)
+{
+ T f;
+ TEST(!is_open(f));
+ f.open(filename);
+ TEST(f);
+ TEST(is_open(f));
+ f.close();
+ TEST(f);
+ TEST(!is_open(f));
+}
+
+void test_is_open(const char* filename)
+{
+ // Note the order: Output before input so file exists
+ do_test_is_open<nw::ofstream>(filename);
+ do_test_is_open<nw::ifstream>(filename);
+ do_test_is_open<nw::fstream>(filename);
+ TEST(nw::remove(filename) == 0);
+}
+
+void test_main(int, char** argv, char**)
+{
+ const std::string exampleFilename = std::string(argv[0]) + "-\xd7\xa9-\xd0\xbc-\xce\xbd.txt";
+ std::cout << "Testing fstream" << std::endl;
+ test_ofstream_creates_file(exampleFilename.c_str());
+ test_ofstream_write(exampleFilename.c_str());
+ test_ifstream_open_read(exampleFilename.c_str());
+ test_fstream(exampleFilename.c_str());
+ test_is_open(exampleFilename.c_str());
+
+ std::cout << "Complex IO" << std::endl;
+ test_with_different_buffer_sizes(exampleFilename.c_str());
+
+ std::cout << "filebuf::close" << std::endl;
+ test_close(exampleFilename.c_str());
+
+ std::cout << "Flush - Sanity Check" << std::endl;
+ test_flush<std::ifstream, std::ofstream>(exampleFilename.c_str());
+ std::cout << "Flush - Test" << std::endl;
+ test_flush<nw::ifstream, nw::ofstream>(exampleFilename.c_str());
+}
diff --git a/src/boost/libs/nowide/test/test_fstream_cxx11.cpp b/src/boost/libs/nowide/test/test_fstream_cxx11.cpp
new file mode 100644
index 000000000..3ad16b711
--- /dev/null
+++ b/src/boost/libs/nowide/test/test_fstream_cxx11.cpp
@@ -0,0 +1,201 @@
+//
+// Copyright (c) 2019 Alexander Grund
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/nowide/config.hpp>
+
+#if BOOST_NOWIDE_CXX11
+
+#include <boost/nowide/fstream.hpp>
+
+#include <boost/nowide/cstdio.hpp>
+#include <iterator>
+#include <utility>
+
+#include "test.hpp"
+
+namespace nw = boost::nowide;
+
+void create_file(const std::string& filename, const std::string& contents)
+{
+ nw::ofstream f(filename, std::ios::trunc);
+ TEST(f << contents);
+}
+
+template<typename T>
+std::string get_file_contents(T& stream)
+{
+ TEST(stream);
+ std::string s((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>());
+ return s;
+}
+
+std::string get_file_contents(const std::string& filename)
+{
+ nw::ifstream f(filename);
+ return get_file_contents(f);
+}
+
+nw::ifstream make_ifstream(const std::string& filename)
+{
+ nw::ifstream f(filename);
+ TEST(f);
+ std::string s;
+ TEST(f >> s);
+ TEST(s == "Hello");
+ return f;
+}
+
+void test_ifstream(const std::string& filename)
+{
+ create_file(filename, "Hello\nWorld");
+ // Move construct
+ {
+ nw::ifstream f = make_ifstream(filename);
+ TEST(f);
+ std::string s;
+ TEST(f >> s);
+ TEST(s == "World");
+ }
+ // Move assign
+ {
+ nw::ifstream f;
+ {
+ nw::ifstream f2 = make_ifstream(filename);
+ f = std::move(f2);
+ }
+ TEST(f);
+ std::string s;
+ TEST(f >> s);
+ TEST(s == "World");
+ }
+ // Swap
+ {
+ nw::ifstream f;
+ {
+ nw::ifstream f2 = make_ifstream(filename);
+ swap(f, f2);
+ TEST(!f2.is_open());
+ }
+ TEST(f);
+ std::string s;
+ TEST(f >> s);
+ TEST(s == "World");
+ }
+ TEST(nw::remove(filename.c_str()) == 0);
+}
+
+nw::ofstream make_ofstream(const std::string& filename)
+{
+ nw::ofstream f(filename);
+ TEST(f);
+ TEST(f << "Hello");
+ return f;
+}
+
+void test_ofstream(const std::string& filename)
+{
+ // Move construct
+ {
+ nw::ofstream f = make_ofstream(filename);
+ TEST(f);
+ TEST(f << " world");
+ f.close();
+ TEST(get_file_contents(filename) == "Hello world");
+ }
+ // Move assign
+ {
+ nw::ofstream f;
+ {
+ nw::ofstream f2 = make_ofstream(filename);
+ f = std::move(f2);
+ }
+ TEST(f);
+ TEST(f << " world");
+ f.close();
+ TEST(get_file_contents(filename) == "Hello world");
+ }
+ // Swap
+ {
+ nw::ofstream f;
+ {
+ nw::ofstream f2 = make_ofstream(filename);
+ swap(f, f2);
+ TEST(!f2.is_open());
+ }
+ TEST(f);
+ TEST(f << " world");
+ f.close();
+ TEST(get_file_contents(filename) == "Hello world");
+ }
+ TEST(nw::remove(filename.c_str()) == 0);
+}
+
+nw::fstream make_fstream(const std::string& filename)
+{
+ create_file(filename, "");
+ nw::fstream f(filename);
+ TEST(f << "Hello");
+ return f;
+}
+
+void test_fstream(const std::string& filename)
+{
+ // Move construct
+ {
+ nw::fstream f = make_fstream(filename);
+ TEST(f);
+ TEST(f << " world");
+ f.seekg(0);
+ TEST(get_file_contents(f) == "Hello world");
+ }
+ // Move assign
+ {
+ nw::fstream f;
+ {
+ nw::fstream f2 = make_fstream(filename);
+ f = std::move(f2);
+ }
+ TEST(f);
+ TEST(f << " world");
+ f.seekg(0);
+ TEST(get_file_contents(f) == "Hello world");
+ }
+ // Swap
+ {
+ nw::fstream f;
+ {
+ nw::fstream f2 = make_fstream(filename);
+ swap(f, f2);
+ TEST(!f2.is_open());
+ }
+ TEST(f);
+ TEST(f << " world");
+ f.seekg(0);
+ TEST(get_file_contents(f) == "Hello world");
+ }
+ TEST(nw::remove(filename.c_str()) == 0);
+}
+
+void test_main(int, char** argv, char**)
+{
+ const std::string exampleFilename = std::string(argv[0]) + "-\xd7\xa9-\xd0\xbc-\xce\xbd.txt";
+ test_ifstream(exampleFilename);
+ test_ofstream(exampleFilename);
+ test_fstream(exampleFilename);
+}
+
+#else
+
+#include <iostream>
+
+int main()
+{
+ std::cout << "Test skipped as there is no C++11 support by the compiler" << std::endl;
+}
+
+#endif
diff --git a/src/boost/libs/nowide/test/test_iostream.cpp b/src/boost/libs/nowide/test/test_iostream.cpp
new file mode 100644
index 000000000..cd5078f10
--- /dev/null
+++ b/src/boost/libs/nowide/test/test_iostream.cpp
@@ -0,0 +1,87 @@
+//
+// Copyright (c) 2015 Artyom Beilis (Tonkikh)
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/nowide/iostream.hpp>
+
+#include <boost/nowide/detail/utf.hpp>
+#include <string>
+
+#include "test.hpp"
+
+bool isValidUTF8(const std::string& s)
+{
+ using namespace boost::nowide::detail::utf;
+ for(std::string::const_iterator it = s.begin(); it != s.end();)
+ {
+ code_point c = utf_traits<char>::decode(it, s.end());
+ if(!is_valid_codepoint(c))
+ return false;
+ }
+ return true;
+}
+
+void test_main(int argc, char** argv, char**)
+{
+ const char* example = "Basic letters: \xd7\xa9-\xd0\xbc-\xce\xbd\n"
+ "East Asian Letters: \xe5\x92\x8c\xe5\xb9\xb3\n"
+ "Non-BMP letters: \xf0\x9d\x84\x9e\n"
+ "Invalid UTF-8: `\xFF' `\xd7\xFF' `\xe5\xFF\x8c' `\xf0\x9d\x84\xFF' \n"
+ "\n";
+
+ // If we are using the standard rdbuf we can only put back 1 char
+ if(boost::nowide::cin.rdbuf() == std::cin.rdbuf())
+ {
+ std::cout << "Using std::cin" << std::endl;
+ int maxval = 15000;
+ for(int i = 0; i < maxval; i++)
+ {
+ char c = i % 96 + ' ';
+ TEST(boost::nowide::cin.putback(c));
+ int ci = i % 96 + ' ';
+ TEST(boost::nowide::cin.get() == ci);
+ }
+ } else
+ {
+ int maxval = 15000;
+ for(int i = 0; i < maxval; i++)
+ {
+ char c = i % 96 + ' ';
+ TEST(boost::nowide::cin.putback(c));
+ }
+ for(int i = maxval - 1; i >= 0; i--)
+ {
+ int c = i % 96 + ' ';
+ TEST(boost::nowide::cin.get() == c);
+ }
+ }
+ boost::nowide::cout << "Normal I/O:" << std::endl;
+ boost::nowide::cout << example << std::endl;
+ boost::nowide::cerr << example << std::endl;
+
+ boost::nowide::cout << "Flushing each character:" << std::endl;
+
+ for(const char* s = example; *s; s++)
+ {
+ boost::nowide::cout << *s << std::flush;
+ TEST(boost::nowide::cout);
+ }
+
+ TEST(boost::nowide::cout);
+ TEST(boost::nowide::cerr);
+ if(argc == 2 && argv[1] == std::string("-i"))
+ {
+ std::string v1, v2;
+ boost::nowide::cin >> v1 >> v2;
+ TEST(boost::nowide::cin);
+ TEST(isValidUTF8(v1));
+ TEST(isValidUTF8(v2));
+ boost::nowide::cout << "First: " << v1 << std::endl;
+ boost::nowide::cout << "Second: " << v2 << std::endl;
+ TEST(boost::nowide::cout);
+ }
+}
diff --git a/src/boost/libs/nowide/test/test_sets.hpp b/src/boost/libs/nowide/test/test_sets.hpp
new file mode 100644
index 000000000..10243e9b8
--- /dev/null
+++ b/src/boost/libs/nowide/test/test_sets.hpp
@@ -0,0 +1,135 @@
+//
+// Copyright (c) 2012 Artyom Beilis (Tonkikh)
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+#ifndef BOOST_NOWIDE_TEST_SETS_HPP_INCLUDED
+#define BOOST_NOWIDE_TEST_SETS_HPP_INCLUDED
+
+#include <boost/nowide/config.hpp>
+#include <iostream>
+#include <string>
+
+struct utf8_to_wide
+{
+ const char* utf8;
+ const wchar_t* wide;
+};
+
+struct wide_to_utf8
+{
+ const wchar_t* wide;
+ const char* utf8;
+};
+
+#if defined(BOOST_MSVC) && BOOST_MSVC < 1700
+#pragma warning(disable : 4428) // universal-character-name encountered in source
+#endif
+
+const std::wstring wreplacement_str(1, wchar_t(BOOST_NOWIDE_REPLACEMENT_CHARACTER));
+
+// clang-format off
+const utf8_to_wide roundtrip_tests[] = {
+ {"", L""},
+ {"\xf0\x9d\x92\x9e-\xD0\xBF\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD1\x82-\xE3\x82\x84\xE3\x81\x82.txt",
+ L"\U0001D49E-\u043F\u0440\u0438\u0432\u0435\u0442-\u3084\u3042.txt"},
+ {"\xd7\xa9-\xd0\xbc-\xce\xbd.txt",
+ L"\u05e9-\u043c-\u03bd.txt"},
+ {"\xd7\xa9\xd7\x9c\xd7\x95\xd7\x9d",
+ L"\u05e9\u05dc\u05d5\u05dd"},
+};
+
+const utf8_to_wide invalid_utf8_tests[] = {
+ {"\xFF\xFF", L"\ufffd\ufffd"},
+ {"\xd7\xa9\xFF", L"\u05e9\ufffd"},
+ {"\xd7", L"\ufffd"},
+ {"\xFF\xd7\xa9", L"\ufffd\u05e9"},
+ {"\xFF\xD0\xBF\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD1\x82", L"\uFFFD\u043F\u0440\u0438\u0432\u0435\u0442"},
+ {"\xD0\xBF\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD1\x82\xFF", L"\u043F\u0440\u0438\u0432\u0435\u0442\uFFFD"},
+ {"\xE3\x82\xFF\xE3\x81\x82", L"\ufffd\u3042"},
+ {"\xE3\xFF\x84\xE3\x81\x82", L"\ufffd\ufffd\u3042"},
+};
+
+const wide_to_utf8 invalid_wide_tests[] = {
+ {L"\xDC01\x05e9", "\xEF\xBF\xBD\xd7\xa9"},
+ {L"\x05e9\xD800", "\xd7\xa9\xEF\xBF\xBD"},
+ {L"\xDC00\x20\u043F\u0440\u0438\u0432\u0435\u0442-\u3084\u3042",
+ "\xEF\xBF\xBD \xD0\xBF\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD1\x82-\xE3\x82\x84\xE3\x81\x82"},
+ {L"\u3084\u3042\xDC00\x20\u043F\u0440\u0438\u0432\u0435\u0442-\u3084\u3042",
+ "\xE3\x82\x84\xE3\x81\x82\xEF\xBF\xBD \xD0\xBF\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD1\x82-\xE3\x82\x84\xE3\x81\x82"},
+};
+
+
+const wide_to_utf8 invalid_utf16_tests[] = {
+ {L"\xD800\x20\u043F\u0440\u0438\u0432\u0435\u0442-\u3084\u3042",
+ "\xEF\xBF\xBD\xD0\xBF\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD1\x82-\xE3\x82\x84\xE3\x81\x82"},
+ {L"\u3084\u3042\xD800\x20\u043F\u0440\u0438\u0432\u0435\u0442-\u3084\u3042",
+ "\xE3\x82\x84\xE3\x81\x82\xEF\xBF\xBD\xD0\xBF\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD1\x82-\xE3\x82\x84\xE3\x81\x82"},
+};
+
+const wide_to_utf8 invalid_utf32_tests[] = {
+ {L"\xD800\x20\u043F\u0440\u0438\u0432\u0435\u0442-\u3084\u3042",
+ "\xEF\xBF\xBD \xD0\xBF\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD1\x82-\xE3\x82\x84\xE3\x81\x82"},
+ {L"\u3084\u3042\xD800\x20\u043F\u0440\u0438\u0432\u0435\u0442-\u3084\u3042",
+ "\xE3\x82\x84\xE3\x81\x82\xEF\xBF\xBD \xD0\xBF\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD1\x82-\xE3\x82\x84\xE3\x81\x82"},
+};
+
+// clang-format on
+
+#ifdef BOOST_MSVC
+#pragma warning(push)
+#pragma warning(disable : 4127) // Constant expression detected
+#endif
+
+template<typename T, size_t N>
+size_t array_size(const T (&)[N])
+{
+ return N;
+}
+
+void run_all(std::wstring (*to_wide)(const std::string&), std::string (*to_narrow)(const std::wstring&))
+{
+ for(size_t i = 0; i < array_size(roundtrip_tests); i++)
+ {
+ std::cout << " Roundtrip " << i << std::endl;
+ TEST(roundtrip_tests[i].utf8 == to_narrow(roundtrip_tests[i].wide));
+ TEST(to_wide(roundtrip_tests[i].utf8) == roundtrip_tests[i].wide);
+ }
+
+ for(size_t i = 0; i < array_size(invalid_utf8_tests); i++)
+ {
+ std::cout << " Invalid UTF8 " << i << std::endl;
+ TEST(to_wide(invalid_utf8_tests[i].utf8) == invalid_utf8_tests[i].wide);
+ }
+
+ for(size_t i = 0; i < array_size(invalid_wide_tests); i++)
+ {
+ std::cout << " Invalid Wide " << i << std::endl;
+ TEST(to_narrow(invalid_wide_tests[i].wide) == invalid_wide_tests[i].utf8);
+ }
+
+ size_t total = 0;
+ const wide_to_utf8* ptr = 0;
+ if(sizeof(wchar_t) == 2)
+ {
+ ptr = invalid_utf16_tests;
+ total = array_size(invalid_utf16_tests);
+ } else
+ {
+ ptr = invalid_utf32_tests;
+ total = array_size(invalid_utf32_tests);
+ }
+ for(size_t i = 0; i < total; i++)
+ {
+ std::cout << " Invalid UTF16/32 " << i << std::endl;
+ TEST(to_narrow(ptr[i].wide) == ptr[i].utf8);
+ }
+}
+
+#endif
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
diff --git a/src/boost/libs/nowide/test/test_stackstring.cpp b/src/boost/libs/nowide/test/test_stackstring.cpp
new file mode 100644
index 000000000..df675c54c
--- /dev/null
+++ b/src/boost/libs/nowide/test/test_stackstring.cpp
@@ -0,0 +1,256 @@
+//
+// Copyright (c) 2012 Artyom Beilis (Tonkikh)
+// Copyright (c) 2019-2020 Alexander Grund
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/nowide/stackstring.hpp>
+#include <iostream>
+#include <vector>
+
+#include "test.hpp"
+#include "test_sets.hpp"
+
+#if defined(BOOST_MSVC) && BOOST_MSVC < 1700
+#pragma warning(disable : 4428) // universal-character-name encountered in source
+#endif
+
+template<typename CharOut, typename CharIn, size_t BufferSize>
+class test_basic_stackstring : public boost::nowide::basic_stackstring<CharOut, CharIn, BufferSize>
+{
+public:
+ typedef boost::nowide::basic_stackstring<CharOut, CharIn, BufferSize> parent;
+
+#if BOOST_NOWIDE_CXX11
+ using parent::parent;
+#else
+ test_basic_stackstring()
+ {}
+ explicit test_basic_stackstring(const CharIn* input) : parent(input)
+ {}
+ test_basic_stackstring(const CharIn* begin, const CharIn* end) : parent(begin, end)
+ {}
+#endif
+ using parent::uses_stack_memory;
+ bool uses_heap_memory() const
+ {
+ return !uses_stack_memory() && this->get();
+ }
+};
+
+typedef test_basic_stackstring<wchar_t, char, 256> test_wstackstring;
+typedef test_basic_stackstring<char, wchar_t, 256> test_stackstring;
+
+std::wstring stackstring_to_wide(const std::string& s)
+{
+ const test_wstackstring ss(s.c_str());
+ TEST(ss.uses_stack_memory());
+ return ss.get();
+}
+
+std::string stackstring_to_narrow(const std::wstring& s)
+{
+ const test_stackstring ss(s.c_str());
+ TEST(ss.uses_stack_memory());
+ return ss.get();
+}
+
+std::wstring heap_stackstring_to_wide(const std::string& s)
+{
+ const test_basic_stackstring<wchar_t, char, 1> ss(s.c_str());
+ TEST(ss.uses_heap_memory() || s.empty());
+ return ss.get();
+}
+
+std::string heap_stackstring_to_narrow(const std::wstring& s)
+{
+ const test_basic_stackstring<char, wchar_t, 1> ss(s.c_str());
+ TEST(ss.uses_heap_memory() || s.empty());
+ return ss.get();
+}
+
+void test_main(int, char**, char**)
+{
+ std::string hello = "\xd7\xa9\xd7\x9c\xd7\x95\xd7\x9d";
+ std::wstring whello = boost::nowide::widen(hello);
+ const wchar_t* wempty = L"";
+
+ {
+ std::cout << "-- Default constructed string is NULL" << std::endl;
+ const boost::nowide::short_stackstring s;
+ TEST(s.get() == NULL);
+ }
+ {
+ std::cout << "-- NULL ptr passed to ctor results in NULL" << std::endl;
+ const boost::nowide::short_stackstring s(NULL);
+ TEST(s.get() == NULL);
+ const boost::nowide::short_stackstring s2(NULL, NULL);
+ TEST(s2.get() == NULL);
+ }
+ {
+ std::cout << "-- NULL ptr passed to convert results in NULL" << std::endl;
+ boost::nowide::short_stackstring s(L"foo");
+ TEST(s.get() == std::string("foo"));
+ s.convert(NULL);
+ TEST(s.get() == NULL);
+ boost::nowide::short_stackstring s2(L"foo");
+ TEST(s2.get() == std::string("foo"));
+ s2.convert(NULL, NULL);
+ TEST(s2.get() == NULL);
+ }
+ {
+ std::cout << "-- An empty string is accepted" << std::endl;
+ const boost::nowide::short_stackstring s(wempty);
+ TEST(s.get());
+ TEST(s.get() == std::string());
+ const boost::nowide::short_stackstring s2(wempty, wempty);
+ TEST(s2.get());
+ TEST(s2.get() == std::string());
+ }
+ {
+ std::cout << "-- An empty string is accepted" << std::endl;
+ boost::nowide::short_stackstring s, s2;
+ TEST(s.convert(wempty));
+ TEST(s.get() == std::string());
+ TEST(s2.convert(wempty, wempty));
+ TEST(s2.get() == std::string());
+ }
+ {
+ std::cout << "-- Will be put on heap" << std::endl;
+ test_basic_stackstring<wchar_t, char, 3> sw;
+ TEST(sw.convert(hello.c_str()));
+ TEST(sw.uses_heap_memory());
+ TEST(sw.get() == whello);
+ TEST(sw.convert(hello.c_str(), hello.c_str() + hello.size()));
+ TEST(sw.uses_heap_memory());
+ TEST(sw.get() == whello);
+ }
+ {
+ std::cout << "-- Will be put on stack" << std::endl;
+ test_basic_stackstring<wchar_t, char, 40> sw;
+ TEST(sw.convert(hello.c_str()));
+ TEST(sw.uses_stack_memory());
+ TEST(sw.get() == whello);
+ TEST(sw.convert(hello.c_str(), hello.c_str() + hello.size()));
+ TEST(sw.uses_stack_memory());
+ TEST(sw.get() == whello);
+ }
+ {
+ std::cout << "-- Will be put on heap" << std::endl;
+ test_basic_stackstring<char, wchar_t, 3> sw;
+ TEST(sw.convert(whello.c_str()));
+ TEST(sw.uses_heap_memory());
+ TEST(sw.get() == hello);
+ TEST(sw.convert(whello.c_str(), whello.c_str() + whello.size()));
+ TEST(sw.uses_heap_memory());
+ TEST(sw.get() == hello);
+ }
+ {
+ std::cout << "-- Will be put on stack" << std::endl;
+ test_basic_stackstring<char, wchar_t, 40> sw;
+ TEST(sw.convert(whello.c_str()));
+ TEST(sw.uses_stack_memory());
+ TEST(sw.get() == hello);
+ TEST(sw.convert(whello.c_str(), whello.c_str() + whello.size()));
+ TEST(sw.uses_stack_memory());
+ TEST(sw.get() == hello);
+ }
+ {
+ typedef test_basic_stackstring<wchar_t, char, 6> stackstring;
+ const std::wstring heapVal = L"heapValue";
+ const std::wstring stackVal = L"stack";
+ const stackstring heap(boost::nowide::narrow(heapVal).c_str());
+ const stackstring stack(boost::nowide::narrow(stackVal).c_str());
+ TEST(heap.uses_heap_memory());
+ TEST(stack.uses_stack_memory());
+
+ {
+ stackstring sw2(heap), sw3, sEmpty;
+ sw3 = heap;
+ TEST(sw2.get() == heapVal);
+ TEST(sw3.get() == heapVal);
+ // Self assign avoiding clang self-assign-overloaded warning
+ sw3 = static_cast<const stackstring&>(sw3); //-V570
+ TEST(sw3.get() == heapVal);
+ // Assign empty
+ sw3 = sEmpty; //-V820
+ TEST(sw3.get() == NULL);
+ }
+ {
+ stackstring sw2(stack), sw3, sEmpty;
+ sw3 = stack;
+ TEST(sw2.get() == stackVal);
+ TEST(sw3.get() == stackVal);
+ // Self assign avoiding clang self-assign-overloaded warning
+ sw3 = static_cast<const stackstring&>(sw3); //-V570
+ TEST(sw3.get() == stackVal);
+ // Assign empty
+ sw3 = sEmpty; //-V820
+ TEST(sw3.get() == NULL);
+ }
+ {
+ stackstring sw2(stack);
+ sw2 = heap;
+ TEST(sw2.get() == heapVal);
+ }
+ {
+ stackstring sw2(heap);
+ sw2 = stack;
+ TEST(sw2.get() == stackVal);
+ }
+ {
+ stackstring sw2(heap), sw3(stack), sEmpty1, sEmpty2;
+ swap(sw2, sw3);
+ TEST(sw2.get() == stackVal);
+ TEST(sw3.get() == heapVal);
+ swap(sw2, sw3);
+ TEST(sw2.get() == heapVal);
+ TEST(sw3.get() == stackVal);
+ swap(sw2, sEmpty1);
+ TEST(sEmpty1.get() == heapVal);
+ TEST(sw2.get() == NULL);
+ swap(sw3, sEmpty2);
+ TEST(sEmpty2.get() == stackVal);
+ TEST(sw3.get() == NULL);
+ }
+ {
+ stackstring sw2(heap), sw3(heap);
+ sw3.get()[0] = 'z';
+ const std::wstring val2 = sw3.get();
+ swap(sw2, sw3);
+ TEST(sw2.get() == val2);
+ TEST(sw3.get() == heapVal);
+ }
+ {
+ stackstring sw2(stack), sw3(stack);
+ sw3.get()[0] = 'z';
+ const std::wstring val2 = sw3.get();
+ swap(sw2, sw3);
+ TEST(sw2.get() == val2);
+ TEST(sw3.get() == stackVal);
+ }
+ std::cout << "-- Sanity check" << std::endl;
+ TEST(stack.get() == stackVal);
+ TEST(heap.get() == heapVal);
+ }
+ {
+ std::cout << "-- Test putting stackstrings into vector (done by args) class" << std::endl;
+ // Use a smallish buffer, to have stack and heap values
+ typedef boost::nowide::basic_stackstring<wchar_t, char, 5> stackstring;
+ std::vector<stackstring> strings;
+ strings.resize(2);
+ TEST(strings[0].convert("1234") == std::wstring(L"1234"));
+ TEST(strings[1].convert("Hello World") == std::wstring(L"Hello World"));
+ strings.push_back(stackstring("FooBar"));
+ TEST(strings[0].get() == std::wstring(L"1234"));
+ TEST(strings[1].get() == std::wstring(L"Hello World"));
+ TEST(strings[2].get() == std::wstring(L"FooBar"));
+ }
+ std::cout << "- Stackstring" << std::endl;
+ run_all(stackstring_to_wide, stackstring_to_narrow);
+ std::cout << "- Heap Stackstring" << std::endl;
+ run_all(heap_stackstring_to_wide, heap_stackstring_to_narrow);
+}
diff --git a/src/boost/libs/nowide/test/test_stdio.cpp b/src/boost/libs/nowide/test/test_stdio.cpp
new file mode 100644
index 000000000..250b6019d
--- /dev/null
+++ b/src/boost/libs/nowide/test/test_stdio.cpp
@@ -0,0 +1,144 @@
+//
+// Copyright (c) 2012 Artyom Beilis (Tonkikh)
+// Copyright (c) 2019 Alexander Grund
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/nowide/cstdio.hpp>
+
+#include <boost/nowide/convert.hpp>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+
+#include "test.hpp"
+
+bool file_exists(const std::string& filename)
+{
+#ifdef BOOST_WINDOWS
+ FILE* f = boost::nowide::detail::wfopen(boost::nowide::widen(filename).c_str(), L"r");
+#else
+ FILE* f = std::fopen(filename.c_str(), "r");
+#endif
+ bool result = false;
+ if(f)
+ {
+ std::fclose(f);
+ result = true;
+ }
+ return result;
+}
+
+void create_test_file(const std::string& filename)
+{
+#ifdef BOOST_WINDOWS
+ FILE* f = boost::nowide::detail::wfopen(boost::nowide::widen(filename).c_str(), L"w");
+#else
+ FILE* f = std::fopen(filename.c_str(), "w");
+#endif
+ TEST(f);
+ TEST(std::fputs("test\n", f) >= 0);
+ std::fclose(f);
+}
+
+#if BOOST_MSVC
+#include <crtdbg.h> // For _CrtSetReportMode
+void noop_invalid_param_handler(const wchar_t*, const wchar_t*, const wchar_t*, unsigned, uintptr_t)
+{}
+#endif
+
+void test_main(int, char** argv, char**)
+{
+ const std::string prefix = argv[0];
+ const std::string filename = prefix + "\xd7\xa9-\xd0\xbc-\xce\xbd.txt";
+#if BOOST_MSVC
+ // Prevent abort on freopen(NULL, ...)
+ _set_invalid_parameter_handler(noop_invalid_param_handler);
+#endif
+
+ std::cout << " -- fopen - existing file" << std::endl;
+ {
+ create_test_file(filename);
+ FILE* f = boost::nowide::fopen(filename.c_str(), "r");
+ TEST(f);
+ char buf[16];
+ TEST(std::fgets(buf, 16, f) != 0);
+ TEST(strcmp(buf, "test\n") == 0);
+ std::fclose(f);
+ }
+ std::cout << " -- remove" << std::endl;
+ {
+ create_test_file(filename);
+ TEST(file_exists(filename));
+ TEST(boost::nowide::remove(filename.c_str()) == 0);
+ TEST(!file_exists(filename));
+ }
+ std::cout << " -- fopen non-existing file" << std::endl;
+ {
+ boost::nowide::remove(filename.c_str());
+ TEST(!file_exists(filename));
+ TEST(boost::nowide::fopen(filename.c_str(), "r") == NULL);
+ TEST(!file_exists(filename));
+ }
+ std::cout << " -- freopen" << std::endl;
+ {
+ create_test_file(filename);
+ FILE* f = boost::nowide::fopen(filename.c_str(), "r+");
+ TEST(f);
+ std::cout << " -- Can read & write" << std::endl;
+ {
+ char buf[32];
+ TEST(std::fgets(buf, 32, f) != 0);
+ TEST(strcmp(buf, "test\n") == 0);
+ TEST(std::fseek(f, 0, SEEK_END) == 0);
+ TEST(std::fputs("foobar\n", f) >= 0);
+ }
+ // Reopen in read mode
+ // Note that changing the mode is not possibly on all implementations
+ // E.g. MSVC disallows NULL completely as the file parameter
+ FILE* f2 = boost::nowide::freopen(NULL, "r", f);
+ if(!f2)
+ f2 = boost::nowide::freopen(filename.c_str(), "r", f);
+ std::cout << " -- no write possible" << std::endl;
+ {
+ TEST(f2 == f);
+ TEST(std::fputs("not-written\n", f) < 0);
+ TEST(std::fseek(f, 0, SEEK_SET) == 0);
+ char buf[32];
+ TEST(std::fgets(buf, 32, f) != 0);
+ TEST(strcmp(buf, "test\n") == 0);
+ TEST(std::fgets(buf, 32, f) != 0);
+ TEST(strcmp(buf, "foobar\n") == 0);
+ }
+ std::cout << " -- Reopen different file" << std::endl;
+ const std::string filename2 = filename + ".1.txt";
+ TEST(boost::nowide::freopen(filename2.c_str(), "w", f) == f);
+ {
+ char buf[32];
+ TEST(std::fputs("baz\n", f) >= 0);
+ std::fclose(f);
+ f = boost::nowide::fopen(filename2.c_str(), "r");
+ TEST(f);
+ TEST(std::fgets(buf, 32, f) != 0);
+ TEST(strcmp(buf, "baz\n") == 0);
+ }
+ std::fclose(f);
+ boost::nowide::remove(filename2.c_str());
+ }
+ std::cout << " -- rename" << std::endl;
+ {
+ create_test_file(filename);
+ const std::string filename2 = filename + ".1.txt";
+ boost::nowide::remove(filename2.c_str());
+ TEST(file_exists(filename));
+ TEST(!file_exists(filename2));
+ TEST(boost::nowide::rename(filename.c_str(), filename2.c_str()) == 0);
+ TEST(!file_exists(filename));
+ TEST(file_exists(filename2));
+ TEST(boost::nowide::remove(filename.c_str()) < 0);
+ TEST(boost::nowide::remove(filename2.c_str()) == 0);
+ }
+}
diff --git a/src/boost/libs/nowide/test/test_system.cpp b/src/boost/libs/nowide/test/test_system.cpp
new file mode 100644
index 000000000..3a6f64580
--- /dev/null
+++ b/src/boost/libs/nowide/test/test_system.cpp
@@ -0,0 +1,178 @@
+//
+// Copyright (c) 2012 Artyom Beilis (Tonkikh)
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+#ifdef _MSC_VER
+#define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include <boost/nowide/cstdlib.hpp>
+
+#include <boost/nowide/args.hpp>
+#include <boost/nowide/detail/convert.hpp>
+#include <algorithm>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "test.hpp"
+
+bool is_ascii(const std::string& s)
+{
+ for(std::string::const_iterator it = s.begin(); it != s.end(); ++it)
+ {
+ if(static_cast<unsigned char>(*it) > 0x7F)
+ return false;
+ }
+ return true;
+}
+
+std::string replace_non_ascii(const std::string& s)
+{
+ std::string::const_iterator it = s.begin();
+ namespace utf = boost::nowide::detail::utf;
+ typedef utf::utf_traits<char> utf8;
+ std::string result;
+ result.reserve(s.size());
+ while(it != s.end())
+ {
+ utf::code_point c = utf8::decode(it, s.end());
+ TEST(c != utf::illegal && c != utf::incomplete);
+ if(c > 0x7F)
+ c = '?'; // WinAPI seems to do this
+ result.push_back(static_cast<char>(c));
+ }
+ return result;
+}
+
+void compare_string_arrays(char** main_val, char** utf8_val, bool sort)
+{
+ std::vector<std::string> vec_main, vec_utf8;
+ for(; *main_val; ++main_val)
+ vec_main.push_back(std::string(*main_val));
+ for(; *utf8_val; ++utf8_val)
+ vec_utf8.push_back(std::string(*utf8_val));
+ // Same number of strings
+ TEST_EQ(vec_main.size(), vec_utf8.size());
+ if(sort)
+ {
+ // Order doesn't matter
+ std::sort(vec_main.begin(), vec_main.end());
+ std::sort(vec_utf8.begin(), vec_utf8.end());
+ }
+ for(size_t i = 0; i < vec_main.size(); ++i)
+ {
+ // Skip strings with non-ascii chars
+ if(is_ascii(vec_main[i]) && vec_main[i] != vec_utf8[i])
+ TEST_EQ(vec_main[i], replace_non_ascii(vec_utf8[i]));
+ }
+}
+
+void compare_getenv(char** env)
+{
+ // For all all variables in env check against getenv
+ for(char** e = env; *e != 0; e++)
+ {
+ const char* key_begin = *e;
+ const char* key_end = strchr(key_begin, '=');
+ TEST(key_end);
+ std::string key = std::string(key_begin, key_end);
+ const char* std_value = std::getenv(key.c_str());
+ const char* bnw_value = boost::nowide::getenv(key.c_str());
+ // If std_value is set, bnw value must be too and be equal, else bnw value must be unset too
+ if(std_value)
+ {
+ TEST(bnw_value);
+ // Compare only if ascii
+ if(is_ascii(std_value) && std::string(std_value) != std::string(bnw_value))
+ TEST_EQ(std_value, replace_non_ascii(bnw_value));
+ } else
+ TEST(!bnw_value);
+ }
+}
+
+const std::string example = "\xd7\xa9-\xd0\xbc-\xce\xbd";
+
+void run_child(int argc, char** argv, char** env)
+{
+ // Test arguments
+ TEST(argc == 2);
+ TEST_EQ(argv[1], example);
+ TEST(argv[2] == 0);
+
+ // Test getenv
+ TEST(boost::nowide::getenv("BOOST_NOWIDE_TEST"));
+ TEST_EQ(boost::nowide::getenv("BOOST_NOWIDE_TEST"), example);
+ TEST(boost::nowide::getenv("BOOST_NOWIDE_TEST_NONE") == 0);
+ // Empty variables are unreliable on windows, hence skip. E.g. using "set FOO=" unsets FOO
+#ifndef BOOST_WINDOWS
+ TEST(boost::nowide::getenv("BOOST_NOWIDE_EMPTY"));
+ TEST_EQ(boost::nowide::getenv("BOOST_NOWIDE_EMPTY"), std::string());
+#endif // !_WIN32
+
+ // This must be contained in env
+ std::string sample = "BOOST_NOWIDE_TEST=" + example;
+ bool found = false;
+ for(char** e = env; *e != 0; e++)
+ {
+ if(*e == sample)
+ found = true;
+ }
+ TEST(found);
+
+ std::cout << "Subprocess ok" << std::endl;
+}
+
+void run_parent(const char* exe_path)
+{
+#if BOOST_NOWIDE_TEST_USE_NARROW
+ TEST(boost::nowide::setenv("BOOST_NOWIDE_TEST", example.c_str(), 1) == 0);
+ TEST(boost::nowide::setenv("BOOST_NOWIDE_TEST_NONE", example.c_str(), 1) == 0);
+ TEST(boost::nowide::unsetenv("BOOST_NOWIDE_TEST_NONE") == 0);
+ TEST(boost::nowide::setenv("BOOST_NOWIDE_EMPTY", "", 1) == 0);
+ TEST(boost::nowide::getenv("BOOST_NOWIDE_EMPTY"));
+ std::string command = "\"";
+ command += exe_path;
+ command += "\" ";
+ command += example;
+ TEST(boost::nowide::system(command.c_str()) == 0);
+ std::cout << "Parent ok" << std::endl;
+#else
+ std::wstring envVar = L"BOOST_NOWIDE_TEST=" + boost::nowide::widen(example);
+ TEST(_wputenv(envVar.c_str()) == 0);
+ std::wstring wcommand = boost::nowide::widen(exe_path) + L" " + boost::nowide::widen(example);
+ TEST(_wsystem(wcommand.c_str()) == 0);
+ std::cout << "Wide Parent ok" << std::endl;
+#endif
+}
+
+void test_main(int argc, char** argv, char** env)
+{
+ const int old_argc = argc;
+ char** old_argv = argv;
+ char** old_env = env;
+ {
+ boost::nowide::args _(argc, argv, env);
+ TEST(argc == old_argc);
+ std::cout << "Checking arguments" << std::endl;
+ compare_string_arrays(old_argv, argv, false);
+ std::cout << "Checking env" << std::endl;
+ compare_string_arrays(old_env, env, true);
+ compare_getenv(env);
+ }
+ // When `args` is destructed the old values must be restored
+ TEST(argc == old_argc);
+ TEST(argv == old_argv);
+ TEST(env == old_env);
+
+ boost::nowide::args a(argc, argv, env);
+ if(argc == 1)
+ run_parent(argv[0]);
+ else
+ run_child(argc, argv, env);
+}
diff --git a/src/boost/libs/nowide/tools/create_standalone.sh b/src/boost/libs/nowide/tools/create_standalone.sh
new file mode 100644
index 000000000..76d9df096
--- /dev/null
+++ b/src/boost/libs/nowide/tools/create_standalone.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+
+set -euo pipefail
+
+cd "$(dirname "$0")/.."
+
+if ! [ -e "tools/create_standalone.sh" ]; then
+ echo "Could not change to repo root"
+ exit 1
+fi
+
+targetFolder="${1:-nowide_standalone}"
+
+# If target folder exists fail, unless it is the default in which case it is removed
+if [ -e "$targetFolder" ]; then
+ if [[ "$targetFolder" == "nowide_standalone" ]]; then
+ rm -r "$targetFolder"
+ else
+ echo "Target folder $targetFolder exists"
+ exit 1
+ fi
+fi
+
+mkdir -p "$targetFolder"/include
+
+cp -r include/boost/nowide "$targetFolder"/include
+cp -r src test cmake CMakeLists.txt LICENSE "$targetFolder"
+cp standalone/*.hpp "$targetFolder"/include/nowide
+mv "$targetFolder/cmake/BoostAddOptions.cmake" "$targetFolder/cmake/NowideAddOptions.cmake"
+mv "$targetFolder/cmake/BoostAddWarnings.cmake" "$targetFolder/cmake/NowideAddWarnings.cmake"
+find "$targetFolder" -name 'Jamfile*' -delete
+
+SOURCES=$(find "$targetFolder" -name '*.hpp' -or -name '*.cpp')
+SOURCES_NO_BOOST=$(echo "$SOURCES" | grep -v 'filesystem.hpp')
+
+sed 's/BOOST_NOWIDE_/NOWIDE_/g' -i $SOURCES
+sed 's/BOOST_/NOWIDE_/g' -i $SOURCES
+sed 's/boost::nowide/nowide/g' -i $SOURCES
+sed 's/boost::chrono/std::chrono/g' -i $SOURCES
+sed 's/boost::milli/std::milli/g' -i $SOURCES
+sed 's/boost::/nowide::/g' -i $SOURCES_NO_BOOST
+sed '/namespace boost/d' -i $SOURCES
+sed 's/<boost\/chrono.hpp/<chrono/g' -i $SOURCES
+sed 's/<boost\/nowide\//<nowide\//g' -i $SOURCES
+sed 's/<boost\//<nowide\//g' -i $SOURCES_NO_BOOST
+sed '/config\/abi_/d' -i $SOURCES
+
+CMLs=$(find "$targetFolder" -name 'CMakeLists.txt' -or -name '*.cmake')
+
+sed 's/ BOOST_ALL_NO_LIB//' -i $CMLs
+sed 's/BOOST_NOWIDE_/NOWIDE_/g' -i $CMLs
+sed 's/Boost_NOWIDE_/NOWIDE_/g' -i $CMLs
+sed 's/boost_nowide/nowide/g' -i $CMLs
+sed 's/boost_/nowide_/g' -i $CMLs
+sed 's/Boost::nowide/nowide::nowide/g' -i $CMLs
+sed 's/Boost/Nowide/g' -i $CMLs
+sed 's/ OR BOOST_SUPERPROJECT_SOURCE_DIR//' -i $CMLs
+
+sed '/PUBLIC BOOST_NOWIDE_NO_LIB)/d' -i "$targetFolder/CMakeLists.txt"
+sed '/^if(BOOST_SUPERPROJECT_SOURCE_DIR)/,/^endif/d' -i "$targetFolder/CMakeLists.txt"
+sed '/add_warnings/atarget_compile_features(nowide PUBLIC cxx_std_11)' -i "$targetFolder/CMakeLists.txt"
+sed 's/NAMESPACE Nowide CONFIG_FILE.*$/NAMESPACE nowide)/' -i "$targetFolder/CMakeLists.txt"
+
+sed '/if(NOT BOOST_SUPERPROJECT_SOURCE_DIR)/,/endif/d' -i "$targetFolder/test/CMakeLists.txt"
+sed 's/ LIBRARIES Nowide::chrono//' -i "$targetFolder/test/CMakeLists.txt"
+sed '/Nowide::filesystem/d' -i "$targetFolder/test/CMakeLists.txt"