changeset 670:2d4a781b517c

misc: remove everything C++
author David Demelier <markand@malikania.fr>
date Thu, 24 Mar 2022 07:22:08 +0100
parents 72e143a85525
children 2bee2b6b6386
files CMakeLists.txt cpp/CMakeLists.txt cpp/is_boolean/CMakeLists.txt cpp/is_boolean/is_boolean.hpp cpp/is_boolean/test/main.cpp cpp/is_number/CMakeLists.txt cpp/is_number/is_number.hpp cpp/is_number/test/main.cpp cpp/join/CMakeLists.txt cpp/join/join.hpp cpp/join/test/main.cpp cpp/json_util/CMakeLists.txt cpp/json_util/json_util.cpp cpp/json_util/json_util.hpp cpp/json_util/test/main.cpp cpp/options/CMakeLists.txt cpp/options/options.hpp cpp/options/test/main.cpp cpp/pexec/CMakeLists.txt cpp/pexec/pexec.hpp cpp/pexec/test/main.cpp cpp/to_int/CMakeLists.txt cpp/to_int/test/main.cpp cpp/to_int/to_int.hpp
diffstat 24 files changed, 0 insertions(+), 1958 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Sat Oct 03 16:20:03 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-#
-# CMakeLists.txt -- code building for common code
-#
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-
-cmake_minimum_required(VERSION 3.5)
-project(code)
-
-set(CMAKE_CXX_STANDARD 17)
-set(CMAKE_CXX_STANDARD_REQUIRED On)
-
-if (CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang")
-	set(CMAKE_CXX_FLAGS "-Wall -Wextra -pedantic ${CMAKE_CXX_FLAGS}")
-	set(CMAKE_CXX_FLAGS_DEBUG "-Werror ${CMAKE_CXX_FLAGS_DEBUG}")
-endif ()
-
-find_package(Doxygen)
-find_package(Boost REQUIRED COMPONENTS unit_test_framework)
-
-add_subdirectory(extern/libjson)
-
-enable_testing()
-
-#
-# code_define_module
-# -------------------------------------------------------------------
-#
-# code_define_module(
-#	 NAME lowercase name
-#	 SOURCES source files
-#	 LIBRARIES (Optional) libraries
-#	 INCLUDES (Optional) include directories
-#	 FLAGS (Optional) flags
-# )
-#
-# Create a test for the given module.
-#
-# This macro adds a new option WITH_<uppercase NAME> to test the module.
-#
-# If the module has a file test/main.cpp in its directory, a target test-<NAME> is created.
-#
-function(code_define_module)
-	set(oneValueArgs NAME)
-	set(multiValueArgs SOURCES LIBRARIES INCLUDES FLAGS)
-
-	cmake_parse_arguments(MOD "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
-
-	if (NOT MOD_NAME)
-		message(FATAL_ERROR "Argument NAME is not set")
-	endif ()
-
-	# Create the option for enabling the test.
-	string(TOUPPER ${MOD_NAME} optionname)
-	option(WITH_${optionname} "Enable ${MOD_NAME}" On)
-
-	if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/test/main.cpp AND WITH_${optionname})
-		add_executable(test-${MOD_NAME} ${MOD_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/test/main.cpp)
-		set_target_properties(
-			test-${MOD_NAME}
-			PROPERTIES
-				RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
-				RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}
-				RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}
-				RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR}
-				RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_BINARY_DIR}
-		)
-		target_compile_definitions(
-			test-${MOD_NAME}
-			PRIVATE
-				BOOST_TEST_DYN_LINK
-				${MOD_FLAGS}
-		)
-		target_include_directories(
-			test-${MOD_NAME}
-			PRIVATE
-				${CMAKE_CURRENT_SOURCE_DIR}
-				${MOD_INCLUDES}
-		)
-		target_link_libraries(
-			test-${MOD_NAME}
-			Boost::dynamic_linking
-			Boost::disable_autolinking
-			Boost::unit_test_framework
-			${MOD_LIBRARIES}
-		)
-
-		# Register the test.
-		add_test(
-			NAME ${MOD_NAME}
-			COMMAND test-${MOD_NAME}
-			WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-		)
-	endif ()
-endfunction()
-
-if (DOXYGEN_FOUND)
-	set(DOXYGEN_PROJECT_NAME code)
-	set(DOXYGEN_STRIP_FROM_PATH ${code_SOURCE_DIR}/cpp)
-	set(DOXYGEN_FILE_PATTERNS "*.hpp")
-	set(DOXYGEN_WARN_NO_PARAMDOC YES)
-	set(DOXYGEN_WARN_AS_ERROR YES)
-	set(DOXYGEN_QUIET YES)
-
-	doxygen_add_docs(
-		doxygen
-		${code_SOURCE_DIR}/cpp
-		WORKING_DIRECTORY ${code_SOURCE_DIR}
-	)
-
-	add_custom_target(docs ALL DEPENDS doxygen)
-endif ()
-
-add_subdirectory(cpp)
--- a/cpp/CMakeLists.txt	Sat Oct 03 16:20:03 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-#
-# CMakeLists.txt -- code building for common code
-#
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-
-add_subdirectory(is_boolean)
-add_subdirectory(is_number)
-add_subdirectory(join)
-add_subdirectory(json_util)
-add_subdirectory(options)
-add_subdirectory(pexec)
-add_subdirectory(to_int)
--- a/cpp/is_boolean/CMakeLists.txt	Sat Oct 03 16:20:03 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-#
-# CMakeLists.txt -- code building for common code
-#
-# Copyright (c) 2016-2019 David Demelier <markand@malikania.fr>
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-
-code_define_module(
-	NAME is-boolean
-	SOURCES is_boolean.hpp
-)
--- a/cpp/is_boolean/is_boolean.hpp	Sat Oct 03 16:20:03 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * is_number.hpp -- check if string is a boolean
- *
- * Copyright (c) 2016-2019 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IS_BOOLEAN_HPP
-#define IS_BOOLEAN_HPP
-
-#include <algorithm>
-#include <cctype>
-#include <string>
-
-/**
- * Check if the value is a boolean, 1, yes and true are accepted.
- *
- * \param value the value (will be change to uppercase)
- * \return true if is boolean
- * \note this function is case-insensitive
- */
-inline auto is_boolean(std::string value) noexcept -> bool
-{
-	std::transform(value.begin(), value.end(), value.begin(), [] (auto c) noexcept {
-		return toupper(c);
-	});
-
-	return value == "1" || value == "YES" || value == "TRUE" || value == "ON";
-}
-
-#endif // !IS_BOOLEAN_HPP
--- a/cpp/is_boolean/test/main.cpp	Sat Oct 03 16:20:03 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * main.cpp -- test is_boolean functions
- *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#define BOOST_TEST_MODULE "is-number"
-#include <boost/test/unit_test.hpp>
-
-#include "is_boolean.hpp"
-
-BOOST_AUTO_TEST_CASE(simple_is_boolean)
-{
-	BOOST_REQUIRE(is_boolean("true"));
-	BOOST_REQUIRE(is_boolean("True"));
-	BOOST_REQUIRE(is_boolean("TRUE"));
-	BOOST_REQUIRE(is_boolean("TruE"));
-	BOOST_REQUIRE(is_boolean("yes"));
-	BOOST_REQUIRE(is_boolean("Yes"));
-	BOOST_REQUIRE(is_boolean("YES"));
-	BOOST_REQUIRE(is_boolean("YeS"));
-	BOOST_REQUIRE(is_boolean("on"));
-	BOOST_REQUIRE(is_boolean("On"));
-	BOOST_REQUIRE(is_boolean("oN"));
-	BOOST_REQUIRE(is_boolean("ON"));
-	BOOST_REQUIRE(is_boolean("1"));
-	BOOST_REQUIRE(!is_boolean("false"));
-	BOOST_REQUIRE(!is_boolean("lol"));
-	BOOST_REQUIRE(!is_boolean(""));
-	BOOST_REQUIRE(!is_boolean("0"));
-}
--- a/cpp/is_number/CMakeLists.txt	Sat Oct 03 16:20:03 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-#
-# CMakeLists.txt -- code building for common code
-#
-# Copyright (c) 2016-2019 David Demelier <markand@malikania.fr>
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-
-code_define_module(
-	NAME is-number
-	SOURCES is_number.hpp
-)
--- a/cpp/is_number/is_number.hpp	Sat Oct 03 16:20:03 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * is_number.hpp -- check if string is a number
- *
- * Copyright (c) 2016-2019 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef IS_NUMBER_HPP
-#define IS_NUMBER_HPP
-
-#include <cstdlib>
-#include <string>
-
-/**
- * Check if the string is an integer.
- *
- * \param value the input
- * \param base the optional base
- * \return true if integer
- */
-inline auto is_int(const std::string& str, int base = 10) noexcept -> bool
-{
-	if (str.empty())
-		return false;
-
-	char* ptr;
-
-	std::strtol(str.c_str(), &ptr, base);
-
-	return *ptr == 0;
-}
-
-/**
- * Check if the string is real.
- *
- * \param value the value
- * \return true if real
- */
-inline auto is_real(const std::string &str) noexcept -> bool
-{
-	if (str.empty())
-		return false;
-
-	char* ptr;
-
-	std::strtod(str.c_str(), &ptr);
-
-	return *ptr == 0;
-}
-
-/**
- * Check if the string is a number.
- *
- * \param value the value
- * \return true if it is a number
- */
-inline auto is_number(const std::string& str) noexcept -> bool
-{
-	return is_int(str) || is_real(str);
-}
-
-#endif // !IS_NUMBER_HPP
--- a/cpp/is_number/test/main.cpp	Sat Oct 03 16:20:03 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * main.cpp -- test is_number functions
- *
- * Copyright (c) 2016-2019 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#define BOOST_TEST_MODULE "is-number"
-#include <boost/test/unit_test.hpp>
-
-#include "is_number.hpp"
-
-BOOST_AUTO_TEST_CASE(simple_is_int)
-{
-	BOOST_TEST(is_int("123"));
-	BOOST_TEST(is_int("-126"));
-	BOOST_TEST(!is_int(""));
-	BOOST_TEST(!is_int("bdf"));
-	BOOST_TEST(!is_int("false"));
-}
-
-BOOST_AUTO_TEST_CASE(simple_is_real)
-{
-	BOOST_TEST(is_real("123"));
-	BOOST_TEST(is_real("-126"));
-	BOOST_TEST(is_real("56.28"));
-	BOOST_TEST(is_real("1e5"));
-	BOOST_TEST(!is_real(""));
-	BOOST_TEST(!is_real("bdf"));
-	BOOST_TEST(!is_real("false"));
-}
-
-BOOST_AUTO_TEST_CASE(simple_is_number)
-{
-	BOOST_TEST(is_number("123"));
-	BOOST_TEST(is_number("-126"));
-	BOOST_TEST(is_number("56.28"));
-	BOOST_TEST(is_number("1e5"));
-	BOOST_TEST(!is_number(""));
-	BOOST_TEST(!is_number("bdf"));
-	BOOST_TEST(!is_number("false"));
-}
--- a/cpp/join/CMakeLists.txt	Sat Oct 03 16:20:03 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-#
-# CMakeLists.txt -- code building for common code
-#
-# Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-
-code_define_module(
-	NAME join
-	SOURCES join.hpp
-)
--- a/cpp/join/join.hpp	Sat Oct 03 16:20:03 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * join.hpp -- join lists into a string
- *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/**
- * \file join.hpp
- * \brief Join function
- */
-
-#include <initializer_list>
-#include <sstream>
-#include <string>
-
-/**
- * Join values by a separator and return a string.
- *
- * \param first the first iterator
- * \param last the last iterator
- * \param delim the optional delimiter
- * \return the string
- */
-template <typename InputIt, typename DelimType = char>
-auto join(InputIt first, InputIt last, DelimType delim = ':') -> std::string
-{
-	std::ostringstream oss;
-
-	if (first != last) {
-		oss << *first;
-
-		while (++first != last)
-			oss << delim << *first;
-	}
-
-	return oss.str();
-}
-
-/**
- * Convenient overload.
- *
- * \param list the initializer list
- * \param delim the delimiter
- * \return the string
- */
-template <typename T, typename DelimType = char>
-auto join(std::initializer_list<T> list, DelimType delim = ':') -> std::string
-{
-	return join(list.begin(), list.end(), delim);
-}
--- a/cpp/join/test/main.cpp	Sat Oct 03 16:20:03 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * main.cpp -- test join function
- *
- * Copyright (c) 2013-2019 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#define BOOST_TEST_MODULE "Join"
-#include <boost/test/unit_test.hpp>
-
-#include "join.hpp"
-
-BOOST_AUTO_TEST_CASE(empty)
-{
-	std::string expected = "";
-	std::string result = join<int>({});
-
-	BOOST_REQUIRE_EQUAL(expected, result);
-}
-
-BOOST_AUTO_TEST_CASE(one)
-{
-	std::string expected = "1";
-	std::string result = join({1});
-
-	BOOST_REQUIRE_EQUAL(expected, result);
-}
-
-BOOST_AUTO_TEST_CASE(two)
-{
-	std::string expected = "1:2";
-	std::string result = join({1, 2});
-
-	BOOST_REQUIRE_EQUAL(expected, result);
-}
-
-BOOST_AUTO_TEST_CASE(delimiterString)
-{
-	std::string expected = "1;;2;;3";
-	std::string result = join({1, 2, 3}, ";;");
-
-	BOOST_REQUIRE_EQUAL(expected, result);
-}
-
-BOOST_AUTO_TEST_CASE(delimiterChar)
-{
-	std::string expected = "1@2@3@4";
-	std::string result = join({1, 2, 3, 4}, '@');
-
-	BOOST_REQUIRE_EQUAL(expected, result);
-}
--- a/cpp/json_util/CMakeLists.txt	Sat Oct 03 16:20:03 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-#
-# CMakeLists.txt -- json_util module
-#
-# Copyright (c) 2019 David Demelier <markand@malikania.fr>
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-
-project(json-util)
-
-code_define_module(
-	NAME json-util
-	LIBRARIES libjson
-	SOURCES
-		${json-util_SOURCE_DIR}/json_util.hpp
-		${json-util_SOURCE_DIR}/json_util.cpp
-)
--- a/cpp/json_util/json_util.cpp	Sat Oct 03 16:20:03 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,162 +0,0 @@
-/*
- * json_util.cpp -- utilities for JSON
- *
- * Copyright (c) 2019 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <limits>
-#include <type_traits>
-
-#include "json_util.hpp"
-
-using nlohmann::json;
-
-namespace json_util {
-
-namespace {
-
-template <typename Int>
-auto clampi(const json& value) noexcept -> std::optional<Int>
-{
-	static_assert(std::is_signed<Int>::value, "Int must be signed");
-
-	if (!value.is_number_integer())
-		return std::nullopt;
-
-	const auto ret = value.get<std::int64_t>();
-
-	if (ret < std::numeric_limits<Int>::min() || ret > std::numeric_limits<Int>::max())
-		return std::nullopt;
-
-	return static_cast<Int>(ret);
-}
-
-template <typename Int>
-auto clampu(const json& value) noexcept -> std::optional<Int>
-{
-	static_assert(std::is_unsigned<Int>::value, "Int must be unsigned");
-
-	if (!value.is_number_unsigned())
-		return std::nullopt;
-
-	const auto ret = value.get<std::uint64_t>();
-
-	if (ret > std::numeric_limits<Int>::max())
-		return std::nullopt;
-
-	return static_cast<Int>(ret);
-}
-
-} // !namespace
-
-auto type_traits<bool>::get(const json& value) noexcept -> std::optional<bool>
-{
-	if (!value.is_boolean())
-		return std::nullopt;
-
-	return value.get<bool>();
-}
-
-auto type_traits<double>::get(const json& value) noexcept -> std::optional<double>
-{
-	if (!value.is_number_float())
-		return std::nullopt;
-
-	return value.get<double>();
-}
-
-auto type_traits<std::string>::get(const json& value) -> std::optional<std::string>
-{
-	if (!value.is_string())
-		return std::nullopt;
-
-	return value.get<std::string>();
-}
-
-auto type_traits<std::string_view>::get(const json& value) -> std::optional<std::string_view>
-{
-	if (!value.is_string())
-		return std::nullopt;
-
-	return value.get<std::string_view>();
-}
-
-auto type_traits<std::int8_t>::get(const json& value) -> std::optional<std::int8_t>
-{
-	return clampi<std::int8_t>(value);
-}
-
-auto type_traits<std::int16_t>::get(const json& value) -> std::optional<std::int16_t>
-{
-	return clampi<std::int16_t>(value);
-}
-
-auto type_traits<std::int32_t>::get(const json& value) -> std::optional<std::int32_t>
-{
-	return clampi<std::int32_t>(value);
-}
-
-auto type_traits<std::int64_t>::get(const json& value) noexcept -> std::optional<std::int64_t>
-{
-	if (!value.is_number_integer())
-		return std::nullopt;
-
-	return value.get<std::int64_t>();
-}
-
-auto type_traits<std::uint8_t>::get(const json& value) -> std::optional<std::uint8_t>
-{
-	return clampu<std::uint8_t>(value);
-}
-
-auto type_traits<std::uint16_t>::get(const json& value) -> std::optional<std::uint16_t>
-{
-	return clampu<std::uint16_t>(value);
-}
-
-auto type_traits<std::uint32_t>::get(const json& value) -> std::optional<std::uint32_t>
-{
-	return clampu<std::uint32_t>(value);
-}
-
-auto type_traits<std::uint64_t>::get(const json& value) noexcept -> std::optional<std::uint64_t>
-{
-	if (!value.is_number_unsigned())
-		return std::nullopt;
-
-	return value.get<std::uint64_t>();
-}
-
-auto pretty(const json& value, int indent) -> std::string
-{
-	switch (value.type()) {
-	case json::value_t::null:
-		return "null";
-	case json::value_t::string:
-		return value.get<std::string>();
-	case json::value_t::boolean:
-		return value.get<bool>() ? "true" : "false";
-	case json::value_t::number_integer:
-		return std::to_string(value.get<std::int64_t>());
-	case json::value_t::number_unsigned:
-		return std::to_string(value.get<std::uint64_t>());
-	case json::value_t::number_float:
-		return std::to_string(value.get<double>());
-	default:
-		return value.dump(indent);
-	}
-}
-
-} // !json_util
--- a/cpp/json_util/json_util.hpp	Sat Oct 03 16:20:03 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,319 +0,0 @@
-/*
- * json_util.hpp -- utilities for JSON
- *
- * Copyright (c) 2019 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef JSON_UTIL_HPP
-#define JSON_UTIL_HPP
-
-/**
- * \file json_util.hpp
- * \brief Utilities for JSON.
- */
-
-#include <cstdint>
-#include <optional>
-#include <string>
-
-#include <json.hpp>
-
-/**
- * \brief Utilities for JSON.
- */
-namespace json_util {
-
-/**
- * \brief Describe how to convert a JSON value.
- *
- * This traits must be specialized for every type you want to convert from JSON
- * to its native type.
- *
- * You only need to implement the get function with the following signature:
- *
- * ```cpp
- * static std::optional<T> get(const nlohmann::json& value);
- * ```
- *
- * The implementation should not throw an exception but return a null optional
- * instead.
- *
- * This traits is already specialized for the given types:
- *
- * - bool
- * - double
- * - std::uint(8, 16, 32, 64)_t
- * - std::string
- */
-template <typename T>
-struct type_traits;
-
-/**
- * \brief Specialization for `bool`.
- */
-template <>
-struct type_traits<bool> {
-	/**
-	 * Convert the JSON value to bool.
-	 *
-	 * \param value the value
-	 * \return the bool or empty if not a boolean type
-	 */
-	static auto get(const nlohmann::json& value) noexcept -> std::optional<bool>;
-};
-
-/**
- * \brief Specialization for `double`.
- */
-template <>
-struct type_traits<double> {
-	/**
-	 * Convert the JSON value to bool.
-	 *
-	 * \param value the value
-	 * \return the double or empty if not a double type
-	 */
-	static auto get(const nlohmann::json& value) noexcept -> std::optional<double>;
-};
-
-/**
- * \brief Specialization for `std::string`.
- */
-template <>
-struct type_traits<std::string> {
-	/**
-	 * Convert the JSON value to std::string.
-	 *
-	 * \param value the value
-	 * \return the string or empty if not a string type
-	 */
-	static auto get(const nlohmann::json& value) -> std::optional<std::string>;
-};
-
-/**
- * \brief Specialization for `std::string_view`.
- */
-template <>
-struct type_traits<std::string_view> {
-	/**
-	 * Convert the JSON value to std::string.
-	 *
-	 * \param value the value
-	 * \return the string or empty if not a string type
-	 */
-	static auto get(const nlohmann::json& value) -> std::optional<std::string_view>;
-};
-
-/**
- * \brief Specialization for `std::int8_t`.
- */
-template <>
-struct type_traits<std::int8_t> {
-	/**
-	 * Convert the JSON value to std::int8_t.
-	 *
-	 * \param value the value
-	 * \return the value or empty if value does not fit between the range
-	 */
-	static auto get(const nlohmann::json& value) -> std::optional<std::int8_t>;
-};
-
-/**
- * \brief Specialization for `std::int16_t`.
- */
-template <>
-struct type_traits<std::int16_t> {
-	/**
-	 * Convert the JSON value to std::int16_t.
-	 *
-	 * \param value the value
-	 * \return the value or empty if value does not fit between the range
-	 */
-	static auto get(const nlohmann::json& value) -> std::optional<std::int16_t>;
-};
-
-/**
- * \brief Specialization for `std::int32_t`.
- */
-template <>
-struct type_traits<std::int32_t> {
-	/**
-	 * Convert the JSON value to std::int32_t.
-	 *
-	 * \param value the value
-	 * \return the value or empty if value does not fit between the range
-	 */
-	static auto get(const nlohmann::json& value) -> std::optional<std::int32_t>;
-};
-
-/**
- * \brief Specialization for `std::int64_t`.
- */
-template <>
-struct type_traits<std::int64_t> {
-	/**
-	 * Convert the JSON value to std::int64_t.
-	 *
-	 * \param value the value
-	 * \return the int or empty if not a int type
-	 */
-	static auto get(const nlohmann::json& value) noexcept -> std::optional<std::int64_t>;
-};
-
-/**
- * \brief Specialization for `std::uint8_t`.
- */
-template <>
-struct type_traits<std::uint8_t> {
-	/**
-	 * Convert the JSON value to std::uint8_t.
-	 *
-	 * \param value the value
-	 * \return the value or empty if value does not fit between the range
-	 */
-	static auto get(const nlohmann::json& value) -> std::optional<std::uint8_t>;
-};
-
-/**
- * \brief Specialization for `std::uint16_t`.
- */
-template <>
-struct type_traits<std::uint16_t> {
-	/**
-	 * Convert the JSON value to std::uint16_t.
-	 *
-	 * \param value the value
-	 * \return the value or empty if value does not fit between the range
-	 */
-	static auto get(const nlohmann::json& value) -> std::optional<std::uint16_t>;
-};
-
-/**
- * \brief Specialization for `std::int32_t`.
- */
-template <>
-struct type_traits<std::uint32_t> {
-	/**
-	 * Convert the JSON value to std::uint32_t.
-	 *
-	 * \param value the value
-	 * \return the value or empty if value does not fit between the range
-	 */
-	static auto get(const nlohmann::json& value) -> std::optional<std::uint32_t>;
-};
-
-/**
- * \brief Specialization for `std::uint64_t`.
- */
-template <>
-struct type_traits<std::uint64_t> {
-	/**
-	 * Convert the JSON value to std::uint64_t.
-	 *
-	 * \param value the value
-	 * \return the int or empty if not a int type
-	 */
-	static auto get(const nlohmann::json& value) noexcept -> std::optional<std::uint64_t>;
-};
-
-/**
- * \brief Convenient JSON object parser
- *
- * This class helps destructuring insecure JSON input by returning optional
- * values if they are not present or invalid.
- */
-class deserializer : public nlohmann::json {
-public:
-	/**
-	 * Inherited constructor.
-	 */
-	using nlohmann::json::json;
-
-	/**
-	 * Get a value from the document object.
-	 *
-	 * \param key the property key
-	 * \return the value or std::nullopt if not found or not convertible
-	 */
-	template <typename Type>
-	auto get(std::string_view key) const noexcept -> std::optional<Type>
-	{
-		const auto it = find(key);
-
-		if (it == end())
-			return std::nullopt;
-
-		return type_traits<Type>::get(*it);
-	}
-
-	/**
-	 * Get a value from the document object or return def if:
-	 *
-	 * - Key is absent from the document
-	 * - Object property is not the same type
-	 *
-	 * \param key the property key
-	 * \param def the default value
-	 * \return the object or def
-	 * \throw any exception from nlohmann::json constructor
-	 */
-	template <typename Type, typename DefaultValue>
-	auto get_or(std::string_view key, DefaultValue&& def) const -> Type
-	{
-		const auto it = find(key);
-
-		if (it == end())
-		       return std::forward<DefaultValue>(def);
-		if (nlohmann::json(std::forward<DefaultValue>(def)).type() != it->type())
-			return std::forward<DefaultValue>(def);
-
-		return it->get<Type>();
-	}
-
-	/**
-	 * Get an optional value from the document object.
-	 *
-	 * If the value is undefined, the default value is returned. Otherwise, if
-	 * the value is not in the given type, std::nullopt is returned.
-	 *
-	 * \param key the property key
-	 * \param def the default value if property is undefined
-	 * \return the value, std::nullopt or def
-	 */
-	template <typename Type, typename DefaultValue>
-	auto optional(std::string_view key, DefaultValue&& def) const noexcept -> std::optional<Type>
-	{
-		const auto it = find(key);
-
-		if (it == end())
-			return std::optional<Type>(std::forward<DefaultValue>(def));
-
-		return type_traits<Type>::get(*it);
-	}
-};
-
-/**
- * Print the value as human readable.
- *
- * \note This only works on flat objects.
- * \param value the value
- * \param indent the optional indent for objects/arrays
- * \return the string
- */
-auto pretty(const nlohmann::json& value, int indent = 4) -> std::string;
-
-} // !json_util
-
-#endif // !JSON_UTIL_HPP
--- a/cpp/json_util/test/main.cpp	Sat Oct 03 16:20:03 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,208 +0,0 @@
-/*
- * main.cpp -- main test file for json_util
- *
- * Copyright (c) 2019 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#define BOOST_TEST_MODULE "json_util"
-#include <boost/test/unit_test.hpp>
-
-#include <json_util.hpp>
-
-namespace json_util {
-
-class test_fixture {
-protected:
-	deserializer document_{
-		{ "boolean",    true    },
-		{ "int",        -1234   },
-		{ "int2",       1234    },
-		{ "uint",       1234U   },
-		{ "string",     "str"   }
-	};
-};
-
-BOOST_FIXTURE_TEST_SUITE(test_fixture_suite, test_fixture)
-
-BOOST_AUTO_TEST_SUITE(get)
-
-BOOST_AUTO_TEST_CASE(boolean)
-{
-	const auto v = document_.get<bool>("boolean");
-
-	BOOST_TEST(v.has_value());
-	BOOST_TEST(*v);
-	BOOST_TEST(!document_.get<bool>("int"));
-	BOOST_TEST(!document_.get<bool>("int"));
-	BOOST_TEST(!document_.get<bool>("uint"));
-	BOOST_TEST(!document_.get<bool>("string"));
-}
-
-BOOST_AUTO_TEST_CASE(integer)
-{
-	const auto v = document_.get<int>("int");
-
-	BOOST_TEST(v.has_value());
-	BOOST_TEST(*v == -1234);
-	BOOST_TEST(!document_.get<int>("bool"));
-	BOOST_TEST(!document_.get<int>("string"));
-}
-
-BOOST_AUTO_TEST_CASE(unsigned_integer)
-{
-	const auto v = document_.get<unsigned>("uint");
-
-	BOOST_TEST(v.has_value());
-	BOOST_TEST(*v == 1234U);
-	BOOST_TEST(!document_.get<unsigned>("bool"));
-	BOOST_TEST(!document_.get<unsigned>("int"));
-	BOOST_TEST(!document_.get<unsigned>("string"));
-}
-
-BOOST_AUTO_TEST_CASE(string)
-{
-	const auto v = document_.get<std::string>("string");
-
-	BOOST_TEST(v.has_value());
-	BOOST_TEST(*v == "str");
-	BOOST_TEST(!document_.get<std::string>("bool"));
-	BOOST_TEST(!document_.get<std::string>("int"));
-	BOOST_TEST(!document_.get<std::string>("uint"));
-}
-
-BOOST_AUTO_TEST_CASE(string_view)
-{
-	const auto v = document_.get<std::string_view>("string");
-
-	BOOST_TEST(v.has_value());
-	BOOST_TEST(*v == "str");
-	BOOST_TEST(!document_.get<std::string_view>("bool"));
-	BOOST_TEST(!document_.get<std::string_view>("int"));
-	BOOST_TEST(!document_.get<std::string_view>("uint"));
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
-BOOST_AUTO_TEST_SUITE(optional_not_present)
-
-BOOST_AUTO_TEST_CASE(boolean)
-{
-	BOOST_TEST(*document_.optional<bool>("undefined", true));
-	BOOST_TEST(!*document_.optional<bool>("undefined", false));
-}
-
-BOOST_AUTO_TEST_CASE(integer)
-{
-	BOOST_TEST(*document_.optional<int>("undefined", 1234) == 1234);
-}
-
-BOOST_AUTO_TEST_CASE(unsigned_integer)
-{
-	BOOST_TEST(*document_.optional<unsigned>("undefined", 1234U) == 1234U);
-}
-
-BOOST_AUTO_TEST_CASE(string)
-{
-	BOOST_TEST(*document_.optional<std::string>("undefined", "foo") == "foo");
-}
-
-BOOST_AUTO_TEST_CASE(string_view)
-{
-	BOOST_TEST(*document_.optional<std::string_view>("undefined", "foo") == "foo");
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
-BOOST_AUTO_TEST_SUITE(optional_invalid)
-
-BOOST_AUTO_TEST_CASE(boolean)
-{
-	BOOST_TEST(!document_.optional<bool>("int", true));
-	BOOST_TEST(!document_.optional<bool>("uint", true));
-	BOOST_TEST(!document_.optional<bool>("string", true));
-}
-
-BOOST_AUTO_TEST_CASE(integer)
-{
-	BOOST_TEST(!document_.optional<int>("boolean", 1234));
-	BOOST_TEST(!document_.optional<int>("string", 1234));
-}
-
-BOOST_AUTO_TEST_CASE(unsigned_integer)
-{
-	BOOST_TEST(!document_.optional<unsigned>("boolean", 1234));
-	BOOST_TEST(!document_.optional<unsigned>("int", 1234));
-	BOOST_TEST(!document_.optional<unsigned>("string", 1234));
-}
-
-BOOST_AUTO_TEST_CASE(string)
-{
-	BOOST_TEST(!document_.optional<std::string>("boolean", "foo"));
-	BOOST_TEST(!document_.optional<std::string>("int", "foo"));
-	BOOST_TEST(!document_.optional<std::string>("uint", "foo"));
-}
-
-BOOST_AUTO_TEST_CASE(string_view)
-{
-	BOOST_TEST(!document_.optional<std::string_view>("boolean", "foo"));
-	BOOST_TEST(!document_.optional<std::string_view>("int", "foo"));
-	BOOST_TEST(!document_.optional<std::string_view>("uint", "foo"));
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
-BOOST_AUTO_TEST_SUITE(get_or)
-
-BOOST_AUTO_TEST_CASE(boolean)
-{
-	BOOST_TEST(document_.get_or<bool>("boolean", false));
-	BOOST_TEST(document_.get_or<bool>("int", true));
-	BOOST_TEST(document_.get_or<bool>("undefined", true));
-}
-
-BOOST_AUTO_TEST_CASE(integer)
-{
-	BOOST_TEST(document_.get_or<int>("int", 3320) == -1234);
-	BOOST_TEST(document_.get_or<int>("int2", 3320) == 1234);
-	BOOST_TEST(document_.get_or<int>("boolean", 3320) == 3320);
-	BOOST_TEST(document_.get_or<int>("undefined", 3320) == 3320);
-}
-
-BOOST_AUTO_TEST_CASE(unsigned_integer)
-{
-	BOOST_TEST(document_.get_or<unsigned>("uint", 3320U) == 1234U);
-	BOOST_TEST(document_.get_or<unsigned>("boolean", 3320U) == 3320);
-	BOOST_TEST(document_.get_or<unsigned>("undefined", 3320U) == 3320);
-}
-
-BOOST_AUTO_TEST_CASE(string)
-{
-	BOOST_TEST(document_.get_or<std::string>("string", "hello") == "str");
-	BOOST_TEST(document_.get_or<std::string>("boolean", "hello") == "hello");
-	BOOST_TEST(document_.get_or<std::string>("undefined", "hello") == "hello");
-}
-
-BOOST_AUTO_TEST_CASE(string_view)
-{
-	BOOST_TEST(document_.get_or<std::string_view>("string", "hello") == "str");
-	BOOST_TEST(document_.get_or<std::string_view>("boolean", "hello") == "hello");
-	BOOST_TEST(document_.get_or<std::string_view>("undefined", "hello") == "hello");
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
-BOOST_AUTO_TEST_SUITE_END()
-
-} // !json_util
--- a/cpp/options/CMakeLists.txt	Sat Oct 03 16:20:03 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-#
-# CMakeLists.txt -- code building for common code
-#
-# Copyright (c) 2019 David Demelier <markand@malikania.fr>
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-
-code_define_module(
-	NAME options
-	SOURCES options.hpp
-)
--- a/cpp/options/options.hpp	Sat Oct 03 16:20:03 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
-/*
- * options.hpp -- C++ similar interface to getopt(3)
- *
- * Copyright (c) 2019 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef OPTIONS_HPP
-#define OPTIONS_HPP
-
-/**
- * \file options.hpp
- * \brief C++ similar interface to getopt(3).
- */
-
-#include <initializer_list>
-#include <stdexcept>
-#include <string>
-#include <string_view>
-#include <tuple>
-#include <unordered_map>
-#include <vector>
-
-/**
- * \brief C++ similar interface to getopt(3).
- */
-namespace options {
-
-/**
- * Store the positional arguments and options.
- */
-using pack = std::tuple<
-	std::vector<std::string>,
-	std::unordered_multimap<char, std::string>
->;
-
-/**
- * Parse a collection of options and arguments.
- *
- * This function uses the same format as getopt(3) function, you need specify
- * each option in the fmt string and add a colon after the option character if
- * it requires a value.
- *
- * If a -- option appears in the argument list, it stops option parsing and all
- * next tokens are considered arguments even if they start with an hyphen.
- *
- * If the exlamation mark appears in the fmt argument, the function will stop
- * parsing tokens immediately when one argument is not an option.
- *
- * This function explicitly takes references to it and end parameters to allow
- * the user to determine the number of tokens actually parsed.
- *
- * Example of format strings:
- *
- * - "abc": are all three boolean options,
- * - "c:v": v is a boolean option c requires a value.
- *
- * Example of invocation:
- *
- * - `mycli -v -a`: is similar to `-va` if both 'v' and 'a' are boolean options,
- * - `mycli -v -- -c`: -c will be a positional argument rather than an option
- *   but '-v' is still an option.
- *
- * \tparam InputIt must dereference a string type (literal, std::string_view or
- * std::string)
- * \param it the first item
- * \param end the next item
- * \param fmt the format string
- * \return the result
- */
-template <typename InputIt>
-inline auto parse(InputIt&& it, InputIt&& end, std::string_view fmt) -> pack
-{
-	pack result;
-
-	for (; it != end; ++it) {
-		const std::string_view token(*it);
-
-		/*
-		 * Special token that stops parsing options, all next tokens
-		 * will be considered as positional arguments.
-		 */
-		if (token == "--") {
-			for (++it; it != end; ++it)
-				std::get<0>(result).push_back(std::string(*it));
-			break;
-		}
-
-		// Is this a positional argument?
-		if (token.compare(0U, 1U, "-") != 0) {
-			// Stop parsing in case of '!' in format string.
-			if (fmt.find('!') != std::string_view::npos)
-				break;
-
-			std::get<0>(result).push_back(std::string(token));
-			continue;
-		}
-
-		const auto sub = token.substr(1);
-
-		for (std::size_t i = 0U; i < sub.size(); ++i) {
-			const auto idx = fmt.find(sub[i]);
-
-			if (idx == std::string_view::npos)
-				throw std::runtime_error("invalid option");
-
-			// This is a boolean value.
-			if (fmt.compare(idx + 1U, 1U, ":") != 0) {
-				std::get<1>(result).emplace(sub[i], "");
-				continue;
-			}
-
-			/*
-			 * The value is adjacent to the option (e.g.
-			 * -csuper.conf).
-			 */
-			if (idx + 1U < sub.size()) {
-				std::get<1>(result).emplace(sub[i], std::string(sub.substr(i + 1)));
-				break;
-			}
-
-			// Option is the next token (e.g. -c super.conf).
-			if (++it == end || std::string_view(*it).compare(0U, 1U, "-") == 0)
-				throw std::runtime_error("option require a value");
-
-			std::get<1>(result).emplace(sub[i], std::string(*it));
-		}
-	}
-
-	return result;
-}
-
-/**
- * Convenient overload with an initializer_list.
- *
- * \tparam StringType must be either a std::string or std::string_view
- * \param args the arguments
- * \param fmt the format string
- * \return the result
- */
-template <typename String>
-inline auto parse(std::initializer_list<String> args, std::string_view fmt) -> pack
-{
-	auto begin = args.begin();
-	auto end = args.end();
-
-	return parse(begin, end, fmt);
-}
-
-/**
- * Convenient overload for main() arguments.
- *
- * \param argc the number of arguments
- * \param argv the arguments
- * \param fmt the format string
- * \return the result
- */
-inline auto parse(int argc, char** argv, std::string_view fmt) -> pack
-{
-	std::vector<std::string_view> args(argc);
-
-	for (int i = 0; i < argc; ++i)
-		args[i] = argv[i];
-
-	auto begin = args.begin();
-	auto end = args.end();
-
-	return parse(begin, end, fmt);
-}
-
-
-} // !options
-
-#endif // !OPTIONS_HPP
--- a/cpp/options/test/main.cpp	Sat Oct 03 16:20:03 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,166 +0,0 @@
-/*
- * main.cpp -- test options functions
- *
- * Copyright (c) 2019 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#define BOOST_TEST_MODULE "options"
-#include <boost/test/unit_test.hpp>
-
-#include "options.hpp"
-
-BOOST_AUTO_TEST_CASE(boolean)
-{
-	const auto [ args, options ] = options::parse({"-v"}, "v");
-
-	BOOST_TEST(args.size() == 0U);
-	BOOST_TEST(options.size() == 1U);
-	BOOST_TEST(options.count('v'));
-	BOOST_TEST(options.find('v')->second.empty());
-}
-
-BOOST_AUTO_TEST_CASE(boolean_repeat_detached)
-{
-	const auto [ args, options ] = options::parse({"-v", "-v"}, "v");
-
-	BOOST_TEST(args.size() == 0U);
-	BOOST_TEST(options.size() == 2U);
-	BOOST_TEST(options.count('v') == 2U);
-}
-
-BOOST_AUTO_TEST_CASE(boolean_repeat_adjacent)
-{
-	const auto [ args, options ] = options::parse({"-vv"}, "v");
-
-	BOOST_TEST(args.size() == 0U);
-	BOOST_TEST(options.size() == 2U);
-	BOOST_TEST(options.count('v') == 2U);
-}
-
-BOOST_AUTO_TEST_CASE(parameter_detached)
-{
-	const auto [ args, options ] = options::parse({"-c", "config"}, "c:");
-
-	BOOST_TEST(args.size() == 0U);
-	BOOST_TEST(options.size() == 1u);
-	BOOST_TEST(options.count('c'));
-	BOOST_TEST(options.find('c')->second == "config");
-}
-
-BOOST_AUTO_TEST_CASE(parameter_adjacent)
-{
-	const auto [ args, options ] = options::parse({"-cconfig"}, "c:");
-
-	BOOST_TEST(args.size() == 0U);
-	BOOST_TEST(options.size() == 1U);
-	BOOST_TEST(options.count('c'));
-	BOOST_TEST(options.find('c')->second == "config");
-}
-
-BOOST_AUTO_TEST_CASE(mixed_detached)
-{
-	const auto [ args, options ] = options::parse({"-vc", "config"}, "vc:");
-
-	BOOST_TEST(args.size() == 0U);
-	BOOST_TEST(options.size() == 2U);
-	BOOST_TEST(options.count('v'));
-	BOOST_TEST(options.find('v')->second.empty());
-	BOOST_TEST(options.count('c'));
-	BOOST_TEST(options.find('c')->second == "config");
-}
-
-BOOST_AUTO_TEST_CASE(mixed_adjacent)
-{
-	const auto [ args, options ] = options::parse({"-vcconfig"}, "vc:");
-
-	BOOST_TEST(args.size() == 0U);
-	BOOST_TEST(options.size() == 2U);
-	BOOST_TEST(options.count('v'));
-	BOOST_TEST(options.find('v')->second.empty());
-	BOOST_TEST(options.count('c'));
-	BOOST_TEST(options.find('c')->second == "config");
-}
-
-BOOST_AUTO_TEST_CASE(mixed_repeat)
-{
-	const auto [ args, options ] = options::parse({"-vvcconfig"}, "vc:");
-
-	BOOST_TEST(args.size() == 0U);
-	BOOST_TEST(options.size() == 3U);
-	BOOST_TEST(options.count('v') == 2U);
-	BOOST_TEST(options.find('v')->second.empty());
-	BOOST_TEST(options.count('c'));
-	BOOST_TEST(options.find('c')->second == "config");
-}
-
-BOOST_AUTO_TEST_CASE(arguments)
-{
-	const auto [ args, options ] = options::parse({"-c", "config", "install", "-v"}, "vc:");
-
-	BOOST_TEST(args.size() == 1U);
-	BOOST_TEST(args[0] == "install");
-	BOOST_TEST(options.size() == 2U);
-	BOOST_TEST(options.count('v') == 1U);
-	BOOST_TEST(options.find('v')->second.empty());
-	BOOST_TEST(options.count('c'));
-	BOOST_TEST(options.find('c')->second == "config");
-}
-
-BOOST_AUTO_TEST_CASE(stop)
-{
-	const auto [ args, options ] = options::parse({"rm", "-f", "--", "-p"}, "f");
-
-	BOOST_TEST(args.size() == 2U);
-	BOOST_TEST(args[0] == "rm");
-	BOOST_TEST(args[1] == "-p");
-	BOOST_TEST(options.size() == 1U);
-	BOOST_TEST(options.count('f') == 1U);
-	BOOST_TEST(options.find('f')->second.empty());
-}
-
-BOOST_AUTO_TEST_CASE(exclam)
-{
-	const auto [ args, options ] = options::parse({"-v", "install", "-p"}, "pv!");
-
-	BOOST_TEST(args.size() == 0U);
-	BOOST_TEST(options.size() == 1U);
-	BOOST_TEST(options.count('v') == 1U);
-	BOOST_TEST(options.find('v')->second.empty());
-	BOOST_TEST(options.count('p') == 0U);
-}
-
-BOOST_AUTO_TEST_SUITE(errors)
-
-BOOST_AUTO_TEST_CASE(invalid_option)
-{
-	BOOST_REQUIRE_THROW(options::parse({"-x"}, "v"), std::runtime_error);
-}
-
-BOOST_AUTO_TEST_CASE(value_required)
-{
-	BOOST_REQUIRE_THROW(options::parse({"-c", "-v"}, "vc:"), std::runtime_error);
-}
-
-BOOST_AUTO_TEST_CASE(value_required_detached)
-{
-	BOOST_REQUIRE_THROW(options::parse({"-v", "-c"}, "vc:"), std::runtime_error);
-}
-
-BOOST_AUTO_TEST_CASE(value_required_adjacent)
-{
-	BOOST_REQUIRE_THROW(options::parse({"-vc"}, "vc:"), std::runtime_error);
-}
-
-BOOST_AUTO_TEST_SUITE_END()
--- a/cpp/pexec/CMakeLists.txt	Sat Oct 03 16:20:03 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-#
-# CMakeLists.txt -- code building for common code
-#
-# Copyright (c) 2016-2019 David Demelier <markand@malikania.fr>
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-
-code_define_module(
-	NAME pexec
-	SOURCES pexec.hpp
-)
--- a/cpp/pexec/pexec.hpp	Sat Oct 03 16:20:03 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * pexec.hpp -- wrap an unsafe function and return an optional
- *
- * Copyright (c) 2016-2019 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <functional>
-#include <optional>
-
-template <typename Func, typename... Args>
-auto pexec(Func&& func, Args&&... args)
-{
-	using type = std::invoke_result_t<Func, Args...>;
-
-	try {
-		return std::optional<type>(std::invoke(std::forward<Func>(func), std::forward<Args>(args)...));
-	} catch (...) {
-		return std::optional<type>();
-	}
-}
--- a/cpp/pexec/test/main.cpp	Sat Oct 03 16:20:03 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * main.cpp -- test pexec function
- *
- * Copyright (c) 2016-2019 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#define BOOST_TEST_MODULE "pexec"
-#include <boost/test/unit_test.hpp>
-
-#include "pexec.hpp"
-
-namespace {
-
-int add(int x, int y)
-{
-	return x + y;
-}
-
-int fail(double)
-{
-	throw std::runtime_error("failed");
-}
-
-class math {
-public:
-	int add(int x, int y) const noexcept
-	{
-		return x + y;
-	}
-
-	int fail(double) const
-	{
-		throw std::runtime_error("failed");
-	}
-};
-
-BOOST_AUTO_TEST_SUITE(free)
-
-BOOST_AUTO_TEST_CASE(simple)
-{
-	BOOST_TEST(pexec(add, 10, 20).value() == 30);
-}
-
-BOOST_AUTO_TEST_CASE(error)
-{
-	BOOST_TEST(!pexec(fail, 5.5));
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
-BOOST_AUTO_TEST_SUITE(member)
-
-BOOST_AUTO_TEST_CASE(simple)
-{
-	math m;
-
-	BOOST_TEST(pexec(&math::add, &m, 10, 20).value() == 30);
-	BOOST_TEST(pexec(&math::add, std::ref(m), 10, 20).value() == 30);
-	BOOST_TEST(pexec(&math::add, m, 10, 20).value() == 30);
-}
-
-BOOST_AUTO_TEST_CASE(error)
-{
-	math m;
-
-	BOOST_TEST(!pexec(&math::fail, &m, 5.5));
-	BOOST_TEST(!pexec(&math::fail, std::ref(m), 5.5));
-	BOOST_TEST(!pexec(&math::fail, m, 5.5));
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
-} // !namespace
--- a/cpp/to_int/CMakeLists.txt	Sat Oct 03 16:20:03 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-#
-# CMakeLists.txt -- code building for common code
-#
-# Copyright (c) 2017-2019 David Demelier <markand@malikania.fr>
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-
-code_define_module(
-	NAME to-int
-	SOURCES to_int.hpp
-)
--- a/cpp/to_int/test/main.cpp	Sat Oct 03 16:20:03 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * main.cpp -- test to_int functions
- *
- * Copyright (c) 2017-2019 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#define BOOST_TEST_MODULE "to-int"
-#include <boost/test/unit_test.hpp>
-
-#include "to_int.hpp"
-
-BOOST_AUTO_TEST_SUITE(valid)
-
-BOOST_AUTO_TEST_CASE(signed_to_int)
-{
-	BOOST_TEST(*to_int("10") == 10);
-	BOOST_TEST(*to_int<std::int8_t>("-10") == -10);
-	BOOST_TEST(*to_int<std::int8_t>("10") == 10);
-	BOOST_TEST(*to_int<std::int16_t>("-1000") == -1000);
-	BOOST_TEST(*to_int<std::int16_t>("1000") == 1000);
-	BOOST_TEST(*to_int<std::int32_t>("-1000") == -1000);
-	BOOST_TEST(*to_int<std::int32_t>("1000") == 1000);
-}
-
-BOOST_AUTO_TEST_CASE(signed_to_int64)
-{
-	BOOST_TEST(*to_int<std::int64_t>("-9223372036854775807") == -9223372036854775807LL);
-	BOOST_TEST(*to_int<std::int64_t>("9223372036854775807") == 9223372036854775807LL);
-}
-
-BOOST_AUTO_TEST_CASE(unsigned_to_uint)
-{
-	BOOST_TEST(*to_uint("10") == 10U);
-	BOOST_TEST(*to_uint<std::uint8_t>("10") == 10U);
-	BOOST_TEST(*to_uint<std::uint16_t>("1000") == 1000U);
-	BOOST_TEST(*to_uint<std::uint32_t>("1000") == 1000U);
-}
-
-BOOST_AUTO_TEST_CASE(unsigned_to_uint64)
-{
-	BOOST_TEST(*to_uint<std::uint64_t>("18446744073709551615") == 18446744073709551615ULL);
-}
-
-BOOST_AUTO_TEST_SUITE_END()
-
-BOOST_AUTO_TEST_SUITE(errors)
-
-BOOST_AUTO_TEST_CASE(invalid_argument)
-{
-	BOOST_TEST(!to_int("plopation"));
-	BOOST_TEST(!to_uint("plopation"));
-}
-
-BOOST_AUTO_TEST_CASE(out_of_range)
-{
-	BOOST_TEST(!to_int<std::int8_t>("1000"));
-	BOOST_TEST(!to_int<std::int8_t>("-1000"));
-	BOOST_TEST(!to_uint<std::uint8_t>("1000"));
-	BOOST_TEST(!to_uint<std::uint8_t>("-1000"));
-}
-
-BOOST_AUTO_TEST_SUITE_END()
--- a/cpp/to_int/to_int.hpp	Sat Oct 03 16:20:03 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * to_int.hpp -- safely convert string to integers
- *
- * Copyright (c) 2017-2019 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef TO_INT_HPP
-#define TO_INT_HPP
-
-/**
- * \file to_int.hpp
- * \brief Safely convert string to integers.
- */
-
-#include <cstdlib>
-#include <limits>
-#include <optional>
-#include <string>
-#include <type_traits>
-
-/**
- * Convert the given string into a signed integer.
- *
- * \param str the string to convert
- * \param min the minimum value allowed
- * \param max the maximum value allowed
- * \return the value or std::none if not convertible
- */
-template <typename T = int>
-auto to_int(const std::string& str,
-            T min = std::numeric_limits<T>::min(),
-            T max = std::numeric_limits<T>::max()) noexcept -> std::optional<T>
-{
-	static_assert(std::is_signed<T>::value, "must be signed");
-
-	char* end;
-	auto v = std::strtoll(str.c_str(), &end, 10);
-
-	if (*end != '\0' || v < min || v > max)
-		return std::nullopt;
-
-	return static_cast<T>(v);
-}
-
-/**
- * Convert the given string into a unsigned integer.
- *
- * \note invalid numbers are valid as well
- * \param str the string to convert
- * \param min the minimum value allowed
- * \param max the maximum value allowed
- * \return the value or std::none if not convertible
- */
-template <typename T = unsigned>
-auto to_uint(const std::string& str,
-             T min = std::numeric_limits<T>::min(),
-             T max = std::numeric_limits<T>::max()) noexcept -> std::optional<T>
-{
-	static_assert(std::is_unsigned<T>::value, "must be unsigned");
-
-	char* end;
-	auto v = std::strtoull(str.c_str(), &end, 10);
-
-	if (*end != '\0' || v < min || v > max)
-		return std::nullopt;
-
-	return static_cast<T>(v);
-}
-
-#endif // !TO_INT_HPP