From 08d077b84d2c869d91e6e8b55d130b4499c21a77 Mon Sep 17 00:00:00 2001 From: Tino Didriksen Date: Tue, 10 Sep 2024 17:30:58 +0200 Subject: [PATCH] Use C++17; Use host utfcpp / utf8cpp; Drop bundled mapbox::variant --- .gitignore | 1 + README.md | 8 +- configure.ac | 25 +- python/libdivvun.i | 3 +- python/setup.py.in | 2 +- src/Makefile.am | 3 - src/blanktag.hpp | 4 +- src/cgspell.cpp | 9 +- src/cgspell.hpp | 4 +- src/checker.cpp | 14 +- src/cxxopts.hpp | 16 +- src/main_checker.cpp | 113 ++-- src/mapbox/LICENSE | 25 - src/mapbox/LICENSE_1_0.txt | 23 - src/mapbox/recursive_wrapper.hpp | 122 ---- src/mapbox/variant.hpp | 1040 ------------------------------ src/mapbox/variant_visitor.hpp | 43 -- src/normaliser.hpp | 2 - src/phon.hpp | 2 - src/pipespec.hpp | 3 - src/suggest.cpp | 31 +- src/suggest.hpp | 5 +- src/utf8.h | 34 - src/utf8/checked.h | 327 ---------- src/utf8/core.h | 332 ---------- src/utf8/unchecked.h | 228 ------- src/util.hpp | 3 +- 27 files changed, 141 insertions(+), 2281 deletions(-) delete mode 100644 src/mapbox/LICENSE delete mode 100644 src/mapbox/LICENSE_1_0.txt delete mode 100644 src/mapbox/recursive_wrapper.hpp delete mode 100644 src/mapbox/variant.hpp delete mode 100644 src/mapbox/variant_visitor.hpp delete mode 100644 src/utf8.h delete mode 100644 src/utf8/checked.h delete mode 100644 src/utf8/core.h delete mode 100644 src/utf8/unchecked.h diff --git a/.gitignore b/.gitignore index f0ccc36..5fa6ce8 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ install-sh missing config.log config.status +*~ src/.deps/ src/*.o /src/divvun-suggest diff --git a/README.md b/README.md index 007ac55..1c882b7 100644 --- a/README.md +++ b/README.md @@ -150,8 +150,9 @@ this package. ## For just `divvun-suggest` and `divvun-blanktag` - gcc >=5.0.0 with libstdc++-5-dev (or similarly recent version of - clang, with full C++11 support) + clang, with full C++17 support) - libxml2-utils (just for xmllint) +- utfcpp (also known as utf8cpp) - libhfst >=3.12.2 - libpugixml >=1.7.2 (optional) @@ -170,8 +171,9 @@ that library. Alternatively, you can run ./configure with ## If you also want `divvun-checker` - gcc >=5.0.0 with libstdc++-5-dev (or similarly recent version of - clang, with full C++11 support) + clang, with full C++17 support) - libxml2-utils (just for xmllint) +- utfcpp (also known as utf8cpp) - libhfst >=3.12.2 - libpugixml >=1.7.2 - libcg3-dev >=1.1.2.12327 @@ -1403,7 +1405,7 @@ then your C++ compiler is too old. See [Prerequisites](#org6558baf). If you get - configure: error: 'g++ -std=c++11 -Wall -I/usr/include/hfst/ @GLIB_CFLAGS@ -I/usr/include/ ' does not accept ISO C++11 + configure: error: 'g++ -std=c++17 -Wall -I/usr/include/hfst/ @GLIB_CFLAGS@ -I/usr/include/ ' does not accept ISO C++17 then you may be at the receiving end of . A workaround is to edit diff --git a/configure.ac b/configure.ac index 1dc7a2f..3c10f09 100644 --- a/configure.ac +++ b/configure.ac @@ -32,19 +32,24 @@ AX_CHECK_COMPILE_FLAG([-Wall], [], AC_MSG_ERROR([compiler doesn't accept -Wall - AX_CHECK_COMPILE_FLAG([-fstack-protector-strong], [CXXFLAGS="$CXXFLAGS -fstack-protector-strong"]) +AC_CHECK_HEADER(["$HOMEBREW_PREFIX/include/utf8cpp/utf8.h"], [CPPFLAGS="-I$HOMEBREW_PREFIX/include/utf8cpp/ $CPPFLAGS"], [ + AC_CHECK_HEADER([utf8cpp/utf8.h], [CPPFLAGS="-I/usr/include/utf8cpp/ $CPPFLAGS"], [ + AC_CHECK_HEADER([utf8.h], [], [AC_MSG_ERROR([You don't have utfcpp installed.])]) + ]) +]) + + dnl ==================== -dnl Checks C++11 support +dnl Checks C++17 support dnl ==================== -AX_CHECK_COMPILE_FLAG([-std=c++17], [CXXFLAGS="$CXXFLAGS -std=c++17"], [ - AX_CHECK_COMPILE_FLAG([-std=c++1z], [CXXFLAGS="$CXXFLAGS -std=c++1z"], [ - AX_CHECK_COMPILE_FLAG([-std=c++14], [CXXFLAGS="$CXXFLAGS -std=c++14"], [ - AX_CHECK_COMPILE_FLAG([-std=c++1y], [CXXFLAGS="$CXXFLAGS -std=c++1y"], [ - AX_CHECK_COMPILE_FLAG([-std=c++11], [CXXFLAGS="$CXXFLAGS -std=c++11"], [ - AC_MSG_ERROR([compiler doesn't accept any -std=c++11, please upgrade your compiler])]) - ]) - ]) - ]) +for version in 26 2c 23 2b 20 2a 17; do + version_flag="-std=c++${version}" + AX_CHECK_COMPILE_FLAG([${version_flag}], [break], [version_flag=none]) +done +AS_IF([test "$version_flag" = none], [ + AC_MSG_ERROR([Could not enable at least C++17 - upgrade your compiler]) ]) +CXXFLAGS="$CXXFLAGS ${version_flag}" dnl ================== diff --git a/python/libdivvun.i b/python/libdivvun.i index 6f3556f..607e293 100644 --- a/python/libdivvun.i +++ b/python/libdivvun.i @@ -31,7 +31,7 @@ %{ #include "../src/checkertypes.hpp" #include "../src/checker.hpp" -#include "../src/utf8.h" +#include %} #ifdef _MSC_VER @@ -58,7 +58,6 @@ wrap_unique_ptr(CheckerUniquePtr, divvun::Checker); %include "../src/checkertypes.hpp" %include "../src/checker.hpp" -%include "../src/utf8.h" %template(StringVector) std::vector; %template(StringSet) std::set; diff --git a/python/setup.py.in b/python/setup.py.in index 6651961..4edbd49 100644 --- a/python/setup.py.in +++ b/python/setup.py.in @@ -28,7 +28,7 @@ libdivvun_module = Extension( include_dirs=['@top_srcdir@/src'], library_dirs=['@top_srcdir@/src/.libs'], libraries=['divvun'], - extra_compile_args=getenv_list('CPPFLAGS') + getenv_list('CXXFLAGS'), + extra_compile_args='@CPPFLAGS@'.split() + '@CXXFLAGS@'.split() + getenv_list('CPPFLAGS') + getenv_list('CXXFLAGS'), extra_link_args=getenv_list('LDFLAGS')) diff --git a/src/Makefile.am b/src/Makefile.am index 24038ce..d140766 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,9 +2,6 @@ datadir = $(prefix)/share/libdivvun AM_CPPFLAGS = -DPREFIX="\"$(prefix)\"" noinst_HEADERS=util.hpp hfst_util.hpp json.hpp \ - utf8.h utf8/checked.h utf8/core.h utf8/unchecked.h \ - mapbox/variant.hpp mapbox/recursive_wrapper.hpp \ - mapbox/variant_visitor.hpp \ cxxopts.hpp # divvun-suggest binary: divvun_suggest_SOURCES = main_suggest.cpp suggest.cpp suggest.hpp diff --git a/src/blanktag.hpp b/src/blanktag.hpp index 076708e..e540e8d 100644 --- a/src/blanktag.hpp +++ b/src/blanktag.hpp @@ -33,11 +33,11 @@ #include #include // variants: -#include "mapbox/variant.hpp" +#include namespace divvun { -using mapbox::util::variant; +using std::variant; using std::string; using std::vector; using std::unique_ptr; diff --git a/src/cgspell.cpp b/src/cgspell.cpp index 1e6ce0a..0e83fdb 100644 --- a/src/cgspell.cpp +++ b/src/cgspell.cpp @@ -81,8 +81,13 @@ void print_cg_subreading(size_t indent, } if(indent == 1) { os << " "; - mw_a.match([] (Nothing) {}, - [&os] (Weight w_a) { os << " "; }); + std::visit([&](auto&& arg){ + using T = std::decay_t; + if constexpr (std::is_same_v) {} + if constexpr (std::is_same_v) { + os << " "; + } + }, mw_a); os << " " << errtag; os << " \"" << form << "\"S"; } diff --git a/src/cgspell.hpp b/src/cgspell.hpp index d095cf0..406a18e 100644 --- a/src/cgspell.hpp +++ b/src/cgspell.hpp @@ -31,11 +31,11 @@ // hfst: #include // variants: -#include "mapbox/variant.hpp" +#include namespace divvun { -using mapbox::util::variant; +using std::variant; using std::string; using std::vector; using std::pair; diff --git a/src/checker.cpp b/src/checker.cpp index dde2cc5..7b17048 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -164,13 +164,15 @@ std::set searchPaths() { "/usr/share/voikko/4", "/usr/local/share/voikko/4" }; - expanduser().match( - [](Nothing){ }, - [&](string home) { - dirs.insert(home + "/.voikko/4"); + std::visit([&](auto&& arg){ + using T = std::decay_t; + if constexpr (std::is_same_v) {} + if constexpr (std::is_same_v) { + dirs.insert(arg + "/.voikko/4"); // TODO: getenv freedesktop stuff - dirs.insert(home + "/.config/voikko/4"); - }); + dirs.insert(arg + "/.config/voikko/4"); + } + }, expanduser()); return dirs; } diff --git a/src/cxxopts.hpp b/src/cxxopts.hpp index d4e1b72..14301b7 100644 --- a/src/cxxopts.hpp +++ b/src/cxxopts.hpp @@ -303,7 +303,7 @@ namespace cxxopts { public: option_exists_error(const std::string& option) - : OptionSpecException(u8"Option ‘" + option + u8"’ already exists") + : OptionSpecException("Option ‘" + option + "’ already exists") { } }; @@ -312,7 +312,7 @@ namespace cxxopts { public: invalid_option_format_error(const std::string& format) - : OptionSpecException(u8"Invalid option format ‘" + format + u8"’") + : OptionSpecException("Invalid option format ‘" + format + "’") { } }; @@ -321,7 +321,7 @@ namespace cxxopts { public: option_not_exists_exception(const std::string& option) - : OptionParseException(u8"Option ‘" + option + u8"’ does not exist") + : OptionParseException("Option ‘" + option + "’ does not exist") { } }; @@ -330,7 +330,7 @@ namespace cxxopts { public: missing_argument_exception(const std::string& option) - : OptionParseException(u8"Option ‘" + option + u8"’ is missing an argument") + : OptionParseException("Option ‘" + option + "’ is missing an argument") { } }; @@ -339,7 +339,7 @@ namespace cxxopts { public: option_requires_argument_exception(const std::string& option) - : OptionParseException(u8"Option ‘" + option + u8"’ requires an argument") + : OptionParseException("Option ‘" + option + "’ requires an argument") { } }; @@ -353,7 +353,7 @@ namespace cxxopts const std::string& arg ) : OptionParseException( - u8"Option ‘" + option + u8"’ does not take an argument, but argument‘" + "Option ‘" + option + "’ does not take an argument, but argument‘" + arg + "’ given") { } @@ -363,7 +363,7 @@ namespace cxxopts { public: option_not_present_exception(const std::string& option) - : OptionParseException(u8"Option ‘" + option + u8"’ not present") + : OptionParseException("Option ‘" + option + "’ not present") { } }; @@ -376,7 +376,7 @@ namespace cxxopts const std::string& arg ) : OptionParseException( - u8"Argument ‘" + arg + u8"’ failed to parse" + "Argument ‘" + arg + "’ failed to parse" ) { } diff --git a/src/main_checker.cpp b/src/main_checker.cpp index 5578b39..7f24368 100644 --- a/src/main_checker.cpp +++ b/src/main_checker.cpp @@ -30,15 +30,20 @@ using divvun::Pipeline; using divvun::toUtf8; using divvun::variant; - variant getPipelineXml(const std::string& path, const variant& mpipename, bool verbose, bool trace) { const std::unique_ptr spec(new divvun::PipeSpec(path)); - std::u16string pipename = - mpipename.match([&](Nothing) { return spec->default_pipe; }, - [](std::u16string s) { return s; }); + std::u16string pipename = std::visit([&](auto&& arg) { + using T = std::decay_t; + if constexpr (std::is_same_v) { + return spec->default_pipe; + } + if constexpr (std::is_same_v) { + return arg; + } + }, mpipename); if (spec->pnodes.find(pipename) == spec->pnodes.end()) { std::cerr << "divvun-checker: ERROR: Couldn't find pipe " << toUtf8(pipename) << " in " << path << std::endl; @@ -52,9 +57,15 @@ variant getPipelineAr(const std::string& path, bool verbose, bool trace) { const auto& ar_spec = divvun::readArPipeSpec(path); - std::u16string pipename = - mpipename.match([&](Nothing) { return ar_spec->spec->default_pipe; }, - [](std::u16string s) { return s; }); + std::u16string pipename = std::visit([&](auto&& arg) { + using T = std::decay_t; + if constexpr (std::is_same_v) { + return ar_spec->spec->default_pipe; + } + if constexpr (std::is_same_v) { + return arg; + } + }, mpipename); if (ar_spec->spec->pnodes.find(pipename) == ar_spec->spec->pnodes.end()) { std::cerr << "divvun-checker: ERROR: Couldn't find pipe " << toUtf8(pipename) << " in " << path << std::endl; @@ -221,18 +232,22 @@ int main(int argc, char** argv) { if (options.count("variant")) { pipename = fromUtf8(options["variant"].as()); } - return getPipelineXml(specfile, pipename, verbose, trace) - .match([](int r) { return r; }, - [&](Pipeline& p) { - p.setIgnores(ignores); - if (options.count("preferences")) { - printPrefs(p); - } - else { - run(p); - } - return EXIT_SUCCESS; - }); + return std::visit([&](auto&& arg) { + using T = std::decay_t; + if constexpr (std::is_same_v) { + return arg; + } + if constexpr (std::is_same_v) { + arg.setIgnores(ignores); + if (options.count("preferences")) { + printPrefs(arg); + } + else { + run(arg); + } + return EXIT_SUCCESS; + } + }, getPipelineXml(specfile, pipename, verbose, trace)); } else if (options.count("archive")) { if (options.count("language")) { @@ -250,19 +265,23 @@ int main(int argc, char** argv) { if (options.count("variant")) { pipename = fromUtf8(options["variant"].as()); } - return getPipelineAr(archive, pipename, verbose, trace) - .match([](int r) { return r; }, - [&](Pipeline& p) { - p.setIgnores(ignores); - p.setIncludes(includes); - if (options.count("preferences")) { - printPrefs(p); - } - else { - run(p); - } - return EXIT_SUCCESS; - }); + return std::visit([&](auto&& arg) { + using T = std::decay_t; + if constexpr (std::is_same_v) { + return arg; + } + if constexpr (std::is_same_v) { + arg.setIgnores(ignores); + arg.setIncludes(includes); + if (options.count("preferences")) { + printPrefs(arg); + } + else { + run(arg); + } + return EXIT_SUCCESS; + } + }, getPipelineAr(archive, pipename, verbose, trace)); } else if (options.count("language")) { const auto& lang = options["language"].as(); @@ -286,19 +305,23 @@ int main(int argc, char** argv) { if (options.count("variant")) { pipename = fromUtf8(options["variant"].as()); } - return getPipelineAr(archive, pipename, verbose, trace) - .match([](int r) { return r; }, - [&](Pipeline& p) { - p.setIgnores(ignores); - p.setIncludes(includes); - if (options.count("preferences")) { - printPrefs(p); - } - else { - run(p); - } - return EXIT_SUCCESS; - }); + return std::visit([&](auto&& arg) { + using T = std::decay_t; + if constexpr (std::is_same_v) { + return arg; + } + if constexpr (std::is_same_v) { + arg.setIgnores(ignores); + arg.setIncludes(includes); + if (options.count("preferences")) { + printPrefs(arg); + } + else { + run(arg); + } + return EXIT_SUCCESS; + } + }, getPipelineAr(archive, pipename, verbose, trace)); } else { std::cerr << argv[0] diff --git a/src/mapbox/LICENSE b/src/mapbox/LICENSE deleted file mode 100644 index 6c4ce40..0000000 --- a/src/mapbox/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) MapBox -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -- Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -- Redistributions in binary form must reproduce the above copyright notice, this - list of conditions and the following disclaimer in the documentation and/or - other materials provided with the distribution. -- Neither the name "MapBox" nor the names of its contributors may be - used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/src/mapbox/LICENSE_1_0.txt b/src/mapbox/LICENSE_1_0.txt deleted file mode 100644 index 36b7cd9..0000000 --- a/src/mapbox/LICENSE_1_0.txt +++ /dev/null @@ -1,23 +0,0 @@ -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/mapbox/recursive_wrapper.hpp b/src/mapbox/recursive_wrapper.hpp deleted file mode 100644 index 4ffcbd7..0000000 --- a/src/mapbox/recursive_wrapper.hpp +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP -#define MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP - -// Based on variant/recursive_wrapper.hpp from boost. -// -// Original license: -// -// Copyright (c) 2002-2003 -// Eric Friedman, Itay Maman -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include - -namespace mapbox { -namespace util { - -template -class recursive_wrapper -{ - - T* p_; - - void assign(T const& rhs) - { - this->get() = rhs; - } - -public: - using type = T; - - /** - * Default constructor default initializes the internally stored value. - * For POD types this means nothing is done and the storage is - * uninitialized. - * - * @throws std::bad_alloc if there is insufficient memory for an object - * of type T. - * @throws any exception thrown by the default constructur of T. - */ - recursive_wrapper() - : p_(new T){} - - ~recursive_wrapper() noexcept { delete p_; } - - recursive_wrapper(recursive_wrapper const& operand) - : p_(new T(operand.get())) {} - - recursive_wrapper(T const& operand) - : p_(new T(operand)) {} - - recursive_wrapper(recursive_wrapper&& operand) - : p_(new T(std::move(operand.get()))) {} - - recursive_wrapper(T&& operand) - : p_(new T(std::move(operand))) {} - - inline recursive_wrapper& operator=(recursive_wrapper const& rhs) - { - assign(rhs.get()); - return *this; - } - - inline recursive_wrapper& operator=(T const& rhs) - { - assign(rhs); - return *this; - } - - inline void swap(recursive_wrapper& operand) noexcept - { - T* temp = operand.p_; - operand.p_ = p_; - p_ = temp; - } - - recursive_wrapper& operator=(recursive_wrapper&& rhs) noexcept - { - swap(rhs); - return *this; - } - - recursive_wrapper& operator=(T&& rhs) - { - get() = std::move(rhs); - return *this; - } - - T& get() - { - assert(p_); - return *get_pointer(); - } - - T const& get() const - { - assert(p_); - return *get_pointer(); - } - - T* get_pointer() { return p_; } - - const T* get_pointer() const { return p_; } - - operator T const&() const { return this->get(); } - - operator T&() { return this->get(); } - -}; // class recursive_wrapper - -template -inline void swap(recursive_wrapper& lhs, recursive_wrapper& rhs) noexcept -{ - lhs.swap(rhs); -} -} // namespace util -} // namespace mapbox - -#endif // MAPBOX_UTIL_RECURSIVE_WRAPPER_HPP diff --git a/src/mapbox/variant.hpp b/src/mapbox/variant.hpp deleted file mode 100644 index 335a4be..0000000 --- a/src/mapbox/variant.hpp +++ /dev/null @@ -1,1040 +0,0 @@ -#ifndef MAPBOX_UTIL_VARIANT_HPP -#define MAPBOX_UTIL_VARIANT_HPP - -#include -#include // size_t -#include // operator new -#include // runtime_error -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -// clang-format off -// [[deprecated]] is only available in C++14, use this for the time being -#if __cplusplus <= 201103L -# ifdef __GNUC__ -# define MAPBOX_VARIANT_DEPRECATED __attribute__((deprecated)) -# elif defined(_MSC_VER) -# define MAPBOX_VARIANT_DEPRECATED __declspec(deprecated) -# else -# define MAPBOX_VARIANT_DEPRECATED -# endif -#else -# define MAPBOX_VARIANT_DEPRECATED [[deprecated]] -#endif - - -#ifdef _MSC_VER -// https://msdn.microsoft.com/en-us/library/bw1hbe6y.aspx -# ifdef NDEBUG -# define VARIANT_INLINE __forceinline -# else -# define VARIANT_INLINE //__declspec(noinline) -# endif -#else -# ifdef NDEBUG -# define VARIANT_INLINE //inline __attribute__((always_inline)) -# else -# define VARIANT_INLINE __attribute__((noinline)) -# endif -#endif -// clang-format on - -// Exceptions -#if defined( __EXCEPTIONS) || defined( _MSC_VER) -#define HAS_EXCEPTIONS -#endif - -#define VARIANT_MAJOR_VERSION 1 -#define VARIANT_MINOR_VERSION 1 -#define VARIANT_PATCH_VERSION 0 - -#define VARIANT_VERSION (VARIANT_MAJOR_VERSION * 100000) + (VARIANT_MINOR_VERSION * 100) + (VARIANT_PATCH_VERSION) - -namespace mapbox { -namespace util { - -// XXX This should derive from std::logic_error instead of std::runtime_error. -// See https://github.com/mapbox/variant/issues/48 for details. -class bad_variant_access : public std::runtime_error -{ - -public: - explicit bad_variant_access(const std::string& what_arg) - : runtime_error(what_arg) {} - - explicit bad_variant_access(const char* what_arg) - : runtime_error(what_arg) {} - -}; // class bad_variant_access - -template -struct MAPBOX_VARIANT_DEPRECATED static_visitor -{ - using result_type = R; - -protected: - static_visitor() {} - ~static_visitor() {} -}; - -#if !defined(MAPBOX_VARIANT_MINIMIZE_SIZE) -using type_index_t = unsigned int; -#else -#if defined(MAPBOX_VARIANT_OPTIMIZE_FOR_SPEED) -using type_index_t = std::uint_fast8_t; -#else -using type_index_t = std::uint_least8_t; -#endif -#endif - -namespace detail { - -static constexpr type_index_t invalid_value = type_index_t(-1); - -template -struct direct_type; - -template -struct direct_type -{ - static constexpr type_index_t index = std::is_same::value - ? sizeof...(Types) - : direct_type::index; -}; - -template -struct direct_type -{ - static constexpr type_index_t index = invalid_value; -}; - -#if __cpp_lib_logical_traits >= 201510L - -using std::conjunction; -using std::disjunction; - -#else - -template -struct conjunction : std::true_type {}; - -template -struct conjunction : B1 {}; - -template -struct conjunction : std::conditional::type {}; - -template -struct conjunction : std::conditional, B1>::type {}; - -template -struct disjunction : std::false_type {}; - -template -struct disjunction : B1 {}; - -template -struct disjunction : std::conditional::type {}; - -template -struct disjunction : std::conditional>::type {}; - -#endif - -template -struct convertible_type; - -template -struct convertible_type -{ - static constexpr type_index_t index = std::is_convertible::value - ? disjunction...>::value ? invalid_value : sizeof...(Types) - : convertible_type::index; -}; - -template -struct convertible_type -{ - static constexpr type_index_t index = invalid_value; -}; - -template -struct value_traits -{ - using value_type = typename std::remove_const::type>::type; - using value_type_wrapper = recursive_wrapper; - static constexpr type_index_t direct_index = direct_type::index; - static constexpr bool is_direct = direct_index != invalid_value; - static constexpr type_index_t index_direct_or_wrapper = is_direct ? direct_index : direct_type::index; - static constexpr bool is_direct_or_wrapper = index_direct_or_wrapper != invalid_value; - static constexpr type_index_t index = is_direct_or_wrapper ? index_direct_or_wrapper : convertible_type::index; - static constexpr bool is_valid = index != invalid_value; - static constexpr type_index_t tindex = is_valid ? sizeof...(Types)-index : 0; - using target_type = typename std::tuple_element>::type; -}; - -template -struct enable_if_type -{ - using type = R; -}; - -template -struct result_of_unary_visit -{ - using type = typename std::result_of::type; -}; - -template -struct result_of_unary_visit::type> -{ - using type = typename F::result_type; -}; - -template -struct result_of_binary_visit -{ - using type = typename std::result_of::type; -}; - -template -struct result_of_binary_visit::type> -{ - using type = typename F::result_type; -}; - -template -struct static_max; - -template -struct static_max -{ - static const type_index_t value = arg; -}; - -template -struct static_max -{ - static const type_index_t value = arg1 >= arg2 ? static_max::value : static_max::value; -}; - -template -struct variant_helper; - -template -struct variant_helper -{ - VARIANT_INLINE static void destroy(const type_index_t type_index, void* data) - { - if (type_index == sizeof...(Types)) - { - reinterpret_cast(data)->~T(); - } - else - { - variant_helper::destroy(type_index, data); - } - } - - VARIANT_INLINE static void move(const type_index_t old_type_index, void* old_value, void* new_value) - { - if (old_type_index == sizeof...(Types)) - { - new (new_value) T(std::move(*reinterpret_cast(old_value))); - } - else - { - variant_helper::move(old_type_index, old_value, new_value); - } - } - - VARIANT_INLINE static void copy(const type_index_t old_type_index, const void* old_value, void* new_value) - { - if (old_type_index == sizeof...(Types)) - { - new (new_value) T(*reinterpret_cast(old_value)); - } - else - { - variant_helper::copy(old_type_index, old_value, new_value); - } - } -}; - -template <> -struct variant_helper<> -{ - VARIANT_INLINE static void destroy(const type_index_t, void*) {} - VARIANT_INLINE static void move(const type_index_t, void*, void*) {} - VARIANT_INLINE static void copy(const type_index_t, const void*, void*) {} -}; - -template -struct unwrapper -{ - static T const& apply_const(T const& obj) { return obj; } - static T& apply(T& obj) { return obj; } -}; - -template -struct unwrapper> -{ - static auto apply_const(recursive_wrapper const& obj) - -> typename recursive_wrapper::type const& - { - return obj.get(); - } - static auto apply(recursive_wrapper& obj) - -> typename recursive_wrapper::type& - { - return obj.get(); - } -}; - -template -struct unwrapper> -{ - static auto apply_const(std::reference_wrapper const& obj) - -> typename std::reference_wrapper::type const& - { - return obj.get(); - } - static auto apply(std::reference_wrapper& obj) - -> typename std::reference_wrapper::type& - { - return obj.get(); - } -}; - -template -struct dispatcher; - -template -struct dispatcher -{ - VARIANT_INLINE static R apply_const(V const& v, F&& f) - { - if (v.template is()) - { - return f(unwrapper::apply_const(v.template get_unchecked())); - } - else - { - return dispatcher::apply_const(v, std::forward(f)); - } - } - - VARIANT_INLINE static R apply(V& v, F&& f) - { - if (v.template is()) - { - return f(unwrapper::apply(v.template get_unchecked())); - } - else - { - return dispatcher::apply(v, std::forward(f)); - } - } -}; - -template -struct dispatcher -{ - VARIANT_INLINE static R apply_const(V const& v, F&& f) - { - return f(unwrapper::apply_const(v.template get_unchecked())); - } - - VARIANT_INLINE static R apply(V& v, F&& f) - { - return f(unwrapper::apply(v.template get_unchecked())); - } -}; - -template -struct binary_dispatcher_rhs; - -template -struct binary_dispatcher_rhs -{ - VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f) - { - if (rhs.template is()) // call binary functor - { - return f(unwrapper::apply_const(lhs.template get_unchecked()), - unwrapper::apply_const(rhs.template get_unchecked())); - } - else - { - return binary_dispatcher_rhs::apply_const(lhs, rhs, std::forward(f)); - } - } - - VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f) - { - if (rhs.template is()) // call binary functor - { - return f(unwrapper::apply(lhs.template get_unchecked()), - unwrapper::apply(rhs.template get_unchecked())); - } - else - { - return binary_dispatcher_rhs::apply(lhs, rhs, std::forward(f)); - } - } -}; - -template -struct binary_dispatcher_rhs -{ - VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f) - { - return f(unwrapper::apply_const(lhs.template get_unchecked()), - unwrapper::apply_const(rhs.template get_unchecked())); - } - - VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f) - { - return f(unwrapper::apply(lhs.template get_unchecked()), - unwrapper::apply(rhs.template get_unchecked())); - } -}; - -template -struct binary_dispatcher_lhs; - -template -struct binary_dispatcher_lhs -{ - VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f) - { - if (lhs.template is()) // call binary functor - { - return f(unwrapper::apply_const(lhs.template get_unchecked()), - unwrapper::apply_const(rhs.template get_unchecked())); - } - else - { - return binary_dispatcher_lhs::apply_const(lhs, rhs, std::forward(f)); - } - } - - VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f) - { - if (lhs.template is()) // call binary functor - { - return f(unwrapper::apply(lhs.template get_unchecked()), - unwrapper::apply(rhs.template get_unchecked())); - } - else - { - return binary_dispatcher_lhs::apply(lhs, rhs, std::forward(f)); - } - } -}; - -template -struct binary_dispatcher_lhs -{ - VARIANT_INLINE static R apply_const(V const& lhs, V const& rhs, F&& f) - { - return f(unwrapper::apply_const(lhs.template get_unchecked()), - unwrapper::apply_const(rhs.template get_unchecked())); - } - - VARIANT_INLINE static R apply(V& lhs, V& rhs, F&& f) - { - return f(unwrapper::apply(lhs.template get_unchecked()), - unwrapper::apply(rhs.template get_unchecked())); - } -}; - -template -struct binary_dispatcher; - -template -struct binary_dispatcher -{ - VARIANT_INLINE static R apply_const(V const& v0, V const& v1, F&& f) - { - if (v0.template is()) - { - if (v1.template is()) - { - return f(unwrapper::apply_const(v0.template get_unchecked()), - unwrapper::apply_const(v1.template get_unchecked())); // call binary functor - } - else - { - return binary_dispatcher_rhs::apply_const(v0, v1, std::forward(f)); - } - } - else if (v1.template is()) - { - return binary_dispatcher_lhs::apply_const(v0, v1, std::forward(f)); - } - return binary_dispatcher::apply_const(v0, v1, std::forward(f)); - } - - VARIANT_INLINE static R apply(V& v0, V& v1, F&& f) - { - if (v0.template is()) - { - if (v1.template is()) - { - return f(unwrapper::apply(v0.template get_unchecked()), - unwrapper::apply(v1.template get_unchecked())); // call binary functor - } - else - { - return binary_dispatcher_rhs::apply(v0, v1, std::forward(f)); - } - } - else if (v1.template is()) - { - return binary_dispatcher_lhs::apply(v0, v1, std::forward(f)); - } - return binary_dispatcher::apply(v0, v1, std::forward(f)); - } -}; - -template -struct binary_dispatcher -{ - VARIANT_INLINE static R apply_const(V const& v0, V const& v1, F&& f) - { - return f(unwrapper::apply_const(v0.template get_unchecked()), - unwrapper::apply_const(v1.template get_unchecked())); // call binary functor - } - - VARIANT_INLINE static R apply(V& v0, V& v1, F&& f) - { - return f(unwrapper::apply(v0.template get_unchecked()), - unwrapper::apply(v1.template get_unchecked())); // call binary functor - } -}; - -// comparator functors -struct equal_comp -{ - template - bool operator()(T const& lhs, T const& rhs) const - { - return lhs == rhs; - } -}; - -struct less_comp -{ - template - bool operator()(T const& lhs, T const& rhs) const - { - return lhs < rhs; - } -}; - -template -class comparer -{ -public: - explicit comparer(Variant const& lhs) noexcept - : lhs_(lhs) {} - comparer& operator=(comparer const&) = delete; - // visitor - template - bool operator()(T const& rhs_content) const - { - T const& lhs_content = lhs_.template get_unchecked(); - return Comp()(lhs_content, rhs_content); - } - -private: - Variant const& lhs_; -}; - -// hashing visitor -struct hasher -{ - template - std::size_t operator()(const T& hashable) const - { - return std::hash{}(hashable); - } -}; - -} // namespace detail - -struct no_init {}; - -template -class variant -{ - static_assert(sizeof...(Types) > 0, "Template parameter type list of variant can not be empty."); - static_assert(!detail::disjunction...>::value, "Variant can not hold reference types. Maybe use std::reference_wrapper?"); - static_assert(!detail::disjunction...>::value, "Variant can not hold array types."); - static_assert(sizeof...(Types) < std::numeric_limits::max(), "Internal index type must be able to accommodate all alternatives."); -private: - static const std::size_t data_size = detail::static_max::value; - static const std::size_t data_align = detail::static_max::value; -public: - struct adapted_variant_tag; - using types = std::tuple; -private: - using first_type = typename std::tuple_element<0, types>::type; - using data_type = typename std::aligned_storage::type; - using helper_type = detail::variant_helper; - - type_index_t type_index; - data_type data; - -public: - VARIANT_INLINE variant() noexcept(std::is_nothrow_default_constructible::value) - : type_index(sizeof...(Types)-1) - { - static_assert(std::is_default_constructible::value, "First type in variant must be default constructible to allow default construction of variant."); - new (&data) first_type(); - } - - VARIANT_INLINE variant(no_init) noexcept - : type_index(detail::invalid_value) {} - - // http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers - template , - typename Enable = typename std::enable_if, typename Traits::value_type>::value>::type > - VARIANT_INLINE variant(T&& val) noexcept(std::is_nothrow_constructible::value) - : type_index(Traits::index) - { - new (&data) typename Traits::target_type(std::forward(val)); - } - - VARIANT_INLINE variant(variant const& old) - : type_index(old.type_index) - { - helper_type::copy(old.type_index, &old.data, &data); - } - - VARIANT_INLINE variant(variant&& old) - noexcept(detail::conjunction...>::value) - : type_index(old.type_index) - { - helper_type::move(old.type_index, &old.data, &data); - } - -private: - VARIANT_INLINE void copy_assign(variant const& rhs) - { - helper_type::destroy(type_index, &data); - type_index = detail::invalid_value; - helper_type::copy(rhs.type_index, &rhs.data, &data); - type_index = rhs.type_index; - } - - VARIANT_INLINE void move_assign(variant&& rhs) - { - helper_type::destroy(type_index, &data); - type_index = detail::invalid_value; - helper_type::move(rhs.type_index, &rhs.data, &data); - type_index = rhs.type_index; - } - -public: - VARIANT_INLINE variant& operator=(variant&& other) - { - move_assign(std::move(other)); - return *this; - } - - VARIANT_INLINE variant& operator=(variant const& other) - { - copy_assign(other); - return *this; - } - - // conversions - // move-assign - template - VARIANT_INLINE variant& operator=(T&& rhs) noexcept - { - variant temp(std::forward(rhs)); - move_assign(std::move(temp)); - return *this; - } - - // copy-assign - template - VARIANT_INLINE variant& operator=(T const& rhs) - { - variant temp(rhs); - copy_assign(temp); - return *this; - } - - template ::index != detail::invalid_value)>::type* = nullptr> - VARIANT_INLINE bool is() const - { - return type_index == detail::direct_type::index; - } - - template , Types...>::index != detail::invalid_value)>::type* = nullptr> - VARIANT_INLINE bool is() const - { - return type_index == detail::direct_type, Types...>::index; - } - - VARIANT_INLINE bool valid() const - { - return type_index != detail::invalid_value; - } - - template - VARIANT_INLINE void set(Args&&... args) - { - helper_type::destroy(type_index, &data); - type_index = detail::invalid_value; - new (&data) T(std::forward(args)...); - type_index = detail::direct_type::index; - } - - // get_unchecked() - template ::index != detail::invalid_value)>::type* = nullptr> - VARIANT_INLINE T& get_unchecked() - { - return *reinterpret_cast(&data); - } - -#ifdef HAS_EXCEPTIONS - // get() - template ::index != detail::invalid_value)>::type* = nullptr> - VARIANT_INLINE T& get() - { - if (type_index == detail::direct_type::index) - { - return *reinterpret_cast(&data); - } - else - { - throw bad_variant_access("in get()"); - } - } -#endif - - template ::index != detail::invalid_value)>::type* = nullptr> - VARIANT_INLINE T const& get_unchecked() const - { - return *reinterpret_cast(&data); - } - -#ifdef HAS_EXCEPTIONS - template ::index != detail::invalid_value)>::type* = nullptr> - VARIANT_INLINE T const& get() const - { - if (type_index == detail::direct_type::index) - { - return *reinterpret_cast(&data); - } - else - { - throw bad_variant_access("in get()"); - } - } -#endif - - // get_unchecked() - T stored as recursive_wrapper - template , Types...>::index != detail::invalid_value)>::type* = nullptr> - VARIANT_INLINE T& get_unchecked() - { - return (*reinterpret_cast*>(&data)).get(); - } - -#ifdef HAS_EXCEPTIONS - // get() - T stored as recursive_wrapper - template , Types...>::index != detail::invalid_value)>::type* = nullptr> - VARIANT_INLINE T& get() - { - if (type_index == detail::direct_type, Types...>::index) - { - return (*reinterpret_cast*>(&data)).get(); - } - else - { - throw bad_variant_access("in get()"); - } - } -#endif - - template , Types...>::index != detail::invalid_value)>::type* = nullptr> - VARIANT_INLINE T const& get_unchecked() const - { - return (*reinterpret_cast const*>(&data)).get(); - } - -#ifdef HAS_EXCEPTIONS - template , Types...>::index != detail::invalid_value)>::type* = nullptr> - VARIANT_INLINE T const& get() const - { - if (type_index == detail::direct_type, Types...>::index) - { - return (*reinterpret_cast const*>(&data)).get(); - } - else - { - throw bad_variant_access("in get()"); - } - } -#endif - - // get_unchecked() - T stored as std::reference_wrapper - template , Types...>::index != detail::invalid_value)>::type* = nullptr> - VARIANT_INLINE T& get_unchecked() - { - return (*reinterpret_cast*>(&data)).get(); - } - -#ifdef HAS_EXCEPTIONS - // get() - T stored as std::reference_wrapper - template , Types...>::index != detail::invalid_value)>::type* = nullptr> - VARIANT_INLINE T& get() - { - if (type_index == detail::direct_type, Types...>::index) - { - return (*reinterpret_cast*>(&data)).get(); - } - else - { - throw bad_variant_access("in get()"); - } - } -#endif - - template , Types...>::index != detail::invalid_value)>::type* = nullptr> - VARIANT_INLINE T const& get_unchecked() const - { - return (*reinterpret_cast const*>(&data)).get(); - } - -#ifdef HAS_EXCEPTIONS - template , Types...>::index != detail::invalid_value)>::type* = nullptr> - VARIANT_INLINE T const& get() const - { - if (type_index == detail::direct_type, Types...>::index) - { - return (*reinterpret_cast const*>(&data)).get(); - } - else - { - throw bad_variant_access("in get()"); - } - } -#endif - - // This function is deprecated because it returns an internal index field. - // Use which() instead. - MAPBOX_VARIANT_DEPRECATED VARIANT_INLINE type_index_t get_type_index() const - { - return type_index; - } - - VARIANT_INLINE int which() const noexcept - { - return static_cast(sizeof...(Types)-type_index - 1); - } - - template ::index != detail::invalid_value)>::type* = nullptr> - VARIANT_INLINE static constexpr int which() noexcept - { - return static_cast(sizeof...(Types)-detail::direct_type::index - 1); - } - - // visitor - // unary - template ::type> - auto VARIANT_INLINE static visit(V const& v, F&& f) - -> decltype(detail::dispatcher::apply_const(v, std::forward(f))) - { - return detail::dispatcher::apply_const(v, std::forward(f)); - } - // non-const - template ::type> - auto VARIANT_INLINE static visit(V& v, F&& f) - -> decltype(detail::dispatcher::apply(v, std::forward(f))) - { - return detail::dispatcher::apply(v, std::forward(f)); - } - - // binary - // const - template ::type> - auto VARIANT_INLINE static binary_visit(V const& v0, V const& v1, F&& f) - -> decltype(detail::binary_dispatcher::apply_const(v0, v1, std::forward(f))) - { - return detail::binary_dispatcher::apply_const(v0, v1, std::forward(f)); - } - // non-const - template ::type> - auto VARIANT_INLINE static binary_visit(V& v0, V& v1, F&& f) - -> decltype(detail::binary_dispatcher::apply(v0, v1, std::forward(f))) - { - return detail::binary_dispatcher::apply(v0, v1, std::forward(f)); - } - - // match - // unary - template - auto VARIANT_INLINE match(Fs&&... fs) const - -> decltype(variant::visit(*this, ::mapbox::util::make_visitor(std::forward(fs)...))) - { - return variant::visit(*this, ::mapbox::util::make_visitor(std::forward(fs)...)); - } - // non-const - template - auto VARIANT_INLINE match(Fs&&... fs) - -> decltype(variant::visit(*this, ::mapbox::util::make_visitor(std::forward(fs)...))) - { - return variant::visit(*this, ::mapbox::util::make_visitor(std::forward(fs)...)); - } - - ~variant() noexcept // no-throw destructor - { - helper_type::destroy(type_index, &data); - } - - // comparison operators - // equality - VARIANT_INLINE bool operator==(variant const& rhs) const - { - assert(valid() && rhs.valid()); - if (this->which() != rhs.which()) - { - return false; - } - detail::comparer visitor(*this); - return visit(rhs, visitor); - } - - VARIANT_INLINE bool operator!=(variant const& rhs) const - { - return !(*this == rhs); - } - - // less than - VARIANT_INLINE bool operator<(variant const& rhs) const - { - assert(valid() && rhs.valid()); - if (this->which() != rhs.which()) - { - return this->which() < rhs.which(); - } - detail::comparer visitor(*this); - return visit(rhs, visitor); - } - VARIANT_INLINE bool operator>(variant const& rhs) const - { - return rhs < *this; - } - VARIANT_INLINE bool operator<=(variant const& rhs) const - { - return !(*this > rhs); - } - VARIANT_INLINE bool operator>=(variant const& rhs) const - { - return !(*this < rhs); - } -}; - -// unary visitor interface -// const -template -auto VARIANT_INLINE apply_visitor(F&& f, V const& v) -> decltype(V::visit(v, std::forward(f))) -{ - return V::visit(v, std::forward(f)); -} - -// non-const -template -auto VARIANT_INLINE apply_visitor(F&& f, V& v) -> decltype(V::visit(v, std::forward(f))) -{ - return V::visit(v, std::forward(f)); -} - -// binary visitor interface -// const -template -auto VARIANT_INLINE apply_visitor(F&& f, V const& v0, V const& v1) -> decltype(V::binary_visit(v0, v1, std::forward(f))) -{ - return V::binary_visit(v0, v1, std::forward(f)); -} - -// non-const -template -auto VARIANT_INLINE apply_visitor(F&& f, V& v0, V& v1) -> decltype(V::binary_visit(v0, v1, std::forward(f))) -{ - return V::binary_visit(v0, v1, std::forward(f)); -} - -// getter interface - -#ifdef HAS_EXCEPTIONS -template -auto get(T& var)->decltype(var.template get()) -{ - return var.template get(); -} -#endif - -template -ResultType& get_unchecked(T& var) -{ - return var.template get_unchecked(); -} - -#ifdef HAS_EXCEPTIONS -template -auto get(T const& var)->decltype(var.template get()) -{ - return var.template get(); -} -#endif - -template -ResultType const& get_unchecked(T const& var) -{ - return var.template get_unchecked(); -} -} // namespace util -} // namespace mapbox - -// hashable iff underlying types are hashable -namespace std { -template -struct hash< ::mapbox::util::variant> { - std::size_t operator()(const ::mapbox::util::variant& v) const noexcept - { - return ::mapbox::util::apply_visitor(::mapbox::util::detail::hasher{}, v); - } -}; -} - -#endif // MAPBOX_UTIL_VARIANT_HPP diff --git a/src/mapbox/variant_visitor.hpp b/src/mapbox/variant_visitor.hpp deleted file mode 100644 index 54ddba0..0000000 --- a/src/mapbox/variant_visitor.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef MAPBOX_UTIL_VARIANT_VISITOR_HPP -#define MAPBOX_UTIL_VARIANT_VISITOR_HPP - -#include - -namespace mapbox { -namespace util { - -template -struct visitor; - -template -struct visitor : Fn -{ - using Fn::operator(); - - template - visitor(T&& fn) : Fn(std::forward(fn)) {} -}; - -template -struct visitor : Fn, visitor -{ - using Fn::operator(); - using visitor::operator(); - - template - visitor(T&& fn, Ts&&... fns) - : Fn(std::forward(fn)) - , visitor(std::forward(fns)...) {} -}; - -template -visitor::type...> make_visitor(Fns&&... fns) -{ - return visitor::type...> - (std::forward(fns)...); -} - -} // namespace util -} // namespace mapbox - -#endif // MAPBOX_UTIL_VARIANT_VISITOR_HPP diff --git a/src/normaliser.hpp b/src/normaliser.hpp index aa38c86..e5de217 100644 --- a/src/normaliser.hpp +++ b/src/normaliser.hpp @@ -32,8 +32,6 @@ // hfst: # include # include -// variants: -# include "mapbox/variant.hpp" namespace divvun { diff --git a/src/phon.hpp b/src/phon.hpp index 4c035f8..d9e2c20 100644 --- a/src/phon.hpp +++ b/src/phon.hpp @@ -33,8 +33,6 @@ // hfst: #include #include -// variants: -#include "mapbox/variant.hpp" namespace divvun { diff --git a/src/pipespec.hpp b/src/pipespec.hpp index bd3013a..ebfdb82 100644 --- a/src/pipespec.hpp +++ b/src/pipespec.hpp @@ -51,11 +51,8 @@ #include #endif // HAVE_LIBARCHIVE -#include "mapbox/variant.hpp" - namespace divvun { -//using mapbox::util::variant; using std::string; using std::stringstream; using std::u16string; diff --git a/src/suggest.cpp b/src/suggest.cpp index 513b462..a997270 100644 --- a/src/suggest.cpp +++ b/src/suggest.cpp @@ -738,14 +738,15 @@ variant Suggest::cohort_errs(const ErrId& err_id, size_t i_c, // If there are LEFT/RIGHT added relations, add suggestions with those concatenated to our form // TODO: What about our current suggestions of the same error tag? Currently just using wordform const auto squiggle = squiggle_bounds(r.rels, sentence, i_c, c); - build_squiggle_replacement(r, err_id, i_c, c, sentence, beg, end, squiggle.first, squiggle.second, verbose) - .match( - [ ](Nothing) {}, - [&](pair, UStringVector> p) { - beg = p.first.first; - end = p.first.second; - rep.insert(rep.end(), p.second.begin(), p.second.end()); - }); + std::visit([&](auto&& arg) { + using T = std::decay_t; + if constexpr (std::is_same_v) {} + if constexpr (std::is_same_v, UStringVector>>) { + beg = arg.first.first; + end = arg.first.second; + rep.insert(rep.end(), arg.second.begin(), arg.second.end()); + } + }, build_squiggle_replacement(r, err_id, i_c, c, sentence, beg, end, squiggle.first, squiggle.second, verbose)); } // Avoid unchanging replacements: auto form = text.substr(beg, end - beg); @@ -1030,11 +1031,15 @@ void Suggest::mk_errs(Sentence& sentence) { if (errtype.empty()) { continue; } - cohort_errs(errtype, i_c, c, sentence, text) - .match([](Nothing) {}, [&](Err err) { - c.errs.push_back(err); - sentence.errs.push_back(err); - }); + + std::visit([&](auto&& arg) { + using T = std::decay_t; + if constexpr (std::is_same_v) {} + if constexpr (std::is_same_v) { + c.errs.push_back(arg); + sentence.errs.push_back(arg); + } + }, cohort_errs(errtype, i_c, c, sentence, text)); } } // Postprocessing for overlapping errors: diff --git a/src/suggest.hpp b/src/suggest.hpp index e482af4..e9778c4 100644 --- a/src/suggest.hpp +++ b/src/suggest.hpp @@ -26,6 +26,7 @@ # include # include # include +# include // divvun-gramcheck: # include "util.hpp" @@ -40,11 +41,11 @@ # include # include // variants: -# include "mapbox/variant.hpp" +# include namespace divvun { -using mapbox::util::variant; +using std::variant; using std::pair; using std::string; using std::stringstream; diff --git a/src/utf8.h b/src/utf8.h deleted file mode 100644 index 82b13f5..0000000 --- a/src/utf8.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2006 Nemanja Trifunovic - -/* -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - - -#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 -#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 - -#include "utf8/checked.h" -#include "utf8/unchecked.h" - -#endif // header guard diff --git a/src/utf8/checked.h b/src/utf8/checked.h deleted file mode 100644 index 2aef583..0000000 --- a/src/utf8/checked.h +++ /dev/null @@ -1,327 +0,0 @@ -// Copyright 2006-2016 Nemanja Trifunovic - -/* -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - - -#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 -#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 - -#include "core.h" -#include - -namespace utf8 -{ - // Base for the exceptions that may be thrown from the library - class exception : public ::std::exception { - }; - - // Exceptions that may be thrown from the library functions. - class invalid_code_point : public exception { - uint32_t cp; - public: - invalid_code_point(uint32_t codepoint) : cp(codepoint) {} - virtual const char* what() const throw() { return "Invalid code point"; } - uint32_t code_point() const {return cp;} - }; - - class invalid_utf8 : public exception { - uint8_t u8; - public: - invalid_utf8 (uint8_t u) : u8(u) {} - virtual const char* what() const throw() { return "Invalid UTF-8"; } - uint8_t utf8_octet() const {return u8;} - }; - - class invalid_utf16 : public exception { - uint16_t u16; - public: - invalid_utf16 (uint16_t u) : u16(u) {} - virtual const char* what() const throw() { return "Invalid UTF-16"; } - uint16_t utf16_word() const {return u16;} - }; - - class not_enough_room : public exception { - public: - virtual const char* what() const throw() { return "Not enough space"; } - }; - - /// The library API - functions intended to be called by the users - - template - octet_iterator append(uint32_t cp, octet_iterator result) - { - if (!utf8::internal::is_code_point_valid(cp)) - throw invalid_code_point(cp); - - if (cp < 0x80) // one octet - *(result++) = static_cast(cp); - else if (cp < 0x800) { // two octets - *(result++) = static_cast((cp >> 6) | 0xc0); - *(result++) = static_cast((cp & 0x3f) | 0x80); - } - else if (cp < 0x10000) { // three octets - *(result++) = static_cast((cp >> 12) | 0xe0); - *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); - *(result++) = static_cast((cp & 0x3f) | 0x80); - } - else { // four octets - *(result++) = static_cast((cp >> 18) | 0xf0); - *(result++) = static_cast(((cp >> 12) & 0x3f) | 0x80); - *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); - *(result++) = static_cast((cp & 0x3f) | 0x80); - } - return result; - } - - template - output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement) - { - while (start != end) { - octet_iterator sequence_start = start; - internal::utf_error err_code = utf8::internal::validate_next(start, end); - switch (err_code) { - case internal::UTF8_OK : - for (octet_iterator it = sequence_start; it != start; ++it) - *out++ = *it; - break; - case internal::NOT_ENOUGH_ROOM: - throw not_enough_room(); - case internal::INVALID_LEAD: - out = utf8::append (replacement, out); - ++start; - break; - case internal::INCOMPLETE_SEQUENCE: - case internal::OVERLONG_SEQUENCE: - case internal::INVALID_CODE_POINT: - out = utf8::append (replacement, out); - ++start; - // just one replacement mark for the sequence - while (start != end && utf8::internal::is_trail(*start)) - ++start; - break; - } - } - return out; - } - - template - inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out) - { - static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd); - return utf8::replace_invalid(start, end, out, replacement_marker); - } - - template - uint32_t next(octet_iterator& it, octet_iterator end) - { - uint32_t cp = 0; - internal::utf_error err_code = utf8::internal::validate_next(it, end, cp); - switch (err_code) { - case internal::UTF8_OK : - break; - case internal::NOT_ENOUGH_ROOM : - throw not_enough_room(); - case internal::INVALID_LEAD : - case internal::INCOMPLETE_SEQUENCE : - case internal::OVERLONG_SEQUENCE : - throw invalid_utf8(*it); - case internal::INVALID_CODE_POINT : - throw invalid_code_point(cp); - } - return cp; - } - - template - uint32_t peek_next(octet_iterator it, octet_iterator end) - { - return utf8::next(it, end); - } - - template - uint32_t prior(octet_iterator& it, octet_iterator start) - { - // can't do much if it == start - if (it == start) - throw not_enough_room(); - - octet_iterator end = it; - // Go back until we hit either a lead octet or start - while (utf8::internal::is_trail(*(--it))) - if (it == start) - throw invalid_utf8(*it); // error - no lead byte in the sequence - return utf8::peek_next(it, end); - } - - /// Deprecated in versions that include "prior" - template - uint32_t previous(octet_iterator& it, octet_iterator pass_start) - { - octet_iterator end = it; - while (utf8::internal::is_trail(*(--it))) - if (it == pass_start) - throw invalid_utf8(*it); // error - no lead byte in the sequence - octet_iterator temp = it; - return utf8::next(temp, end); - } - - template - void advance (octet_iterator& it, distance_type n, octet_iterator end) - { - for (distance_type i = 0; i < n; ++i) - utf8::next(it, end); - } - - template - typename std::iterator_traits::difference_type - distance (octet_iterator first, octet_iterator last) - { - typename std::iterator_traits::difference_type dist; - for (dist = 0; first < last; ++dist) - utf8::next(first, last); - return dist; - } - - template - octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) - { - while (start != end) { - uint32_t cp = utf8::internal::mask16(*start++); - // Take care of surrogate pairs first - if (utf8::internal::is_lead_surrogate(cp)) { - if (start != end) { - uint32_t trail_surrogate = utf8::internal::mask16(*start++); - if (utf8::internal::is_trail_surrogate(trail_surrogate)) - cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; - else - throw invalid_utf16(static_cast(trail_surrogate)); - } - else - throw invalid_utf16(static_cast(cp)); - - } - // Lone trail surrogate - else if (utf8::internal::is_trail_surrogate(cp)) - throw invalid_utf16(static_cast(cp)); - - result = utf8::append(cp, result); - } - return result; - } - - template - u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) - { - while (start < end) { - uint32_t cp = utf8::next(start, end); - if (cp > 0xffff) { //make a surrogate pair - *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET); - *result++ = static_cast((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); - } - else - *result++ = static_cast(cp); - } - return result; - } - - template - octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) - { - while (start != end) - result = utf8::append(*(start++), result); - - return result; - } - - template - u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) - { - while (start < end) - (*result++) = utf8::next(start, end); - - return result; - } - - // The iterator class - template - class iterator : public std::iterator { - octet_iterator it; - octet_iterator range_start; - octet_iterator range_end; - public: - iterator () {} - explicit iterator (const octet_iterator& octet_it, - const octet_iterator& rangestart, - const octet_iterator& rangeend) : - it(octet_it), range_start(rangestart), range_end(rangeend) - { - if (it < range_start || it > range_end) - throw std::out_of_range("Invalid utf-8 iterator position"); - } - // the default "big three" are OK - octet_iterator base () const { return it; } - uint32_t operator * () const - { - octet_iterator temp = it; - return utf8::next(temp, range_end); - } - bool operator == (const iterator& rhs) const - { - if (range_start != rhs.range_start || range_end != rhs.range_end) - throw std::logic_error("Comparing utf-8 iterators defined with different ranges"); - return (it == rhs.it); - } - bool operator != (const iterator& rhs) const - { - return !(operator == (rhs)); - } - iterator& operator ++ () - { - utf8::next(it, range_end); - return *this; - } - iterator operator ++ (int) - { - iterator temp = *this; - utf8::next(it, range_end); - return temp; - } - iterator& operator -- () - { - utf8::prior(it, range_start); - return *this; - } - iterator operator -- (int) - { - iterator temp = *this; - utf8::prior(it, range_start); - return temp; - } - }; // class iterator - -} // namespace utf8 - -#endif //header guard - - diff --git a/src/utf8/core.h b/src/utf8/core.h deleted file mode 100644 index ae0f367..0000000 --- a/src/utf8/core.h +++ /dev/null @@ -1,332 +0,0 @@ -// Copyright 2006 Nemanja Trifunovic - -/* -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - - -#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 -#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 - -#include - -namespace utf8 -{ - // The typedefs for 8-bit, 16-bit and 32-bit unsigned integers - // You may need to change them to match your system. - // These typedefs have the same names as ones from cstdint, or boost/cstdint - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; - -// Helper code - not intended to be directly called by the library users. May be changed at any time -namespace internal -{ - // Unicode constants - // Leading (high) surrogates: 0xd800 - 0xdbff - // Trailing (low) surrogates: 0xdc00 - 0xdfff - const uint16_t LEAD_SURROGATE_MIN = 0xd800u; - const uint16_t LEAD_SURROGATE_MAX = 0xdbffu; - const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u; - const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu; - const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10); - const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN; - - // Maximum valid value for a Unicode code point - const uint32_t CODE_POINT_MAX = 0x0010ffffu; - - template - inline uint8_t mask8(octet_type oc) - { - return static_cast(0xff & oc); - } - template - inline uint16_t mask16(u16_type oc) - { - return static_cast(0xffff & oc); - } - template - inline bool is_trail(octet_type oc) - { - return ((utf8::internal::mask8(oc) >> 6) == 0x2); - } - - template - inline bool is_lead_surrogate(u16 cp) - { - return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX); - } - - template - inline bool is_trail_surrogate(u16 cp) - { - return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); - } - - template - inline bool is_surrogate(u16 cp) - { - return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); - } - - template - inline bool is_code_point_valid(u32 cp) - { - return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp)); - } - - template - inline typename std::iterator_traits::difference_type - sequence_length(octet_iterator lead_it) - { - uint8_t lead = utf8::internal::mask8(*lead_it); - if (lead < 0x80) - return 1; - else if ((lead >> 5) == 0x6) - return 2; - else if ((lead >> 4) == 0xe) - return 3; - else if ((lead >> 3) == 0x1e) - return 4; - else - return 0; - } - - template - inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length) - { - if (cp < 0x80) { - if (length != 1) - return true; - } - else if (cp < 0x800) { - if (length != 2) - return true; - } - else if (cp < 0x10000) { - if (length != 3) - return true; - } - - return false; - } - - enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT}; - - /// Helper for get_sequence_x - template - utf_error increase_safely(octet_iterator& it, octet_iterator end) - { - if (++it == end) - return NOT_ENOUGH_ROOM; - - if (!utf8::internal::is_trail(*it)) - return INCOMPLETE_SEQUENCE; - - return UTF8_OK; - } - - #define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;} - - /// get_sequence_x functions decode utf-8 sequences of the length x - template - utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point) - { - if (it == end) - return NOT_ENOUGH_ROOM; - - code_point = utf8::internal::mask8(*it); - - return UTF8_OK; - } - - template - utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point) - { - if (it == end) - return NOT_ENOUGH_ROOM; - - code_point = utf8::internal::mask8(*it); - - UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - - code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f); - - return UTF8_OK; - } - - template - utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point) - { - if (it == end) - return NOT_ENOUGH_ROOM; - - code_point = utf8::internal::mask8(*it); - - UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - - code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); - - UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - - code_point += (*it) & 0x3f; - - return UTF8_OK; - } - - template - utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point) - { - if (it == end) - return NOT_ENOUGH_ROOM; - - code_point = utf8::internal::mask8(*it); - - UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - - code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); - - UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - - code_point += (utf8::internal::mask8(*it) << 6) & 0xfff; - - UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - - code_point += (*it) & 0x3f; - - return UTF8_OK; - } - - #undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR - - template - utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point) - { - if (it == end) - return NOT_ENOUGH_ROOM; - - // Save the original value of it so we can go back in case of failure - // Of course, it does not make much sense with i.e. stream iterators - octet_iterator original_it = it; - - uint32_t cp = 0; - // Determine the sequence length based on the lead octet - typedef typename std::iterator_traits::difference_type octet_difference_type; - const octet_difference_type length = utf8::internal::sequence_length(it); - - // Get trail octets and calculate the code point - utf_error err = UTF8_OK; - switch (length) { - case 0: - return INVALID_LEAD; - case 1: - err = utf8::internal::get_sequence_1(it, end, cp); - break; - case 2: - err = utf8::internal::get_sequence_2(it, end, cp); - break; - case 3: - err = utf8::internal::get_sequence_3(it, end, cp); - break; - case 4: - err = utf8::internal::get_sequence_4(it, end, cp); - break; - } - - if (err == UTF8_OK) { - // Decoding succeeded. Now, security checks... - if (utf8::internal::is_code_point_valid(cp)) { - if (!utf8::internal::is_overlong_sequence(cp, length)){ - // Passed! Return here. - code_point = cp; - ++it; - return UTF8_OK; - } - else - err = OVERLONG_SEQUENCE; - } - else - err = INVALID_CODE_POINT; - } - - // Failure branch - restore the original value of the iterator - it = original_it; - return err; - } - - template - inline utf_error validate_next(octet_iterator& it, octet_iterator end) { - uint32_t ignored; - return utf8::internal::validate_next(it, end, ignored); - } - -} // namespace internal - - /// The library API - functions intended to be called by the users - - // Byte order mark - const uint8_t bom[] = {0xef, 0xbb, 0xbf}; - - template - octet_iterator find_invalid(octet_iterator start, octet_iterator end) - { - octet_iterator result = start; - while (result != end) { - utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end); - if (err_code != internal::UTF8_OK) - return result; - } - return result; - } - - template - inline bool is_valid(octet_iterator start, octet_iterator end) - { - return (utf8::find_invalid(start, end) == end); - } - - template - inline bool starts_with_bom (octet_iterator it, octet_iterator end) - { - return ( - ((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) && - ((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) && - ((it != end) && (utf8::internal::mask8(*it)) == bom[2]) - ); - } - - //Deprecated in release 2.3 - template - inline bool is_bom (octet_iterator it) - { - return ( - (utf8::internal::mask8(*it++)) == bom[0] && - (utf8::internal::mask8(*it++)) == bom[1] && - (utf8::internal::mask8(*it)) == bom[2] - ); - } -} // namespace utf8 - -#endif // header guard - - diff --git a/src/utf8/unchecked.h b/src/utf8/unchecked.h deleted file mode 100644 index cb24271..0000000 --- a/src/utf8/unchecked.h +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright 2006 Nemanja Trifunovic - -/* -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - - -#ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 -#define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 - -#include "core.h" - -namespace utf8 -{ - namespace unchecked - { - template - octet_iterator append(uint32_t cp, octet_iterator result) - { - if (cp < 0x80) // one octet - *(result++) = static_cast(cp); - else if (cp < 0x800) { // two octets - *(result++) = static_cast((cp >> 6) | 0xc0); - *(result++) = static_cast((cp & 0x3f) | 0x80); - } - else if (cp < 0x10000) { // three octets - *(result++) = static_cast((cp >> 12) | 0xe0); - *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); - *(result++) = static_cast((cp & 0x3f) | 0x80); - } - else { // four octets - *(result++) = static_cast((cp >> 18) | 0xf0); - *(result++) = static_cast(((cp >> 12) & 0x3f)| 0x80); - *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); - *(result++) = static_cast((cp & 0x3f) | 0x80); - } - return result; - } - - template - uint32_t next(octet_iterator& it) - { - uint32_t cp = utf8::internal::mask8(*it); - typename std::iterator_traits::difference_type length = utf8::internal::sequence_length(it); - switch (length) { - case 1: - break; - case 2: - it++; - cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f); - break; - case 3: - ++it; - cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); - ++it; - cp += (*it) & 0x3f; - break; - case 4: - ++it; - cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); - ++it; - cp += (utf8::internal::mask8(*it) << 6) & 0xfff; - ++it; - cp += (*it) & 0x3f; - break; - } - ++it; - return cp; - } - - template - uint32_t peek_next(octet_iterator it) - { - return utf8::unchecked::next(it); - } - - template - uint32_t prior(octet_iterator& it) - { - while (utf8::internal::is_trail(*(--it))) ; - octet_iterator temp = it; - return utf8::unchecked::next(temp); - } - - // Deprecated in versions that include prior, but only for the sake of consistency (see utf8::previous) - template - inline uint32_t previous(octet_iterator& it) - { - return utf8::unchecked::prior(it); - } - - template - void advance (octet_iterator& it, distance_type n) - { - for (distance_type i = 0; i < n; ++i) - utf8::unchecked::next(it); - } - - template - typename std::iterator_traits::difference_type - distance (octet_iterator first, octet_iterator last) - { - typename std::iterator_traits::difference_type dist; - for (dist = 0; first < last; ++dist) - utf8::unchecked::next(first); - return dist; - } - - template - octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) - { - while (start != end) { - uint32_t cp = utf8::internal::mask16(*start++); - // Take care of surrogate pairs first - if (utf8::internal::is_lead_surrogate(cp)) { - uint32_t trail_surrogate = utf8::internal::mask16(*start++); - cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; - } - result = utf8::unchecked::append(cp, result); - } - return result; - } - - template - u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) - { - while (start < end) { - uint32_t cp = utf8::unchecked::next(start); - if (cp > 0xffff) { //make a surrogate pair - *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET); - *result++ = static_cast((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); - } - else - *result++ = static_cast(cp); - } - return result; - } - - template - octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) - { - while (start != end) - result = utf8::unchecked::append(*(start++), result); - - return result; - } - - template - u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) - { - while (start < end) - (*result++) = utf8::unchecked::next(start); - - return result; - } - - // The iterator class - template - class iterator : public std::iterator { - octet_iterator it; - public: - iterator () {} - explicit iterator (const octet_iterator& octet_it): it(octet_it) {} - // the default "big three" are OK - octet_iterator base () const { return it; } - uint32_t operator * () const - { - octet_iterator temp = it; - return utf8::unchecked::next(temp); - } - bool operator == (const iterator& rhs) const - { - return (it == rhs.it); - } - bool operator != (const iterator& rhs) const - { - return !(operator == (rhs)); - } - iterator& operator ++ () - { - ::std::advance(it, utf8::internal::sequence_length(it)); - return *this; - } - iterator operator ++ (int) - { - iterator temp = *this; - ::std::advance(it, utf8::internal::sequence_length(it)); - return temp; - } - iterator& operator -- () - { - utf8::unchecked::prior(it); - return *this; - } - iterator operator -- (int) - { - iterator temp = *this; - utf8::unchecked::prior(it); - return temp; - } - }; // class iterator - - } // namespace utf8::unchecked -} // namespace utf8 - - -#endif // header guard - diff --git a/src/util.hpp b/src/util.hpp index f21952f..c377668 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -32,10 +32,11 @@ #include #include #include +#include #include #include -#include "utf8.h" +#include namespace divvun {