Last active
July 2, 2021 04:22
-
-
Save ThePhD/80764f840be25ae05a0c8953a210f0f5 to your computer and use it in GitHub Desktop.
The single-header include of ztd.text.
This file has been truncated, but you can view the full file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ============================================================================= | |
// | |
// ztd.text | |
// Copyright © 2021 JeanHeyd "ThePhD" Meneide and Shepherd's Oasis, LLC | |
// Contact: opensource@soasis.org | |
// | |
// Commercial License Usage | |
// Licensees holding valid commercial ztd.text licenses may use this file in | |
// accordance with the commercial license agreement provided with the | |
// Software or, alternatively, in accordance with the terms contained in | |
// a written agreement between you and Shepherd's Oasis, LLC. | |
// For licensing terms and conditions see your agreement. For | |
// further information contact opensource@soasis.org. | |
// | |
// Apache License Version 2 Usage | |
// Alternatively, this file may be used under the terms of Apache License | |
// Version 2.0 (the "License") for non-commercial use; you may not use this | |
// file except in compliance with the License. You may obtain a copy of the | |
// License at | |
// | |
// http://www.apache.org/licenses/LICENSE-2.0 | |
// | |
// Unless required by applicable law or agreed to in writing, software | |
// distributed under the License is distributed on an "AS IS" BASIS, | |
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
// See the License for the specific language governing permissions and | |
// limitations under the License. | |
// | |
// ============================================================================> | |
/* This is an automatically generated header file. | |
* Generated from the ztd.text repository at 2021-07-02 04:21:09.346004, | |
* Version v0.0.1 (Revision 7610526). | |
*/ | |
#ifndef ZTD_TEXT_SINGLE_INCLUDE_HPP | |
#define ZTD_TEXT_SINGLE_INCLUDE_HPP | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text.hpp | |
#ifndef ZTD_TEXT_HPP | |
#define ZTD_TEXT_HPP | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/version.hpp | |
#include <cstddef> | |
#include <cstdint> | |
#include <climits> | |
#include <type_traits> | |
#define ZTD_TEXT_VERSION_MAJOR 0 | |
#define ZTD_TEXT_VERSION_MINOR 0 | |
#define ZTD_TEXT_VERSION_PATCH 0 | |
#define ZTD_TEXT_VERSION_STRING "0.0.0" | |
#define ZTD_TEXT_VERSION \ | |
((ZTD_TEXT_VERSION_MAJOR * 100'000) + (ZTD_TEXT_VERSION_MINOR * 100) + (ZTD_TEXT_VERSION_PATCH)) | |
#define ZTD_TEXT_IS_ON(OP_SYMBOL) ((3 OP_SYMBOL 3) != 0) | |
#define ZTD_TEXT_IS_OFF(OP_SYMBOL) ((3 OP_SYMBOL 3) == 0) | |
#define ZTD_TEXT_IS_DEFAULT_ON(OP_SYMBOL) ((3 OP_SYMBOL 3) > 3) | |
#define ZTD_TEXT_IS_DEFAULT_OFF(OP_SYMBOL) ((3 OP_SYMBOL 3 OP_SYMBOL 3) < 0) | |
#define ZTD_TEXT_ON | | |
#define ZTD_TEXT_OFF ^ | |
#define ZTD_TEXT_DEFAULT_ON + | |
#define ZTD_TEXT_DEFAULT_OFF - | |
#if defined(__has_include) | |
#define ZTD_TEXT_COMPILER_WITH_HAS_INCLUDE_I_ ZTD_TEXT_ON | |
#define ZTD_TEXT_HAS_INCLUDE_I_(...) __has_include(__VA_ARGS__) | |
#else | |
#define ZTD_TEXT_COMPILER_WITH_HAS_INCLUDE_I_ ZTD_TEXT_OFF | |
#define ZTD_TEXT_HAS_INCLUDE_I_(...) 0 | |
#endif | |
#define ZTD_TEXT_TOKEN_TO_STRING_POST_EXPANSION_I_(__TOK) #__TOK | |
#define ZTD_TEXT_TOKEN_TO_STRING_I_(__TOK) ZTD_TEXT_TOKEN_TO_STRING_POST_EXPANSION_I_(__TOK) | |
#if ZTD_TEXT_HAS_INCLUDE_I_(<version>) | |
// Can check __has_include and we have the C++20 <version> header | |
#include <version> | |
#endif | |
#if defined(__clang__) | |
#define ZTD_TEXT_COMPILER_CLANG_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_COMPILER_CLANG_I_ ZTD_TEXT_OFF | |
#endif | |
#if defined(__GNUC__) | |
#define ZTD_TEXT_COMPILER_GCC_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_COMPILER_GCC_I_ ZTD_TEXT_OFF | |
#endif | |
#if defined (_MSC_VER) | |
#define ZTD_TEXT_COMPILER_VCXX_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_COMPILER_VCXX_I_ ZTD_TEXT_OFF | |
#endif | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_COMPILER_VCXX_I_) && ZTD_TEXT_IS_ON(ZTD_TEXT_COMPILER_CLANG_I_) | |
#define ZTD_TEXT_COMPILER_VCXX_CLANG_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_COMPILER_VCXX_CLANG_I_ ZTD_TEXT_OFF | |
#endif | |
#if defined(__MINGW32__) | |
#define ZTD_TEXT_COMPILER_MINGW_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_COMPILER_MINGW_I_ ZTD_TEXT_OFF | |
#endif | |
#if defined(__GLIBCXX__) | |
#define ZTD_TEXT_LIBSTDCXX_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_LIBSTDCXX_I_ ZTD_TEXT_OFF | |
#endif | |
#if defined(_LIBCPP_VERSION) | |
#define ZTD_TEXT_LIBCXX_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_LIBCXX_I_ ZTD_TEXT_OFF | |
#endif | |
#if defined (_YVALS_CORE_H_) // Volatile definition; would be nice if VC++ exposed some documented macros... | |
#define ZTD_TEXT_LIBVCXX_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_LIBVCXX_I_ ZTD_TEXT_OFF | |
#endif | |
#if defined(_WIN32) | |
#define ZTD_TEXT_PLATFORM_WINDOWS_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_PLATFORM_WINDOWS_I_ ZTD_TEXT_OFF | |
#endif // Windows | |
#if defined(__CYGWIN__) | |
#define ZTD_TEXT_PLATFORM_CYGWIN_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_PLATFORM_CYGWIN_I_ ZTD_TEXT_OFF | |
#endif // Cygwin shenanigans | |
#if defined(__MVS__) | |
#define ZTD_TEXT_PLATFORM_ZEDOS_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_PLATFORM_ZEDOS_I_ ZTD_TEXT_OFF | |
#endif // IBM's Z/OS | |
#if defined(__STDC_HOSTED__) | |
#define ZTD_TEXT_PLATFORM_FREESTANDING_I_ ZTD_TEXT_OFF | |
#else | |
#define ZTD_TEXT_PLATFORM_FREESTANDING_I_ ZTD_TEXT_ON | |
#endif | |
#if defined(_AIX) | |
// We are on the AIX platform | |
#define ZTD_TEXT_PLATFORM_AIX_I_ ZTD_TEXT_ON | |
#else | |
// We are not on the AIX platform | |
#define ZTD_TEXT_PLATFORM_AIX_I_ ZTD_TEXT_OFF | |
#endif // IBM's AIX | |
#if defined(ZTD_TEXT_PLATFORM_UNKNOWN_CHECK) | |
#if (ZTD_TEXT_PLATFORM_UNKNOWN_CHECK != 0) | |
#define ZTD_TEXT_PLATFORM_UNKNOWN_CHECK_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_PLATFORM_UNKNOWN_CHECK_I_ ZTD_TEXT_OFF | |
#endif | |
#else | |
#define ZTD_TEXT_PLATFORM_UNKNOWN_CHECK_I_ ZTD_TEXT_OFF | |
#endif | |
#if defined(sun) || defined(__sun) | |
#if defined(__SVR4) || defined(__svr4__) | |
// Solaris | |
#define ZTD_TEXT_PLATFORM_SUNOS_I_ ZTD_TEXT_DEFAULT_OFF | |
#define ZTD_TEXT_PLATFORM_SOLARIS_I_ ZTD_TEXT_DEFAULT_ON | |
#else | |
// SunOS | |
#define ZTD_TEXT_PLATFORM_SUNOS_I_ ZTD_TEXT_DEFAULT_ON | |
#define ZTD_TEXT_PLATFORM_SOLARIS_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#else | |
#define ZTD_TEXT_PLATFORM_SUNOS_I_ ZTD_TEXT_DEFAULT_OFF | |
#define ZTD_TEXT_PLATFORM_SOLARIS_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif // SunOS and Solaris | |
#if defined(__unix) || defined(__unix__) | |
#define ZTD_TEXT_PLATFORM_UNIX_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_PLATFORM_UNIX_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif // UNIX platforms | |
#if defined(__linux) || defined(__linux__) || defined(linux) | |
#define ZTD_TEXT_PLATFORM_LINUX_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_PLATFORM_LINUX_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif // Linux platforms | |
#if defined(__STDC_ISO_10646__) && (__STDC_ISO_10646__ != 0) | |
#define ZTD_TEXT_WCHAR_T_UTF32_COMPATIBLE_I_ ZTD_TEXT_DEFAULT_ON | |
#else | |
#define ZTD_TEXT_WCHAR_T_UTF32_COMPATIBLE_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#if defined(ZTD_TEXT_CHAR8_T) | |
#define ZTD_TEXT_USE_USER_CHAR8_T_I_ ZTD_TEXT_ON | |
#define ZTD_TEXT_CHAR8_T_I_ ZTD_TEXT_CHAR8_T | |
#elif defined(__cpp_char8_t) | |
#define ZTD_TEXT_USE_USER_CHAR8_T_I_ ZTD_TEXT_DEFAULT_OFF | |
#define ZTD_TEXT_CHAR8_T_I_ char8_t | |
#else | |
#define ZTD_TEXT_USE_USER_CHAR8_T_I_ ZTD_TEXT_DEFAULT_OFF | |
#define ZTD_TEXT_CHAR8_T_I_ unsigned char | |
#endif // char8_t defined by the user | |
#if defined(__cpp_char8_t) | |
#define ZTD_TEXT_NATIVE_CHAR8_T_I_ ZTD_TEXT_DEFAULT_ON | |
#else | |
#define ZTD_TEXT_NATIVE_CHAR8_T_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif // char8_t exists natively (C++) - C proposal in WG14 still in progress | |
#if defined(ZTD_TEXT_BUILD) | |
#if (ZTD_TEXT_BUILD != 0) | |
#define ZTD_TEXT_BUILD_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_BUILD_I_ ZTD_TEXT_OFF | |
#endif | |
#else | |
#define ZTD_TEXT_BUILD_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif // Building or not | |
#if defined(ZTD_TEXT_DLL) && (ZTD_TEXT_DLL != 0) | |
#define ZTD_TEXT_DLL_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_DLL_I_ ZTD_TEXT_OFF | |
#endif // Building or not | |
#if defined(ZTD_TEXT_HEADER_ONLY) | |
#if (ZTD_TEXT_HEADER_ONLY != 0) | |
#define ZTD_TEXT_HEADER_ONLY_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_HEADER_ONLY_I_ ZTD_TEXT_OFF | |
#endif | |
#else | |
#define ZTD_TEXT_HEADER_ONLY_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif // Header only library | |
#if defined(ZTD_TEXT_INLINE_BUILD) | |
#if (ZTD_TEXT_INLINE_BUILD != 0) | |
#define ZTD_TEXT_INLINE_BUILD_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_INLINE_BUILD_I_ ZTD_TEXT_OFF | |
#endif | |
#else | |
#define ZTD_TEXT_INLINE_BUILD_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif // Header only library | |
#if !defined(ZTD_TEXT_FUNCTION_LINKAGE) | |
#if defined(__cplusplus) | |
// C++ | |
#define ZTD_TEXT_FUNCTION_LINKAGE_I_ extern "C" | |
#else | |
// normal | |
#define ZTD_TEXT_FUNCTION_LINKAGE_I_ | |
#endif // C++ or not | |
#else | |
#define ZTD_TEXT_FUNCTION_LINKAGE_I_ ZTD_TEXT_FUNCTION_LINKAGE | |
#endif // Linkage specification | |
#if defined(ZTD_TEXT_API_LINKAGE) | |
#define ZTD_TEXT_API_LINKAGE_I_ ZTD_TEXT_API_LINKAGE | |
#else | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_DLL_I_) | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_COMPILER_VCXX_I_) || ZTD_TEXT_IS_ON(ZTD_TEXT_PLATFORM_WINDOWS_I_) || ZTD_TEXT_IS_ON(ZTD_TEXT_PLATFORM_CYGWIN_I_) | |
// MSVC Compiler; or, Windows, or Cygwin platforms | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_BUILD_I_) | |
// Building the library | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_COMPILER_GCC_I_) | |
// Using GCC | |
#define ZTD_TEXT_API_LINKAGE_I_ __attribute__((dllexport)) | |
#else | |
// Using Clang, MSVC, etc... | |
#define ZTD_TEXT_API_LINKAGE_I_ __declspec(dllexport) | |
#endif | |
#else | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_PLATFORM_GCC_I_) | |
#define ZTD_TEXT_API_LINKAGE_I_ __attribute__((dllimport)) | |
#else | |
#define ZTD_TEXT_API_LINKAGE_I_ __declspec(dllimport) | |
#endif | |
#endif | |
#else | |
// extern if building normally on non-MSVC | |
#define ZTD_TEXT_API_LINKAGE_I_ extern | |
#endif | |
#elif ZTD_TEXT_IS_ON(ZTD_TEXT_INLINE_BUILD_I_) | |
// Built-in library, like how stb typical works | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_HEADER_ONLY_I_) | |
// Header only, so functions are defined "inline" | |
#define ZTD_TEXT_API_LINKAGE_I_ inline | |
#else | |
// Not header only, so seperately compiled files | |
#define ZTD_TEXT_API_LINKAGE_I_ extern | |
#endif | |
#else | |
// Normal static library | |
#if defined(__cplusplus) | |
#define ZTD_TEXT_API_LINKAGE_I_ | |
#else | |
#define ZTD_TEXT_API_LINKAGE_I_ extern | |
#endif | |
#endif // DLL or not | |
#endif // Build definitions | |
#if defined (ZTD_TEXT_ALIGNED_OPERATOR_NEW) | |
#if (ZTD_TEXT_ALIGNED_OPERATOR_NEW != 0) | |
#define ZTD_TEXT_ALIGNED_OPERATOR_NEW_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_ALIGNED_OPERATOR_NEW_I_ ZTD_TEXT_OFF | |
#endif | |
#elif defined(__cpp_aligned_new) | |
#define ZTD_TEXT_ALIGNED_OPERATOR_NEW_I_ ZTD_TEXT_DEFAULT_ON | |
#elif defined(__cplusplus) && __cplusplus > 201603L | |
#define ZTD_TEXT_ALIGNED_OPERATOR_NEW_I_ ZTD_TEXT_DEFAULT_ON | |
#else | |
#define ZTD_TEXT_ALIGNED_OPERATOR_NEW_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif // C++ operator new, with alignment parameter | |
#if defined(ZTD_TEXT_CONCEPTS) | |
#if (ZTD_TEXT_CONCEPTS != 0) | |
#define ZTD_TEXT_CONCEPTS_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_CONCEPTS_I_ ZTD_TEXT_OFF | |
#endif | |
#elif ZTD_TEXT_IS_ON(ZTD_TEXT_COMPILER_CLANG_I_) | |
// clang is busted right now! | |
// taking bets: Clang 14 is when it'll get fixed! | |
#if (__clang_major__ > 14) | |
#define ZTD_TEXT_CONCEPTS_I_ ZTD_TEXT_DEFAULT_ON | |
#else | |
#define ZTD_TEXT_CONCEPTS_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#elif defined(__cpp_concepts) && (__cpp_concepts >= 201907LL) | |
#define ZTD_TEXT_CONCEPTS_I_ ZTD_TEXT_DEFAULT_ON | |
#else | |
#define ZTD_TEXT_CONCEPTS_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#if defined(ZTD_TEXT_LANGINFO) | |
#if (ZTD_TEXT_LANGINFO != 0) | |
#define ZTD_TEXT_LANGINFO_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_LANGINFO_I_ ZTD_TEXT_OFF | |
#endif | |
#else | |
#if ZTD_TEXT_HAS_INCLUDE_I_(<langinfo.h>) | |
#define ZTD_TEXT_LANGINFO_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_LANGINFO_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#endif // langinfo POSIX | |
#if defined(ZTD_TEXT_NL_LANGINFO) | |
#if (ZTD_TEXT_NL_LANGINFO != 0) | |
#define ZTD_TEXT_NL_LANGINFO_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_NL_LANGINFO_I_ ZTD_TEXT_OFF | |
#endif | |
#else | |
#if ZTD_TEXT_HAS_INCLUDE_I_(<nl_langinfo.h>) | |
#define ZTD_TEXT_NL_LANGINFO_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_NL_LANGINFO_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#endif // nl_langinfo POSIX | |
#if defined(ZTD_TEXT_DEFAULT_HANDLER_THROWS) | |
#if (ZTD_TEXT_DEFAULT_HANDLER_THROWS != 0) | |
#define ZTD_TEXT_DEFAULT_HANDLER_THROWS_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_DEFAULT_HANDLER_THROWS_I_ ZTD_TEXT_OFF | |
#endif | |
#else | |
#define ZTD_TEXT_DEFAULT_HANDLER_THROWS_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#if defined(ZTD_TEXT_LOCALE_DEPENDENT_WIDE_EXECUTION) | |
#if (ZTD_TEXT_LOCALE_DEPENDENT_WIDE_EXECUTION != 0) | |
#define ZTD_TEXT_LOCALE_DEPENDENT_WIDE_EXECUTION_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_LOCALE_DEPENDENT_WIDE_EXECUTION_I_ ZTD_TEXT_OFF | |
#endif | |
#elif ZTD_TEXT_IS_ON(ZTD_TEXT_NL_LANGINFO_I_) && (ZTD_TEXT_IS_ON(ZTD_TEXT_PLATFORM_ZEDOS_I_) || ZTD_TEXT_IS_ON(ZTD_TEXT_PLATFORM_AIX_I_)) | |
#define ZTD_TEXT_LOCALE_DEPENDENT_WIDE_EXECUTION_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_LOCALE_DEPENDENT_WIDE_EXECUTION_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif // Locale-dependent wchar_t detection | |
#if defined(ZTD_TEXT_INTERMEDIATE_BUFFER_SIZE) | |
#define ZTD_TEXT_INTERMEDIATE_BUFFER_SIZE_I_ ZTD_TEXT_INTERMEDIATE_BUFFER_SIZE | |
#else | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_COMPILER_VCXX_I_) | |
// "The reserve value specifies the total stack allocation in virtual memory. | |
// For ARM, x86 and x64 machines, the default stack size is 1 MB." | |
// ... | |
// "For ARM, x86 and x64 machines, the default commit value is 4 KB" | |
// https://docs.microsoft.com/en-us/cpp/build/reference/stack-stack-allocations?view=vs-2019 | |
#define ZTD_TEXT_INTERMEDIATE_BUFFER_SIZE_I_ (1024 * 64) | |
#elif ZTD_TEXT_IS_ON(ZTD_TEXT_PLATFORM_LINUX_I_) || ZTD_TEXT_IS_ON(ZTD_TEXT_PLATFORM_UNIX_I_) | |
// "Here is the vale for a few architectures:" | |
// | |
// │Architecture │ Default stack size │ | |
// ├─────────────┼────────────────────┤ | |
// │i386 │ 2 MB │ | |
// ├─────────────┼────────────────────┤ | |
// │IA-64 │ 32 MB │ | |
// ├─────────────┼────────────────────┤ | |
// │PowerPC │ 4 MB │ | |
// ├─────────────┼────────────────────┤ | |
// │S/390 │ 2 MB │ | |
// ├─────────────┼────────────────────┤ | |
// │Sparc-32 │ 2 MB │ | |
// ├─────────────┼────────────────────┤ | |
// │Sparc-64 │ 4 MB │ | |
// ├─────────────┼────────────────────┤ | |
// │x86_64 │ 2 MB │ | |
// └─────────────┴────────────────────┘ | |
// http://man7.org/linux/man-pages/man3/pthread_create.3.html | |
#define ZTD_TEXT_INTERMEDIATE_BUFFER_SIZE_I_ (1024 * 128) | |
#else | |
// Tiny embbeded compiler shenanigans?? | |
#define ZTD_TEXT_INTERMEDIATE_BUFFER_SIZE_I_ (1024 * 2) | |
#endif // MSVC vs. others | |
#endif // Intermediate buffer sizing | |
#if defined (__has_cpp_attribute) && (__has_cpp_attribute(nodiscard) != 0L) | |
#if __has_cpp_attribute(nodiscard) >= 201907L | |
#define ZTD_TEXT_NODISCARD_MESSAGE_I_(__message) [[nodiscard(__message)]] | |
#define ZTD_TEXT_NODISCARD_I_ [[nodiscard]] | |
#else | |
#define ZTD_TEXT_NODISCARD_MESSAGE_I_(__message) [[nodiscard]] | |
#define ZTD_TEXT_NODISCARD_I_ [[nodiscard]] | |
#endif | |
#elif defined (__has_c_attribute) && (__has_c_attribute(nodiscard) != 0L) | |
#define ZTD_TEXT_NODISCARD_MESSAGE_I_(__message) [[nodiscard(__message)]] | |
#define ZTD_TEXT_NODISCARD_I_ [[nodiscard]] | |
#else | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_COMPILER_VCXX_I_) && defined(_Check_return_) | |
#define ZTD_TEXT_NODISCARD_MESSAGE_I_(__message) _Check_return_ | |
#define ZTD_TEXT_NODISCARD_I_ _Check_return_ | |
#elif ZTD_TEXT_IS_ON(ZTD_TEXT_COMPILER_CLANG_I_) || ZTD_TEXT_IS_ON(ZTD_TEXT_COMPILER_GCC_I_) | |
#define ZTD_TEXT_NODISCARD_MESSAGE_I_(__message) __attribute__((warn_unused_result)) | |
#define ZTD_TEXT_NODISCARD_I_ __attribute__((warn_unused_result)) | |
#else | |
// :c | |
#define ZTD_TEXT_NODSICARD_I_(__message) | |
#define ZTD_TEXT_NODISCARD_I_ | |
#endif | |
#endif | |
#if defined(ZTD_TEXT_STD_TEXT_ENCODING_ID) | |
#if (ZTD_TEXT_STD_TEXT_ENCODING_ID != 0) | |
#define ZTD_TEXT_STD_TEXT_ENCODING_ID_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_STD_TEXT_ENCODING_ID_I_ ZTD_TEXT_OFF | |
#endif | |
#elif defined(__cpp_lib_text_encoding_id) | |
#define ZTD_TEXT_STD_TEXT_ENCODING_ID_I_ ZTD_TEXT_DEFAULT_ON | |
#else | |
#define ZTD_TEXT_STD_TEXT_ENCODING_ID_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#if defined(ZTD_TEXT_STD_LIBRARY_CONSTEXPR_ALGORITHMS) | |
#if (ZTD_TEXT_STD_LIBRARY_CONSTEXPR_ALGORITHMS != 0) | |
#define ZTD_TEXT_STD_LIBRARY_CONSTEXPR_ALGORITHMS_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_STD_LIBRARY_CONSTEXPR_ALGORITHMS_I_ ZTD_TEXT_OFF | |
#endif | |
#elif defined(__cpp_lib_constexpr_algorithms) | |
#define ZTD_TEXT_STD_LIBRARY_CONSTEXPR_ALGORITHMS_I_ ZTD_TEXT_DEFAULT_ON | |
#else | |
#define ZTD_TEXT_STD_LIBRARY_CONSTEXPR_ALGORITHMS_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#if defined(ZTD_TEXT_STD_LIBRARY_RANGES) | |
#if (ZTD_TEXT_STD_LIBRARY_RANGES != 0) | |
#define ZTD_TEXT_STD_LIBRARY_RANGES_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_STD_LIBRARY_RANGES_I_ ZTD_TEXT_OFF | |
#endif | |
#elif ZTD_TEXT_IS_ON(ZTD_TEXT_COMPILER_CLANG_I_) | |
#if 0 | |
#define ZTD_TEXT_STD_LIBRARY_RANGES_I_ ZTD_TEXT_DEFAULT_ON | |
#else | |
// clang's concepts implementation, which powers ranges, is busted! | |
#define ZTD_TEXT_STD_LIBRARY_RANGES_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#elif defined(__cpp_lib_ranges) | |
#define ZTD_TEXT_STD_LIBRARY_RANGES_I_ ZTD_TEXT_DEFAULT_ON | |
#else | |
#define ZTD_TEXT_STD_LIBRARY_RANGES_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#if defined(ZTD_TEXT_STD_LIBRARY_ENDIAN) | |
#if (ZTD_TEXT_STD_LIBRARY_ENDIAN != 0) | |
#define ZTD_TEXT_STD_LIBRARY_ENDIAN_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_STD_LIBRARY_ENDIAN_I_ ZTD_TEXT_OFF | |
#endif | |
#elif defined(__cpp_lib_endian) | |
#define ZTD_TEXT_STD_LIBRARY_ENDIAN_I_ ZTD_TEXT_DEFAULT_ON | |
#else | |
#define ZTD_TEXT_STD_LIBRARY_ENDIAN_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#if defined(ZTD_TEXT_STD_LIBRARY_REFERENCE_WRAPPER_CONSTEXPR) | |
#if (ZTD_TEXT_STD_LIBRARY_REFERENCE_WRAPPER_CONSTEXPR != 0) | |
#define ZTD_TEXT_STD_LIBRARY_REFERENCE_WRAPPER_CONSTEXPR_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_STD_LIBRARY_REFERENCE_WRAPPER_CONSTEXPR_I_ ZTD_TEXT_OFF | |
#endif | |
#elif defined(__cpp_lib_constexpr_utility) && (__cpp_lib_constexpr_utility >= 201811L) | |
#define ZTD_TEXT_STD_LIBRARY_REFERENCE_WRAPPER_CONSTEXPR_I_ ZTD_TEXT_DEFAULT_ON | |
#else | |
#define ZTD_TEXT_STD_LIBRARY_REFERENCE_WRAPPER_CONSTEXPR_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#if defined(ZTD_TEXT_STD_LIBRARY_CONCEPTS) | |
#if (ZTD_TEXT_STD_LIBRARY_CONCEPTS != 0) | |
#define ZTD_TEXT_STD_LIBRARY_CONCEPTS_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_STD_LIBRARY_CONCEPTS_I_ ZTD_TEXT_OFF | |
#endif | |
#elif defined(__cpp_lib_concepts) | |
#define ZTD_TEXT_STD_LIBRARY_CONCEPTS_I_ ZTD_TEXT_DEFAULT_ON | |
#else | |
#define ZTD_TEXT_STD_LIBRARY_CONCEPTS_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#if defined(ZTD_TEXT_STD_LIBRARY_CONTIGUOUS_ITERATOR_TAG) | |
#if (ZTD_TEXT_STD_LIBRARY_CONTIGUOUS_ITERATOR_TAG != 0) | |
#define ZTD_TEXT_STD_LIBRARY_CONTIGUOUS_ITERATOR_TAG_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_STD_LIBRARY_CONTIGUOUS_ITERATOR_TAG_I_ ZTD_TEXT_OFF | |
#endif | |
#elif ZTD_TEXT_IS_ON(ZTD_TEXT_LIBVCXX_I_) && ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_CONCEPTS_I_) | |
#define ZTD_TEXT_STD_LIBRARY_CONTIGUOUS_ITERATOR_TAG_I_ ZTD_TEXT_DEFAULT_ON | |
#elif ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_CONCEPTS_I_) && ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_RANGES_I_) | |
#define ZTD_TEXT_STD_LIBRARY_CONTIGUOUS_ITERATOR_TAG_I_ ZTD_TEXT_DEFAULT_ON | |
#else | |
#define ZTD_TEXT_STD_LIBRARY_CONTIGUOUS_ITERATOR_TAG_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#if defined(ZTD_TEXT_COMPILE_TIME_ENCODING_NAME) | |
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_GET_I_() ZTD_TEXT_COMPILE_TIME_ENCODING_NAME | |
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_DESCRIPTION_I_() "set by the user with ZTD_TEXT_COMPILE_TIME_ENCODING_NAME as (" ZTD_TEXT_TOKEN_TO_STRING_I_(ZTD_TEXT_COMPILE_TIME_ENCODING_NAME) ")" | |
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON | |
#elif ZTD_TEXT_IS_ON(ZTD_TEXT_STD_TEXT_ENCODING_ID_I_) | |
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_GET_I_() ::std::text_encoding::literal().name() | |
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_DESCRIPTION_I_() "from std::text_encoding::literal().name()" | |
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME ZTD_TEXT_DEFAULT_ON | |
#elif defined(__MSC_EXECUTION_CHARSET_ID) | |
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_GET_I_() ::ztd::text::__txt_detail::__msvc_encoding_name_from_id(__MSC_EXECUTION_CHARSET_ID) | |
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_DESCRIPTION_I_() "MSVC CodePage ID: " ZTD_TEXT_TOKEN_TO_STRING_I_(__MSC_EXECUTION_CHARSET_ID) | |
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON | |
#elif defined(__GNUC_EXECUTION_CHARSET_NAME) | |
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_GET_I_() __GNUC_EXECUTION_CHARSET_NAME | |
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_DESCRIPTION_I_() __GNUC_EXECUTION_CHARSET_NAME | |
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON | |
#elif defined(__clang_literal_encoding__) | |
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_GET_I_() __clang_literal_encoding__ | |
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_DESCRIPTION_I_() __clang_literal_encoding__ | |
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON | |
#elif ZTD_TEXT_IS_ON(ZTD_TEXT_COMPILER_CLANG_I_) | |
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_GET_I_() "UTF-8" | |
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_DESCRIPTION_I_() "UTF-8" | |
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON | |
#else | |
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_GET_I_() "UTF-8" | |
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_DESCRIPTION_I_() "UTF-8" | |
#define ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#if defined(ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME) | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_DESCRIPTION_I_() "set by the user with ZTD_TEXT_COMPILE_TIME_ENCODING_NAME as (" ZTD_TEXT_TOKEN_TO_STRING_I_(ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME) ")" | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_I_ ZTD_TEXT_ON | |
#elif ZTD_TEXT_IS_ON(ZTD_TEXT_STD_TEXT_ENCODING_ID_I_) | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() ::std::text_encoding::wide_literal().name() | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_DESCRIPTION_I_() "from ::std::text_encoding::wide_literal().name()" | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON | |
#elif defined(__GNUC_WIDE_EXECUTION_CHARSET_NAME) | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() __GNUC_WIDE_EXECUTION_CHARSET_NAME | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_DESCRIPTION_I_() ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON | |
#elif defined(__clang_wide_literal_encoding__) | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() __clang_wide_literal_encoding__ | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_DESCRIPTION_I_() ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON | |
#elif ZTD_TEXT_IS_ON(ZTD_TEXT_PLATFORM_WINDOWS_I_) | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() "UTF-16" | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_DESCRIPTION_I_() "UTF-16" | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON | |
#elif (WCHAR_MAX >= 0x001FFFFF) && ZTD_TEXT_IS_ON(ZTD_TEXT_WCHAR_T_UTF32_COMPATIBLE_I_) | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() "UTF-32" | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_DESCRIPTION_I_() "UTF-32" | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON | |
#elif (WCHAR_MAX >= 0xFFFF) | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() "UTF-16" | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_DESCRIPTION_I_() "UTF-16" | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON | |
#elif (WCHAR_MAX >= 0xFF) | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() "UTF-8" | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_DESCRIPTION_I_() "UTF-8" | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_ON | |
#else | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_() "UTF-32" | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_DESCRIPTION_I_() "UTF-32" | |
#define ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#if defined(ZTD_TEXT_YES_PLEASE_DESTROY_MY_LITERALS_UTTERLY_I_MEAN_IT) | |
#if (ZTD_TEXT_YES_PLEASE_DESTROY_MY_LITERALS_UTTERLY_I_MEAN_IT != 0) | |
#define ZTD_TEXT_YES_PLEASE_DESTROY_MY_LITERALS_UTTERLY_I_MEAN_IT_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_YES_PLEASE_DESTROY_MY_LITERALS_UTTERLY_I_MEAN_IT_I_ ZTD_TEXT_OFF | |
#endif | |
#else | |
#define ZTD_TEXT_YES_PLEASE_DESTROY_MY_LITERALS_UTTERLY_I_MEAN_IT_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#if defined(ZTD_TEXT_YES_PLEASE_DESTROY_MY_WIDE_LITERALS_UTTERLY_I_MEAN_IT) | |
#if (ZTD_TEXT_YES_PLEASE_DESTROY_MY_WIDE_LITERALS_UTTERLY_I_MEAN_IT != 0) | |
#define ZTD_TEXT_YES_PLEASE_DESTROY_MY_WIDE_LITERALS_UTTERLY_I_MEAN_IT_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_YES_PLEASE_DESTROY_MY_WIDE_LITERALS_UTTERLY_I_MEAN_IT_I_ ZTD_TEXT_OFF | |
#endif | |
#else | |
#define ZTD_TEXT_YES_PLEASE_DESTROY_MY_WIDE_LITERALS_UTTERLY_I_MEAN_IT_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#if defined (__has_cpp_attribute) && (__has_cpp_attribute(deprecated) != 0L) | |
#define ZTD_TEXT_DEPRECATED_I_(__message) [[deprecated(__message)]] | |
#elif defined (__has_c_attribute) && (__has_c_attribute(deprecated) != 0L) | |
#define ZTD_TEXT_DEPRECATED_I_(__message) [[deprecated(__message)]] | |
#else | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_COMPILER_VCXX_I_) | |
#define ZTD_TEXT_DEPRECATED_I_(__message) declspec(deprecated) | |
#elif ZTD_TEXT_IS_ON(ZTD_TEXT_COMPILER_CLANG_I_) || ZTD_TEXT_IS_ON(ZTD_TEXT_COMPILER_GCC_I_) | |
#define ZTD_TEXT_DEPRECATED_I_(__message) __attribute__((warn_unused_result)) | |
#else | |
// :c | |
#define ZTD_TEXT_DEPRECATED_I_(__message) | |
#endif | |
#endif | |
#if defined(ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED) | |
#if (ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED != 0) | |
#define ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED_I_ ZTD_TEXT_OFF | |
#endif | |
#elif defined(__cpp_lib_is_constant_evaluated) | |
#define ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED_I_ ZTD_TEXT_DEFAULT_ON | |
#else | |
#define ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#if defined(ZTD_TEXT_STD_LIBRARY_TO_ADDRESS) | |
#if (ZTD_TEXT_STD_LIBRARY_TO_ADDRESS != 0) | |
#define ZTD_TEXT_STD_LIBRARY_TO_ADDRESS_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_STD_LIBRARY_TO_ADDRESS_I_ ZTD_TEXT_OFF | |
#endif | |
#elif defined(__cpp_lib_to_address) | |
#define ZTD_TEXT_STD_LIBRARY_TO_ADDRESS_I_ ZTD_TEXT_DEFAULT_ON | |
#else | |
#define ZTD_TEXT_STD_LIBRARY_TO_ADDRESS_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#if defined (ZTD_TEXT_CONSTEXPR_IF_CONSTANT_EVALUATED) | |
#if (ZTD_TEXT_CONSTEXPR_IF_CONSTANT_EVALUATED != 0) | |
#define ZTD_TEXT_CONSTEXPR_IF_CONSTANT_EVALUATED_I_ constexpr | |
#else | |
#define ZTD_TEXT_CONSTEXPR_IF_CONSTANT_EVALUATED_I_ | |
#endif | |
#elif ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED_I_) | |
#define ZTD_TEXT_CONSTEXPR_IF_CONSTANT_EVALUATED_I_ constexpr | |
#else | |
#define ZTD_TEXT_CONSTEXPR_IF_CONSTANT_EVALUATED_I_ | |
#endif | |
#if defined(ZTD_TEXT_STD_LIBRARY_SPACESHIP_COMPARE) | |
#if (ZTD_TEXT_STD_LIBRARY_SPACESHIP_COMPARE != 0) | |
#define ZTD_TEXT_STD_LIBRARY_SPACESHIP_COMPARE_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_STD_LIBRARY_SPACESHIP_COMPARE_I_ ZTD_TEXT_OFF | |
#endif | |
#elif defined(__cpp_lib_three_way_comparison) | |
#define ZTD_TEXT_STD_LIBRARY_SPACESHIP_COMPARE_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_STD_LIBRARY_SPACESHIP_COMPARE_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#if defined(ZTD_TEXT_STD_LIBRARY_STARTS_ENDS_WITH) | |
#if (ZTD_TEXT_STD_LIBRARY_STARTS_ENDS_WITH != 0) | |
#define ZTD_TEXT_STD_LIBRARY_STARTS_ENDS_WITH_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_STD_LIBRARY_STARTS_ENDS_WITH_I_ ZTD_TEXT_ON | |
#endif | |
#elif defined(__cpp_lib_starts_ends_with) | |
#define ZTD_TEXT_STD_LIBRARY_STARTS_ENDS_WITH_I_ ZTD_TEXT_DEFAULT_ON | |
#else | |
#define ZTD_TEXT_STD_LIBRARY_STARTS_ENDS_WITH_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#if defined(ZTD_TEXT_STD_LIBRARY_STRING_CONTAINS) | |
#if (ZTD_TEXT_STD_LIBRARY_STRING_CONTAINS != 0) | |
#define ZTD_TEXT_STD_LIBRARY_STRING_CONTAINS_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_STD_LIBRARY_STRING_CONTAINS_I_ ZTD_TEXT_ON | |
#endif | |
#elif defined(__cpp_lib_string_contains) | |
#define ZTD_TEXT_STD_LIBRARY_STRING_CONTAINS_I_ ZTD_TEXT_DEFAULT_ON | |
#else | |
#define ZTD_TEXT_STD_LIBRARY_STRING_CONTAINS_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#if defined(ZTD_TEXT_STD_LIBRARY_SPAN) | |
#if (ZTD_TEXT_STD_LIBRARY_SPAN != 0) | |
#define ZTD_TEXT_STD_LIBRARY_SPAN_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_STD_LIBRARY_SPAN_I_ ZTD_TEXT_ON | |
#endif | |
#elif defined(__cpp_lib_span) && ZTD_TEXT_IS_OFF(ZTD_TEXT_LIBVCXX_I_) | |
#define ZTD_TEXT_STD_LIBRARY_SPAN_I_ ZTD_TEXT_DEFAULT_ON | |
#else | |
#define ZTD_TEXT_STD_LIBRARY_SPAN_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#if defined (ZTD_TEXT_UNICODE_CODE_POINT_DISTINCT_TYPE) | |
#if (ZTD_TEXT_UNICODE_CODE_POINT_DISTINCT_TYPE != 0) | |
#define ZTD_TEXT_UNICODE_CODE_POINT_DISTINCT_TYPE_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_UNICODE_CODE_POINT_DISTINCT_TYPE_I_ ZTD_TEXT_OFF | |
#endif | |
#else | |
#define ZTD_TEXT_UNICODE_CODE_POINT_DISTINCT_TYPE_I_ ZTD_TEXT_DEFAULT_OFF | |
#endif | |
#if defined(ZTD_TEXT_UNICODE_CODE_POINT_INVARIANT_ABORT) | |
#if (ZTD_TEXT_UNICODE_CODE_POINT_INVARIANT_ABORT != 0) | |
#define ZTD_TEXT_UNICODE_CODE_POINT_INVARIANT_ABORT_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_UNICODE_CODE_POINT_INVARIANT_ABORT_I_ ZTD_TEXT_OFF | |
#endif | |
#else | |
#define ZTD_TEXT_UNICODE_CODE_POINT_INVARIANT_ABORT_I_ ZTD_TEXT_OFF | |
#endif | |
#if defined (ZTD_TEXT_UNICODE_SCALAR_VALUE_DISTINCT_TYPE) | |
#if (ZTD_TEXT_UNICODE_CODE_POINT_DISTINCT_TYPE != 0) | |
#define ZTD_TEXT_UNICODE_SCALAR_VALUE_DISTINCT_TYPE_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_UNICODE_SCALAR_VALUE_DISTINCT_TYPE_I_ ZTD_TEXT_OFF | |
#endif | |
#else | |
#define ZTD_TEXT_UNICODE_SCALAR_VALUE_DISTINCT_TYPE_I_ ZTD_TEXT_DEFAULT_ON | |
#endif | |
#if defined(ZTD_TEXT_UNICODE_SCALAR_VALUE_INVARIANT_ABORT) | |
#if (ZTD_TEXT_UNICODE_SCALAR_VALUE_INVARIANT_ABORT != 0) | |
#define ZTD_TEXT_UNICODE_SCALAR_VALUE_INVARIANT_ABORT_I_ ZTD_TEXT_ON | |
#else | |
#define ZTD_TEXT_UNICODE_SCALAR_VALUE_INVARIANT_ABORT_I_ ZTD_TEXT_OFF | |
#endif | |
#else | |
#define ZTD_TEXT_UNICODE_SCALAR_VALUE_INVARIANT_ABORT_I_ ZTD_TEXT_OFF | |
#endif | |
#if defined(ZTD_TEXT_FWD) | |
#define ZTD_TEXT_FWD_I_(__val) ZTD_TEXT_FWD(__val) | |
#else | |
#define ZTD_TEXT_FWD_I_(__val) static_cast<decltype(__val)&&>(__val) | |
#endif | |
#if defined(ZTD_TEXT_MOVE) | |
#define ZTD_TEXT_MOVE_I_(__val) ZTD_TEXT_MOVE(__val) | |
#else | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_COMPILER_GCC_I_) || ZTD_TEXT_IS_ON(ZTD_TEXT_COMPILER_CLANG_I_) | |
// C's "typeof" never returns a reference | |
#define ZTD_TEXT_MOVE_I_(__val) static_cast<__typeof(__val)&&>(__val) | |
#else | |
#define ZTD_TEXT_MOVE_I_(__val) static_cast<::std::remove_reference_t<decltype(__val)>&&>(__val) | |
#endif | |
#endif | |
#if defined(ZTD_TEXT_ABI_NAMESPACE) | |
#define ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ inline namespace ZTD_TEXT_ABI_NAMESPACE { | |
#define ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ } | |
#else | |
#define ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ inline namespace __v0 { | |
#define ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ } | |
#endif | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/prologue.hpp | |
#if defined(ZTD_TEXT_DETAIL_PROLOGUE_I_) | |
#error "[ztd.text] Library Prologue was already included in translation unit and not properly ended with an epilogue." | |
#endif | |
#define ZTD_TEXT_DETAIL_PROLOGUE_I_ 1 | |
#define _FWD(...) static_cast<decltype( __VA_ARGS__ )&&>( __VA_ARGS__ ) | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_COMPILER_GCC_I_) | |
#define _MOVE(...) static_cast<__typeof( __VA_ARGS__ )&&>( __VA_ARGS__ ) | |
#else | |
#include <type_traits> | |
#define _MOVE(...) static_cast<::std::remove_reference_t<( __VA_ARGS__ )>&&>( __VA_OPT__(,) ) | |
#endif | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/prologue.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/epilogue.hpp | |
#if !defined(ZTD_TEXT_DETAIL_PROLOGUE_I_) | |
#error "[ztd.text] Library Prologue is missing from this translation unit." | |
#else | |
#undef ZTD_TEXT_DETAIL_PROLOGUE_I_ | |
#endif | |
#undef _FWD | |
#undef _MOVE | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/epilogue.hpp | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/version.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/forward.hpp | |
#ifndef ZTD_TEXT_FORWARD_HPP | |
#define ZTD_TEXT_FORWARD_HPP | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
class __empty_state; | |
} // namespace __txt_detail | |
namespace __impl { | |
class __utf8_tag; | |
class __utf16_tag; | |
class __utf32_tag; | |
template <typename, typename, typename, bool, bool, bool> | |
class __utf8_with; | |
template <typename, typename, typename, bool> | |
class __utf16_with; | |
template <typename, typename, typename, bool> | |
class __utf32_with; | |
class __unicode_code_point; | |
class __unicode_scalar_value; | |
} // namespace __impl | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_UNICODE_CODE_POINT_DISTINCT_TYPE_I_) | |
using unicode_code_point = __impl::__unicode_code_point; | |
#else | |
using unicode_code_point = char32_t; | |
#endif | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_UNICODE_SCALAR_VALUE_DISTINCT_TYPE_I_) | |
using unicode_scalar_value = __impl::__unicode_scalar_value; | |
#else | |
using unicode_scalar_value = char32_t; | |
#endif | |
using uchar8_t = ZTD_TEXT_CHAR8_T_I_; | |
class assume_valid_handler; | |
class pass_through_handler; | |
template <typename, typename> | |
class incomplete_handler; | |
class replacement_handler; | |
class default_handler; | |
template <typename, typename> | |
class basic_ascii; | |
using ascii = basic_ascii<char, unicode_code_point>; | |
class execution; | |
class wide_execution; | |
template <typename, typename> | |
class basic_utf8; | |
template <typename, typename> | |
class basic_utf16; | |
template <typename, typename> | |
class basic_utf32; | |
using utf8 = basic_utf8<uchar8_t, unicode_code_point>; | |
using utf16 = basic_utf16<char16_t, unicode_code_point>; | |
using utf32 = basic_utf32<char32_t, unicode_code_point>; | |
class nfc; | |
class nfd; | |
class nfkc; | |
class nfkd; | |
template <typename, typename, typename, typename> | |
class basic_text_view; | |
template <typename, typename, typename, typename> | |
class basic_text; | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
#endif // ZTD_TEXT_FORWARD_HPP | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/forward.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/char8_t.hpp | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_properties Property and Trait Helpers | |
/// | |
/// @{ | |
///// | |
////// | |
/// @brief An alias to a unsigned representation of an 8-bit (or greater) code unit type. | |
/// | |
/// @remarks This will be a type alias for the type given in @c ZTD_TEXT_CHAR8_T is defined by the user. Otherwise, | |
/// it will be a type alias for @c char8_t if present. If neither are available, it will alias @c uchar | |
/// for the type. | |
////// | |
using uchar8_t = ZTD_TEXT_CHAR8_T_I_; | |
////// | |
/// @} | |
///// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/char8_t.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/encoding.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/execution.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/encode_result.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/unicode_code_point.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/assert.hpp | |
#if defined(ZTD_TEXT_ASSERT_USER) | |
#define ZTD_TEXT_ASSERT_I_(...) ZTD_TEXT_ASSERT_USER(__VA_ARGS__) | |
#else | |
#ifndef NDEBUG | |
#include <exception> | |
#include <iostream> | |
#include <cstdlib> | |
#define ZTD_TEXT_ASSERT_I_(...) \ | |
do { \ | |
if (!(__VA_ARGS__)) { \ | |
::std::cerr << "Assertion `" #__VA_ARGS__ "` failed in " << __FILE__ << " line " << __LINE__ << ::std::endl; \ | |
::std::terminate(); \ | |
} \ | |
} while (false) | |
#else | |
#define ZTD_TEXT_ASSERT_I_(...) \ | |
do { \ | |
if (false) { \ | |
(void)(__VA_ARGS__); \ | |
} \ | |
} while (false) | |
#endif | |
#endif | |
#if defined(ZTD_TEXT_ASSERT_MESSAGE_USER) | |
#define ZTD_TEXT_ASSERT_MESSAGE_I_(...) ZTD_TEXT_ASSERT_MESSAGE_USER(__VA_ARGS__) | |
#else | |
#ifndef NDEBUG | |
#include <exception> | |
#include <iostream> | |
#include <cstdlib> | |
#define ZTD_TEXT_ASSERT_MESSAGE_I_(__message, ...) \ | |
do { \ | |
if (!(__VA_ARGS__)) { \ | |
::std::cerr << "Assertion `" #__VA_ARGS__ "` failed in " << __FILE__ << " line " << __LINE__ << ": " \ | |
<< __message << ::std::endl; \ | |
::std::terminate(); \ | |
} \ | |
} while (false) | |
#else | |
#define ZTD_TEXT_ASSERT_MESSAGE_I_(__message, ...) \ | |
do { \ | |
if (false) { \ | |
(void)(__VA_ARGS__); \ | |
(void)sizeof(__message); \ | |
} \ | |
} while (false) | |
#endif | |
#endif | |
#define ZTD_TEXT_ASSERT(...) ZTD_TEXT_ASSERT_I_(__VA_ARGS__) | |
#define ZTD_TEXT_ASSERT_MESSAGE(...) ZTD_TEXT_ASSERT_MESSAGE_I_(__VA_ARGS__) | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/assert.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/unicode.hpp | |
#include <cstddef> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
// codepoint related | |
inline constexpr char32_t __last_code_point = 0x10FFFF; | |
inline constexpr char32_t __first_lead_surrogate = 0xD800; | |
inline constexpr char32_t __last_lead_surrogate = 0xDBFF; | |
inline constexpr char32_t __first_trail_surrogate = 0xDC00; | |
inline constexpr char32_t __last_trail_surrogate = 0xDFFF; | |
inline constexpr char32_t __first_surrogate = __first_lead_surrogate; | |
inline constexpr char32_t __last_surrogate = __last_trail_surrogate; | |
inline constexpr bool __is_lead_surrogate(char32_t __value) noexcept { | |
return __value >= __first_lead_surrogate && __value <= __last_lead_surrogate; | |
} | |
inline constexpr bool __is_trail_surrogate(char32_t __value) noexcept { | |
return __value >= __first_trail_surrogate && __value <= __last_trail_surrogate; | |
} | |
inline constexpr bool __is_surrogate(char32_t __value) noexcept { | |
return __value >= __first_surrogate && __value <= __last_surrogate; | |
} | |
// utf8 related | |
inline constexpr char32_t __last_1byte_value = 0x7F; | |
inline constexpr char32_t __last_2byte_value = 0x7FF; | |
inline constexpr char32_t __last_3byte_value = 0xFFFF; | |
inline constexpr char32_t __last_4byte_value = 0x1FFFFF; | |
inline constexpr char32_t __last_5byte_value = 0x3FFFFFF; | |
inline constexpr char32_t __last_6byte_value = 0x7FFFFFFF; | |
inline constexpr uchar8_t __start_1byte_mask = 0x80u; | |
inline constexpr uchar8_t __start_1byte_continuation = 0x00u; | |
inline constexpr uchar8_t __start_1byte_shift = 7u; | |
inline constexpr uchar8_t __start_2byte_mask = 0xC0u; | |
inline constexpr uchar8_t __start_2byte_continuation = __start_2byte_mask; | |
inline constexpr uchar8_t __start_2byte_shift = 5u; | |
inline constexpr uchar8_t __start_3byte_mask = 0xE0u; | |
inline constexpr uchar8_t __start_3byte_continuation = __start_3byte_mask; | |
inline constexpr uchar8_t __start_3byte_shift = 4u; | |
inline constexpr uchar8_t __start_4byte_mask = 0xF0u; | |
inline constexpr uchar8_t __start_4byte_continuation = __start_4byte_mask; | |
inline constexpr uchar8_t __start_4byte_shift = 3u; | |
inline constexpr uchar8_t __start_5byte_mask = 0xF8u; | |
inline constexpr uchar8_t __start_5byte_continuation = __start_5byte_mask; | |
inline constexpr uchar8_t __start_5byte_shift = 2u; | |
inline constexpr uchar8_t __start_6byte_mask = 0xFCu; | |
inline constexpr uchar8_t __start_6byte_continuation = __start_6byte_mask; | |
inline constexpr uchar8_t __start_6byte_shift = 1u; | |
inline constexpr uchar8_t __continuation_mask = 0xC0u; | |
inline constexpr uchar8_t __continuation_signature = 0x80u; | |
inline constexpr uchar8_t __continuation_mask_value = 0x3Fu; | |
inline constexpr uchar8_t __single_mask_value = 0x7Fu; | |
inline constexpr bool __utf8_is_invalid(uchar8_t __b) noexcept { | |
return __b == 0xC0 || __b == 0xC1 || __b > 0xF4; | |
} | |
inline constexpr bool __utf8_is_continuation(uchar8_t __value) noexcept { | |
return (__value & __continuation_mask) == __continuation_signature; | |
} | |
inline constexpr bool __utf8_is_overlong(char32_t __value, ::std::size_t __bytes) noexcept { | |
return __value <= __last_1byte_value || (__value <= __last_2byte_value && __bytes > 2) | |
|| (__value <= __last_3byte_value && __bytes > 3); | |
} | |
inline constexpr bool __utf8_is_overlong_extended(char32_t __value, ::std::size_t __bytes) noexcept { | |
return __value <= __last_1byte_value || (__value <= __last_2byte_value && __bytes > 2) | |
|| (__value <= __last_3byte_value && __bytes > 3) || (__value <= __last_4byte_value && __bytes > 4) | |
|| (__value <= __last_5byte_value && __bytes > 5); | |
} | |
template <bool __overlong_allowed = false> | |
inline constexpr int __decode_length(char32_t __value) noexcept { | |
if (__value <= __txt_detail::__last_1byte_value) { | |
return 1; | |
} | |
if (__value <= __txt_detail::__last_2byte_value) { | |
return 2; | |
} | |
if (__value <= __txt_detail::__last_3byte_value) { | |
return 3; | |
} | |
if (__value <= __txt_detail::__last_4byte_value) { | |
return 4; | |
} | |
if constexpr (__overlong_allowed) { | |
if (__value <= __txt_detail::__last_5byte_value) { | |
return 5; | |
} | |
if (__value <= __txt_detail::__last_6byte_value) { | |
return 6; | |
} | |
} | |
return 8; | |
} | |
inline constexpr int __sequence_length(uchar8_t __value) noexcept { | |
return (__value & __start_1byte_mask) == __start_1byte_continuation ? 1 | |
: (__value & __start_3byte_mask) != __start_3byte_continuation ? 2 | |
: (__value & __start_4byte_mask) != __start_4byte_continuation ? 3 | |
: 4; | |
} | |
inline constexpr int __sequence_length_extended(uchar8_t __value) noexcept { | |
return (__value & __start_1byte_mask) == __start_1byte_continuation ? 1 | |
: (__value & __start_3byte_mask) != __start_3byte_continuation ? 2 | |
: (__value & __start_4byte_mask) != __start_4byte_continuation ? 3 | |
: (__value & __start_5byte_mask) != __start_5byte_continuation ? 4 | |
: (__value & __start_6byte_mask) != __start_6byte_continuation ? 5 | |
: 6; | |
} | |
inline constexpr char32_t __decode(uchar8_t __value0, uchar8_t __value1) noexcept { | |
return static_cast<char32_t>(((__value0 & 0x1F) << 6) | (__value1 & 0x3F)); | |
} | |
inline constexpr char32_t __decode(uchar8_t __value0, uchar8_t __value1, uchar8_t __value2) noexcept { | |
return static_cast<char32_t>(((__value0 & 0x0F) << 12) | ((__value1 & 0x3F) << 6) | (__value2 & 0x3F)); | |
} | |
inline constexpr char32_t __decode( | |
uchar8_t __value0, uchar8_t __value1, uchar8_t __value2, uchar8_t __value3) noexcept { | |
return static_cast<char32_t>(((__value0 & 0x07) << 18) | ((__value1 & 0x3F) << 12) | |
| ((__value2 & 0x3F) << 6) | (__value3 & 0x3F)); | |
} | |
// utf16 related | |
inline constexpr char32_t __last_ascii_value = 0x7F; | |
inline constexpr char32_t __last_bmp_value = 0xFFFF; | |
inline constexpr char32_t __normalizing_value = 0x10000; | |
inline constexpr int __lead_surrogate_bitmask = 0xFFC00; | |
inline constexpr int __trail_surrogate_bitmask = 0x3FF; | |
inline constexpr int __lead_shifted_bits = 10; | |
inline constexpr char32_t __replacement = 0xFFFD; | |
inline constexpr char32_t __ascii_replacement = 0x003F; | |
inline constexpr char32_t __utf16_combine_surrogates(char16_t __lead, char16_t __trail) noexcept { | |
auto __hibits = __lead - __first_lead_surrogate; | |
auto __lobits = __trail - __first_trail_surrogate; | |
return __normalizing_value + ((__hibits << __lead_shifted_bits) | __lobits); | |
} | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/unicode.hpp | |
#include <utility> | |
#include <string> | |
#include <cstdint> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __impl { | |
////// | |
/// @brief A 32-bit value that is within the allowed 21 bits of Unicode. Can be one of the surrogate values. | |
/// | |
////// | |
class __unicode_code_point { | |
public: | |
////// | |
/// @brief Constructs a code point value of indeterminate value (if no parentheses/brackets are provided) | |
/// or with the value 0 (if parentheses/brackets are provided for intentional value initialization). | |
/// | |
////// | |
__unicode_code_point() noexcept = default; | |
////// | |
/// @brief Constructs a code point value with the given code point value. | |
/// | |
/// @remarks | |
////// | |
constexpr __unicode_code_point(char32_t __code_point) noexcept : _M_scalar(__code_point) { | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_UNICODE_CODE_POINT_INVARIANT_ABORT_I_) | |
if (__txt_detail::__is_surrogate(this->_M_scalar) | |
|| (this->_M_scalar > __txt_detail::__last_code_point)) { | |
::std::abort(); | |
} | |
#else | |
ZTD_TEXT_ASSERT_MESSAGE_I_("The code point value must be a valid code point.", | |
(this->_M_scalar <= __txt_detail::__last_code_point)); | |
#endif | |
} | |
////// | |
/// @brief An explicit conversion to a typical char32_t value, bit-compatible with a normal code point | |
/// value. | |
/// | |
////// | |
constexpr explicit operator char32_t() const noexcept { | |
return this->_M_scalar; | |
} | |
////// | |
/// @brief Retrieves the underlying value. | |
/// | |
////// | |
constexpr const char32_t& value() const& noexcept { | |
return this->_M_scalar; | |
} | |
////// | |
/// @brief Retrieves the underlying value. | |
/// | |
////// | |
constexpr char32_t& value() & noexcept { | |
return this->_M_scalar; | |
} | |
////// | |
/// @brief Retrieves the underlying value. | |
/// | |
////// | |
constexpr char32_t&& value() && noexcept { | |
return ::std::move(this->_M_scalar); | |
} | |
private: | |
char32_t _M_scalar; | |
}; | |
////// | |
/// @brief Check if two unicode code points are equal. | |
/// | |
/// @param[in] __left Left hand value of equality operator. | |
/// @param[in] __right Right hand value of equality operator. | |
////// | |
constexpr bool operator==(const __unicode_code_point& __left, const __unicode_code_point& __right) { | |
return __left.value() == __right.value(); | |
} | |
////// | |
/// @brief Check if two unicode code points are not equal. | |
/// | |
/// @param[in] __left Left hand value of inequality operator. | |
/// @param[in] __right Right hand value of inequality operator. | |
////// | |
constexpr bool operator!=(const __unicode_code_point& __left, const __unicode_code_point& __right) { | |
return __left.value() != __right.value(); | |
} | |
////// | |
/// @brief Check if one unicode code point is less than the other. | |
/// | |
/// @param[in] __left Left hand value of less than operator. | |
/// @param[in] __right Right hand value of less than operator. | |
////// | |
constexpr bool operator<(const __unicode_code_point& __left, const __unicode_code_point& __right) { | |
return __left.value() < __right.value(); | |
} | |
} // namespace __impl | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_UNICODE_CODE_POINT_DISTINCT_TYPE_I_) | |
using unicode_code_point = ____impl::__unicode_code_point; | |
#else | |
// TODO: what are the merits of a strong type here? | |
using unicode_code_point = char32_t; | |
#endif | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
namespace std { | |
template <> | |
class char_traits<::ztd::text::__impl::__unicode_code_point> { | |
using char_type = ::ztd::text::__impl::__unicode_code_point; | |
using int_type = ::std::int_least32_t; | |
using pos_type = ::std::streampos; | |
using off_type = ::std::streamoff; | |
using state_type = ::std::mbstate_t; | |
static /*constexpr*/ char_type* copy( | |
char_type* __destination, const char_type* __source, ::std::size_t __count) noexcept { | |
// TODO: constexpr. right now illegal cast | |
return reinterpret_cast<char_type*>(::std::char_traits<char32_t>::copy( | |
reinterpret_cast<char32_t*>(__destination), reinterpret_cast<const char32_t*>(__source), __count)); | |
} | |
static /*constexpr*/ char_type* move( | |
char_type* __destination, const char_type* __source, ::std::size_t __count) noexcept { | |
// TODO: constexpr. right now illegal cast | |
return reinterpret_cast<char_type*>(::std::char_traits<char32_t>::move( | |
reinterpret_cast<char32_t*>(__destination), reinterpret_cast<const char32_t*>(__source), __count)); | |
} | |
ZTD_TEXT_NODISCARD_I_ static /*constexpr*/ int compare( | |
const char_type* __left, const char_type* __right, ::std::size_t __count) noexcept { | |
// TODO: constexpr. right now illegal cast | |
return ::std::char_traits<char32_t>::compare( | |
reinterpret_cast<const char32_t*>(__left), reinterpret_cast<const char32_t*>(__right), __count); | |
} | |
ZTD_TEXT_NODISCARD_I_ static constexpr size_t length(const char_type* __it) noexcept { | |
size_t __count = 0; | |
const char_type __null_value {}; | |
while (*__it != __null_value) { | |
++__count; | |
++__it; | |
} | |
return __count; | |
} | |
ZTD_TEXT_NODISCARD_I_ static constexpr const char_type* find( | |
const char_type* __it, size_t __count, const char_type& __c) noexcept { | |
for (; 0 < __count; --__count, (void)++__it) { | |
if (*__it == __c) { | |
return __it; | |
} | |
} | |
return nullptr; | |
} | |
static constexpr char_type* assign(char_type* __first, size_t __count, const char_type __c) noexcept { | |
for (char_type* __it = __first; __count > 0; --__count, (void)++__it) { | |
*__it = __c; | |
} | |
return __first; | |
} | |
static constexpr void assign(char_type& __left, const char_type& __right) noexcept { | |
__left = __right; | |
} | |
ZTD_TEXT_NODISCARD_I_ static constexpr bool eq(const char_type& __left, const char_type& __right) noexcept { | |
return __left == __right; | |
} | |
ZTD_TEXT_NODISCARD_I_ static constexpr bool lt(const char_type& __left, const char_type& __right) noexcept { | |
return __left < __right; | |
} | |
ZTD_TEXT_NODISCARD_I_ static constexpr char_type to_char_type(const int_type& __c_as_int) noexcept { | |
return char_type(static_cast<char32_t>(__c_as_int)); | |
} | |
ZTD_TEXT_NODISCARD_I_ static constexpr int_type to_int_type(const char_type& __c) noexcept { | |
return static_cast<int_type>(__c.value()); | |
} | |
ZTD_TEXT_NODISCARD_I_ static constexpr bool eq_int_type( | |
const int_type& __left, const int_type& __right) noexcept { | |
return __left == __right; | |
} | |
ZTD_TEXT_NODISCARD_I_ static constexpr int_type not_eof(const int_type& __c_as_int) noexcept { | |
return __c_as_int != eof() ? __c_as_int : !eof(); | |
} | |
ZTD_TEXT_NODISCARD_I_ static constexpr int_type eof() noexcept { | |
return static_cast<int_type>(EOF); | |
} | |
}; | |
} // namespace std | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/unicode_code_point.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/encoding_error.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/to_underlying.hpp | |
#include <type_traits> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _Enum> | |
inline constexpr ::std::underlying_type_t<_Enum> __to_underlying(_Enum __value) noexcept { | |
return static_cast<::std::underlying_type_t<_Enum>>(__value); | |
} | |
template <typename _MaybeEnum> | |
inline constexpr auto __any_to_underlying(_MaybeEnum __value) noexcept { | |
if constexpr (::std::is_enum_v<_MaybeEnum>) { | |
return __to_underlying(__value); | |
} | |
else { | |
// TODO: verify integral-ness? | |
return __value; | |
} | |
} | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/to_underlying.hpp | |
#include <cstddef> | |
#include <system_error> | |
#include <type_traits> | |
#include <string> | |
#include <string_view> | |
#include <exception> | |
#include <array> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_encoding_error ztd::text::encoding_error | |
/// @brief This enumeration describes the kind of failures that can happen in ztd_text_transcode, | |
/// ztd_text_decode, ztd_text_encode, and lower-level operations. | |
/// @{ | |
////// | |
////// | |
/// @brief Describes a failure to encode, decode, transcode, or count, for four core various reasons. | |
/// | |
/// @remarks This does not cover specific failures, like if a sequence was overlong (e.g., UTF-8) or if an encode | |
/// operation produced an uunpaired surrogate value (e.g. UTF-16). | |
////// | |
enum class encoding_error : int { | |
////// | |
/// @brief The okay status; everything is fine. | |
/// | |
/// @remarks This does not necessarily mean an error handler was not called. An error handler can set the | |
/// error code to ztd::text::encoding_error::ok after performing corrective action: see | |
/// ztd::text::replacement_handler for an example. | |
////// | |
ok = 0x00, | |
////// | |
/// Input contains ill-formed sequences. This means there were available units of input to read, but what was | |
/// read resulted in an error. | |
////// | |
invalid_sequence = 0x01, | |
////// | |
/// Input contains incomplete sequences. This means that the input was exhausted, without finding an invalid | |
/// sequence, and therefore more input may be required. | |
/// | |
/// @remarks Depending on context, this may or may not be an error in your use case (e.g., reading part of an | |
/// incomplete network buffer and waiting for more). See ztd::text::incomplete_handler as a way to aid with | |
/// this use case. | |
////// | |
incomplete_sequence = 0x02, | |
////// | |
/// Output cannot receive the successfully encoded or decoded sequence. This means that, while there were no | |
/// invalid or incomplete sequences in the input, the output ran out of space to receive it. | |
/// | |
/// @remarks Provide a bigger storage area or guarantee that it meets the minimum required size for potential | |
/// output. This can be queried for an encoding by using ztd::text::max_code_points_v<the_encoding> for code | |
/// points, and ztd::text::max_code_units_v<the_encoding> for code units. | |
////// | |
insufficient_output_space = 0x03, | |
#if 0 | |
/* These error types are not used because they are too specific to Unicode. I suspect that some people will | |
find them useful for error reporting cases, but it does result in more checking for higher-level APIs. It's | |
best to leave them off, for now. */ | |
////// | |
/// Input contains overlong encoding sequence. This is specific to certain encodings, such as Unicode | |
/// Transformation Formats like UTF-8 where different sequences can end up encoding the same character but are | |
/// not allowed. | |
////// | |
invalid_sequence = 0x04, | |
////// | |
/// leading code unit is wrong | |
////// | |
invalid_sequence = 0x05, | |
////// | |
/// leading code units were correct, trailing code units were wrong | |
////// | |
invalid_sequence = 0x06 | |
#endif | |
}; | |
////// | |
/// @brief Converts an encoding_error to a string value. | |
/// | |
/// @returns A null-terminated string_view to the data. | |
/// | |
/// @remarks If a value outside of the allowed encoding_error is passed, then undefined behavior happens. | |
////// | |
inline constexpr ::std::string_view to_name(encoding_error __error_code) { | |
constexpr ::std::array<::std::string_view, 4> __translation { { "ok", "invalid_sequence", | |
"incomplete_sequence", "insufficient_output_space" } }; | |
return __translation[static_cast<::std::size_t>(__txt_detail::__to_underlying(__error_code))]; | |
} | |
namespace __txt_detail { | |
////// | |
/// @brief The encoding category for system_error-style exceptions and errors. | |
/// | |
/// @remarks This type is generally paired with a std::error_condition. | |
///// | |
class __encoding_category : public ::std::error_category { | |
virtual const char* name() const noexcept override { | |
return "encoding_error"; | |
} | |
virtual ::std::string message(int __untyped_error_code) const override { | |
encoding_error __error_code = static_cast<encoding_error>(__untyped_error_code); | |
switch (__error_code) { | |
case encoding_error::ok: | |
case encoding_error::incomplete_sequence: | |
case encoding_error::insufficient_output_space: | |
case encoding_error::invalid_sequence: { | |
::std::string_view __name = ::ztd::text::to_name(__error_code); | |
return ::std::string(__name.data(), __name.size()); | |
} | |
} | |
return "unrecognized untyped error code"; | |
} | |
virtual ::std::error_condition default_error_condition( | |
int __untyped_error_code) const noexcept override { | |
return ::std::error_condition(__untyped_error_code, *this); | |
} | |
}; | |
} // namespace __txt_detail | |
////// | |
/// @brief The system_error category type to be used with std::error_category-requiring errors. | |
/// | |
/// @remarks Not constexpr in general because of ABI shenanigans from the 2019 Belfast Meeting, where it did not | |
/// successfully pass through Incubator review. | |
////// | |
inline const ::std::error_category& encoding_category() { | |
static const __txt_detail::__encoding_category __category = __txt_detail::__encoding_category(); | |
return __category; | |
} | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
namespace std { | |
template <> | |
struct is_error_condition_enum<::ztd::text::encoding_error> : public ::std::true_type { }; | |
template <> | |
class hash<::ztd::text::encoding_error> { | |
private: | |
using _UnderlyingErrorType = ::std::underlying_type_t<::ztd::text::encoding_error>; | |
public: | |
::std::size_t operator()(::ztd::text::encoding_error __error_code) const noexcept( | |
noexcept(::std::hash<_UnderlyingErrorType> {}(static_cast<_UnderlyingErrorType>(__error_code)))) { | |
using _UnderlyingErrorType = ::std::underlying_type_t<::ztd::text::encoding_error>; | |
::std::hash<_UnderlyingErrorType> __hasher {}; | |
return __hasher(static_cast<_UnderlyingErrorType>(__error_code)); | |
} | |
}; | |
} // namespace std | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/encoding_error.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/reconstruct.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/reconstruct.types.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/subrange.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/range.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/adl.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/type_traits.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/reference_wrapper.hpp | |
#include <functional> | |
#include <utility> | |
#include <type_traits> | |
#include <memory> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _Ty> | |
class __reference_wrapper { | |
private: | |
using _Ref = ::std::add_lvalue_reference_t<_Ty>; | |
using _Ptr = ::std::add_pointer_t<_Ty>; | |
_Ptr __ptr; | |
public: | |
constexpr __reference_wrapper(_Ref __ref) noexcept : __ptr(::std::addressof(__ref)) { | |
} | |
constexpr operator _Ref() const noexcept { | |
return *__ptr; | |
} | |
constexpr _Ref get() const noexcept { | |
return *__ptr; | |
} | |
}; | |
template <typename _Ty> | |
__reference_wrapper(_Ty&) -> __reference_wrapper<_Ty>; | |
} // namespace __txt_detail | |
////// | |
/// @brief A subsitute for C++20's reference wrapper if the current @c std::reference_wrapper provided by the | |
/// standard library is not @c constexpr since it was only done then. | |
/// | |
////// | |
template <typename _Ty> | |
using reference_wrapper = | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_REFERENCE_WRAPPER_CONSTEXPR_I_) | |
::std::reference_wrapper<_Ty> | |
#else | |
::ztd::text::__txt_detail::__reference_wrapper<_Ty> | |
#endif | |
; | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/reference_wrapper.hpp | |
#include <type_traits> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _Type, typename = ::std::remove_cv_t<::std::remove_reference_t<_Type>>> | |
struct __unwrap_impl { | |
using type = _Type; | |
}; | |
template <typename _Dummy, typename _Type> | |
struct __unwrap_impl<_Dummy, ::std::reference_wrapper<_Type>> { | |
using type = ::std::add_lvalue_reference_t<_Type>; | |
}; | |
template <typename _Dummy, typename _Type> | |
struct __unwrap_impl<_Dummy, ::ztd::text::__txt_detail::__reference_wrapper<_Type>> { | |
using type = ::std::add_lvalue_reference_t<_Type>; | |
}; | |
template <typename _Type> | |
using __unwrap_t = typename __unwrap_impl<_Type>::type; | |
template <typename> | |
class __always_false : public ::std::integral_constant<bool, false> { }; | |
template <typename _Type, _Type> | |
class __always_false_constant : public __always_false<_Type> { }; | |
template <typename _Type, _Type _Val> | |
inline constexpr bool __always_false_constant_v = __always_false_constant<_Type, _Val>::value; | |
template <::std::size_t _Val> | |
using __always_false_index = __always_false_constant<::std::size_t, _Val>; | |
template <::std::size_t _Val> | |
inline constexpr bool __always_false_index_v = __always_false_index<_Val>::value; | |
template <typename _Type> | |
inline constexpr bool __always_false_v = __always_false<_Type>::value; | |
template <typename> | |
using __always_true = ::std::integral_constant<bool, true>; | |
template <typename _Type> | |
inline constexpr bool __always_true_v = __always_true<_Type>::value; | |
template <typename _Type> | |
using __remove_cvref = ::std::remove_cv<::std::remove_reference_t<_Type>>; | |
template <typename _Type> | |
using __remove_cvref_t = typename __remove_cvref<_Type>::type; | |
// clang-format off | |
template <typename _Type> | |
using __is_character = ::std::integral_constant<bool, | |
::std::is_same_v<_Type, char> || ::std::is_same_v<_Type, wchar_t> || | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_NATIVE_CHAR8_T_I_) | |
::std::is_same_v<_Type, char8_t> || | |
#endif | |
::std::is_same_v<_Type, ::ztd::text::uchar8_t> || | |
::std::is_same_v<_Type, unsigned char> || | |
::std::is_same_v<_Type, signed char> || | |
::std::is_same_v<_Type, char16_t> || | |
::std::is_same_v<_Type, char32_t> || | |
::std::is_same_v<_Type, ::ztd::text::unicode_code_point> || | |
::std::is_same_v<_Type, ::ztd::text::unicode_scalar_value> | |
>; | |
template <typename _Type> | |
using __is_char_traitable = ::std::integral_constant<bool, | |
::std::is_same_v<_Type, char> || ::std::is_same_v<_Type, wchar_t> || | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_NATIVE_CHAR8_T_I_) | |
::std::is_same_v<_Type, char8_t> || | |
#endif | |
::std::is_same_v<_Type, char16_t> || | |
::std::is_same_v<_Type, char32_t> || | |
::std::is_same_v<_Type, ::ztd::text::unicode_code_point> || | |
::std::is_same_v<_Type, ::ztd::text::unicode_scalar_value> | |
>; | |
// clang-format on | |
template <typename _Type> | |
inline constexpr bool __is_character_v = __is_character<_Type>::value; | |
template <typename _Type> | |
inline constexpr bool __is_char_traitable_v = __is_char_traitable<_Type>::value; | |
template <typename T, template <typename...> class Templ> | |
struct __is_specialization_of_impl : ::std::false_type { }; | |
template <typename... T, template <typename...> class Templ> | |
struct __is_specialization_of_impl<Templ<T...>, Templ> : ::std::true_type { }; | |
template <typename T, template <typename...> class Templ> | |
using __is_specialization_of = __is_specialization_of_impl<__remove_cvref_t<T>, Templ>; | |
template <typename T, template <typename...> class Templ> | |
inline constexpr bool __is_specialization_of_v = __is_specialization_of<T, Templ>::value; | |
template <typename _Default, typename _Void, template <typename...> typename _Op, typename... _Args> | |
class __detector { | |
public: | |
using value_t = ::std::false_type; | |
using type = _Default; | |
}; | |
template <typename _Default, template <typename...> typename _Op, typename... _Args> | |
class __detector<_Default, ::std::void_t<_Op<_Args...>>, _Op, _Args...> { | |
public: | |
using value_t = ::std::true_type; | |
using type = _Op<_Args...>; | |
}; | |
class __nonesuch { | |
public: | |
~__nonesuch() = delete; | |
__nonesuch(__nonesuch const&) = delete; | |
__nonesuch& operator=(__nonesuch const&) = delete; | |
}; | |
template <template <typename...> typename _Op, typename... _Args> | |
using __is_detected = typename __detector<__nonesuch, void, _Op, _Args...>::value_t; | |
template <template <typename...> typename _Op, typename... _Args> | |
inline constexpr bool __is_detected_v = __is_detected<_Op, _Args...>::value; | |
template <template <typename...> typename _Op, typename... _Args> | |
using __detected_t = typename __detector<__nonesuch, void, _Op, _Args...>::type; | |
template <typename _Default, template <typename...> typename _Op, typename... _Args> | |
using __detected_or = __detector<_Default, void, _Op, _Args...>; | |
template <typename _Type> | |
struct __type_identity { | |
using type = _Type; | |
}; | |
// useful for suppression | |
template <typename _Type> | |
using __type_identity_t = typename __type_identity<_Type>::type; | |
template <typename _Type, typename _SizeType = ::std::size_t> | |
using __detect_reserve_with_size_type | |
= decltype(::std::declval<_Type>().reserve(::std::declval<_SizeType>())); | |
template <typename _Left, typename _Right> | |
using __detect_equality_comparable = decltype(::std::declval<_Left>() == ::std::declval<_Right>()); | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/type_traits.hpp | |
#include <iterator> | |
#include <limits> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _It, typename = void> | |
struct __iterator_value_type_from_ref_or_void { | |
using type = void; | |
}; | |
template <typename _It> | |
struct __iterator_value_type_from_ref_or_void<_It, ::std::void_t<decltype(*::std::declval<_It&>())>> { | |
using type = ::std::remove_reference_t<decltype(*::std::declval<_It&>())>; | |
}; | |
template <typename _It, typename = void> | |
struct __iterator_value_type_or_fallback { | |
using type = typename __iterator_value_type_from_ref_or_void<_It>::type; | |
}; | |
template <typename _It> | |
struct __iterator_value_type_or_fallback<_It, | |
::std::void_t<typename ::std::iterator_traits<::std::remove_reference_t<_It>>::value_type>> { | |
using type = typename ::std::iterator_traits<::std::remove_reference_t<_It>>::value_type; | |
}; | |
template <typename _It, typename = void> | |
struct __iterator_reference_or_fallback { | |
using type = decltype(*::std::declval<_It&>()); | |
}; | |
template <typename _It> | |
struct __iterator_reference_or_fallback<_It, | |
::std::void_t<typename ::std::iterator_traits<::std::remove_reference_t<_It>>::reference>> { | |
using type = typename ::std::iterator_traits<::std::remove_reference_t<_It>>::reference; | |
}; | |
template <typename _It, typename = void> | |
struct __iterator_difference_type_or_fallback { | |
using type = ::std::ptrdiff_t; | |
}; | |
template <typename _It> | |
struct __iterator_difference_type_or_fallback<_It, | |
::std::void_t<typename ::std::iterator_traits<::std::remove_reference_t<_It>>::difference_type>> { | |
private: | |
using __maybe_void_type = | |
typename ::std::iterator_traits<::std::remove_reference_t<_It>>::difference_type; | |
public: | |
using type | |
= ::std::conditional_t<::std::is_void_v<__maybe_void_type>, ::std::ptrdiff_t, __maybe_void_type>; | |
}; | |
template <typename _It, typename = void> | |
struct __iterator_value_type_interception { | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_RANGES_I_) | |
using type = ::std::iter_value_t<_It>; | |
#else | |
using type = typename __iterator_value_type_or_fallback<::std::remove_reference_t<_It>>::type; | |
#endif | |
}; | |
template <typename _Container> | |
struct __iterator_value_type_interception<::std::back_insert_iterator<_Container>> { | |
using type = typename __remove_cvref_t<__unwrap_t<_Container>>::value_type; | |
}; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_RANGES_I_) | |
template <typename _It> | |
using __iterator_reference_t = ::std::iter_reference_t<_It>; | |
template <typename _It> | |
using __iterator_difference_type_t = ::std::iter_difference_t<_It>; | |
#else | |
template <typename _It> | |
using __iterator_reference_t = | |
typename __iterator_reference_or_fallback<::std::remove_reference_t<_It>>::type; | |
template <typename _It> | |
using __iterator_difference_type_t = | |
typename __iterator_difference_type_or_fallback<::std::remove_reference_t<_It>>::type; | |
#endif | |
template <typename _It> | |
using __iterator_value_type_t = typename __iterator_value_type_interception<_It>::type; | |
template <typename _It> | |
using __iterator_size_type_t | |
= ::std::make_signed_t<__iterator_difference_type_t<::std::remove_reference_t<_It>>>; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_RANGES_I_) | |
namespace __adl { | |
template <typename _Range> | |
constexpr auto __adl_begin(_Range&& __range) noexcept( | |
noexcept(::std::ranges::begin(::std::forward<_Range>(__range)))) | |
-> decltype(::std::ranges::begin(::std::forward<_Range>(__range))) { | |
return ::std::ranges::begin(::std::forward<_Range>(__range)); | |
} | |
template <typename _Range> | |
constexpr auto __adl_cbegin(_Range&& __range) noexcept( | |
noexcept(::std::ranges::cbegin(::std::forward<_Range>(__range)))) | |
-> decltype(::std::ranges::cbegin(::std::forward<_Range>(__range))) { | |
return ::std::ranges::cbegin(::std::forward<_Range>(__range)); | |
} | |
template <typename _Range> | |
constexpr auto __adl_rbegin(_Range&& __range) noexcept( | |
noexcept(::std::ranges::rbegin(::std::forward<_Range>(__range)))) | |
-> decltype(::std::ranges::rbegin(::std::forward<_Range>(__range))) { | |
return ::std::ranges::rbegin(::std::forward<_Range>(__range)); | |
} | |
template <typename _Range> | |
constexpr auto __adl_crbegin(_Range&& __range) noexcept( | |
noexcept(::std::ranges::crbegin(::std::forward<_Range>(__range)))) | |
-> decltype(::std::ranges::crbegin(::std::forward<_Range>(__range))) { | |
return ::std::ranges::crbegin(::std::forward<_Range>(__range)); | |
} | |
template <typename _Range> | |
constexpr auto __adl_end(_Range&& __range) noexcept( | |
noexcept(::std::ranges::end(::std::forward<_Range>(__range)))) | |
-> decltype(::std::ranges::end(::std::forward<_Range>(__range))) { | |
return ::std::ranges::end(::std::forward<_Range>(__range)); | |
} | |
template <typename _Range> | |
constexpr auto __adl_cend(_Range&& __range) noexcept( | |
noexcept(::std::ranges::cend(::std::forward<_Range>(__range)))) | |
-> decltype(::std::ranges::cend(::std::forward<_Range>(__range))) { | |
return ::std::ranges::cend(::std::forward<_Range>(__range)); | |
} | |
template <typename _Range> | |
constexpr auto __adl_rend(_Range&& __range) noexcept( | |
noexcept(::std::ranges::rend(::std::forward<_Range>(__range)))) | |
-> decltype(::std::ranges::rend(::std::forward<_Range>(__range))) { | |
return ::std::ranges::rend(::std::forward<_Range>(__range)); | |
} | |
template <typename _Range> | |
constexpr auto __adl_crend(_Range&& __range) noexcept( | |
noexcept(::std::ranges::crend(::std::forward<_Range>(__range)))) | |
-> decltype(::std::ranges::crend(::std::forward<_Range>(__range))) { | |
return ::std::ranges::crend(::std::forward<_Range>(__range)); | |
} | |
template <typename _Range> | |
constexpr auto __adl_data(_Range&& __range) noexcept( | |
noexcept(::std::ranges::data(::std::forward<_Range>(__range)))) | |
-> decltype(::std::ranges::data(::std::forward<_Range>(__range))) { | |
return ::std::ranges::data(::std::forward<_Range>(__range)); | |
} | |
template <typename _Range> | |
constexpr auto __adl_size(_Range&& __range) noexcept( | |
noexcept(::std::ranges::size(::std::forward<_Range>(__range)))) | |
-> decltype(::std::ranges::size(::std::forward<_Range>(__range))) { | |
return ::std::ranges::size(::std::forward<_Range>(__range)); | |
} | |
template <typename _Range> | |
constexpr auto __adl_ssize(_Range&& __range) noexcept( | |
noexcept(::std::ranges::ssize(::std::forward<_Range>(__range)))) | |
-> decltype(::std::ranges::ssize(::std::forward<_Range>(__range))) { | |
return ::std::ranges::ssize(::std::forward<_Range>(__range)); | |
} | |
template <typename _Range> | |
constexpr auto __adl_empty(_Range&& __range) noexcept( | |
noexcept(::std::ranges::empty(::std::forward<_Range>(__range)))) | |
-> decltype(::std::ranges::empty(::std::forward<_Range>(__range))) { | |
return ::std::ranges::empty(::std::forward<_Range>(__range)); | |
} | |
template <typename _It> | |
constexpr auto __adl_iter_move(_It&& __it) noexcept( | |
noexcept(::std::ranges::iter_move(::std::forward<_It>(__it)))) | |
-> decltype(::std::ranges::iter_move(::std::forward<_It>(__it))) { | |
return ::std::ranges::iter_move(::std::forward<_It>(__it)); | |
} | |
template <typename _ItLeft, typename _ItRight> | |
constexpr auto __adl_iter_swap(_ItLeft&& __left, _ItRight&& __right) noexcept(noexcept( | |
::std::ranges::iter_swap(::std::forward<_ItLeft>(__left), ::std::forward<_ItRight>(__right)))) | |
-> decltype(::std::ranges::iter_swap( | |
::std::forward<_ItLeft>(__left), ::std::forward<_ItRight>(__right))) { | |
::std::ranges::iter_swap(::std::forward<_ItLeft>(__left), ::std::forward<_ItRight>(__right)); | |
} | |
} // namespace __adl | |
#else | |
// Blessed Overload Overlord Xeo, | |
// may his name be praised. | |
namespace __adl { | |
// using ::std::cdata; | |
using ::std::data; | |
using ::std::empty; | |
using ::std::size; | |
using ::std::begin; | |
using ::std::cbegin; | |
using ::std::crbegin; | |
using ::std::rbegin; | |
using ::std::cend; | |
using ::std::crend; | |
using ::std::end; | |
using ::std::rend; | |
using ::std::iter_swap; | |
template <typename _Range, | |
::std::enable_if_t<::std::is_rvalue_reference_v<_Range> && !::std::is_const_v<_Range>>* = nullptr> | |
constexpr auto begin(_Range&& __range) -> decltype(::std::move(__range).begin()) { | |
return ::std::move(__range).begin(); | |
} | |
template <typename _Range> | |
using __detect_begin = decltype(begin(::std::declval<_Range>())); | |
template <typename _Range> | |
using __detect_cbegin = decltype(rbegin(::std::declval<_Range>())); | |
template <typename _Range> | |
using __detect_rbegin = decltype(cbegin(::std::declval<_Range>())); | |
template <typename _Range> | |
using __detect_crbegin = decltype(crbegin(::std::declval<_Range>())); | |
template <typename _Range> | |
using __detect_end = decltype(end(::std::declval<_Range>())); | |
template <typename _Range> | |
using __detect_cend = decltype(rend(::std::declval<_Range>())); | |
template <typename _Range> | |
using __detect_rend = decltype(cend(::std::declval<_Range>())); | |
template <typename _Range> | |
using __detect_crend = decltype(crend(::std::declval<_Range>())); | |
template <typename _Range> | |
constexpr bool __adl_begin_noexcept() noexcept { | |
if constexpr (::std::is_array_v<__remove_cvref_t<_Range>>) { | |
return true; | |
} | |
else if constexpr (__is_detected_v<__detect_begin, _Range>) { | |
return noexcept(begin(::std::declval<_Range>())); | |
} | |
else { | |
return noexcept(::std::declval<_Range>().begin()); | |
} | |
} | |
template <typename _Range> | |
constexpr bool __adl_cbegin_noexcept() noexcept { | |
if constexpr (::std::is_array_v<__remove_cvref_t<_Range>>) { | |
return true; | |
} | |
else if constexpr (__is_detected_v<__detect_cbegin, _Range>) { | |
return noexcept(cbegin(::std::declval<_Range>())); | |
} | |
else { | |
return noexcept(::std::declval<_Range>().cbegin()); | |
} | |
} | |
template <typename _Range> | |
constexpr bool __adl_rbegin_noexcept() noexcept { | |
if constexpr (::std::is_array_v<__remove_cvref_t<_Range>>) { | |
return true; | |
} | |
else if constexpr (__is_detected_v<__detect_rbegin, _Range>) { | |
return noexcept(rbegin(::std::declval<_Range>())); | |
} | |
else { | |
return noexcept(::std::declval<_Range>().rbegin()); | |
} | |
} | |
template <typename _Range> | |
constexpr bool __adl_crbegin_noexcept() noexcept { | |
if constexpr (::std::is_array_v<__remove_cvref_t<_Range>>) { | |
return true; | |
} | |
else if constexpr (__is_detected_v<__detect_crbegin, _Range>) { | |
return noexcept(crbegin(::std::declval<_Range>())); | |
} | |
else { | |
return noexcept(::std::declval<_Range>().crbegin()); | |
} | |
} | |
template <typename _Range> | |
constexpr bool __adl_end_noexcept() noexcept { | |
if constexpr (::std::is_array_v<__remove_cvref_t<_Range>>) { | |
return true; | |
} | |
else if constexpr (__is_detected_v<__detect_end, _Range>) { | |
return noexcept(end(::std::declval<_Range>())); | |
} | |
else { | |
return noexcept(::std::declval<_Range>().end()); | |
} | |
} | |
template <typename _Range> | |
constexpr bool __adl_cend_noexcept() noexcept { | |
if constexpr (::std::is_array_v<__remove_cvref_t<_Range>>) { | |
return true; | |
} | |
else if constexpr (__is_detected_v<__detect_cend, _Range>) { | |
return noexcept(cend(::std::declval<_Range>())); | |
} | |
else { | |
return noexcept(::std::declval<_Range>().cend()); | |
} | |
} | |
template <typename _Range> | |
constexpr bool __adl_rend_noexcept() noexcept { | |
if constexpr (::std::is_array_v<__remove_cvref_t<_Range>>) { | |
return true; | |
} | |
else if constexpr (__is_detected_v<__detect_rend, _Range>) { | |
return noexcept(rend(::std::declval<_Range>())); | |
} | |
else { | |
return noexcept(::std::declval<_Range>().rend()); | |
} | |
} | |
template <typename _Range> | |
constexpr bool __adl_crend_noexcept() noexcept { | |
if constexpr (::std::is_array_v<__remove_cvref_t<_Range>>) { | |
return true; | |
} | |
else if constexpr (__is_detected_v<__detect_crend, _Range>) { | |
return noexcept(crend(::std::declval<_Range>())); | |
} | |
else { | |
return noexcept(::std::declval<_Range>().crend()); | |
} | |
} | |
template <typename _It> | |
constexpr bool __iter_move_noexcept() noexcept { | |
if constexpr (::std::is_lvalue_reference_v<decltype(*::std::declval<_It>())>) { | |
return noexcept(::std::move(*::std::declval<_It>())); | |
} | |
else { | |
return noexcept(*::std::declval<_It>()); | |
} | |
} | |
template <typename _It> | |
constexpr auto iter_move(_It&& __it) noexcept(__iter_move_noexcept<_It>()) | |
-> ::std::conditional_t<::std::is_lvalue_reference_v<decltype(*::std::forward<_It>(__it))>, | |
decltype(::std::move(*::std::forward<_It>(__it))), decltype(*::std::forward<_It>(__it))> { | |
if constexpr (::std::is_lvalue_reference_v<decltype(*::std::forward<_It>(__it))>) { | |
return ::std::move(*::std::forward<_It>(__it)); | |
} | |
else { | |
return *::std::forward<_It>(__it); | |
} | |
} | |
template <typename _Range> | |
constexpr decltype(auto) __adl_begin(_Range&& __range) noexcept(__adl_begin_noexcept<_Range>()) { | |
if constexpr (::std::is_array_v<__remove_cvref_t<_Range>>) { | |
return (__range + 0); | |
} | |
else if constexpr (__is_detected_v<__detect_begin, _Range>) { | |
return begin(::std::forward<_Range>(__range)); | |
} | |
else { | |
return ::std::forward<_Range>(__range).begin(); | |
} | |
} | |
template <typename _Range> | |
constexpr decltype(auto) __adl_cbegin(_Range&& __range) noexcept(__adl_cbegin_noexcept<_Range>()) { | |
if constexpr (::std::is_array_v<__remove_cvref_t<_Range>>) { | |
return (__range + 0); | |
} | |
else if constexpr (__is_detected_v<__detect_cbegin, _Range>) { | |
return cbegin(::std::forward<_Range>(__range)); | |
} | |
else { | |
return ::std::forward<_Range>(__range).cbegin(); | |
} | |
} | |
template <typename _Range> | |
constexpr decltype(auto) __adl_rbegin(_Range&& __range) noexcept(__adl_rbegin_noexcept<_Range>()) { | |
if constexpr (::std::is_array_v<__remove_cvref_t<_Range>>) { | |
return ::std::make_reverse_iterator(__range + ::std::extent_v<__remove_cvref_t<_Range>>); | |
} | |
else if constexpr (__is_detected_v<__detect_rbegin, _Range>) { | |
return rbegin(::std::forward<_Range>(__range)); | |
} | |
else { | |
return ::std::forward<_Range>(__range).rbegin(); | |
} | |
} | |
template <typename _Range> | |
constexpr decltype(auto) __adl_crbegin(_Range&& __range) noexcept(__adl_crbegin_noexcept<_Range>()) { | |
if constexpr (::std::is_array_v<__remove_cvref_t<_Range>>) { | |
return ::std::make_reverse_iterator(__range + ::std::extent_v<__remove_cvref_t<_Range>>); | |
} | |
else if constexpr (__is_detected_v<__detect_crbegin, _Range>) { | |
return crbegin(::std::forward<_Range>(__range)); | |
} | |
else { | |
return ::std::forward<_Range>(__range).crbegin(); | |
} | |
} | |
template <typename _Range> | |
constexpr decltype(auto) __adl_end(_Range&& __range) noexcept(__adl_end_noexcept<_Range>()) { | |
if constexpr (::std::is_array_v<__remove_cvref_t<_Range>>) { | |
return (__range + ::std::extent_v<__remove_cvref_t<_Range>>); | |
} | |
else if constexpr (__is_detected_v<__detect_end, _Range>) { | |
return end(::std::forward<_Range>(__range)); | |
} | |
else { | |
return ::std::forward<_Range>(__range).end(); | |
} | |
} | |
template <typename _Range> | |
constexpr decltype(auto) __adl_cend(_Range&& __range) noexcept(__adl_cend_noexcept<_Range>()) { | |
if constexpr (::std::is_array_v<__remove_cvref_t<_Range>>) { | |
return (__range + ::std::extent_v<__remove_cvref_t<_Range>>); | |
} | |
else if constexpr (__is_detected_v<__detect_cend, _Range>) { | |
return cend(::std::forward<_Range>(__range)); | |
} | |
else { | |
return ::std::forward<_Range>(__range).cend(); | |
} | |
} | |
template <typename _Range> | |
constexpr decltype(auto) __adl_rend(_Range&& __range) noexcept(__adl_rend_noexcept<_Range>()) { | |
if constexpr (::std::is_array_v<__remove_cvref_t<_Range>>) { | |
return ::std::make_reverse_iterator(__range + 0); | |
} | |
else if constexpr (__is_detected_v<__detect_rend, _Range>) { | |
return rend(::std::forward<_Range>(__range)); | |
} | |
else { | |
return ::std::forward<_Range>(__range).rend(); | |
} | |
} | |
template <typename _Range> | |
constexpr decltype(auto) __adl_crend(_Range&& __range) noexcept(__adl_crend_noexcept<_Range>()) { | |
if constexpr (::std::is_array_v<__remove_cvref_t<_Range>>) { | |
return ::std::make_reverse_iterator(__range + 0); | |
} | |
else if constexpr (__is_detected_v<__detect_crend, _Range>) { | |
return crend(::std::forward<_Range>(__range)); | |
} | |
else { | |
return ::std::forward<_Range>(__range).crend(); | |
} | |
} | |
template <typename _Range> | |
constexpr auto __adl_data(_Range&& __range) noexcept(noexcept(data(::std::forward<_Range>(__range)))) | |
-> decltype(data(::std::forward<_Range>(__range))) { | |
return data(::std::forward<_Range>(__range)); | |
} | |
template <typename _Range> | |
constexpr auto __adl_size(_Range&& __range) noexcept(noexcept(size(::std::forward<_Range>(__range)))) | |
-> decltype(size(::std::forward<_Range>(__range))) { | |
return size(::std::forward<_Range>(__range)); | |
} | |
template <typename _Range> | |
constexpr auto __adl_ssize(_Range&& __range) noexcept( | |
noexcept(static_cast<__iterator_difference_type_t<_Range>>(size(::std::forward<_Range>(__range))))) | |
-> ::std::enable_if_t<::std::numeric_limits<__iterator_difference_type_t<_Range>>::digits | |
>= ::std::numeric_limits<::std::ptrdiff_t>::digits, | |
decltype(static_cast<__iterator_difference_type_t<_Range>>( | |
size(::std::forward<_Range>(__range))))> { | |
return static_cast<__iterator_difference_type_t<_Range>>(size(::std::forward<_Range>(__range))); | |
} | |
template <typename _Range> | |
constexpr auto __adl_ssize(_Range&& __range) noexcept( | |
noexcept(static_cast<::std::ptrdiff_t>(__adl_size(::std::forward<_Range>(__range))))) | |
-> ::std::enable_if_t<(::std::numeric_limits<__iterator_difference_type_t<_Range>>::digits | |
< ::std::numeric_limits<::std::ptrdiff_t>::digits), | |
decltype(static_cast<::std::ptrdiff_t>(__adl_size(::std::forward<_Range>(__range))))> { | |
return static_cast<::std::ptrdiff_t>(__adl_size(::std::forward<_Range>(__range))); | |
} | |
template <typename _Range> | |
constexpr auto __adl_empty(_Range&& __range) noexcept(noexcept(empty(::std::forward<_Range>(__range)))) | |
-> decltype(empty(::std::forward<_Range>(__range))) { | |
return empty(::std::forward<_Range>(__range)); | |
} | |
template <typename _It> | |
constexpr auto __adl_iter_move(_It&& __it) noexcept(noexcept(::std::move(*::std::forward<_It>(__it)))) | |
-> decltype(::std::move(*::std::forward<_It>(__it))) { | |
return ::std::move(*::std::forward<_It>(__it)); | |
} | |
template <typename _ItLeft, typename _ItRight> | |
constexpr auto __adl_iter_swap(_ItLeft&& __left, _ItRight&& __right) noexcept( | |
noexcept(iter_swap(::std::forward<_ItLeft>(__left), ::std::forward<_ItRight>(__right)))) | |
-> decltype(iter_swap(::std::forward<_ItLeft>(__left), ::std::forward<_ItRight>(__right))) { | |
iter_swap(::std::forward<_ItLeft>(__left), ::std::forward<_ItRight>(__right)); | |
} | |
} // namespace __adl | |
#endif | |
template <typename _Range> | |
using __detect_adl_size | |
= decltype(__adl::__adl_size(::std::declval<::std::add_lvalue_reference_t<_Range>>())); | |
template <typename _Range> | |
using __detect_adl_empty | |
= decltype(__adl::__adl_empty(::std::declval<::std::add_lvalue_reference_t<_Range>>())); | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/adl.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/iterator.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/memory.hpp | |
#include <memory> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _Type, typename = void> | |
struct __operator_arrow { }; | |
template <typename _Type> | |
struct __operator_arrow<_Type, ::std::void_t<decltype(::std::declval<_Type&>().operator->())>> { | |
using type = typename __operator_arrow<decltype(::std::declval<_Type&>().operator->())>::type; | |
}; | |
template <typename _Type> | |
using __operator_arrow_t = typename __operator_arrow<_Type>::type; | |
template <typename _Type, typename = void> | |
struct __is_operator_arrowable : public ::std::integral_constant<bool, ::std::is_pointer_v<_Type>> { }; | |
template <typename _Type> | |
struct __is_operator_arrowable<_Type, ::std::void_t<decltype(::std::declval<_Type&>().operator->())>> | |
: public ::std::integral_constant<bool, | |
__is_operator_arrowable<decltype(::std::declval<_Type&>().operator->())>::value> { }; | |
template <typename _Type> | |
using __detect_std_pointer_traits_to_address | |
= decltype(::std::pointer_traits<_Type>::to_address(::std::declval<_Type&>())); | |
template <typename _Type> | |
inline constexpr bool __is_operator_arrowable_v = __is_operator_arrowable<_Type>::value; | |
template <typename _Type, typename = void> | |
struct __is_to_addressable { | |
inline static constexpr bool value | |
= (::std::is_pointer_v< | |
_Type> && !::std::is_function_v<::std::remove_reference_t<::std::remove_pointer_t<_Type>>>) | |
|| __is_operator_arrowable_v<::std::remove_reference_t<_Type>>; | |
}; | |
template <typename _Type> | |
struct __is_to_addressable<_Type, ::std::void_t<typename __remove_cvref_t<_Type>::element_type>> | |
: public ::std::integral_constant<bool, | |
__is_detected_v<__detect_std_pointer_traits_to_address, | |
_Type> || (!::std::is_function_v<::std::remove_reference_t<_Type>> && __is_operator_arrowable_v<::std::remove_reference_t<_Type>>)> { | |
}; | |
template <typename _Type> | |
inline constexpr bool __is_to_addressable_v = __is_to_addressable<_Type>::value; | |
namespace __adl { | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_TO_ADDRESS_I_) | |
template <typename _Type> | |
constexpr auto __adl_to_address(_Type&& __ptr_like) noexcept( | |
noexcept(::std::to_address(::std::forward<_Type>(__ptr_like)))) | |
-> decltype(::std::to_address(::std::forward<_Type>(__ptr_like))) { | |
return ::std::to_address(::std::forward<_Type>(__ptr_like)); | |
} | |
#else | |
template <typename _Type> | |
constexpr _Type* __adl_to_address(_Type* __ptr) noexcept { | |
static_assert(!::std::is_function_v<_Type>, "the pointer shall not be function pointer type"); | |
return __ptr; | |
} | |
template <typename _Pointer, ::std::enable_if_t<!::std::is_pointer_v<_Pointer>>* = nullptr> | |
auto __adl_to_address(_Pointer& p) noexcept { | |
if constexpr (__is_detected_v<__detect_std_pointer_traits_to_address, _Pointer>) { | |
return ::std::pointer_traits<_Pointer>::to_address(p); | |
} | |
else { | |
return __adl_to_address(p.operator->()); | |
} | |
} | |
#endif | |
} // namespace __adl | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/memory.hpp | |
#include <iterator> | |
#include <type_traits> | |
#include <utility> | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_RANGES_I_) | |
#include <ranges> | |
#endif | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
class __contiguous_iterator_tag : public ::std::random_access_iterator_tag { }; | |
} // namespace __txt_detail | |
////// | |
/// @brief Either a typedef or a polyfill of the contiguous iterator tag, only standardized in C++20. | |
////// | |
using contiguous_iterator_tag = | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_CONTIGUOUS_ITERATOR_TAG_I_) | |
::std::contiguous_iterator_tag; | |
#else | |
__txt_detail::__contiguous_iterator_tag; | |
#endif | |
namespace __txt_detail { | |
template <typename _Type, typename... _Args> | |
using __detect_next = decltype(::std::declval<_Type>().next(::std::declval<_Args>()...)); | |
template <typename _Type, typename... _Args> | |
using __detect_prev = decltype(::std::declval<_Type>().next(::std::declval<_Args>()...)); | |
template <typename _Type, typename... _Args> | |
using __detect_advance = decltype(::std::declval<_Type>().advance(::std::declval<_Args>()...)); | |
template <typename _Type, typename... _Args> | |
using __detect_recede = decltype(::std::declval<_Type>().recede(::std::declval<_Args>()...)); | |
template <typename _Type> | |
using __detect_lvalue_increment = decltype(++::std::declval<_Type&>()); | |
template <typename _Type> | |
using __detect_lvalue_decrement = decltype(--::std::declval<_Type&>()); | |
template <typename _It, typename _Sen, typename = void> | |
struct __is_distance_operable : ::std::false_type { }; | |
template <typename _It, typename _Sen> | |
struct __is_distance_operable<_It, _Sen, | |
::std::void_t<decltype(::std::declval<_Sen>() - ::std::declval<_It>())>> | |
: ::std::integral_constant<bool, | |
::std::is_convertible_v<decltype(::std::declval<_Sen>() - ::std::declval<_It>()), | |
__iterator_difference_type_t<_It>>> { }; | |
template <typename _It, typename _Sen> | |
inline constexpr bool __is_distance_operable_v = __is_distance_operable<_It, _Sen>::value; | |
template <typename _It, typename = void> | |
struct __iterator_category_failure { | |
using type = ::std::conditional_t<::std::is_pointer_v<__remove_cvref_t<_It>>, contiguous_iterator_tag, | |
::std::output_iterator_tag>; | |
}; | |
template <typename _It> | |
struct __iterator_category_failure<_It, | |
::std::void_t<typename ::std::remove_reference_t<_It>::iterator_category>> { | |
using type = typename ::std::remove_reference_t<_It>::iterator_category; | |
}; | |
template <typename _It, typename = void> | |
struct __iterator_category_or_fallback { | |
using type = typename __iterator_category_failure<_It>::type; | |
}; | |
template <typename _It> | |
struct __iterator_category_or_fallback<_It, | |
::std::void_t<typename ::std::iterator_traits<::std::remove_reference_t<_It>>::iterator_category>> { | |
using type = typename ::std::iterator_traits<::std::remove_reference_t<_It>>::iterator_category; | |
}; | |
template <typename _It, typename = void> | |
struct __iterator_concept_failure { | |
using type = ::std::conditional_t<::std::is_pointer_v<__remove_cvref_t<_It>>, contiguous_iterator_tag, | |
::std::output_iterator_tag>; | |
}; | |
template <typename _It> | |
struct __iterator_concept_failure<_It, | |
::std::void_t<typename ::std::remove_reference_t<_It>::iterator_concept>> { | |
using type = typename ::std::remove_reference_t<_It>::iterator_concept; | |
}; | |
template <typename _It, typename = void> | |
struct __iterator_concept_or_fallback { | |
using type = typename __iterator_concept_failure<_It>::type; | |
}; | |
template <typename _It> | |
struct __iterator_concept_or_fallback<_It, | |
::std::void_t<typename ::std::iterator_traits<::std::remove_reference_t<_It>>::iterator_concept>> { | |
using type = typename ::std::iterator_traits<::std::remove_reference_t<_It>>::iterator_concept; | |
}; | |
template <typename _It, typename = void> | |
struct __iterator_category_or_concept_or_fallback { | |
private: | |
using _MaybeType = typename __iterator_category_or_fallback<_It>::type; | |
public: | |
using type = ::std::conditional_t<::std::is_same_v<_MaybeType, ::std::output_iterator_tag>, | |
typename __iterator_concept_or_fallback<__remove_cvref_t<_It>>::type, _MaybeType>; | |
}; | |
template <typename _It> | |
struct __iterator_category_or_concept_or_fallback<_It, | |
::std::void_t<typename ::std::iterator_traits<::std::remove_reference_t<_It>>::iterator_category>> { | |
using type = typename ::std::iterator_traits<::std::remove_reference_t<_It>>::iterator_category; | |
}; | |
template <typename _It, typename = void> | |
struct __iterator_concept_or_category_or_fallback { | |
private: | |
using _MaybeType = typename __iterator_concept_or_fallback<_It>::type; | |
public: | |
using type = ::std::conditional_t<::std::is_same_v<_MaybeType, ::std::output_iterator_tag>, | |
typename __iterator_category_or_fallback<__remove_cvref_t<_It>>::type, _MaybeType>; | |
}; | |
template <typename _It> | |
struct __iterator_concept_or_category_or_fallback<_It, | |
::std::void_t<typename ::std::iterator_traits<::std::remove_reference_t<_It>>::iterator_concept>> { | |
using type = typename ::std::iterator_traits<::std::remove_reference_t<_It>>::iterator_concept; | |
}; | |
template <typename _It, typename = void> | |
struct __iterator_pointer_or_fallback { | |
private: | |
using _Reference = __iterator_reference_t<::std::remove_reference_t<_It>>; | |
public: | |
using type = ::std::conditional_t<::std::is_reference_v<_Reference>, | |
::std::add_pointer_t<::std::remove_reference_t<_Reference>>, void>; | |
}; | |
template <typename _It> | |
struct __iterator_pointer_or_fallback<_It, | |
::std::void_t<typename ::std::iterator_traits<::std::remove_reference_t<_It>>::pointer>> { | |
using type = typename ::std::iterator_traits<::std::remove_reference_t<_It>>::pointer; | |
}; | |
template <typename _It> | |
using __iterator_rvalue_reference_t = decltype(__adl::__adl_iter_move(::std::declval<_It&>())); | |
template <typename _It> | |
using __iterator_pointer_t = typename __iterator_pointer_or_fallback<::std::remove_reference_t<_It>>::type; | |
template <typename _It> | |
using __iterator_category_t = | |
typename __iterator_category_or_concept_or_fallback<::std::remove_reference_t<_It>>::type; | |
template <typename _It> | |
using __iterator_concept_or_fallback_t = | |
typename __iterator_concept_or_category_or_fallback<::std::remove_reference_t<_It>>::type; | |
template <typename _It> | |
using __iterator_concept_t = __iterator_concept_or_fallback_t<_It>; | |
template <typename _Tag, typename _It> | |
inline constexpr bool __is_iterator_concept_or_better_v | |
= ::std::is_base_of_v<_Tag, __iterator_concept_t<_It>>; | |
template <typename _It> | |
inline constexpr bool __is_iterator_contiguous_iterator_v | |
= ( | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_CONTIGUOUS_ITERATOR_TAG_I_) | |
__is_iterator_concept_or_better_v<contiguous_iterator_tag, _It>) | |
|| (__is_iterator_concept_or_better_v<contiguous_iterator_tag, _It> && | |
#else | |
::std::is_pointer_v<_It> && | |
#endif | |
__is_to_addressable_v< | |
_It> && ::std::is_lvalue_reference_v<__iterator_reference_t<::std::remove_reference_t<_It>>>); | |
template <typename _It> | |
inline constexpr bool __is_iterator_input_iterator_v | |
= ::std::is_same_v<::std::input_iterator_tag, __iterator_concept_t<_It>>; | |
template <typename _It> | |
inline constexpr bool __is_iterator_output_iterator_v | |
= ::std::is_same_v<::std::output_iterator_tag, __iterator_concept_t<_It>>; | |
template <typename _It> | |
inline constexpr bool __is_iterator_input_or_output_iterator_v | |
= __is_iterator_input_iterator_v<_It> || __is_iterator_output_iterator_v<_It>; | |
template <typename _It, typename _Sen> | |
inline constexpr bool __is_sized_sentinel_for_v = __is_distance_operable_v<_It, _Sen>; | |
template <typename _It> | |
constexpr auto __dereference(_It&& __it) noexcept(noexcept(*::std::forward<_It>(__it))) | |
-> decltype(*::std::forward<_It>(__it)) { | |
return *::std::forward<_It>(__it); | |
} | |
template <typename _It, typename... _Args> | |
constexpr bool __advance_noexcept() noexcept { | |
if constexpr (__is_detected_v<__detect_advance, _It, _Args...>) { | |
return noexcept(::std::declval<_It>().advance(::std::declval<_Args>()...)); | |
} | |
else { | |
return noexcept(++::std::declval<::std::add_lvalue_reference_t<::std::remove_reference_t<_It>>>()); | |
} | |
} | |
template <typename _It, typename... _Args> | |
constexpr bool __recede_noexcept() noexcept { | |
if constexpr (__is_detected_v<__detect_recede, _It, _Args...>) { | |
return noexcept(::std::declval<_It>().recede(::std::declval<_Args>()...)); | |
} | |
else { | |
return noexcept(--::std::declval<::std::add_lvalue_reference_t<::std::remove_reference_t<_It>>>()); | |
} | |
} | |
template <typename _It> | |
constexpr _It&& __advance(_It&& __it) noexcept(__advance_noexcept<_It>()) { | |
if constexpr (__is_detected_v<__detect_advance, _It>) { | |
::std::forward<_It>(__it).advance(); | |
} | |
else { | |
++__it; | |
} | |
return ::std::forward<_It>(__it); | |
} | |
template <typename _It, typename _Diff> | |
constexpr _It&& __advance(_It&& __it, _Diff __diff) noexcept(__advance_noexcept<_It, _Diff>()) { | |
if constexpr (__is_detected_v<__detect_advance, _It, _Diff>) { | |
::std::forward<_It>(__it).advance(__diff); | |
} | |
else { | |
if constexpr (__is_iterator_concept_or_better_v<::std::random_access_iterator_tag, | |
__remove_cvref_t<_It>>) { | |
__it += __diff; | |
} | |
else { | |
for (; __diff > 0; --__diff) { | |
++__it; | |
} | |
} | |
} | |
return ::std::forward<_It>(__it); | |
} | |
template <typename _It> | |
constexpr _It&& __recede(_It&& __it) noexcept(__recede_noexcept<_It>()) { | |
if constexpr (__is_detected_v<__detect_recede, _It>) { | |
::std::forward<_It>(__it).recede(); | |
} | |
else { | |
--__it; | |
} | |
return ::std::forward<_It>(__it); | |
} | |
template <typename _It, typename _Diff> | |
constexpr _It&& __recede(_It&& __it, _Diff __diff) noexcept(__recede_noexcept<_It, _Diff>()) { | |
if constexpr (__is_detected_v<__detect_recede, _It, _Diff>) { | |
::std::forward<_It>(__it).recede(__diff); | |
} | |
else { | |
if constexpr (__is_iterator_concept_or_better_v<::std::random_access_iterator_tag, | |
__remove_cvref_t<_It>>) { | |
__it -= __diff; | |
} | |
else { | |
for (; __diff > 0; --__diff) { | |
--__it; | |
} | |
} | |
return ::std::forward<_It>(__it); | |
} | |
} | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/iterator.hpp | |
#include <iterator> | |
#include <type_traits> | |
#include <utility> | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_RANGES_I_) | |
#include <ranges> | |
#endif | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_RANGES_I_) | |
template <typename _Range> | |
using __range_iterator_t = ::std::ranges::iterator_t<_Range>; | |
template <typename _Range> | |
using __range_sentinel_t = ::std::ranges::sentinel_t<_Range>; | |
template <typename _Range> | |
using __range_value_type_t = ::std::ranges::range_value_t<_Range>; | |
template <typename _Range> | |
using __range_reference_t = ::std::ranges::range_reference_t<_Range>; | |
template <typename _Range> | |
using __range_rvalue_reference_t = ::std::ranges::range_rvalue_reference_t<_Range>; | |
template <typename _Range> | |
using __range_difference_type_t = ::std::ranges::range_difference_t<_Range>; | |
template <typename _Range> | |
using __range_size_type_t = ::std::ranges::range_size_t<_Range>; | |
#else | |
template <typename _Range> | |
using __range_iterator_t = ::std::remove_reference_t<decltype( | |
__adl::__adl_begin(::std::declval<::std::add_lvalue_reference_t<_Range>>()))>; | |
template <typename _Range> | |
using __range_sentinel_t = ::std::remove_reference_t<decltype( | |
__adl::__adl_end(::std::declval<::std::add_lvalue_reference_t<_Range>>()))>; | |
template <typename _Range> | |
using __range_value_type_t = __iterator_value_type_t<__range_iterator_t<_Range>>; | |
template <typename _Range> | |
using __range_reference_t = __iterator_reference_t<__range_iterator_t<_Range>>; | |
template <typename _Range> | |
using __range_rvalue_reference_t = __iterator_rvalue_reference_t<__range_iterator_t<_Range>>; | |
template <typename _Range> | |
using __range_difference_type_t = __iterator_difference_type_t<__range_iterator_t<_Range>>; | |
template <typename _Range> | |
using __range_size_type_t = __iterator_size_type_t<__range_iterator_t<_Range>>; | |
#endif | |
template <typename _Range> | |
using __range_const_iterator_t | |
= decltype(__adl::__adl_cbegin(::std::declval<::std::add_lvalue_reference_t<_Range>>())); | |
template <typename _Range> | |
using __range_const_sentinel_t | |
= decltype(__adl::__adl_cend(::std::declval<::std::add_lvalue_reference_t<_Range>>())); | |
template <typename _Range> | |
using __range_pointer_t = __iterator_pointer_t<__range_iterator_t<_Range>>; | |
template <typename _Range> | |
using __range_iterator_category_t = __iterator_category_t<__range_iterator_t<_Range>>; | |
template <typename _Range> | |
using __range_iterator_concept_t = __iterator_concept_t<__range_iterator_t<_Range>>; | |
template <typename _Tag, typename _Range> | |
inline constexpr bool __is_range_iterator_concept_or_better_v | |
= ::std::is_base_of_v<_Tag, __range_iterator_concept_t<_Range>>; | |
template <typename _Range> | |
inline constexpr bool __is_range_input_or_output_range_v | |
= __is_iterator_input_or_output_iterator_v<__range_iterator_t<_Range>>; | |
template <typename _Range> | |
inline constexpr bool __is_range_contiguous_range_v | |
= __is_iterator_contiguous_iterator_v<__range_iterator_t<_Range>>; | |
template <typename _Range> | |
inline constexpr bool __is_sized_range_v | |
= __is_sized_sentinel_for_v<__range_iterator_t<_Range>, __range_sentinel_t<_Range>>; | |
template <typename _Range, typename _Element> | |
using __detect_push_back = decltype(::std::declval<_Range>().push_back(::std::declval<_Element>())); | |
template <typename _Range, typename _IterFirst, typename _IterLast = _IterFirst> | |
using __detect_insert_bulk | |
= decltype(::std::declval<_Range>().insert(__adl::__adl_begin(::std::declval<_Range>()), | |
::std::declval<_IterFirst>(), ::std::declval<_IterLast>())); | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/range.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/empty_state.hpp | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
class __empty_state { }; | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/empty_state.hpp | |
#include <iterator> | |
#include <utility> | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_RANGES_I_) | |
#include <ranges> | |
#endif | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_support Support Classes | |
/// @{ | |
////// | |
namespace __txt_detail { | |
using __size_mark = __empty_state; | |
////// | |
/// @brief An enumeration that helps determine whether a subrange has size information or not. | |
/// | |
////// | |
enum class __subrange_kind : bool { | |
////// | |
/// @brief Does not have a size (or does not have a size that can be computed in O(1)). | |
/// | |
////// | |
unsized, | |
////// | |
/// @brief Has a size that can be computed in O(1). | |
/// | |
////// | |
sized | |
}; | |
template <typename _SizeType, bool _Store> | |
struct __subrange_size { | |
constexpr __subrange_size() noexcept { | |
} | |
}; | |
template <typename _SizeType> | |
struct __subrange_size<_SizeType, true> { | |
_SizeType _M_size; | |
constexpr __subrange_size() noexcept : _M_size(static_cast<_SizeType>(0)) { | |
} | |
constexpr __subrange_size(_SizeType&& __size) noexcept(::std::is_nothrow_move_constructible_v<_SizeType>) | |
: _M_size(::std::move(__size)) { | |
} | |
constexpr __subrange_size(const _SizeType& __size) noexcept( | |
::std::is_nothrow_copy_constructible_v<_SizeType>) | |
: _M_size(__size) { | |
} | |
}; | |
////// | |
/// @brief A utility class to aid in trafficking iterator pairs (or, possibly, and iterator and sentinel pair) | |
/// through the API to provide a generic, basic "range" type. Attempts to mimic @c std::ranges::subrange on | |
/// platforms where it is not available. | |
/// | |
/// @tparam _It The iterator type. | |
/// @tparam _Sen The sentinel type, defaulted to @p _It. | |
/// @tparam _Kind Whether or not this is a "Sized Subrange": that is, that a calculation for the size of the | |
/// subrange can be done in O(1) time and is available. | |
////// | |
template <typename _It, typename _Sen = _It, | |
__subrange_kind _Kind | |
= __txt_detail::__is_sized_sentinel_for_v<_It, _Sen> ? __subrange_kind::sized : __subrange_kind::unsized> | |
class __subrange : __txt_detail::__subrange_size<__txt_detail::__iterator_size_type_t<_It>, | |
!__txt_detail::__is_sized_sentinel_for_v<_It, _Sen>> { | |
private: | |
inline static constexpr bool _SizeRequired | |
= _Kind == __subrange_kind::sized && !__txt_detail::__is_sized_sentinel_for_v<_It, _Sen>; | |
using _SizeType = __txt_detail::__iterator_size_type_t<_It>; | |
using __base_size_t = __txt_detail::__subrange_size<_SizeType, _SizeRequired>; | |
public: | |
////// | |
/// @brief The @c iterator type for this subrange, dictated by the template parameter @p _It. | |
/// | |
////// | |
using iterator = _It; | |
////// | |
/// @brief The @c const_iterator type for this subrange, dictated by the template parameter @p _It. | |
/// | |
////// | |
using const_iterator = iterator; | |
////// | |
/// @brief The @c sentinel type for this subrange, dictated by the template parameter @p _Sen. | |
/// | |
////// | |
using sentinel = _Sen; | |
////// | |
/// @brief The @c const_sentinel type for this subrange, dictated by the template parameter @p _Sen. | |
/// | |
////// | |
using const_sentinel = sentinel; | |
////// | |
/// @brief The iterator category. Same as the iterator category for @p _It. | |
/// | |
////// | |
using iterator_category = __txt_detail::__iterator_category_t<iterator>; | |
////// | |
/// @brief The iterator concept. Same as the iterator concept for @p _It. | |
/// | |
////// | |
using iterator_concept = __txt_detail::__iterator_concept_t<iterator>; | |
////// | |
/// @brief The @c pointer type. Same as the @c pointer type for @p _It. | |
/// | |
////// | |
using pointer = __txt_detail::__iterator_pointer_t<iterator>; | |
////// | |
/// @brief The @c const_pointer type. Same as the @c const_pointer type for @p _It. | |
/// | |
////// | |
using const_pointer = pointer; | |
////// | |
/// @brief The @c reference type. Same as the @c reference type for @p _It. | |
/// | |
////// | |
using reference = __txt_detail::__iterator_reference_t<iterator>; | |
////// | |
/// @brief The @c const_reference type. Same as the @c const_reference type for @p _It. | |
/// | |
////// | |
using const_reference = reference; | |
////// | |
/// @brief The @c value_type. Same as the @c value_type for @p _It. | |
/// | |
////// | |
using value_type = __txt_detail::__iterator_value_type_t<iterator>; | |
////// | |
/// @brief The @c difference_type. Same as the @c difference_type for @p _It. | |
/// | |
////// | |
using difference_type = __txt_detail::__iterator_difference_type_t<iterator>; | |
////// | |
/// @brief The @c size_type. Same as the @c size_type for @p _It. | |
/// | |
////// | |
using size_type = _SizeType; | |
////// | |
/// @brief Constructs a ztd::text::subrange containing a defaulted iterator and a defaulted sentinel. | |
/// | |
////// | |
constexpr __subrange() noexcept = default; | |
////// | |
/// @brief Constructs a ztd::text::subrange with its begin and end constructed by @p __range's @c begin() | |
/// and | |
/// @c end() values. | |
/// | |
/// @param[in] __range The Range to get the @c begin() and @c end() out of to initialize the subrange's | |
/// iterators. | |
////// | |
template <typename _Range, | |
::std::enable_if_t< | |
!::std::is_same_v<__txt_detail::__remove_cvref_t<_Range>, __subrange>>* = nullptr> | |
constexpr __subrange(_Range&& __range) noexcept(::std::is_nothrow_constructible_v<__subrange, | |
__txt_detail::__range_iterator_t<__txt_detail::__remove_cvref_t<_Range>>, | |
__txt_detail::__range_sentinel_t<__txt_detail::__remove_cvref_t<_Range>>>) | |
: __subrange(__txt_detail::__adl::__adl_begin(::std::forward<_Range>(__range)), | |
__txt_detail::__adl::__adl_end(::std::forward<_Range>(__range))) { | |
} | |
////// | |
/// @brief Constructs a ztd::text::subrange with its begin and end constructed by @p __range's @c begin() | |
/// and | |
/// @c end() values. | |
/// | |
/// @param[in] __range The Range to get the @c begin() and @c end() out of to initialize the subrange's | |
/// iterators. | |
/// @param[in] __size The size to construct with. | |
////// | |
template <typename _Range, __subrange_kind _DummyKind = _Kind, | |
::std::enable_if_t<(_DummyKind == __subrange_kind::sized)>* = nullptr> | |
constexpr __subrange(_Range&& __range, size_type __size) noexcept( | |
noexcept(__subrange(__txt_detail::__adl::__adl_begin(::std::forward<_Range>(__range)), | |
__txt_detail::__adl::__adl_end(::std::forward<_Range>(__range)), ::std::move(__size)))) | |
: __subrange(__txt_detail::__adl::__adl_begin(::std::forward<_Range>(__range)), | |
__txt_detail::__adl::__adl_end(::std::forward<_Range>(__range)), ::std::move(__size)) { | |
} | |
////// | |
/// @brief Constructs a ztd::text::subrange with its begin and end constructed by @p __range's @c begin() | |
/// and | |
/// @c end() values. | |
/// | |
/// @param[in] __it An iterator value to @c std::move in. | |
/// @param[in] __sen A sentinel value to @c std::move in. | |
////// | |
constexpr __subrange(iterator __it, sentinel __sen) noexcept( | |
::std::is_nothrow_move_constructible_v<iterator>&& ::std::is_nothrow_move_constructible_v<sentinel>) | |
: __subrange(__size_mark {}, ::std::integral_constant<bool, _SizeRequired>(), ::std::move(__it), | |
::std::move(__sen)) { | |
} | |
////// | |
/// @brief Constructs a ztd::text::subrange with its begin and end constructed by @p __range's @c begin() | |
/// and | |
/// @c end() values. | |
/// | |
/// @param[in] __it An iterator value to construct with. | |
/// @param[in] __sen A sentinel value to construct with. | |
/// @param[in] __size The size to construct with. | |
////// | |
template <__subrange_kind _DummyKind = _Kind, | |
::std::enable_if_t<_DummyKind == __subrange_kind::sized>* = nullptr> | |
constexpr __subrange(iterator __it, sentinel __sen, size_type __size) noexcept( | |
::std::is_nothrow_move_constructible_v<iterator>&& ::std::is_nothrow_constructible_v< | |
sentinel>&& ::std::is_nothrow_move_constructible_v<size_type>) | |
: __base_size_t(::std::move(__size)), _M_it(::std::move(__it)), _M_sen(::std::move(__sen)) { | |
} | |
////// | |
/// @brief The stored begin iterator. | |
/// | |
////// | |
constexpr iterator begin() & noexcept { | |
if constexpr (::std::is_copy_constructible_v<iterator>) { | |
return this->_M_it; | |
} | |
else { | |
return ::std::move(this->_M_it); | |
} | |
} | |
////// | |
/// @brief The stored begin iterator. | |
/// | |
////// | |
constexpr iterator begin() const& noexcept { | |
return this->_M_it; | |
} | |
////// | |
/// @brief The stored begin iterator. | |
/// | |
////// | |
constexpr iterator begin() && noexcept { | |
return ::std::move(this->_M_it); | |
} | |
////// | |
/// @brief The stored end iterator. | |
/// | |
////// | |
constexpr const sentinel& end() const& noexcept { | |
return this->_M_sen; | |
} | |
////// | |
/// @brief The stored end iterator. | |
/// | |
////// | |
constexpr sentinel& end() & noexcept { | |
return this->_M_sen; | |
} | |
////// | |
/// @brief The stored end iterator. | |
/// | |
////// | |
constexpr sentinel&& end() && noexcept { | |
return ::std::move(this->_M_sen); | |
} | |
////// | |
/// @brief Whether or not this range is empty. | |
/// | |
/// @returns @c begin() == @c end() | |
////// | |
constexpr bool empty() const noexcept { | |
return this->_M_it == this->_M_sen; | |
} | |
////// | |
/// @brief The size of the range. | |
/// | |
/// @returns @code std::distance(begin(), end()) @endcode | |
/// | |
/// @remarks This function call only works if the @p _Kind of this subrange is | |
/// ztd::text::subrange_kind::sized. | |
////// | |
template <__subrange_kind _Dummy = _Kind, | |
::std::enable_if_t<_Dummy == __subrange_kind::sized>* = nullptr> | |
constexpr size_type size() const noexcept { | |
return ::std::distance(this->_M_it, this->_M_sen); | |
} | |
////// | |
/// @brief A @c pointer to the range of elements. | |
/// | |
/// @returns @c std::addressof(*begin()). | |
/// | |
/// @remarks This function call only works if the @c iterator_concept is a @c contiguous_iterator_tag or | |
/// better. | |
////// | |
template <typename _Dummy = _It, | |
::std::enable_if_t< | |
__txt_detail::__is_iterator_concept_or_better_v<contiguous_iterator_tag, _Dummy>>* = nullptr> | |
constexpr pointer data() const noexcept { | |
return __txt_detail::__adl::__adl_to_address(this->_M_it); | |
} | |
////// | |
/// @brief Produces a copy of the subrange and advances the @c begin() iterator by 1. | |
/// | |
/// @remarks This function call only works if the underlying iterator and sentinal types are copyable. | |
////// | |
[[nodiscard]] constexpr __subrange next() const& noexcept( | |
(::std::is_nothrow_copy_constructible_v< | |
iterator> && ::std::is_nothrow_copy_constructible_v<sentinel>)&& noexcept(__txt_detail:: | |
__advance(::std::declval<iterator&>()))) { | |
auto __it = this->_M_it; | |
__txt_detail::__advance(__it); | |
return __subrange(::std::move(__it), this->_M_sen); | |
} | |
////// | |
/// @brief Produces a copy of the subrange and advances the @c begin() iterator by 1. | |
/// | |
/// @remarks This function call can be more efficient and allows working with move-only iterators. This | |
/// function call will move the iterators underlying this object. | |
////// | |
[[nodiscard]] constexpr __subrange next() && noexcept( | |
(::std::is_nothrow_move_constructible_v< | |
iterator> && ::std::is_nothrow_move_constructible_v<sentinel>)&& noexcept(__txt_detail:: | |
__advance(::std::declval<iterator&>()))) { | |
iterator __it = ::std::move(this->_M_it); | |
__txt_detail::__advance(__it); | |
return __subrange(::std::move(__it), ::std::move(this->_M_sen)); | |
} | |
////// | |
/// @brief Produces a copy of the subrange and advances the @c begin() iterator by @p __diff. | |
/// | |
/// @param[in] __diff The amount to move this iterator by. Can be positive or negative. | |
/// | |
/// @remarks This function call only works if the underlying iterator and sentinal types are copyable. | |
////// | |
[[nodiscard]] constexpr __subrange next(difference_type __diff) const& noexcept( | |
(::std::is_nothrow_copy_constructible_v< | |
iterator> && ::std::is_nothrow_copy_constructible_v<sentinel>)&& noexcept(__txt_detail:: | |
__advance(::std::declval<iterator&>(), ::std::declval<difference_type>()))) { | |
auto __it = this->_M_it; | |
__txt_detail::__advance(__it, __diff); | |
return __subrange(::std::move(__it), this->_M_sen); | |
} | |
////// | |
/// @brief Produces a copy of the subrange and advances the @c begin() iterator by @p __diff. | |
/// | |
/// @param[in] __diff The amount to move this iterator by. Can be positive or negative. | |
/// | |
/// @remarks This function call can be more efficient and allows working with move-only iterators. This | |
/// function call will move the iterators underlying this object. | |
////// | |
[[nodiscard]] constexpr __subrange next(difference_type __diff) && noexcept( | |
(::std::is_nothrow_move_constructible_v< | |
iterator> && ::std::is_nothrow_move_constructible_v<sentinel>)&& noexcept(__txt_detail:: | |
__advance(::std::declval<iterator&>(), ::std::declval<difference_type>()))) { | |
iterator __it = ::std::move(this->_M_it); | |
__txt_detail::__advance(__it, __diff); | |
return __subrange(::std::move(__it), ::std::move(this->_M_sen)); | |
} | |
////// | |
/// @brief Produces a copy of the subrange and recedes the @c begin() iterator by @p __diff. | |
/// | |
/// @param[in] __diff The amount to move this iterator by. Can be positive or negative. | |
/// | |
/// @remarks This function call requires that the underlying iterator are bidirectional. | |
////// | |
[[nodiscard]] constexpr __subrange prev(difference_type __diff = 1) const noexcept( | |
(::std::is_nothrow_copy_constructible_v< | |
iterator> && ::std::is_nothrow_copy_constructible_v<sentinel>)&& noexcept(__txt_detail:: | |
__recede(::std::declval<iterator&>(), ::std::declval<difference_type>()))) { | |
auto __it = this->_M_it; | |
__recede(__it, __diff); | |
return __subrange(::std::move(__it), this->_M_sen); | |
} | |
////// | |
/// @brief Advances the @c begin() iterator of this ztd::text::subrange by @p __diff or just @c 1 if the | |
/// argument is not specified. | |
/// | |
/// @param[in] __diff The amount to move this iterator by. Can be positive or negative. | |
////// | |
constexpr __subrange& advance(difference_type __diff = 1) noexcept( | |
noexcept(__txt_detail::__advance(::std::declval<iterator&>(), ::std::declval<difference_type>()))) { | |
__txt_detail::__advance(this->_M_it, __diff); | |
return *this; | |
} | |
////// | |
/// @brief Recedes the @c begin() iterator of this ztd::text::subrange by @p __diff or just @c 1 if the | |
/// argument is not specified. | |
/// | |
/// @param[in] __diff The amount to move this iterator by. Can be positive or negative. | |
/// | |
/// @remarks This function call requires that the underlying iterator are bidirectional. | |
////// | |
constexpr __subrange& recede(difference_type __diff = 1) noexcept( | |
noexcept(__txt_detail::__recede(std::declval<iterator&>(), ::std::declval<difference_type>()))) { | |
__txt_detail::__recede(this->_M_it, __diff); | |
return *this; | |
} | |
private: | |
template <typename _ArgIterator, typename _ArgSentinel> | |
constexpr __subrange(__size_mark, ::std::true_type, _ArgIterator&& __it, _ArgSentinel&& __sen) noexcept( | |
::std::is_nothrow_constructible_v<iterator, _ArgIterator>&& ::std::is_nothrow_constructible_v< | |
sentinel, _ArgSentinel>&& ::std::is_nothrow_constructible_v<__base_size_t, _SizeType>) | |
: __base_size_t(static_cast<_SizeType>(__sen - __it)) | |
, _M_it(::std::forward<_ArgIterator>(__it)) | |
, _M_sen(::std::forward<_ArgSentinel>(__sen)) { | |
} | |
template <typename _ArgIterator, typename _ArgSentinel> | |
constexpr __subrange(__size_mark, ::std::false_type, _ArgIterator&& __it, _ArgSentinel&& __sen) noexcept( | |
::std::is_nothrow_constructible_v<iterator, | |
_ArgIterator>&& ::std::is_nothrow_constructible_v<sentinel, _ArgSentinel>) | |
: _M_it(::std::forward<_ArgIterator>(__it)), _M_sen(::std::forward<_ArgSentinel>(__sen)) { | |
} | |
iterator _M_it; | |
sentinel _M_sen; | |
}; | |
} // namespace __txt_detail | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_RANGES_I_) | |
// std::subrange is busted and I'm not interested in digging into why it's busted | |
using ::std::ranges::subrange; | |
using ::std::ranges::subrange_kind; | |
#else | |
////// | |
/// @brief The type of subrange, sized or unsized. | |
/// | |
////// | |
using subrange_kind = __txt_detail::__subrange_kind; | |
////// | |
/// @brief A general-purpose iterator-sentinel (or iterator-sentinel-size) container. | |
/// | |
////// | |
template <typename _It, typename _Sen = _It, | |
subrange_kind _Kind | |
= __txt_detail::__is_sized_sentinel_for_v<_It, _Sen> ? subrange_kind::sized : subrange_kind::unsized> | |
using subrange = ::ztd::text::__txt_detail::__subrange<_It, _Sen, _Kind>; | |
#endif | |
namespace __txt_detail { | |
template <typename _Range> | |
using __subrange_for_t = subrange<__range_iterator_t<_Range>, __range_sentinel_t<_Range>>; | |
} // namespace __txt_detail | |
////// | |
/// @brief Decomposes a range into its two iterators and returns it as a ztd::text::subrange. | |
/// | |
////// | |
template <typename _Range> | |
constexpr __txt_detail::__subrange_for_t<_Range> make_subrange(_Range&& __range) noexcept( | |
::std::is_nothrow_constructible_v<_Range, __txt_detail::__subrange_for_t<_Range>>) { | |
return { __txt_detail::__adl::__adl_begin(__range), __txt_detail::__adl::__adl_end(__range) }; | |
} | |
////// | |
/// @brief Takes two iterators and returns them as a ztd::text::subrange. | |
/// | |
////// | |
template <typename _It, typename _Sen> | |
constexpr subrange<_It, _Sen> make_subrange(_It&& __it, _Sen&& __sen) noexcept( | |
::std::is_nothrow_constructible_v<subrange<_It, _Sen>, _It, _Sen>) { | |
return { ::std::forward<_It>(__it), ::std::forward<_Sen>(__sen) }; | |
} | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_CONCEPTS_I_) && ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_RANGES_I_) | |
namespace std { namespace ranges { | |
template <typename _It, typename _Sen, ::ztd::text::__txt_detail::__subrange_kind _Kind> | |
inline constexpr bool enable_borrowed_range<::ztd::text::__txt_detail::__subrange<_It, _Sen, _Kind>> = true; | |
}} // namespace std::ranges | |
#endif | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/subrange.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/span.hpp | |
#include <type_traits> | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_SPAN_I_) | |
#include <span> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @brief dynamic extent copycat | |
/// | |
////// | |
inline constexpr decltype(::std::dynamic_extent) dynamic_extent = ::std::dynamic_extent; | |
using ::std::as_bytes; | |
using ::std::as_writable_bytes; | |
using ::std::span; | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
#else | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/span.implementation.hpp | |
#ifndef NONSTD_SPAN_HPP_INCLUDED | |
#define NONSTD_SPAN_HPP_INCLUDED | |
#define span_lite_MAJOR 0 | |
#define span_lite_MINOR 9 | |
#define span_lite_PATCH 2 | |
#define span_lite_VERSION \ | |
span_STRINGIFY(span_lite_MAJOR) "." span_STRINGIFY(span_lite_MINOR) "." span_STRINGIFY(span_lite_PATCH) | |
#define span_STRINGIFY(x) span_STRINGIFY_(x) | |
#define span_STRINGIFY_(x) #x | |
#define span_SPAN_DEFAULT 0 | |
#define span_SPAN_NONSTD 1 | |
#define span_SPAN_STD 2 | |
#ifdef __has_include | |
#if __has_include(<nonstd/span.tweak.hpp>) | |
#include <nonstd/span.tweak.hpp> | |
#endif | |
#define span_HAVE_TWEAK_HEADER 1 | |
#else | |
#define span_HAVE_TWEAK_HEADER 0 | |
#endif | |
#define span_HAVE(feature) (span_HAVE_##feature) | |
#ifndef span_CONFIG_SELECT_SPAN | |
#define span_CONFIG_SELECT_SPAN (span_HAVE_STD_SPAN ? span_SPAN_STD : span_SPAN_NONSTD) | |
#endif | |
#ifndef span_CONFIG_EXTENT_TYPE | |
#define span_CONFIG_EXTENT_TYPE std::size_t | |
#endif | |
#ifndef span_CONFIG_SIZE_TYPE | |
#define span_CONFIG_SIZE_TYPE std::size_t | |
#endif | |
#ifdef span_CONFIG_INDEX_TYPE | |
#error `span_CONFIG_INDEX_TYPE` is deprecated since v0.7.0; it is replaced by `span_CONFIG_SIZE_TYPE`. | |
#endif | |
#ifndef span_FEATURE_WITH_CONTAINER | |
#ifdef span_FEATURE_WITH_CONTAINER_TO_STD | |
#define span_FEATURE_WITH_CONTAINER span_IN_STD(span_FEATURE_WITH_CONTAINER_TO_STD) | |
#else | |
#define span_FEATURE_WITH_CONTAINER 0 | |
#endif | |
#endif | |
#ifndef span_FEATURE_CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE | |
#define span_FEATURE_CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE 0 | |
#endif | |
#ifndef span_FEATURE_MEMBER_AT | |
#define span_FEATURE_MEMBER_AT 0 | |
#endif | |
#ifndef span_FEATURE_MEMBER_BACK_FRONT | |
#define span_FEATURE_MEMBER_BACK_FRONT 1 | |
#endif | |
#ifndef span_FEATURE_MEMBER_CALL_OPERATOR | |
#define span_FEATURE_MEMBER_CALL_OPERATOR 0 | |
#endif | |
#ifndef span_FEATURE_MEMBER_SWAP | |
#define span_FEATURE_MEMBER_SWAP 0 | |
#endif | |
#ifndef span_FEATURE_NON_MEMBER_FIRST_LAST_SUB | |
#define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB 0 | |
#elif span_FEATURE_NON_MEMBER_FIRST_LAST_SUB | |
#define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN 1 | |
#define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER 1 | |
#endif | |
#ifndef span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN | |
#define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_SPAN 0 | |
#endif | |
#ifndef span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER | |
#define span_FEATURE_NON_MEMBER_FIRST_LAST_SUB_CONTAINER 0 | |
#endif | |
#ifndef span_FEATURE_COMPARISON | |
#define span_FEATURE_COMPARISON 0 // Note: C++20 does not provide comparison | |
#endif | |
#ifndef span_FEATURE_SAME | |
#define span_FEATURE_SAME 0 | |
#endif | |
#if span_FEATURE_SAME && !span_FEATURE_COMPARISON | |
#error `span_FEATURE_SAME` requires `span_FEATURE_COMPARISON` | |
#endif | |
#ifndef span_FEATURE_MAKE_SPAN | |
#ifdef span_FEATURE_MAKE_SPAN_TO_STD | |
#define span_FEATURE_MAKE_SPAN span_IN_STD(span_FEATURE_MAKE_SPAN_TO_STD) | |
#else | |
#define span_FEATURE_MAKE_SPAN 0 | |
#endif | |
#endif | |
#ifndef span_FEATURE_BYTE_SPAN | |
#define span_FEATURE_BYTE_SPAN 0 | |
#endif | |
#ifndef span_CONFIG_NO_EXCEPTIONS | |
#if _MSC_VER | |
#include <cstddef> // for _HAS_EXCEPTIONS | |
#endif | |
#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS) | |
#define span_CONFIG_NO_EXCEPTIONS 0 | |
#else | |
#define span_CONFIG_NO_EXCEPTIONS 1 | |
#undef span_CONFIG_CONTRACT_VIOLATION_THROWS | |
#undef span_CONFIG_CONTRACT_VIOLATION_TERMINATES | |
#define span_CONFIG_CONTRACT_VIOLATION_THROWS 0 | |
#define span_CONFIG_CONTRACT_VIOLATION_TERMINATES 1 | |
#endif | |
#endif | |
#if defined(span_CONFIG_CONTRACT_LEVEL_ON) | |
#define span_CONFIG_CONTRACT_LEVEL_MASK 0x11 | |
#elif defined(span_CONFIG_CONTRACT_LEVEL_OFF) | |
#define span_CONFIG_CONTRACT_LEVEL_MASK 0x00 | |
#elif defined(span_CONFIG_CONTRACT_LEVEL_EXPECTS_ONLY) | |
#define span_CONFIG_CONTRACT_LEVEL_MASK 0x01 | |
#elif defined(span_CONFIG_CONTRACT_LEVEL_ENSURES_ONLY) | |
#define span_CONFIG_CONTRACT_LEVEL_MASK 0x10 | |
#else | |
#define span_CONFIG_CONTRACT_LEVEL_MASK 0x11 | |
#endif | |
#if defined(span_CONFIG_CONTRACT_VIOLATION_THROWS) | |
#define span_CONFIG_CONTRACT_VIOLATION_THROWS_V span_CONFIG_CONTRACT_VIOLATION_THROWS | |
#else | |
#define span_CONFIG_CONTRACT_VIOLATION_THROWS_V 0 | |
#endif | |
#if defined(span_CONFIG_CONTRACT_VIOLATION_THROWS) && span_CONFIG_CONTRACT_VIOLATION_THROWS \ | |
&& defined(span_CONFIG_CONTRACT_VIOLATION_TERMINATES) && span_CONFIG_CONTRACT_VIOLATION_TERMINATES | |
# error Please define none or one of span_CONFIG_CONTRACT_VIOLATION_THROWS and span_CONFIG_CONTRACT_VIOLATION_TERMINATES to 1, but not both. | |
#endif | |
#ifndef span_CPLUSPLUS | |
#if defined(_MSVC_LANG) && !defined(__clang__) | |
#define span_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG) | |
#else | |
#define span_CPLUSPLUS __cplusplus | |
#endif | |
#endif | |
#define span_CPP98_OR_GREATER (span_CPLUSPLUS >= 199711L) | |
#define span_CPP11_OR_GREATER (span_CPLUSPLUS >= 201103L) | |
#define span_CPP14_OR_GREATER (span_CPLUSPLUS >= 201402L) | |
#define span_CPP17_OR_GREATER (span_CPLUSPLUS >= 201703L) | |
#define span_CPP20_OR_GREATER (span_CPLUSPLUS >= 202000L) | |
#define span_CPLUSPLUS_V (span_CPLUSPLUS / 100 - (span_CPLUSPLUS > 200000 ? 2000 : 1994)) | |
#define span_IN_STD(v) (((v) == 98 ? 3 : (v)) >= span_CPLUSPLUS_V) | |
#define span_CONFIG(feature) (span_CONFIG_##feature) | |
#define span_FEATURE(feature) (span_FEATURE_##feature) | |
#define span_FEATURE_TO_STD(feature) (span_IN_STD(span_FEATURE(feature##_TO_STD))) | |
#if span_CPP20_OR_GREATER && defined(__has_include) | |
#if __has_include(<span> ) | |
#define span_HAVE_STD_SPAN 1 | |
#else | |
#define span_HAVE_STD_SPAN 0 | |
#endif | |
#else | |
#define span_HAVE_STD_SPAN 0 | |
#endif | |
#define span_USES_STD_SPAN \ | |
((span_CONFIG_SELECT_SPAN == span_SPAN_STD) \ | |
|| ((span_CONFIG_SELECT_SPAN == span_SPAN_DEFAULT) && span_HAVE_STD_SPAN)) | |
#if span_USES_STD_SPAN | |
#include <span> | |
namespace nonstd { | |
using std::span; | |
using std::as_bytes; | |
using std::as_writable_bytes; | |
using std::dynamic_extent; | |
// Note: C++20 does not provide comparison | |
// using std::operator==; | |
// using std::operator!=; | |
// using std::operator<; | |
// using std::operator<=; | |
// using std::operator>; | |
// using std::operator>=; | |
} // namespace nonstd | |
#else // span_USES_STD_SPAN | |
#include <algorithm> | |
#if defined(_MSC_VER) && !defined(__clang__) | |
#define span_COMPILER_MSVC_VER (_MSC_VER) | |
#define span_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * (5 + (_MSC_VER < 1900))) | |
#else | |
#define span_COMPILER_MSVC_VER 0 | |
#define span_COMPILER_MSVC_VERSION 0 | |
#endif | |
#define span_COMPILER_VERSION(major, minor, patch) (10 * (10 * (major) + (minor)) + (patch)) | |
#if defined(__clang__) | |
#define span_COMPILER_CLANG_VERSION span_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) | |
#else | |
#define span_COMPILER_CLANG_VERSION 0 | |
#endif | |
#if defined(__GNUC__) && !defined(__clang__) | |
#define span_COMPILER_GNUC_VERSION span_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) | |
#else | |
#define span_COMPILER_GNUC_VERSION 0 | |
#endif | |
#define span_BETWEEN(v, lo, hi) ((lo) <= (v) && (v) < (hi)) | |
#if defined(__clang__) | |
#pragma clang diagnostic push | |
#pragma clang diagnostic ignored "-Wundef" | |
#pragma clang diagnostic ignored "-Wmismatched-tags" | |
#define span_RESTORE_WARNINGS() _Pragma("clang diagnostic pop") | |
#elif defined __GNUC__ | |
#pragma GCC diagnostic push | |
#pragma GCC diagnostic ignored "-Wundef" | |
#define span_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop") | |
#elif span_COMPILER_MSVC_VER >= 1900 | |
#define span_DISABLE_MSVC_WARNINGS(codes) __pragma(warning(push)) __pragma(warning(disable : codes)) | |
#define span_RESTORE_WARNINGS() __pragma(warning(pop)) | |
span_DISABLE_MSVC_WARNINGS(26439 26440 26472 26473 26481 26490) | |
#else | |
#define span_RESTORE_WARNINGS() /*empty*/ | |
#endif | |
#ifdef _HAS_CPP0X | |
#define span_HAS_CPP0X _HAS_CPP0X | |
#else | |
#define span_HAS_CPP0X 0 | |
#endif | |
#define span_CPP11_80 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1400) | |
#define span_CPP11_90 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1500) | |
#define span_CPP11_100 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1600) | |
#define span_CPP11_110 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1700) | |
#define span_CPP11_120 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1800) | |
#define span_CPP11_140 (span_CPP11_OR_GREATER || span_COMPILER_MSVC_VER >= 1900) | |
#define span_CPP14_000 (span_CPP14_OR_GREATER) | |
#define span_CPP14_120 (span_CPP14_OR_GREATER || span_COMPILER_MSVC_VER >= 1800) | |
#define span_CPP14_140 (span_CPP14_OR_GREATER || span_COMPILER_MSVC_VER >= 1900) | |
#define span_CPP17_000 (span_CPP17_OR_GREATER) | |
#define span_HAVE_ALIAS_TEMPLATE span_CPP11_140 | |
#define span_HAVE_AUTO span_CPP11_100 | |
#define span_HAVE_CONSTEXPR_11 span_CPP11_140 | |
#define span_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG span_CPP11_120 | |
#define span_HAVE_EXPLICIT_CONVERSION span_CPP11_140 | |
#define span_HAVE_INITIALIZER_LIST span_CPP11_120 | |
#define span_HAVE_IS_DEFAULT span_CPP11_140 | |
#define span_HAVE_IS_DELETE span_CPP11_140 | |
#define span_HAVE_NOEXCEPT span_CPP11_140 | |
#define span_HAVE_NULLPTR span_CPP11_100 | |
#define span_HAVE_STATIC_ASSERT span_CPP11_100 | |
#define span_HAVE_CONSTEXPR_14 span_CPP14_000 | |
#define span_HAVE_DEPRECATED span_CPP17_000 | |
#define span_HAVE_NODISCARD span_CPP17_000 | |
#define span_HAVE_NORETURN span_CPP17_000 | |
#if defined(__cpp_deduction_guides) | |
#define span_HAVE_DEDUCTION_GUIDES 1 | |
#else | |
#define span_HAVE_DEDUCTION_GUIDES (span_CPP17_OR_GREATER && !span_BETWEEN(span_COMPILER_MSVC_VER, 1, 1913)) | |
#endif | |
#define span_HAVE_ADDRESSOF span_CPP17_000 | |
#define span_HAVE_ARRAY span_CPP11_110 | |
#define span_HAVE_BYTE span_CPP17_000 | |
#define span_HAVE_CONDITIONAL span_CPP11_120 | |
#define span_HAVE_CONTAINER_DATA_METHOD (span_CPP11_140 || (span_COMPILER_MSVC_VER >= 1500 && span_HAS_CPP0X)) | |
#define span_HAVE_DATA span_CPP17_000 | |
#define span_HAVE_LONGLONG span_CPP11_80 | |
#define span_HAVE_REMOVE_CONST span_CPP11_110 | |
#define span_HAVE_SNPRINTF span_CPP11_140 | |
#define span_HAVE_STRUCT_BINDING span_CPP11_120 | |
#define span_HAVE_TYPE_TRAITS span_CPP11_90 | |
#ifdef NONSTD_BYTE_LITE_HPP | |
#define span_HAVE_NONSTD_BYTE 1 | |
#else | |
#define span_HAVE_NONSTD_BYTE 0 | |
#endif | |
#if span_HAVE_ADDRESSOF | |
#define span_ADDRESSOF(x) std::addressof(x) | |
#else | |
#define span_ADDRESSOF(x) (&x) | |
#endif | |
#if span_HAVE_CONSTEXPR_11 | |
#define span_constexpr constexpr | |
#else | |
#define span_constexpr /*span_constexpr*/ | |
#endif | |
#if span_HAVE_CONSTEXPR_14 | |
#define span_constexpr14 constexpr | |
#else | |
#define span_constexpr14 /*span_constexpr*/ | |
#endif | |
#if span_HAVE_EXPLICIT_CONVERSION | |
#define span_explicit explicit | |
#else | |
#define span_explicit /*explicit*/ | |
#endif | |
#if span_HAVE_IS_DELETE | |
#define span_is_delete = delete | |
#else | |
#define span_is_delete | |
#endif | |
#if span_HAVE_IS_DELETE | |
#define span_is_delete_access public | |
#else | |
#define span_is_delete_access private | |
#endif | |
#if span_HAVE_NOEXCEPT && !span_CONFIG_CONTRACT_VIOLATION_THROWS_V | |
#define span_noexcept noexcept | |
#else | |
#define span_noexcept /*noexcept*/ | |
#endif | |
#if span_HAVE_NULLPTR | |
#define span_nullptr nullptr | |
#else | |
#define span_nullptr NULL | |
#endif | |
#if span_HAVE_DEPRECATED | |
#define span_deprecated(msg) [[deprecated(msg)]] | |
#else | |
#define span_deprecated(msg) /*[[deprecated]]*/ | |
#endif | |
#if span_HAVE_NODISCARD | |
#define span_nodiscard [[nodiscard]] | |
#else | |
#define span_nodiscard /*[[nodiscard]]*/ | |
#endif | |
#if span_HAVE_NORETURN | |
#define span_noreturn [[noreturn]] | |
#else | |
#define span_noreturn /*[[noreturn]]*/ | |
#endif | |
#define span_HAVE_CONSTRAINED_SPAN_CONTAINER_CTOR span_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG | |
#define span_HAVE_ITERATOR_CTOR span_HAVE_DEFAULT_FUNCTION_TEMPLATE_ARG | |
#if span_HAVE(ADDRESSOF) | |
#include <memory> | |
#endif | |
#if span_HAVE(ARRAY) | |
#include <array> | |
#endif | |
#if span_HAVE(BYTE) | |
#include <cstddef> | |
#endif | |
#if span_HAVE(DATA) | |
#include <iterator> // for std::data(), std::size() | |
#endif | |
#if span_HAVE(TYPE_TRAITS) | |
#include <type_traits> | |
#endif | |
#if !span_HAVE(CONSTRAINED_SPAN_CONTAINER_CTOR) | |
#include <vector> | |
#endif | |
#if span_FEATURE(MEMBER_AT) > 1 | |
#include <cstdio> | |
#endif | |
#if !span_CONFIG(NO_EXCEPTIONS) | |
#include <stdexcept> | |
#endif | |
#define span_ELIDE_CONTRACT_EXPECTS (0 == (span_CONFIG_CONTRACT_LEVEL_MASK & 0x01)) | |
#define span_ELIDE_CONTRACT_ENSURES (0 == (span_CONFIG_CONTRACT_LEVEL_MASK & 0x10)) | |
#if span_ELIDE_CONTRACT_EXPECTS | |
#define span_constexpr_exp span_constexpr | |
#define span_EXPECTS(cond) /* Expect elided */ | |
#else | |
#define span_constexpr_exp span_constexpr14 | |
#define span_EXPECTS(cond) span_CONTRACT_CHECK("Precondition", cond) | |
#endif | |
#if span_ELIDE_CONTRACT_ENSURES | |
#define span_constexpr_ens span_constexpr | |
#define span_ENSURES(cond) /* Ensures elided */ | |
#else | |
#define span_constexpr_ens span_constexpr14 | |
#define span_ENSURES(cond) span_CONTRACT_CHECK("Postcondition", cond) | |
#endif | |
#define span_CONTRACT_CHECK(type, cond) \ | |
cond ? static_cast<void>(0) \ | |
: nonstd::span_lite::detail::report_contract_violation( \ | |
span_LOCATION(__FILE__, __LINE__) ": " type " violation.") | |
#ifdef __GNUG__ | |
#define span_LOCATION(file, line) file ":" span_STRINGIFY(line) | |
#else | |
#define span_LOCATION(file, line) file "(" span_STRINGIFY(line) ")" | |
#endif | |
#if span_HAVE(DEFAULT_FUNCTION_TEMPLATE_ARG) | |
#define span_REQUIRES_0(VA) template <bool B = (VA), typename std::enable_if<B, int>::type = 0> | |
#if span_BETWEEN(span_COMPILER_MSVC_VERSION, 1, 140) | |
#define span_REQUIRES_T(VA) , typename = typename std::enable_if<(VA), nonstd::span_lite::detail::enabler>::type | |
#else | |
#define span_REQUIRES_T(VA) , typename std::enable_if<(VA), int>::type = 0 | |
#endif | |
#define span_REQUIRES_R(R, VA) typename std::enable_if<(VA), R>::type | |
#define span_REQUIRES_A(VA) , typename std::enable_if<(VA), void*>::type = nullptr | |
#else | |
#define span_REQUIRES_0(VA) /*empty*/ | |
#define span_REQUIRES_T(VA) /*empty*/ | |
#define span_REQUIRES_R(R, VA) R | |
#define span_REQUIRES_A(VA) /*empty*/ | |
#endif | |
namespace nonstd { namespace span_lite { | |
// [views.constants], constants | |
typedef span_CONFIG_EXTENT_TYPE extent_t; | |
typedef span_CONFIG_SIZE_TYPE size_t; | |
span_constexpr const extent_t dynamic_extent = static_cast<extent_t>(-1); | |
template <class T, extent_t Extent = dynamic_extent> | |
class span; | |
// Tag to select span constructor taking a container (prevent ms-gsl warning C26426): | |
struct with_container_t { | |
span_constexpr with_container_t() span_noexcept { | |
} | |
}; | |
const span_constexpr with_container_t with_container; | |
// C++11 emulation: | |
namespace std11 { | |
#if span_HAVE(REMOVE_CONST) | |
using std::remove_const; | |
using std::remove_cv; | |
using std::remove_volatile; | |
#else | |
template <class T> | |
struct remove_const { | |
typedef T type; | |
}; | |
template <class T> | |
struct remove_const<T const> { | |
typedef T type; | |
}; | |
template <class T> | |
struct remove_volatile { | |
typedef T type; | |
}; | |
template <class T> | |
struct remove_volatile<T volatile> { | |
typedef T type; | |
}; | |
template <class T> | |
struct remove_cv { | |
typedef typename std11::remove_volatile<typename std11::remove_const<T>::type>::type type; | |
}; | |
#endif // span_HAVE( REMOVE_CONST ) | |
#if span_HAVE(TYPE_TRAITS) | |
using std::false_type; | |
using std::integral_constant; | |
using std::is_same; | |
using std::is_signed; | |
using std::remove_reference; | |
using std::true_type; | |
#else | |
template <class T, T v> | |
struct integral_constant { | |
enum { value = v }; | |
}; | |
typedef integral_constant<bool, true> true_type; | |
typedef integral_constant<bool, false> false_type; | |
template <class T, class U> | |
struct is_same : false_type { }; | |
template <class T> | |
struct is_same<T, T> : true_type { }; | |
template <typename T> | |
struct is_signed : false_type { }; | |
template <> | |
struct is_signed<signed char> : true_type { }; | |
template <> | |
struct is_signed<signed int> : true_type { }; | |
template <> | |
struct is_signed<signed long> : true_type { }; | |
#endif | |
} // namespace std11 | |
// C++17 emulation: | |
namespace std17 { | |
template <bool v> | |
struct bool_constant : std11::integral_constant<bool, v> { }; | |
#if span_CPP11_120 | |
template <class...> | |
using void_t = void; | |
#endif | |
#if span_HAVE(DATA) | |
using std::data; | |
using std::size; | |
#elif span_HAVE(CONSTRAINED_SPAN_CONTAINER_CTOR) | |
template <typename T, std::size_t N> | |
inline span_constexpr auto size(const T (&)[N]) span_noexcept -> size_t { | |
return N; | |
} | |
template <typename C> | |
inline span_constexpr auto size(C const& cont) -> decltype(cont.size()) { | |
return cont.size(); | |
} | |
template <typename T, std::size_t N> | |
inline span_constexpr auto data(T (&arr)[N]) span_noexcept -> T* { | |
return &arr[0]; | |
} | |
template <typename C> | |
inline span_constexpr auto data(C& cont) -> decltype(cont.data()) { | |
return cont.data(); | |
} | |
template <typename C> | |
inline span_constexpr auto data(C const& cont) -> decltype(cont.data()) { | |
return cont.data(); | |
} | |
template <typename E> | |
inline span_constexpr auto data(std::initializer_list<E> il) span_noexcept -> E const* { | |
return il.begin(); | |
} | |
#endif // span_HAVE( DATA ) | |
#if span_HAVE(BYTE) | |
using std::byte; | |
#elif span_HAVE(NONSTD_BYTE) | |
using nonstd::byte; | |
#endif | |
} // namespace std17 | |
// C++20 emulation: | |
namespace std20 { | |
#if span_HAVE(DEDUCTION_GUIDES) | |
template <class T> | |
using iter_reference_t = decltype(*std::declval<T&>()); | |
#endif | |
} // namespace std20 | |
// Implementation details: | |
namespace detail { | |
/*enum*/ struct enabler { }; | |
template <typename T> | |
constexpr bool is_positive(T x) { | |
return std11::is_signed<T>::value ? x >= 0 : true; | |
} | |
#if span_HAVE(TYPE_TRAITS) | |
template <class Q> | |
struct is_span_oracle : std::false_type { }; | |
template <class T, span_CONFIG_EXTENT_TYPE Extent> | |
struct is_span_oracle<span<T, Extent>> : std::true_type { }; | |
template <class Q> | |
struct is_span : is_span_oracle<typename std::remove_cv<Q>::type> { }; | |
template <class Q> | |
struct is_std_array_oracle : std::false_type { }; | |
#if span_HAVE(ARRAY) | |
template <class T, std::size_t Extent> | |
struct is_std_array_oracle<std::array<T, Extent>> : std::true_type { }; | |
#endif | |
template <class Q> | |
struct is_std_array : is_std_array_oracle<typename std::remove_cv<Q>::type> { }; | |
template <class Q> | |
struct is_array : std::false_type { }; | |
template <class T> | |
struct is_array<T[]> : std::true_type { }; | |
template <class T, std::size_t N> | |
struct is_array<T[N]> : std::true_type { }; | |
#if span_CPP11_140 && !span_BETWEEN(span_COMPILER_GNUC_VERSION, 1, 500) | |
template <class, class = void> | |
struct has_size_and_data : std::false_type { }; | |
template <class C> | |
struct has_size_and_data<C, | |
std17::void_t<decltype(std17::size(std::declval<C>())), decltype(std17::data(std::declval<C>()))>> | |
: std::true_type { }; | |
template <class, class, class = void> | |
struct is_compatible_element : std::false_type { }; | |
template <class C, class E> | |
struct is_compatible_element<C, E, std17::void_t<decltype(std17::data(std::declval<C>()))>> | |
: std::is_convertible<typename std::remove_pointer<decltype(std17::data(std::declval<C&>()))>::type (*)[], | |
E (*)[]> { }; | |
template <class C> | |
struct is_container : std17::bool_constant<!is_span<C>::value && !is_array<C>::value | |
&& !is_std_array<C>::value && has_size_and_data<C>::value> { }; | |
template <class C, class E> | |
struct is_compatible_container | |
: std17::bool_constant<is_container<C>::value && is_compatible_element<C, E>::value> { }; | |
#else // span_CPP11_140 | |
template <class C, | |
class E span_REQUIRES_T((!is_span<C>::value && !is_array<C>::value && !is_std_array<C>::value | |
&& (std::is_convertible< | |
typename std::remove_pointer<decltype(std17::data(std::declval<C&>()))>::type (*)[], | |
E (*)[]>::value) | |
// && has_size_and_data< C >::value | |
)), | |
class = decltype(std17::size(std::declval<C>())), class = decltype(std17::data(std::declval<C>()))> | |
struct is_compatible_container : std::true_type { }; | |
#endif // span_CPP11_140 | |
#endif // span_HAVE( TYPE_TRAITS ) | |
#if !span_CONFIG(NO_EXCEPTIONS) | |
#if span_FEATURE(MEMBER_AT) > 1 | |
// format index and size: | |
#if defined(__clang__) | |
#pragma clang diagnostic ignored "-Wlong-long" | |
#elif defined __GNUC__ | |
#pragma GCC diagnostic ignored "-Wformat=ll" | |
#pragma GCC diagnostic ignored "-Wlong-long" | |
#endif | |
inline void throw_out_of_range(size_t idx, size_t size) { | |
const char fmt[] = "span::at(): index '%lli' is out of range [0..%lli)"; | |
char buffer[2 * 20 + sizeof fmt]; | |
sprintf(buffer, fmt, static_cast<long long>(idx), static_cast<long long>(size)); | |
throw std::out_of_range(buffer); | |
} | |
#else // MEMBER_AT | |
inline void throw_out_of_range(size_t /*idx*/, size_t /*size*/) { | |
throw std::out_of_range("span::at(): index outside span"); | |
} | |
#endif // MEMBER_AT | |
#endif // NO_EXCEPTIONS | |
#if span_CONFIG(CONTRACT_VIOLATION_THROWS_V) | |
struct contract_violation : std::logic_error { | |
explicit contract_violation(char const* const message) : std::logic_error(message) { | |
} | |
}; | |
inline void report_contract_violation(char const* msg) { | |
throw contract_violation(msg); | |
} | |
#else // span_CONFIG( CONTRACT_VIOLATION_THROWS_V ) | |
span_noreturn inline void report_contract_violation(char const* /*msg*/) span_noexcept { | |
std::terminate(); | |
} | |
#endif // span_CONFIG( CONTRACT_VIOLATION_THROWS_V ) | |
} // namespace detail | |
// Prevent signed-unsigned mismatch: | |
#define span_sizeof(T) static_cast<extent_t>(sizeof(T)) | |
template <class T> | |
inline span_constexpr size_t to_size(T size) { | |
return static_cast<size_t>(size); | |
} | |
// | |
// [views.span] - A view over a contiguous, single-dimension sequence of objects | |
// | |
template <class T, extent_t Extent /*= dynamic_extent*/> | |
class span { | |
public: | |
// constants and types | |
typedef T element_type; | |
typedef typename std11::remove_cv<T>::type value_type; | |
typedef T& reference; | |
typedef T* pointer; | |
typedef T const* const_pointer; | |
typedef T const& const_reference; | |
typedef size_t size_type; | |
typedef extent_t extent_type; | |
typedef pointer iterator; | |
typedef const_pointer const_iterator; | |
typedef std::ptrdiff_t difference_type; | |
typedef std::reverse_iterator<iterator> reverse_iterator; | |
typedef std::reverse_iterator<const_iterator> const_reverse_iterator; | |
// static constexpr extent_type extent = Extent; | |
enum { extent = Extent }; | |
// 26.7.3.2 Constructors, copy, and assignment [span.cons] | |
span_REQUIRES_0((Extent == 0) || (Extent == dynamic_extent)) span_constexpr span() span_noexcept | |
: data_(span_nullptr), | |
size_(0) { | |
// span_EXPECTS( data() == span_nullptr ); | |
// span_EXPECTS( size() == 0 ); | |
} | |
#if span_HAVE(ITERATOR_CTOR) | |
// Didn't yet succeed in combining the next two constructors: | |
span_constexpr_exp span(std::nullptr_t, size_type count) : data_(span_nullptr), size_(count) { | |
span_EXPECTS(data_ == span_nullptr && count == 0); | |
} | |
template <typename It span_REQUIRES_T( | |
(std::is_convertible<decltype(*std::declval<It&>()), element_type>::value))> | |
span_constexpr_exp span(It first, size_type count) : data_(to_address(first)), size_(count) { | |
span_EXPECTS( | |
(data_ == span_nullptr && count == 0) || (data_ != span_nullptr && detail::is_positive(count))); | |
} | |
#else | |
span_constexpr_exp span(pointer ptr, size_type count) : data_(ptr), size_(count) { | |
span_EXPECTS((ptr == span_nullptr && count == 0) || (ptr != span_nullptr && detail::is_positive(count))); | |
} | |
#endif | |
#if span_HAVE(ITERATOR_CTOR) | |
template <typename It, | |
typename End span_REQUIRES_T((std::is_convertible<decltype(*std::declval<It&>()), element_type>::value | |
&& !std::is_convertible<End, std::size_t>::value))> | |
span_constexpr_exp span(It first, End last) : data_(to_address(first)), size_(to_size(last - first)) { | |
span_EXPECTS(last - first >= 0); | |
} | |
#else | |
span_constexpr_exp span(pointer first, pointer last) : data_(first), size_(to_size(last - first)) { | |
span_EXPECTS(last - first >= 0); | |
} | |
#endif | |
template <std::size_t N span_REQUIRES_T(((Extent == dynamic_extent || Extent == static_cast<extent_t>(N)) | |
&& std::is_convertible<value_type (*)[], element_type (*)[]>::value))> | |
span_constexpr span(element_type (&arr)[N]) span_noexcept : data_(span_ADDRESSOF(arr[0])), size_(N) { | |
} | |
#if span_HAVE(ARRAY) | |
template <std::size_t N span_REQUIRES_T(((Extent == dynamic_extent || Extent == static_cast<extent_t>(N)) | |
&& std::is_convertible<value_type (*)[], element_type (*)[]>::value))> | |
#if span_FEATURE(CONSTRUCTION_FROM_STDARRAY_ELEMENT_TYPE) | |
span_constexpr span(std::array<element_type, N>& arr) span_noexcept | |
#else | |
span_constexpr span(std::array<value_type, N>& arr) span_noexcept | |
#endif | |
: data_(arr.data()), | |
size_(to_size(arr.size())) { | |
} | |
template <std::size_t N | |
#if span_HAVE(DEFAULT_FUNCTION_TEMPLATE_ARG) | |
span_REQUIRES_T(((Extent == dynamic_extent || Extent == static_cast<extent_t>(N)) | |
&& std::is_convertible<value_type (*)[], element_type (*)[]>::value)) | |
#endif | |
> | |
span_constexpr span(std::array<value_type, N> const& arr) span_noexcept : data_(arr.data()), | |
size_(to_size(arr.size())) { | |
} | |
#endif // span_HAVE( ARRAY ) | |
#if span_HAVE(CONSTRAINED_SPAN_CONTAINER_CTOR) | |
template <class Container span_REQUIRES_T((detail::is_compatible_container<Container, element_type>::value))> | |
span_constexpr span(Container& cont) : data_(std17::data(cont)), size_(to_size(std17::size(cont))) { | |
} | |
template <class Container span_REQUIRES_T( | |
(std::is_const<element_type>::value && detail::is_compatible_container<Container, element_type>::value))> | |
span_constexpr span(Container const& cont) : data_(std17::data(cont)), size_(to_size(std17::size(cont))) { | |
} | |
#endif // span_HAVE( CONSTRAINED_SPAN_CONTAINER_CTOR ) | |
#if span_FEATURE(WITH_CONTAINER) | |
template <class Container> | |
span_constexpr span(with_container_t, Container& cont) | |
: data_(cont.size() == 0 ? span_nullptr : span_ADDRESSOF(cont[0])), size_(to_size(cont.size())) { | |
} | |
template <class Container> | |
span_constexpr span(with_container_t, Container const& cont) | |
: data_(cont.size() == 0 ? span_nullptr : const_cast<pointer>(span_ADDRESSOF(cont[0]))) | |
, size_(to_size(cont.size())) { | |
} | |
#endif | |
#if span_HAVE(IS_DEFAULT) | |
span_constexpr span(span const& other) span_noexcept = default; | |
~span() span_noexcept = default; | |
span_constexpr14 span& operator=(span const& other) span_noexcept = default; | |
#else | |
span_constexpr span(span const& other) span_noexcept : data_(other.data_), size_(other.size_) { | |
} | |
~span() span_noexcept { | |
} | |
span_constexpr14 span& operator=(span const& other) span_noexcept { | |
data_ = other.data_; | |
size_ = other.size_; | |
return *this; | |
} | |
#endif | |
template <class OtherElementType, | |
extent_type OtherExtent span_REQUIRES_T(((Extent == dynamic_extent || Extent == OtherExtent) | |
&& std::is_convertible<OtherElementType (*)[], element_type (*)[]>::value))> | |
span_constexpr_exp span(span<OtherElementType, OtherExtent> const& other) span_noexcept | |
: data_(reinterpret_cast<pointer>(other.data())), | |
size_(other.size()) { | |
span_EXPECTS(OtherExtent == dynamic_extent || other.size() == to_size(OtherExtent)); | |
} | |
// 26.7.3.3 Subviews [span.sub] | |
template <extent_type Count> | |
span_constexpr_exp span<element_type, Count> first() const { | |
span_EXPECTS(detail::is_positive(Count) && Count <= size()); | |
return span<element_type, Count>(data(), Count); | |
} | |
template <extent_type Count> | |
span_constexpr_exp span<element_type, Count> last() const { | |
span_EXPECTS(detail::is_positive(Count) && Count <= size()); | |
return span<element_type, Count>(data() + (size() - Count), Count); | |
} | |
#if span_HAVE(DEFAULT_FUNCTION_TEMPLATE_ARG) | |
template <size_type Offset, extent_type Count = dynamic_extent> | |
#else | |
template <size_type Offset, extent_type Count /*= dynamic_extent*/> | |
#endif | |
span_constexpr_exp span<element_type, Count> subspan() const { | |
span_EXPECTS((detail::is_positive(Offset) && Offset <= size()) | |
&& (Count == dynamic_extent || (detail::is_positive(Count) && Count + Offset <= size()))); | |
return span<element_type, Count>(data() + Offset, | |
Count != dynamic_extent ? Count : (Extent != dynamic_extent ? Extent - Offset : size() - Offset)); | |
} | |
span_constexpr_exp span<element_type, dynamic_extent> first(size_type count) const { | |
span_EXPECTS(detail::is_positive(count) && count <= size()); | |
return span<element_type, dynamic_extent>(data(), count); | |
} | |
span_constexpr_exp span<element_type, dynamic_extent> last(size_type count) const { | |
span_EXPECTS(detail::is_positive(count) && count <= size()); | |
return span<element_type, dynamic_extent>(data() + (size() - count), count); | |
} | |
span_constexpr_exp span<element_type, dynamic_extent> subspan( | |
size_type offset, size_type count = static_cast<size_type>(dynamic_extent)) const { | |
span_EXPECTS(((detail::is_positive(offset) && offset <= size())) | |
&& (count == static_cast<size_type>(dynamic_extent) | |
|| (detail::is_positive(count) && offset + count <= size()))); | |
return span<element_type, dynamic_extent>( | |
data() + offset, count == static_cast<size_type>(dynamic_extent) ? size() - offset : count); | |
} | |
// 26.7.3.4 Observers [span.obs] | |
span_constexpr size_type size() const span_noexcept { | |
return size_; | |
} | |
span_constexpr std::ptrdiff_t ssize() const span_noexcept { | |
return static_cast<std::ptrdiff_t>(size_); | |
} | |
span_constexpr size_type size_bytes() const span_noexcept { | |
return size() * to_size(sizeof(element_type)); | |
} | |
span_nodiscard span_constexpr bool empty() const span_noexcept { | |
return size() == 0; | |
} | |
// 26.7.3.5 Element access [span.elem] | |
span_constexpr_exp reference operator[](size_type idx) const { | |
span_EXPECTS(detail::is_positive(idx) && idx < size()); | |
return *(data() + idx); | |
} | |
#if span_FEATURE(MEMBER_CALL_OPERATOR) | |
span_deprecated("replace operator() with operator[]") | |
span_constexpr_exp reference | |
operator()(size_type idx) const { | |
span_EXPECTS(detail::is_positive(idx) && idx < size()); | |
return *(data() + idx); | |
} | |
#endif | |
#if span_FEATURE(MEMBER_AT) | |
span_constexpr14 reference at(size_type idx) const { | |
#if span_CONFIG(NO_EXCEPTIONS) | |
return this->operator[](idx); | |
#else | |
if (!detail::is_positive(idx) || size() <= idx) { | |
detail::throw_out_of_range(idx, size()); | |
} | |
return *(data() + idx); | |
#endif | |
} | |
#endif | |
span_constexpr pointer data() const span_noexcept { | |
return data_; | |
} | |
#if span_FEATURE(MEMBER_BACK_FRONT) | |
span_constexpr_exp reference front() const span_noexcept { | |
span_EXPECTS(!empty()); | |
return *data(); | |
} | |
span_constexpr_exp reference back() const span_noexcept { | |
span_EXPECTS(!empty()); | |
return *(data() + size() - 1); | |
} | |
#endif | |
// xx.x.x.x Modifiers [span.modifiers] | |
#if span_FEATURE(MEMBER_SWAP) | |
span_constexpr14 void swap(span& other) span_noexcept { | |
using std::swap; | |
swap(data_, other.data_); | |
swap(size_, other.size_); | |
} | |
#endif | |
// 26.7.3.6 Iterator support [span.iterators] | |
span_constexpr iterator begin() const span_noexcept { | |
#if span_CPP11_OR_GREATER | |
return { data() }; | |
#else | |
return iterator(data()); | |
#endif | |
} | |
span_constexpr iterator end() const span_noexcept { | |
#if span_CPP11_OR_GREATER | |
return { data() + size() }; | |
#else | |
return iterator(data() + size()); | |
#endif | |
} | |
span_constexpr const_iterator cbegin() const span_noexcept { | |
#if span_CPP11_OR_GREATER | |
return { data() }; | |
#else | |
return const_iterator(data()); | |
#endif | |
} | |
span_constexpr const_iterator cend() const span_noexcept { | |
#if span_CPP11_OR_GREATER | |
return { data() + size() }; | |
#else | |
return const_iterator(data() + size()); | |
#endif | |
} | |
span_constexpr reverse_iterator rbegin() const span_noexcept { | |
return reverse_iterator(end()); | |
} | |
span_constexpr reverse_iterator rend() const span_noexcept { | |
return reverse_iterator(begin()); | |
} | |
span_constexpr const_reverse_iterator crbegin() const span_noexcept { | |
return const_reverse_iterator(cend()); | |
} | |
span_constexpr const_reverse_iterator crend() const span_noexcept { | |
return const_reverse_iterator(cbegin()); | |
} | |
private: | |
// Note: C++20 has std::pointer_traits<Ptr>::to_address( it ); | |
#if span_HAVE(ITERATOR_CTOR) | |
static inline span_constexpr pointer to_address(std::nullptr_t) span_noexcept { | |
return nullptr; | |
} | |
template <typename U> | |
static inline span_constexpr U* to_address(U* p) span_noexcept { | |
return p; | |
} | |
template <typename Ptr span_REQUIRES_T((!std::is_pointer<Ptr>::value))> | |
static inline span_constexpr pointer to_address(Ptr const& it) span_noexcept { | |
return to_address(it.operator->()); | |
} | |
#endif // span_HAVE( ITERATOR_CTOR ) | |
private: | |
pointer data_; | |
size_type size_; | |
}; | |
// class template argument deduction guides: | |
#if span_HAVE(DEDUCTION_GUIDES) | |
template <class T, size_t N> | |
span(T (&)[N]) -> span<T, static_cast<extent_t>(N)>; | |
template <class T, size_t N> | |
span(std::array<T, N>&) -> span<T, static_cast<extent_t>(N)>; | |
template <class T, size_t N> | |
span(std::array<T, N> const&) -> span<const T, static_cast<extent_t>(N)>; | |
#if span_HAVE(CONSTRAINED_SPAN_CONTAINER_CTOR) | |
template <class Container> | |
span(Container&) -> span<typename Container::value_type>; | |
template <class Container> | |
span(Container const&) -> span<const typename Container::value_type>; | |
#endif | |
// iterator: constraints: It satisfies contiguous_iterator. | |
template <class It, class EndOrSize> | |
span(It, EndOrSize) -> span<typename std11::remove_reference<typename std20::iter_reference_t<It>>::type>; | |
#endif // span_HAVE( DEDUCTION_GUIDES ) | |
// 26.7.3.7 Comparison operators [span.comparison] | |
#if span_FEATURE(COMPARISON) | |
#if span_FEATURE(SAME) | |
template <class T1, extent_t E1, class T2, extent_t E2> | |
inline span_constexpr bool same(span<T1, E1> const& l, span<T2, E2> const& r) span_noexcept { | |
return std11::is_same<T1, T2>::value && l.size() == r.size() | |
&& static_cast<void const*>(l.data()) == r.data(); | |
} | |
#endif | |
template <class T1, extent_t E1, class T2, extent_t E2> | |
inline span_constexpr bool operator==(span<T1, E1> const& l, span<T2, E2> const& r) { | |
return | |
#if span_FEATURE(SAME) | |
same(l, r) || | |
#endif | |
(l.size() == r.size() && std::equal(l.begin(), l.end(), r.begin())); | |
} | |
template <class T1, extent_t E1, class T2, extent_t E2> | |
inline span_constexpr bool operator<(span<T1, E1> const& l, span<T2, E2> const& r) { | |
return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); | |
} | |
template <class T1, extent_t E1, class T2, extent_t E2> | |
inline span_constexpr bool operator!=(span<T1, E1> const& l, span<T2, E2> const& r) { | |
return !(l == r); | |
} | |
template <class T1, extent_t E1, class T2, extent_t E2> | |
inline span_constexpr bool operator<=(span<T1, E1> const& l, span<T2, E2> const& r) { | |
return !(r < l); | |
} | |
template <class T1, extent_t E1, class T2, extent_t E2> | |
inline span_constexpr bool operator>(span<T1, E1> const& l, span<T2, E2> const& r) { | |
return (r < l); | |
} | |
template <class T1, extent_t E1, class T2, extent_t E2> | |
inline span_constexpr bool operator>=(span<T1, E1> const& l, span<T2, E2> const& r) { | |
return !(l < r); | |
} | |
#endif // span_FEATURE( COMPARISON ) | |
// 26.7.2.6 views of object representation [span.objectrep] | |
#if span_HAVE(BYTE) || span_HAVE(NONSTD_BYTE) | |
// Avoid MSVC 14.1 (1910), VS 2017: warning C4307: '*': integral constant overflow: | |
template <typename T, extent_t Extent> | |
struct BytesExtent { | |
#if span_CPP11_OR_GREATER | |
enum ET : extent_t { value = span_sizeof(T) * Extent }; | |
#else | |
enum ET { value = span_sizeof(T) * Extent }; | |
#endif | |
}; | |
template <typename T> | |
struct BytesExtent<T, dynamic_extent> { | |
#if span_CPP11_OR_GREATER | |
enum ET : extent_t { value = dynamic_extent }; | |
#else | |
enum ET { value = dynamic_extent }; | |
#endif | |
}; | |
template <class T, extent_t Extent> | |
inline span_constexpr span<const std17::byte, BytesExtent<T, Extent>::value> as_bytes( | |
span<T, Extent> spn) span_noexcept { | |
#if 0 | |
return { reinterpret_cast< std17::byte const * >( spn.data() ), spn.size_bytes() }; | |
#else | |
return span<const std17::byte, BytesExtent<T, Extent>::value>( | |
reinterpret_cast<std17::byte const*>(spn.data()), spn.size_bytes()); // NOLINT | |
#endif | |
} | |
template <class T, extent_t Extent> | |
inline span_constexpr span<std17::byte, BytesExtent<T, Extent>::value> as_writable_bytes( | |
span<T, Extent> spn) span_noexcept { | |
#if 0 | |
return { reinterpret_cast< std17::byte * >( spn.data() ), spn.size_bytes() }; | |
#else | |
return span<std17::byte, BytesExtent<T, Extent>::value>( | |
reinterpret_cast<std17::byte*>(spn.data()), spn.size_bytes()); // NOLINT | |
#endif | |
} | |
#endif // span_HAVE( BYTE ) || span_HAVE( NONSTD_BYTE ) | |
// 27.8 Container and view access [iterator.container] | |
template <class T, extent_t Extent /*= dynamic_extent*/> | |
span_constexpr std::size_t size(span<T, Extent> const& spn) { | |
return static_cast<std::size_t>(spn.size()); | |
} | |
template <class T, extent_t Extent /*= dynamic_extent*/> | |
span_constexpr std::ptrdiff_t ssize(span<T, Extent> const& spn) { | |
return static_cast<std::ptrdiff_t>(spn.size()); | |
} | |
}} // namespace nonstd::span_lite | |
namespace nonstd { | |
using span_lite::dynamic_extent; | |
using span_lite::span; | |
using span_lite::with_container; | |
#if span_FEATURE(COMPARISON) | |
#if span_FEATURE(SAME) | |
using span_lite::same; | |
#endif | |
using span_lite::operator==; | |
using span_lite::operator!=; | |
using span_lite::operator<; | |
using span_lite::operator<=; | |
using span_lite::operator>; | |
using span_lite::operator>=; | |
#endif | |
#if span_HAVE(BYTE) | |
using span_lite::as_bytes; | |
using span_lite::as_writable_bytes; | |
#endif | |
using span_lite::size; | |
using span_lite::ssize; | |
} // namespace nonstd | |
#endif // span_USES_STD_SPAN | |
#if span_FEATURE(MAKE_SPAN) || span_FEATURE(NON_MEMBER_FIRST_LAST_SUB_SPAN) \ | |
|| span_FEATURE(NON_MEMBER_FIRST_LAST_SUB_CONTAINER) | |
#if span_USES_STD_SPAN | |
#define span_constexpr constexpr | |
#define span_noexcept noexcept | |
#define span_nullptr nullptr | |
#ifndef span_CONFIG_EXTENT_TYPE | |
#define span_CONFIG_EXTENT_TYPE std::size_t | |
#endif | |
using extent_t = span_CONFIG_EXTENT_TYPE; | |
#endif // span_USES_STD_SPAN | |
namespace nonstd { namespace span_lite { | |
template <class T> | |
inline span_constexpr span<T> make_span(T* ptr, size_t count) span_noexcept { | |
return span<T>(ptr, count); | |
} | |
template <class T> | |
inline span_constexpr span<T> make_span(T* first, T* last) span_noexcept { | |
return span<T>(first, last); | |
} | |
template <class T, std::size_t N> | |
inline span_constexpr span<T, static_cast<extent_t>(N)> make_span(T (&arr)[N]) span_noexcept { | |
return span<T, static_cast<extent_t>(N)>(&arr[0], N); | |
} | |
#if span_USES_STD_SPAN || span_HAVE(ARRAY) | |
template <class T, std::size_t N> | |
inline span_constexpr span<T, static_cast<extent_t>(N)> make_span(std::array<T, N>& arr) span_noexcept { | |
return span<T, static_cast<extent_t>(N)>(arr); | |
} | |
template <class T, std::size_t N> | |
inline span_constexpr span<const T, static_cast<extent_t>(N)> make_span( | |
std::array<T, N> const& arr) span_noexcept { | |
return span<const T, static_cast<extent_t>(N)>(arr); | |
} | |
#endif // span_HAVE( ARRAY ) | |
#if span_USES_STD_SPAN | |
template <class Container, class EP = decltype(std::data(std::declval<Container&>()))> | |
inline span_constexpr auto make_span(Container& cont) span_noexcept | |
-> span<typename std::remove_pointer<EP>::type> { | |
return span<typename std::remove_pointer<EP>::type>(cont); | |
} | |
template <class Container, class EP = decltype(std::data(std::declval<Container&>()))> | |
inline span_constexpr auto make_span(Container const& cont) span_noexcept | |
-> span<const typename std::remove_pointer<EP>::type> { | |
return span<const typename std::remove_pointer<EP>::type>(cont); | |
} | |
#elif span_HAVE(CONSTRAINED_SPAN_CONTAINER_CTOR) && span_HAVE(AUTO) | |
template <class Container, class EP = decltype(std17::data(std::declval<Container&>()))> | |
inline span_constexpr auto make_span(Container& cont) span_noexcept | |
-> span<typename std::remove_pointer<EP>::type> { | |
return span<typename std::remove_pointer<EP>::type>(cont); | |
} | |
template <class Container, class EP = decltype(std17::data(std::declval<Container&>()))> | |
inline span_constexpr auto make_span(Container const& cont) span_noexcept | |
-> span<const typename std::remove_pointer<EP>::type> { | |
return span<const typename std::remove_pointer<EP>::type>(cont); | |
} | |
#else | |
template <class T> | |
inline span_constexpr span<T> make_span(span<T> spn) span_noexcept { | |
return spn; | |
} | |
template <class T, class Allocator> | |
inline span_constexpr span<T> make_span(std::vector<T, Allocator>& cont) span_noexcept { | |
return span<T>(with_container, cont); | |
} | |
template <class T, class Allocator> | |
inline span_constexpr span<const T> make_span(std::vector<T, Allocator> const& cont) span_noexcept { | |
return span<const T>(with_container, cont); | |
} | |
#endif // span_USES_STD_SPAN || ( ... ) | |
#if !span_USES_STD_SPAN && span_FEATURE(WITH_CONTAINER) | |
template <class Container> | |
inline span_constexpr span<typename Container::value_type> make_span( | |
with_container_t, Container& cont) span_noexcept { | |
return span<typename Container::value_type>(with_container, cont); | |
} | |
template <class Container> | |
inline span_constexpr span<const typename Container::value_type> make_span( | |
with_container_t, Container const& cont) span_noexcept { | |
return span<const typename Container::value_type>(with_container, cont); | |
} | |
#endif // ! span_USES_STD_SPAN && span_FEATURE( WITH_CONTAINER ) | |
// extensions: non-member views: | |
// this feature implies the presence of make_span() | |
#if span_FEATURE(NON_MEMBER_FIRST_LAST_SUB_SPAN) | |
template <extent_t Count, class T, extent_t Extent> | |
span_constexpr span<T, Count> first(span<T, Extent> spn) { | |
return spn.template first<Count>(); | |
} | |
template <class T, extent_t Extent> | |
span_constexpr span<T> first(span<T, Extent> spn, size_t count) { | |
return spn.first(count); | |
} | |
template <extent_t Count, class T, extent_t Extent> | |
span_constexpr span<T, Count> last(span<T, Extent> spn) { | |
return spn.template last<Count>(); | |
} | |
template <class T, extent_t Extent> | |
span_constexpr span<T> last(span<T, Extent> spn, size_t count) { | |
return spn.last(count); | |
} | |
template <size_t Offset, extent_t Count, class T, extent_t Extent> | |
span_constexpr span<T, Count> subspan(span<T, Extent> spn) { | |
return spn.template subspan<Offset, Count>(); | |
} | |
template <class T, extent_t Extent> | |
span_constexpr span<T> subspan(span<T, Extent> spn, size_t offset, extent_t count = dynamic_extent) { | |
return spn.subspan(offset, count); | |
} | |
#endif // span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_SPAN ) | |
#if span_FEATURE(NON_MEMBER_FIRST_LAST_SUB_CONTAINER) && span_CPP11_120 | |
template <extent_t Count, class T> | |
span_constexpr auto first(T& t) -> decltype(make_span(t).template first<Count>()) { | |
return make_span(t).template first<Count>(); | |
} | |
template <class T> | |
span_constexpr auto first(T& t, size_t count) -> decltype(make_span(t).first(count)) { | |
return make_span(t).first(count); | |
} | |
template <extent_t Count, class T> | |
span_constexpr auto last(T& t) -> decltype(make_span(t).template last<Count>()) { | |
return make_span(t).template last<Count>(); | |
} | |
template <class T> | |
span_constexpr auto last(T& t, extent_t count) -> decltype(make_span(t).last(count)) { | |
return make_span(t).last(count); | |
} | |
template <size_t Offset, extent_t Count = dynamic_extent, class T> | |
span_constexpr auto subspan(T& t) -> decltype(make_span(t).template subspan<Offset, Count>()) { | |
return make_span(t).template subspan<Offset, Count>(); | |
} | |
template <class T> | |
span_constexpr auto subspan(T& t, size_t offset, extent_t count = dynamic_extent) | |
-> decltype(make_span(t).subspan(offset, count)) { | |
return make_span(t).subspan(offset, count); | |
} | |
#endif // span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_CONTAINER ) | |
}} // namespace nonstd::span_lite | |
namespace nonstd { | |
using span_lite::make_span; | |
#if span_FEATURE(NON_MEMBER_FIRST_LAST_SUB_SPAN) \ | |
|| (span_FEATURE(NON_MEMBER_FIRST_LAST_SUB_CONTAINER) && span_CPP11_120) | |
using span_lite::first; | |
using span_lite::last; | |
using span_lite::subspan; | |
#endif // span_FEATURE( NON_MEMBER_FIRST_LAST_SUB_[SPAN|CONTAINER] ) | |
} // namespace nonstd | |
#endif // #if span_FEATURE_TO_STD( MAKE_SPAN ) | |
#if span_CPP11_OR_GREATER && span_FEATURE(BYTE_SPAN) && (span_HAVE(BYTE) || span_HAVE(NONSTD_BYTE)) | |
namespace nonstd { namespace span_lite { | |
template <class T> | |
inline span_constexpr auto byte_span(T& t) span_noexcept -> span<std17::byte, span_sizeof(T)> { | |
return span<std17::byte, span_sizeof(t)>(reinterpret_cast<std17::byte*>(&t), span_sizeof(T)); | |
} | |
template <class T> | |
inline span_constexpr auto byte_span(T const& t) span_noexcept -> span<const std17::byte, span_sizeof(T)> { | |
return span<const std17::byte, span_sizeof(t)>(reinterpret_cast<std17::byte const*>(&t), span_sizeof(T)); | |
} | |
}} // namespace nonstd::span_lite | |
namespace nonstd { | |
using span_lite::byte_span; | |
} // namespace nonstd | |
#endif // span_FEATURE( BYTE_SPAN ) | |
#if span_HAVE(STRUCT_BINDING) | |
#if span_CPP14_OR_GREATER | |
#include <tuple> | |
#elif span_CPP11_OR_GREATER | |
#include <tuple> | |
namespace std { | |
template <std::size_t I, typename T> | |
using tuple_element_t = typename tuple_element<I, T>::type; | |
} | |
#else | |
namespace std { | |
template <typename T> | |
class tuple_size; /*undefined*/ | |
template <std::size_t I, typename T> | |
class tuple_element; /* undefined */ | |
} // namespace std | |
#endif // span_CPP14_OR_GREATER | |
namespace std { | |
// 26.7.X Tuple interface | |
// std::tuple_size<>: | |
template <typename ElementType, nonstd::span_lite::extent_t Extent> | |
class tuple_size<nonstd::span<ElementType, Extent>> | |
: public integral_constant<size_t, static_cast<size_t>(Extent)> { }; | |
// std::tuple_size<>: Leave undefined for dynamic extent: | |
template <typename ElementType> | |
class tuple_size<nonstd::span<ElementType, nonstd::dynamic_extent>>; | |
// std::tuple_element<>: | |
template <size_t I, typename ElementType, nonstd::span_lite::extent_t Extent> | |
class tuple_element<I, nonstd::span<ElementType, Extent>> { | |
public: | |
#if span_HAVE(STATIC_ASSERT) | |
static_assert(Extent != nonstd::dynamic_extent && I < Extent, | |
"tuple_element<I,span>: dynamic extent or index out of range"); | |
#endif | |
using type = ElementType; | |
}; | |
// std::get<>(), 2 variants: | |
template <size_t I, typename ElementType, nonstd::span_lite::extent_t Extent> | |
span_constexpr ElementType& get(nonstd::span<ElementType, Extent>& spn) span_noexcept { | |
#if span_HAVE(STATIC_ASSERT) | |
static_assert( | |
Extent != nonstd::dynamic_extent && I < Extent, "get<>(span): dynamic extent or index out of range"); | |
#endif | |
return spn[I]; | |
} | |
template <size_t I, typename ElementType, nonstd::span_lite::extent_t Extent> | |
span_constexpr ElementType const& get(nonstd::span<ElementType, Extent> const& spn) span_noexcept { | |
#if span_HAVE(STATIC_ASSERT) | |
static_assert( | |
Extent != nonstd::dynamic_extent && I < Extent, "get<>(span): dynamic extent or index out of range"); | |
#endif | |
return spn[I]; | |
} | |
} // end namespace std | |
#endif // span_HAVE( STRUCT_BINDING ) | |
#if !span_USES_STD_SPAN | |
span_RESTORE_WARNINGS() | |
#endif // span_USES_STD_SPAN | |
#endif // NONSTD_SPAN_HPP_INCLUDED | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/span.implementation.hpp | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @brief dynamic extent copycat | |
/// | |
////// | |
inline constexpr decltype(::nonstd::dynamic_extent) dynamic_extent = ::nonstd::dynamic_extent; | |
using ::nonstd::as_bytes; | |
using ::nonstd::as_writable_bytes; | |
using ::nonstd::span; | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
#endif | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _Ty> | |
class __is_std_span : public ::std::false_type { }; | |
template <typename _Ty, decltype(::ztd::text::dynamic_extent) _N> | |
class __is_std_span<::ztd::text::span<_Ty, _N>> : public ::std::true_type { }; | |
template <typename _Ty> | |
inline constexpr bool __is_std_span_v = __is_std_span<_Ty>::value; | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/span.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/empty_string.hpp | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
using __uchar_one_t = unsigned char[1]; | |
inline constexpr const __uchar_one_t __u_shim = {}; | |
using __schar_one_t = signed char[1]; | |
inline constexpr const __schar_one_t __s_shim = {}; | |
template <typename C> | |
inline constexpr decltype(auto) __empty_string() noexcept { | |
static_assert(__always_false_v<C>, "unrecognized character type"); | |
return ""; | |
} | |
template <> | |
inline constexpr decltype(auto) __empty_string<char>() noexcept { | |
return ""; | |
} | |
template <> | |
inline constexpr decltype(auto) __empty_string<unsigned char>() noexcept { | |
return (__u_shim); | |
} | |
template <> | |
inline constexpr decltype(auto) __empty_string<signed char>() noexcept { | |
return (__s_shim); | |
} | |
template <> | |
inline constexpr decltype(auto) __empty_string<wchar_t>() noexcept { | |
return L""; | |
} | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_NATIVE_CHAR8_T_I_) | |
template <> | |
inline constexpr decltype(auto) __empty_string<char8_t>() noexcept { | |
return u8""; | |
} | |
#endif | |
template <> | |
inline constexpr decltype(auto) __empty_string<char16_t>() noexcept { | |
return u""; | |
} | |
template <> | |
inline constexpr decltype(auto) __empty_string<char32_t>() noexcept { | |
return U""; | |
} | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/empty_string.hpp | |
#include <iterator> | |
#include <utility> | |
#include <type_traits> | |
#include <string_view> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _Ty, decltype(::ztd::text::dynamic_extent) _Extent, typename _It, typename _Sen, | |
::std::enable_if_t< | |
__is_iterator_contiguous_iterator_v< | |
_It> && ((::std::is_const_v<::std::remove_reference_t<__iterator_reference_t<_It>>>) ? std::is_const_v<_Ty> : true)>* = nullptr> | |
constexpr ::ztd::text::span<_Ty> reconstruct( | |
::std::in_place_type_t<::ztd::text::span<_Ty, _Extent>>, _It __iterator, _Sen __sentinel) noexcept { | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_SPAN_I_) | |
return ::ztd::text::span<_Ty>(__iterator, __sentinel); | |
#else | |
if constexpr (!::std::is_integral_v<_Sen>) { | |
auto __iterator_address = __adl::__adl_to_address(__iterator); | |
auto __sentinel_address = __adl::__adl_to_address(__sentinel); | |
return ::ztd::text::span<_Ty>(__iterator_address, __sentinel_address - __iterator_address); | |
} | |
else { | |
auto __iterator_address = __adl::__adl_to_address(__iterator); | |
return ::ztd::text::span<_Ty>(__iterator_address, __sentinel); | |
} | |
#endif | |
} | |
template <typename _Ty, typename _Traits, typename _It, typename _Sen, | |
::std::enable_if_t<__is_iterator_contiguous_iterator_v<_It>>* = nullptr> | |
constexpr ::std::basic_string_view<_Ty, _Traits> reconstruct( | |
::std::in_place_type_t<::std::basic_string_view<_Ty, _Traits>>, _It __iterator, | |
_Sen __sentinel) noexcept { | |
using _SizeType = typename ::std::basic_string_view<_Ty, _Traits>::size_type; | |
if constexpr (!::std::is_integral_v<_Sen>) { | |
_SizeType __ptr_size = static_cast<_SizeType>(__sentinel - __iterator); | |
#if defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL >= 1 | |
if (__ptr_size == static_cast<_SizeType>(0)) { | |
const auto& __empty_str = __empty_string<_Ty>(); | |
return ::std::basic_string_view<_Ty, _Traits>(__empty_str + 0, 0); | |
} | |
#endif | |
return ::std::basic_string_view<_Ty, _Traits>(::std::addressof(*__iterator), __ptr_size); | |
} | |
else { | |
#if defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL >= 1 | |
if (static_cast<_SizeType>(__sentinel) == static_cast<_SizeType>(0)) { | |
const auto& __empty_str = __empty_string<_Ty>(); | |
return ::std::basic_string_view<_Ty, _Traits>(__empty_str + 0, 0); | |
} | |
#endif | |
return ::std::basic_string_view<_Ty, _Traits>( | |
::std::addressof(*__iterator), static_cast<_SizeType>(__sentinel)); | |
} | |
} | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/reconstruct.types.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/reconstruct.cpo.hpp | |
#include <iterator> | |
#include <utility> | |
#include <type_traits> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _It, typename _Sen> | |
constexpr auto __adl_iterator_reconstruct(_It&& __iterator, _Sen&& __sentinel) noexcept( | |
noexcept(reconstruct(::std::declval<_It>(), ::std::declval<_Sen>()))) | |
-> decltype(reconstruct(::std::declval<_It>(), ::std::declval<_Sen>())) { | |
return reconstruct(::std::forward<_It>(__iterator), ::std::forward<_Sen>(__sentinel)); | |
} | |
template <typename _Tag, typename _It, typename _Sen> | |
constexpr auto __adl_reconstruct(::std::in_place_type_t<_Tag> __ty, _It&& __iterator, | |
_Sen&& __sentinel) noexcept(noexcept(reconstruct(__ty, ::std::declval<_It>(), ::std::declval<_Sen>()))) | |
-> decltype(reconstruct(__ty, ::std::declval<_It>(), ::std::declval<_Sen>())) { | |
return reconstruct(__ty, ::std::forward<_It>(__iterator), ::std::forward<_Sen>(__sentinel)); | |
} | |
template <typename _Tag, typename _InRange, typename _It, typename _Sen> | |
constexpr auto __adl_range_iterator_reconstruct(::std::in_place_type_t<_Tag> __ty, _InRange&& __in_range, | |
_It&& __iterator, | |
_Sen&& __sentinel) noexcept(noexcept(reconstruct(__ty, ::std::forward<_InRange>(__in_range)))) | |
-> decltype(reconstruct(__ty, ::std::forward<_InRange>(__in_range), ::std::forward<_It>(__iterator), | |
::std::forward<_Sen>(__sentinel))) { | |
return reconstruct(__ty, ::std::forward<_InRange>(__in_range), ::std::forward<_It>(__iterator), | |
::std::forward<_Sen>(__sentinel)); | |
} | |
template <typename _Tag, typename _Range> | |
constexpr auto __adl_range_reconstruct(::std::in_place_type_t<_Tag> __ty, _Range&& __in_range) noexcept( | |
noexcept(reconstruct(__ty, ::std::forward<_Range>(__in_range)))) | |
-> decltype(reconstruct(__ty, ::std::forward<_Range>(__in_range))) { | |
return reconstruct(__ty, ::std::forward<_Range>(__in_range)); | |
} | |
template <typename _It, typename _Sen> | |
using __detect_is_iterator_reconstructible_range | |
= decltype(__adl_iterator_reconstruct(::std::declval<_It>(), ::std::declval<_Sen>())); | |
template <typename _Tag, typename _It, typename _Sen> | |
using __detect_is_reconstructible_range = decltype(__adl_reconstruct( | |
::std::in_place_type<__remove_cvref_t<_Tag>>, ::std::declval<_It>(), ::std::declval<_Sen>())); | |
template <typename _Tag, typename _Range, typename _It, typename _Sen> | |
using __detect_is_range_iterator_reconstructible_range | |
= decltype(__adl_range_iterator_reconstruct(::std::in_place_type<__remove_cvref_t<_Tag>>, | |
::std::declval<_Range>(), ::std::declval<_It>(), ::std::declval<_Sen>())); | |
template <typename _Tag, typename _Range> | |
using __detect_is_range_reconstructible_range = decltype(__adl_range_reconstruct( | |
::std::in_place_type<__remove_cvref_t<_Tag>>, ::std::declval<_Range>())); | |
template <typename _It, typename _Sen> | |
using __is_iterator_reconstructible_range = ::std::integral_constant<bool, | |
__is_detected<__detect_is_iterator_reconstructible_range, _It, _Sen>::value | |
&& (::std::is_class_v<__remove_cvref_t< | |
_It>> || std::is_enum_v<__remove_cvref_t<_It>> || ::std::is_class_v<__remove_cvref_t<_Sen>> || std::is_enum_v<__remove_cvref_t<_Sen>>)>; | |
template <typename _Tag, typename _It, typename _Sen> | |
using __is_reconstructible_range = __is_detected<__detect_is_reconstructible_range, _Tag, _It, _Sen>; | |
template <typename _Tag, typename _Range, typename _It, typename _Sen> | |
using __is_range_iterator_reconstructible_range | |
= __is_detected<__detect_is_range_iterator_reconstructible_range, _Tag, _Range, _It, _Sen>; | |
template <typename _Tag, typename _Range> | |
using __is_range_reconstructible_range = __is_detected<__detect_is_range_reconstructible_range, _Tag, _Range>; | |
template <typename _It, typename _Sen> | |
inline constexpr bool __is_iterator_reconstructible_range_v | |
= __is_iterator_reconstructible_range<_It, _Sen>::value; | |
template <typename _Tag, typename _It, typename _Sen> | |
inline constexpr bool __is_reconstructible_range_v = __is_reconstructible_range<_Tag, _It, _Sen>::value; | |
template <typename _Tag, typename _Range, typename _It, typename _Sen> | |
inline constexpr bool __is_range_iterator_reconstructible_range_v | |
= __is_range_iterator_reconstructible_range<_Tag, _Range, _It, _Sen>::value; | |
template <typename _Tag, typename _Range> | |
inline constexpr bool __is_range_reconstructible_range_v | |
= __is_range_reconstructible_range<_Tag, _Range>::value; | |
template <typename _It, typename _Sen, typename = void> | |
class __is_nothrow_iterator_reconstructible_range : public ::std::false_type { }; | |
template <typename _It, typename _Sen> | |
class __is_nothrow_iterator_reconstructible_range<_It, _Sen, | |
::std::enable_if_t<__is_iterator_reconstructible_range_v<_It, _Sen>>> | |
: public ::std::integral_constant<bool, | |
noexcept(__adl_iterator_reconstruct(::std::declval<_It>(), ::std::declval<_Sen>()))> { }; | |
template <typename _It, typename _Sen> | |
inline constexpr bool __is_nothrow_iterator_reconstructible_range_v | |
= __is_nothrow_iterator_reconstructible_range<_It, _Sen>::value; | |
template <typename _Tag, typename _It, typename _Sen, typename = void> | |
class __is_nothrow_reconstructible_range : public ::std::false_type { }; | |
template <typename _Tag, typename _It, typename _Sen> | |
class __is_nothrow_reconstructible_range<_Tag, _It, _Sen, | |
::std::enable_if_t<__is_reconstructible_range_v<_Tag, _It, _Sen>>> | |
: public ::std::integral_constant<bool, | |
noexcept(__adl_reconstruct(::std::in_place_type<__remove_cvref_t<_Tag>>, ::std::declval<_It>(), | |
::std::declval<_Sen>()))> { }; | |
template <typename _Tag, typename _It, typename _Sen> | |
inline constexpr bool __is_nothrow_reconstructible_range_v | |
= __is_nothrow_reconstructible_range<_Tag, _It, _Sen>::value; | |
template <typename _Tag, typename _Range, typename _It, typename _Sen, typename = void> | |
class __is_nothrow_range_iterator_reconstructible_range : public ::std::false_type { }; | |
template <typename _Tag, typename _Range, typename _It, typename _Sen> | |
class __is_nothrow_range_iterator_reconstructible_range<_Tag, _Range, _It, _Sen, | |
::std::enable_if_t<__is_range_iterator_reconstructible_range_v<_Tag, _Range, _It, _Sen>>> | |
: public ::std::integral_constant<bool, | |
noexcept(__adl_range_iterator_reconstruct(::std::in_place_type<__remove_cvref_t<_Tag>>, | |
::std::declval<_Range>(), ::std::declval<_It>(), ::std::declval<_Sen>()))> { }; | |
template <typename _Tag, typename _Range, typename _It, typename _Sen> | |
inline constexpr bool __is_nothrow_range_iterator_reconstructible_range_v | |
= __is_nothrow_range_iterator_reconstructible_range<_Tag, _Range, _It, _Sen>::value; | |
template <typename _Tag, typename _Range, typename = void> | |
class __is_nothrow_range_reconstructible_range : public ::std::false_type { }; | |
template <typename _Tag, typename _Range> | |
class __is_nothrow_range_reconstructible_range<_Tag, _Range, | |
::std::enable_if_t<__is_range_reconstructible_range_v<_Tag, _Range>>> | |
: public ::std::integral_constant<bool, | |
noexcept(__adl_range_reconstruct( | |
::std::in_place_type<__remove_cvref_t<_Tag>>, ::std::declval<_Range>()))> { }; | |
template <typename _Tag, typename _Range> | |
inline constexpr bool __is_nothrow_range_reconstructible_range_v | |
= __is_nothrow_range_reconstructible_range<_Tag, _Range>::value; | |
struct __reconstruct_cpo { | |
private: | |
template <typename _Tag, typename _It, typename _Sen> | |
static constexpr bool __reconstruct_noexcept() noexcept { | |
if constexpr (__is_reconstructible_range_v<_Tag, _It, _Sen>) { | |
return __is_nothrow_reconstructible_range_v<_Tag, _It, _Sen>; | |
} | |
else { | |
return __range_reconstruct_or_iterator_reconstruct_noexcept<_It, _Sen>(); | |
} | |
} | |
template <typename _Tag, typename _Range, typename _It, typename _Sen> | |
static constexpr bool __range_iterator_reconstruct_noexcept() noexcept { | |
if constexpr (__is_range_iterator_reconstructible_range_v<_Tag, _Range, _It, _Sen>) { | |
return __is_nothrow_range_iterator_reconstructible_range_v<_Tag, _Range, _It, _Sen>; | |
} | |
else { | |
return __reconstruct_noexcept<_Tag, _It, _Sen>(); | |
} | |
} | |
template <typename _TagOrIt, typename _RangeOrSen> | |
static constexpr bool __range_reconstruct_or_iterator_reconstruct_noexcept() noexcept { | |
if constexpr (__is_specialization_of_v<__remove_cvref_t<_TagOrIt>, ::std::in_place_type_t>) { | |
if constexpr (__is_range_reconstructible_range_v<_TagOrIt, _RangeOrSen>) { | |
return __is_nothrow_range_reconstructible_range_v<_TagOrIt, _RangeOrSen>; | |
} | |
else { | |
using _It = __range_iterator_t<_RangeOrSen>; | |
using _Sen = __range_sentinel_t<_RangeOrSen>; | |
return __range_iterator_reconstruct_noexcept<_TagOrIt, _RangeOrSen, _It, _Sen>(); | |
} | |
} | |
else { | |
if constexpr (__is_iterator_reconstructible_range_v<_TagOrIt, _RangeOrSen>) { | |
return __is_nothrow_iterator_reconstructible_range_v<_TagOrIt, _RangeOrSen>; | |
} | |
else if (::std::is_constructible_v< | |
::ztd::text::subrange<__remove_cvref_t<_TagOrIt>, __remove_cvref_t<_RangeOrSen>>, | |
_TagOrIt, _RangeOrSen>) { | |
return ::std::is_nothrow_constructible_v< | |
::ztd::text::subrange<__remove_cvref_t<_TagOrIt>, __remove_cvref_t<_RangeOrSen>>, | |
_TagOrIt, _RangeOrSen>; | |
} | |
else { | |
return false; | |
} | |
} | |
} | |
public: | |
template <typename _Tag, typename _It, typename _Sen> | |
constexpr auto operator()(::std::in_place_type_t<_Tag> __ty, _It&& __iterator, _Sen&& __sentinel) const | |
noexcept(__reconstruct_noexcept<_Tag, _It, _Sen>()) { | |
if constexpr (__is_reconstructible_range_v<_Tag, _It, _Sen>) { | |
return __adl_reconstruct( | |
__ty, ::std::forward<_It>(__iterator), ::std::forward<_Sen>(__sentinel)); | |
} | |
else { | |
return (*this)(::std::forward<_It>(__iterator), ::std::forward<_Sen>(__sentinel)); | |
} | |
} | |
template <typename _Tag, typename _Range, typename _It, typename _Sen> | |
constexpr decltype(auto) operator()(::std::in_place_type_t<_Tag> __tag, _Range&& __range, _It&& __it, | |
_Sen&& __sen) const noexcept(__range_iterator_reconstruct_noexcept<_Tag, _Range, _It, _Sen>()) { | |
if constexpr (__is_range_iterator_reconstructible_range_v<_Tag, _Range, _It, _Sen>) { | |
return __adl_range_iterator_reconstruct(__tag, ::std::forward<_Range>(__range), | |
::std::forward<_It>(__it), ::std::forward<_Sen>(__sen)); | |
} | |
else { | |
return (*this)(__tag, ::std::forward<_It>(__it), ::std::forward<_Sen>(__sen)); | |
} | |
} | |
template <typename _TagOrIt, typename _RangeOrSen> | |
constexpr decltype(auto) operator()( | |
_TagOrIt&& __tag_or_iterator, _RangeOrSen&& __range_or_sentinel) const | |
noexcept(__range_reconstruct_or_iterator_reconstruct_noexcept<_TagOrIt, _RangeOrSen>()) { | |
if constexpr (__is_specialization_of_v<__remove_cvref_t<_TagOrIt>, ::std::in_place_type_t>) { | |
if constexpr (__is_range_reconstructible_range_v<_TagOrIt, _RangeOrSen>) { | |
return __adl_range_reconstruct( | |
__tag_or_iterator, ::std::forward<_RangeOrSen>(__range_or_sentinel)); | |
} | |
else { | |
return (*this)(__tag_or_iterator, ::std::forward<_RangeOrSen>(__range_or_sentinel), | |
__adl::__adl_begin(__range_or_sentinel), __adl::__adl_end(__range_or_sentinel)); | |
} | |
} | |
else if constexpr (__is_iterator_reconstructible_range_v<_TagOrIt, _RangeOrSen>) { | |
return __adl_iterator_reconstruct(::std::forward<_TagOrIt>(__tag_or_iterator), | |
::std::forward<_RangeOrSen>(__range_or_sentinel)); | |
} | |
else { | |
return subrange<__remove_cvref_t<_TagOrIt>, __remove_cvref_t<_RangeOrSen>>( | |
::std::forward<_TagOrIt>(__tag_or_iterator), | |
::std::forward<_RangeOrSen>(__range_or_sentinel)); | |
} | |
} | |
} inline constexpr __reconstruct = {}; | |
template <typename _Tag, typename _It = __range_iterator_t<__remove_cvref_t<_Tag>>, | |
typename _Sen = __range_sentinel_t<__remove_cvref_t<_Tag>>> | |
using __reconstruct_t = decltype(__reconstruct(::std::in_place_type<__remove_cvref_t<_Tag>>, | |
::std::declval<__remove_cvref_t<_It>>(), ::std::declval<__remove_cvref_t<_Sen>>())); | |
template <typename _Range, typename _Tag = __remove_cvref_t<_Range>> | |
using __range_reconstruct_t = decltype(__reconstruct(::std::in_place_type<_Tag>, ::std::declval<_Range>())); | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/reconstruct.cpo.hpp | |
#include <string_view> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _Input> | |
constexpr bool __span_or_reconstruct_noexcept() { | |
using _UInput = __remove_cvref_t<_Input>; | |
if constexpr (::std::is_array_v<_UInput> && ::std::is_lvalue_reference_v<_Input>) { | |
return true; | |
} | |
else if constexpr (__is_iterator_contiguous_iterator_v<__range_iterator_t<_Input>>) { | |
return true; | |
} | |
else { | |
return noexcept(__reconstruct(::std::in_place_type<_UInput>, ::std::declval<_Input>())); | |
} | |
} | |
template <typename _Input> | |
constexpr bool __string_view_or_span_or_reconstruct_noexcept() { | |
using _VInput = ::std::remove_reference_t<_Input>; | |
using _UInput = __remove_cvref_t<_Input>; | |
if constexpr ( | |
::std::is_array_v< | |
_UInput> && ::std::is_const_v<::std::remove_extent_t<_VInput>> && ::std::is_lvalue_reference_v<_Input>) { | |
return true; | |
} | |
else { | |
return noexcept(__reconstruct(::std::in_place_type<_UInput>, ::std::declval<_Input>())); | |
} | |
} | |
template <typename _Input> | |
constexpr auto __span_or_reconstruct(_Input&& __input) noexcept(__span_or_reconstruct_noexcept<_Input>()) { | |
using _VInput = ::std::remove_reference_t<_Input>; | |
using _UInput = __remove_cvref_t<_Input>; | |
if constexpr ( | |
__is_iterator_contiguous_iterator_v<__range_iterator_t< | |
_Input>> && !__is_specialization_of_v<_UInput, ::std::basic_string_view> && !__is_std_span_v<_UInput>) { | |
using _Ty = ::std::remove_extent_t<_VInput>; | |
return __reconstruct(::std::in_place_type<::ztd::text::span<_Ty>>, __adl::__adl_begin(__input), | |
__adl::__adl_end(__input)); | |
} | |
else { | |
return __reconstruct(::std::in_place_type<_UInput>, ::std::forward<_Input>(__input)); | |
} | |
} | |
template <typename _Input> | |
constexpr auto __string_view_or_span_or_reconstruct(_Input&& __input) noexcept( | |
__string_view_or_span_or_reconstruct_noexcept<_Input>()) { | |
using _VInput = ::std::remove_reference_t<_Input>; | |
using _UInput = __remove_cvref_t<_Input>; | |
if constexpr ( | |
::std::is_array_v< | |
_UInput> && ::std::is_const_v<::std::remove_extent_t<_VInput>> && ::std::is_lvalue_reference_v<_Input>) { | |
using _CharTy = ::std::remove_extent_t<_UInput>; | |
if constexpr (__is_char_traitable_v<_CharTy>) { | |
return ::std::basic_string_view<_CharTy>(::std::forward<_Input>(__input)); | |
} | |
else { | |
using _Ty = ::std::remove_extent_t<_VInput>; | |
return __reconstruct(::std::in_place_type<::ztd::text::span<_Ty>>, __adl::__adl_begin(__input), | |
__adl::__adl_end(__input)); | |
} | |
} | |
else { | |
if constexpr ( | |
__is_iterator_contiguous_iterator_v<__range_iterator_t< | |
_Input>> && !__is_specialization_of_v<_UInput, ::std::basic_string_view> && !__is_std_span_v<_UInput>) { | |
using _CharTy = __range_value_type_t<_Input>; | |
if constexpr (__is_char_traitable_v<_CharTy>) { | |
return __reconstruct(::std::in_place_type<::std::basic_string_view<_CharTy>>, | |
__adl::__adl_begin(__input), __adl::__adl_end(__input)); | |
} | |
else { | |
using _Ty = ::std::remove_extent_t<_VInput>; | |
return __reconstruct(::std::in_place_type<::ztd::text::span<_Ty>>, | |
__adl::__adl_begin(__input), __adl::__adl_end(__input)); | |
} | |
} | |
else { | |
return __reconstruct(::std::in_place_type<_UInput>, ::std::forward<_Input>(__input)); | |
} | |
} | |
} | |
template <typename _Input> | |
using __span_or_reconstruct_t = decltype(__span_or_reconstruct(::std::declval<_Input>())); | |
template <typename _Input> | |
using __string_view_or_span_or_reconstruct_t | |
= decltype(__string_view_or_span_or_reconstruct(::std::declval<_Input>())); | |
} // namespace __txt_detail | |
inline namespace __cpo { | |
////// | |
/// @brief The reconstruct object is a Customization Point Object (CPO) as defined by the Standard Library in | |
/// [customization.point.object] (http://eel.is/c++draft/customization.point.object). It is the route for | |
/// being able to put a range back from various bits and pieces of itself. For more in-depth information, see | |
/// P1664 (https://thephd.dev/_vendor/future_cxx/papers/d1664.html). | |
////// | |
inline constexpr auto& reconstruct = __txt_detail::__reconstruct; | |
} // namespace __cpo | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/reconstruct.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/encoding_range.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/state.hpp | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _Type, typename = void> | |
struct __decode_state { | |
using type = typename _Type::state; | |
}; | |
template <typename _Type> | |
struct __decode_state<_Type, ::std::void_t<typename _Type::decode_state>> { | |
using type = typename _Type::decode_state; | |
}; | |
template <typename _Type, typename = void> | |
struct __encode_state { | |
using type = typename _Type::state; | |
}; | |
template <typename _Type> | |
struct __encode_state<_Type, ::std::void_t<typename _Type::encode_state>> { | |
using type = typename _Type::encode_state; | |
}; | |
} // namespace __txt_detail | |
////// | |
/// @addtogroup ztd_text_state Encoding State Management | |
/// | |
/// @brief These allow a person to inspect the state of an encoding type, and create them when necessary. It is | |
/// important to use these properties and functions in generic code, lest you make assumptions that will break down | |
/// in the future or in the face of more advanced encoding objects. | |
/// | |
/// @{ | |
///// | |
////// | |
/// @brief Retrieves the @c decode_state of the encoding type if it has one, or the @c state type of the | |
/// encoding. | |
////// | |
template <typename _Type> | |
class decode_state { | |
public: | |
////// | |
/// @brief The @c decode_state type or @c state type on a given encoding type. | |
/// | |
////// | |
using type = typename __txt_detail::__decode_state<__txt_detail::__remove_cvref_t<_Type>>::type; | |
}; | |
////// | |
/// @brief Typename alias for ztd::text::decode_state. | |
/// | |
////// | |
template <typename _Type> | |
using decode_state_t = typename decode_state<_Type>::type; | |
////// | |
/// @brief Retrieves the @c encode_state of the encoding type if it has one, or the @c state type of the | |
/// encoding. | |
////// | |
template <typename _Type> | |
class encode_state { | |
public: | |
////// | |
/// @brief The @c encode_state type or @c state type on a given encoding type. | |
/// | |
////// | |
using type = typename __txt_detail::__encode_state<__txt_detail::__remove_cvref_t<_Type>>::type; | |
}; | |
////// | |
/// @brief Typename alias for ztd::text::encode_state. | |
/// | |
////// | |
template <typename _Type> | |
using encode_state_t = typename encode_state<_Type>::type; | |
////// | |
/// @brief Whether or not the given type can be constructed without information from the encoding | |
/// itself. | |
/// | |
/// @tparam _Encoding The encoding that may contain necessary information. | |
/// @tparam _Type The state type that may need information from the encoding to be successfully constructed. | |
/// | |
/// @remarks This value tells users at compile time whether or not they need to be careful with the state. Rather | |
/// than let users have to work this independently, two functions — ztd::text::make_encode_state(_Encoding) and | |
/// ztd::text::make_encode_state(_Encoding) — handle the details here. | |
////// | |
template <typename _Encoding, typename _Type> | |
inline constexpr bool is_state_independent_v | |
= !::std::is_constructible_v<_Type, _Encoding> && ::std::is_default_constructible_v<_Type>; | |
////// | |
/// @brief Whether or not the encoding's @c decode_state can be constructed without information from the | |
/// encoding itself. | |
////// | |
template <typename _Encoding> | |
inline constexpr bool is_decode_state_independent_v = is_state_independent_v<_Encoding, decode_state_t<_Encoding>>; | |
////// | |
/// @brief Whether or not the encoding's @c decode_state can be constructed without information from the | |
/// encoding itself. | |
////// | |
template <typename _Encoding> | |
inline constexpr bool is_encode_state_independent_v = is_state_independent_v<_Encoding, encode_state_t<_Encoding>>; | |
////// | |
/// @brief Constructs the @c decode_state of the given encoding, based on whether or not the encoding and state | |
/// meet the criteria of ztd::text::is_decode_state_independent_v. | |
/// | |
/// @param[in] __encoding The encoding object to use, if applicable, for the construction of the state. | |
////// | |
template <typename _Encoding> | |
constexpr decode_state_t<__txt_detail::__remove_cvref_t<_Encoding>> make_decode_state( | |
_Encoding& __encoding) noexcept { | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
using _DecodeState = decode_state_t<_UEncoding>; | |
if constexpr (is_encode_state_independent_v<_UEncoding>) { | |
(void)__encoding; | |
return _DecodeState(); | |
} | |
else { | |
return _DecodeState(__encoding); | |
} | |
} | |
////// | |
/// @brief Constructs the @c encode_state of the given encoding, based on whether or not the encoding and state | |
/// meet the criteria of ztd::text::is_encode_state_independent_v. | |
/// | |
/// @param[in] __encoding The encoding object to use, if applicable, for the construction of the state. | |
////// | |
template <typename _Encoding> | |
constexpr encode_state_t<__txt_detail::__remove_cvref_t<_Encoding>> make_encode_state( | |
_Encoding& __encoding) noexcept { | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
using _EncodeState = encode_state_t<_UEncoding>; | |
if constexpr (is_encode_state_independent_v<_UEncoding>) { | |
(void)__encoding; | |
return _EncodeState(); | |
} | |
else { | |
return _EncodeState(__encoding); | |
} | |
} | |
////// | |
/// @brief Constructs the @c decode_state of the given encoding, based on whether or not the encoding and state | |
/// meet the criteria of ztd::text::is_decode_state_independent_v or whether it can be created by copy construction | |
/// from the given @p __encode_state. | |
/// | |
/// @param[in] __encoding The encoding object to use, if applicable, for the construction of the state. | |
/// @param[in] __encode_state A preexisting state from the decoder. | |
////// | |
template <typename _Encoding> | |
constexpr decode_state_t<__txt_detail::__remove_cvref_t<_Encoding>> make_decode_state_with(_Encoding& __encoding, | |
const encode_state_t<__txt_detail::__remove_cvref_t<_Encoding>>& __encode_state) noexcept { | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
using _DecodeState = decode_state_t<_UEncoding>; | |
using _EncodeState = encode_state_t<_UEncoding>; | |
if constexpr (is_decode_state_independent_v<_UEncoding>) { | |
if constexpr (::std::is_constructible_v<_EncodeState, const _DecodeState&>) { | |
(void)__encoding; | |
return _DecodeState(__encode_state); | |
} | |
else { | |
(void)__encoding; | |
(void)__encode_state; | |
return _DecodeState(); | |
} | |
} | |
else { | |
if constexpr (::std::is_constructible_v<_EncodeState, const _UEncoding&, const _DecodeState&>) { | |
return _DecodeState(__encoding, __encode_state); | |
} | |
else { | |
(void)__encode_state; | |
return _DecodeState(__encoding); | |
} | |
} | |
} | |
////// | |
/// @brief Constructs the @c encode_state of the given encoding, based on whether or not the encoding and state | |
/// meet the criteria of ztd::text::is_encode_state_independent_v or whether it can be created by copy construction | |
/// from the given @p __decode_state. | |
/// | |
/// @param[in] __encoding The encoding object to use, if applicable, for the construction of the state. | |
/// @param[in] __decode_state A preexisting state from the decoder. | |
////// | |
template <typename _Encoding> | |
constexpr encode_state_t<__txt_detail::__remove_cvref_t<_Encoding>> make_encode_state_with(_Encoding& __encoding, | |
const decode_state_t<__txt_detail::__remove_cvref_t<_Encoding>>& __decode_state) noexcept { | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
using _DecodeState = decode_state_t<_UEncoding>; | |
using _EncodeState = encode_state_t<_UEncoding>; | |
if constexpr (is_encode_state_independent_v<_UEncoding>) { | |
if constexpr (::std::is_constructible_v<_EncodeState, const _DecodeState&>) { | |
(void)__encoding; | |
return _EncodeState(__decode_state); | |
} | |
else { | |
(void)__encoding; | |
(void)__decode_state; | |
return _EncodeState(); | |
} | |
} | |
else { | |
if constexpr (::std::is_constructible_v<_EncodeState, const _UEncoding&, const _DecodeState&>) { | |
return _EncodeState(__encoding, __decode_state); | |
} | |
else { | |
(void)__decode_state; | |
return _EncodeState(__encoding); | |
} | |
} | |
} | |
////// | |
/// @} | |
///// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/state.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/code_point.hpp | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_properties Property and Trait Helpers | |
/// @{ | |
///// | |
////// | |
/// @brief Retrieves the code point type for the given type. | |
/// | |
////// | |
template <typename _Type> | |
class code_point { | |
public: | |
////// | |
/// @brief The code point type for the given encoding type. If it does not exist, @c | |
/// ztd::text::unicode_code_point is assumed. | |
/// | |
////// | |
using type = typename __txt_detail::__remove_cvref_t<_Type>::code_point; | |
}; | |
////// | |
/// @brief A typename alias for ztd::text::code_point. | |
/// | |
////// | |
template <typename _Type> | |
using code_point_t = typename code_point<_Type>::type; | |
////// | |
/// @brief Gets the maximum number of code points that can be produced by an encoding during a decode operation, | |
/// suitable for initializing a automatic storage duration ("stack-allocated") buffer. | |
////// | |
template <typename _Type> | |
inline static constexpr ::std::size_t max_code_points_v = _Type::max_code_points; | |
////// | |
/// @} | |
///// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/code_point.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/code_unit.hpp | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_properties Property and Trait Helpers | |
/// | |
/// @brief Type-trait like properties and helpers, with @c _t ( @c \::type ) and @c _v ( @c \::value ). | |
/// | |
/// @remarks These should be the go-to way to reference necessary type and constant static data out of encoding | |
/// objects when not interfacing with the well-defined, guaranteed members. For example, directly accessing the @c | |
/// obj::code_unit type is not viable for many encoding types and it is best to go through here. | |
/// @{ | |
///// | |
////// | |
/// @brief Retrieves the code unit type for the given type. | |
/// | |
////// | |
template <typename _Type> | |
class code_unit { | |
public: | |
////// | |
/// @brief The code unit type for the encoding type. | |
/// | |
////// | |
using type = typename __txt_detail::__remove_cvref_t<_Type>::code_unit; | |
}; | |
////// | |
/// @brief A typename alias for ztd::text::code_unit. | |
/// | |
////// | |
template <typename _Type> | |
using code_unit_t = typename code_unit<_Type>::type; | |
////// | |
/// @brief Gets the maximum number of code units that can be produced by an encoding during an encode operation, | |
/// suitable for initializing a automatic storage duration ("stack-allocated") buffer. | |
////// | |
template <typename _Type> | |
inline static constexpr ::std::size_t max_code_units_v = _Type::max_code_units; | |
////// | |
/// @} | |
///// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/code_unit.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/tag.hpp | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @brief A tag type, useful in helping to constrain extension points and more. | |
/// | |
/// @tparam _Args The types to be used as part of the tagging mechanism. As this is variadic, allows no classes to | |
/// be passed. | |
/// | |
/// @remarks The tag type will always be used | |
////// | |
template <typename... _Args> | |
class tag { }; | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/tag.hpp | |
#include <utility> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
// validation: decode | |
template <typename _Input, typename _Encoding, typename _State, typename... _AdditionalStates> | |
using __detect_adl_internal_text_validate_decodable_as | |
= decltype(__text_validate_decodable_as(tag<__remove_cvref_t<_Encoding>> {}, ::std::declval<_Input>(), | |
::std::declval<_Encoding>(), ::std::declval<_State&>(), ::std::declval<_AdditionalStates&>()...)); | |
template <typename _Input, typename _Encoding, typename _State, typename... _AdditionalStates> | |
using __detect_adl_text_validate_decodable_as | |
= decltype(text_validate_decodable_as(tag<__remove_cvref_t<_Encoding>> {}, ::std::declval<_Input>(), | |
::std::declval<_Encoding>(), ::std::declval<_State&>(), ::std::declval<_AdditionalStates&>()...)); | |
template <typename _Input, typename _Encoding, typename _State, typename... _AdditionalStates> | |
using __detect_adl_text_validate_decodable_as_one | |
= decltype(text_validate_decodable_as_one(tag<__remove_cvref_t<_Encoding>> {}, ::std::declval<_Input>(), | |
::std::declval<_Encoding>(), ::std::declval<_State&>(), ::std::declval<_AdditionalStates&>()...)); | |
template <typename _Input, typename _Encoding, typename _State, typename... _AdditionalStates> | |
using __detect_adl_internal_text_validate_decodable_as_one = decltype(__text_validate_decodable_as_one( | |
tag<__remove_cvref_t<_Encoding>> {}, ::std::declval<_Input>(), ::std::declval<_Encoding>(), | |
::std::declval<_State&>(), ::std::declval<_AdditionalStates&>()...)); | |
// validation: encode | |
template <typename _Input, typename _Encoding, typename _State, typename... _AdditionalStates> | |
using __detect_adl_internal_text_validate_encodable_as | |
= decltype(__text_validate_encodable_as(tag<__remove_cvref_t<_Encoding>> {}, ::std::declval<_Input>(), | |
::std::declval<_Encoding>(), ::std::declval<_State&>(), ::std::declval<_AdditionalStates&>()...)); | |
template <typename _Input, typename _Encoding, typename _State, typename... _AdditionalStates> | |
using __detect_adl_text_validate_encodable_as | |
= decltype(text_validate_encodable_as(tag<__remove_cvref_t<_Encoding>> {}, ::std::declval<_Input>(), | |
::std::declval<_Encoding>(), ::std::declval<_State&>(), ::std::declval<_AdditionalStates&>()...)); | |
template <typename _Input, typename _Encoding, typename _State, typename... _AdditionalStates> | |
using __detect_adl_internal_text_validate_encodable_as_one = decltype(__text_validate_encodable_as_one( | |
tag<__remove_cvref_t<_Encoding>> {}, ::std::declval<_Input>(), ::std::declval<_Encoding>(), | |
::std::declval<_State&>(), ::std::declval<_AdditionalStates&>()...)); | |
template <typename _Input, typename _Encoding, typename _State, typename... _AdditionalStates> | |
using __detect_adl_text_validate_encodable_as_one | |
= decltype(text_validate_encodable_as_one(tag<__remove_cvref_t<_Encoding>> {}, ::std::declval<_Input>(), | |
::std::declval<_Encoding>(), ::std::declval<_State&>(), ::std::declval<_AdditionalStates&>()...)); | |
// validation: transcode | |
template <typename _Input, typename _FromEncoding, typename _ToEncoding, typename _FromState, | |
typename _ToState> | |
using __detect_adl_internal_text_validate_transcodable_as = decltype(__text_validate_encodable_as( | |
tag<__remove_cvref_t<_FromEncoding>, __remove_cvref_t<_ToEncoding>> {}, ::std::declval<_Input>(), | |
::std::declval<_FromEncoding>(), ::std::declval<_ToEncoding>(), ::std::declval<_FromState&>(), | |
::std::declval<_ToState&>())); | |
template <typename _Input, typename _FromEncoding, typename _ToEncoding, typename _FromState, | |
typename _ToState> | |
using __detect_adl_text_validate_transcodable_as = decltype(text_validate_transcodable_as( | |
tag<__remove_cvref_t<_FromEncoding>, __remove_cvref_t<_ToEncoding>> {}, ::std::declval<_Input>(), | |
::std::declval<_FromEncoding>(), ::std::declval<_ToEncoding>(), ::std::declval<_FromState&>(), | |
::std::declval<_ToState&>())); | |
template <typename _Input, typename _FromEncoding, typename _ToEncoding, typename _FromState, | |
typename _ToState> | |
using __detect_adl_internal_text_validate_transcodable_as_one = decltype(__text_validate_transcodable_as_one( | |
tag<__remove_cvref_t<_FromEncoding>, __remove_cvref_t<_ToEncoding>> {}, ::std::declval<_Input>(), | |
::std::declval<_FromEncoding>(), ::std::declval<_ToEncoding>(), ::std::declval<_FromState&>(), | |
::std::declval<_ToState&>())); | |
template <typename _Input, typename _FromEncoding, typename _ToEncoding, typename _FromState, | |
typename _ToState> | |
using __detect_adl_text_validate_transcodable_as_one = decltype(text_validate_transcodable_as_one( | |
tag<__remove_cvref_t<_FromEncoding>, __remove_cvref_t<_ToEncoding>> {}, ::std::declval<_Input>(), | |
::std::declval<_FromEncoding>(), ::std::declval<_ToEncoding>(), ::std::declval<_FromState&>(), | |
::std::declval<_ToState&>())); | |
// counting: code units | |
template <typename _Input, typename _Encoding, typename _Handler, typename _State> | |
using __detect_adl_internal_text_count_decodable_one | |
= decltype(__text_count_decodable_one(tag<__remove_cvref_t<_Encoding>> {}, ::std::declval<_Input>(), | |
::std::declval<_Encoding>(), ::std::declval<_Handler>(), ::std::declval<_State&>())); | |
template <typename _Input, typename _Encoding, typename _Handler, typename _State> | |
using __detect_adl_text_count_decodable_one | |
= decltype(text_count_decodable_one(tag<__remove_cvref_t<_Encoding>> {}, ::std::declval<_Input>(), | |
::std::declval<_Encoding>(), ::std::declval<_Handler>(), ::std::declval<_State&>())); | |
template <typename _Input, typename _Encoding, typename _Handler, typename _State> | |
using __detect_adl_text_count_decodable | |
= decltype(text_count_decodable(tag<__remove_cvref_t<_Encoding>> {}, ::std::declval<_Input>(), | |
::std::declval<_Encoding>(), ::std::declval<_Handler>(), ::std::declval<_State&>())); | |
template <typename _Input, typename _Encoding, typename _Handler, typename _State> | |
using __detect_adl_internal_text_count_decodable | |
= decltype(__text_count_decodable(tag<__remove_cvref_t<_Encoding>> {}, ::std::declval<_Input>(), | |
::std::declval<_Encoding>(), ::std::declval<_Handler>(), ::std::declval<_State&>())); | |
// counting: code points | |
template <typename _Input, typename _Encoding, typename _Handler, typename _State> | |
using __detect_adl_internal_text_count_encodable_one | |
= decltype(__text_count_encodable_one(tag<__remove_cvref_t<_Encoding>> {}, ::std::declval<_Encoding>(), | |
::std::declval<_Input>(), ::std::declval<_Handler>(), ::std::declval<_State&>())); | |
template <typename _Input, typename _Encoding, typename _Handler, typename _State> | |
using __detect_adl_text_count_encodable_one | |
= decltype(text_count_encodable_one(tag<__remove_cvref_t<_Encoding>> {}, ::std::declval<_Encoding>(), | |
::std::declval<_Input>(), ::std::declval<_Handler>(), ::std::declval<_State&>())); | |
template <typename _Input, typename _Encoding, typename _Handler, typename _State> | |
using __detect_adl_text_count_encodable | |
= decltype(text_count_encodable(tag<__remove_cvref_t<_Encoding>> {}, ::std::declval<_Input>(), | |
::std::declval<_Encoding>(), ::std::declval<_Handler>(), ::std::declval<_State&>())); | |
template <typename _Input, typename _Encoding, typename _Handler, typename _State> | |
using __detect_adl_internal_text_count_encodable = decltype(__text_count_encodable(::std::declval<_Input>(), | |
::std::declval<_Encoding>(), ::std::declval<_Handler>(), ::std::declval<_State&>())); | |
// counting: transcode code units | |
template <typename _Input, typename _FromEncoding, typename _ToEncoding, typename _FromHandler, | |
typename _ToHandler, typename _FromState, typename _ToState> | |
using __detect_adl_internal_text_count_transcodable_one = decltype(__text_count_encodable_one( | |
tag<__remove_cvref_t<_FromEncoding>, __remove_cvref_t<_ToEncoding>> {}, ::std::declval<_FromEncoding>(), | |
::std::declval<_ToEncoding>(), ::std::declval<_Input>(), ::std::declval<_FromHandler>(), | |
::std::declval<_ToHandler>(), ::std::declval<_FromState&>(), ::std::declval<_ToState&>())); | |
template <typename _Input, typename _FromEncoding, typename _ToEncoding, typename _FromHandler, | |
typename _ToHandler, typename _FromState, typename _ToState> | |
using __detect_adl_text_count_transcodable_one = decltype(text_count_encodable_one( | |
tag<__remove_cvref_t<_FromEncoding>, __remove_cvref_t<_ToEncoding>> {}, ::std::declval<_Input>(), | |
::std::declval<_FromEncoding>(), ::std::declval<_ToEncoding>(), ::std::declval<_FromHandler>(), | |
::std::declval<_ToHandler>(), ::std::declval<_FromState&>(), ::std::declval<_ToState&>())); | |
template <typename _Input, typename _FromEncoding, typename _ToEncoding, typename _FromHandler, | |
typename _ToHandler, typename _FromState, typename _ToState> | |
using __detect_adl_text_count_transcodable = decltype(text_count_encodable( | |
tag<__remove_cvref_t<_FromEncoding>, __remove_cvref_t<_ToEncoding>> {}, ::std::declval<_Input>(), | |
::std::declval<_FromEncoding>(), ::std::declval<_ToEncoding>(), ::std::declval<_FromHandler>(), | |
::std::declval<_ToHandler>(), ::std::declval<_FromState&>(), ::std::declval<_ToState&>())); | |
template <typename _Input, typename _FromEncoding, typename _ToEncoding, typename _FromHandler, | |
typename _ToHandler, typename _FromState, typename _ToState> | |
using __detect_adl_internal_text_count_transcodable = decltype(__text_count_encodable( | |
tag<__remove_cvref_t<_FromEncoding>, __remove_cvref_t<_ToEncoding>> {}, ::std::declval<_Input>(), | |
::std::declval<_FromEncoding>(), ::std::declval<_ToEncoding>(), ::std::declval<_FromHandler>(), | |
::std::declval<_ToHandler>(), ::std::declval<_FromState&>(), ::std::declval<_ToState&>())); | |
// decode | |
template <typename _Encoding, typename _Input, typename _Output, typename _Handler, typename _State> | |
using __detect_object_decode_one = decltype(::std::declval<_Encoding>().decode_one(::std::declval<_Input>(), | |
::std::declval<_Output>(), ::std::declval<_Handler>(), ::std::declval<_State&>())); | |
template <typename _Encoding, typename _Input, typename _Output, typename _Handler, typename _State> | |
using __detect_object_decode_one_backwards | |
= decltype(::std::declval<_Encoding>().decode_one_backwards(::std::declval<_Input>(), | |
::std::declval<_Output>(), ::std::declval<_Handler>(), ::std::declval<_State&>())); | |
template <typename _Input, typename _Encoding, typename _Output, typename _Handler, typename _State> | |
using __detect_adl_text_decode = decltype(text_decode(tag<__remove_cvref_t<_Encoding>> {}, | |
::std::declval<_Input>(), ::std::declval<_Encoding>(), ::std::declval<_Output>(), | |
::std::declval<_Handler>(), ::std::declval<_State&>())); | |
template <typename _Input, typename _Encoding, typename _Output, typename _Handler, typename _State> | |
using __detect_adl_internal_text_decode = decltype(__text_decode(tag<__remove_cvref_t<_Encoding>> {}, | |
::std::declval<_Input>(), ::std::declval<_Encoding>(), ::std::declval<_Output>(), | |
::std::declval<_Handler>(), ::std::declval<_State&>())); | |
// encode | |
template <typename _Encoding, typename _Input, typename _Output, typename _Handler, typename _State> | |
using __detect_object_encode_one = decltype(::std::declval<_Encoding>().encode_one(::std::declval<_Input>(), | |
::std::declval<_Output>(), ::std::declval<_Handler>(), ::std::declval<_State&>())); | |
template <typename _Encoding, typename _Input, typename _Output, typename _Handler, typename _State> | |
using __detect_object_encode_one_backwards | |
= decltype(::std::declval<_Encoding>().encode_one_backwards(::std::declval<_Input>(), | |
::std::declval<_Output>(), ::std::declval<_Handler>(), ::std::declval<_State&>())); | |
template <typename _Input, typename _Encoding, typename _Output, typename _Handler, typename _State> | |
using __detect_adl_text_encode = decltype(text_encode(tag<__remove_cvref_t<_Encoding>> {}, | |
::std::declval<_Input>(), ::std::declval<_Encoding>(), ::std::declval<_Output>(), | |
::std::declval<_Handler>(), ::std::declval<_State&>())); | |
template <typename _Input, typename _Encoding, typename _Output, typename _Handler, typename _State> | |
using __detect_adl_internal_text_encode = decltype(__text_encode(tag<__remove_cvref_t<_Encoding>> {}, | |
::std::declval<_Input>(), ::std::declval<_Encoding>(), ::std::declval<_Output>(), | |
::std::declval<_Handler>(), ::std::declval<_State&>())); | |
// transcode | |
template <typename _Input, typename _FromEncoding, typename _Output, typename _ToEncoding, | |
typename _FromHandler, typename _ToHandler, typename _FromState, typename _ToState> | |
using __detect_adl_text_transcode | |
= decltype(text_transcode(tag<__remove_cvref_t<_FromEncoding>, __remove_cvref_t<_ToEncoding>> {}, | |
::std::declval<_Input>(), ::std::declval<_FromEncoding>(), ::std::declval<_Output>(), | |
::std::declval<_ToEncoding>(), ::std::declval<_FromHandler>(), ::std::declval<_ToHandler>(), | |
::std::declval<_FromState&>(), ::std::declval<_ToState&>())); | |
template <typename _Input, typename _FromEncoding, typename _Output, typename _ToEncoding, | |
typename _FromHandler, typename _ToHandler, typename _FromState, typename _ToState> | |
using __detect_adl_internal_text_transcode | |
= decltype(__text_transcode(tag<__remove_cvref_t<_FromEncoding>, __remove_cvref_t<_ToEncoding>> {}, | |
::std::declval<_Input>(), ::std::declval<_FromEncoding>(), ::std::declval<_Output>(), | |
::std::declval<_ToEncoding>(), ::std::declval<_FromHandler>(), ::std::declval<_ToHandler>(), | |
::std::declval<_FromState&>(), ::std::declval<_ToState&>())); | |
template <typename _Input, typename _FromEncoding, typename _Output, typename _ToEncoding, | |
typename _FromHandler, typename _ToHandler, typename _FromState, typename _ToState> | |
using __detect_adl_internal_text_transcode_one | |
= decltype(__text_transcode_one(tag<__remove_cvref_t<_FromEncoding>, __remove_cvref_t<_ToEncoding>> {}, | |
::std::declval<_Input>(), ::std::declval<_FromEncoding>(), ::std::declval<_Output>(), | |
::std::declval<_ToEncoding>(), ::std::declval<_FromHandler>(), ::std::declval<_ToHandler>(), | |
::std::declval<_FromState&>(), ::std::declval<_ToState&>())); | |
template <typename _Input, typename _FromEncoding, typename _Output, typename _ToEncoding, | |
typename _FromHandler, typename _ToHandler, typename _FromState, typename _ToState> | |
using __detect_adl_text_transcode_one | |
= decltype(text_transcode_one(tag<__remove_cvref_t<_FromEncoding>, __remove_cvref_t<_ToEncoding>> {}, | |
::std::declval<_Input>(), ::std::declval<_FromEncoding>(), ::std::declval<_Output>(), | |
::std::declval<_ToEncoding>(), ::std::declval<_FromHandler>(), ::std::declval<_ToHandler>(), | |
::std::declval<_FromState&>(), ::std::declval<_ToState&>())); | |
template <typename _Handler, typename _Encoding, typename _Result, typename _Progress> | |
using __detect_callable_handler = decltype(::std::declval<_Handler>()( | |
::std::declval<const _Encoding&>(), ::std::declval<_Result>(), ::std::declval<_Progress>())); | |
template <typename _Encoding, typename = void> | |
struct __range_category { | |
using type = void; | |
}; | |
template <typename _Encoding> | |
struct __range_category<_Encoding, ::std::void_t<typename __remove_cvref_t<_Encoding>::range_category>> { | |
using type = typename __remove_cvref_t<_Encoding>::range_category; | |
}; | |
template <typename _Encoding, typename = void> | |
struct __decode_range_category : public __range_category<_Encoding> { }; | |
template <typename _Encoding> | |
struct __decode_range_category<_Encoding, | |
::std::void_t<typename __remove_cvref_t<_Encoding>::decode_range_category>> { | |
using type = typename __remove_cvref_t<_Encoding>::decode_range_category; | |
}; | |
template <typename _Encoding, typename = void> | |
struct __encode_range_category : public __range_category<_Encoding> { }; | |
template <typename _Encoding> | |
struct __encode_range_category<_Encoding, | |
::std::void_t<typename __remove_cvref_t<_Encoding>::encode_range_category>> { | |
using type = typename __remove_cvref_t<_Encoding>::encode_range_category; | |
}; | |
template <typename _Encoding> | |
using __decode_range_category_t = typename __decode_range_category<_Encoding>::type; | |
template <typename _Encoding> | |
using __encode_range_category_t = typename __encode_range_category<_Encoding>::type; | |
template <typename _Encoding> | |
inline constexpr bool __is_decode_range_category_output_v | |
= ::std::is_base_of_v<__decode_range_category_t<_Encoding>, ::std::output_iterator_tag>; | |
template <typename _Encoding> | |
inline constexpr bool __is_encode_range_category_output_v | |
= ::std::is_base_of_v<__encode_range_category_t<_Encoding>, ::std::output_iterator_tag>; | |
template <typename _Encoding> | |
inline constexpr bool __is_encode_range_category_contiguous_v | |
= ::std::is_base_of_v<__encode_range_category_t<_Encoding>, ::ztd::text::contiguous_iterator_tag>; | |
template <typename _Encoding> | |
inline constexpr bool __is_decode_range_category_contiguous_v | |
= ::std::is_base_of_v<__decode_range_category_t<_Encoding>, ::ztd::text::contiguous_iterator_tag>; | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/encoding_range.hpp | |
#include <cstddef> | |
#include <array> | |
#include <utility> | |
#include <functional> | |
#include <system_error> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_result Result Types | |
/// @{ | |
////// | |
////// | |
/// @brief The result of all encode operations from encoding objects and higher-level calls (such as | |
/// ztd_text_encode). | |
////// | |
template <typename _Input, typename _Output> | |
class stateless_encode_result { | |
public: | |
////// | |
/// @brief The reconstructed input_view object, with its .begin() incremented by the number of code units | |
/// successfully read (can be identical to .begin() on original range on failure). | |
////// | |
_Input input; | |
////// | |
/// @brief The reconstructed output_view object, with its .begin() incremented by the number of code units | |
/// successfully written (can be identical to .begin() on original range on failure). | |
////// | |
_Output output; | |
////// | |
/// @brief The kind of error that occured, if any. | |
////// | |
encoding_error error_code; | |
////// | |
/// @brief Whether or not the error handler was invoked, regardless of if the error_code is set or not set to | |
/// ztd::text::encoding_error::ok. | |
////// | |
::std::size_t handled_errors; | |
////// | |
/// @brief Constructs a ztd::text::encode_result, defaulting the error code to | |
/// ztd::text::encoding_error::ok if not provided. | |
/// | |
/// @param[in] __input The input range to store. | |
/// @param[in] __output The output range to store. | |
/// @param[in] __error_code The error code for the decoding opertion, if any. | |
////// | |
template <typename _ArgInput, typename _ArgOutput> | |
constexpr stateless_encode_result(_ArgInput&& __input, _ArgOutput&& __output, | |
encoding_error __error_code | |
= encoding_error::ok) noexcept(noexcept(stateless_encode_result(::std::forward<_ArgInput>(__input), | |
::std::forward<_ArgOutput>(__output), __error_code, __error_code != encoding_error::ok))) | |
: stateless_encode_result(::std::forward<_ArgInput>(__input), ::std::forward<_ArgOutput>(__output), | |
__error_code, | |
__error_code != encoding_error::ok ? static_cast<::std::size_t>(1) : static_cast<::std::size_t>(0)) { | |
} | |
////// | |
/// @brief Constructs a ztd::text::encode_result with the provided parameters and information, | |
/// including whether or not an error was handled. | |
/// | |
/// @param[in] __input The input range to store. | |
/// @param[in] __output The output range to store. | |
/// @param[in] __error_code The error code for the encode operation, if any. | |
/// @param[in] __handled_errors Whether or not an error was handled. Some error handlers are corrective (see | |
/// ztd::text::replacement_handler), and so the error code is not enough to determine if the handler was | |
/// invoked. This allows the value to be provided directly when constructing this result type. | |
////// | |
template <typename _ArgInput, typename _ArgOutput> | |
constexpr stateless_encode_result(_ArgInput&& __input, _ArgOutput&& __output, encoding_error __error_code, | |
::std::size_t __handled_errors) noexcept(::std::is_nothrow_constructible_v<_Input, | |
_ArgInput>&& ::std::is_nothrow_constructible_v<_Output, _ArgOutput>) | |
: input(::std::forward<_ArgInput>(__input)) | |
, output(::std::forward<_ArgOutput>(__output)) | |
, error_code(__error_code) | |
, handled_errors(__handled_errors) { | |
} | |
////// | |
/// @brief Whether or not any errors were handled. | |
/// | |
/// @returns Simply checks whether @c handled_errors is greater than 0. | |
////// | |
constexpr bool errors_were_handled() const noexcept { | |
return this->handled_errors > 0; | |
} | |
}; | |
////// | |
/// @brief The result of all encode operations from encoding objects and higher-level calls (such as | |
/// ztd_text_encode). | |
////// | |
template <typename _Input, typename _Output, typename _State> | |
class encode_result : public stateless_encode_result<_Input, _Output> { | |
private: | |
using __base_t = stateless_encode_result<_Input, _Output>; | |
public: | |
////// | |
/// @brief The state of the associated Encoding used for decoding input code points to code units. | |
////// | |
_State& state; | |
////// | |
/// @brief Constructs a ztd::text::encode_result, defaulting the error code to | |
/// ztd::text::encoding_error::ok if not provided. | |
/// | |
/// @param[in] __input The input range to store. | |
/// @param[in] __output The output range to store. | |
/// @param[in] __state The state related to the Encoding that performed the encode operation. | |
/// @param[in] __error_code The error code for the decoding opertion, if any. | |
////// | |
template <typename _ArgInput, typename _ArgOutput, typename _ArgState> | |
constexpr encode_result(_ArgInput&& __input, _ArgOutput&& __output, _ArgState&& __state, | |
encoding_error __error_code = encoding_error::ok) | |
: encode_result(::std::forward<_ArgInput>(__input), ::std::forward<_ArgOutput>(__output), | |
::std::forward<_ArgState>(__state), __error_code, | |
__error_code != encoding_error::ok ? static_cast<::std::size_t>(1) : static_cast<::std::size_t>(0)) { | |
} | |
////// | |
/// @brief Constructs a ztd::text::encode_result with the provided parameters and information, | |
/// including whether or not an error was handled. | |
/// | |
/// @param[in] __input The input range to store. | |
/// @param[in] __output The output range to store. | |
/// @param[in] __state The state related to the Encoding that performed the encode operation. | |
/// @param[in] __error_code The error code for the encode operation, if any. | |
/// @param[in] __handled_errors Whether or not an error was handled. Some error handlers are corrective (see | |
/// ztd::text::replacement_handler), and so the error code is not enough to determine if the handler was | |
/// invoked. This allows the value to be provided directly when constructing this result type. | |
////// | |
template <typename _ArgInput, typename _ArgOutput, typename _ArgState> | |
constexpr encode_result(_ArgInput&& __input, _ArgOutput&& __output, _ArgState&& __state, | |
encoding_error __error_code, ::std::size_t __handled_errors) | |
: __base_t( | |
::std::forward<_ArgInput>(__input), ::std::forward<_ArgOutput>(__output), __error_code, __handled_errors) | |
, state(::std::forward<_ArgState>(__state)) { | |
} | |
}; | |
////// | |
/// @brief A type alias to produce a span-containing encode result type. Useful for end-users with fairly standard, | |
/// pointer-based buffer usages. | |
////// | |
template <typename _Encoding> | |
using span_encode_result_for = encode_result<::ztd::text::span<const code_point_t<_Encoding>>, | |
::ztd::text::span<code_unit_t<_Encoding>>, encode_state_t<_Encoding>>; | |
////// | |
/// @brief A type alias to produce a concrete error handler for the encoding result of the specified @p _Encoding | |
/// type. | |
/// | |
/// @tparam _Encoding The encoding to base this error handler off of. | |
/// @tparam _Function The template function type that will be used as the base type to insert the function | |
/// signature into. | |
////// | |
template <typename _Encoding, template <class...> class _Function = std::function> | |
using basic_encode_error_handler_for = _Function<span_encode_result_for<_Encoding>( | |
const _Encoding&, span_encode_result_for<_Encoding>, ::ztd::text::span<const code_point_t<_Encoding>>)>; | |
////// | |
/// @} | |
////// | |
namespace __txt_detail { | |
template <typename _Input, typename _Output, typename _State> | |
constexpr stateless_encode_result<_Input, _Output> | |
__slice_to_stateless(encode_result<_Input, _Output, _State>&& __result) noexcept( | |
::std::is_nothrow_constructible_v<stateless_encode_result<_Input, _Output>, | |
stateless_encode_result<_Input, _Output>>) { | |
return ::std::move(__result); | |
} | |
template <typename _Input, typename _Output, typename _State, typename _DesiredOutput> | |
constexpr encode_result<_Input, __remove_cvref_t<_DesiredOutput>, _State> __replace_result_output( | |
encode_result<_Input, _Output, _State>&& __result, | |
_DesiredOutput&& | |
__desired_output) noexcept(::std::is_nothrow_constructible_v<encode_result<_Input, _Output, _State>, | |
_Input&&, _DesiredOutput, _State&, encoding_error, ::std::size_t>) { | |
using _Result = encode_result<_Input, __remove_cvref_t<_DesiredOutput>, _State>; | |
return _Result(::std::move(__result.input), ::std::forward<_DesiredOutput>(__desired_output), | |
__result.state, __result.error_code, __result.handled_errors); | |
} | |
template <typename _InputRange, typename _OutputRange, typename _State> | |
using __reconstruct_encode_result_t | |
= encode_result<__range_reconstruct_t<_InputRange>, __range_reconstruct_t<_OutputRange>, _State>; | |
template <typename _InputRange, typename _OutputRange, typename _State, typename _InFirst, typename _InLast, | |
typename _OutFirst, typename _OutLast, typename _ArgState> | |
constexpr decltype(auto) __reconstruct_stateless_encode_result(_InFirst&& __in_first, _InLast&& __in_last, | |
_OutFirst&& __out_first, _OutLast&& __out_last, _ArgState&& __state, encoding_error __error_code, | |
::std::size_t __handled_errors) { | |
decltype(auto) __in_range = __reconstruct(::std::in_place_type<_InputRange>, | |
::std::forward<_InFirst>(__in_first), ::std::forward<_InLast>(__in_last)); | |
decltype(auto) __out_range = __reconstruct(::std::in_place_type<_OutputRange>, | |
::std::forward<_OutFirst>(__out_first), ::std::forward<_OutLast>(__out_last)); | |
return encode_result<_InputRange, _OutputRange, _State>(::std::forward<decltype(__in_range)>(__in_range), | |
::std::forward<decltype(__out_range)>(__out_range), ::std::forward<_ArgState>(__state), | |
__error_code, __handled_errors); | |
} | |
template <typename _InputRange, typename _OutputRange, typename _State, typename _InFirst, typename _InLast, | |
typename _OutFirst, typename _OutLast, typename _ArgState> | |
constexpr decltype(auto) __reconstruct_stateless_encode_result(_InFirst&& __in_first, _InLast&& __in_last, | |
_OutFirst&& __out_first, _OutLast&& __out_last, _ArgState&& __state, | |
encoding_error __error_code = encoding_error::ok) { | |
return __reconstruct_encode_result_t<_InputRange, _OutputRange, _State>( | |
::std::forward<_InFirst>(__in_first), ::std::forward<_InLast>(__in_last), | |
::std::forward<_OutFirst>(__out_first), ::std::forward<_OutLast>(__out_last), | |
::std::forward<_ArgState>(__state), __error_code); | |
} | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/encode_result.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/decode_result.hpp | |
#include <cstddef> | |
#include <array> | |
#include <utility> | |
#include <functional> | |
#include <system_error> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_result Result Types | |
/// @{ | |
///// | |
////// | |
/// @brief The result of all decode operations from encoding objects and higher-level calls (such as | |
/// ztd_text_decode). | |
////// | |
template <typename _Input, typename _Output> | |
class stateless_decode_result { | |
public: | |
////// | |
/// @brief The reconstructed input_view object, with its .begin() incremented by the number of code units | |
/// successfully read (can be identical to .begin() on original range on failure). | |
////// | |
_Input input; | |
////// | |
/// @brief The reconstructed output_view object, with its .begin() incremented by the number of code units | |
/// successfully written (can be identical to .begin() on original range on failure). | |
////// | |
_Output output; | |
////// | |
/// @brief The kind of error that occured, if any. | |
////// | |
encoding_error error_code; | |
////// | |
/// @brief Whether or not the error handler was invoked, regardless of if the error_code is set or not set to | |
/// ztd::text::encoding_error::ok. | |
////// | |
::std::size_t handled_errors; | |
////// | |
/// @brief Constructs a ztd::text::decode_result, defaulting the error code to | |
/// ztd::text::encoding_error::ok if not provided. | |
/// | |
/// @param[in] __input The input range to store. | |
/// @param[in] __output The output range to store. | |
/// @param[in] __error_code The error code for the decoding opertion, if any. | |
////// | |
template <typename _ArgInput, typename _ArgOutput, typename _ArgState> | |
constexpr stateless_decode_result(_ArgInput&& __input, _ArgOutput&& __output, | |
encoding_error __error_code | |
= encoding_error::ok) noexcept(noexcept(stateless_decode_result(::std::forward<_ArgInput>(__input), | |
::std::forward<_ArgOutput>(__output), __error_code, __error_code != encoding_error::ok))) | |
: stateless_decode_result(::std::forward<_ArgInput>(__input), ::std::forward<_ArgOutput>(__output), | |
__error_code, | |
__error_code != encoding_error::ok ? static_cast<::std::size_t>(1) : static_cast<::std::size_t>(0)) { | |
} | |
////// | |
/// @brief Constructs a ztd::text::decode_result with the provided parameters and information, | |
/// including whether or not an error was handled. | |
/// | |
/// @param[in] __input The input range to store. | |
/// @param[in] __output The output range to store. | |
/// @param[in] __error_code The error code for the decode operation, taken as the first of either the decode | |
/// operation that failed. | |
/// @param[in] __handled_errors Whether or not an error was handled. Some error handlers are corrective (see | |
/// ztd::text::replacement_handler), and so the error code is not enough to determine if the handler was | |
/// invoked. This allows the value to be provided directly when constructing this result type. | |
////// | |
template <typename _ArgInput, typename _ArgOutput> | |
constexpr stateless_decode_result(_ArgInput&& __input, _ArgOutput&& __output, encoding_error __error_code, | |
::std::size_t __handled_errors) noexcept(::std::is_nothrow_constructible_v<_Input, | |
_ArgInput>&& ::std::is_nothrow_constructible_v<_Output, _ArgOutput>) | |
: input(::std::forward<_ArgInput>(__input)) | |
, output(::std::forward<_ArgOutput>(__output)) | |
, error_code(__error_code) | |
, handled_errors(__handled_errors) { | |
} | |
////// | |
/// @brief Whether or not any errors were handled. | |
/// | |
/// @returns Simply checks whether @c handled_errors is greater than 0. | |
////// | |
constexpr bool errors_were_handled() const noexcept { | |
return this->handled_errors > 0; | |
} | |
}; | |
////// | |
/// @brief The result of all decode operations from encoding objects and higher-level calls (such as | |
/// ztd_text_decode). | |
////// | |
template <typename _Input, typename _Output, typename _State> | |
class decode_result : public stateless_decode_result<_Input, _Output> { | |
private: | |
using __base_t = stateless_decode_result<_Input, _Output>; | |
public: | |
////// | |
/// @brief The state of the associated Encoding used for decoding input code units to code points. | |
/// | |
////// | |
::ztd::text::reference_wrapper<_State> state; | |
////// | |
/// @brief Constructs a ztd::text::decode_result, defaulting the error code to | |
/// ztd::text::encoding_error::ok if not provided. | |
/// | |
/// @param[in] __input The input range to store. | |
/// @param[in] __output The output range to store. | |
/// @param[in] __state The state related to the Encoding that performed the decode operation. | |
/// @param[in] __error_code The error code for the decoding opertion, if any. | |
////// | |
template <typename _ArgInput, typename _ArgOutput, typename _ArgState> | |
constexpr decode_result(_ArgInput&& __input, _ArgOutput&& __output, _ArgState&& __state, | |
encoding_error __error_code = encoding_error::ok) | |
: decode_result(::std::forward<_ArgInput>(__input), ::std::forward<_ArgOutput>(__output), | |
::std::forward<_ArgState>(__state), __error_code, | |
__error_code != encoding_error::ok ? static_cast<::std::size_t>(1) : static_cast<::std::size_t>(0)) { | |
} | |
////// | |
/// @brief Constructs a ztd::text::decode_result with the provided parameters and information, | |
/// including whether or not an error was handled. | |
/// | |
/// @param[in] __input The input range to store. | |
/// @param[in] __output The output range to store. | |
/// @param[in] __state The state related to the Encoding that performed the decode operation. | |
/// @param[in] __error_code The error code for the decode operation, taken as the first of either the decode | |
/// operation that failed. | |
/// @param[in] __handled_errors Whether or not an error was handled. Some error handlers are corrective (see | |
/// ztd::text::replacement_handler), and so the error code is not enough to determine if the handler was | |
/// invoked. This allows the value to be provided directly when constructing this result type. | |
////// | |
template <typename _ArgInput, typename _ArgOutput, typename _ArgState> | |
constexpr decode_result(_ArgInput&& __input, _ArgOutput&& __output, _ArgState&& __state, | |
encoding_error __error_code, ::std::size_t __handled_errors) | |
: __base_t( | |
::std::forward<_ArgInput>(__input), ::std::forward<_ArgOutput>(__output), __error_code, __handled_errors) | |
, state(::std::forward<_ArgState>(__state)) { | |
} | |
}; | |
////// | |
/// @brief A type alias to produce a span-containing decode result type. Useful for end-users with fairly standard, | |
/// pointer-based buffer usages. | |
////// | |
template <typename _Encoding> | |
using span_decode_result_for = decode_result<::ztd::text::span<const code_unit_t<_Encoding>>, | |
::ztd::text::span<code_point_t<_Encoding>>, decode_state_t<_Encoding>>; | |
////// | |
/// @brief A type alias to produce a concrete error handler for the encoding result of the specified @p _Encoding | |
/// type. | |
/// | |
/// @tparam _Encoding The encoding to base this error handler off of. | |
/// @tparam _Function The template function type that will be used as the base type to insert the function | |
/// signature into. | |
////// | |
template <typename _Encoding, template <class...> class _Function = std::function> | |
using basic_decode_error_handler_for = _Function<span_decode_result_for<_Encoding>( | |
const _Encoding&, span_decode_result_for<_Encoding>, ::ztd::text::span<const code_unit_t<_Encoding>>)>; | |
////// | |
/// @} | |
///// | |
namespace __txt_detail { | |
template <typename _Input, typename _Output, typename _State> | |
constexpr stateless_decode_result<_Input, _Output> | |
__slice_to_stateless(decode_result<_Input, _Output, _State>&& __result) noexcept( | |
::std::is_nothrow_constructible_v<stateless_decode_result<_Input, _Output>, | |
stateless_decode_result<_Input, _Output>>) { | |
return ::std::move(__result); | |
} | |
template <typename _Input, typename _Output, typename _State, typename _DesiredOutput> | |
constexpr decode_result<_Input, __remove_cvref_t<_DesiredOutput>, _State> __replace_result_output( | |
decode_result<_Input, _Output, _State>&& __result, | |
_DesiredOutput&& | |
__desired_output) noexcept(::std::is_nothrow_constructible_v<decode_result<_Input, _Output, _State>, | |
_Input&&, _DesiredOutput, _State&, encoding_error, ::std::size_t>) { | |
using _Result = decode_result<_Input, __remove_cvref_t<_DesiredOutput>, _State>; | |
return _Result(::std::move(__result.input), ::std::forward<_DesiredOutput>(__desired_output), | |
__result.state, __result.error_code, __result.handled_errors); | |
} | |
template <typename _InputRange, typename _OutputRange, typename _State> | |
using __reconstruct_decode_result_t | |
= decode_result<__range_reconstruct_t<_InputRange>, __range_reconstruct_t<_OutputRange>, _State>; | |
template <typename _InputRange, typename _OutputRange, typename _State, typename _InFirst, typename _InLast, | |
typename _OutFirst, typename _OutLast, typename _ArgState> | |
constexpr decltype(auto) __reconstruct_stateless_decode_result(_InFirst&& __in_first, _InLast&& __in_last, | |
_OutFirst&& __out_first, _OutLast&& __out_last, _ArgState&& __state, encoding_error __error_code, | |
::std::size_t __handled_errors) { | |
decltype(auto) __in_range = __reconstruct(::std::in_place_type<_InputRange>, | |
::std::forward<_InFirst>(__in_first), ::std::forward<_InLast>(__in_last)); | |
decltype(auto) __out_range = __reconstruct(::std::in_place_type<_OutputRange>, | |
::std::forward<_OutFirst>(__out_first), ::std::forward<_OutLast>(__out_last)); | |
return decode_result<_InputRange, _OutputRange, _State>(::std::forward<decltype(__in_range)>(__in_range), | |
::std::forward<decltype(__out_range)>(__out_range), ::std::forward<_ArgState>(__state), | |
__error_code, __handled_errors); | |
} | |
template <typename _InputRange, typename _OutputRange, typename _State, typename _InFirst, typename _InLast, | |
typename _OutFirst, typename _OutLast, typename _ArgState> | |
constexpr decltype(auto) __reconstruct_stateless_decode_result(_InFirst&& __in_first, _InLast&& __in_last, | |
_OutFirst&& __out_first, _OutLast&& __out_last, _ArgState&& __state, | |
encoding_error __error_code = encoding_error::ok) { | |
return __reconstruct_decode_result_t<_InputRange, _OutputRange, _State>( | |
::std::forward<_InFirst>(__in_first), ::std::forward<_InLast>(__in_last), | |
::std::forward<_OutFirst>(__out_first), ::std::forward<_OutLast>(__out_last), | |
::std::forward<_ArgState>(__state), __error_code); | |
} | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/decode_result.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/error_handler.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/c_string_view.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/basic_c_string_view.hpp | |
#include <string_view> | |
#include <utility> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @brief A sentinel type for ztd::text::basic_c_string_view. Provides additional type safety. | |
/// | |
////// | |
class c_string_sentinel_t {}; | |
////// | |
/// @brief An instance of the c_string_sentinel_t type, for ease of use. | |
/// | |
////// | |
inline constexpr c_string_sentinel_t c_string_sentinel = {}; | |
////// | |
/// @brief A class that is identical to std::string_view, except that it attempts to verify and guarantee that | |
/// ``.data() + .size()``, when dereferenced, is valid and gives a nullptr. The ``.size()`` does not include the | |
/// null terminator in its count. | |
////// | |
template <typename _CharType, typename _Traits = ::std::char_traits<_CharType>> | |
class basic_c_string_view : private ::std::basic_string_view<_CharType, _Traits> { | |
private: | |
using __base_t = ::std::basic_string_view<_CharType, _Traits>; | |
constexpr bool _M_last_element_check() const noexcept { | |
const _CharType& __last_element = *(this->data() + this->size()); | |
return __last_element == static_cast<_CharType>('\0'); | |
} | |
public: | |
using const_iterator = typename __base_t::const_iterator; | |
using const_pointer = typename __base_t::const_pointer; | |
using const_reverse_iterator = typename __base_t::const_reverse_iterator; | |
using difference_type = typename __base_t::difference_type; | |
using iterator = typename __base_t::iterator; | |
using pointer = typename __base_t::pointer; | |
using reference = typename __base_t::reference; | |
using const_reference = typename __base_t::reference; | |
using reverse_iterator = typename __base_t::reverse_iterator; | |
using size_type = typename __base_t::size_type; | |
using traits_type = typename __base_t::traits_type; | |
using value_type = typename __base_t::value_type; | |
using __base_t::npos; | |
constexpr basic_c_string_view() noexcept | |
: basic_c_string_view( | |
static_cast<const_pointer>(__txt_detail::__empty_string<_CharType>()), static_cast<size_type>(1)) { | |
} | |
constexpr basic_c_string_view(const_iterator __arg0, const_iterator __arg1) noexcept | |
#if defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL >= 1 | |
: __base_t(__arg0 == __arg1 ? __txt_detail::__empty_string<_CharType>() : ::std::addressof(*__arg0), | |
::std::distance(__arg0, __arg1)) { | |
#else | |
: __base_t(::std::addressof(*__arg0), ::std::distance(__arg0, __arg1)) { | |
#endif | |
ZTD_TEXT_ASSERT_MESSAGE_I_("c_string_view must be null-terminated!", this->_M_last_element_check()); | |
} | |
constexpr basic_c_string_view(const_iterator __arg0, size_type __arg1) noexcept : __base_t(__arg0, __arg1) { | |
ZTD_TEXT_ASSERT_MESSAGE_I_("c_string_view must be null-terminated!", this->_M_last_element_check()); | |
} | |
#if defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL >= 0 | |
constexpr basic_c_string_view(const_pointer __arg0, const_pointer __arg1) noexcept | |
#if defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL >= 1 | |
: __base_t(__arg0 == __arg1 ? __txt_detail::__empty_string<_CharType>() : ::std::addressof(*__arg0), | |
::std::distance(__arg0, __arg1)) { | |
#else | |
: __base_t(::std::addressof(*__arg0), ::std::distance(__arg0, __arg1)) { | |
#endif | |
ZTD_TEXT_ASSERT_MESSAGE_I_("c_string_view must be null-terminated!", this->_M_last_element_check()); | |
} | |
constexpr basic_c_string_view(const_pointer __arg0, size_type __arg1) : __base_t(__arg0, __arg1) { | |
ZTD_TEXT_ASSERT_MESSAGE_I_("c_string_view must be null-terminated!", this->_M_last_element_check()); | |
} | |
#endif // not needed if iterator is implicitly constructible from the pointer | |
constexpr basic_c_string_view(const_pointer __arg0) noexcept : __base_t(__arg0, _Traits::length(__arg0)) { | |
ZTD_TEXT_ASSERT_MESSAGE_I_("c_string_view must be null-terminated!", this->_M_last_element_check()); | |
} | |
template <typename _Arg, | |
::std::enable_if_t< | |
!::std::is_same_v<__txt_detail::__remove_cvref_t<_Arg>, | |
basic_c_string_view> && !::std::is_same_v<__txt_detail::__remove_cvref_t<_Arg>, const_pointer> && !::std::is_array_v<__txt_detail::__remove_cvref_t<_Arg>>>* = nullptr> | |
constexpr basic_c_string_view(_Arg&& __arg) noexcept : __base_t(::std::data(__arg), ::std::size(__arg)) { | |
ZTD_TEXT_ASSERT_MESSAGE_I_("c_string_view must be null-terminated!", this->_M_last_element_check()); | |
} | |
constexpr basic_c_string_view(basic_c_string_view&&) = default; | |
constexpr basic_c_string_view(const basic_c_string_view&) = default; | |
constexpr basic_c_string_view& operator=(basic_c_string_view&&) = default; | |
constexpr basic_c_string_view& operator=(const basic_c_string_view&) = default; | |
constexpr size_type size() const noexcept { | |
return this->__base_t::size(); | |
} | |
constexpr size_type length() const noexcept { | |
return this->size(); | |
} | |
using __base_t::front; | |
using __base_t::max_size; | |
using __base_t::operator[]; | |
constexpr bool empty() const noexcept { | |
return this->cbegin() == this->cend(); | |
} | |
constexpr reference back() noexcept { | |
return *(this->data() + this->size()); | |
} | |
constexpr const_reference back() const noexcept { | |
return *(this->data() + this->size()); | |
} | |
constexpr pointer data() noexcept { | |
return this->__base_t::data(); | |
} | |
constexpr const_pointer data() const noexcept { | |
return this->__base_t::data(); | |
} | |
constexpr const_pointer cdata() const noexcept { | |
return this->__base_t::data(); | |
} | |
constexpr const_pointer c_str() const noexcept { | |
return this->data(); | |
} | |
constexpr const_iterator begin() const noexcept { | |
return this->__base_t::begin(); | |
} | |
constexpr iterator begin() noexcept { | |
return this->__base_t::begin(); | |
} | |
constexpr const_iterator cbegin() const noexcept { | |
return this->__base_t::cbegin(); | |
} | |
constexpr const_iterator end() const noexcept { | |
const_iterator __it = this->__base_t::end(); | |
return __it; | |
} | |
constexpr iterator end() noexcept { | |
iterator __it = this->__base_t::end(); | |
return __it; | |
} | |
constexpr const_iterator cend() const noexcept { | |
const_iterator __it = this->__base_t::cend(); | |
return __it; | |
} | |
constexpr const_reverse_iterator rbegin() const noexcept { | |
return this->__base_t::rbegin(); | |
} | |
constexpr reverse_iterator rbegin() noexcept { | |
return this->__base_t::rbegin(); | |
} | |
constexpr const_reverse_iterator crbegin() const noexcept { | |
return this->__base_t::crbegin(); | |
} | |
constexpr const_reverse_iterator rend() const noexcept { | |
const_reverse_iterator __it = this->__base_t::rend(); | |
return __it; | |
} | |
constexpr reverse_iterator rend() noexcept { | |
reverse_iterator __it = this->__base_t::rend(); | |
return __it; | |
} | |
constexpr const_reverse_iterator crend() const noexcept { | |
const_reverse_iterator __it = this->__base_t::crend(); | |
return __it; | |
} | |
// TODO: properly re-implement all of these methods to exclude the null terminator!! | |
using __base_t::compare; | |
using __base_t::copy; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_STARTS_ENDS_WITH_I_) | |
using __base_t::ends_with; | |
using __base_t::starts_with; | |
#endif | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_STRING_CONTAINS_I_) | |
using __base_t::contains; | |
#endif | |
using __base_t::find; | |
using __base_t::remove_prefix; | |
using __base_t::rfind; | |
using __base_t::find_first_not_of; | |
using __base_t::find_first_of; | |
using __base_t::find_last_not_of; | |
using __base_t::find_last_of; | |
template <typename _It, typename _Sen> | |
friend constexpr __base_t reconstruct( | |
::std::in_place_type_t<basic_c_string_view>, _It __iterator, _Sen __sentinel) { | |
using _SizeType = typename __base_t::size_type; | |
if constexpr (!::std::is_integral_v<_Sen>) { | |
#if defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL >= 1 | |
if (__iterator == __sentinel) { | |
const auto& __empty_str = __txt_detail::__empty_string<value_type>(); | |
return __base_t(__empty_str + 0, 0); | |
} | |
#endif | |
return __base_t(::std::addressof(*__iterator), static_cast<_SizeType>(__sentinel - __iterator)); | |
} | |
else { | |
#if defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL >= 1 | |
if (static_cast<_SizeType>(__sentinel) == static_cast<_SizeType>(0)) { | |
const auto& __empty_str = __txt_detail::__empty_string<value_type>(); | |
return __base_t(__empty_str + 0, 0); | |
} | |
#endif | |
return __base_t(::std::addressof(*__iterator), static_cast<_SizeType>(__sentinel)); | |
} | |
} | |
}; | |
template <typename _CharType, typename _Traits> | |
constexpr bool operator==( | |
basic_c_string_view<_CharType, _Traits> __left, basic_c_string_view<_CharType, _Traits> __right) noexcept { | |
return __left.size() == __right.size() && __left.compare(__right) == 0; | |
} | |
template <typename _CharType, typename _Traits> | |
constexpr bool operator==(basic_c_string_view<_CharType, _Traits> __left, | |
__txt_detail::__type_identity_t<basic_c_string_view<_CharType, _Traits>> __right) noexcept { | |
return __left.size() == __right.size() && __left.compare(__right) == 0; | |
} | |
template <typename _CharType, typename _Traits> | |
constexpr bool operator==(__txt_detail::__type_identity_t<basic_c_string_view<_CharType, _Traits>> __left, | |
basic_c_string_view<_CharType, _Traits> __right) noexcept { | |
return __left.size() == __right.size() && __left.compare(__right) == 0; | |
} | |
template <typename _CharType, typename _Traits> | |
constexpr bool operator!=( | |
basic_c_string_view<_CharType, _Traits> __left, basic_c_string_view<_CharType, _Traits> __right) noexcept { | |
return !(__left == __right); | |
} | |
template <typename _CharType, typename _Traits> | |
constexpr bool operator!=(basic_c_string_view<_CharType, _Traits> __left, | |
__txt_detail::__type_identity_t<basic_c_string_view<_CharType, _Traits>> __right) noexcept { | |
return !(__left == __right); | |
} | |
template <typename _CharType, typename _Traits> | |
constexpr bool operator!=(__txt_detail::__type_identity_t<basic_c_string_view<_CharType, _Traits>> __left, | |
basic_c_string_view<_CharType, _Traits> __right) noexcept { | |
return !(__left == __right); | |
} | |
template <typename _CharType, typename _Traits> | |
constexpr bool operator<( | |
basic_c_string_view<_CharType, _Traits> __left, basic_c_string_view<_CharType, _Traits> __right) noexcept { | |
return __left.compare(__right) < 0; | |
} | |
template <typename _CharType, typename _Traits> | |
constexpr bool operator<(basic_c_string_view<_CharType, _Traits> __left, | |
__txt_detail::__type_identity_t<basic_c_string_view<_CharType, _Traits>> __right) noexcept { | |
return __left.compare(__right) < 0; | |
} | |
template <typename _CharType, typename _Traits> | |
constexpr bool operator<(__txt_detail::__type_identity_t<basic_c_string_view<_CharType, _Traits>> __left, | |
basic_c_string_view<_CharType, _Traits> __right) noexcept { | |
return __left.compare(__right) < 0; | |
} | |
template <typename _CharType, typename _Traits> | |
constexpr bool operator>( | |
basic_c_string_view<_CharType, _Traits> __left, basic_c_string_view<_CharType, _Traits> __right) noexcept { | |
return __left.compare(__right) > 0; | |
} | |
template <typename _CharType, typename _Traits> | |
constexpr bool operator>(basic_c_string_view<_CharType, _Traits> __left, | |
__txt_detail::__type_identity_t<basic_c_string_view<_CharType, _Traits>> __right) noexcept { | |
return __left.compare(__right) > 0; | |
} | |
template <typename _CharType, typename _Traits> | |
constexpr bool operator>(__txt_detail::__type_identity_t<basic_c_string_view<_CharType, _Traits>> __left, | |
basic_c_string_view<_CharType, _Traits> __right) noexcept { | |
return __left.compare(__right) > 0; | |
} | |
template <typename _CharType, typename _Traits> | |
constexpr bool operator<=( | |
basic_c_string_view<_CharType, _Traits> __left, basic_c_string_view<_CharType, _Traits> __right) noexcept { | |
return __left.compare(__right) <= 0; | |
} | |
template <typename _CharType, typename _Traits> | |
constexpr bool operator<=(basic_c_string_view<_CharType, _Traits> __left, | |
__txt_detail::__type_identity_t<basic_c_string_view<_CharType, _Traits>> __right) noexcept { | |
return __left.compare(__right) <= 0; | |
} | |
template <typename _CharType, typename _Traits> | |
constexpr bool operator<=(__txt_detail::__type_identity_t<basic_c_string_view<_CharType, _Traits>> __left, | |
basic_c_string_view<_CharType, _Traits> __right) noexcept { | |
return __left.compare(__right) <= 0; | |
} | |
template <typename _CharType, typename _Traits> | |
constexpr bool operator>=( | |
basic_c_string_view<_CharType, _Traits> __left, basic_c_string_view<_CharType, _Traits> __right) noexcept { | |
return __left.compare(__right) >= 0; | |
} | |
template <typename _CharType, typename _Traits> | |
constexpr bool operator>=(basic_c_string_view<_CharType, _Traits> __left, | |
__txt_detail::__type_identity_t<basic_c_string_view<_CharType, _Traits>> __right) noexcept { | |
return __left.compare(__right) >= 0; | |
} | |
template <typename _CharType, typename _Traits> | |
constexpr bool operator>=(__txt_detail::__type_identity_t<basic_c_string_view<_CharType, _Traits>> __left, | |
basic_c_string_view<_CharType, _Traits> __right) noexcept { | |
return __left.compare(__right) >= 0; | |
} | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
namespace std { | |
template <typename _CharType, typename _Traits> | |
struct hash<::ztd::text::basic_c_string_view<_CharType, _Traits>> { | |
constexpr size_t operator()(const ::ztd::text::basic_c_string_view<_CharType, _Traits>& __c_string) const { | |
::std::hash<::std::basic_string_view<_CharType, _Traits>> h; | |
return h(__c_string); | |
} | |
}; | |
} // namespace std | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/basic_c_string_view.hpp | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @brief A basic_c_string_view for a @c char sequence. | |
/// | |
////// | |
using c_string_view = basic_c_string_view<char>; | |
////// | |
/// @brief A basic_c_string_view for a @c wchar_t sequence. | |
/// | |
////// | |
using wc_string_view = basic_c_string_view<wchar_t>; | |
////// | |
/// @brief A basic_c_string_view for a @c char8_t sequence. | |
/// | |
////// | |
using u8c_string_view = basic_c_string_view<uchar8_t>; | |
////// | |
/// @brief A basic_c_string_view for a @c char16_t sequence. | |
/// | |
////// | |
using u16c_string_view = basic_c_string_view<char16_t>; | |
////// | |
/// @brief A basic_c_string_view for a @c char32_t sequence. | |
/// | |
////// | |
using u32c_string_view = basic_c_string_view<char32_t>; | |
inline namespace literals { inline namespace string_view_literals { | |
////// | |
/// @brief A literal suffix to obtain a ztd::text::c_string_view from a @c "abc" string literal. | |
/// | |
////// | |
inline constexpr c_string_view operator"" _csv(const char* __str, size_t __len) noexcept { | |
return c_string_view(__str, __len); | |
} | |
////// | |
/// @brief A literal suffix to obtain a ztd::text::wc_string_view from a @c L"abc" string literal. | |
/// | |
////// | |
inline constexpr wc_string_view operator"" _wcsv(const wchar_t* __str, size_t __len) noexcept { | |
return wc_string_view(__str, __len); | |
} | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_NATIVE_CHAR8_T_I_) | |
////// | |
/// @brief A literal suffix to obtain a ztd::text::u8c_string_view from a @c u8"abc" string literal. | |
/// | |
////// | |
inline constexpr u8c_string_view operator"" _u8csv(const char8_t* __str, size_t __len) noexcept { | |
if constexpr (::std::is_same_v<uchar8_t, char8_t>) { | |
return u8c_string_view(__str, __len); | |
} | |
else { | |
return u8c_string_view(reinterpret_cast<const uchar8_t*>(__str), __len); | |
} | |
} | |
#else | |
////// | |
/// @brief A literal suffix to obtain a ztd::text::u8c_string_view from a @c u8"abc" string literal. | |
/// | |
////// | |
inline u8c_string_view operator"" _u8csv(const char* __str, size_t __len) noexcept { | |
return u8c_string_view(reinterpret_cast<const uchar8_t*>(__str), __len); | |
} | |
#endif // char8_t hacks | |
////// | |
/// @brief A literal suffix to obtain a ztd::text::u16c_string_view from a @c u"abc" string literal. | |
/// | |
////// | |
inline constexpr u16c_string_view operator"" _u16csv(const char16_t* __str, size_t __len) noexcept { | |
return u16c_string_view(__str, __len); | |
} | |
////// | |
/// @brief A literal suffix to obtain a ztd::text::u32c_string_view from a @c U"abc" string literal. | |
/// | |
////// | |
inline constexpr u32c_string_view operator"" _u32csv(const char32_t* __str, size_t __len) noexcept { | |
return u32c_string_view(__str, __len); | |
} | |
}} // namespace literals::string_view_literals | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/c_string_view.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/is_code_points_replaceable.hpp | |
#include <type_traits> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _Type> | |
using __detect_is_code_points_maybe_replaceable | |
= decltype(::std::declval<const _Type&>().maybe_replacement_code_points()); | |
template <typename _Type> | |
using __detect_is_code_points_replaceable | |
= decltype(::std::declval<const _Type&>().replacement_code_points()); | |
} // namespace __txt_detail | |
////// | |
/// @brief Checks whether the given encoding type returns a maybe-replacement range of code points. | |
/// | |
/// @tparam _Type The type to check for the proper function call. | |
/// | |
/// @remarks The @c value boolean is true if the given @p _Type has a function named @c | |
/// maybe_replacement_code_points() on it that can be called from a @c const -qualified @p _Type object which | |
/// returns a @c std::optional containing a contiguous view of code points. | |
////// | |
template <typename _Type> | |
class is_code_points_maybe_replaceable | |
: public __txt_detail::__is_detected<__txt_detail::__detect_is_code_points_maybe_replaceable, _Type> { }; | |
////// | |
/// @brief A @c \::value alias for ztd::text::is_code_points_maybe_replaceable | |
/// | |
////// | |
template <typename _Type> | |
inline constexpr bool is_code_points_maybe_replaceable_v = is_code_points_maybe_replaceable<_Type>::value; | |
////// | |
/// @brief Checks whether the given encoding type returns a maybe-replacement range of code points. | |
/// | |
/// @tparam _Type The type to check for the proper function call. | |
/// | |
/// @remarks The @c value boolean is true if the given @p _Type has a function named @c | |
/// replacement_code_points() on it that can be called from a @c const -qualified @c _Type object which returns a | |
/// contiguous view of code points. | |
////// | |
template <typename _Type> | |
class is_code_points_replaceable | |
: public __txt_detail::__is_detected<__txt_detail::__detect_is_code_points_replaceable, _Type> { }; | |
////// | |
/// @brief A @c \::value alias for ztd::text::is_code_points_replaceable | |
/// | |
////// | |
template <typename _Type> | |
inline constexpr bool is_code_points_replaceable_v = is_code_points_replaceable<_Type>::value; | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/is_code_points_replaceable.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/is_code_units_replaceable.hpp | |
#include <type_traits> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _Type> | |
using __detect_is_code_units_maybe_replaceable | |
= decltype(::std::declval<const _Type&>().maybe_replacement_code_units()); | |
template <typename _Type> | |
using __detect_is_code_units_replaceable = decltype(::std::declval<const _Type&>().replacement_code_units()); | |
} // namespace __txt_detail | |
////// | |
/// @brief Checks whether the given encoding type returns a maybe-replacement range of code units. | |
/// | |
/// @tparam _Type The type to check for the proper function call. | |
/// | |
/// @remarks The @c value boolean is true if the given @p _Type has a function named @c | |
/// maybe_replacement_code_units() on it that can be called from a @c const -qualified @c _Type which returns | |
/// a @c std::optional containing a contiguous view of code units. | |
////// | |
template <typename _Type> | |
class is_code_units_maybe_replaceable | |
: public __txt_detail::__is_detected<__txt_detail::__detect_is_code_units_maybe_replaceable, _Type> { }; | |
////// | |
/// @brief A @c \::value alias for ztd::text::is_code_units_maybe_replaceable | |
/// | |
////// | |
template <typename _Type> | |
inline constexpr bool is_code_units_maybe_replaceable_v = is_code_units_maybe_replaceable<_Type>::value; | |
////// | |
/// @brief Checks whether the given encoding type returns a maybe-replacement range of code units. | |
/// | |
/// @tparam _Type The type to check for the proper function call. | |
/// | |
/// @remarks The @c \::value boolean is true if the given @p _Type has a function named @c | |
/// replacement_code_units() on it that can be called from a @c const -qualified @c _Type which returns | |
/// a contiguous view of code units. | |
////// | |
template <typename _Type> | |
class is_code_units_replaceable | |
: public __txt_detail::__is_detected<__txt_detail::__detect_is_code_units_replaceable, _Type> { }; | |
////// | |
/// @brief A @c \::value alias for ztd::text::is_code_units_replaceable | |
/// | |
////// | |
template <typename _Type> | |
inline constexpr bool is_code_units_replaceable_v = is_code_units_replaceable<_Type>::value; | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/is_code_units_replaceable.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/is_unicode_code_point.hpp | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
template <typename _Type> | |
class is_unicode_scalar_value | |
: public ::std::integral_constant<bool, | |
::std::is_same_v<__txt_detail::__remove_cvref_t<_Type>, __impl::__unicode_scalar_value>> { }; | |
template <typename _Type> | |
inline constexpr bool is_unicode_scalar_value_v = is_unicode_scalar_value<_Type>::value; | |
template <typename _Type> | |
class is_unicode_code_point | |
: public ::std::integral_constant<bool, | |
::std::is_same_v<__txt_detail::__remove_cvref_t<_Type>, | |
char32_t> || ::std::is_same_v<__txt_detail::__remove_cvref_t<_Type>, __impl::__unicode_code_point> || is_unicode_scalar_value_v<_Type>> { | |
}; | |
template <typename _Type> | |
inline constexpr bool is_unicode_code_point_v = is_unicode_code_point<_Type>::value; | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/is_unicode_code_point.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/ebco.hpp | |
#include <utility> | |
#include <type_traits> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _Type, ::std::size_t = 0, typename = void> | |
class __ebco { | |
private: | |
_Type _M_value; | |
public: | |
__ebco() = default; | |
__ebco(const __ebco&) = default; | |
__ebco(__ebco&&) = default; | |
__ebco& operator=(const __ebco&) = default; | |
__ebco& operator=(__ebco&&) = default; | |
constexpr __ebco(const _Type& __value) noexcept(::std::is_nothrow_copy_constructible_v<_Type>) | |
: _M_value(__value) {}; | |
constexpr __ebco(_Type&& __value) noexcept(::std::is_nothrow_move_constructible_v<_Type>) | |
: _M_value(::std::move(__value)) {}; | |
constexpr __ebco& operator=(const _Type& __value) noexcept(::std::is_nothrow_copy_assignable_v<_Type>) { | |
this->_M_value = __value; | |
return *this; | |
} | |
constexpr __ebco& operator=(_Type&& __value) noexcept(::std::is_nothrow_move_assignable_v<_Type>) { | |
this->_M_value = ::std::move(__value); | |
return *this; | |
}; | |
template <typename _Arg, typename... _Args, | |
typename = ::std::enable_if_t< | |
!::std::is_same_v<::std::remove_reference_t<::std::remove_cv_t<_Arg>>, | |
__ebco> && !::std::is_same_v<::std::remove_reference_t<::std::remove_cv_t<_Arg>>, _Type>>> | |
constexpr __ebco(_Arg&& __arg, _Args&&... __args) noexcept( | |
::std::is_nothrow_constructible_v<_Type, _Arg, _Args...>) | |
: _M_value(::std::forward<_Arg>(__arg), ::std::forward<_Args>(__args)...) { | |
} | |
constexpr _Type& __get_value() & noexcept { | |
return static_cast<_Type&>(this->_M_value); | |
} | |
constexpr _Type const& __get_value() const& noexcept { | |
return static_cast<_Type const&>(this->_M_value); | |
} | |
constexpr _Type&& __get_value() && noexcept { | |
return static_cast<_Type&&>(this->_M_value); | |
} | |
}; | |
template <typename _Type, ::std::size_t _Tag> | |
class __ebco<_Type, _Tag, | |
::std::enable_if_t< | |
::std::is_class_v<_Type> && !::std::is_final_v<_Type> && !::std::is_reference_v<_Type>>> | |
: private _Type { | |
public: | |
__ebco() = default; | |
__ebco(const __ebco&) = default; | |
__ebco(__ebco&&) = default; | |
constexpr __ebco(const _Type& __value) noexcept(::std::is_nothrow_copy_constructible_v<_Type>) | |
: _Type(__value) {}; | |
constexpr __ebco(_Type&& __value) noexcept(::std::is_nothrow_move_constructible_v<_Type>) | |
: _Type(::std::move(__value)) {}; | |
template <typename _Arg, typename... _Args, | |
typename = ::std::enable_if_t< | |
!::std::is_same_v<::std::remove_reference_t<::std::remove_cv_t<_Arg>>, | |
__ebco> && !::std::is_same_v<::std::remove_reference_t<::std::remove_cv_t<_Arg>>, _Type>>> | |
constexpr __ebco(_Arg&& __arg, _Args&&... __args) noexcept( | |
::std::is_nothrow_constructible_v<_Type, _Arg, _Args...>) | |
: _Type(::std::forward<_Arg>(__arg), ::std::forward<_Args>(__args)...) { | |
} | |
__ebco& operator=(const __ebco&) = default; | |
__ebco& operator=(__ebco&&) = default; | |
constexpr __ebco& operator=(const _Type& __value) noexcept(::std::is_nothrow_copy_assignable_v<_Type>) { | |
static_cast<_Type&>(*this) = __value; | |
return *this; | |
} | |
constexpr __ebco& operator=(_Type&& __value) noexcept(::std::is_nothrow_move_assignable_v<_Type>) { | |
static_cast<_Type&>(*this) = ::std::move(__value); | |
return *this; | |
} | |
constexpr _Type& __get_value() & noexcept { | |
return static_cast<_Type&>(*this); | |
} | |
constexpr _Type const& __get_value() const& noexcept { | |
return static_cast<_Type const&>(*this); | |
} | |
constexpr _Type&& __get_value() && noexcept { | |
return static_cast<_Type&&>(*this); | |
} | |
}; | |
template <typename _Type, ::std::size_t _Tag> | |
class __ebco<_Type&, _Tag> { | |
private: | |
_Type* _M_p_value; | |
public: | |
__ebco() = default; | |
__ebco(const __ebco&) = default; | |
__ebco(__ebco&&) = default; | |
__ebco& operator=(const __ebco&) = default; | |
__ebco& operator=(__ebco&&) = default; | |
constexpr __ebco(_Type& __value) noexcept : _M_p_value(::std::addressof(__value)) {}; | |
constexpr __ebco& operator=(_Type& __value) noexcept { | |
*(this->_M_p_value) = __value; | |
return *this; | |
} | |
constexpr _Type& __get_value() & noexcept { | |
return *(this->_M_p_value); | |
} | |
constexpr _Type const& __get_value() const& noexcept { | |
return *(this->_M_p_value); | |
} | |
constexpr _Type&& __get_value() && noexcept { | |
return ::std::move(*(this->_M_p_value)); | |
} | |
}; | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/ebco.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/pass_through_handler.hpp | |
#include <type_traits> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <bool _AssumeVailidity = false> | |
class __pass_through_handler_with { | |
public: | |
////// | |
/// @brief A type that is true when calling code can not call this function and ignore it, and false when | |
/// it cannot ignore it. See ztd::text::assume_valid_handler for details. | |
////// | |
using assume_valid = ::std::integral_constant<bool, _AssumeVailidity>; | |
////// | |
/// @brief A handler for either decode or encode results that simply passes the result type back through | |
/// with no changes made. | |
/// | |
/// @param[in] __result The current state of the encode operation to pass through. | |
////// | |
template <typename _Encoding, typename _Result, typename _Progress> | |
constexpr auto operator()(const _Encoding&, _Result __result, const _Progress&) const { | |
return __result; | |
} | |
}; | |
using __pass_through_handler = __pass_through_handler_with<false>; | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/pass_through_handler.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/forwarding_handler.hpp | |
#include <utility> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _Encoding, typename _ErrorHandler> | |
class __forwarding_handler : private __txt_detail::__ebco<_Encoding&, 0>, | |
private __txt_detail::__ebco<_ErrorHandler&, 1> { | |
private: | |
using __encoding_base_t = __txt_detail::__ebco<_Encoding&, 0>; | |
using __error_handler_base_t = __txt_detail::__ebco<_ErrorHandler&, 1>; | |
public: | |
constexpr __forwarding_handler(_Encoding& __encoding, _ErrorHandler& __error_handler) noexcept | |
: __encoding_base_t(__encoding), __error_handler_base_t(__error_handler) { | |
} | |
template <typename _UnderlyingEncoding, typename _Result, typename _Progress> | |
constexpr auto operator()(_UnderlyingEncoding&&, _Result&& __result, _Progress&& __progress) const | |
noexcept(noexcept(this->__error_handler_base_t::__get_value()(this->__encoding_base_t::__get_value(), | |
::std::forward<_Result>(__result), ::std::forward<_Progress>(__progress)))) { | |
return this->__error_handler_base_t::__get_value()(this->__encoding_base_t::__get_value(), | |
::std::forward<_Result>(__result), ::std::forward<_Progress>(__progress)); | |
} | |
}; | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/forwarding_handler.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/transcode_one.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/transcode_result.hpp | |
#include <cstddef> | |
#include <array> | |
#include <utility> | |
#include <system_error> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_result Result Types | |
/// @brief The result types are used in the transcoding, validation and counting functions. Their sole goal is to | |
/// make sure. | |
/// @{ | |
///// | |
////// | |
/// @brief The result of transcoding operations (such as ztd_text_transcode) that specifically do not include | |
/// a reference to the state. | |
////// | |
template <typename _Input, typename _Output> | |
class stateless_transcode_result { | |
public: | |
////// | |
/// @brief The reconstructed input_view object, with its .begin() incremented by the number of code units | |
/// successfully read (can be identical to .begin() on original range on failure). | |
////// | |
_Input input; | |
////// | |
/// @brief The reconstructed output_view object, with its .begin() incremented by the number of code units | |
/// successfully written (can be identical to .begin() on original range on failure). | |
////// | |
_Output output; | |
////// | |
/// @brief The kind of error that occured, if any. | |
/// | |
////// | |
encoding_error error_code; | |
////// | |
/// @brief Whether or not the error handler was invoked, regardless of if the error_code is set or not set to | |
/// ztd::text::encoding_error::ok. | |
////// | |
::std::size_t handled_errors; | |
////// | |
/// @brief Constructs a ztd::text::stateless_transcode_result, defaulting the error code to | |
/// ztd::text::encoding_error::ok if not provided. | |
/// | |
/// @param[in] __input The input range to store. | |
/// @param[in] __output The output range to store. | |
/// @param[in] __error_code The error code for the encode operation, taken as the first of either the encode | |
/// or decode operation that failed. | |
////// | |
template <typename _ArgInput, typename _ArgOutput> | |
constexpr stateless_transcode_result(_ArgInput&& __input, _ArgOutput&& __output, | |
encoding_error __error_code | |
= encoding_error::ok) noexcept(noexcept(stateless_transcode_result(::std::forward<_ArgInput>(__input), | |
::std::forward<_ArgOutput>(__output), __error_code, __error_code != encoding_error::ok))) | |
: stateless_transcode_result(::std::forward<_ArgInput>(__input), ::std::forward<_ArgOutput>(__output), | |
__error_code, __error_code != encoding_error::ok) { | |
} | |
////// | |
/// @brief Constructs a ztd::text::stateless_transcode_result with the provided parameters and | |
/// information, including whether or not an error was handled. | |
/// | |
/// @param[in] __input The input range to store. | |
/// @param[in] __output The output range to store. | |
/// @param[in] __error_code The error code for the encode operation, taken as the first of either the encode | |
/// or decode operation that failed. | |
/// @param[in] __handled_errors Whether or not an error was handled. Some error handlers are corrective (see | |
/// ztd::text::replacement_handler), and so the error code is not enough to determine if the handler was | |
/// invoked. This allows the value to be provided directly when constructing this result type. | |
////// | |
template <typename _ArgInput, typename _ArgOutput> | |
constexpr stateless_transcode_result(_ArgInput&& __input, _ArgOutput&& __output, encoding_error __error_code, | |
::std::size_t __handled_errors) noexcept(::std::is_nothrow_constructible_v<_Input, | |
_ArgInput>&& ::std::is_nothrow_constructible_v<_Output, _ArgOutput>) | |
: input(::std::forward<_ArgInput>(__input)) | |
, output(::std::forward<_ArgOutput>(__output)) | |
, error_code(__error_code) | |
, handled_errors(__handled_errors) { | |
} | |
////// | |
/// @brief Whether or not any errors were handled. | |
/// | |
/// @returns Simply checks whether @c handled_errors is greater than 0. | |
////// | |
constexpr bool errors_were_handled() const noexcept { | |
return this->handled_errors > 0; | |
} | |
}; | |
////// | |
/// @brief The result of transcoding operations (such as ztd_text_transcode). | |
/// | |
////// | |
template <typename _Input, typename _Output, typename _FromState, typename _ToState> | |
class transcode_result : public stateless_transcode_result<_Input, _Output> { | |
private: | |
using __base_t = stateless_transcode_result<_Input, _Output>; | |
public: | |
////// | |
/// @brief A reference to the state of the associated Encoding used for decoding input code units to | |
/// intermediate code points. | |
////// | |
::ztd::text::reference_wrapper<_FromState> from_state; | |
////// | |
/// @brief A reference to the state of the associated Encoding used for encoding intermediate code points to | |
/// code units. | |
////// | |
::ztd::text::reference_wrapper<_ToState> to_state; | |
////// | |
/// @brief Constructs a ztd::text::transcode_result, defaulting the error code to | |
/// ztd::text::encoding_error::ok if not provided. | |
/// | |
/// @param[in] __input The input range to store. | |
/// @param[in] __output The output range to store. | |
/// @param[in] __from_state The state related to the "From Encoding" that performed the decode half of the | |
/// operation. | |
/// @param[in] __to_state The state related to the "To Encoding" that performed the encode half of the | |
/// operation. | |
/// @param[in] __error_code The error code for the encode operation, taken as the first of either the encode | |
/// or decode operation that failed. | |
////// | |
template <typename _ArgInput, typename _ArgOutput, typename _ArgFromState, typename _ArgToState> | |
constexpr transcode_result(_ArgInput&& __input, _ArgOutput&& __output, _ArgFromState&& __from_state, | |
_ArgToState&& __to_state, encoding_error __error_code = encoding_error::ok) | |
: transcode_result(::std::forward<_ArgInput>(__input), ::std::forward<_ArgOutput>(__output), | |
::std::forward<_ArgFromState>(__from_state), ::std::forward<_ArgToState>(__to_state), __error_code, | |
__error_code != encoding_error::ok ? static_cast<::std::size_t>(1) : static_cast<::std::size_t>(0)) { | |
} | |
////// | |
/// @brief Constructs a ztd::text::transcode_result with the provided parameters and information, | |
/// including whether or not an error was handled. | |
/// | |
/// @param[in] __input The input range to store. | |
/// @param[in] __output The output range to store. | |
/// @param[in] __from_state The state related to the "From Encoding" that performed the decode half of the | |
/// operation. | |
/// @param[in] __to_state The state related to the "To Encoding" that performed the encode half of the | |
/// operation. | |
/// @param[in] __error_code The error code for the encode operation, taken as the first of either the encode | |
/// or decode operation that failed. | |
/// @param[in] __handled_errors Whether or not an error was handled. Some error handlers are corrective (see | |
/// ztd::text::replacement_handler), and so the error code is not enough to determine if the handler was | |
/// invoked. This allows the value to be provided directly when constructing this result type. | |
////// | |
template <typename _ArgInput, typename _ArgOutput, typename _ArgFromState, typename _ArgToState> | |
constexpr transcode_result(_ArgInput&& __input, _ArgOutput&& __output, _ArgFromState&& __from_state, | |
_ArgToState&& __to_state, encoding_error __error_code, ::std::size_t __handled_errors) | |
: __base_t( | |
::std::forward<_ArgInput>(__input), ::std::forward<_ArgOutput>(__output), __error_code, __handled_errors) | |
, from_state(::std::forward<_ArgFromState>(__from_state)) | |
, to_state(::std::forward<_ArgToState>(__to_state)) { | |
} | |
}; | |
////// | |
/// @} | |
///// | |
namespace __txt_detail { | |
template <typename _Input, typename _Output, typename _FromState, typename _ToState> | |
constexpr stateless_transcode_result<_Input, _Output> | |
__slice_to_stateless(transcode_result<_Input, _Output, _FromState, _ToState>&& __result) noexcept( | |
::std::is_nothrow_constructible_v<stateless_transcode_result<_Input, _Output>, | |
stateless_transcode_result<_Input, _Output>>) { | |
return ::std::move(__result); | |
} | |
template <typename _Input, typename _Output, typename _FromState, typename _ToState, typename _DesiredOutput> | |
constexpr transcode_result<_Input, __remove_cvref_t<_DesiredOutput>, _FromState, _ToState> | |
__replace_result_output(transcode_result<_Input, _Output, _FromState, _ToState>&& __result, | |
_DesiredOutput&& __desired_output) noexcept(::std:: | |
is_nothrow_constructible_v<transcode_result<_Input, _Output, _FromState, _ToState>, _Input&&, | |
_DesiredOutput, _FromState&, _ToState&, encoding_error, ::std::size_t>) { | |
using _Result = transcode_result<_Input, __remove_cvref_t<_DesiredOutput>, _FromState, _ToState>; | |
return _Result(::std::move(__result.input), ::std::forward<_DesiredOutput>(__desired_output), | |
__result.from_state, __result.to_state, __result.error_code, __result.handled_errors); | |
} | |
template <typename _InputRange, typename _OutputRange, typename _FromState, typename _ToState> | |
using __reconstruct_transcode_result_t = transcode_result<__range_reconstruct_t<_InputRange>, | |
__range_reconstruct_t<_OutputRange>, _FromState, _ToState>; | |
template <typename _InputRange, typename _OutputRange, typename _ToState, typename _FromState, | |
typename _InFirst, typename _InLast, typename _OutFirst, typename _OutLast, typename _ArgToState, | |
typename _ArgFromState> | |
constexpr decltype(auto) __reconstruct_stateless_transcode_result(_InFirst&& __in_first, _InLast&& __in_last, | |
_OutFirst&& __out_first, _OutLast&& __out_last, _ArgFromState&& __to_state, _ArgToState&& __from_state, | |
encoding_error __error_code, ::std::size_t __handled_errors) { | |
decltype(auto) __in_range = __reconstruct(::std::in_place_type<_InputRange>, | |
::std::forward<_InFirst>(__in_first), ::std::forward<_InLast>(__in_last)); | |
decltype(auto) __out_range = __reconstruct(::std::in_place_type<_OutputRange>, | |
::std::forward<_OutFirst>(__out_first), ::std::forward<_OutLast>(__out_last)); | |
return transcode_result<_InputRange, _OutputRange, _FromState, _ToState>( | |
::std::forward<decltype(__in_range)>(__in_range), | |
::std::forward<decltype(__out_range)>(__out_range), ::std::forward<_ArgFromState>(__from_state), | |
::std::forward<_ArgToState>(__to_state), __error_code, __handled_errors); | |
} | |
template <typename _InputRange, typename _OutputRange, typename _FromState, typename _ToState, | |
typename _InFirst, typename _InLast, typename _OutFirst, typename _OutLast, typename _ArgToState, | |
typename _ArgFromState> | |
constexpr decltype(auto) __reconstruct_stateless_transcode_result(_InFirst&& __in_first, _InLast&& __in_last, | |
_OutFirst&& __out_first, _OutLast&& __out_last, _ArgFromState&& __from_state, _ArgToState&& __to_state, | |
encoding_error __error_code = encoding_error::ok) { | |
return __reconstruct_transcode_result_t<_InputRange, _OutputRange, _FromState, _ToState>( | |
::std::forward<_InFirst>(__in_first), ::std::forward<_InLast>(__in_last), | |
::std::forward<_OutFirst>(__out_first), ::std::forward<_OutLast>(__out_last), | |
::std::forward<_ArgFromState>(__from_state), ::std::forward<_ArgToState>(__to_state), __error_code); | |
} | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/transcode_result.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/validate_result.hpp | |
#include <cstddef> | |
#include <array> | |
#include <utility> | |
#include <system_error> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_result Result Types | |
/// @{ | |
///// | |
////// | |
/// @brief The result of valdation operations (such as ztd_text_validate_decodable_as and | |
/// ztd_text_validate_encodable_as) that specifically do not include a reference to the state. | |
////// | |
template <typename _Input> | |
class stateless_validate_result { | |
public: | |
////// | |
/// @brief The reconstructed input_view object, with its .begin() incremented by the number of code units | |
/// successfully read (can be identical to .begin() on original range on failure). | |
////// | |
_Input input; | |
////// | |
/// @brief Whether or not the specified input is valid or not. | |
////// | |
bool valid; | |
////// | |
/// @brief Constructs a ztd::text::validate_result, defaulting the error code to | |
/// ztd::text::encoding_error::ok if not provided. | |
/// | |
/// @param[in] __input The input range to store. | |
/// @param[in] __is_valid Whether or not the validation succeeded. | |
////// | |
template <typename _ArgInput> | |
constexpr stateless_validate_result(_ArgInput&& __input, bool __is_valid) | |
: input(::std::forward<_ArgInput>(__input)), valid(__is_valid) { | |
} | |
////// | |
/// @brief A conversion for use in if statements and conditional operators. | |
/// | |
/// @return Whether or not the result is valid or not. | |
////// | |
constexpr explicit operator bool() const noexcept { | |
return valid; | |
} | |
}; | |
////// | |
/// @brief The result of validation operations (such as ztd_text_validate_decodable_as and | |
/// ztd_text_validate_encodable_as). | |
/// | |
////// | |
template <typename _Input, typename _State> | |
class validate_result : public stateless_validate_result<_Input> { | |
private: | |
using __base_t = stateless_validate_result<_Input>; | |
public: | |
////// | |
/// @brief A reference to the state of the associated Encoding used for validating the input. | |
/// | |
////// | |
::ztd::text::reference_wrapper<_State> state; | |
////// | |
/// @brief Constructs a ztd::text::validate_result, defaulting the error code to | |
/// ztd::text::encoding_error::ok if not provided. | |
/// | |
/// @param[in] __input The input range to store. | |
/// @param[in] __is_valid Whether or not the validation succeeded. | |
/// @param[in] __state The state related to the encoding that was used to do validation. | |
////// | |
template <typename _ArgInput, typename _ArgState> | |
constexpr validate_result(_ArgInput&& __input, bool __is_valid, _ArgState&& __state) | |
: __base_t(::std::forward<_ArgInput>(__input), __is_valid), state(::std::forward<_ArgState>(__state)) { | |
} | |
}; | |
////// | |
/// @brief The result of a transcoding validation operations (e.g. from ztd_text_validate_transcodable_as). | |
/// | |
////// | |
template <typename _Input, typename _DecodeState, typename _EncodeState> | |
class validate_transcode_result : public stateless_validate_result<_Input> { | |
private: | |
using __base_t = stateless_validate_result<_Input>; | |
public: | |
////// | |
/// @brief A reference to the state of the associated Encoding used for validating the input. | |
/// | |
////// | |
::ztd::text::reference_wrapper<_DecodeState> from_state; | |
////// | |
/// @brief A reference to the state of the associated Encoding used for validating the input. | |
/// | |
////// | |
::ztd::text::reference_wrapper<_EncodeState> to_state; | |
////// | |
/// @brief Constructs a ztd::text::validate_result, defaulting the error code to | |
/// ztd::text::encoding_error::ok if not provided. | |
/// | |
/// @param[in] __input The input range to store. | |
/// @param[in] __is_valid Whether or not the validation succeeded. | |
/// @param[in] __from_state The state related to the encoding that was used to do validation. | |
/// @param[in] __to_state The state related to the encoding that was used to do validation. | |
////// | |
template <typename _ArgInput, typename _ArgFromState, typename _ArgToState> | |
constexpr validate_transcode_result( | |
_ArgInput&& __input, bool __is_valid, _ArgFromState&& __from_state, _ArgToState&& __to_state) | |
: __base_t(::std::forward<_ArgInput>(__input), __is_valid) | |
, from_state(::std::forward<_ArgFromState>(__from_state)) | |
, to_state(::std::forward<_ArgToState>(__to_state)) { | |
} | |
}; | |
////// | |
/// @} | |
///// | |
namespace __txt_detail { | |
template <typename _Input, typename _State> | |
constexpr stateless_validate_result<_Input> | |
__slice_to_stateless(validate_result<_Input, _State>&& __result) noexcept( | |
::std::is_nothrow_constructible_v<stateless_validate_result<_Input>, validate_result<_Input, _State>>) { | |
return __result; | |
} | |
template <typename _Input, typename _DecodeState, typename _EncodeState> | |
constexpr stateless_validate_result<_Input> | |
__slice_to_stateless(validate_transcode_result<_Input, _DecodeState, _EncodeState>&& __result) noexcept( | |
::std::is_nothrow_constructible_v<stateless_validate_result<_Input>, | |
validate_transcode_result<_Input, _DecodeState, _EncodeState>>) { | |
return __result; | |
} | |
template <typename _Input, typename _DecodeState, typename _EncodeState> | |
constexpr validate_result<_Input, _DecodeState> | |
__drop_single_state(validate_transcode_result<_Input, _DecodeState, _EncodeState>&& __result) noexcept( | |
::std::is_nothrow_constructible_v<validate_result<_Input, _DecodeState>, _Input&&, bool&, | |
_DecodeState&>) { | |
return validate_result<_Input, _DecodeState>( | |
::std::move(__result.input), ::std::move(__result.valid), __result.from_state); | |
} | |
template <typename _InputRange, typename _State> | |
using __reconstruct_validate_result_t = validate_result<__reconstruct_t<_InputRange>, _State>; | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/validate_result.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/count_result.hpp | |
#include <cstddef> | |
#include <array> | |
#include <utility> | |
#include <system_error> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_result Result Types | |
/// @{ | |
////// | |
////// | |
/// @brief The result of counting operations (such as ztd_text_count_encodable and | |
/// ztd_text_count_encodable) that specifically do not include a reference to the state. | |
////// | |
template <typename _Input> | |
class stateless_count_result { | |
public: | |
////// | |
/// @brief The reconstructed input_view object, with its .begin() incremented by the number of code units | |
/// successfully read (can be identical to .begin() on original range on failure). | |
////// | |
_Input input; | |
////// | |
/// @brief The number of code units or code points counted successfully, so far. | |
/// | |
////// | |
::std::size_t count; | |
////// | |
/// @brief The kind of error that occured, if any. | |
/// | |
////// | |
encoding_error error_code; | |
////// | |
/// @brief Whether or not the error handler was invoked, regardless of if the error_code is set or not set to | |
/// ztd::text::encoding_error::ok. | |
////// | |
::std::size_t handled_errors; | |
////// | |
/// @brief Constructs a ztd::text::stateless_count_result, defaulting the error code to | |
/// ztd::text::encoding_error::ok if not provided. | |
/// | |
/// @param[in] __input The input range to store. | |
/// @param[in] __count The number of code points or code units successfully counted. | |
/// @param[in] __error_code The error code for the encode operation, taken as the first of either the encode | |
/// or decode operation that failed. | |
////// | |
template <typename _ArgInput> | |
constexpr stateless_count_result( | |
_ArgInput&& __input, ::std::size_t __count, encoding_error __error_code = encoding_error::ok) | |
: stateless_count_result( | |
::std::forward<_ArgInput>(__input), __count, __error_code, __error_code != encoding_error::ok) { | |
} | |
////// | |
/// @brief Constructs a ztd::text::stateless_count_result with the provided parameters and | |
/// information, including whether or not an error was handled. | |
/// | |
/// @param[in] __input The input range to store. | |
/// @param[in] __count The number of code points or code units successfully counted. | |
/// @param[in] __error_code The error code for the encode operation, taken as the first of either the encode | |
/// or decode operation that failed. | |
/// @param[in] __handled_errors Whether or not an error was handled. Some error handlers are corrective (see | |
/// ztd::text::replacement_handler), and so the error code is not enough to determine if the handler was | |
/// invoked. This allows the value to be provided directly when constructing this result type. | |
////// | |
template <typename _ArgInput> | |
constexpr stateless_count_result( | |
_ArgInput&& __input, ::std::size_t __count, encoding_error __error_code, ::std::size_t __handled_errors) | |
: input(::std::forward<_ArgInput>(__input)) | |
, count(__count) | |
, error_code(__error_code) | |
, handled_errors(__handled_errors) { | |
} | |
////// | |
/// @brief Whether or not any errors were handled. | |
/// | |
/// @returns Simply checks whether @c handled_errors is greater than 0. | |
////// | |
constexpr bool errors_were_handled() const noexcept { | |
return this->handled_errors > 0; | |
} | |
}; | |
////// | |
/// @brief The result of counting operations (such as ztd_text_count_encodable and | |
/// ztd_text_count_encodable). | |
////// | |
template <typename _Input, typename _State> | |
class count_result : public stateless_count_result<_Input> { | |
private: | |
using __base_t = stateless_count_result<_Input>; | |
public: | |
////// | |
/// @brief A reference to the state of the associated Encoding used for counting. | |
////// | |
::ztd::text::reference_wrapper<_State> state; | |
////// | |
/// @brief Constructs a ztd::text::count_result, defaulting the error code to | |
/// ztd::text::encoding_error::ok if not provided. | |
/// | |
/// @param[in] __input The input range to store. | |
/// @param[in] __count The number of code points or code units successfully counted. | |
/// @param[in] __state The state related to the encoding for the counting operation. | |
/// @param[in] __error_code The error code for the encode operation, taken as the first of either the encode | |
/// or decode operation that failed. | |
////// | |
template <typename _ArgInput, typename _ArgState> | |
constexpr count_result(_ArgInput&& __input, ::std::size_t __count, _ArgState&& __state, | |
encoding_error __error_code = encoding_error::ok) | |
: count_result(::std::forward<_ArgInput>(__input), __count, ::std::forward<_ArgState>(__state), __error_code, | |
__error_code != encoding_error::ok ? static_cast<::std::size_t>(1) : static_cast<::std::size_t>(0)) { | |
} | |
////// | |
/// @brief Constructs a ztd::text::count_result with the provided parameters and information, | |
/// including whether or not an error was handled. | |
/// | |
/// @param[in] __input The input range to store. | |
/// @param[in] __count The number of code points or code units successfully counted. | |
/// @param[in] __state The state related to the encode operation that counted the code units. | |
/// @param[in] __error_code The error code for the encode operation, taken as the first of either the encode | |
/// or decode operation that failed. | |
/// @param[in] __handled_errors Whether or not an error was handled. Some error handlers are corrective (see | |
/// ztd::text::replacement_handler), and so the error code is not enough to determine if the handler was | |
/// invoked. This allows the value to be provided directly when constructing this result type. | |
////// | |
template <typename _ArgInput, typename _ArgState> | |
constexpr count_result(_ArgInput&& __input, ::std::size_t __count, _ArgState&& __state, | |
encoding_error __error_code, ::std::size_t __handled_errors) | |
: __base_t(::std::forward<_ArgInput>(__input), __count, __error_code, __handled_errors) | |
, state(::std::forward<_ArgState>(__state)) { | |
} | |
}; | |
////// | |
/// @brief The result of counting operations (such as ztd_text_count_encodable and | |
/// ztd_text_count_encodable). | |
////// | |
template <typename _Input, typename _FromState, typename _ToState> | |
class count_transcode_result : public stateless_count_result<_Input> { | |
private: | |
using __base_t = stateless_count_result<_Input>; | |
public: | |
////// | |
/// @brief A reference to the state of the associated Encoding used for counting which covers the decoding | |
/// portion of the transcode operation. | |
////// | |
::ztd::text::reference_wrapper<_FromState> from_state; | |
////// | |
/// @brief A reference to the state of the associated Encoding used for counting which covers the encoding | |
/// portion of the transcode operation. | |
////// | |
::ztd::text::reference_wrapper<_ToState> to_state; | |
////// | |
/// @brief Constructs a ztd::text::count_result, defaulting the error code to | |
/// ztd::text::encoding_error::ok if not provided. | |
/// | |
/// @param[in] __input The input range to store. | |
/// @param[in] __count The number of code points or code units successfully counted. | |
/// @param[in] __from_state The state related to the encoding for the decode portion of the transcode counting | |
/// operation. | |
/// @param[in] __to_state The state related to the encoding for the encode portion of the transcode counting | |
/// operation. | |
/// @param[in] __error_code The error code for the encode operation, taken as the first of either the encode | |
/// or decode operation that failed. | |
////// | |
template <typename _ArgInput, typename _ArgFromState, typename _ArgToState> | |
constexpr count_transcode_result(_ArgInput&& __input, ::std::size_t __count, _ArgFromState&& __from_state, | |
_ArgToState&& __to_state, encoding_error __error_code = encoding_error::ok) | |
: count_transcode_result(::std::forward<_ArgInput>(__input), __count, | |
::std::forward<_ArgFromState>(__from_state), ::std::forward<_ArgToState>(__to_state), __error_code, | |
__error_code != encoding_error::ok ? static_cast<::std::size_t>(1) : static_cast<::std::size_t>(0)) { | |
} | |
////// | |
/// @brief Constructs a ztd::text::count_result with the provided parameters and information, | |
/// including whether or not an error was handled. | |
/// | |
/// @param[in] __input The input range to store. | |
/// @param[in] __count The number of code points or code units successfully counted. | |
/// @param[in] __from_state The state related to the encoding for the decode portion of the transcode counting | |
/// operation. | |
/// @param[in] __to_state The state related to the encoding for the encode portion of the transcode counting | |
/// operation. | |
/// @param[in] __error_code The error code for the encode operation, taken as the first of either the encode | |
/// or decode operation that failed. | |
/// @param[in] __handled_errors Whether or not an error was handled. Some error handlers are corrective (see | |
/// ztd::text::replacement_handler), and so the error code is not enough to determine if the handler was | |
/// invoked. This allows the value to be provided directly when constructing this result type. | |
////// | |
template <typename _ArgInput, typename _ArgFromState, typename _ArgToState> | |
constexpr count_transcode_result(_ArgInput&& __input, ::std::size_t __count, _ArgFromState&& __from_state, | |
_ArgToState&& __to_state, encoding_error __error_code, ::std::size_t __handled_errors) | |
: __base_t(::std::forward<_ArgInput>(__input), __count, __error_code, __handled_errors) | |
, from_state(::std::forward<_ArgFromState>(__from_state)) | |
, to_state(::std::forward<_ArgToState>(__to_state)) { | |
} | |
}; | |
////// | |
/// @} | |
////// | |
namespace __txt_detail { | |
template <typename _Input, typename _State> | |
constexpr stateless_count_result<_Input> __slice_to_stateless(count_result<_Input, _State>&& __result) { | |
return __result; | |
} | |
template <typename _Input, typename _FromState, typename _ToState> | |
constexpr stateless_count_result<_Input> __slice_to_stateless( | |
count_transcode_result<_Input, _FromState, _ToState>&& __result) { | |
return __result; | |
} | |
template <typename _InputRange, typename _State> | |
using __reconstruct_count_result_t = count_result<__reconstruct_t<_InputRange>, _State>; | |
template <typename _InputRange, typename _State, typename _InFirst, typename _InLast, typename _ArgState> | |
constexpr decltype(auto) __reconstruct_stateless_count_result(_InFirst&& __in_first, _InLast&& __in_last, | |
::std::size_t __count, _ArgState&& __state, encoding_error __error_code, | |
::std::size_t __handled_errors) { | |
decltype(auto) __in_range = __reconstruct(::std::in_place_type<_InputRange>, | |
::std::forward<_InFirst>(__in_first), ::std::forward<_InLast>(__in_last)); | |
return count_result<_InputRange, _State>(::std::forward<decltype(__in_range)>(__in_range), __count, | |
::std::forward<_ArgState>(__state), __error_code, __handled_errors); | |
} | |
template <typename _InputRange, typename _State, typename _InFirst, typename _InLast, typename _ArgState> | |
constexpr decltype(auto) __reconstruct_stateless_count_result(_InFirst&& __in_first, _InLast&& __in_last, | |
::std::size_t __count, _ArgState&& __state, encoding_error __error_code = encoding_error::ok) { | |
return __reconstruct_stateless_count_result<_InputRange, _State>(::std::forward<_InFirst>(__in_first), | |
::std::forward<_InLast>(__in_last), __count, ::std::forward<_ArgState>(__state), __error_code); | |
} | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/count_result.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/unbounded.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/unreachable_sentinel.hpp | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_support Support Classes | |
/// @{ | |
////// | |
////// | |
/// @brief A sentinel that cannot compare equal to any other iterator and thus results in infinitely long ranges. | |
/// | |
////// | |
class unreachable_sentinel_t { | |
////// | |
/// @brief Equality comparison. Always false. | |
/// | |
////// | |
template <typename _Left> | |
friend constexpr bool operator==(const _Left&, const unreachable_sentinel_t&) { | |
return false; | |
} | |
////// | |
/// @brief Equality comparison. Always false. | |
/// | |
////// | |
template <typename _Right> | |
friend constexpr bool operator==(const unreachable_sentinel_t&, const _Right&) { | |
return false; | |
} | |
////// | |
/// @brief Inequality comparison. Always true. | |
/// | |
////// | |
template <typename _Left> | |
friend constexpr bool operator!=(const _Left&, const unreachable_sentinel_t&) { | |
return true; | |
} | |
////// | |
/// @brief Inequality comparison. Always true. | |
/// | |
////// | |
template <typename _Right> | |
friend constexpr bool operator!=(const unreachable_sentinel_t&, const _Right&) { | |
return true; | |
} | |
}; | |
////// | |
/// @brief An available and usable ztd::text::unreachable_sentinel_t for ease of use. | |
/// | |
////// | |
inline constexpr unreachable_sentinel_t unreachable_sentinel = {}; | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/unreachable_sentinel.hpp | |
#include <iterator> | |
#include <utility> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_support Support Classes | |
/// @{ | |
////// | |
////// | |
/// @brief A class whose iterator and sentinel denote an infinity-range that, if iterated with a traditional for | |
/// range loop, will never cease. | |
////// | |
template <typename _It> | |
class unbounded_view { | |
private: | |
_It _M_it; | |
public: | |
////// | |
/// @brief The iterator type. | |
/// | |
////// | |
using iterator = _It; | |
////// | |
/// @brief The iterator type that can iterate indefinitely (or some approximation thereof). | |
/// | |
////// | |
using const_iterator = iterator; | |
////// | |
/// @brief The sentinel type, an infinity type that compares equal to nothing. | |
/// | |
////// | |
using sentinel = unreachable_sentinel_t; | |
////// | |
/// @brief The const sentinel type. | |
/// | |
/// @remarks It's just the sentinal type. | |
////// | |
using const_sentinel = sentinel; | |
////// | |
/// @brief The pointer type related to the iterator. | |
/// | |
////// | |
using pointer = __txt_detail::__iterator_pointer_t<iterator>; | |
////// | |
/// @brief The const pointer type related to the iterator. | |
/// | |
/// @remarks It's just the pointer type. | |
////// | |
using const_pointer = pointer; | |
////// | |
/// @brief The reference type for this range. | |
/// | |
////// | |
using reference = __txt_detail::__iterator_reference_t<iterator>; | |
////// | |
/// @brief The const reference type for this range. | |
/// | |
/// @remarks It's just the reference type. | |
////// | |
using const_reference = reference; | |
////// | |
/// @brief The value type for this range. | |
/// | |
////// | |
using value_type = __txt_detail::__iterator_value_type_t<iterator>; | |
////// | |
/// @brief The difference type that results from iterator subtraction (not practical for this range). | |
/// | |
////// | |
using difference_type = __txt_detail::__iterator_difference_type_t<iterator>; | |
////// | |
/// @brief The iterator concept - no matter what, this is a forward range at best. | |
/// | |
////// | |
using iterator_concept = ::std::conditional_t< | |
__txt_detail::__is_iterator_concept_or_better_v<::std::forward_iterator_tag, iterator>, | |
::std::forward_iterator_tag, __txt_detail::__iterator_concept_t<iterator>>; | |
////// | |
/// @brief Constructs a default-constructed iterator and an infinity sentinel as the range. | |
/// | |
/// @remarks Not very useful for anything other than generic programming shenanigans. | |
////// | |
constexpr unbounded_view() noexcept = default; | |
////// | |
/// @brief Constructs an unbounded_view using the specified iterator value iterator and an infinity sentinel. | |
/// | |
////// | |
constexpr unbounded_view(iterator __it) noexcept : _M_it(::std::move(__it)) { | |
} | |
////// | |
/// @brief The iterator the unbounded_view was constructed with. | |
/// | |
/// @remarks This function copies the contained iterator. | |
////// | |
constexpr iterator begin() & noexcept { | |
if constexpr (::std::is_copy_constructible_v<iterator>) { | |
return this->_M_it; | |
} | |
else { | |
return ::std::move(this->_M_it); | |
} | |
} | |
////// | |
/// @brief The iterator the unbounded_view was constructed with. | |
/// | |
/// @remarks This function copies the contained iterator. | |
////// | |
constexpr iterator begin() const& noexcept { | |
return this->_M_it; | |
} | |
////// | |
/// @brief The iterator the unbounded_view was constructed with. | |
/// | |
/// @remarks This function moves the contained iterator out. | |
////// | |
constexpr iterator begin() && noexcept { | |
return ::std::move(this->_M_it); | |
} | |
////// | |
/// @brief The ending sentinel. | |
/// | |
/// @remarks The sentinel is an infinity sentinel that never compares equal to any other thing: in short, any | |
/// range composed of [iterator, unreachable_sentinel) will never cease. | |
////// | |
constexpr sentinel end() const noexcept { | |
return sentinel {}; | |
} | |
////// | |
/// @brief The reconstruct extension point for re-creating this type from its iterator and sentinel. | |
/// | |
/// | |
////// | |
constexpr friend unbounded_view reconstruct(::std::in_place_type_t<unbounded_view>, iterator __iterator, | |
sentinel) noexcept(::std::is_nothrow_move_constructible_v<iterator>) { | |
return unbounded_view<_It>(::std::move(__iterator)); | |
} | |
////// | |
/// @brief Checks whether this ztd::texT::unbounded_view is empty. | |
/// | |
/// @remarks This can prevent needing to call @c begin() which may be beneficial for move-only iterators. This | |
/// is always false for a ztd::text::unbounded_view. | |
////// | |
constexpr bool empty() const noexcept { | |
return false; | |
} | |
////// | |
/// @brief Produces a copy of the unbounded_view and advances the @c begin() iterator by 1. | |
/// | |
/// @remarks This function call only works if the underlying iterator and sentinal types are copyable. | |
////// | |
[[nodiscard]] constexpr unbounded_view next() const& noexcept( | |
::std::is_nothrow_copy_constructible_v<iterator>&& noexcept(__txt_detail::__advance(this->_M_it))) { | |
auto __it = this->_M_it; | |
__txt_detail::__advance(__it); | |
return unbounded_view(::std::move(__it)); | |
} | |
////// | |
/// @brief Produces a copy of the unbounded_view and advances the @c begin() iterator by 1. | |
/// | |
/// @remarks This function call can be more efficient and allows working with move-only iterators. This | |
/// function call will move the iterators underlying this object. | |
////// | |
[[nodiscard]] constexpr unbounded_view next() && noexcept( | |
::std::is_nothrow_move_constructible_v<iterator>&& noexcept(__txt_detail::__advance(this->_M_it))) { | |
iterator __it = ::std::move(this->_M_it); | |
__txt_detail::__advance(__it); | |
return unbounded_view(::std::move(__it)); | |
} | |
////// | |
/// @brief Produces a copy of the unbounded_view and advances the @c begin() iterator by @p __diff. | |
/// | |
/// @param[in] __diff The amount to move this iterator by. Can be positive or negative. | |
/// | |
/// @remarks This function call only works if the underlying iterator and sentinal types are copyable. | |
////// | |
[[nodiscard]] constexpr unbounded_view next(difference_type __diff) const& noexcept( | |
::std::is_nothrow_copy_constructible_v<iterator>&& noexcept( | |
__txt_detail::__advance(this->_M_it, __diff))) { | |
auto __it = this->_M_it; | |
__txt_detail::__advance(__it, __diff); | |
return unbounded_view(::std::move(__it)); | |
} | |
////// | |
/// @brief Produces a copy of the unbounded_view and advances the @c begin() iterator by @p __diff. | |
/// | |
/// @param[in] __diff The amount to move this iterator by. Can be positive or negative. | |
/// | |
/// @remarks This function call can be more efficient and allows working with move-only iterators. This | |
/// function call will move the iterators underlying this object. | |
////// | |
[[nodiscard]] constexpr unbounded_view next(difference_type __diff) && noexcept( | |
::std::is_nothrow_move_constructible_v<iterator>&& noexcept( | |
__txt_detail::__advance(this->_M_it, __diff))) { | |
iterator __it = ::std::move(this->_M_it); | |
__txt_detail::__advance(__it, __diff); | |
return unbounded_view(::std::move(__it)); | |
} | |
////// | |
/// @brief Produces a copy of the unbounded_view and recedes the @c begin() iterator by @p __diff. | |
/// | |
/// @param[in] __diff The amount to move this iterator by. Can be positive or negative. | |
/// | |
/// @remarks This function call requires that the underlying iterator are bidirectional. | |
////// | |
[[nodiscard]] constexpr unbounded_view prev(difference_type __diff = 1) const | |
noexcept(::std::is_nothrow_copy_constructible_v<iterator>&& noexcept( | |
__txt_detail::__recede(this->_M_it, __diff))) { | |
auto __it = this->_M_it; | |
__recede(__it, __diff); | |
return unbounded_view(::std::move(__it)); | |
} | |
////// | |
/// @brief Advances the @c begin() iterator of this ztd::text::unbounded_view by @p __diff or just @c 1 if the | |
/// argument is not specified. | |
/// | |
/// @param[in] __diff The amount to move this iterator by. Can be positive or negative. | |
////// | |
constexpr unbounded_view& advance(difference_type __diff = 1) noexcept( | |
noexcept(__txt_detail::__advance(this->_M_it, __diff))) { | |
__txt_detail::__advance(this->_M_it, __diff); | |
return *this; | |
} | |
////// | |
/// @brief Recedes the @c begin() iterator of this ztd::text::unbounded_view by @p __diff or just @c 1 if the | |
/// argument is not specified. | |
/// | |
/// @param[in] __diff The amount to move this iterator by. Can be positive or negative. | |
/// | |
/// @remarks This function call requires that the underlying iterator are bidirectional. | |
////// | |
constexpr unbounded_view& recede(difference_type __diff = 1) noexcept( | |
noexcept(__txt_detail::__recede(this->_M_it, __diff))) { | |
__txt_detail::__recede(this->_M_it, __diff); | |
return *this; | |
} | |
}; | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_CONCEPTS_I_) && ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_RANGES_I_) | |
namespace std { namespace ranges { | |
template <typename _It> | |
inline constexpr bool enable_borrowed_range<::ztd::text::unbounded_view<_It>> = true; | |
}} // namespace std::ranges | |
#endif | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/unbounded.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/is_lossless.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/is_full_range_representable.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/is_transcoding_compatible.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/unicode_scalar_value.hpp | |
#include <string> | |
#include <utility> | |
#include <cstdint> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __impl { | |
////// | |
/// @brief A 32-bit value that is within the allowed 21 bits of Unicode and is not one of the Surrogate | |
/// values. | |
/// | |
/// @remarks The invariant is enforced with an assertion in normal modes, and can optionally be enforced by | |
/// turning on @c ZTD_TEXT_UNICODE_SCALAR_VALUE_INVARIANT_ABORT. | |
////// | |
class alignas(alignof(char32_t)) __unicode_scalar_value { | |
public: | |
////// | |
/// @brief Constructs a scalar value of indeterminate value (if no parentheses/brackets are provided) or | |
/// with the value 0 (if parentheses/brackets are provided for intentional value initialization). | |
/// | |
////// | |
__unicode_scalar_value() noexcept = default; | |
////// | |
/// @brief Constructs a scalar value with the given code point value. | |
/// | |
/// @remarks | |
////// | |
constexpr __unicode_scalar_value(char32_t __code_point) noexcept : _M_scalar(__code_point) { | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_UNICODE_SCALAR_VALUE_INVARIANT_ABORT_I_) | |
if (__txt_detail::__is_surrogate(this->_M_scalar) | |
|| (this->_M_scalar > __txt_detail::__last_code_point)) { | |
::std::abort(); | |
} | |
#else | |
ZTD_TEXT_ASSERT_MESSAGE_I_( | |
"The code point value must be a valid code point and must not be a surrogate value.", | |
!__txt_detail::__is_surrogate(this->_M_scalar) | |
&& (this->_M_scalar <= __txt_detail::__last_code_point)); | |
#endif | |
} | |
////// | |
/// @brief An explicit conversion to a typical char32_t value, bit-compatible with a normal code point | |
/// value. | |
/// | |
////// | |
constexpr explicit operator char32_t() const noexcept { | |
return this->_M_scalar; | |
} | |
////// | |
/// @brief Retrieves the underlying value. | |
/// | |
////// | |
constexpr const char32_t& value() const& noexcept { | |
return this->_M_scalar; | |
} | |
////// | |
/// @brief Retrieves the underlying value. | |
/// | |
////// | |
constexpr char32_t& value() & noexcept { | |
return this->_M_scalar; | |
} | |
////// | |
/// @brief Retrieves the underlying value. | |
/// | |
////// | |
constexpr char32_t&& value() && noexcept { | |
return ::std::move(this->_M_scalar); | |
} | |
private: | |
char32_t _M_scalar; | |
}; | |
////// | |
/// @brief Check if two unicode scalar values are equal. | |
/// | |
/// @param[in] __left Left hand value of equality operator. | |
/// @param[in] __right Right hand value of equality operator. | |
////// | |
constexpr bool operator==(const __unicode_scalar_value& __left, const __unicode_scalar_value& __right) { | |
return __left.value() == __right.value(); | |
} | |
////// | |
/// @brief Check if two unicode code points are not equal. | |
/// | |
/// @param[in] __left Left hand value of inequality operator. | |
/// @param[in] __right Right hand value of inequality operator. | |
////// | |
constexpr bool operator!=(const __unicode_scalar_value& __left, const __unicode_scalar_value& __right) { | |
return __left.value() != __right.value(); | |
} | |
////// | |
/// @brief Check if one unicode scalar value is less than the other. | |
/// | |
/// @param[in] __left Left hand value of less than operator. | |
/// @param[in] __right Right hand value of less than operator. | |
////// | |
constexpr bool operator<(const __unicode_scalar_value& __left, const __unicode_scalar_value& __right) { | |
return __left.value() < __right.value(); | |
} | |
} // namespace __impl | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_UNICODE_SCALAR_VALUE_DISTINCT_TYPE_I_) | |
using unicode_scalar_value = __impl::__unicode_scalar_value; | |
#else | |
using unicode_scalar_value = char32_t; | |
#endif | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
namespace std { | |
template <> | |
class char_traits<::ztd::text::__impl::__unicode_scalar_value> { | |
using char_type = ::ztd::text::__impl::__unicode_scalar_value; | |
using int_type = ::std::int_least32_t; | |
using pos_type = ::std::streampos; | |
using off_type = ::std::streamoff; | |
using state_type = ::std::mbstate_t; | |
static /*constexpr*/ char_type* copy( | |
char_type* __destination, const char_type* __source, ::std::size_t __count) noexcept { | |
// TODO: constexpr. right now illegal cast | |
return reinterpret_cast<char_type*>(::std::char_traits<char32_t>::copy( | |
reinterpret_cast<char32_t*>(__destination), reinterpret_cast<const char32_t*>(__source), __count)); | |
} | |
static /*constexpr*/ char_type* move( | |
char_type* __destination, const char_type* __source, ::std::size_t __count) noexcept { | |
// TODO: constexpr. right now illegal cast | |
return reinterpret_cast<char_type*>(::std::char_traits<char32_t>::move( | |
reinterpret_cast<char32_t*>(__destination), reinterpret_cast<const char32_t*>(__source), __count)); | |
} | |
ZTD_TEXT_NODISCARD_I_ static /*constexpr*/ int compare( | |
const char_type* __left, const char_type* __right, ::std::size_t __count) noexcept { | |
// TODO: constexpr. right now illegal cast | |
return ::std::char_traits<char32_t>::compare( | |
reinterpret_cast<const char32_t*>(__left), reinterpret_cast<const char32_t*>(__right), __count); | |
} | |
ZTD_TEXT_NODISCARD_I_ static constexpr size_t length(const char_type* __it) noexcept { | |
size_t __count = 0; | |
const char_type __null_value {}; | |
while (*__it != __null_value) { | |
++__count; | |
++__it; | |
} | |
return __count; | |
} | |
ZTD_TEXT_NODISCARD_I_ static constexpr const char_type* find( | |
const char_type* __it, size_t __count, const char_type& __c) noexcept { | |
for (; 0 < __count; --__count, (void)++__it) { | |
if (*__it == __c) { | |
return __it; | |
} | |
} | |
return nullptr; | |
} | |
static constexpr char_type* assign(char_type* __first, size_t __count, const char_type __c) noexcept { | |
for (char_type* __it = __first; __count > 0; --__count, (void)++__it) { | |
*__it = __c; | |
} | |
return __first; | |
} | |
static constexpr void assign(char_type& __left, const char_type& __right) noexcept { | |
__left = __right; | |
} | |
ZTD_TEXT_NODISCARD_I_ static constexpr bool eq(const char_type& __left, const char_type& __right) noexcept { | |
return __left == __right; | |
} | |
ZTD_TEXT_NODISCARD_I_ static constexpr bool lt(const char_type& __left, const char_type& __right) noexcept { | |
return __left < __right; | |
} | |
ZTD_TEXT_NODISCARD_I_ static constexpr char_type to_char_type(const int_type& __c_as_int) noexcept { | |
return char_type(static_cast<char32_t>(__c_as_int)); | |
} | |
ZTD_TEXT_NODISCARD_I_ static constexpr int_type to_int_type(const char_type& __c) noexcept { | |
return static_cast<int_type>(__c.value()); | |
} | |
ZTD_TEXT_NODISCARD_I_ static constexpr bool eq_int_type( | |
const int_type& __left, const int_type& __right) noexcept { | |
return __left == __right; | |
} | |
ZTD_TEXT_NODISCARD_I_ static constexpr int_type not_eof(const int_type& __c_as_int) noexcept { | |
return __c_as_int != eof() ? __c_as_int : !eof(); | |
} | |
ZTD_TEXT_NODISCARD_I_ static constexpr int_type eof() noexcept { | |
return static_cast<int_type>(EOF); | |
} | |
}; | |
} // namespace std | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/unicode_scalar_value.hpp | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
// clang-format off | |
template <typename _From, typename _To> | |
struct __is_bitwise_transcoding_compatible : ::std::integral_constant<bool, | |
::std::is_same_v<__remove_cvref_t<_To>, __remove_cvref_t<_From>> | |
// if the To is from ASCII, then it's bitwise-compatible with all UTF-8 implementations, | |
// provided those UTF-8 implementations have a sufficiently sized/aligned char that can be bit-copied. | |
|| (::std::is_same_v<__remove_cvref_t<_From>, ascii> | |
&& (::std::is_same_v<__remove_cvref_t<_To>, utf8> | |
|| ::std::is_base_of_v<__impl::__utf8_tag, __remove_cvref_t<_To>>) | |
&& ((sizeof(code_unit_t<__remove_cvref_t<_To>>) == sizeof(char)) | |
&& (alignof(code_unit_t<__remove_cvref_t<_To>>) == alignof(char))) | |
) | |
> { }; | |
// clang-format on | |
template <typename _From, typename _To> | |
inline constexpr bool __is_bitwise_transcoding_compatible_v | |
= __is_bitwise_transcoding_compatible<_From, _To>::value; | |
} // namespace __txt_detail | |
////// | |
/// @addtogroup ztd_text_properties Property and Trait Helpers | |
/// | |
/// @{ | |
///// | |
////// | |
/// @brief Checks whether or not the specified @p _From encoding can be transcoded to the @p _To encoding without | |
/// by form of bit copying. | |
/// | |
/// @tparam _From The encoding that is going to decode the input code units into the intermediate code points. | |
/// @tparam _To The encoding that is going to encode the intermediate code points into the final code units. | |
////// | |
template <typename _From, typename _To> | |
class is_bitwise_transcoding_compatible | |
: public ::std::integral_constant<bool, __txt_detail::__is_bitwise_transcoding_compatible_v<_From, _To>> { }; | |
////// | |
/// @brief A @c \::value alias for ztd::text::is_transcoding_compatible. | |
/// | |
////// | |
template <typename _From, typename _To> | |
constexpr bool is_bitwise_transcoding_compatible_v = is_bitwise_transcoding_compatible<_From, _To>::value; | |
namespace __txt_detail { | |
// clang-format off | |
template <typename _From, typename _To> | |
inline constexpr bool __is_transcoding_compatible_v | |
= is_bitwise_transcoding_compatible_v<_From,_To> | |
|| ::std::is_same_v<__txt_detail::__remove_cvref_t<_From>, __txt_detail::__remove_cvref_t<_To>> | |
|| ::std::is_same_v<code_point_t<_From>, code_point_t<_To>> | |
|| (is_unicode_scalar_value_v<code_point_t<_From>> | |
? (is_unicode_code_point_v<code_point_t<_To>>) | |
: (is_unicode_code_point_v<_From> && !is_unicode_scalar_value_v<_To>)); | |
// clang-format on | |
} // namespace __txt_detail | |
////// | |
/// @brief Checks whether or not the specified @p _From encoding can be transcoded to the @p _To encoding without | |
/// invoking a lossy conversion when using the intermediate code points. | |
/// | |
/// @tparam _From The encoding that is going to decode the input code units into the intermediate code points. | |
/// @tparam _To The encoding that is going to encode the intermediate code points into the final code units. | |
/// | |
/// @remarks First, it checks if the encodings are bitwise compatible with one another (e.g., transcoding ASCII to | |
/// UTF-8). If that is not the case, then it checks if the two encodings are just identical. Finally, it checks if | |
/// the code point types are the same or if it's putting unicode scalar values into unicode code points (which is | |
/// valid one way, but not the other way since scalar values do not allow surrogates). If none of these are true, | |
/// then, the intermediate code point likely cannot convert between the two losslessly. | |
////// | |
template <typename _From, typename _To> | |
class is_transcoding_compatible | |
: public ::std::integral_constant<bool, __txt_detail::__is_bitwise_transcoding_compatible_v<_From, _To>> { }; | |
////// | |
/// @brief A @c \::value alias for ztd::text::is_transcoding_compatible. | |
/// | |
////// | |
template <typename _From, typename _To> | |
constexpr bool is_transcoding_compatible_v = is_transcoding_compatible<_To, _From>::value; | |
////// | |
/// @} | |
///// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/is_transcoding_compatible.hpp | |
#include <type_traits> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _Type> | |
using __detect_is_encode_injective = decltype(_Type::is_encode_injective::value); | |
template <typename, typename = void> | |
struct __is_encode_injective_sfinae : ::std::false_type { }; | |
template <typename _Type> | |
struct __is_encode_injective_sfinae<_Type, | |
::std::enable_if_t<__is_detected_v<__detect_is_encode_injective, _Type>>> | |
: ::std::integral_constant<bool, _Type::is_encode_injective::value> { }; | |
template <typename _Type> | |
using __detect_is_decode_injective = decltype(_Type::is_decode_injective::value); | |
template <typename, typename = void> | |
struct __is_decode_injective_sfinae : ::std::false_type { }; | |
template <typename _Type> | |
struct __is_decode_injective_sfinae<_Type, | |
::std::enable_if_t<__is_detected_v<__detect_is_decode_injective, _Type>>> | |
: ::std::integral_constant<bool, _Type::is_decode_injective::value> { }; | |
} // namespace __txt_detail | |
////// | |
/// @addtogroup ztd_text_properties Property and Trait Helpers | |
/// | |
/// @{ | |
///// | |
////// | |
/// @brief Checks whether or not the decoding step for @p _Type is injective (cannot possibly lose information | |
/// regardless of whatever valid input is put in). | |
/// | |
/// @tparam _Type The encoding type to check. | |
/// | |
/// @remarks If the encoding object does not define is_decode_injective, it is assumed to be false (the safest | |
/// default). | |
////// | |
template <typename _Type> | |
class is_decode_injective : public __txt_detail::__is_decode_injective_sfinae<_Type> { }; | |
////// | |
/// @brief A @c \::value alias for ztd::text::is_decode_injective. | |
/// | |
////// | |
template <typename _Type> | |
inline constexpr bool is_decode_injective_v = is_decode_injective<_Type>::value; | |
////// | |
/// @brief Checks whether or not the encoding step for @p _Type is injective (cannot possibly lose information | |
/// regardless of whatever valid input is put in). | |
/// | |
/// @tparam _Type The encoding type to check. | |
/// | |
/// @remarks If the encoding object does not define is_encode_injective, it is assumed to be false (the safest | |
/// default). | |
////// | |
template <typename _Type> | |
class is_encode_injective : public __txt_detail::__is_encode_injective_sfinae<_Type> { }; | |
////// | |
/// @brief A @c \::value alias for ztd::text::is_encode_injective. | |
/// | |
////// | |
template <typename _Type> | |
inline constexpr bool is_encode_injective_v = is_encode_injective<_Type>::value; | |
////// | |
/// @brief Checks whether a decode operation with @p _From piped to a decode operation with @p _To is | |
/// | |
////// | |
template <typename _From, typename _To> | |
class is_full_range_representable_between | |
: public ::std::integral_constant<bool, | |
is_decode_injective_v< | |
__txt_detail::__remove_cvref_t<_From>> && is_encode_injective_v<__txt_detail::__remove_cvref_t<_To>>> { | |
}; | |
////// | |
/// @brief A @c \::value alias for ztd::text::is_full_range_representable_between. | |
/// | |
////// | |
template <typename _From, typename _To> | |
inline constexpr bool is_full_range_representable_bewtween_v | |
= is_full_range_representable_between<_From, _To>::value; | |
////// | |
/// @brief An alias for ztd::text::is_full_range_representable_between<_Type, _Type>. | |
/// | |
////// | |
template <typename _Type> | |
using is_full_range_representable = is_full_range_representable_between<_Type, _Type>; | |
////// | |
/// @brief A @c \::value alias for ztd::text::is_full_range_representable_between<_Type, _Type>. | |
/// | |
////// | |
template <typename _Type> | |
inline constexpr bool is_full_range_representable_v = is_full_range_representable<_Type>::value; | |
////// | |
/// @} | |
///// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/is_full_range_representable.hpp | |
#include <type_traits> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _ErrorHandler> | |
inline constexpr bool __is_careless_error_handler_v | |
= ::std::is_same_v<__txt_detail::__remove_cvref_t<_ErrorHandler>, default_handler>; | |
template <typename _Encoding, typename _ErrorHandler> | |
class __is_encode_lossless_or_deliberate | |
: public ::std::integral_constant<bool, | |
__txt_detail::__is_careless_error_handler_v<_ErrorHandler> ? is_encode_injective_v<_Encoding> : true> { | |
}; | |
template <typename _Encoding, typename _ErrorHandler> | |
inline constexpr bool __is_encode_lossless_or_deliberate_v | |
= __is_encode_lossless_or_deliberate<_Encoding, _ErrorHandler>::value; | |
template <typename _Encoding, typename _ErrorHandler> | |
class __is_decode_lossless_or_deliberate | |
: public ::std::integral_constant<bool, | |
__txt_detail::__is_careless_error_handler_v<_ErrorHandler> ? is_decode_injective_v<_Encoding> : true> { | |
}; | |
template <typename _Encoding, typename _ErrorHandler> | |
inline constexpr bool __is_decode_lossless_or_deliberate_v | |
= __is_decode_lossless_or_deliberate<_Encoding, _ErrorHandler>::value; | |
template <typename _FromEncoding, typename _ToEncoding, typename _FromErrorHandler, typename _ToErrorHandler> | |
class __is_transcode_lossless_or_deliberate | |
: public ::std::integral_constant<bool, | |
(__txt_detail::__is_careless_error_handler_v<_FromErrorHandler> ? is_decode_injective_v<_FromEncoding> | |
: true) | |
&& (__txt_detail::__is_careless_error_handler_v<_ToErrorHandler> | |
? is_encode_injective_v<_ToEncoding> | |
: true)> { }; | |
template <typename _FromEncoding, typename _ToEncoding, typename _FromErrorHandler, typename _ToErrorHandler> | |
inline constexpr bool __is_transcode_lossless_or_deliberate_v | |
= __is_transcode_lossless_or_deliberate<_FromEncoding, _ToEncoding, _FromErrorHandler, | |
_ToErrorHandler>::value; | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/is_lossless.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/blackhole_iterator.hpp | |
#include <tuple> | |
#include <iterator> | |
#include <cstddef> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
// A more aggressive form of std::ignore, | |
// this form includes a constructor which takes everything | |
// and does nothing, making it truly the devourer of all things. | |
struct __blackhole { | |
constexpr __blackhole() = default; | |
constexpr __blackhole(const __blackhole&) = default; | |
constexpr __blackhole(__blackhole&&) = default; | |
template <typename _Right, | |
::std::enable_if_t<!::std::is_same_v<__remove_cvref_t<_Right>, __blackhole>>* = nullptr> | |
constexpr __blackhole(_Right&&) noexcept { | |
} | |
constexpr __blackhole& operator=(const __blackhole&) = default; | |
constexpr __blackhole& operator=(__blackhole&&) = default; | |
template <typename _Right, | |
::std::enable_if_t<!::std::is_same_v<__remove_cvref_t<_Right>, __blackhole>>* = nullptr> | |
constexpr __blackhole& operator=(_Right&&) noexcept { | |
return *this; | |
} | |
}; | |
class __blackhole_iterator { | |
public: | |
using iterator_category = ::std::output_iterator_tag; | |
using difference_type = ::std::ptrdiff_t; | |
using pointer = __blackhole*; | |
using value_type = __blackhole; | |
using reference = __blackhole; | |
constexpr __blackhole_iterator operator++(int) const { | |
auto __copy = *this; | |
++__copy; | |
return __copy; | |
} | |
constexpr __blackhole_iterator& operator+=(difference_type) { | |
return *this; | |
} | |
constexpr __blackhole_iterator& operator-=(difference_type) { | |
return *this; | |
} | |
constexpr __blackhole_iterator operator+(difference_type) { | |
return *this; | |
} | |
constexpr __blackhole_iterator operator-(difference_type) { | |
return *this; | |
} | |
constexpr difference_type operator-(__blackhole_iterator) { | |
return 0; | |
} | |
constexpr __blackhole_iterator& operator++() { | |
return *this; | |
} | |
constexpr __blackhole_iterator operator--(int) const { | |
return *this; | |
} | |
constexpr __blackhole_iterator& operator--() { | |
return *this; | |
} | |
constexpr reference operator*() const { | |
return reference {}; | |
} | |
}; | |
}ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text::__txt_detail | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/blackhole_iterator.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/encoding_iterator_storage.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/math.hpp | |
#include <cstdint> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
constexpr uint_least64_t __ce_ipow_r(uint_least64_t base, uint_least64_t exp, uint_least64_t result) { | |
return exp < 1u ? result : __ce_ipow_r(base * base, exp / 2, (exp % 2) ? result * base : result); | |
} | |
constexpr uint_least64_t __ce_ipow(uint_least64_t base, uint_least64_t exp) { | |
return __ce_ipow_r(base, exp, 1); | |
} | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/math.hpp | |
#include <cstddef> | |
#include <climits> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
inline constexpr ::std::size_t _CursorlessSizeSentinel = 1; | |
template <typename _Encoding, typename _EncodingState, ::std::size_t _Id = 0> | |
class __state_storage : private __ebco<__remove_cvref_t<__unwrap_t<_EncodingState>>, _Id> { | |
private: | |
using _UEncoding = __remove_cvref_t<__unwrap_t<_Encoding>>; | |
using _UEncodingState = __remove_cvref_t<__unwrap_t<_EncodingState>>; | |
using __state_base_t = __ebco<__remove_cvref_t<__unwrap_t<_EncodingState>>, _Id>; | |
public: | |
template <typename _ArgEncoding = _UEncoding, | |
::std::enable_if_t< | |
!is_state_independent_v<__remove_cvref_t<_ArgEncoding>, | |
_UEncodingState> && !::std::is_same_v<__remove_cvref_t<_ArgEncoding>, __state_storage>>* = nullptr> | |
constexpr __state_storage(_ArgEncoding& __encoding) noexcept( | |
::std::is_nothrow_constructible_v<__state_base_t, _Encoding&>) | |
: __state_base_t(::std::forward<_ArgEncoding>(__encoding)) { | |
} | |
template <typename _ArgEncoding = _UEncoding, | |
::std::enable_if_t< | |
is_state_independent_v<__remove_cvref_t<_ArgEncoding>, | |
_UEncodingState> && !::std::is_same_v<__remove_cvref_t<_ArgEncoding>, __state_storage>>* = nullptr> | |
constexpr __state_storage(_ArgEncoding&) noexcept( | |
::std::is_nothrow_default_constructible_v<__state_base_t>) | |
: __state_base_t() { | |
} | |
constexpr __state_storage(_Encoding&, const _UEncodingState& __state) noexcept( | |
::std::is_nothrow_constructible_v<__state_base_t, const _UEncodingState&>) | |
: __state_base_t(__state) { | |
} | |
constexpr __state_storage(_Encoding&, _UEncodingState&& __state) noexcept( | |
::std::is_nothrow_constructible_v<__state_base_t, _UEncodingState&&>) | |
: __state_base_t(::std::move(__state)) { | |
} | |
constexpr __state_storage(const __state_storage&) = default; | |
constexpr __state_storage(__state_storage&&) = default; | |
constexpr __state_storage& operator=(const __state_storage&) = default; | |
constexpr __state_storage& operator=(__state_storage&&) = default; | |
constexpr ::std::add_lvalue_reference_t<_UEncodingState> _M_get_state() noexcept { | |
return this->__state_base_t::__get_value(); | |
} | |
constexpr ::std::add_const_t<::std::add_lvalue_reference_t<_UEncodingState>> | |
_M_get_state() const noexcept { | |
return this->__state_base_t::__get_value(); | |
} | |
}; | |
template <::std::size_t _MaxN, bool __is_input_or_output_iterator> | |
class __cursor_cache { | |
public: | |
// clang-format off | |
using _SizeType = ::std::conditional_t<(_MaxN <= UCHAR_MAX), unsigned char, | |
::std::conditional_t<(_MaxN <= USHRT_MAX), unsigned short, | |
::std::conditional_t<(_MaxN <= UINT_MAX), unsigned int, | |
::std::conditional_t<(_MaxN <= ULONG_MAX), unsigned long, | |
::std::conditional_t<(_MaxN <= ULLONG_MAX), unsigned long long, ::std::size_t> | |
> | |
> | |
> | |
>; | |
// clang-format on | |
_SizeType _M_size = static_cast<_SizeType>(0); | |
_SizeType _M_position = static_cast<_SizeType>(0); | |
}; | |
template <> | |
class __cursor_cache<1, true> { | |
public: | |
using _SizeType = unsigned char; | |
_SizeType _M_size = static_cast<_SizeType>(0); | |
}; | |
template <> | |
class __cursor_cache<1, false> { | |
public: | |
using _SizeType = unsigned char; | |
_SizeType _M_size = static_cast<_SizeType>(0); | |
}; | |
template <bool> | |
class __error_cache { | |
public: | |
encoding_error _M_error_code = encoding_error::ok; | |
}; | |
template <> | |
class __error_cache<true> { }; | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/encoding_iterator_storage.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/algorithm.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/counted_iterator.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/default_sentinel.hpp | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_RANGES_I_) | |
#include <ranges> | |
#endif | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_support Support Classes | |
/// @{ | |
////// | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_RANGES_I_) | |
////// | |
/// @brief A sentinel that cannot compare equal to any other iterator and thus results in infinitely long ranges. | |
/// | |
////// | |
using default_sentinel_t = ::std::default_sentinel_t; | |
#else | |
////// | |
/// @brief A sentinel that cannot compare equal to any other iterator and thus results in infinitely long ranges. | |
/// | |
////// | |
struct default_sentinel_t { }; | |
#endif | |
////// | |
/// @brief An available and usable ztd::text::default_sentinel for ease of use. | |
/// | |
////// | |
inline constexpr default_sentinel_t default_sentinel = {}; | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/default_sentinel.hpp | |
#include <iterator> | |
#include <utility> | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_RANGES_I_) | |
#include <ranges> | |
#endif | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_support Support Classes | |
/// @{ | |
////// | |
////// | |
/// @brief A sentinel for the counted_iterator to be paired with; lets a ztd::text::counted_iterator compare | |
/// against this type to test if it is at the end. | |
////// | |
using counted_sentinel_t = default_sentinel_t; | |
namespace __txt_detail { | |
template <typename _It> | |
class __counted_iterator { | |
private: | |
using _ItDiff = __txt_detail::__iterator_difference_type_t<_It>; | |
static constexpr bool _S_operator_plusplus_noexcept() noexcept { | |
return noexcept(++::std::declval<_It&>())&& noexcept(--::std::declval<_ItDiff&>()); | |
} | |
static constexpr bool _S_operator_minusminus_noexcept() noexcept { | |
return noexcept(--::std::declval<_It&>())&& noexcept(++::std::declval<_ItDiff&>()); | |
} | |
public: | |
using iterator_type = _It; | |
using difference_type = _ItDiff; | |
constexpr __counted_iterator() = default; | |
constexpr __counted_iterator(_It __it, _ItDiff __count) noexcept( | |
::std::is_nothrow_move_constructible_v<iterator_type>) | |
: _M_it(::std::move(__it)), _M_count(::std::move(__count)) { | |
} | |
template <typename _It2, ::std::enable_if_t<::std::is_convertible_v<_It2, iterator_type>>* = nullptr> | |
constexpr __counted_iterator(const __counted_iterator<_It2>& __from) noexcept( | |
::std::is_nothrow_convertible_v<const _It2&, iterator_type>) | |
: _M_count(__from._M_count), _M_it(__from._M_it) { | |
} | |
template <typename _It2, ::std::enable_if_t<::std::is_convertible_v<_It2, iterator_type>>* = nullptr> | |
constexpr __counted_iterator(__counted_iterator<_It2>&& __from) noexcept( | |
::std::is_nothrow_convertible_v<_It2&&, iterator_type>) | |
: _M_count(::std::move(__from._M_count)), _M_it(::std::move(__from._M_it)) { | |
} | |
template <typename _It2, ::std::enable_if_t<::std::is_assignable_v<_It2, iterator_type>>* = nullptr> | |
constexpr __counted_iterator& operator=(const __counted_iterator<_It2>& __right) noexcept( | |
::std::is_nothrow_assignable_v<const _It2&, iterator_type>) { | |
this->_M_count = __right._M_count; | |
this->_M_it = __right._M_it; | |
return *this; | |
} | |
template <typename _It2, ::std::enable_if_t<::std::is_assignable_v<_It2, iterator_type>>* = nullptr> | |
constexpr __counted_iterator& operator=(__counted_iterator<_It2>&& __right) noexcept( | |
::std::is_nothrow_assignable_v<_It2&&, iterator_type>) { | |
this->_M_count = ::std::move(__right._M_count); | |
this->_M_it = ::std::move(__right._M_it); | |
return *this; | |
} | |
constexpr _It base() const& noexcept(::std::is_nothrow_copy_constructible_v<_It>) { | |
return this->_M_it; | |
} | |
constexpr _It base() & noexcept(::std::is_nothrow_copy_constructible_v<_It>) { | |
return this->_M_it; | |
} | |
constexpr _It&& base() && noexcept { | |
return ::std::move(this->_M_it); | |
} | |
constexpr _ItDiff count() const noexcept { | |
return this->_M_count; | |
} | |
constexpr decltype(auto) operator*() noexcept(noexcept(*this->_M_it)) { | |
return *this->_M_it; | |
} | |
constexpr decltype(auto) operator*() const noexcept(noexcept(*this->_M_it)) { | |
return *this->_M_it; | |
} | |
constexpr __counted_iterator& operator++() noexcept(_S_operator_plusplus_noexcept()) { | |
++this->_M_it; | |
--this->_M_count; | |
return *this; | |
} | |
constexpr __counted_iterator operator++(int) noexcept(_S_operator_plusplus_noexcept()) { | |
++(*this); | |
return *this; | |
} | |
constexpr __counted_iterator& operator--() noexcept(_S_operator_minusminus_noexcept()) { | |
--this->_M_it; | |
++this->_M_count; | |
return *this; | |
} | |
constexpr __counted_iterator operator--(int) noexcept(_S_operator_minusminus_noexcept()) { | |
--(*this); | |
return *this; | |
} | |
#if 0 | |
constexpr __counted_iterator operator+(_ItDiff n) const requires random_access_iterator<_It>; | |
friend constexpr __counted_iterator operator+( | |
_ItDiff n, const __counted_iterator& x) requires random_access_iterator<_It>; | |
constexpr __counted_iterator& operator+=(_ItDiff n) requires random_access_iterator<_It>; | |
constexpr __counted_iterator operator-(_ItDiff n) const requires random_access_iterator<_It>; | |
template <typename _ItRight> | |
friend constexpr iter_difference_t<_ItRight> operator-(const __counted_iterator& x, const __counted_iterator<_ItRight>& y); | |
constexpr __counted_iterator& operator-=(_ItDiff n) requires random_access_iterator<_It>; | |
constexpr decltype(auto) operator[](_ItDiff n) const requires random_access_iterator<_It>; | |
#endif | |
friend constexpr _ItDiff operator-(const __counted_iterator& __left, default_sentinel_t) noexcept { | |
return __left._M_count; | |
} | |
friend constexpr _ItDiff operator-(default_sentinel_t, const __counted_iterator& __right) noexcept { | |
return -__right._M_count; | |
} | |
template <typename _ItRight> | |
friend constexpr bool operator==( | |
const __counted_iterator& __left, const __counted_iterator<_ItRight>& __right) noexcept { | |
return __left._M_it == __right._M_it && __left._M_count == __right._M_count; | |
} | |
friend constexpr bool operator==(const __counted_iterator& __left, default_sentinel_t) noexcept { | |
return __left._M_count == static_cast<_ItDiff>(0); | |
} | |
template <typename _ItRight> | |
friend constexpr bool operator!=( | |
const __counted_iterator& __left, const __counted_iterator<_ItRight>& __right) noexcept { | |
return __left._M_it != __right._M_it || __left._M_count != __right._M_count; | |
} | |
friend constexpr bool operator!=(const __counted_iterator& __left, default_sentinel_t) noexcept { | |
return __left._M_count != static_cast<_ItDiff>(0); | |
} | |
friend constexpr __txt_detail::__iterator_rvalue_reference_t<_It> | |
iter_move(const __counted_iterator& __it) noexcept( | |
noexcept(__txt_detail::__adl::__adl_iter_move(__it._M_it))) { | |
return __txt_detail::__adl::__adl_iter_move(__it._M_it); | |
} | |
template <typename _ItRight> | |
friend constexpr void | |
iter_swap(const __counted_iterator& x, const __counted_iterator<_ItRight>& y) noexcept( | |
noexcept(__txt_detail::__adl::__adl_iter_swap(x._M_it, y._M_it))) { | |
__txt_detail::__adl::__adl_iter_swap(x._M_it, y._M_it); | |
} | |
private: | |
_It _M_it = _It(); | |
_ItDiff _M_count = 0; | |
}; | |
} // namespace __txt_detail | |
////// | |
/// @brief A counted iterator that stores an iterator plus a count, which is used to iterator over the | |
/// specified count of elements. Useful for algorithms wherein the iterator is not random access but still | |
/// works on a given iterator and a size (e.g., the @c std::ranges::copy algorithm). | |
/// | |
/// @tparam _It The Iterator to wrap. The count is a @c difference_type that is associated with the Iterator. | |
/// (The | |
/// @c difference_type is usually a signed type such as the @c ptrdiff_t type.) | |
////// | |
template <typename _It> | |
using counted_iterator = | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_RANGES_I_) | |
::std::counted_iterator<_It>; | |
#else | |
__txt_detail::__counted_iterator<_It>; | |
#endif | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
namespace std { | |
template <typename _It> | |
struct iterator_traits<::ztd::text::__txt_detail::__counted_iterator<_It>> : iterator_traits<_It> { | |
using pointer = void; | |
}; | |
} // namespace std | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/counted_iterator.hpp | |
#include <algorithm> | |
#include <cstring> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_RANGES_I_) | |
template <typename _InItOrRange, typename _OutItOrRange> | |
using __in_out_result = ::std::ranges::in_out_result<_InItOrRange, _OutItOrRange>; | |
#else | |
template <typename _InItOrRange, typename _OutItOrRange> | |
struct __in_out_result { | |
_InItOrRange in; | |
_OutItOrRange out; | |
template <typename _ArgInIt, typename _ArgOutIt, | |
::std::enable_if_t<::std::is_convertible_v<const _InItOrRange&, | |
_ArgInIt>&& ::std::is_convertible_v<const _OutItOrRange&, _ArgOutIt>>* = nullptr> | |
constexpr operator __in_out_result<_ArgInIt, _ArgOutIt>() const& { | |
return { in, out }; | |
} | |
template <typename _ArgInIt, typename _ArgOutIt, | |
::std::enable_if_t<::std::is_convertible_v<_InItOrRange, | |
_ArgInIt>&& ::std::is_convertible_v<_OutItOrRange, _ArgOutIt>>* = nullptr> | |
constexpr operator __in_out_result<_ArgInIt, _ArgOutIt>() && { | |
return { ::std::move(in), ::std::move(out) }; | |
} | |
}; | |
#endif | |
template <typename _Iterator0, typename _Sentinel0, typename _Iterator1, typename _Sentinel1> | |
constexpr bool __equal(_Iterator0 __first0, _Sentinel0 __last0, _Iterator1 __first1, _Sentinel1 __last1) { | |
// std lib does not take differing sentinels, which is kind of shitty tbh | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_CONSTEXPR_ALGORITHMS_I_) && ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_RANGES_I_) | |
return ::std::ranges::equal( | |
::std::move(__first0), ::std::move(__last0), ::std::move(__first1), ::std::move(__last1)); | |
#else | |
if (__first0 == __last0) { | |
if (__first1 == __last1) { | |
return true; | |
} | |
return false; | |
} | |
for (; __first0 != __last0; (void)++__first0, ++__first1) { | |
if (__first1 == __last1) { | |
return false; | |
} | |
if (*__first0 != *__first1) { | |
return false; | |
} | |
} | |
return __first1 == __last1; | |
#endif | |
} | |
template <typename _Iterator0, typename _Iterator1> | |
constexpr _Iterator0 __reverse(_Iterator0 __first, _Iterator1 __last) noexcept { | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_CONSTEXPR_ALGORITHMS_I_) && ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_RANGES_I_) | |
return ::std::ranges::reverse(::std::move(__first), ::std::move(__last)); | |
#else | |
if (__first == __last) { | |
return __first; | |
} | |
--__last; | |
if (__first == __last) { | |
return __first; | |
} | |
// we have to start bringing them closer | |
for (;;) { | |
// we know these are different, so | |
// do a swap | |
__adl::__adl_iter_swap(__first, __last); | |
--__last; | |
if (__first == __last) { | |
break; | |
} | |
++__first; | |
if (__first == __last) { | |
break; | |
} | |
// otherwise, keep going | |
} | |
return __first; | |
#endif | |
} | |
template <typename _First, typename, typename _OutFirst> | |
constexpr bool __copy_unsafe_noexcept() noexcept { | |
return ::std::is_nothrow_assignable_v<__iterator_reference_t<_OutFirst>, __iterator_reference_t<_First>>; | |
} | |
template <typename _First, typename _Last, typename _OutFirst, typename _OutLast> | |
constexpr bool __copy_noexcept() noexcept { | |
if constexpr (__is_sized_sentinel_for_v<_OutFirst, _OutLast>) { | |
return __copy_unsafe_noexcept<_First, _Last, _OutFirst>() | |
&& ::std::is_nothrow_assignable_v<__iterator_reference_t<_OutFirst>, | |
__iterator_reference_t<_First>>; | |
} | |
else { | |
return ::std::is_nothrow_assignable_v<__iterator_reference_t<_OutFirst>, | |
__iterator_reference_t<_First>>; | |
} | |
} | |
template <typename _First, typename _FirstCount, typename _OutFirst> | |
constexpr auto __copy_n_unsafe(_First __first, _FirstCount __size, _OutFirst __out_first) noexcept( | |
__copy_unsafe_noexcept<_First, _FirstCount, _OutFirst>()) { | |
using _ResultInIt = counted_iterator<_First>; | |
using _InRange = subrange<_ResultInIt, default_sentinel_t>; | |
using _OutRange = unbounded_view<_OutFirst>; | |
using _Result = __in_out_result<_InRange, _OutRange>; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED_I_) | |
if (!::std::is_constant_evaluated()) | |
#else | |
if (false) | |
#endif | |
{ | |
using _ValueType = __iterator_value_type_t<_First>; | |
using _OutValueType = __iterator_value_type_t<_OutFirst>; | |
if constexpr ( | |
__is_iterator_contiguous_iterator_v< | |
_First> && __is_iterator_contiguous_iterator_v<_OutFirst> && ::std::has_unique_object_representations_v<_ValueType> && ::std::has_unique_object_representations_v<_OutValueType>) { | |
auto __first_ptr = __adl::__adl_to_address(__first); | |
auto __distance = __size; | |
::std::size_t __byte_distance = sizeof(_ValueType) * __distance; | |
::std::size_t __out_distance = __byte_distance / sizeof(_OutValueType); | |
::std::memcpy(__adl::__adl_to_address(__out_first), __first_ptr, __byte_distance); | |
return _Result { _InRange(_ResultInIt(::std::move(__first) + __distance, 0), default_sentinel), | |
_OutRange(::std::move(__out_first) + __out_distance) }; | |
} | |
} | |
_FirstCount __current_size = 0; | |
for (; __current_size < __size; ++__first, (void)++__out_first, (void)++__current_size) { | |
*__out_first = *__first; | |
} | |
return _Result { _InRange(_ResultInIt(::std::move(__first), 0), default_sentinel), | |
_OutRange(::std::move(__out_first)) }; | |
} | |
template <typename _First, typename _Last, typename _OutFirst> | |
constexpr auto __copy_unsafe(_First __first, _Last __last, _OutFirst __out_first) noexcept( | |
__copy_unsafe_noexcept<_First, _Last, _OutFirst>()) { | |
using _InRange = subrange<_First, _Last>; | |
using _OutRange = unbounded_view<_OutFirst>; | |
using _Result = __in_out_result<_InRange, _OutRange>; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED_I_) | |
if (!::std::is_constant_evaluated()) | |
#else | |
if (false) | |
#endif | |
{ | |
using _ValueType = __iterator_value_type_t<_First>; | |
using _OutValueType = __iterator_value_type_t<_OutFirst>; | |
if constexpr ( | |
__is_iterator_contiguous_iterator_v< | |
_First> && __is_iterator_contiguous_iterator_v<_OutFirst> && ::std::has_unique_object_representations_v<_ValueType> && ::std::has_unique_object_representations_v<_OutValueType>) { | |
auto __first_ptr = __adl::__adl_to_address(__first); | |
auto __distance = __last - __first; | |
::std::size_t __byte_distance = sizeof(_ValueType) * __distance; | |
::std::size_t __out_distance = __byte_distance / sizeof(_OutValueType); | |
::std::memcpy(__adl::__adl_to_address(__out_first), __first_ptr, __byte_distance); | |
return _Result { _InRange(::std::move(__first) + __distance, ::std::move(__last)), | |
_OutRange(::std::move(__out_first) + __out_distance) }; | |
} | |
} | |
for (; __first != __last; ++__first, (void)++__out_first) { | |
*__out_first = *__first; | |
} | |
return _Result { _InRange(::std::move(__first), ::std::move(__last)), | |
_OutRange(::std::move(__out_first)) }; | |
} | |
template <typename _First, typename _FirstCount, typename _OutFirst, typename _OutFirstCount> | |
constexpr auto __copy_n(_First __first, _FirstCount __size, _OutFirst __out_first, | |
_OutFirstCount __out_size) noexcept(__copy_noexcept<_First, _FirstCount, _OutFirst, _OutFirstCount>()) { | |
using _InRange = subrange<counted_iterator<_First>, default_sentinel_t>; | |
using _OutRange = subrange<counted_iterator<_OutFirst>, default_sentinel_t>; | |
using _Result = __in_out_result<_InRange, _OutRange>; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED_I_) | |
if (!::std::is_constant_evaluated()) | |
#else | |
if (false) | |
#endif | |
{ | |
if constexpr (__is_iterator_concept_or_better_v<::std::random_access_iterator_tag, _OutFirst>) { | |
if (__size <= __out_size) { | |
auto __result = __copy_n_unsafe(::std::move(__first), __size, ::std::move(__out_first)); | |
return _Result { ::std::move(__result.in), | |
_OutRange(__result.out.begin(), __result.out.begin() + __size) }; | |
} | |
else { | |
auto __result | |
= __copy_n_unsafe(::std::move(__first), __out_size, ::std::move(__out_first)); | |
__iterator_difference_type_t<_OutFirst> __out_size_left | |
= static_cast<__iterator_difference_type_t<_OutFirst>>(__size - __out_size); | |
return _Result { ::std::move(__result.in), | |
_OutRange( | |
{ ::std::move(__result.out).begin(), __out_size_left }, default_sentinel) }; | |
} | |
} | |
} | |
decltype(__size) __current_count = 0; | |
decltype(__out_size) __current_out_count = 0; | |
for (; __current_count < __size && __current_out_count != __out_size; | |
++__first, (void)++__out_first, (void)++__current_count, (void)++__current_out_count) { | |
*__out_first = *__first; | |
} | |
__iterator_difference_type_t<_First> __size_left | |
= static_cast<__iterator_difference_type_t<_First>>(__size - __current_count); | |
__iterator_difference_type_t<_OutFirst> __out_size_left | |
= static_cast<__iterator_difference_type_t<_OutFirst>>(__out_size - __current_out_count); | |
return _Result { _InRange({ ::std::move(__first), __size_left }, default_sentinel), | |
_OutRange({ ::std::move(__out_first), __out_size_left }, default_sentinel) }; | |
} | |
template <typename _First, typename _Last, typename _OutFirst, typename _OutLast> | |
constexpr auto __copy(_First __first, _Last __last, _OutFirst __out_first, _OutLast __out_last) noexcept( | |
__copy_noexcept<_First, _Last, _OutFirst, _OutLast>()) { | |
using _InRange = subrange<_First, _Last>; | |
using _OutRange = subrange<_OutFirst, _OutLast>; | |
using _Result = __in_out_result<_InRange, _OutRange>; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED_I_) | |
if (!::std::is_constant_evaluated()) | |
#else | |
if (false) | |
#endif | |
{ | |
if constexpr (__is_sized_sentinel_for_v<_OutFirst, _OutLast>) { | |
auto __out_size = __out_last - __out_first; | |
auto __size = __last - __first; | |
if (__size <= __out_size) { | |
auto __result | |
= __copy_unsafe(::std::move(__first), ::std::move(__last), ::std::move(__out_first)); | |
return _Result { ::std::move(__result.in), | |
_OutRange(::std::move(__result.out).begin(), ::std::move(__out_last)) }; | |
} | |
else { | |
auto __short_last = __first + __out_size; | |
auto __result = __copy_unsafe( | |
::std::move(__first), ::std::move(__short_last), ::std::move(__out_first)); | |
return _Result { ::std::move(__result.in), | |
_OutRange(::std::move(__result.out).begin(), ::std::move(__out_last)) }; | |
} | |
} | |
} | |
for (; __first != __last && __out_first != __out_last; ++__first, (void)++__out_first) { | |
*__out_first = *__first; | |
} | |
return _Result { _InRange(::std::move(__first), ::std::move(__last)), | |
_OutRange(::std::move(__out_first), ::std::move(__out_last)) }; | |
} | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/algorithm.hpp | |
#include <array> | |
#include <algorithm> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
enum class __consume : unsigned char { __no = 0, __embrace_the_void = 1 }; | |
enum class __transaction : unsigned char { __encode = 0, __decode = 1 }; | |
template <__consume _ConsumeIntoTheNothingness, typename _Encoding, typename _Input, typename _Output, | |
typename _ErrorHandler, typename _State> | |
constexpr auto __basic_decode_one(_Input&& __input, _Encoding&& __encoding, _Output&& __output, | |
_ErrorHandler& __error_handler, _State& __state) { | |
using _UOutput = __remove_cvref_t<_Output>; | |
using _UEncoding = __remove_cvref_t<_Encoding>; | |
if constexpr (_ConsumeIntoTheNothingness == __consume::__embrace_the_void | |
&& __is_decode_range_category_output_v<_UEncoding>) { | |
(void)__output; | |
using _Blackhole = unbounded_view<__blackhole_iterator>; | |
_Blackhole __output_range(__blackhole_iterator {}); | |
return __encoding.decode_one( | |
::std::forward<_Input>(__input), __output_range, __error_handler, __state); | |
} | |
else if ( | |
(!__is_range_contiguous_range_v<_UOutput> || __is_range_input_or_output_range_v<_UOutput>)&&__is_decode_range_category_contiguous_v< | |
_UEncoding>) { | |
code_point_t<_UEncoding> __intermediate_output_storage[max_code_points_v<_UEncoding>]; | |
::ztd::text::span<code_point_t<_UEncoding>, max_code_points_v<_UEncoding>> __intermediate_output( | |
__intermediate_output_storage); | |
auto __intermediate_result = __encoding.decode_one( | |
::std::forward<_Input>(__input), __intermediate_output, __error_handler, __state); | |
using _ReconstructedResult | |
= decode_result<decltype(__intermediate_result.input), __range_reconstruct_t<_Output>, _State>; | |
if (__intermediate_result.error_code != encoding_error::ok) { | |
auto __intermediate_last = __intermediate_result.output.data(); | |
auto __out_it = __adl::__adl_begin(::std::move(__output)); | |
auto __out_last = __adl::__adl_end(::std::move(__output)); | |
for (auto __intermediate_it = __intermediate_output.data(); | |
__intermediate_it != __intermediate_last;) { | |
*__out_it = *__intermediate_it; | |
++__intermediate_it; | |
++__out_it; | |
} | |
return _ReconstructedResult(::std::move(__intermediate_result.input), | |
__reconstruct(::std::in_place_type<_UOutput>, ::std::forward<_Output>(__output), | |
::std::move(__out_it), ::std::move(__out_last)), | |
__state, __intermediate_result.error_code, __intermediate_result.handled_errors); | |
} | |
return _ReconstructedResult(::std::move(__intermediate_result.input), | |
__reconstruct(::std::in_place_type<_UOutput>, ::std::forward<_Output>(__output)), __state, | |
__intermediate_result.error_code, __intermediate_result.handled_errors); | |
} | |
else if (false) { | |
// TODO: this branch SHOULD check for conditions conducive to unbounded_view... | |
} | |
else { | |
return __encoding.decode_one( | |
::std::forward<_Input>(__input), ::std::forward<_Output>(__output), __error_handler, __state); | |
} | |
} | |
template <__consume _ConsumeIntoTheNothingness, typename _Encoding, typename _Input, typename _Output, | |
typename _ErrorHandler, typename _State> | |
constexpr auto __basic_encode_one(_Input&& __input, _Encoding&& __encoding, _Output&& __output, | |
_ErrorHandler& __error_handler, _State& __state) { | |
using _UOutput = __remove_cvref_t<_Output>; | |
using _UEncoding = __remove_cvref_t<_Encoding>; | |
if constexpr (_ConsumeIntoTheNothingness == __consume::__embrace_the_void | |
&& __is_encode_range_category_output_v<_UEncoding>) { | |
(void)__output; | |
using _Blackhole = unbounded_view<__blackhole_iterator>; | |
_Blackhole __output_range(__blackhole_iterator {}); | |
return __encoding.encode_one( | |
::std::forward<_Input>(__input), __output_range, __error_handler, __state); | |
} | |
else if ( | |
(!__is_range_contiguous_range_v<_UOutput> || __is_range_input_or_output_range_v<_UOutput>)&&__is_encode_range_category_contiguous_v< | |
_UEncoding>) { | |
constexpr ::std::size_t _IntermediateMax = max_code_units_v<_UEncoding>; | |
code_unit_t<_UEncoding> __intermediate_output_storage[_IntermediateMax]; | |
::ztd::text::span<code_unit_t<_UEncoding>, _IntermediateMax> __intermediate_output( | |
__intermediate_output_storage); | |
auto __intermediate_result = __encoding.encode_one( | |
::std::forward<_Input>(__input), __intermediate_output, __error_handler, __state); | |
using _ReconstructedResult | |
= encode_result<decltype(__intermediate_result.input), __range_reconstruct_t<_Output>, _State>; | |
if (__intermediate_result.error_code != encoding_error::ok) { | |
auto __intermediate_last = __intermediate_result.output.data(); | |
auto __out_it = __adl::__adl_begin(::std::move(__output)); | |
auto __out_last = __adl::__adl_end(::std::move(__output)); | |
for (auto __intermediate_it = __intermediate_output.data(); | |
__intermediate_it != __intermediate_last;) { | |
*__out_it = *__intermediate_it; | |
++__intermediate_it; | |
++__out_it; | |
} | |
return _ReconstructedResult(::std::move(__intermediate_result.input), | |
__reconstruct(::std::in_place_type<_UOutput>, ::std::forward<_Output>(__output), | |
::std::move(__out_it), ::std::move(__out_last)), | |
__state, __intermediate_result.error_code, __intermediate_result.handled_errors); | |
} | |
return _ReconstructedResult(::std::move(__intermediate_result.input), | |
__reconstruct(::std::in_place_type<_UOutput>, ::std::forward<_Output>(__output)), __state, | |
__intermediate_result.error_code, __intermediate_result.handled_errors); | |
} | |
else if (false) { | |
// TODO: this branch SHOULD check for conditions conducive to unbounded_view... | |
} | |
else { | |
return __encoding.encode_one( | |
::std::forward<_Input>(__input), ::std::forward<_Output>(__output), __error_handler, __state); | |
} | |
} | |
template <__consume _ConsumeIntoTheNothingness, __transaction __encode_or_decode, typename _Encoding, | |
typename _Input, typename _OutputContainer, typename _ErrorHandler, typename _State> | |
constexpr auto __basic_encode_or_decode_one(_Input&& __input, _Encoding&& __encoding, | |
_OutputContainer& __output, _ErrorHandler& __error_handler, _State& __state) { | |
if constexpr (__encode_or_decode == __transaction::__decode) { | |
return __basic_decode_one<_ConsumeIntoTheNothingness>(::std::forward<_Input>(__input), | |
::std::forward<_Encoding>(__encoding), __output, __error_handler, __state); | |
} | |
else { | |
return __basic_encode_one<_ConsumeIntoTheNothingness>(::std::forward<_Input>(__input), | |
::std::forward<_Encoding>(__encoding), __output, __error_handler, __state); | |
} | |
} | |
template <__consume _ConsumeIntoTheNothingness, typename _Input, typename _FromEncoding, typename _Output, | |
typename _ToEncoding, typename _FromErrorHandler, typename _ToErrorHandler, typename _FromState, | |
typename _ToState, typename _Intermediate> | |
constexpr auto __super_basic_transcode_one(_Input&& __input, _FromEncoding& __from_encoding, | |
_Output&& __output, _ToEncoding& __to_encoding, _FromErrorHandler& __from_error_handler, | |
_ToErrorHandler& __to_error_handler, _FromState& __from_state, _ToState& __to_state, | |
_Intermediate& __intermediate) { | |
using _InitialIntermediate = __span_or_reconstruct_t<_Intermediate>; | |
using _DecodeResult | |
= decltype(__basic_decode_one<_ConsumeIntoTheNothingness>(::std::forward<_Input>(__input), | |
__from_encoding, ::std::declval<_InitialIntermediate>(), __from_error_handler, __from_state)); | |
using _InputView = decltype(::std::declval<_DecodeResult>().input); | |
using _WorkingIntermediate = decltype(::std::declval<_DecodeResult>().output); | |
using _OutputView | |
= decltype(__basic_encode_one<_ConsumeIntoTheNothingness>(::std::declval<_WorkingIntermediate>(), | |
__to_encoding, ::std::forward<_Output>(__output), __to_error_handler, __to_state) | |
.output); | |
using _Result = transcode_result<_InputView, _OutputView, _FromState, _ToState>; | |
static_assert(__txt_detail::__is_decode_lossless_or_deliberate_v<__remove_cvref_t<_FromEncoding>, | |
__remove_cvref_t<_FromErrorHandler>>, | |
"The decode (input) portion of this transcode is a lossy, non-injective operation. This means " | |
"you " | |
"may lose data that you did not intend to lose; specify an 'in_handler' error handler " | |
"parameter to " | |
"transcode[_to](in, in_encoding, out_encoding, in_handler, ...) or transcode_into(in, " | |
"in_encoding, " | |
"out, " | |
"out_encoding, in_handler, ...) explicitly in order to bypass this."); | |
static_assert(__txt_detail::__is_encode_lossless_or_deliberate_v<__remove_cvref_t<_ToEncoding>, | |
__remove_cvref_t<_ToErrorHandler>>, | |
"The encode (output) portion of this transcode is a lossy, non-injective operation. This " | |
"means you " | |
"may lose data that you did not intend to lose; specify an 'out_handler' error handler " | |
"parameter " | |
"to transcode[_to](in, in_encoding, out_encoding, in_handler, out_handler, ...) or " | |
"transcode_into(in, " | |
"in_encoding, out, out_encoding, in_handler, out_handler, ...) explicitly in order to bypass " | |
"this."); | |
// TODO: is_range_convertible_to_v<DecodeCodePoint, EncodeCodePoint> ? | |
// static_assert(::std::is_convertible_v<>, "The intermediary codepoint types are not trivially | |
// convertible to one another"); | |
_WorkingIntermediate __working_output = __span_or_reconstruct(__intermediate); | |
auto __intermediate_result = __basic_decode_one<__consume::__no>(::std::forward<_Input>(__input), | |
__from_encoding, __working_output, __from_error_handler, __from_state); | |
if (__intermediate_result.error_code != encoding_error::ok) { | |
#if 0 | |
if constexpr (::std::is_same_v<__range_iterator_t<_OutputView>, __blackhole_iterator>) { | |
return _Result(::std::move(__intermediate_result.input), _OutputView {}, | |
__intermediate_result.state, __to_state, __intermediate_result.error_code, | |
__intermediate_result.handled_errors); | |
} | |
else if constexpr (__is_specialization_of_v<_OutputView, unbounded_view>) { | |
return _Result(::std::move(__intermediate_result.input), | |
__reconstruct(::std::in_place_type<_OutputView>, __adl::__adl_begin(__output), | |
__range_sentinel_t<_OutputView> {}), | |
__intermediate_result.state, __to_state, __intermediate_result.error_code, | |
__intermediate_result.handled_errors); | |
} | |
else { | |
#endif | |
return _Result(::std::move(__intermediate_result.input), | |
__reconstruct(::std::in_place_type<_OutputView>, ::std::forward<_Output>(__output)), | |
__intermediate_result.state, __to_state, __intermediate_result.error_code, | |
__intermediate_result.handled_errors); | |
#if 0 | |
} | |
#endif | |
} | |
_WorkingIntermediate __working_input = __reconstruct(::std::in_place_type<_WorkingIntermediate>, | |
__adl::__adl_begin(__working_output), __adl::__adl_begin(__intermediate_result.output)); | |
auto __end_result = __basic_encode_one<_ConsumeIntoTheNothingness>(::std::move(__working_input), | |
__to_encoding, ::std::forward<_Output>(__output), __to_error_handler, __to_state); | |
return _Result(::std::move(__intermediate_result.input), ::std::move(__end_result.output), | |
__intermediate_result.state, __end_result.state, __end_result.error_code, | |
__intermediate_result.handled_errors + __end_result.handled_errors); | |
} | |
template <__consume _ConsumeIntoTheNothingness, typename _Input, typename _FromEncoding, typename _Output, | |
typename _ToEncoding, typename _FromErrorHandler, typename _ToErrorHandler, typename _FromState, | |
typename _ToState> | |
constexpr auto __super_basic_transcode_one(_Input&& __input, _FromEncoding& __from_encoding, | |
_Output&& __output, _ToEncoding& __to_encoding, _FromErrorHandler& __from_error_handler, | |
_ToErrorHandler& __to_error_handler, _FromState& __from_state, _ToState& __to_state) { | |
using _IntermediateCodePoint = code_point_t<_FromEncoding>; | |
constexpr ::std::size_t _IntermediateMaxCodePoints = max_code_points_v<_FromEncoding>; | |
_IntermediateCodePoint __intermediate_storage[_IntermediateMaxCodePoints] {}; | |
::ztd::text::span<_IntermediateCodePoint, _IntermediateMaxCodePoints> __intermediate( | |
__intermediate_storage); | |
return __super_basic_transcode_one<_ConsumeIntoTheNothingness>(::std::forward<_Input>(__input), | |
__from_encoding, ::std::forward<_Output>(__output), __to_encoding, __from_error_handler, | |
__to_error_handler, __from_state, __to_state, __intermediate); | |
} | |
template <__consume _ConsumeIntoTheNothingness, typename _Input, typename _FromEncoding, typename _Output, | |
typename _ToEncoding, typename _FromErrorHandler, typename _ToErrorHandler, typename _FromState, | |
typename _ToState, typename _Intermediate> | |
constexpr auto __basic_transcode_one(_Input&& __input, _FromEncoding& __from_encoding, _Output&& __output, | |
_ToEncoding& __to_encoding, _FromErrorHandler& __from_error_handler, _ToErrorHandler& __to_error_handler, | |
_FromState& __from_state, _ToState& __to_state, _Intermediate& __intermediate) { | |
using _UToEncoding = __remove_cvref_t<_ToEncoding>; | |
if constexpr (_ConsumeIntoTheNothingness == __consume::__embrace_the_void | |
&& __is_encode_range_category_output_v<_UToEncoding>) { | |
using _Blackhole = unbounded_view<__blackhole_iterator>; | |
if constexpr (__is_detected_v<__detect_adl_text_transcode_one, _Input, _FromEncoding, _Blackhole, | |
_ToEncoding, _FromErrorHandler, _ToErrorHandler, _FromState, _ToState>) { | |
(void)__intermediate; | |
_Blackhole __output_range(__blackhole_iterator {}); | |
return text_transcode_one( | |
tag<__remove_cvref_t<_FromEncoding>, __remove_cvref_t<_ToEncoding>> {}, | |
::std::forward<_Input>(__input), __from_encoding, ::std::move(__output_range), | |
__to_encoding, __from_error_handler, __to_error_handler, __from_state, __to_state); | |
} | |
else if constexpr (__is_detected_v<__detect_adl_internal_text_transcode_one, _Input, _FromEncoding, | |
_Blackhole, _ToEncoding, _FromErrorHandler, _ToErrorHandler, _FromState, | |
_ToState>) { | |
(void)__intermediate; | |
_Blackhole __output_range(__blackhole_iterator {}); | |
return __text_transcode_one( | |
tag<__remove_cvref_t<_FromEncoding>, __remove_cvref_t<_ToEncoding>> {}, | |
::std::forward<_Input>(__input), __from_encoding, ::std::move(__output_range), | |
__to_encoding, __from_error_handler, __to_error_handler, __from_state, __to_state); | |
} | |
else { | |
return __super_basic_transcode_one<_ConsumeIntoTheNothingness>(::std::forward<_Input>(__input), | |
__from_encoding, __intermediate, ::std::forward<_Output>(__output), __to_encoding, | |
__from_error_handler, __to_error_handler, __from_state, __to_state); | |
} | |
} | |
else { | |
if constexpr (__is_detected_v<__detect_adl_text_transcode_one, _Input, _FromEncoding, _Output, | |
_ToEncoding, _FromErrorHandler, _ToErrorHandler, _FromState, _ToState>) { | |
(void)__intermediate; | |
return text_transcode_one( | |
tag<__remove_cvref_t<_FromEncoding>, __remove_cvref_t<_ToEncoding>> {}, | |
::std::forward<_Input>(__input), __from_encoding, ::std::forward<_Output>(__output), | |
__to_encoding, __from_error_handler, __to_error_handler, __from_state, __to_state); | |
} | |
else if constexpr (__is_detected_v<__detect_adl_internal_text_transcode_one, _Input, _FromEncoding, | |
_Output, _ToEncoding, _FromErrorHandler, _ToErrorHandler, _FromState, | |
_ToState>) { | |
(void)__intermediate; | |
return __text_transcodeB_one( | |
tag<__remove_cvref_t<_FromEncoding>, __remove_cvref_t<_ToEncoding>> {}, | |
::std::forward<_Input>(__input), __from_encoding, ::std::forward<_Output>(__output), | |
__to_encoding, __from_error_handler, __to_error_handler, __from_state, __to_state); | |
} | |
else { | |
return __super_basic_transcode_one<_ConsumeIntoTheNothingness>(::std::forward<_Input>(__input), | |
__from_encoding, ::std::forward<_Output>(__output), __to_encoding, __from_error_handler, | |
__to_error_handler, __from_state, __to_state, __intermediate); | |
} | |
} | |
} | |
template <__consume _ConsumeIntoTheNothingness, typename _Input, typename _FromEncoding, typename _Output, | |
typename _ToEncoding, typename _FromErrorHandler, typename _ToErrorHandler, typename _FromState, | |
typename _ToState> | |
constexpr auto __basic_transcode_one(_Input&& __input, _FromEncoding& __from_encoding, _Output&& __output, | |
_ToEncoding& __to_encoding, _FromErrorHandler& __from_error_handler, _ToErrorHandler& __to_error_handler, | |
_FromState& __from_state, _ToState& __to_state) { | |
using _IntermediateCodePoint = code_point_t<_FromEncoding>; | |
constexpr ::std::size_t _IntermediateMaxCodePoints = max_code_points_v<_FromEncoding>; | |
_IntermediateCodePoint __intermediate_storage[_IntermediateMaxCodePoints] {}; | |
::ztd::text::span<_IntermediateCodePoint, _IntermediateMaxCodePoints> __intermediate( | |
__intermediate_storage); | |
return __basic_transcode_one<_ConsumeIntoTheNothingness>(::std::forward<_Input>(__input), | |
__from_encoding, ::std::forward<_Output>(__output), __to_encoding, __from_error_handler, | |
__to_error_handler, __from_state, __to_state, __intermediate); | |
} | |
template <typename _Input, typename _Encoding, typename _Output, typename _DecodeState, typename _EncodeState, | |
typename _Intermediate> | |
constexpr auto __basic_validate_decodable_as_one(_Input&& __input, _Encoding&& __encoding, _Output& __output, | |
_DecodeState& __decode_state, _EncodeState& __encode_state, _Intermediate& __intermediate) { | |
using _UInput = __remove_cvref_t<_Input>; | |
using _UOutput = __remove_cvref_t<_Output>; | |
using _InSubRange = subrange<__range_iterator_t<_UInput>, __range_sentinel_t<_UInput>>; | |
using _OutSubRange = subrange<__range_iterator_t<_UOutput>, __range_sentinel_t<_UOutput>>; | |
_InSubRange __working_input(::std::forward<_Input>(__input)); | |
_OutSubRange __working_output(__output); | |
__pass_through_handler __error_handler {}; | |
using _Result = validate_result<__range_reconstruct_t<_InSubRange, _UInput>, _DecodeState>; | |
auto __transcode_result | |
= __basic_transcode_one<__consume::__no>(__working_input, __encoding, __working_output, __encoding, | |
__error_handler, __error_handler, __decode_state, __encode_state, __intermediate); | |
if (__transcode_result.error_code != encoding_error::ok) { | |
return _Result(__reconstruct(::std::in_place_type<_UInput>, ::std::move(__transcode_result.input)), | |
false, __decode_state); | |
} | |
const bool __is_equal_transcode | |
= __equal(__adl::__adl_begin(__working_input), __adl::__adl_begin(__transcode_result.input), | |
__adl::__adl_begin(__working_output), __adl::__adl_begin(__transcode_result.output)); | |
if (!__is_equal_transcode) { | |
return _Result(__reconstruct(::std::in_place_type<_UInput>, ::std::move(__transcode_result.input)), | |
false, __decode_state); | |
} | |
return _Result(__reconstruct(::std::in_place_type<_UInput>, ::std::move(__transcode_result.input)), true, | |
__decode_state); | |
} | |
template <typename _Input, typename _Encoding, typename _DecodeState, typename _EncodeState> | |
constexpr auto __basic_validate_decodable_as_one( | |
_Input&& __input, _Encoding&& __encoding, _DecodeState& __decode_state, _EncodeState& __encode_state) { | |
using _UEncoding = __remove_cvref_t<_Encoding>; | |
using _CodeUnit = code_unit_t<_UEncoding>; | |
using _CodePoint = code_point_t<_UEncoding>; | |
_CodePoint __intermediate_storage[max_code_points_v<_UEncoding>] {}; | |
::ztd::text::span<_CodePoint, max_code_points_v<_UEncoding>> __intermediate(__intermediate_storage); | |
_CodeUnit __output_storage[max_code_units_v<_UEncoding>] {}; | |
::ztd::text::span<_CodeUnit, max_code_units_v<_UEncoding>> __output(__output_storage); | |
return __basic_validate_decodable_as_one(::std::forward<_Input>(__input), | |
::std::forward<_Encoding>(__encoding), __output, __decode_state, __encode_state, __intermediate); | |
} | |
template <typename _Input, typename _Encoding, typename _CodeUnitContainer, typename _EncodeState, | |
typename _DecodeState, typename _Intermediate> | |
constexpr auto __basic_validate_encodable_as_one(_Input&& __input, _Encoding&& __encoding, | |
_CodeUnitContainer& __output, _EncodeState& __encode_state, _DecodeState& __decode_state, | |
_Intermediate& __intermediate) { | |
using _UInput = __remove_cvref_t<_Input>; | |
using _UIntermediate = __remove_cvref_t<_Intermediate>; | |
using _InSubRange = subrange<__range_iterator_t<_UInput>, __range_sentinel_t<_UInput>>; | |
using _IntermediateSubRange | |
= subrange<__range_iterator_t<_UIntermediate>, __range_sentinel_t<_UIntermediate>>; | |
using _Result = validate_result<__range_reconstruct_t<_InSubRange, _UInput>, _EncodeState>; | |
__pass_through_handler __error_handler {}; | |
_InSubRange __working_input(::std::forward<_Input>(__input)); | |
auto __encode_result = __basic_encode_one<__consume::__no>( | |
__working_input, __encoding, __output, __error_handler, __encode_state); | |
if (__encode_result.error_code != encoding_error::ok) { | |
return _Result(__reconstruct(::std::in_place_type<_UInput>, ::std::move(__encode_result.input)), | |
false, __encode_state); | |
} | |
_IntermediateSubRange __working_intermediate(__intermediate); | |
auto __decode_result = __basic_decode_one<__consume::__no>( | |
__output, __encoding, __working_intermediate, __error_handler, __decode_state); | |
if (__decode_result.error_code != encoding_error::ok) { | |
return _Result(__reconstruct(::std::in_place_type<_UInput>, ::std::move(__encode_result.input)), | |
false, __encode_state); | |
} | |
const bool __is_equal_transcode | |
= __equal(__adl::__adl_begin(__working_input), __adl::__adl_begin(__encode_result.input), | |
__adl::__adl_begin(__working_intermediate), __adl::__adl_begin(__decode_result.output)); | |
if (!__is_equal_transcode) { | |
return _Result(__reconstruct(::std::in_place_type<_UInput>, ::std::move(__encode_result.input)), | |
false, __encode_state); | |
} | |
return _Result(__reconstruct(::std::in_place_type<_UInput>, ::std::move(__encode_result.input)), true, | |
__encode_state); | |
} | |
template <typename _Input, typename _Encoding, typename _EncodeState, typename _DecodeState> | |
constexpr auto __basic_validate_encodable_as_one( | |
_Input&& __input, _Encoding&& __encoding, _EncodeState& __encode_state, _DecodeState& __decode_state) { | |
using _UEncoding = __remove_cvref_t<_Encoding>; | |
using _CodePoint = code_point_t<_UEncoding>; | |
using _CodeUnit = code_unit_t<_UEncoding>; | |
_CodeUnit __output_storage[max_code_units_v<_UEncoding>] {}; | |
::ztd::text::span<_CodeUnit, max_code_units_v<_UEncoding>> __output(__output_storage); | |
_CodePoint __intermediate_storage[max_code_points_v<_UEncoding>] {}; | |
::ztd::text::span<_CodePoint, max_code_points_v<_UEncoding>> __intermediate(__intermediate_storage); | |
return __basic_validate_encodable_as_one(::std::forward<_Input>(__input), | |
::std::forward<_Encoding>(__encoding), __output, __encode_state, __decode_state, __intermediate); | |
} | |
template <typename _Input, typename _Encoding, typename _ErrorHandler, typename _State, | |
typename _Intermediate> | |
constexpr auto __basic_count_encodable_one(_Input&& __input, _Encoding&& __encoding, | |
_ErrorHandler&& __error_handler, _State& __state, _Intermediate& __intermediate) { | |
using _Result = count_result<__reconstruct_t<_Input>, _State>; | |
auto __intermediate_result = __basic_encode_one<__consume::__no>(::std::forward<_Input>(__input), | |
::std::forward<_Encoding>(__encoding), __intermediate, | |
::std::forward<_ErrorHandler>(__error_handler), __state); | |
::std::size_t __written = static_cast<::std::size_t>( | |
__adl::__adl_data(__intermediate_result.output) - __adl::__adl_data(__intermediate)); | |
return _Result(::std::move(__intermediate_result.input), __written, __intermediate_result.state, | |
__intermediate_result.error_code, __intermediate_result.handled_errors); | |
} | |
template <typename _Input, typename _Encoding, typename _ErrorHandler, typename _State> | |
constexpr auto __basic_count_encodable_one( | |
_Input&& __input, _Encoding&& __encoding, _ErrorHandler&& __error_handler, _State& __state) { | |
using _UEncoding = __remove_cvref_t<_Encoding>; | |
using _IntermediateCodeUnit = code_unit_t<_UEncoding>; | |
constexpr ::std::size_t _IntermediateMaxCodeUnits = max_code_units_v<_UEncoding>; | |
_IntermediateCodeUnit __intermediate_storage[_IntermediateMaxCodeUnits] {}; | |
::ztd::text::span<_IntermediateCodeUnit, _IntermediateMaxCodeUnits> __intermediate( | |
__intermediate_storage); | |
return __basic_count_encodable_one(::std::forward<_Input>(__input), | |
::std::forward<_Encoding>(__encoding), ::std::forward<_ErrorHandler>(__error_handler), __state, | |
__intermediate); | |
} | |
template <typename _Input, typename _Encoding, typename _ErrorHandler, typename _State, | |
typename _Intermediate> | |
constexpr auto __basic_count_decodable_one(_Input&& __input, _Encoding&& __encoding, | |
_ErrorHandler&& __error_handler, _State& __state, _Intermediate& __intermediate) { | |
using _Result = count_result<__reconstruct_t<_Input>, _State>; | |
auto __intermediate_result = __basic_decode_one<__consume::__no>(::std::forward<_Input>(__input), | |
::std::forward<_Encoding>(__encoding), __intermediate, | |
::std::forward<_ErrorHandler>(__error_handler), __state); | |
::std::size_t __written = static_cast<::std::size_t>( | |
__adl::__adl_data(__intermediate_result.output) - __adl::__adl_data(__intermediate)); | |
return _Result(::std::move(__intermediate_result.input), __written, __intermediate_result.state, | |
__intermediate_result.error_code, __intermediate_result.handled_errors); | |
} | |
template <typename _Input, typename _Encoding, typename _ErrorHandler, typename _State> | |
constexpr auto __basic_count_decodable_one( | |
_Input&& __input, _Encoding&& __encoding, _ErrorHandler&& __error_handler, _State& __state) { | |
using _UEncoding = __remove_cvref_t<_Encoding>; | |
using _IntermediateCodePoint = code_point_t<_UEncoding>; | |
constexpr ::std::size_t _IntermediateMaxCodePoints = max_code_points_v<_UEncoding>; | |
_IntermediateCodePoint __intermediate_storage[_IntermediateMaxCodePoints] {}; | |
::ztd::text::span<_IntermediateCodePoint, _IntermediateMaxCodePoints> __intermediate( | |
__intermediate_storage); | |
return __basic_count_decodable_one(::std::forward<_Input>(__input), | |
::std::forward<_Encoding>(__encoding), ::std::forward<_ErrorHandler>(__error_handler), __state, | |
__intermediate); | |
} | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/transcode_one.hpp | |
#include <climits> | |
#include <cstddef> | |
#include <exception> | |
#include <string_view> | |
#include <utility> | |
#include <array> | |
#include <system_error> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _Encoding, typename _Input, typename _Result> | |
constexpr _Result&& __write_direct(const _Encoding&, _Input&& __input, _Result&& __result) noexcept { | |
using _UOutputRange = __txt_detail::__remove_cvref_t<decltype(__result.output)>; | |
auto __outit = __txt_detail::__adl::__adl_begin(__result.output); | |
auto __outlast = __txt_detail::__adl::__adl_end(__result.output); | |
if (__outit == __outlast) { | |
// BAIL | |
return ::std::forward<_Result>(__result); | |
} | |
if (__txt_detail::__adl::__adl_empty(__input)) { | |
// empty range, everything is okay | |
__result.error_code = encoding_error::ok; | |
return ::std::forward<_Result>(__result); | |
} | |
for (const auto& __element : ::std::forward<_Input>(__input)) { | |
if (__outit == __outlast) { | |
__result.output = __txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::move(__outit), ::std::move(__outlast)); | |
return ::std::forward<_Result>(__result); | |
} | |
(*__outit) = __element; | |
++__outit; | |
} | |
__result.output = __txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::move(__outit), ::std::move(__outlast)); | |
__result.error_code = encoding_error::ok; | |
return ::std::forward<_Result>(__result); | |
} | |
template <typename _Encoding, typename _Result> | |
constexpr _Result&& __write_static_code_points_direct( | |
const _Encoding& __encoding, _Result&& __result) noexcept { | |
using _InputCodePoint = code_point_t<_Encoding>; | |
if constexpr (is_code_points_replaceable_v<_Encoding>) { | |
return __txt_detail::__write_direct( | |
__encoding, __encoding.replacement_code_points(), ::std::forward<_Result>(__result)); | |
} | |
else if constexpr (is_code_points_maybe_replaceable_v<_Encoding>) { | |
decltype(auto) __maybe_code_points = __encoding.maybe_replacement_code_points(); | |
if (__maybe_code_points) { | |
return __txt_detail::__write_direct(__encoding, | |
*::std::forward<decltype(__maybe_code_points)>(__maybe_code_points), | |
::std::forward<_Result>(__result)); | |
} | |
else { | |
return ::std::forward<_Result>(__result); | |
} | |
} | |
else if constexpr (is_unicode_code_point_v<_InputCodePoint>) { | |
constexpr _InputCodePoint __replacements[1] | |
= { static_cast<_InputCodePoint>(__txt_detail::__replacement) }; | |
return __txt_detail::__write_direct(__encoding, __replacements, ::std::forward<_Result>(__result)); | |
} | |
else { | |
static_assert(__txt_detail::__always_false_v<_Encoding>, | |
"There is no logical replacement code points to insert into the stream on failure for the " | |
"specified encoding type."); | |
} | |
} | |
template <typename _Encoding, typename _Result> | |
constexpr _Result&& __write_static_code_units_direct( | |
const _Encoding& __encoding, _Result&& __result) noexcept { | |
using _InputCodeUnit = code_unit_t<_Encoding>; | |
if constexpr (is_code_units_replaceable_v<_Encoding>) { | |
return __txt_detail::__write_direct( | |
__encoding, __encoding.replacement_code_units(), ::std::forward<_Result>(__result)); | |
} | |
else if constexpr (is_code_units_maybe_replaceable_v<_Encoding>) { | |
decltype(auto) __maybe_code_points = __encoding.maybe_replacement_code_units(); | |
if (__maybe_code_points) { | |
return __txt_detail::__write_direct(__encoding, | |
*::std::forward<decltype(__maybe_code_points)>(__maybe_code_points), | |
::std::forward<_Result>(__result)); | |
} | |
else { | |
return ::std::forward<_Result>(__result); | |
} | |
} | |
else if constexpr (sizeof(_InputCodeUnit) >= sizeof(char)) { | |
constexpr _InputCodeUnit __replacements[1] | |
= { static_cast<_InputCodeUnit>(__txt_detail::__ascii_replacement) }; | |
return __txt_detail::__write_direct(__encoding, __replacements, ::std::forward<_Result>(__result)); | |
} | |
else { | |
static_assert(__txt_detail::__always_false_v<_Encoding>, | |
"There is no logical replacement code units to insert into the stream on failure for the " | |
"specified encoding type."); | |
} | |
} | |
template <typename _Encoding> | |
constexpr ::std::size_t __fill_replacement_code_point_static(const _Encoding& __encoding, | |
code_point_t<_Encoding> (&__replacement_code_points)[max_code_points_v<_Encoding>]) { | |
using _InputCodePoint = code_point_t<_Encoding>; | |
if constexpr (is_code_points_replaceable_v<_Encoding>) { | |
::std::size_t __replacement_index = 0; | |
for (const auto& __element : __encoding.replacement_code_points()) { | |
__replacement_code_points[__replacement_index] = static_cast<_InputCodePoint>(__element); | |
++__replacement_index; | |
} | |
return __replacement_index; | |
} | |
else if constexpr (is_code_points_maybe_replaceable_v<_Encoding>) { | |
::std::size_t __replacement_index = 0; | |
decltype(auto) __maybe_code_points = __encoding.maybe_replacement_code_points(); | |
if (__maybe_code_points) { | |
decltype(auto) __code_points | |
= *::std::forward<decltype(__maybe_code_points)>(__maybe_code_points); | |
for (const auto& __element : __code_points) { | |
__replacement_code_points[__replacement_index] = static_cast<_InputCodePoint>(__element); | |
++__replacement_index; | |
} | |
} | |
return __replacement_index; | |
} | |
else if constexpr (is_unicode_code_point_v<_InputCodePoint>) { | |
__replacement_code_points[0] = static_cast<_InputCodePoint>(__replacement); | |
return 1; | |
} | |
else { | |
static_assert(__always_false_v<_Encoding>, | |
"There is no logical replacement code points to insert into the stream on failure for the " | |
"specified encoding type."); | |
} | |
} | |
template <typename _Encoding> | |
constexpr ::std::size_t __fill_replacement_code_unit_static(const _Encoding& __encoding, | |
code_unit_t<_Encoding> (&__replacement_code_units)[max_code_units_v<_Encoding>]) { | |
using _InputCodeUnit = code_unit_t<_Encoding>; | |
if constexpr (is_code_units_replaceable_v<_Encoding>) { | |
::std::size_t __replacement_index = 0; | |
for (const auto& __element : __encoding.replacement_code_units()) { | |
__replacement_code_units[__replacement_index] = static_cast<_InputCodeUnit>(__element); | |
++__replacement_index; | |
} | |
return __replacement_index; | |
} | |
else if constexpr (is_code_units_maybe_replaceable_v<_Encoding>) { | |
::std::size_t __replacement_index = 0; | |
decltype(auto) __maybe_code_units = __encoding.maybe_replacement_code_units(); | |
if (__maybe_code_units) { | |
decltype(auto) __code_units | |
= *::std::forward<decltype(__maybe_code_units)>(__maybe_code_units); | |
for (const auto& __element : __code_units) { | |
__replacement_code_units[__replacement_index] = static_cast<_InputCodeUnit>(__element); | |
++__replacement_index; | |
} | |
} | |
return __replacement_index; | |
} | |
else if constexpr (is_unicode_code_point_v<_InputCodeUnit>) { | |
__replacement_code_units[0] = static_cast<_InputCodeUnit>(__replacement); | |
return 1; | |
} | |
else if constexpr (sizeof(_InputCodeUnit) >= sizeof(char)) { | |
__replacement_code_units[0] = static_cast<_InputCodeUnit>(__ascii_replacement); | |
return 1; | |
} | |
else { | |
static_assert(__always_false_v<_Encoding>, | |
"There is no logical replacement code units to insert into the stream on failure for the " | |
"specified encoding type."); | |
} | |
} | |
} // namespace __txt_detail | |
////// | |
/// @brief An error handler that tells an encoding that it will pass through any errors, without doing any | |
/// adjustment, correction or checking. | |
/// | |
/// @remarks This error handler is useful in conjunction with a ztd::text::unbounded_view for the fastest possible | |
/// encoding and decoding in a general sense. However: IT IS ALSO EXTREMELY DANGEROUS AND CAN INVOKE UNDEFINED | |
/// BEHAVIOR IF YOUR TEXT IS, IN FACT, MESSED UP. PLEASE DO NOT USE THIS WITHOUT A GOOD REASON! | |
////// | |
class assume_valid_handler : public __txt_detail::__pass_through_handler_with<true> { }; | |
////// | |
/// @brief An error handler that tells an encoding that it will pass through any errors, without doing any | |
/// adjustment, correction or checking. Does not imply it is ignorable, unlike ztd::text::assume_valid_handler | |
/// which can invoke UB if an error occurs. | |
////// | |
class pass_handler : public __txt_detail::__pass_through_handler_with<false> { }; | |
////// | |
/// @brief An error handler that replaces bad code points and code units with a chosen code point / code unit | |
/// sequence. | |
/// | |
/// @remarks This class hooks into the encodings passed as the first parameter to the error handling functions to | |
/// see if they define either @c replacement_code_points() or @c replacement_code_units() function. If so, they | |
/// will call them and use the returned contiguous range to isnert code points or code units into the function. If | |
/// neither of these exist, then it checks for a definition of a @c maybe_replacement_code_points() or a @c | |
/// maybe_replacement_code_units() function. If either is present, they are expected to return a @c std::optional | |
/// of a contiguous range. If it is engaged (the @c std::optional is filled) it will be used. Otherwise, if it is | |
/// not engaged, then it will explicitly fall back to attempt to insert the default replacement character @c U+FFFD | |
/// (@c U'�') or <tt>?</tt> character. If the output is out of room for the desired object, then nothing will be | |
/// inserted at all. | |
////// | |
class replacement_handler { | |
public: | |
////// | |
/// @brief The function call for inserting replacement code units at the point of failure, before returning | |
/// flow back to the caller of the encode operation. | |
/// | |
/// | |
/// @param[in] __encoding The Encoding that experienced the error. | |
/// @param[in] __result The current state of the encode operation. | |
////// | |
template <typename _Encoding, typename _InputRange, typename _OutputRange, typename _State, | |
typename _Progress> | |
constexpr auto operator()(const _Encoding& __encoding, | |
encode_result<_InputRange, _OutputRange, _State> __result, const _Progress&) const noexcept { | |
if (__result.error_code == encoding_error::insufficient_output_space) { | |
// BAIL | |
return __result; | |
} | |
auto __outit = __txt_detail::__adl::__adl_begin(__result.output); | |
auto __outlast = __txt_detail::__adl::__adl_end(__result.output); | |
if (__outit == __outlast) { | |
// BAIL | |
return __result; | |
} | |
if constexpr (is_code_units_replaceable_v<_Encoding>) { | |
return __txt_detail::__write_direct( | |
__encoding, __encoding.replacement_code_units(), ::std::move(__result)); | |
} | |
else { | |
if constexpr (is_code_units_maybe_replaceable_v<_Encoding>) { | |
auto __maybe_direct_replacement = __encoding.maybe_replacement_code_units(); | |
if (__maybe_direct_replacement) { | |
const auto& __direct_replacement = *__maybe_direct_replacement; | |
return __txt_detail::__write_direct( | |
__encoding, __direct_replacement, ::std::move(__result)); | |
} | |
} | |
using _InputCodePoint = code_point_t<_Encoding>; | |
_InputCodePoint __replacement[max_code_points_v<_Encoding>] {}; | |
::std::size_t __replacement_size = 0; | |
if constexpr (is_code_points_replaceable_v<_Encoding>) { | |
auto __replacement_code_units = __encoding.replacement_code_points(); | |
for (const auto& __element : __replacement_code_units) { | |
__replacement[__replacement_size] = __element; | |
++__replacement_size; | |
} | |
} | |
else { | |
__replacement_size | |
= __txt_detail::__fill_replacement_code_point_static(__encoding, __replacement); | |
} | |
const ::ztd::text::span<const _InputCodePoint> __replacement_range( | |
__replacement, __replacement_size); | |
__txt_detail::__pass_through_handler __handler {}; | |
encode_state_t<_Encoding> __state = make_encode_state(__encoding); | |
auto __encresult = __txt_detail::__basic_encode_one<__txt_detail::__consume::__no>( | |
__replacement_range, __encoding, ::std::move(__result.output), __handler, __state); | |
__result.output = ::std::move(__encresult.output); | |
if (__encresult.error_code != encoding_error::ok) { | |
// we can't even encode a single code unit | |
// into the stream... report error and bail | |
return __result; | |
} | |
__result.error_code = encoding_error::ok; | |
return __result; | |
} | |
} | |
////// | |
/// @brief The function call for inserting replacement code points at the point of failure, before returning | |
/// flow back to the caller of the decode operation. | |
/// | |
/// @param[in] __encoding The Encoding that experienced the error. | |
/// @param[in] __result The current state of the encode operation. | |
/// | |
/// @remarks TODO: describe the replacement process thoroughly and fix this! | |
////// | |
template <typename _Encoding, typename _InputRange, typename _OutputRange, typename _State, | |
typename _Progress> | |
constexpr auto operator()(const _Encoding& __encoding, | |
decode_result<_InputRange, _OutputRange, _State> __result, const _Progress&) const noexcept { | |
using _CodePoint = code_point_t<_Encoding>; | |
if (__result.error_code == encoding_error::insufficient_output_space) { | |
// BAIL | |
return __result; | |
} | |
auto __outit = __txt_detail::__adl::__adl_begin(__result.output); | |
auto __outlast = __txt_detail::__adl::__adl_end(__result.output); | |
if (__outit == __outlast) { | |
// BAIL | |
return __result; | |
} | |
if constexpr (is_code_points_replaceable_v<_Encoding>) { | |
return __txt_detail::__write_direct( | |
__encoding, __encoding.replacement_code_points(), ::std::move(__result)); | |
} | |
else if constexpr (!is_code_points_maybe_replaceable_v< | |
_Encoding> && is_unicode_code_point_v<_CodePoint>) { | |
constexpr _CodePoint __replacements[1] = { static_cast<_CodePoint>(__txt_detail::__replacement) }; | |
return __txt_detail::__write_direct(__encoding, __replacements, ::std::move(__result)); | |
} | |
else { | |
if constexpr (is_code_points_maybe_replaceable_v<_Encoding>) { | |
auto __maybe_direct_replacement = __encoding.maybe_replacement_code_points(); | |
if (__maybe_direct_replacement) { | |
const auto& __direct_replacement = *__maybe_direct_replacement; | |
return __txt_detail::__write_direct( | |
__encoding, __direct_replacement, ::std::move(__result)); | |
} | |
} | |
using _InputCodeUnit = code_unit_t<_Encoding>; | |
_InputCodeUnit __replacement[max_code_units_v<_Encoding>] {}; | |
::std::size_t __replacement_size = 0; | |
if constexpr (is_code_units_replaceable_v<_Encoding>) { | |
auto __replacement_code_units = __encoding.replacement_code_units(); | |
for (const auto& __element : __replacement_code_units) { | |
__replacement[__replacement_size] = __element; | |
++__replacement_size; | |
} | |
} | |
else { | |
__replacement_size | |
= __txt_detail::__fill_replacement_code_unit_static(__encoding, __replacement); | |
} | |
const ::ztd::text::span<const _InputCodeUnit> __replacement_range( | |
__replacement, __replacement_size); | |
__txt_detail::__pass_through_handler __handler {}; | |
decode_state_t<_Encoding> __state = make_decode_state(__encoding); | |
auto __decresult = __txt_detail::__basic_decode_one<__txt_detail::__consume::__no>( | |
__replacement_range, __encoding, ::std::move(__result.output), __handler, __state); | |
__result.output = ::std::move(__decresult.output); | |
if (__decresult.error_code != encoding_error::ok) { | |
// we can't even decode a single code unit | |
// into the stream... report error and bail | |
return __result; | |
} | |
__result.error_code = encoding_error::ok; | |
return __result; | |
} | |
} | |
}; | |
////// | |
/// @brief An error handler that throws on any encode operation failure. | |
/// | |
/// @remarks This class absolutely should not be used unless the user is prepared to handle spurious failure, | |
/// especially for text processing that deals with input vectors. This can result in many exceptions being thrown, | |
/// which for resource-intensive applications could cause issues and result in Denial of Service by way of | |
/// repeated, unhandled, and unexpected failure. | |
////// | |
class throw_handler { | |
public: | |
////// | |
/// @brief Throws a ztd::text::encoding_error as an exception on an encode failure. | |
/// | |
////// | |
template <typename _Encoding, typename _InputRange, typename _OutputRange, typename _State, | |
typename _Progress> | |
constexpr encode_result<_InputRange, _OutputRange, _State> operator()(const _Encoding&, | |
encode_result<_InputRange, _OutputRange, _State> __result, const _Progress&) const noexcept(false) { | |
throw ::std::system_error(static_cast<int>(__result.error_code), ::ztd::text::encoding_category()); | |
} | |
////// | |
/// @brief Throws a ztd::text::encoding_error code as an exception on a decode failure. | |
/// | |
////// | |
template <typename _Encoding, typename _InputRange, typename _OutputRange, typename _State, | |
typename _Progress> | |
constexpr decode_result<_InputRange, _OutputRange, _State> operator()(const _Encoding&, | |
decode_result<_InputRange, _OutputRange, _State> __result, const _Progress&) const noexcept(false) { | |
throw ::std::system_error(static_cast<int>(__result.error_code), ::ztd::text::encoding_category()); | |
} | |
}; | |
////// | |
/// @brief This handler detects if the error code is an incomplete seqence, and sets the error code to being okay | |
/// before returning. | |
/// | |
/// @tparam _Encoding The encoding type which dictates the @c code_unit and @c code_point buffers to store in the | |
/// handler to catch unused input from the last parameter of error handler invocations by the encoding. | |
/// @tparam _ErrorHandler An error handler to invoke if the encoding error code is @b NOT an incomplete sequence. | |
/// | |
/// @remarks This type is often useful in conjunction with an accumulation state or buffer, which can be very handy | |
/// for I/O (e.g., Networking) operations. | |
////// | |
template <typename _Encoding, typename _ErrorHandler = default_handler> | |
class incomplete_handler : private __txt_detail::__ebco<_ErrorHandler> { | |
private: | |
using __error_handler_base_t = __txt_detail::__ebco<_ErrorHandler>; | |
using _CodeUnit = code_unit_t<_Encoding>; | |
using _CodePoint = code_point_t<_Encoding>; | |
public: | |
////// | |
/// @brief The underlying error handler type. | |
/// | |
////// | |
using error_handler = _ErrorHandler; | |
////// | |
/// @brief Constructs a ztd::text::incomplete_handler with a default-constructed internal error handler. | |
////// | |
constexpr incomplete_handler() noexcept(::std::is_nothrow_default_constructible_v<__error_handler_base_t>) | |
: __error_handler_base_t(), _M_code_points_size(), _M_code_units_size() { | |
} | |
////// | |
/// @brief Constructs a ztd::text::incomplete_handler with the provided internal error handler object. | |
/// | |
/// @param __error_handler The provided error handler object to copy in and use when the error is not an | |
/// incomplete error. | |
////// | |
constexpr incomplete_handler(const _ErrorHandler& __error_handler) noexcept( | |
::std::is_nothrow_constructible_v<__error_handler_base_t, const _ErrorHandler&>) | |
: __error_handler_base_t(__error_handler) | |
, _M_code_units() | |
, _M_code_units_size() | |
, _M_code_points() | |
, _M_code_points_size() { | |
} | |
////// | |
/// @brief Constructs a ztd::text::incomplete_handler with the provided internal error handler object. | |
/// | |
/// @param __error_handler The provided error handler object to move in and use when the error is not an | |
/// incomplete error. | |
////// | |
constexpr incomplete_handler(_ErrorHandler&& __error_handler) noexcept( | |
::std::is_nothrow_constructible_v<__error_handler_base_t, _ErrorHandler&&>) | |
: __error_handler_base_t(::std::move(__error_handler)) | |
, _M_code_units() | |
, _M_code_units_size() | |
, _M_code_points() | |
, _M_code_points_size() { | |
} | |
////// | |
/// @brief Returns the base error handler that is called when a non-incomplete error occurs. | |
/// | |
////// | |
constexpr _ErrorHandler& base() & noexcept { | |
return this->__error_handler_base_t::__get_value(); | |
} | |
////// | |
/// @brief Returns the base error handler that is called when a non-incomplete error occurs. | |
/// | |
////// | |
constexpr const _ErrorHandler& base() const& noexcept { | |
return this->__error_handler_base_t::__get_value(); | |
} | |
////// | |
/// @brief Returns the base error handler that is called when a non-incomplete error occurs. | |
/// | |
////// | |
constexpr _ErrorHandler&& base() && noexcept { | |
return this->__error_handler_base_t::__get_value(); | |
} | |
////// | |
/// @brief Checks if the __result.error_code is ztd::text::encoding_error::incomplete_sequence, it saves the | |
/// values from @p __progress and returns. Otherwise, invokes the provided error handler this object was | |
/// constructed with. | |
/// | |
/// @param[in] __encoding The Encoding that experienced the error. | |
/// @param[in] __result The current state of the encode operation. | |
/// @param[in] __progress Any unused code units that were read before the failure occurred. These will be | |
/// stored in this handler. | |
////// | |
template <typename _Result, typename _Progress> | |
constexpr auto operator()(const _Encoding& __encoding, _Result __result, const _Progress& __progress) const | |
noexcept(::std::is_nothrow_invocable_v<_ErrorHandler, const _Encoding&, _Result, const _Progress&>) { | |
if (__result.error_code == encoding_error::incomplete_sequence) { | |
// it's incomplete and we are okay with that | |
if constexpr (__txt_detail::__is_specialization_of_v<_Result, decode_result>) { | |
// save the read code units | |
::std::copy_n(__txt_detail::__adl::__adl_cbegin(__progress), | |
__txt_detail::__adl::__adl_cend(__progress), this->_M_code_units.data()); | |
this->_M_code_units_size = __txt_detail::__adl::__adl_size(__progress); | |
} | |
else { | |
// save the read code points | |
::std::copy_n(__txt_detail::__adl::__adl_cbegin(__progress), | |
__txt_detail::__adl::__adl_cend(__progress), this->_M_code_points.data()); | |
this->_M_code_points_size = __txt_detail::__adl::__adl_size(__progress); | |
} | |
return __result; | |
} | |
return this->get_value()(__encoding, ::std::move(__result), __progress); | |
} | |
////// | |
/// @brief Returns the code units from the last incomplete decode operations. | |
/// | |
////// | |
::ztd::text::span<_CodeUnit> code_units() const noexcept { | |
return ::ztd::text::span<_CodeUnit>(this->_M_code_units.data(), this->_M_code_units_size); | |
} | |
////// | |
/// @brief Returns the code points from the last incomplete encode operations. | |
/// | |
////// | |
::ztd::text::span<_CodePoint> code_points() const noexcept { | |
return ::ztd::text::span<_CodePoint>(this->_M_code_units.data(), this->_M_code_units_size); | |
} | |
private: | |
::std::array<_CodeUnit, max_code_units_v<_Encoding>> _M_code_units; | |
::std::size_t _M_code_units_size; | |
::std::array<_CodePoint, max_code_points_v<_Encoding>> _M_code_points; | |
::std::size_t _M_code_points_size; | |
}; | |
////// | |
/// @brief The default error handler for the entire library. Can be configured to use different strategies at build | |
/// time. Without configuration, it defaults to the ztd::text::replacement_handler. | |
////// | |
class default_handler | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_DEFAULT_HANDLER_THROWS_I_) | |
: private throw_handler { | |
private: | |
using __error_handler_base_t = throw_handler; | |
#else | |
: private replacement_handler { | |
private: | |
using __error_handler_base_t = replacement_handler; | |
#endif | |
public: | |
////// | |
/// @brief The underlying error handler type. | |
/// | |
////// | |
using error_handler = __error_handler_base_t; | |
using __error_handler_base_t::__error_handler_base_t; | |
using __error_handler_base_t::operator(); | |
}; | |
using default_incomplete_handler = incomplete_handler<default_handler>; | |
namespace __txt_detail { | |
template <typename _ErrorHandler> | |
constexpr auto __duplicate_or_be_careless(_ErrorHandler& __original) { | |
using _UErrorHandler = __remove_cvref_t<_ErrorHandler>; | |
if constexpr (!::std::is_function_v<_UErrorHandler>) { | |
if constexpr (::std::is_copy_constructible_v<_UErrorHandler>) { | |
return __original; | |
} | |
else { | |
return default_handler {}; | |
} | |
} | |
else { | |
return default_handler {}; | |
} | |
} | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/error_handler.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/is_ignorable_error_handler.hpp | |
#include <type_traits> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _Type> | |
using __detect_decode_always_ok = decltype(_Type::decode_always_ok); | |
template <typename _Type> | |
using __detect_encode_always_ok = decltype(_Type::encode_always_ok); | |
template <typename, typename = void> | |
struct __is_ignorable_error_handler_sfinae : ::std::false_type { }; | |
template <typename _Type> | |
struct __is_ignorable_error_handler_sfinae<_Type, ::std::void_t<decltype(_Type::assume_valid)>> | |
: ::std::integral_constant<bool, _Type::assume_valid::value> { }; | |
template <typename _Encoding, typename _ErrorHandler> | |
struct __decode_error_handler_always_returns_ok | |
: ::std::integral_constant<bool, __is_detected_v<__detect_decode_always_ok, _ErrorHandler>> { }; | |
template <typename _Encoding> | |
struct __decode_error_handler_always_returns_ok<_Encoding, replacement_handler> | |
: ::std::integral_constant<bool, | |
(is_code_points_replaceable_v<_Encoding> && !is_code_points_maybe_replaceable_v<_Encoding>) | |
|| is_unicode_code_point_v<code_point_t<_Encoding>>> { }; | |
template <typename _Encoding> | |
struct __decode_error_handler_always_returns_ok<_Encoding, throw_handler> : ::std::true_type { }; | |
template <typename _Encoding, typename _ErrorHandler> | |
struct __decode_error_handler_always_returns_ok<_Encoding, incomplete_handler<_Encoding, _ErrorHandler>> | |
: __decode_error_handler_always_returns_ok<_Encoding, | |
typename incomplete_handler<_Encoding, _ErrorHandler>::error_handler> { }; | |
template <typename _Encoding> | |
struct __decode_error_handler_always_returns_ok<_Encoding, default_handler> | |
: __decode_error_handler_always_returns_ok<_Encoding, typename default_handler::error_handler> { }; | |
template <typename _Encoding> | |
struct __decode_error_handler_always_returns_ok<_Encoding, assume_valid_handler> : ::std::true_type { }; | |
template <typename _Encoding, typename _ErrorHandler> | |
struct __encode_error_handler_always_returns_ok | |
: ::std::integral_constant<bool, __is_detected_v<__detect_encode_always_ok, _ErrorHandler>> { }; | |
template <typename _Encoding> | |
struct __encode_error_handler_always_returns_ok<_Encoding, replacement_handler> | |
: ::std::integral_constant<bool, | |
(is_code_units_replaceable_v<_Encoding> && !is_code_units_maybe_replaceable_v<_Encoding>) | |
|| is_unicode_code_point_v<code_unit_t<_Encoding>>> { }; | |
template <typename _Encoding> | |
struct __encode_error_handler_always_returns_ok<_Encoding, throw_handler> : ::std::true_type { }; | |
template <typename _Encoding, typename _ErrorHandler> | |
struct __encode_error_handler_always_returns_ok<_Encoding, incomplete_handler<_Encoding, _ErrorHandler>> | |
: __encode_error_handler_always_returns_ok<_Encoding, | |
typename incomplete_handler<_Encoding, _ErrorHandler>::error_handler> { }; | |
template <typename _Encoding> | |
struct __encode_error_handler_always_returns_ok<_Encoding, default_handler> | |
: __encode_error_handler_always_returns_ok<_Encoding, typename default_handler::error_handler> { }; | |
template <typename _Encoding> | |
struct __encode_error_handler_always_returns_ok<_Encoding, assume_valid_handler> : ::std::true_type { }; | |
} // namespace __txt_detail | |
////// | |
/// @addtogroup ztd_text_properties Property and Trait Helpers | |
/// | |
/// @{ | |
///// | |
////// | |
/// @brief Whether or not the given @p _Type is an error handler that can be ignored. | |
/// | |
/// @tparam _Type the Error Handling type to chec. | |
/// | |
/// @remarks An error handler type can mark itself as ignorable by using a @c using @c assume_valid @c = | |
/// @c std::integral_constant<bool, @c value> where @c value determines if the type's error handling callback can | |
/// be ignored. This is what ztd::text::assume_valid does. Being configurable means templated error handlers can | |
/// select whether or not they should be ignorable based on compile time, safe conditions that you can make up | |
/// (including checking Macros or other environment data as a means of determining whether or not validity should | |
/// be ignored.) If this results in a type derived from @c std::true_type and the encoder object using it | |
/// encounters an error, then it is Undefined Behavior what occurs afterwards. | |
////// | |
template <typename _Type> | |
class is_ignorable_error_handler : public __txt_detail::__is_ignorable_error_handler_sfinae<_Type> { }; | |
////// | |
/// @brief A @c \::value alias for ztd::text::is_ignorable_error_handler. | |
/// | |
////// | |
template <typename _Type> | |
inline constexpr bool is_ignorable_error_handler_v = is_ignorable_error_handler<_Type>::value; | |
////// | |
/// @brief Whether or not the given @p _Encoding and @p _Input with the provided @p _ErrorHandler will always | |
/// return ztd::text::encoding_error::ok for any failure that is not related to an output being too small | |
/// (ztd::text::encoding_error::insufficient_output_space). | |
/// | |
/// @tparam _Encoding The encoding type whose @c decode_one function will be used with the error handler. | |
/// @tparam _Input The input range that will be used with the @c decode_one function of the encoding. | |
/// @tparam _ErrorHandler The error handler that will be called with the given @p _Encoding object and @p _Input | |
/// range. | |
/// | |
/// @remarks This is a compile time assertion. If the encoding may exhibit different behavior at runtime based on | |
/// runtime conditions, then this should return false. This is meant for cases where it is provable at compile | |
/// time, this should return true. For example, if the ztd::text::replacement_handler is used in conjunction with | |
/// ztd::text::utf8, then this will return true as | |
////// | |
template <typename _Encoding, typename _ErrorHandler> | |
class decode_error_handler_always_returns_ok | |
: public __txt_detail::__decode_error_handler_always_returns_ok<_Encoding, _ErrorHandler> { }; | |
////// | |
/// @brief A @c \::value alias for ztd::text::decode_error_handler_always_returns_ok_v | |
/// | |
////// | |
template <typename _Encoding, typename _ErrorHandler> | |
inline constexpr bool decode_error_handler_always_returns_ok_v | |
= decode_error_handler_always_returns_ok<_Encoding, _ErrorHandler>::value; | |
////// | |
/// @brief Whether or not the given @p _Type is an error handler that can be ignored. | |
/// | |
/// | |
////// | |
template <typename _Encoding, typename _ErrorHandler> | |
class encode_error_handler_always_returns_ok | |
: public __txt_detail::__encode_error_handler_always_returns_ok<_Encoding, _ErrorHandler> { }; | |
////// | |
/// @brief A @c \::value alias for ztd::text::decode_error_handler_always_returns_ok_v | |
/// | |
////// | |
template <typename _Encoding, typename _ErrorHandler> | |
inline constexpr bool encode_error_handler_always_returns_ok_v | |
= encode_error_handler_always_returns_ok<_Encoding, _ErrorHandler>::value; | |
////// | |
/// @} | |
///// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/is_ignorable_error_handler.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/utf8.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/cast.hpp | |
#include <utility> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
enum class __match_alignment { no, yes }; | |
template <typename _To, __match_alignment __require_aligned = __match_alignment::no, typename _From> | |
constexpr decltype(auto) static_cast_if_lossless(_From&& __from) { | |
if constexpr ((sizeof(__remove_cvref_t<_To>) == sizeof(__remove_cvref_t<_From>)) | |
&& ((__require_aligned == __match_alignment::no) | |
|| (alignof(__remove_cvref_t<_To>) == alignof(__remove_cvref_t<_From>)))) { | |
// explicitly cast, since we know it's of the same size/alignment | |
// (e.g., unsigned char -> std::byte should work, but it requires a cast!) | |
return static_cast<_To>(__from); | |
} | |
else { | |
// let it warn/error for weird conversions | |
// (e.g., short -> char8_t should give a narrowing conversion warning) | |
return ::std::forward<_From>(__from); | |
} | |
} | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/cast.hpp | |
#include <array> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __impl { | |
////// | |
/// @brief Internal tag for detecting a ztd::text-derved UTF-8 type. | |
/// | |
/// @internal | |
////// | |
class __utf8_tag { }; | |
////// | |
/// @brief An internal type meant to provide the bulk of the UTF-8 functionality. | |
/// | |
/// @internal | |
/// | |
/// @remarks Relies on CRTP. | |
////// | |
template <typename _Derived = void, typename _CodeUnit = uchar8_t, typename _CodePoint = unicode_code_point, | |
bool __overlong_allowed = false, bool __surrogates_allowed = false, | |
bool __use_overlong_null_only = false> | |
class __utf8_with : public __utf8_tag { | |
public: | |
////// | |
/// @brief Whether or not this encoding that can encode all of Unicode. | |
/// | |
////// | |
using is_unicode_encoding = ::std::true_type; | |
////// | |
/// @brief The state that can be used between calls to the encoder and decoder. It is an empty struct | |
/// because there is no shift state to preserve between complete units of encoded information. | |
////// | |
using state = __txt_detail::__empty_state; | |
////// | |
/// @brief The individual units that result from an encode operation or are used as input to a decode | |
/// operation. For UTF-8 formats, this is usually char8_t, but this can change (see | |
/// ztd::text::basic_utf8). | |
////// | |
using code_unit = _CodeUnit; | |
////// | |
/// @brief The individual units that result from a decode operation or as used as input to an encode | |
/// operation. For most encodings, this is going to be a Unicode Code Point or a Unicode Scalar Value. | |
////// | |
using code_point = _CodePoint; | |
////// | |
/// @brief Whether or not the decode operation can process all forms of input into code point values. | |
/// Thsi is true for all Unicode Transformation Formats (UTFs), which can encode and decode without a | |
/// loss of information from a valid collection of code units. | |
////// | |
using is_decode_injective = ::std::true_type; | |
////// | |
/// @brief Whether or not the encode operation can process all forms of input into code unit values. | |
/// This is true for all Unicode Transformation Formats (UTFs), which can encode and decode without loss | |
/// of information from a valid input code point. | |
////// | |
using is_encode_injective = ::std::true_type; | |
////// | |
/// @brief The maximum number of code points a single complete operation of decoding can produce. This is | |
/// 1 for all Unicode Transformation Format (UTF) encodings. | |
////// | |
inline static constexpr ::std::size_t max_code_points = 1; | |
////// | |
/// @brief The maximum code units a single complete operation of encoding can produce. If overlong | |
/// sequence allowed, this is 6: otherwise, this is 4. | |
////// | |
inline static constexpr ::std::size_t max_code_units = __overlong_allowed ? 6 : 4; | |
private: | |
using __self_t = ::std::conditional_t<::std::is_void_v<_Derived>, __utf8_with, _Derived>; | |
public: | |
////// | |
/// @brief Encodes a single complete unit of information as code units and produces a result with the | |
/// input and output ranges moved past what was successfully read and written; or, produces an error and | |
/// returns the input and output ranges untouched. | |
/// | |
/// @param[in] __input The input view to read code points from. | |
/// @param[in] __output The output view to write code units into. | |
/// @param[in] __error_handler The error handler to invoke if encoding fails. | |
/// @param[in, out] __s The necessary state information. For this encoding, the state is empty and means | |
/// very little. | |
/// | |
/// @returns A ztd::text::encode_result object that contains the reconstructed input range, | |
/// reconstructed output range, error handler, and a reference to the passed-in state. | |
/// | |
/// @remarks To the best ability of the implementation, the iterators will be returned untouched (e.g., | |
/// the input models at least a view and a forward_range). If it is not possible, returned ranges may be | |
/// incremented even if an error occurs due to the semantics of any view that models an input_range. | |
////// | |
template <typename _InputRange, typename _OutputRange, typename _ErrorHandler> | |
static constexpr auto encode_one( | |
_InputRange&& __input, _OutputRange&& __output, _ErrorHandler&& __error_handler, state& __s) { | |
using _UInputRange = __txt_detail::__remove_cvref_t<_InputRange>; | |
using _UOutputRange = __txt_detail::__remove_cvref_t<_OutputRange>; | |
using _UErrorHandler = __txt_detail::__remove_cvref_t<_ErrorHandler>; | |
using _Result = __txt_detail::__reconstruct_encode_result_t<_InputRange, _OutputRange, state>; | |
constexpr bool __call_error_handler = !is_ignorable_error_handler_v<_UErrorHandler>; | |
auto __init = __txt_detail::__adl::__adl_begin(__input); | |
auto __inlast = __txt_detail::__adl::__adl_end(__input); | |
if (__init == __inlast) { | |
// an exhausted sequence is fine | |
return _Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::forward<_OutputRange>(__output)), | |
__s, encoding_error::ok); | |
} | |
auto __outit = __txt_detail::__adl::__adl_begin(__output); | |
auto __outlast = __txt_detail::__adl::__adl_end(__output); | |
code_point __points[1] {}; | |
__points[0] = __txt_detail::__dereference(__init); | |
const code_point& __point = __points[0]; | |
__txt_detail::__advance(__init); | |
if constexpr (__call_error_handler) { | |
if (__point > __txt_detail::__last_code_point) { | |
__self_t __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::invalid_sequence), | |
::ztd::text::span<code_point, 1>(::std::addressof(__points[0]), 1)); | |
} | |
if constexpr (!__surrogates_allowed) { | |
if (__txt_detail::__is_surrogate(__point)) { | |
__self_t __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::invalid_sequence), | |
::ztd::text::span<code_point, 1>(::std::addressof(__points[0]), 1)); | |
} | |
} | |
} | |
if constexpr (__use_overlong_null_only) { | |
if (__point == static_cast<code_point>(0)) { | |
// overlong MUTF-8 | |
constexpr uchar8_t __payload[] = { 0b11000000u, 0b10000000u }; | |
for (::std::size_t i = 0; i < static_cast<::std::size_t>(2); ++i) { | |
if constexpr (__call_error_handler) { | |
if (__outit == __outlast) { | |
__self_t __self {}; | |
return __error_handler(__self, | |
_Result( | |
__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::insufficient_output_space), | |
::ztd::text::span<code_point, 1>(::std::addressof(__points[0]), 1)); | |
} | |
} | |
__txt_detail::__dereference(__outit) = static_cast<code_unit>(__payload[i]); | |
__txt_detail::__advance(__outit); | |
} | |
return _Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::ok); | |
} | |
} | |
if constexpr (__call_error_handler) { | |
if (__outit == __outlast) { | |
__self_t __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::insufficient_output_space), | |
::ztd::text::span<code_point, 1>(::std::addressof(__points[0]), 1)); | |
} | |
} | |
constexpr uchar8_t __first_mask_continuation_values[][2] = { | |
{ 0b01111111, __txt_detail::__start_1byte_continuation }, | |
{ 0b00011111, __txt_detail::__start_2byte_continuation }, | |
{ 0b00001111, __txt_detail::__start_3byte_continuation }, | |
{ 0b00000111, __txt_detail::__start_4byte_continuation }, | |
{ 0b00000011, __txt_detail::__start_5byte_continuation }, | |
{ 0b00000001, __txt_detail::__start_6byte_continuation }, | |
}; | |
int __length = __txt_detail::__decode_length<__overlong_allowed>(__point); | |
int __lengthindex = __length - 1; | |
const auto& __first_mask_continuation = __first_mask_continuation_values[__lengthindex]; | |
const uchar8_t& __first_mask = __first_mask_continuation[0]; | |
const uchar8_t& __first_continuation = __first_mask_continuation[1]; | |
int __current_shift = 6 * __lengthindex; | |
__txt_detail::__dereference(__outit) = static_cast<code_unit>( | |
__first_continuation | static_cast<uchar8_t>((__point >> __current_shift) & __first_mask)); | |
__txt_detail::__advance(__outit); | |
if (__lengthindex > 0) { | |
__current_shift -= 6; | |
for (; __current_shift >= 0; __current_shift -= 6) { | |
if constexpr (__call_error_handler) { | |
if (__outit == __outlast) { | |
__self_t __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::insufficient_output_space), | |
::ztd::text::span<code_point, 1>(::std::addressof(__points[0]), 1)); | |
} | |
} | |
__txt_detail::__dereference(__outit) | |
= static_cast<code_unit>(__txt_detail::__continuation_signature | |
| static_cast<uchar8_t>( | |
(__point >> __current_shift) & __txt_detail::__continuation_mask_value)); | |
__txt_detail::__advance(__outit); | |
} | |
} | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::ok); | |
} | |
////// | |
/// @brief Decodes a single complete unit of information as code points and produces a result with the | |
/// input and output ranges moved past what was successfully read and written; or, produces an error and | |
/// returns the input and output ranges untouched. | |
/// | |
/// @param[in] __input The input view to read code uunits from. | |
/// @param[in] __output The output view to write code points into. | |
/// @param[in] __error_handler The error handler to invoke if encoding fails. | |
/// @param[in, out] __s The necessary state information. For this encoding, the state is empty and means | |
/// very little. | |
/// | |
/// @returns A ztd::text::decode_result object that contains the reconstructed input range, | |
/// reconstructed output range, error handler, and a reference to the passed-in state. | |
/// | |
/// @remarks To the best ability of the implementation, the iterators will be returned untouched (e.g., | |
/// the input models at least a view and a forward_range). If it is not possible, returned ranges may be | |
/// incremented even if an error occurs due to the semantics of any view that models an input_range. | |
////// | |
template <typename _InputRange, typename _OutputRange, typename _ErrorHandler> | |
static constexpr auto decode_one( | |
_InputRange&& __input, _OutputRange&& __output, _ErrorHandler&& __error_handler, state& __s) { | |
using _UInputRange = __txt_detail::__remove_cvref_t<_InputRange>; | |
using _UOutputRange = __txt_detail::__remove_cvref_t<_OutputRange>; | |
using _UErrorHandler = __txt_detail::__remove_cvref_t<_ErrorHandler>; | |
using _Result = __txt_detail::__reconstruct_decode_result_t<_InputRange, _OutputRange, state>; | |
constexpr bool __call_error_handler = !is_ignorable_error_handler_v<_UErrorHandler>; | |
auto __init = __txt_detail::__adl::__adl_begin(__input); | |
auto __inlast = __txt_detail::__adl::__adl_end(__input); | |
if (__init == __inlast) { | |
// the empty sequence is an OK sequence | |
return _Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::forward<_OutputRange>(__output)), | |
__s, encoding_error::ok); | |
} | |
auto __outit = __txt_detail::__adl::__adl_begin(__output); | |
auto __outlast = __txt_detail::__adl::__adl_end(__output); | |
if constexpr (__call_error_handler) { | |
if (__outit == __outlast) { | |
__self_t __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::insufficient_output_space), | |
::ztd::text::span<code_unit, 0>()); | |
} | |
} | |
else { | |
(void)__outlast; | |
} | |
::std::array<code_unit, max_code_units> __units {}; | |
__units[0] = __txt_detail::static_cast_if_lossless<code_unit>(__txt_detail::__dereference(__init)); | |
const code_unit& __unit0 = __units[0]; | |
__txt_detail::__advance(__init); | |
::std::size_t __length | |
= static_cast<::std::size_t>(__txt_detail::__sequence_length(static_cast<uchar8_t>(__unit0))); | |
if constexpr (!__overlong_allowed) { | |
if constexpr (__call_error_handler) { | |
if (__length > 4) { | |
__self_t __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::invalid_sequence), | |
::ztd::text::span<code_unit, 1>(__units.data(), __units.size())); | |
} | |
} | |
} | |
if (__length == 1) { | |
__txt_detail::__dereference(__outit) = static_cast<code_point>(__unit0); | |
__txt_detail::__advance(__outit); | |
return _Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::move(__outit), ::std::move(__outlast)), | |
__s); | |
} | |
if constexpr (__call_error_handler) { | |
const bool __is_invalid_cu = __txt_detail::__utf8_is_invalid(static_cast<uchar8_t>(__unit0)); | |
if (__is_invalid_cu || __txt_detail::__utf8_is_continuation(static_cast<uchar8_t>(__unit0))) { | |
__self_t __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, | |
__is_invalid_cu ? encoding_error::invalid_sequence | |
: encoding_error::invalid_sequence), | |
::ztd::text::span<code_unit, 1>(__units.data(), 1)); | |
} | |
} | |
for (::std::size_t i = 1; i < __length; ++i) { | |
if constexpr (__call_error_handler) { | |
if (__init == __inlast) { | |
__self_t __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::incomplete_sequence), | |
::ztd::text::span<code_unit>(__units.data(), i)); | |
} | |
} | |
__units[i] | |
= __txt_detail::static_cast_if_lossless<code_unit>(__txt_detail::__dereference(__init)); | |
__txt_detail::__advance(__init); | |
if (!__txt_detail::__utf8_is_continuation(static_cast<uchar8_t>(__units[i]))) { | |
__self_t __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::invalid_sequence), | |
::ztd::text::span<code_unit>(__units.data(), i + 1)); | |
} | |
} | |
code_point __decoded {}; | |
switch (__length) { | |
case 2: | |
__decoded = __txt_detail::__decode( | |
static_cast<uchar8_t>(__units[0]), static_cast<uchar8_t>(__units[1])); | |
break; | |
case 3: | |
__decoded = __txt_detail::__decode(static_cast<uchar8_t>(__units[0]), | |
static_cast<uchar8_t>(__units[1]), static_cast<uchar8_t>(__units[2])); | |
break; | |
case 4: | |
default: | |
__decoded = __txt_detail::__decode(static_cast<uchar8_t>(__units[0]), | |
static_cast<uchar8_t>(__units[1]), static_cast<uchar8_t>(__units[2]), | |
static_cast<uchar8_t>(__units[3])); | |
break; | |
} | |
if constexpr (__call_error_handler) { | |
if constexpr (!__overlong_allowed) { | |
if (__txt_detail::__utf8_is_overlong(__decoded, __length)) { | |
__self_t __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::invalid_sequence), | |
::ztd::text::span<code_unit>(__units.data(), __length)); | |
} | |
} | |
if constexpr (!__surrogates_allowed) { | |
if (__txt_detail::__is_surrogate(__decoded)) { | |
__self_t __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::invalid_sequence), | |
::ztd::text::span<code_unit>(__units.data(), __length)); | |
} | |
} | |
if (static_cast<char32_t>(__decoded) > __txt_detail::__last_code_point) { | |
__self_t __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::invalid_sequence), | |
::ztd::text::span<code_unit>(__units.data(), __length)); | |
} | |
} | |
// then everything is fine | |
__txt_detail::__dereference(__outit) = __decoded; | |
__txt_detail::__advance(__outit); | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::move(__outit), ::std::move(__outlast)), | |
__s); | |
} | |
}; | |
} // namespace __impl | |
////// | |
/// @addtogroup ztd_text_encodings Encodings | |
/// @brief These classes are implementations of the Encoding concept. They serve as the backbone of the library, | |
/// and the point of extension for users. | |
/// @{ | |
////// | |
////// | |
/// @brief A UTF-8 Encoding that traffics in, specifically, the desired code unit type provided as a template | |
/// argument. | |
/// | |
/// @tparam _CodeUnit The code unit type to use. | |
/// @tparam _CodePoint The code point type to use. | |
/// | |
/// @remarks This type as a maximum of 4 input code points and a maximum of 1 output code point. It strictly | |
/// follows the Unicode Specification for allowed conversions. For overlong sequences (e.g., similar to Android or | |
/// Java UTF-8 implementations) and other quirks, see ztd::text::basic_mutf8 or ztd::text::basic_wtf8 . | |
////// | |
template <typename _CodeUnit, typename _CodePoint = unicode_code_point> | |
class basic_utf8 : public __impl::__utf8_with<basic_utf8<_CodeUnit, _CodePoint>, _CodeUnit, _CodePoint> { }; | |
////// | |
/// @brief A UTF-8 Encoding that traffics in uchar8_t. See ztd::text::basic_utf8 for more details. | |
/// | |
////// | |
using utf8 = basic_utf8<uchar8_t>; | |
////// | |
/// @brief A UTF-8 Encoding that traffics in char, for compatibility purposes with older codebases. See | |
/// ztd::text::basic_utf8 for more details. | |
////// | |
using compat_utf8 = basic_utf8<char>; | |
////// | |
/// @brief A "Wobbly Transformation Format 8" (WTF-8) Encoding that traffics in, specifically, the desired code | |
/// unit type provided as a template argument. | |
/// | |
/// @tparam _CodeUnit The code unit type to use. | |
/// @tparam _CodePoint The code point type to use. | |
/// | |
/// @remarks This type as a maximum of 4 input code points and a maximum of 1 output code point. Unpaired | |
/// surrogates are allowed in this type, which may be useful for dealing with legacy storage and implementations of | |
/// the Windows Filesystem (modern Windows no longer lets non-Unicode filenames through). For a strict, | |
/// Unicode-compliant UTF-8 Encoding, see ztd::text::basic_utf8 . | |
////// | |
template <typename _CodeUnit, typename _CodePoint = unicode_code_point> | |
class basic_wtf8 | |
: public __impl::__utf8_with<basic_wtf8<_CodeUnit, _CodePoint>, _CodeUnit, _CodePoint, false, true, false> { }; | |
////// | |
/// @brief A "Wobbly Transformation Format 8" (WTF-8) Encoding that traffics in char8_t. See | |
/// ztd::text::basic_wtf8 for more details. | |
////// | |
using wtf8 = basic_wtf8<uchar8_t>; | |
////// | |
/// @brief A Modified UTF-8 Encoding that traffics in, specifically, the desired code unit type provided as a | |
/// template argument. | |
/// | |
/// @tparam _CodeUnit The code unit type to use. | |
/// @tparam _CodePoint The code point type to use. | |
/// | |
/// @remarks This type as a maximum of 6 input code points and a maximum of 1 output code point. Null values are | |
/// encoded as an overlong sequence to specifically avoid problems with C-style strings, which is useful for | |
/// working with bad implementations sitting on top of POSIX or other Operating System APIs. For a strict, | |
/// Unicode-compliant UTF-8 Encoding, see ztd::text::basic_utf8 . | |
////// | |
template <typename _CodeUnit, typename _CodePoint = unicode_code_point> | |
class basic_mutf8 | |
: public __impl::__utf8_with<basic_mutf8<_CodeUnit, _CodePoint>, _CodeUnit, _CodePoint, true, false, true> { }; | |
////// | |
/// @brief A Modified UTF-8 Encoding that traffics in char8_t. See ztd::text::basic_mutf8 for more details. | |
/// | |
////// | |
using mutf8 = basic_mutf8<uchar8_t>; | |
namespace __txt_detail { | |
template <typename _UTF8Unit, typename _UTF8Point, typename _WTF8Unit, typename _WTF8Point> | |
struct __is_bitwise_transcoding_compatible<basic_utf8<_UTF8Unit, _UTF8Point>, | |
basic_wtf8<_WTF8Unit, _WTF8Point>> | |
: ::std::integral_constant<bool, | |
(sizeof(_UTF8Unit) == sizeof(_WTF8Unit)) && (alignof(_UTF8Unit) == alignof(_WTF8Unit))> { }; | |
template <typename _UTF8Unit, typename _UTF8Point, typename _MUTF8Unit, typename _MUTF8Point> | |
struct __is_bitwise_transcoding_compatible<basic_utf8<_UTF8Unit, _UTF8Point>, | |
basic_mutf8<_MUTF8Unit, _MUTF8Point>> | |
: ::std::integral_constant<bool, | |
(sizeof(_UTF8Unit) == sizeof(_MUTF8Unit)) && (alignof(_UTF8Unit) == alignof(_MUTF8Unit))> { }; | |
} // namespace __txt_detail | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/utf8.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/utf16.hpp | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __impl { | |
////// | |
/// @brief Internal tag for detecting a ztd::text-derved UTF-16 type. | |
/// | |
/// @internal | |
////// | |
class __utf16_tag { }; | |
////// | |
/// @brief An internal type meant to provide the bulk of the UTF-16 functionality. | |
/// | |
/// @internal | |
/// | |
/// @remarks Relies on CRTP. | |
////// | |
template <typename _Derived = void, typename _CodeUnit = char16_t, typename _CodePoint = unicode_code_point, | |
bool __surrogates_allowed = false> | |
class __utf16_with : public __utf16_tag { | |
public: | |
////// | |
/// @brief Whether or not this encoding that can encode all of Unicode. | |
/// | |
////// | |
using is_unicode_encoding = ::std::true_type; | |
////// | |
/// @brief The state that can be used between calls to the encoder and decoder. It is an empty struct | |
/// because there is no shift state to preserve between complete units of encoded information. | |
////// | |
using state = __txt_detail::__empty_state; | |
////// | |
/// @brief The individual units that result from an encode operation or are used as input to a decode | |
/// operation. For UTF-16 formats, this is usually char16_t, but this can change (see | |
/// ztd::text::basic_utf16). | |
////// | |
using code_unit = _CodeUnit; | |
////// | |
/// @brief The individual units that result from a decode operation or as used as input to an encode | |
/// operation. For most encodings, this is going to be a Unicode Code Point or a Unicode Scalar Value. | |
////// | |
using code_point = _CodePoint; | |
////// | |
/// @brief Whether or not the decode operation can process all forms of input into code point values. | |
/// Thsi is true for all Unicode Transformation Formats (UTFs), which can encode and decode without a | |
/// loss of information from a valid collection of code units. | |
////// | |
using is_decode_injective = ::std::true_type; | |
////// | |
/// @brief Whether or not the encode operation can process all forms of input into code unit values. | |
/// This is true for all Unicode Transformation Formats (UTFs), which can encode and decode without loss | |
/// of information from a valid input code point. | |
////// | |
using is_encode_injective = ::std::true_type; | |
////// | |
/// @brief The maximum number of code points a single complete operation of decoding can produce. This is | |
/// 1 for all Unicode Transformation Format (UTF) encodings. | |
////// | |
inline static constexpr ::std::size_t max_code_points = 1; | |
////// | |
/// @brief The maximum code units a single complete operation of encoding can produce. | |
////// | |
inline static constexpr ::std::size_t max_code_units = 2; | |
private: | |
using __self_t = ::std::conditional_t<::std::is_void_v<_Derived>, __utf16_with, _Derived>; | |
public: | |
////// | |
/// @brief Decodes a single complete unit of information as code points and produces a result with the | |
/// input and output ranges moved past what was successfully read and written; or, produces an error and | |
/// returns the input and output ranges untouched. | |
/// | |
/// @param[in] __input The input view to read code uunits from. | |
/// @param[in] __output The output view to write code points into. | |
/// @param[in] __error_handler The error handler to invoke if encoding fails. | |
/// @param[in, out] __s The necessary state information. For this encoding, the state is empty and means | |
/// very little. | |
/// | |
/// @returns A ztd::text::decode_result object that contains the reconstructed input range, | |
/// reconstructed output range, error handler, and a reference to the passed-in state. | |
/// | |
/// @remarks To the best ability of the implementation, the iterators will be returned untouched (e.g., | |
/// the input models at least a view and a forward_range). If it is not possible, returned ranges may be | |
/// incremented even if an error occurs due to the semantics of any view that models an input_range. | |
////// | |
template <typename _InputRange, typename _OutputRange, typename _ErrorHandler> | |
static constexpr auto decode_one( | |
_InputRange&& __input, _OutputRange&& __output, _ErrorHandler&& __error_handler, state& __s) { | |
using _UInputRange = __txt_detail::__remove_cvref_t<_InputRange>; | |
using _UOutputRange = __txt_detail::__remove_cvref_t<_OutputRange>; | |
using _UErrorHandler = __txt_detail::__remove_cvref_t<_ErrorHandler>; | |
using _Result = __txt_detail::__reconstruct_decode_result_t<_InputRange, _OutputRange, state>; | |
constexpr bool __call_error_handler = !is_ignorable_error_handler_v<_UErrorHandler>; | |
auto __init = __txt_detail::__adl::__adl_begin(::std::forward<_InputRange>(__input)); | |
auto __inlast = __txt_detail::__adl::__adl_end(::std::forward<_InputRange>(__input)); | |
if constexpr (__call_error_handler) { | |
if (__init == __inlast) { | |
// an exhausted sequence is fine | |
return _Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::forward<_OutputRange>(__output)), | |
__s, encoding_error::ok); | |
} | |
} | |
else { | |
(void)__inlast; | |
} | |
auto __outit = __txt_detail::__adl::__adl_begin(__output); | |
auto __outlast = __txt_detail::__adl::__adl_end(__output); | |
if constexpr (__call_error_handler) { | |
if (__outit == __outlast) { | |
__self_t __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::insufficient_output_space), | |
::ztd::text::span<code_unit, 0>()); | |
} | |
} | |
else { | |
(void)__outlast; | |
} | |
::std::array<code_unit, 2> __units {}; | |
__units[0] = __txt_detail::__dereference(__init); | |
const code_unit& __lead = __units[0]; | |
__txt_detail::__advance(__init); | |
if (!__txt_detail::__is_surrogate(__lead)) { | |
__txt_detail::__dereference(__outit) = static_cast<code_point>(__lead); | |
__txt_detail::__advance(::std::move(__outit)); | |
return _Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::ok); | |
} | |
if constexpr (__call_error_handler) { | |
if (!__txt_detail::__is_lead_surrogate(__lead)) { | |
__self_t __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::invalid_sequence), | |
::ztd::text::span<code_unit, 1>(__units.data(), 1)); | |
} | |
} | |
if constexpr (__call_error_handler) { | |
if (__init == __inlast) { | |
__self_t __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::incomplete_sequence), | |
::ztd::text::span<code_unit, 1>(__units.data(), 1)); | |
} | |
} | |
__units[1] = __txt_detail::__dereference(__init); | |
const code_unit& __trail = __units[1]; | |
__txt_detail::__advance(__init); | |
if constexpr (__call_error_handler) { | |
if (!__txt_detail::__is_trail_surrogate(__trail)) { | |
__self_t __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::invalid_sequence), | |
::ztd::text::span<code_unit, 2>(__units.data(), 2)); | |
} | |
} | |
__txt_detail::__dereference(__outit) | |
= static_cast<code_point>(__txt_detail::__utf16_combine_surrogates( | |
static_cast<char16_t>(__lead), static_cast<char16_t>(__trail))); | |
__txt_detail::__advance(::std::move(__outit)); | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::ok); | |
} | |
////// | |
/// @brief Encodes a single complete unit of information as code units and produces a result with the | |
/// input and output ranges moved past what was successfully read and written; or, produces an error and | |
/// returns the input and output ranges untouched. | |
/// | |
/// @param[in] __input The input view to read code points from. | |
/// @param[in] __output The output view to write code units into. | |
/// @param[in] __error_handler The error handler to invoke if encoding fails. | |
/// @param[in, out] __s The necessary state information. For this encoding, the state is empty and means | |
/// very little. | |
/// | |
/// @returns A ztd::text::encode_result object that contains the reconstructed input range, | |
/// reconstructed output range, error handler, and a reference to the passed-in state. | |
/// | |
/// @remarks To the best ability of the implementation, the iterators will be returned untouched (e.g., | |
/// the input models at least a view and a forward_range). If it is not possible, returned ranges may be | |
/// incremented even if an error occurs due to the semantics of any view that models an input_range. | |
////// | |
template <typename _InputRange, typename _OutputRange, typename _ErrorHandler> | |
static constexpr auto encode_one( | |
_InputRange&& __input, _OutputRange&& __output, _ErrorHandler&& __error_handler, state& __s) { | |
using _UInputRange = __txt_detail::__remove_cvref_t<_InputRange>; | |
using _UOutputRange = __txt_detail::__remove_cvref_t<_OutputRange>; | |
using _UErrorHandler = __txt_detail::__remove_cvref_t<_ErrorHandler>; | |
using _Result = __txt_detail::__reconstruct_encode_result_t<_InputRange, _OutputRange, state>; | |
constexpr bool __call_error_handler = !is_ignorable_error_handler_v<_UErrorHandler>; | |
auto __init = __txt_detail::__adl::__adl_begin(__input); | |
auto __inlast = __txt_detail::__adl::__adl_end(__input); | |
if (__init == __inlast) { | |
// an exhausted sequence is fine | |
return _Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::forward<_OutputRange>(__output)), | |
__s, encoding_error::ok); | |
} | |
auto __outit = __txt_detail::__adl::__adl_begin(__output); | |
auto __outlast = __txt_detail::__adl::__adl_end(__output); | |
if constexpr (__call_error_handler) { | |
if (__outit == __outlast) { | |
__self_t __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::insufficient_output_space), | |
::ztd::text::span<code_point, 0>()); | |
} | |
} | |
else { | |
(void)__outlast; | |
} | |
code_point __points[1] {}; | |
__points[0] = __txt_detail::__dereference(__init); | |
const code_point& __point = __points[0]; | |
__txt_detail::__advance(__init); | |
if constexpr (__call_error_handler) { | |
if (__point > __txt_detail::__last_code_point) { | |
__self_t __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::invalid_sequence), | |
::ztd::text::span<code_point, 1>(::std::addressof(__points[0]), 1)); | |
} | |
} | |
if (__point <= __txt_detail::__last_bmp_value) { | |
__txt_detail::__dereference(__outit) = static_cast<char16_t>(__point); | |
__txt_detail::__advance(__outit); | |
} | |
else { | |
auto normal = __point - __txt_detail::__normalizing_value; | |
auto lead = __txt_detail::__first_lead_surrogate | |
+ ((normal & __txt_detail::__lead_surrogate_bitmask) | |
>> __txt_detail::__lead_shifted_bits); | |
auto trail = __txt_detail::__first_trail_surrogate | |
+ (normal & __txt_detail::__trail_surrogate_bitmask); | |
__txt_detail::__dereference(__outit) = static_cast<char16_t>(lead); | |
__txt_detail::__advance(__outit); | |
if constexpr (__call_error_handler) { | |
if (__outit == __outlast) { | |
__self_t __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::insufficient_output_space), | |
::ztd::text::span<code_point, 1>(::std::addressof(__points[0]), 1)); | |
} | |
} | |
__txt_detail::__dereference(__outit) = static_cast<char16_t>(trail); | |
__txt_detail::__advance(__outit); | |
} | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::ok); | |
} | |
}; | |
} // namespace __impl | |
////// | |
/// @addtogroup ztd_text_encodings Encodings | |
/// @{ | |
////// | |
////// | |
/// @brief A UTF-16 Encoding that traffics in, specifically, the desired code unit type provided as a template | |
/// argument. | |
/// | |
/// @tparam _CodeUnit The code unit type to use. | |
/// @tparam _CodePoint The code point type to use. | |
/// | |
/// @remarks This is a strict UTF-16 implementation that does not allow lone, unpaired surrogates either in or out. | |
////// | |
template <typename _CodeUnit, typename _CodePoint = unicode_code_point> | |
class basic_utf16 : public __impl::__utf16_with<basic_utf16<_CodeUnit, _CodePoint>, _CodeUnit, _CodePoint> { }; | |
////// | |
/// @brief A UTF-16 Encoding that traffics in char16_t. See ztd::text::basic_utf16 for more details. | |
/// | |
////// | |
using utf16 = basic_utf16<char16_t>; | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/utf16.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/progress_handler.hpp | |
#include <array> | |
#include <type_traits> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <bool _AssumeValid, typename _DesiredEncoding> | |
class __progress_handler { | |
public: | |
using assume_valid = ::std::integral_constant<bool, _AssumeValid>; | |
::std::array<code_point_t<_DesiredEncoding>, max_code_points_v<_DesiredEncoding>> _M_code_points; | |
::std::size_t _M_code_points_size; | |
::std::array<code_unit_t<_DesiredEncoding>, max_code_units_v<_DesiredEncoding>> _M_code_units; | |
::std::size_t _M_code_units_size; | |
constexpr __progress_handler() noexcept | |
: _M_code_points(), _M_code_points_size(), _M_code_units(), _M_code_units_size() { | |
} | |
template <typename _Encoding, typename _InputRange, typename _OutputRange, typename _State, | |
typename _Progress> | |
constexpr auto operator()(const _Encoding&, | |
encode_result<_InputRange, _OutputRange, _State> __result, | |
const _Progress& __progress) noexcept { | |
_M_code_points_size = __adl::__adl_size(__progress); | |
// avoid needing potentially non-constexpr ::std::copy | |
#ifdef __cpp_lib_constexpr_algorithms | |
::std::copy_n(__adl::__adl_cbegin(__progress), this->_M_code_points_size, | |
__adl::__adl_begin(this->_M_code_points)); | |
#else | |
for (::std::size_t __index = 0; __index < _M_code_points_size; ++__index) { | |
_M_code_points[__index] = __progress[__index]; | |
} | |
#endif | |
return __result; | |
} | |
template <typename _Encoding, typename _InputRange, typename _OutputRange, typename _State, | |
typename _Progress> | |
constexpr auto operator()(const _Encoding&, | |
decode_result<_InputRange, _OutputRange, _State> __result, | |
const _Progress& __progress) noexcept { | |
_M_code_units_size = __adl::__adl_size(__progress); | |
#ifdef __cpp_lib_constexpr_algorithms | |
::std::copy_n(__adl::__adl_cbegin(__progress), this->_M_code_units_size, | |
__adl::__adl_begin(this->_M_code_units)); | |
#else | |
// avoid needing potentially non-constexpr ::std::copy | |
auto __first = __adl::__adl_cbegin(__progress); | |
for (::std::size_t __index = 0; __index < _M_code_units_size; (void)++__index, (void)++__first) { | |
_M_code_units[__index] = *__first; | |
} | |
#endif | |
return __result; | |
} | |
}; | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/progress_handler.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/windows.hpp | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_PLATFORM_WINDOWS_I_) | |
#pragma push_macro("NOMINMAX") | |
#pragma push_macro("WIN32_LEAN_AND_MEAN") | |
#pragma push_macro("VC_EXTRALEAN") | |
#define NOMINMAX 1 | |
#define WIN32_LEAN_AND_MEAN 1 | |
#define VC_EXTRALEAN 1 | |
#ifdef _MSC_VER | |
#include <cstddef> | |
#include <ciso646> | |
#include <cwchar> | |
#include <locale> | |
#else | |
#endif | |
extern "C" { | |
#include <Windows.h> | |
} | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { namespace __windows { | |
inline int __determine_active_code_page() noexcept { | |
#if defined(_STL_LANG) || defined(_YVALS_CORE_H) || defined(_STDEXT) | |
// Removed in later versions of VC++ | |
if (___lc_codepage_func() == CP_UTF8) { | |
return CP_UTF8; | |
} | |
#endif // VC++ stuff | |
#if !defined(_KERNELX) && !defined(_ONECORE) | |
if (!::AreFileApisANSI()) { | |
return CP_OEMCP; | |
} | |
#endif // !defined(_KERNELX) && !defined(_ONECORE) | |
return CP_ACP; | |
} | |
inline bool __is_unicode_code_page(int __codepage_id) { | |
switch (__codepage_id) { | |
case CP_UTF7: | |
case CP_UTF8: | |
case 1200: // UTF-16, Little Endian ("utf-16") | |
case 1201: // UTF-16, Big Endian ("unicodeFFFE") | |
case 12000: // UTF-16, Little Endian ("utf-32") | |
case 12001: // UTF-16, Big Endian ("utf-32BE") | |
case 54936: // GB18030, 4 bytes long | |
return true; | |
default: | |
return false; | |
} | |
} | |
}} // namespace __txt_detail::__windows | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
#pragma pop_macro("VC_EXTRALEAN") | |
#pragma pop_macro("WIN32_LEAN_AND_MEAN") | |
#pragma pop_macro("NOMINMAX") | |
#endif // Windows nightmare | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/windows.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/posix.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/encoding_name.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/utf32.hpp | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __impl { | |
////// | |
/// @brief Internal tag for detecting a ztd::text-derved UTF-32 type. | |
/// | |
/// @internal | |
////// | |
class __utf32_tag { }; | |
////// | |
/// @brief An internal type meant to provide the bulk of the UTF-32 functionality. | |
/// | |
/// @internal | |
/// | |
/// @remarks Relies on CRTP. | |
////// | |
template <typename _Derived = void, typename _CodeUnit = char32_t, typename _CodePoint = unicode_code_point, | |
bool __validate_decodable_as = true> | |
class __utf32_with : public __utf32_tag { | |
public: | |
////// | |
/// @brief Whether or not this encoding that can encode all of Unicode. | |
/// | |
////// | |
using is_unicode_encoding = ::std::true_type; | |
////// | |
/// @brief The state that can be used between calls to the encoder and decoder. It is an empty struct | |
/// because there is no shift state to preserve between complete units of encoded information. | |
////// | |
using state = __txt_detail::__empty_state; | |
////// | |
/// @brief The individual units that result from an encode operation or are used as input to a decode | |
/// operation. For UTF-32 formats, this is usually char32_t, but this can change (see | |
/// ztd::text::basic_utf32). | |
////// | |
using code_unit = _CodeUnit; | |
////// | |
/// @brief The individual units that result from a decode operation or as used as input to an encode | |
/// operation. For most encodings, this is going to be a Unicode Code Point or a Unicode Scalar Value. | |
////// | |
using code_point = _CodePoint; | |
////// | |
/// @brief Whether or not the decode operation can process all forms of input into code point values. | |
/// Thsi is true for all Unicode Transformation Formats (UTFs), which can encode and decode without a | |
/// loss of information from a valid collection of code units. | |
////// | |
using is_decode_injective = ::std::true_type; | |
////// | |
/// @brief Whether or not the encode operation can process all forms of input into code unit values. | |
/// This is true for all Unicode Transformation Formats (UTFs), which can encode and decode without loss | |
/// of information from a valid input code point. | |
////// | |
using is_encode_injective = ::std::true_type; | |
////// | |
/// @brief The maximum number of code points a single complete operation of decoding can produce. This is | |
/// 1 for all Unicode Transformation Format (UTF) encodings. | |
////// | |
inline static constexpr ::std::size_t max_code_points = 1; | |
////// | |
/// @brief The maximum code units a single complete operation of encoding can produce. | |
////// | |
inline static constexpr ::std::size_t max_code_units = 1; | |
private: | |
using __self_t = typename ::std::conditional<::std::is_void_v<_Derived>, __utf32_with, _Derived>::type; | |
public: | |
////// | |
/// @brief Decodes a single complete unit of information as code points and produces a result with the | |
/// input and output ranges moved past what was successfully read and written; or, produces an error and | |
/// returns the input and output ranges untouched. | |
/// | |
/// @param[in] __input The input view to read code uunits from. | |
/// @param[in] __output The output view to write code points into. | |
/// @param[in] __error_handler The error handler to invoke if encoding fails. | |
/// @param[in, out] __s The necessary state information. For this encoding, the state is empty and means | |
/// very little. | |
/// | |
/// @returns A ztd::text::decode_result object that contains the reconstructed input range, | |
/// reconstructed output range, error handler, and a reference to the passed-in state. | |
/// | |
/// @remarks To the best ability of the implementation, the iterators will be returned untouched (e.g., | |
/// the input models at least a view and a forward_range). If it is not possible, returned ranges may be | |
/// incremented even if an error occurs due to the semantics of any view that models an input_range. | |
////// | |
template <typename _InputRange, typename _OutputRange, typename _ErrorHandler> | |
static constexpr auto decode_one( | |
_InputRange&& __input, _OutputRange&& __output, _ErrorHandler&& __error_handler, state& __s) { | |
using _UInputRange = __txt_detail::__remove_cvref_t<_InputRange>; | |
using _UOutputRange = __txt_detail::__remove_cvref_t<_OutputRange>; | |
using _UErrorHandler = __txt_detail::__remove_cvref_t<_ErrorHandler>; | |
using _Result = __txt_detail::__reconstruct_decode_result_t<_InputRange, _OutputRange, state>; | |
constexpr bool __call_error_handler = !is_ignorable_error_handler_v<_UErrorHandler>; | |
auto __init = __txt_detail::__adl::__adl_begin(__input); | |
auto __inlast = __txt_detail::__adl::__adl_end(__input); | |
if (__init == __inlast) { | |
// an exhausted sequence is fine | |
return _Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::forward<_OutputRange>(__output)), | |
__s, encoding_error::ok); | |
} | |
auto __outit = __txt_detail::__adl::__adl_begin(__output); | |
auto __outlast = __txt_detail::__adl::__adl_end(__output); | |
if constexpr (__call_error_handler) { | |
if (__outit == __outlast) { | |
__self_t __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::insufficient_output_space), | |
::ztd::text::span<code_unit, 0>()); | |
} | |
} | |
else { | |
(void)__outlast; | |
} | |
code_unit __unit = __txt_detail::__dereference(__init); | |
__txt_detail::__advance(__init); | |
if constexpr (__validate_decodable_as && __call_error_handler) { | |
if (static_cast<char32_t>(__unit) > __txt_detail::__last_code_point | |
|| __txt_detail::__is_surrogate(static_cast<char32_t>(__unit))) { | |
__self_t __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::invalid_sequence), | |
::ztd::text::span<code_unit, 1>(::std::addressof(__unit), 1)); | |
} | |
} | |
__txt_detail::__dereference(__outit) = __unit; | |
__txt_detail::__advance(__outit); | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::ok); | |
} | |
////// | |
/// @brief Encodes a single complete unit of information as code units and produces a result with the | |
/// input and output ranges moved past what was successfully read and written; or, produces an error and | |
/// returns the input and output ranges untouched. | |
/// | |
/// @param[in] __input The input view to read code points from. | |
/// @param[in] __output The output view to write code units into. | |
/// @param[in] __error_handler The error handler to invoke if encoding fails. | |
/// @param[in, out] __s The necessary state information. For this encoding, the state is empty and means | |
/// very little. | |
/// | |
/// @returns A ztd::text::encode_result object that contains the reconstructed input range, | |
/// reconstructed output range, error handler, and a reference to the passed-in state. | |
/// | |
/// @remarks To the best ability of the implementation, the iterators will be returned untouched (e.g., | |
/// the input models at least a view and a forward_range). If it is not possible, returned ranges may be | |
/// incremented even if an error occurs due to the semantics of any view that models an input_range. | |
////// | |
template <typename _InputRange, typename _OutputRange, typename _ErrorHandler> | |
static constexpr auto encode_one( | |
_InputRange&& __input, _OutputRange&& __output, _ErrorHandler&& __error_handler, state& __s) { | |
using _UInputRange = __txt_detail::__remove_cvref_t<_InputRange>; | |
using _UOutputRange = __txt_detail::__remove_cvref_t<_OutputRange>; | |
using _UErrorHandler = __txt_detail::__remove_cvref_t<_ErrorHandler>; | |
using _Result = __txt_detail::__reconstruct_encode_result_t<_InputRange, _OutputRange, state>; | |
constexpr bool __call_error_handler = !is_ignorable_error_handler_v<_UErrorHandler>; | |
auto __init = __txt_detail::__adl::__adl_begin(__input); | |
auto __inlast = __txt_detail::__adl::__adl_end(__input); | |
if (__init == __inlast) { | |
// an exhausted sequence is fine | |
return _Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::forward<_OutputRange>(__output)), | |
__s, encoding_error::ok); | |
} | |
auto __outit = __txt_detail::__adl::__adl_begin(__output); | |
auto __outlast = __txt_detail::__adl::__adl_end(__output); | |
if constexpr (__call_error_handler) { | |
if (__outit == __outlast) { | |
__self_t __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::insufficient_output_space), | |
::ztd::text::span<code_point, 0>()); | |
} | |
} | |
else { | |
(void)__outlast; | |
} | |
code_point __points[1] {}; | |
__points[0] = __txt_detail::__dereference(__init); | |
const code_point& __point = __points[0]; | |
__txt_detail::__advance(__init); | |
if constexpr (__validate_decodable_as && __call_error_handler) { | |
if (__point > __txt_detail::__last_code_point || __txt_detail::__is_surrogate(__point)) { | |
__self_t __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::invalid_sequence), | |
::ztd::text::span<code_point, 1>(::std::addressof(__points[0]), 1)); | |
} | |
} | |
__txt_detail::__dereference(__outit) = __point; | |
__txt_detail::__advance(__outit); | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::ok); | |
} | |
}; | |
} // namespace __impl | |
////// | |
/// @addtogroup ztd_text_encodings Encodings | |
/// @{ | |
////// | |
////// | |
/// @brief A UTF-32 Encoding that traffics in, specifically, the desired code unit type provided as a template | |
/// argument. | |
/// | |
/// @tparam _CodeUnit The code unit type to use. | |
/// @tparam _CodeUnit The code point type to use. | |
/// | |
/// @remarks This is a strict UTF-32 implementation that does not allow lone, unpaired surrogates either in or out. | |
////// | |
template <typename _CodeUnit, typename _CodePoint = unicode_code_point> | |
class basic_utf32 : public __impl::__utf32_with<basic_utf32<_CodeUnit, _CodePoint>, _CodeUnit, _CodePoint> { }; | |
////// | |
/// @brief A UTF-32 Encoding that traffics in char32_t. See ztd::text::basic_utf32 for more details. | |
/// | |
////// | |
using utf32 = basic_utf32<char32_t>; | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/utf32.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/encoding_scheme.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/is_bidirectional_encoding.hpp | |
#ifndef ZTD_TEXT_IS_BIDIRECTIONAL_ENCODING | |
#define ZTD_TEXT_IS_BIDIRECTIONAL_ENCODING | |
#include <type_traits> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _Type, typename _Input, typename _Output, typename _State, typename _ErrorHandler> | |
using __detect_encode_backward | |
= decltype(::std::declval<_Type>().encode_one_backward(::std::declval<_Input&>(), | |
::std::declval<_Output&>(), ::std::declval<_ErrorHandler&>(), ::std::declval<_State&>())); | |
template <typename _Type, typename _Input, typename _Output, typename _State, typename _ErrorHandler> | |
using __detect_decode_backward | |
= decltype(::std::declval<_Type&>().decode_one_backward(::std::declval<_Input&>(), | |
::std::declval<_Output&>(), ::std::declval<_ErrorHandler&>(), ::std::declval<_State&>())); | |
} // namespace __txt_detail | |
template <typename _Type, typename _Input, typename _Output, typename _State, typename _ErrorHandler> | |
class is_bidirectional_encoding | |
: public ::std::integral_constant<bool, | |
__txt_detail::__is_detected_v<__txt_detail::__detect_decode_backward, _Type, _Input, _Output, _State, | |
_ErrorHandler> && __txt_detail::__is_detected_v<__txt_detail::__detect_encode_backward, _Type, _Input, _Output, _State, _ErrorHandler>> { | |
}; | |
template <typename _Type, typename _Input, typename _Output, typename _State, typename _ErrorHandler> | |
inline constexpr bool is_bidirectional_encoding_v | |
= is_bidirectional_encoding<_Type, _Input, _Output, _State, _ErrorHandler>::value; | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
#endif // ZTD_TEXT_IS_BIDIRECTIONAL_ENCODING | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/is_bidirectional_encoding.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/is_unicode_encoding.hpp | |
#include <type_traits> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _Type> | |
using __detect_contains_unicode_encoding | |
= decltype(::std::declval<const _Type&>().contains_unicode_encoding()); | |
template <typename _Type> | |
using __detect_is_unicode_encoding = decltype(_Type::is_unicode_encoding::value); | |
template <typename, typename = void> | |
struct __is_unicode_encoding_sfinae : ::std::false_type { }; | |
template <typename _Type> | |
struct __is_unicode_encoding_sfinae<_Type, | |
::std::enable_if_t<__is_detected_v<__detect_is_unicode_encoding, _Type>>> | |
: ::std::integral_constant<bool, _Type::is_unicode_encoding::value> { }; | |
} // namespace __txt_detail | |
////// | |
/// @addtogroup ztd_text_properties Property and Trait Helpers | |
/// | |
/// @{ | |
///// | |
////// | |
/// @brief Checks whether or not the encoding has declared it can handle all of Unicode. | |
/// | |
/// @tparam _Type The encoding type to check. | |
/// | |
/// @remarks If the encoding object does not define is_unicode_encoding, it is assumed to be false (the safest | |
/// default). | |
////// | |
template <typename _Type> | |
class is_unicode_encoding : public __txt_detail::__is_unicode_encoding_sfinae<_Type> { }; | |
////// | |
/// @brief A @c \::value alias for ztd::text::is_unicode_encoding. | |
/// | |
////// | |
template <typename _Type> | |
inline constexpr bool is_unicode_encoding_v = is_unicode_encoding<_Type>::value; | |
////// | |
/// @brief Whether or not the provided encoding is a Unicode encoding. | |
/// | |
/// @param[in] __encoding The encoding to query. | |
/// | |
/// @remarks This function first checks if there is a function called @c contains_unicode_encoding . If it is | |
/// present, then it returns the value of that function directly. Otherwise, it checks if | |
/// ztd::text::is_unicode_encoding_v is true for the provided @p __encoding . If that's the case, then @c true is | |
/// returned. Otherwise, it assumes the encoding is not a Unicode-compatible encoding and returns false. | |
////// | |
template <typename _Encoding> | |
constexpr bool contains_unicode_encoding(const _Encoding& __encoding) noexcept { | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_contains_unicode_encoding, _Encoding>) { | |
return __encoding.contains_unicode_encoding(); | |
} | |
else if constexpr (is_unicode_encoding_v<_Encoding>) { | |
return true; | |
} | |
else { | |
return false; | |
} | |
} | |
////// | |
/// @} | |
///// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/is_unicode_encoding.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/endian.hpp | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_ENDIAN_I_) | |
#include <bit> | |
#else | |
#endif | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_support Support Classes | |
/// @brief Enumeration values, functions, and other types all in support of making the core of the library function | |
/// properly. | |
/// | |
/// @remarks This contains mostly things like enumerations for things that should have already been standardized | |
/// like @c std::endian, @c std::ranges::unbounded_view, and other related things. | |
/// @{ | |
////// | |
#if ZTD_TEXT_IS_OFF(ZTD_TEXT_STD_LIBRARY_ENDIAN_I_) | |
namespace __txt_detail { | |
enum class __endian { | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_PLATFORM_WINDOWS_I_) | |
////// | |
/// @brief Little endian, in which the least significant byte as the first byte value. | |
/// | |
////// | |
little = 0, | |
////// | |
/// @brief Big endian, in which the most significant byte as the first byte value. | |
/// | |
////// | |
big = 1, | |
// clang-format off | |
#if defined(REG_DWORD) | |
#if (REG_DWORD == REG_DWORD_LITTLE_ENDIAN) | |
////// | |
/// @brief Native endian, whcih is big, little, or some implementation-defined ordering (e.g., middle endian). | |
/// If it is big or little, then ``ztd::text::endian::little`` == `ztd::text::endian::big``. | |
////// | |
native = little | |
#else | |
////// | |
/// @brief Native endian, whcih is big, little, or some implementation-defined ordering (e.g., middle endian). | |
/// If it is big or little, then ``ztd::text::endian::little`` == `ztd::text::endian::big``. | |
////// | |
native = big | |
#endif | |
#else | |
////// | |
/// @brief Native endian, whcih is big, little, or some implementation-defined ordering (e.g., middle endian). | |
/// If it is big or little, then ``ztd::text::endian::little`` == `ztd::text::endian::big``. | |
////// | |
native = big | |
#endif | |
// clang-format on | |
#else | |
////// | |
/// @brief Little endian, in which the least significant byte as the first byte value. | |
/// | |
////// | |
little = __ORDER_LITTLE_ENDIAN__, | |
////// | |
/// @brief Big endian, in which the most significant byte as the first byte value. | |
/// | |
////// | |
big = __ORDER_BIG_ENDIAN__, | |
////// | |
/// @brief Native endian, whcih is big, little, or some implementation-defined ordering (e.g., middle | |
/// endian). | |
/// If it is big or little, then ``ztd::text::endian::little`` == `ztd::text::endian::big``. | |
////// | |
native = __BYTE_ORDER__ | |
#endif | |
}; | |
} // namespace __txt_detail | |
#endif | |
////// | |
/// @brief An endian enumeration. | |
/// | |
/// @remarks It may include little, big, or native values. The native value can be the same as the little or big | |
/// values, but if on a middle-endian machine it may be an implementation-defined "middle endian" value that is not | |
/// equal to either little or big (as on the PDP-11). We don't expect many relevant architectures to be using | |
/// middle-endian, though. | |
////// | |
using endian = | |
#if ZTD_TEXT_IS_OFF(ZTD_TEXT_STD_LIBRARY_ENDIAN_I_) | |
__txt_detail::__endian; | |
#else | |
::std::endian; | |
#endif | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/endian.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/word_iterator.hpp | |
#include <cstddef> | |
#include <limits> | |
#include <climits> | |
#include <cstring> | |
#include <memory> | |
#include <optional> | |
#include <iostream> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _Word, typename _Range, bool> | |
class __word_iterator_storage : private __ebco<_Range> { | |
private: | |
using __base_t = __ebco<_Range>; | |
public: | |
constexpr __word_iterator_storage() noexcept(::std::is_nothrow_default_constructible_v<_Range>) | |
: __base_t() { | |
} | |
constexpr __word_iterator_storage(_Range&& __range) noexcept( | |
::std::is_nothrow_move_constructible_v<_Range>) | |
: __base_t(::std::move(__range)) { | |
} | |
constexpr __word_iterator_storage(const _Range& __range) noexcept( | |
::std::is_nothrow_copy_constructible_v<_Range>) | |
: __base_t(__range) { | |
} | |
using __base_t::__get_value; | |
}; | |
template <typename _Word, typename _Range> | |
class __word_iterator_storage<_Word, _Range, true> : private __ebco<_Range> { | |
private: | |
using __base_t = __ebco<_Range>; | |
public: | |
::std::optional<_Word> _M_val; | |
constexpr __word_iterator_storage() noexcept(::std::is_nothrow_default_constructible_v<_Range>) | |
: __base_t() { | |
} | |
constexpr __word_iterator_storage(_Range&& __range) noexcept( | |
::std::is_nothrow_move_constructible_v<_Range>&& ::std::is_nothrow_default_constructible_v<_Word>) | |
: __base_t(::std::move(__range)), _M_val(::std::nullopt) { | |
} | |
constexpr __word_iterator_storage(const _Range& __range) noexcept( | |
::std::is_nothrow_copy_constructible_v<_Range>&& ::std::is_nothrow_default_constructible_v<_Word>) | |
: __base_t(__range), _M_val(::std::nullopt) { | |
} | |
using __base_t::__get_value; | |
}; | |
using __word_sentinel = default_sentinel_t; | |
template <typename _Word, typename _Range, endian _Endian> | |
class __word_iterator | |
: private __word_iterator_storage<_Word, __reconstruct_t<__remove_cvref_t<_Range>>, | |
__is_iterator_input_iterator_v<__range_iterator_t<__reconstruct_t<__remove_cvref_t<_Range>>>>> { | |
private: | |
using _URange = __reconstruct_t<__remove_cvref_t<_Range>>; | |
using __base_iterator = __range_iterator_t<_URange>; | |
using __base_sentinel = __range_sentinel_t<_URange>; | |
using __base_reference = __iterator_reference_t<__base_iterator>; | |
using __maybe_void_base_value_type = __iterator_value_type_t<__base_iterator>; | |
using __base_value_type = ::std::conditional_t< | |
::std::is_void_v< | |
__maybe_void_base_value_type> || !::std::is_arithmetic_v<__maybe_void_base_value_type>, | |
::std::byte, __maybe_void_base_value_type>; | |
using __difference_type = __iterator_difference_type_t<__base_iterator>; | |
using __size_type = __iterator_size_type_t<__base_iterator>; | |
using __value_type = _Word; | |
inline constexpr static bool _IsInput = __is_iterator_input_iterator_v<__base_iterator>; | |
using __base_storage_t = __word_iterator_storage<_Word, _URange, _IsInput>; | |
static_assert(sizeof(__value_type) >= sizeof(__base_value_type), | |
"the 'byte' type selected for the word_iterator must not be larger than the value_type of the " | |
"iterator that it is meant to view"); | |
static_assert((sizeof(__value_type) % sizeof(__base_value_type)) == 0, | |
"the 'byte' type selected for the word_iterator must be evenly divisible by the " | |
"iterator that it is meant to view"); | |
static inline constexpr __size_type __base_values_per_word | |
= sizeof(__value_type) / sizeof(__base_value_type); | |
class __word_reference { | |
public: | |
using value_type = _Word; | |
private: | |
using __underlying_base_value_type = decltype(__any_to_underlying(__base_value_type {})); | |
using __underlying_value_type = decltype(__any_to_underlying(value_type {})); | |
inline static constexpr __underlying_value_type __base_bits_per_element | |
= static_cast<__underlying_value_type>(sizeof(__underlying_base_value_type) * CHAR_BIT); | |
inline static constexpr __underlying_value_type __base_lowest_bit_mask | |
= static_cast<__underlying_value_type>(__ce_ipow(2, __base_bits_per_element) - 1); | |
public: | |
constexpr __word_reference(_URange& __range) noexcept : _M_base_range_ref(__range) { | |
} | |
template <typename _Value, | |
::std::enable_if_t<::std::is_convertible_v<_Value, | |
value_type> && !::std::is_const_v<__base_iterator>>* = nullptr> | |
constexpr __word_reference& operator=(_Value __maybe_val) noexcept { | |
if constexpr (_Endian == endian::native | |
&& (endian::native != endian::big && endian::native != endian::little)) { | |
static_assert(__always_false_constant_v<endian, _Endian>, | |
"read value from byte stream to native endianness that is neither little nor big " | |
"(byte order is impossible to infer from the standard)"); | |
} | |
static_assert(sizeof(value_type) <= (sizeof(__base_value_type) * __base_values_per_word), | |
"the size of the value type must be less than or equal to the array size"); | |
value_type __val = static_cast<value_type>(__maybe_val); | |
__base_value_type __write_storage[__base_values_per_word] {}; | |
auto __write_storage_first = __write_storage + 0; | |
auto __write_storage_last = __write_storage + __base_values_per_word; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED_I_) | |
if (!::std::is_constant_evaluated()) { | |
// just memcpy the data | |
::std::memcpy(__write_storage, ::std::addressof(__val), sizeof(value_type)); | |
} | |
else | |
#endif | |
{ | |
// God's given, handwritten, bit-splittin' | |
// one-way """memcpy""". 😵 | |
__underlying_value_type __bit_value = __any_to_underlying(static_cast<value_type>(__val)); | |
auto __write_storage_it = __write_storage + 0; | |
for (::std::size_t __index = 0; __index < __base_values_per_word; ++__index) { | |
__underlying_value_type __bit_position | |
= static_cast<__underlying_value_type>(__index * __base_bits_per_element); | |
__underlying_base_value_type __shifted_bit_value | |
= static_cast<__underlying_base_value_type>(__bit_value >> __bit_position); | |
*__write_storage_it | |
= static_cast<__base_value_type>(__shifted_bit_value & __base_lowest_bit_mask); | |
++__write_storage_it; | |
} | |
} | |
if constexpr (_Endian != endian::native) { | |
if constexpr (_Endian == endian::big) { | |
__reverse(__write_storage_first, __write_storage_last); | |
} | |
else { | |
// TODO: what about middle endian or some such?? | |
} | |
} | |
auto& __base_range = this->_M_base_range(); | |
if constexpr (_IsInput) { | |
auto __result = __copy(__write_storage_first, __write_storage_last, | |
__adl::__adl_begin(::std::move(__base_range)), | |
__adl::__adl_end(::std::move(__base_range))); | |
this->_M_base_range() | |
= __reconstruct(::std::in_place_type<_URange>, ::std::move(__result.out)); | |
} | |
else { | |
__copy(__write_storage_first, __write_storage_last, __adl::__adl_begin(__base_range), | |
__adl::__adl_end(__base_range)); | |
} | |
return *this; | |
} | |
constexpr value_type value() const noexcept { | |
if constexpr (_Endian == endian::native | |
&& (endian::native != endian::big && endian::native != endian::little)) { | |
static_assert(__always_false_constant_v<endian, _Endian>, | |
"read value from byte stream to native endianness that is neither little nor big " | |
"(byte order is impossible to infer from the standard)"); | |
} | |
__base_value_type __read_storage[__base_values_per_word] {}; | |
__base_value_type* __read_storage_first = __read_storage + 0; | |
::std::size_t __read_storage_size = __adl::__adl_size(__read_storage); | |
value_type __val {}; | |
if constexpr (_IsInput) { | |
// input iterator here (output iterstors cannot be used) | |
// to do this kind of work | |
// use iterator directly, re-update it when we are done | |
// to prevent failure | |
auto& __base_range = this->_M_base_range(); | |
auto __result = __copy_n_unsafe(__adl::__adl_begin(::std::move(__base_range)), | |
__read_storage_size, __read_storage_first); | |
this->_M_base_range() = __reconstruct(::std::in_place_type<_URange>, | |
::std::move(__result.in).begin().base(), ::std::move(__base_range).end()); | |
} | |
else { | |
// prevent feed-updating iterator through usage here | |
// just copy-and-use | |
auto __base_it_copy = this->_M_base_range().begin(); | |
[[maybe_unused]] auto __result = __copy_n_unsafe( | |
::std::move(__base_it_copy), __read_storage_size, __read_storage_first); | |
} | |
if constexpr (_Endian == endian::big) { | |
if constexpr ((sizeof(value_type) * CHAR_BIT) > 8) { | |
__base_value_type* __read_storage_last = __read_storage + __base_values_per_word; | |
__reverse(__read_storage_first, __read_storage_last); | |
} | |
} | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED_I_) | |
if (!::std::is_constant_evaluated()) | |
#else | |
if (false) | |
#endif | |
{ | |
::std::size_t __read_memory_storage_size | |
= __read_storage_size * sizeof(__base_value_type); | |
::std::memcpy(::std::addressof(__val), __read_storage_first, __read_memory_storage_size); | |
} | |
else { | |
// God's given, handwritten, bit-fusin' | |
// one-way """memcpy""". 😵 | |
for (::std::size_t __index = 0; __index < __base_values_per_word; ++__index) { | |
__underlying_value_type __bit_value = static_cast<__underlying_value_type>( | |
__any_to_underlying(__read_storage[__index])); | |
__underlying_value_type __bit_position | |
= static_cast<__underlying_value_type>(__index * __base_bits_per_element); | |
__underlying_value_type __shifted_bit_value = (__bit_value << __bit_position); | |
__val |= __shifted_bit_value; | |
} | |
} | |
return static_cast<value_type>(__val); | |
} | |
constexpr operator value_type() const noexcept { | |
return this->value(); | |
} | |
private: | |
_URange& _M_base_range() const noexcept { | |
return this->_M_base_range_ref.get(); | |
} | |
::ztd::text::reference_wrapper<_URange> _M_base_range_ref; | |
}; | |
public: | |
using range_type = _URange; | |
using iterator = __base_iterator; | |
using sentinel = __base_sentinel; | |
using iterator_category = __iterator_category_t<__base_iterator>; | |
using iterator_concept = __iterator_concept_t<__base_iterator>; | |
using difference_type = __difference_type; | |
using pointer = _Word*; | |
using value_type = __value_type; | |
using reference = ::std::conditional_t<_IsInput, value_type&, __word_reference>; | |
using const_reference = ::std::conditional_t<_IsInput, const value_type&, __word_reference>; | |
private: | |
static constexpr bool _S_deref_noexcept() noexcept { | |
if constexpr (_IsInput) { | |
return true; | |
} | |
else { | |
return noexcept(reference(::std::declval<range_type&>())); | |
} | |
} | |
static constexpr bool _S_const_deref_noexcept() noexcept { | |
if constexpr (_IsInput) { | |
return true; | |
} | |
else { | |
return noexcept(const_reference(::std::declval<range_type&>())); | |
} | |
} | |
static constexpr bool _S_copy_noexcept() noexcept { | |
return ::std::is_nothrow_copy_constructible_v<iterator>; | |
} | |
static constexpr bool _S_recede_noexcept() noexcept { | |
return noexcept(--::std::declval<iterator&>()); | |
} | |
static constexpr bool _S_advance_noexcept() noexcept { | |
return noexcept(++::std::declval<iterator&>()); | |
} | |
public: | |
constexpr __word_iterator() = default; | |
constexpr __word_iterator(const range_type& __base_range) noexcept( | |
::std::is_nothrow_constructible_v<__base_storage_t, const range_type&>) | |
: __base_storage_t(__base_range) { | |
} | |
constexpr __word_iterator(range_type&& __base_range) noexcept( | |
::std::is_nothrow_constructible_v<__base_storage_t, range_type&&>) | |
: __base_storage_t(::std::move(__base_range)) { | |
} | |
__word_iterator(const __word_iterator&) = default; | |
__word_iterator(__word_iterator&&) = default; | |
__word_iterator& operator=(const __word_iterator&) = default; | |
__word_iterator& operator=(__word_iterator&&) = default; | |
constexpr range_type range() & noexcept(::std::is_copy_constructible_v<range_type> | |
? ::std::is_nothrow_copy_constructible_v<range_type> | |
: ::std::is_nothrow_move_constructible_v<range_type>) { | |
if constexpr (::std::is_copy_constructible_v<range_type>) { | |
return this->__base_storage_t::__get_value(); | |
} | |
else { | |
return ::std::move(this->__base_storage_t::__get_value()); | |
} | |
} | |
constexpr range_type range() const& noexcept(::std::is_nothrow_copy_constructible_v<range_type>) { | |
return this->__base_storage_t::__get_value(); | |
} | |
constexpr range_type range() && noexcept(::std::is_nothrow_move_constructible_v<range_type>) { | |
return ::std::move(this->__base_storage_t::__get_value()); | |
} | |
constexpr __word_iterator operator++(int) const noexcept(_S_copy_noexcept() && _S_advance_noexcept()) { | |
auto __copy = *this; | |
++__copy; | |
return __copy; | |
} | |
constexpr __word_iterator& operator++() noexcept(_S_advance_noexcept()) { | |
if constexpr (_IsInput) { | |
// force read on next dereference | |
this->__base_storage_t::_M_val = ::std::nullopt; | |
} | |
else { | |
auto __first_it = __adl::__adl_begin(::std::move(this->__base_storage_t::__get_value())); | |
auto __last_it = __adl::__adl_end(::std::move(this->__base_storage_t::__get_value())); | |
__advance(__first_it, __base_values_per_word); | |
this->__base_storage_t::__get_value() = __reconstruct( | |
::std::in_place_type<_URange>, ::std::move(__first_it), ::std::move(__last_it)); | |
} | |
return *this; | |
} | |
template <typename _Dummy = range_type> | |
constexpr ::std::enable_if_t< | |
__is_range_iterator_concept_or_better_v<::std::bidirectional_iterator_tag, _Dummy>, __word_iterator> | |
operator--(int) const noexcept(_S_copy_noexcept() && _S_recede_noexcept()) { | |
auto __copy = *this; | |
--__copy; | |
return __copy; | |
} | |
template <typename _Dummy = range_type> | |
constexpr ::std::enable_if_t< | |
__is_range_iterator_concept_or_better_v<::std::bidirectional_iterator_tag, _Dummy>, | |
__word_iterator&> | |
operator--() noexcept { | |
__recede(this->__base_storage_t::__get_value(), __base_values_per_word); | |
return *this; | |
} | |
template <typename _Dummy = range_type> | |
constexpr ::std::enable_if_t< | |
__is_range_iterator_concept_or_better_v<::std::random_access_iterator_tag, _Dummy>, __word_iterator> | |
operator+(difference_type __by) const noexcept(_S_copy_noexcept() && _S_advance_noexcept()) { | |
auto __copy = *this; | |
__copy += __by; | |
return __copy; | |
} | |
template <typename _Dummy = range_type> | |
constexpr ::std::enable_if_t< | |
__is_range_iterator_concept_or_better_v<::std::random_access_iterator_tag, _Dummy>, | |
__word_iterator&> | |
operator+=(difference_type __by) noexcept(_S_advance_noexcept()) { | |
if (__by < static_cast<difference_type>(0)) { | |
return this->operator+=(-__by); | |
} | |
auto __first_it = __adl::__adl_begin(::std::move(this->__base_storage_t::__get_value())); | |
auto __last_it = __adl::__adl_end(::std::move(this->__base_storage_t::__get_value())); | |
__advance(__first_it, __base_values_per_word * __by); | |
this->__base_storage_t::__get_value() = __reconstruct( | |
::std::in_place_type<_URange>, ::std::move(__first_it), ::std::move(__last_it)); | |
return *this; | |
} | |
template <typename _Dummy = range_type> | |
constexpr ::std::enable_if_t< | |
__is_range_iterator_concept_or_better_v<::std::random_access_iterator_tag, _Dummy>, difference_type> | |
operator-(const __word_iterator& __right) const noexcept { | |
difference_type __dist | |
= this->__base_storage_t::__get_value() - __right.__base_storage_t::__get_value(); | |
return static_cast<difference_type>(__dist * __base_values_per_word); | |
} | |
template <typename _Dummy = range_type> | |
constexpr ::std::enable_if_t< | |
__is_range_iterator_concept_or_better_v<::std::random_access_iterator_tag, _Dummy>, __word_iterator> | |
operator-(difference_type __by) const noexcept(_S_copy_noexcept() && _S_recede_noexcept()) { | |
auto __copy = *this; | |
__copy -= __by; | |
return __copy; | |
} | |
template <typename _Dummy = range_type> | |
constexpr ::std::enable_if_t< | |
__is_range_iterator_concept_or_better_v<::std::random_access_iterator_tag, _Dummy>, | |
__word_iterator&> | |
operator-=(difference_type __by) noexcept(_S_recede_noexcept()) { | |
if (__by < static_cast<difference_type>(0)) { | |
return this->operator+=(-__by); | |
} | |
auto __first_it = __adl::__adl_begin(::std::move(this->__base_storage_t::__get_value())); | |
auto __last_it = __adl::__adl_end(::std::move(this->__base_storage_t::__get_value())); | |
__recede(__first_it, __base_values_per_word * __by); | |
this->__base_storage_t::__get_value() = __reconstruct( | |
::std::in_place_type<_URange>, ::std::move(__first_it), ::std::move(__last_it)); | |
return *this; | |
} | |
template <typename _Dummy = range_type> | |
constexpr ::std::enable_if_t< | |
__is_range_iterator_concept_or_better_v<::std::random_access_iterator_tag, _Dummy>, reference> | |
operator[](difference_type __index) noexcept(_S_copy_noexcept() && _S_advance_noexcept()) { | |
auto __copy = *this; | |
__copy += __index; | |
return *__copy; | |
} | |
template <typename _Dummy = range_type> | |
constexpr ::std::enable_if_t< | |
__is_range_iterator_concept_or_better_v<::std::random_access_iterator_tag, _Dummy>, const_reference> | |
operator[](difference_type __index) const noexcept(_S_copy_noexcept() && _S_advance_noexcept()) { | |
auto __copy = *this; | |
__copy += __index; | |
return *__copy; | |
} | |
constexpr reference operator*() noexcept(_S_deref_noexcept()) { | |
if constexpr (_IsInput) { | |
if (this->__base_storage_t::_M_val == ::std::nullopt) { | |
this->_M_read_one(); | |
} | |
return *this->__base_storage_t::_M_val; | |
} | |
else { | |
return reference(this->__base_storage_t::__get_value()); | |
} | |
} | |
constexpr const_reference operator*() const noexcept(_S_const_deref_noexcept()) { | |
if constexpr (_IsInput) { | |
if (this->__base_storage_t::_M_val == ::std::nullopt) { | |
const_cast<__word_iterator*>(this)->_M_read_one(); | |
} | |
return *this->__base_storage_t::_M_val; | |
} | |
else { | |
return const_reference(this->__base_storage_t::__get_value()); | |
} | |
} | |
friend constexpr bool operator==(const __word_iterator& __left, const __word_sentinel&) noexcept( | |
noexcept(__left._M_base_is_empty())) { | |
return __left._M_base_is_empty(); | |
} | |
friend constexpr bool operator!=(const __word_iterator& __left, const __word_sentinel&) noexcept( | |
noexcept(!__left._M_base_is_empty())) { | |
return !__left._M_base_is_empty(); | |
} | |
friend constexpr bool operator==(const __word_sentinel& __sen, const __word_iterator& __left) noexcept( | |
noexcept(__left == __sen)) { | |
return __left == __sen; | |
} | |
friend constexpr bool operator!=(const __word_sentinel& __sen, const __word_iterator& __left) noexcept( | |
noexcept(__left != __sen)) { | |
return __left != __sen; | |
} | |
private: | |
constexpr void _M_read_one() noexcept(_S_deref_noexcept()) { | |
if constexpr (_IsInput) { | |
_Word __read_word = __word_reference(this->__base_storage_t::__get_value()); | |
this->__base_storage_t::_M_val = ::std::optional<_Word>(__read_word); | |
} | |
} | |
constexpr bool _M_base_is_empty() const noexcept { | |
if constexpr (__is_detected_v<__detect_adl_empty, range_type>) { | |
return __adl::__adl_empty(this->__base_storage_t::__get_value()); | |
} | |
else { | |
return __adl::__adl_begin(this->__base_storage_t::__get_value()) | |
== __adl::__adl_end(this->__base_storage_t::__get_value()); | |
} | |
} | |
}; | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/word_iterator.hpp | |
#include <optional> | |
#include <cstddef> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _Byte, typename _UInputRange, typename _UOutputRange, typename _ErrorHandler> | |
class __scheme_decode_handler { | |
private: | |
::ztd::text::reference_wrapper<_ErrorHandler> _M_handler; | |
public: | |
constexpr __scheme_decode_handler(_ErrorHandler& __handler) noexcept : _M_handler(__handler) { | |
} | |
template <typename _Encoding, typename _Input, typename _Output, typename _State, typename _Progress> | |
constexpr auto operator()(const _Encoding& __encoding, decode_result<_Input, _Output, _State> __result, | |
const _Progress& __progress) const noexcept(::std::is_nothrow_invocable_v<_ErrorHandler&, | |
const _Encoding&, decode_result<_Input, _Output, _State>, const _Progress&>) { | |
if constexpr (::std::is_invocable_v<_ErrorHandler&, const _Encoding, | |
decode_result<_Input, _Output, _State>, _Progress>) { | |
return this->_M_handler.get()(__encoding, ::std::move(__result), __progress); | |
} | |
else { | |
using _ProgressPointer = __txt_detail::__range_pointer_t<_Progress>; | |
using _ProgressWord = __txt_detail::__range_value_type_t<_Progress>; | |
_Byte* __byte_progress_data | |
= reinterpret_cast<_Byte*>(const_cast<_ProgressPointer>(__progress.data())); | |
auto __byte_progress_size | |
= (__txt_detail::__adl::__adl_size(__progress) * sizeof(_ProgressWord)) / (sizeof(_Byte)); | |
::ztd::text::span<_Byte> __byte_progress(__byte_progress_data, __byte_progress_size); | |
return this->_M_handler.get()(__encoding, ::std::move(__result), __byte_progress); | |
} | |
} | |
}; | |
template <typename _Super, bool = is_code_units_maybe_replaceable_v<typename _Super::encoding_type>> | |
class __maybe_replacement_code_units_es { }; | |
template <typename _Super> | |
class __maybe_replacement_code_units_es<_Super, true> { | |
private: | |
const _Super& _M_super() const noexcept { | |
return static_cast<const _Super&>(*this); | |
} | |
public: | |
constexpr auto maybe_replacement_code_units() const noexcept { | |
using _OriginalCodeUnit = code_unit_t<typename _Super::encoding_type>; | |
using _CodeUnit = typename _Super::code_unit; | |
decltype(auto) __maybe_original = this->_M_super().base().maybe_replacement_code_units(); | |
if constexpr (::std::is_same_v<_OriginalCodeUnit, _CodeUnit>) { | |
return __maybe_original; | |
} | |
else { | |
using _OriginalSpan = ::ztd::text::span<const _OriginalCodeUnit>; | |
using _TransformedSpan = ::ztd::text::span<const _CodeUnit>; | |
using _MaybeTransformedSpan = ::std::optional<_TransformedSpan>; | |
if (!__maybe_original) { | |
return _MaybeTransformedSpan(::std::nullopt); | |
} | |
decltype(auto) __original = *::std::forward<decltype(__maybe_original)>(__maybe_original); | |
_OriginalSpan __guaranteed_code_unit_view(__original); | |
// transform into proper type... | |
auto __transformed_ptr | |
= reinterpret_cast<const _CodeUnit*>(__guaranteed_code_unit_view.data()); | |
auto __transformed_size = (__guaranteed_code_unit_view.size() * sizeof(_OriginalCodeUnit)) | |
/ sizeof(const _CodeUnit); | |
return _MaybeTransformedSpan(::std::in_place, __transformed_ptr, __transformed_size); | |
} | |
} | |
}; | |
template <typename _Super, bool = is_code_points_maybe_replaceable_v<typename _Super::encoding_type>> | |
class __maybe_replacement_code_points_es { }; | |
template <typename _Super> | |
class __maybe_replacement_code_points_es<_Super, true> { | |
private: | |
const _Super& _M_super() const noexcept { | |
return static_cast<const _Super&>(*this); | |
} | |
public: | |
constexpr auto maybe_replacement_code_points() const noexcept { | |
using _OriginalCodePoint = code_point_t<typename _Super::encoding_type>; | |
using _CodePoint = typename _Super::code_point; | |
decltype(auto) __maybe_original = this->_M_super().base().maybe_replacement_code_points(); | |
if constexpr (::std::is_same_v<_OriginalCodePoint, _CodePoint>) { | |
return __maybe_original; | |
} | |
else { | |
using _OriginalSpan = ::ztd::text::span<const _OriginalCodePoint>; | |
using _TransformedSpan = ::ztd::text::span<const _CodePoint>; | |
using _MaybeTransformedSpan = ::std::optional<_TransformedSpan>; | |
if (!__maybe_original) { | |
return _MaybeTransformedSpan(::std::nullopt); | |
} | |
decltype(auto) __original = *::std::forward<decltype(__maybe_original)>(__maybe_original); | |
_OriginalSpan __guaranteed_code_point_view(__original); | |
// transform into proper type... | |
auto __transformed_ptr | |
= reinterpret_cast<const _CodePoint*>(__guaranteed_code_point_view.data()); | |
auto __transformed_size = (__guaranteed_code_point_view.size() * sizeof(_OriginalCodePoint)) | |
/ sizeof(const _CodePoint); | |
return _MaybeTransformedSpan(::std::in_place, __transformed_ptr, __transformed_size); | |
} | |
} | |
}; | |
template <typename _Super, typename _Encoding, typename = void> | |
class __is_unicode_encoding_es { }; | |
template <typename _Super, typename _Encoding> | |
class __is_unicode_encoding_es<_Super, _Encoding, | |
::std::enable_if_t<__is_detected_v<__detect_is_unicode_encoding, _Encoding>>> { | |
public: | |
using is_unicode_encoding = ::std::integral_constant<bool, is_unicode_encoding_v<_Encoding>>; | |
}; | |
} // namespace __txt_detail | |
////// | |
/// @addtogroup ztd_text_encodings Encodings | |
/// @{ | |
////// | |
////// | |
/// @brief Decomposes the provided Encoding type into a specific endianness (big, little, or native) to allow for a | |
/// single encoding type to be viewed in different ways. | |
/// | |
/// @tparam _Encoding The encoding type. | |
/// @tparam _Endian The endianess to use. Defaults to ztd::text::endian::native. | |
/// @tparam _Byte The byte type to use. Defaults to ``std::byte``. | |
/// | |
/// @remarks For example, this can be used to construct a Big Endian UTF-16 by using | |
/// ``encoding_scheme<ztd::text::utf16, ztd::text::endian::big>``. It can be made interopable with ``unsigned | |
/// char`` buffers rather than ``std::byte`` buffers by doing: ``ztd::text::encoding_scheme<ztd::text::utf32, | |
/// ztd::text::endian::native, unsigned char>``. | |
////// | |
template <typename _Encoding, endian _Endian = endian::native, typename _Byte = ::std::byte> | |
class encoding_scheme : public __txt_detail::__is_unicode_encoding_es<encoding_scheme<_Encoding, _Endian, _Byte>, | |
__txt_detail::__remove_cvref_t<__txt_detail::__unwrap_t<_Encoding>>>, | |
private __txt_detail::__ebco<_Encoding> { | |
private: | |
using __base_t = __txt_detail::__ebco<_Encoding>; | |
using _UBaseEncoding = __txt_detail::__remove_cvref_t<__txt_detail::__unwrap_t<_Encoding>>; | |
using _BaseCodeUnit = code_unit_t<_UBaseEncoding>; | |
public: | |
/////// | |
/// @brief The encoding type that this scheme wraps. | |
/// | |
/////// | |
using encoding_type = _Encoding; | |
////// | |
/// @brief The individual units that result from a decode operation or as used as input to an encode | |
/// operation. For most encodings, this is going to be a Unicode Code Point or a Unicode Scalar Value. | |
////// | |
using code_point = code_point_t<_UBaseEncoding>; | |
/////// | |
/// @brief The individual units that result from an encode operation or are used as input to a decode | |
/// operation. | |
/// | |
/// @remarks Typically, this type is usually always some kind of byte type (unsigned char or std::byte or | |
/// other ``sizeof(obj) == 1`` type). | |
/////// | |
using code_unit = _Byte; | |
////// | |
/// @brief The state that can be used between calls to the decode function. | |
/// | |
/// @remarks Even if the underlying encoding only has a single @c state type, we need to separate the two out | |
/// in order to generically handle all encodings. Therefore, the encoding_scheme will always have both | |
/// @c encode_state and @c decode_state. | |
////// | |
using decode_state = decode_state_t<_UBaseEncoding>; | |
////// | |
/// @brief The state that can be used between calls to the encode function. | |
/// | |
/// @remarks Even if the underlying encoding only has a single @c state type, we need to separate the two out | |
/// in order to generically handle all encodings. Therefore, the encoding_scheme will always have both | |
/// @c encode_state and @c decode_state. | |
////// | |
using encode_state = encode_state_t<_UBaseEncoding>; | |
////// | |
/// @brief Whether or not the encode operation can process all forms of input into code point values. | |
/// | |
/// @remarks Defers to what the underlying @c encoding_type does. | |
////// | |
using is_encode_injective = ::std::integral_constant<bool, is_encode_injective_v<_UBaseEncoding>>; | |
////// | |
/// @brief Whether or not the decode operation can process all forms of input into code point values. | |
/// | |
/// @remarks Defers to what the underlying @c encoding_type does. | |
////// | |
using is_decode_injective = ::std::integral_constant<bool, is_decode_injective_v<_UBaseEncoding>>; | |
////// | |
/// @brief The maximum number of code points a single complete operation of decoding can produce. This is | |
/// 1 for all Unicode Transformation Format (UTF) encodings. | |
////// | |
inline static constexpr const ::std::size_t max_code_points = max_code_points_v<_UBaseEncoding>; | |
////// | |
/// @brief The maximum code units a single complete operation of encoding can produce. | |
/// | |
////// | |
inline static constexpr const ::std::size_t max_code_units | |
= (max_code_units_v<_UBaseEncoding> * sizeof(_BaseCodeUnit)) / (sizeof(_Byte)); | |
////// | |
/// @brief Constructs a ztd::text::encoding_scheme with the given arguments. | |
/// | |
////// | |
using __base_t::__base_t; | |
////// | |
/// @brief Retrives the underlying encoding object. | |
/// | |
/// @returns An l-value reference to the encoding object. | |
////// | |
constexpr encoding_type& base() & noexcept { | |
return this->__base_t::__get_value(); | |
} | |
////// | |
/// @brief Retrives the underlying encoding object. | |
/// | |
/// @returns An l-value reference to the encoding object. | |
////// | |
constexpr const encoding_type& base() const& noexcept { | |
return this->__base_t::__get_value(); | |
} | |
////// | |
/// @brief Retrives the underlying encoding object. | |
/// | |
/// @returns An l-value reference to the encoding object. | |
////// | |
constexpr encoding_type&& base() && noexcept { | |
return this->__base_t::__get_value(); | |
} | |
////// | |
/// @brief Returns, the desired replacement code units to use. | |
/// | |
/// @remarks This is only callable if the function call exists on the wrapped encoding. It is broken down into | |
/// a contiguous view type formulated from bytes if the wrapped code unit types do not match. | |
////// | |
template <typename _Unused = encoding_type, | |
::std::enable_if_t<is_code_units_replaceable_v<_Unused>>* = nullptr> | |
constexpr decltype(auto) replacement_code_units() const noexcept { | |
using _OriginalCodeUnit = code_unit_t<encoding_type>; | |
decltype(auto) __original = this->base().replacement_code_units(); | |
if constexpr (::std::is_same_v<_OriginalCodeUnit, code_unit>) { | |
return __original; | |
} | |
else { | |
using _OriginalSpan = ::ztd::text::span<const _OriginalCodeUnit>; | |
using _TransformedSpan = ::ztd::text::span<const code_unit>; | |
_OriginalSpan __guaranteed_code_unit_view(__original); | |
// transform into proper type... | |
auto __transformed_ptr = reinterpret_cast<const code_unit*>(__guaranteed_code_unit_view.data()); | |
auto __transformed_size | |
= (__guaranteed_code_unit_view.size() * sizeof(_OriginalCodeUnit)) / sizeof(const code_unit); | |
return _TransformedSpan(__transformed_ptr, __transformed_size); | |
} | |
} | |
////// | |
/// @brief Returns the desired replacement code points to use. | |
/// | |
/// @remarks Is only callable if the function call exists on the wrapped encoding. | |
////// | |
template <typename _Unused = encoding_type, | |
::std::enable_if_t<is_code_points_replaceable_v<_Unused>>* = nullptr> | |
constexpr decltype(auto) replacement_code_points() const noexcept { | |
return this->base().replacement_code_points(); | |
} | |
////// | |
/// @brief Returns the desired replacement code units to use, or an empty optional-like type if there is | |
/// nothing present. | |
/// | |
/// @remarks This is only callable if the function call exists on the wrapped encoding. It is broken down into | |
/// a contiguous view type formulated from bytes if the wrapped code unit types do not match. | |
////// | |
template <typename _Unused = encoding_type, | |
::std::enable_if_t<is_code_units_maybe_replaceable_v<_Unused>>* = nullptr> | |
constexpr decltype(auto) maybe_replacement_code_units() const noexcept { | |
using _OriginalCodeUnit = code_unit_t<encoding_type>; | |
decltype(auto) __maybe_original = this->base().maybe_replacement_code_units(); | |
if constexpr (::std::is_same_v<_OriginalCodeUnit, code_unit>) { | |
return __maybe_original; | |
} | |
else { | |
using _OriginalSpan = ::ztd::text::span<const _OriginalCodeUnit>; | |
using _TransformedSpan = ::ztd::text::span<const code_unit>; | |
if (!__maybe_original) { | |
return ::std::optional<_TransformedSpan>(::std::nullopt); | |
} | |
decltype(auto) __original = *__maybe_original; | |
_OriginalSpan __guaranteed_code_unit_view(__original); | |
// transform into proper type... | |
auto __transformed_ptr = reinterpret_cast<const code_unit*>(__guaranteed_code_unit_view.data()); | |
auto __transformed_size | |
= (__guaranteed_code_unit_view.size() * sizeof(_OriginalCodeUnit)) / sizeof(const code_unit); | |
return _TransformedSpan(__transformed_ptr, __transformed_size); | |
} | |
} | |
////// | |
/// @brief Returns the desired replacement code units to use. | |
/// | |
/// @remarks This Is only callable if the function call exists on the wrapped encoding. | |
////// | |
template <typename _Unused = encoding_type, | |
::std::enable_if_t<is_code_points_maybe_replaceable_v<_Unused>>* = nullptr> | |
constexpr decltype(auto) maybe_replacement_code_points() const noexcept { | |
return this->base().maybe_replacement_code_points(); | |
} | |
////// | |
/// @brief Whether or not this encoding is some form of Unicode encoding. | |
/// | |
////// | |
constexpr bool contains_unicode_encoding() const noexcept { | |
return ::ztd::text::contains_unicode_encoding(this->base()); | |
} | |
////// | |
/// @brief Decodes a single complete unit of information as code points and produces a result with the | |
/// input and output ranges moved past what was successfully read and written; or, produces an error and | |
/// returns the input and output ranges untouched. | |
/// | |
/// @param[in] __input The input view to read code uunits from. | |
/// @param[in] __output The output view to write code points into. | |
/// @param[in] __error_handler The error handler to invoke if encoding fails. | |
/// @param[in, out] __s The necessary state information. For this encoding, the state is empty and means | |
/// very little. | |
/// | |
/// @returns A ztd::text::decode_result object that contains the reconstructed input range, | |
/// reconstructed output range, error handler, and a reference to the passed-in state. | |
/// | |
/// @remarks To the best ability of the implementation, the iterators will be returned untouched (e.g., | |
/// the input models at least a view and a forward_range). If it is not possible, returned ranges may be | |
/// incremented even if an error occurs due to the semantics of any view that models an input_range. | |
////// | |
template <typename _InputRange, typename _OutputRange, typename _ErrorHandler> | |
constexpr auto decode_one(_InputRange&& __input, _OutputRange&& __output, _ErrorHandler&& __error_handler, | |
decode_state& __s) const { | |
using _UInputRange = __txt_detail::__remove_cvref_t<_InputRange>; | |
using _UOutputRange = __txt_detail::__remove_cvref_t<_OutputRange>; | |
using _UErrorHandler = __txt_detail::__remove_cvref_t<_ErrorHandler>; | |
using _Result = __txt_detail::__reconstruct_decode_result_t<_InputRange, _OutputRange, decode_state>; | |
using _InByteIt = __txt_detail::__word_iterator<_BaseCodeUnit, _UInputRange, _Endian>; | |
using _InByteSen = __txt_detail::__word_sentinel; | |
subrange<_InByteIt, _InByteSen> __inbytes(_InByteIt(::std::forward<_InputRange>(__input)), _InByteSen()); | |
__txt_detail::__scheme_decode_handler<_Byte, _UInputRange, _UOutputRange, _UErrorHandler> | |
__scheme_handler(__error_handler); | |
auto __result = this->base().decode_one( | |
::std::move(__inbytes), ::std::forward<_OutputRange>(__output), __scheme_handler, __s); | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__result.input).begin().range()), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, ::std::move(__result.output)), __s, | |
__result.error_code, __result.handled_errors); | |
} | |
////// | |
/// @brief Encodes a single complete unit of information as code units and produces a result with the | |
/// input and output ranges moved past what was successfully read and written; or, produces an error and | |
/// returns the input and output ranges untouched. | |
/// | |
/// @param[in] __input The input view to read code points from. | |
/// @param[in] __output The output view to write code units into. | |
/// @param[in] __error_handler The error handler to invoke if encoding fails. | |
/// @param[in, out] __s The necessary state information. For this encoding, the state is empty and means | |
/// very little. | |
/// | |
/// @returns A ztd::text::encode_result object that contains the reconstructed input range, | |
/// reconstructed output range, error handler, and a reference to the passed-in state. | |
/// | |
/// @remarks To the best ability of the implementation, the iterators will be returned untouched (e.g., | |
/// the input models at least a view and a forward_range). If it is not possible, returned ranges may be | |
/// incremented even if an error occurs due to the semantics of any view that models an input_range. | |
////// | |
template <typename _InputRange, typename _OutputRange, typename _ErrorHandler> | |
constexpr auto encode_one(_InputRange&& __input, _OutputRange&& __output, _ErrorHandler&& __error_handler, | |
encode_state& __s) const { | |
using _UInputRange = __txt_detail::__remove_cvref_t<_InputRange>; | |
using _UOutputRange = __txt_detail::__remove_cvref_t<_OutputRange>; | |
using _Result = __txt_detail::__reconstruct_encode_result_t<_InputRange, _OutputRange, encode_state>; | |
using _OutByteIt = __txt_detail::__word_iterator<_BaseCodeUnit, _UOutputRange, _Endian>; | |
using _OutByteSen = __txt_detail::__word_sentinel; | |
subrange<_OutByteIt, _OutByteSen> __outwords( | |
_OutByteIt(::std::forward<_OutputRange>(__output)), _OutByteSen()); | |
auto __result = this->base().encode_one(::std::forward<_InputRange>(__input), __outwords, | |
::std::forward<_ErrorHandler>(__error_handler), __s); | |
return _Result( | |
__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, ::std::move(__result.input)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::move(__result.output).begin().range()), | |
__s, __result.error_code, __result.handled_errors); | |
} | |
}; | |
////// | |
/// @brief A UTF-16 encoding, in Little Endian format, with inputs as a sequence of bytes. | |
/// | |
/// @tparam _Byte The byte type to use. Typically, this is @c std::byte or @c uchar. | |
////// | |
template <typename _Byte> | |
using basic_utf16_le = encoding_scheme<utf16, endian::little, _Byte>; | |
////// | |
/// @brief A UTF-16 encoding, in Big Endian format, with inputs as a sequence of bytes. | |
/// | |
/// @tparam _Byte The byte type to use. Typically, this is @c std::byte or <tt>unsigned char</tt>. | |
////// | |
template <typename _Byte> | |
using basic_utf16_be = encoding_scheme<utf16, endian::big, _Byte>; | |
////// | |
/// @brief A UTF-16 encoding, in Native Endian format, with inputs as a sequence of bytes. | |
/// | |
/// @tparam _Byte The byte type to use. Typically, this is @c std::byte or <tt>unsigned char</tt>. | |
////// | |
template <typename _Byte> | |
using basic_utf16_ne = encoding_scheme<utf16, endian::native, _Byte>; | |
////// | |
/// @brief A UTF-16 encoding, in Little Endian format, with inputs as a sequence of bytes. | |
/// | |
////// | |
using utf16_le = basic_utf16_le<::std::byte>; | |
////// | |
/// @brief A UTF-16 encoding, in Big Endian format, with inputs as a sequence of bytes. | |
/// | |
////// | |
using utf16_be = basic_utf16_be<::std::byte>; | |
////// | |
/// @brief A UTF-16 encoding, in Native Endian format, with inputs as a sequence of bytes. | |
/// | |
////// | |
using utf16_ne = basic_utf16_ne<::std::byte>; | |
////// | |
/// @brief A UTF-32 encoding, in Little Endian format, with inputs as a sequence of bytes. | |
/// | |
/// @tparam _Byte The byte type to use. Typically, this is @c std::byte or <tt>unsigned char</tt> . | |
////// | |
template <typename _Byte> | |
using basic_utf32_le = encoding_scheme<utf32, endian::little, _Byte>; | |
////// | |
/// @brief A UTF-32 encoding, in Big Endian format, with inputs as a sequence of bytes. | |
/// | |
/// @tparam _Byte The byte type to use. Typically, this is @c std::byte or <tt>unsigned char</tt> . | |
////// | |
template <typename _Byte> | |
using basic_utf32_be = encoding_scheme<utf32, endian::big, _Byte>; | |
////// | |
/// @brief A UTF-32 encoding, in Native Endian format, with inputs as a sequence of bytes. | |
/// | |
/// @tparam _Byte The byte type to use. Typically, this is @c std::byte or <tt>unsigned char</tt> . | |
////// | |
template <typename _Byte> | |
using basic_utf32_ne = encoding_scheme<utf32, endian::native, _Byte>; | |
////// | |
/// @brief A UTF-32 encoding, in Little Endian format, with inputs as a sequence of bytes. | |
/// | |
////// | |
using utf32_le = basic_utf32_le<::std::byte>; | |
////// | |
/// @brief A UTF-32 encoding, in Big Endian format, with inputs as a sequence of bytes. | |
/// | |
////// | |
using utf32_be = basic_utf32_be<::std::byte>; | |
////// | |
/// @brief A UTF-32 encoding, in Big Endian format, with inputs as a sequence of bytes. | |
/// | |
////// | |
using utf32_ne = basic_utf32_ne<::std::byte>; | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/encoding_scheme.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/ascii.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/replacement.hpp | |
#include <array> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _CharType> | |
inline constexpr ::std::array<_CharType, 1> __question_mark_replacement_units { { static_cast<_CharType>( | |
__ascii_replacement) } }; | |
template <typename _CharType> | |
inline constexpr ::std::array<_CharType, 1> __0xfffd_replacement_units { { static_cast<_CharType>( | |
__replacement) } }; | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/replacement.hpp | |
#include <array> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_encodings Encodings | |
/// @{ | |
////// | |
////// | |
/// @brief The American Standard Code for Information Exchange (ASCII) Encoding. | |
/// | |
/// @tparam _CodeUnit The code unit type to work over. | |
/// | |
/// @remarks The most vanilla and unimaginative encoding there is in the world, excluding tons of other languages, | |
/// dialects, and even common English idioms and borrowed words. Please don't pick this unless you have good | |
/// reason! | |
////// | |
template <typename _CodeUnit, typename _CodePoint = unicode_code_point> | |
class basic_ascii { | |
public: | |
////// | |
/// @brief The individual units that result from an encode operation or are used as input to a decode | |
/// operation. | |
////// | |
using code_unit = _CodeUnit; | |
////// | |
/// @brief The individual units that result from a decode operation or as used as input to an encode | |
/// operation. For most encodings, this is going to be a Unicode Code Point or a Unicode Scalar Value. | |
////// | |
using code_point = _CodePoint; | |
////// | |
/// @brief The state that can be used between calls to the encoder and decoder. | |
/// | |
/// @remarks It is an empty struct because there is no shift state to preserve between complete units of | |
/// encoded information. It is also only @c state and not separately @c decode_state and @c encode_state | |
/// because one type suffices for both. | |
////// | |
using state = __txt_detail::__empty_state; | |
////// | |
/// @brief Whether or not the decode operation can process all forms of input into code point values. | |
/// | |
/// @remarks ASCII can decode from its 7-bit (unpacked) code units to Unicode Code Points. Since the converion | |
/// is lossless, this property is true. | |
////// | |
using is_decode_injective = ::std::true_type; | |
////// | |
/// @brief Whether or not the encode operation can process all forms of input into code unit values. This is | |
/// not true for ASCII, as many Unicode Code Point and Unicode Scalar Values cannot be represented in ASCII. | |
/// Since the conversion is lossy, this property is false. | |
////// | |
using is_encode_injective = ::std::false_type; | |
////// | |
/// @brief The maximum code units a single complete operation of encoding can produce. | |
/// | |
////// | |
inline static constexpr const ::std::size_t max_code_units = 1; | |
////// | |
/// @brief The maximum number of code points a single complete operation of decoding can produce. This is | |
/// 1 for all Unicode Transformation Format (UTF) encodings. | |
////// | |
inline static constexpr const ::std::size_t max_code_points = 1; | |
////// | |
/// @brief A range of code units representing the values to use when a replacement happen. For ASCII, this | |
/// must be '?' instead of the usual Unicode Replacement Character U'�'. | |
////// | |
static constexpr const ::std::array<code_unit, 1>& replacement_code_units() noexcept { | |
return __txt_detail::__question_mark_replacement_units<code_unit>; | |
} | |
////// | |
/// @brief Decodes a single complete unit of information as code points and produces a result with the | |
/// input and output ranges moved past what was successfully read and written; or, produces an error and | |
/// returns the input and output ranges untouched. | |
/// | |
/// @param[in] __input The input view to read code uunits from. | |
/// @param[in] __output The output view to write code points into. | |
/// @param[in] __error_handler The error handler to invoke if encoding fails. | |
/// @param[in, out] __s The necessary state information. For this encoding, the state is empty and means | |
/// very little. | |
/// | |
/// @returns A ztd::text::decode_result object that contains the reconstructed input range, | |
/// reconstructed output range, error handler, and a reference to the passed-in state. | |
/// | |
/// @remarks To the best ability of the implementation, the iterators will be returned untouched (e.g., | |
/// the input models at least a view and a forward_range). If it is not possible, returned ranges may be | |
/// incremented even if an error occurs due to the semantics of any view that models an input_range. | |
////// | |
template <typename _InputRange, typename _OutputRange, typename _ErrorHandler> | |
static constexpr auto decode_one( | |
_InputRange&& __input, _OutputRange&& __output, _ErrorHandler&& __error_handler, state& __s) { | |
using _UInputRange = __txt_detail::__remove_cvref_t<_InputRange>; | |
using _UOutputRange = __txt_detail::__remove_cvref_t<_OutputRange>; | |
using _UErrorHandler = __txt_detail::__remove_cvref_t<_ErrorHandler>; | |
using _Result = __txt_detail::__reconstruct_decode_result_t<_InputRange, _OutputRange, state>; | |
constexpr bool __call_error_handler = !is_ignorable_error_handler_v<_UErrorHandler>; | |
auto __init = __txt_detail::__adl::__adl_begin(__input); | |
auto __inlast = __txt_detail::__adl::__adl_end(__input); | |
if (__init == __inlast) { | |
// an exhausted sequence is fine | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::forward<_OutputRange>(__output)), | |
__s, encoding_error::ok); | |
} | |
auto __outit = __txt_detail::__adl::__adl_begin(__output); | |
auto __outlast = __txt_detail::__adl::__adl_end(__output); | |
if constexpr (__call_error_handler) { | |
if (__outit == __outlast) { | |
return __error_handler(ascii {}, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::insufficient_output_space), | |
::ztd::text::span<code_unit, 0>()); | |
} | |
} | |
else { | |
(void)__outlast; | |
} | |
code_unit __units[1] {}; | |
__units[0] = __txt_detail::__dereference(__init); | |
const code_unit& __unit = __units[0]; | |
__txt_detail::__advance(__init); | |
if constexpr (__call_error_handler) { | |
if (static_cast<signed char>(__unit) < static_cast<signed char>(0)) { | |
return __error_handler(ascii {}, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::invalid_sequence), | |
::ztd::text::span<code_unit, 1>(::std::addressof(__units[0]), 1)); | |
} | |
} | |
__txt_detail::__dereference(__outit) = __unit; | |
__txt_detail::__advance(__outit); | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::ok); | |
} | |
////// | |
/// @brief Encodes a single complete unit of information as code units and produces a result with the | |
/// input and output ranges moved past what was successfully read and written; or, produces an error and | |
/// returns the input and output ranges untouched. | |
/// | |
/// @param[in] __input The input view to read code points from. | |
/// @param[in] __output The output view to write code units into. | |
/// @param[in] __error_handler The error handler to invoke if encoding fails. | |
/// @param[in, out] __s The necessary state information. For this encoding, the state is empty and means | |
/// very little. | |
/// | |
/// @returns A ztd::text::encode_result object that contains the reconstructed input range, | |
/// reconstructed output range, error handler, and a reference to the passed-in state. | |
/// | |
/// @remarks To the best ability of the implementation, the iterators will be returned untouched (e.g., | |
/// the input models at least a view and a forward_range). If it is not possible, returned ranges may be | |
/// incremented even if an error occurs due to the semantics of any view that models an input_range. | |
////// | |
template <typename _InputRange, typename _OutputRange, typename _ErrorHandler> | |
static constexpr auto encode_one( | |
_InputRange&& __input, _OutputRange&& __output, _ErrorHandler&& __error_handler, state& __s) { | |
using _UInputRange = __txt_detail::__remove_cvref_t<_InputRange>; | |
using _UOutputRange = __txt_detail::__remove_cvref_t<_OutputRange>; | |
using _UErrorHandler = __txt_detail::__remove_cvref_t<_ErrorHandler>; | |
using _Result = __txt_detail::__reconstruct_encode_result_t<_InputRange, _OutputRange, state>; | |
constexpr bool __call_error_handler = !is_ignorable_error_handler_v<_UErrorHandler>; | |
auto __init = __txt_detail::__adl::__adl_begin(__input); | |
auto __inlast = __txt_detail::__adl::__adl_end(__input); | |
if (__init == __inlast) { | |
// an exhausted sequence is fine | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::forward<_OutputRange>(__output)), | |
__s, encoding_error::ok); | |
} | |
auto __outit = __txt_detail::__adl::__adl_begin(__output); | |
auto __outlast = __txt_detail::__adl::__adl_end(__output); | |
if constexpr (__call_error_handler) { | |
if (__outit == __outlast) { | |
return __error_handler(ascii {}, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::insufficient_output_space), | |
::ztd::text::span<code_point, 0>()); | |
} | |
} | |
else { | |
(void)__outlast; | |
} | |
code_point __points[1] {}; | |
__points[0] = __txt_detail::__dereference(__init); | |
const code_point& __point = __points[0]; | |
__txt_detail::__advance(__init); | |
if constexpr (__call_error_handler) { | |
if (__point > __txt_detail::__last_ascii_value) { | |
ascii __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::invalid_sequence), | |
::ztd::text::span<code_point, 1>(::std::addressof(__points[0]), 1)); | |
} | |
} | |
__txt_detail::__dereference(__outit) = static_cast<code_unit>(__point); | |
__txt_detail::__advance(__outit); | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::ok); | |
} | |
}; | |
////// | |
/// @brief The American Standard Code for Information Exchange (ASCII) Encoding. | |
/// | |
/// @remarks The most vanilla and unimaginative encoding there is in the world, excluding tons of other languages, | |
/// dialects, and even common English idioms and borrowed words. Please don't pick this unless you have good | |
/// reason! | |
////// | |
using ascii = basic_ascii<char>; | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/ascii.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/no_encoding.hpp | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_encodings Encodings | |
/// @{ | |
////// | |
////// | |
/// @brief A UTF-32 Encoding that traffics in, specifically, the desired code unit type provided as a template | |
/// argument. | |
/// | |
/// @tparam _Type The code unit type to use. | |
/// | |
/// @remarks This is a strict UTF-32 implementation that does not allow lone, unpaired surrogates either in or out. | |
////// | |
template <typename _CodeUnit, typename _CodePoint> | |
class basic_no_encoding { | |
public: | |
////// | |
/// @brief The state that can be used between calls to the encoder and decoder. It is an empty struct | |
/// because there is no shift state to preserve between complete units of encoded information. | |
////// | |
using state = __txt_detail::__empty_state; | |
////// | |
/// @brief The individual units that result from an encode operation or are used as input to a decode | |
/// operation. | |
////// | |
using code_unit = _CodeUnit; | |
////// | |
/// @brief The individual units that result from a decode operation or as used as input to an encode | |
/// operation. For most encodings, this is going to be a Unicode Code Point or a Unicode Scalar Value. | |
////// | |
using code_point = _CodePoint; | |
////// | |
/// @brief Whether or not the decode operation can process all forms of input into code unit values. This is | |
/// always true because this encoding does nothing. | |
////// | |
using is_decode_injective = ::std::integral_constant<bool, ::std::is_same_v<_CodeUnit, _CodePoint>>; | |
////// | |
/// @brief Whether or not the encode operation can process all forms of input into code unit values. This is | |
/// always true because this encoding does nothing. | |
////// | |
using is_encode_injective = ::std::integral_constant<bool, ::std::is_same_v<_CodeUnit, _CodePoint>>; | |
////// | |
/// @brief The maximum number of code points a single complete operation of decoding can produce. This is 1 | |
/// because this encoding does nothing. | |
////// | |
inline static constexpr ::std::size_t max_code_points = 1; | |
////// | |
/// @brief The maximum code units a single complete operation of encoding can produce. This is 1 because this | |
/// encoding does nothing. | |
////// | |
inline static constexpr ::std::size_t max_code_units = 1; | |
////// | |
/// @brief Decodes a single complete unit of information as code points and produces a result with the | |
/// input and output ranges moved past what was successfully read and written; or, produces an error and | |
/// returns the input and output ranges untouched. | |
/// | |
/// @param[in] __input The input view to read code uunits from. | |
/// @param[in] __output The output view to write code points into. | |
/// @param[in] __error_handler The error handler to invoke if encoding fails. | |
/// @param[in, out] __s The necessary state information. For this encoding, the state is empty and means | |
/// very little. | |
/// | |
/// @returns A ztd::text::decode_result object that contains the reconstructed input range, | |
/// reconstructed output range, error handler, and a reference to the passed-in state. | |
/// | |
/// @remarks To the best ability of the implementation, the iterators will be returned untouched (e.g., | |
/// the input models at least a view and a forward_range). If it is not possible, returned ranges may be | |
/// incremented even if an error occurs due to the semantics of any view that models an input_range. | |
////// | |
template <typename _InputRange, typename _OutputRange, typename _ErrorHandler> | |
static constexpr auto decode_one( | |
_InputRange&& __input, _OutputRange&& __output, _ErrorHandler&& __error_handler, state& __s) { | |
using _UInputRange = __txt_detail::__remove_cvref_t<_InputRange>; | |
using _UOutputRange = __txt_detail::__remove_cvref_t<_OutputRange>; | |
using _UErrorHandler = __txt_detail::__remove_cvref_t<_ErrorHandler>; | |
using _Result = __txt_detail::__reconstruct_decode_result_t<_InputRange, _OutputRange, state>; | |
constexpr bool __call_error_handler = !is_ignorable_error_handler_v<_UErrorHandler>; | |
auto __init = __txt_detail::__adl::__adl_begin(__input); | |
auto __inlast = __txt_detail::__adl::__adl_end(__input); | |
if (__init == __inlast) { | |
// an exhausted sequence is fine | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::forward<_OutputRange>(__output)), | |
__s, encoding_error::ok); | |
} | |
auto __outit = __txt_detail::__adl::__adl_begin(__output); | |
auto __outlast = __txt_detail::__adl::__adl_end(__output); | |
if constexpr (__call_error_handler) { | |
if (__outit == __outlast) { | |
basic_no_encoding __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::insufficient_output_space), | |
::ztd::text::span<code_unit, 0>()); | |
} | |
} | |
else { | |
(void)__outlast; | |
} | |
code_unit __unit = __txt_detail::__dereference(__init); | |
__txt_detail::__advance(__init); | |
__txt_detail::__dereference(__outit) = static_cast<code_point>(__unit); | |
__txt_detail::__advance(__outit); | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::ok); | |
} | |
////// | |
/// @brief Encodes a single complete unit of information as code units and produces a result with the | |
/// input and output ranges moved past what was successfully read and written; or, produces an error and | |
/// returns the input and output ranges untouched. | |
/// | |
/// @param[in] __input The input view to read code points from. | |
/// @param[in] __output The output view to write code units into. | |
/// @param[in] __error_handler The error handler to invoke if encoding fails. | |
/// @param[in, out] __s The necessary state information. For this encoding, the state is empty and means | |
/// very little. | |
/// | |
/// @returns A ztd::text::encode_result object that contains the reconstructed input range, | |
/// reconstructed output range, error handler, and a reference to the passed-in state. | |
/// | |
/// @remarks To the best ability of the implementation, the iterators will be returned untouched (e.g., | |
/// the input models at least a view and a forward_range). If it is not possible, returned ranges may be | |
/// incremented even if an error occurs due to the semantics of any view that models an input_range. | |
////// | |
template <typename _InputRange, typename _OutputRange, typename _ErrorHandler> | |
static constexpr auto encode_one( | |
_InputRange&& __input, _OutputRange&& __output, _ErrorHandler&& __error_handler, state& __s) { | |
using _UInputRange = __txt_detail::__remove_cvref_t<_InputRange>; | |
using _UOutputRange = __txt_detail::__remove_cvref_t<_OutputRange>; | |
using _UErrorHandler = __txt_detail::__remove_cvref_t<_ErrorHandler>; | |
using _Result = __txt_detail::__reconstruct_encode_result_t<_InputRange, _OutputRange, state>; | |
constexpr bool __call_error_handler = !is_ignorable_error_handler_v<_UErrorHandler>; | |
auto __init = __txt_detail::__adl::__adl_begin(__input); | |
auto __inlast = __txt_detail::__adl::__adl_end(__input); | |
if (__init == __inlast) { | |
// an exhausted sequence is fine | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::forward<_OutputRange>(__output)), | |
__s, encoding_error::ok); | |
} | |
auto __outit = __txt_detail::__adl::__adl_begin(__output); | |
auto __outlast = __txt_detail::__adl::__adl_end(__output); | |
if constexpr (__call_error_handler) { | |
if (__outit == __outlast) { | |
basic_no_encoding __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::insufficient_output_space), | |
::ztd::text::span<code_point, 0>()); | |
} | |
} | |
else { | |
(void)__outlast; | |
} | |
code_point __points[1] {}; | |
__points[0] = __txt_detail::__dereference(__init); | |
const code_point& __point = __points[0]; | |
__txt_detail::__advance(__init); | |
__txt_detail::__dereference(__outit) = static_cast<code_unit>(__point); | |
__txt_detail::__advance(__outit); | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::ok); | |
} | |
}; | |
////// | |
/// @brief A do-nothing encoding for @c char types of input. | |
/// | |
////// | |
using no_encoding = basic_no_encoding<char, unicode_code_point>; | |
////// | |
/// @brief A do-nothing encoding for ztd::text::unicode_code_point types of input. | |
/// | |
////// | |
using no_codepoint_encoding = basic_no_encoding<unicode_code_point, unicode_code_point>; | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/no_encoding.hpp | |
#include <string_view> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
inline constexpr ::std::string_view __msvc_encoding_name_from_id(int __msc_id) noexcept { | |
switch (__msc_id) { | |
case 37: | |
return "IBM-037"; // EBCDIC US-Canada | |
case 437: | |
return "IMB-437"; // OEM United States | |
case 500: | |
return "IBM-500"; // EBCDIC Internatinal | |
case 708: | |
return "ASMO-708"; // Arabic | |
case 709: | |
return "ASMO-449"; // Arabic | |
case 710: | |
return "Arabic"; | |
case 720: | |
return "DOS-720"; // Arabic | |
case 737: | |
return "IBM-737"; // Greek | |
case 775: | |
return "IBM 775"; | |
case 850: | |
return "IBM-850"; | |
case 874: | |
return "Windows-874"; // Thai, Windows | |
case 855: | |
return "CP-875"; // EBCDIC Greek, Modern | |
case 932: | |
return "SHIT-JIS"; | |
case 1200: | |
return "UTF-16-LE"; | |
case 1201: | |
return "UTF-16-BE"; | |
case 1251: | |
return "Windows-1251"; // Cyrllic | |
case 1252: | |
return "Windows-1252"; // Latin-1, West Europe | |
case 12000: | |
return "UTF-32-LE"; | |
case 12001: | |
return "UTF-32-BE"; | |
case 20127: | |
return "ASCII"; | |
case 50222: | |
return "ISO-2022-JP"; | |
case 50225: | |
return "ISO-2022-KR"; | |
case 51932: | |
return "EUC-JP"; | |
case 51936: | |
return "EUC-CN"; | |
case 51949: | |
return "EUC-KR"; | |
case 51950: | |
return "EUC-CN-Traditional"; | |
case 54936: | |
return "GB18030"; | |
case 65000: | |
return "UTF-7"; | |
case 65001: | |
return "UTF-8"; | |
default: | |
break; | |
} | |
return "UTF-8"; | |
} | |
inline constexpr bool __is_encoding_name_equal( | |
::std::string_view __left, ::std::string_view __right) noexcept { | |
constexpr ::std::string_view __readable_characters | |
= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuuvwxyz1234567890"; | |
constexpr ::std::string_view __uncased_characters = "abcdefghijklmnopqrstuuvwxyz"; | |
constexpr ::std::string_view __cased_characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | |
::std::size_t __left_size = __left.size(); | |
::std::size_t __right_size = __right.size(); | |
const char* __left_ptr = __left.data(); | |
const char* __right_ptr = __right.data(); | |
::std::size_t __left_index = 0; | |
::std::size_t __right_index = 0; | |
for (; __left_index < __left_size && __right_index < __right_size;) { | |
// find the first non-ignorable character we can read | |
::std::size_t __left_first_index = __left.find_first_of(__readable_characters, __left_index); | |
if (__left_first_index == ::std::string_view::npos) { | |
return __left_index == __right_index; | |
} | |
__left_index = __left_first_index + 1; | |
::std::size_t __right_first_index = __right.find_first_of(__readable_characters, __right_index); | |
if (__right_first_index == ::std::string_view::npos) { | |
return __left_index == __right_index; | |
} | |
__right_index = __right_first_index + 1; | |
char __left_c = __left_ptr[__left_first_index]; | |
char __right_c = __right_ptr[__right_first_index]; | |
// make sure we eliminate casing differences | |
::std::size_t __left_c_casing_index = __uncased_characters.find(__left_c); | |
if (__left_c_casing_index != ::std::string_view::npos) { | |
__left_c = __cased_characters[__left_c_casing_index]; | |
} | |
::std::size_t __right_c_casing_index = __uncased_characters.find(__right_c); | |
if (__right_c_casing_index != ::std::string_view::npos) { | |
__right_c = __cased_characters[__right_c_casing_index]; | |
} | |
// finally, check | |
if (__left_c == __right_c) { | |
continue; | |
} | |
return false; | |
} | |
return true; | |
} | |
inline constexpr bool __is_unicode_encoding_name(::std::string_view __encoding_name) noexcept { | |
constexpr const char* __unicode_names[] | |
= { "UTF-7", "UTF-7-IMAP", "UTF-8", "UTF-16", "UTF-32", "UTF-16LE", "UTF-16BE", "UTF-32LE", | |
"UTF-32BE", "UTF-EBCDIC", "UTF-8-EBCDIC", "MUTF-8", "WTF-8", "GB18030", "CESU-8", "UTF-1" }; | |
constexpr ::std::size_t __unicode_names_count = sizeof(__unicode_names) / sizeof(__unicode_names[0]); | |
for (::std::size_t __index = 0; __index < __unicode_names_count; ++__index) { | |
::std::string_view __unicode_name = __unicode_names[__index]; | |
if (__is_encoding_name_equal(__encoding_name, __unicode_name)) { | |
return true; | |
} | |
} | |
return false; | |
} | |
enum class __encoding_id { | |
__unknown = 0, | |
__utf7imap, | |
__utf7, | |
__utfebcdic, | |
__utf8, | |
__mutf8, | |
__wtf8, | |
__utf16, | |
__utf16le, | |
__utf16be, | |
__utf32, | |
__utf32le, | |
__utf32be, | |
__gb18030, | |
__utf1, | |
__cesu8, | |
__ascii | |
}; | |
inline constexpr __encoding_id __to_encoding_id(::std::string_view __name) { | |
if (__is_encoding_name_equal(__name, "UTF-8")) { | |
return __encoding_id::__utf8; | |
} | |
else if (__is_encoding_name_equal(__name, "UTF-16") || __is_encoding_name_equal(__name, "UCS-2-INTERNAL") | |
|| __is_encoding_name_equal(__name, "UCS-2")) { | |
return __encoding_id::__utf16; | |
} | |
else if (__is_encoding_name_equal(__name, "UTF-16LE") | |
|| __is_encoding_name_equal(__name, "UCS-2LE-INTERNAL") | |
|| __is_encoding_name_equal(__name, "UCS-2LE")) { | |
return __encoding_id::__utf16le; | |
} | |
else if (__is_encoding_name_equal(__name, "UTF-16BE") | |
|| __is_encoding_name_equal(__name, "UCS-2BE-INTERNAL") | |
|| __is_encoding_name_equal(__name, "UCS-2BE")) { | |
return __encoding_id::__utf16be; | |
} | |
else if (__is_encoding_name_equal(__name, "UTF-32") || __is_encoding_name_equal(__name, "UCS-4-INTERNAL") | |
|| __is_encoding_name_equal(__name, "UCS-4")) { | |
return __encoding_id::__utf32; | |
} | |
else if (__is_encoding_name_equal(__name, "UTF-32LE") | |
|| __is_encoding_name_equal(__name, "UCS-4LE-INTERNAL") | |
|| __is_encoding_name_equal(__name, "UCS-4LE")) { | |
return __encoding_id::__utf32le; | |
} | |
else if (__is_encoding_name_equal(__name, "UTF-32BE") | |
|| __is_encoding_name_equal(__name, "UCS-4BE-INTERNAL") | |
|| __is_encoding_name_equal(__name, "UCS-4BE")) { | |
return __encoding_id::__utf32be; | |
} | |
else if (__is_encoding_name_equal(__name, "ASCII") | |
|| __is_encoding_name_equal(__name, "ANSI_X3.4-1968")) { | |
return __encoding_id::__ascii; | |
} | |
else if (__is_encoding_name_equal(__name, "UTF-EBCDIC") | |
|| __is_encoding_name_equal(__name, "UTF-8-EBCDIC")) { | |
return __encoding_id::__utfebcdic; | |
} | |
else if (__is_encoding_name_equal(__name, "WTF-8")) { | |
return __encoding_id::__wtf8; | |
} | |
else if (__is_encoding_name_equal(__name, "MUTF-8")) { | |
return __encoding_id::__mutf8; | |
} | |
else if (__is_encoding_name_equal(__name, "UTF-7")) { | |
return __encoding_id::__utf7; | |
} | |
else if (__is_encoding_name_equal(__name, "UTF-7-IMAP")) { | |
return __encoding_id::__utf7imap; | |
} | |
else { | |
return __encoding_id::__unknown; | |
} | |
} | |
inline constexpr bool __is_unicode_encoding_id(__encoding_id __id) noexcept { | |
switch (__id) { | |
case __encoding_id::__utf7: | |
case __encoding_id::__utf7imap: | |
case __encoding_id::__utfebcdic: | |
case __encoding_id::__utf8: | |
case __encoding_id::__utf16: | |
case __encoding_id::__utf16le: | |
case __encoding_id::__utf16be: | |
case __encoding_id::__utf32: | |
case __encoding_id::__utf32le: | |
case __encoding_id::__utf32be: | |
case __encoding_id::__gb18030: | |
case __encoding_id::__wtf8: | |
case __encoding_id::__mutf8: | |
case __encoding_id::__utf1: | |
case __encoding_id::__cesu8: | |
return true; | |
case __encoding_id::__ascii: | |
case __encoding_id::__unknown: | |
default: | |
return false; | |
} | |
} | |
template <typename _CharType, __encoding_id _Id> | |
constexpr auto __select_encoding() { | |
if constexpr (_Id == __encoding_id::__utf8) { | |
return basic_utf8<_CharType> {}; | |
} | |
else if constexpr (_Id == __encoding_id::__mutf8) { | |
return basic_mutf8<_CharType> {}; | |
} | |
else if constexpr (_Id == __encoding_id::__wtf8) { | |
return basic_wtf8<_CharType> {}; | |
} | |
else if constexpr (_Id == __encoding_id::__utf16) { | |
return basic_utf16<_CharType> {}; | |
} | |
else if constexpr (_Id == __encoding_id::__utf16le) { | |
// TODO: beef up encoding_scheme to handle this better...! | |
return basic_utf16_le<_CharType> {}; | |
} | |
else if constexpr (_Id == __encoding_id::__utf16be) { | |
// TODO: beef up encoding_scheme to handle this better...! | |
return basic_utf16_be<_CharType> {}; | |
} | |
else if constexpr (_Id == __encoding_id::__utf32) { | |
return basic_utf32<_CharType> {}; | |
} | |
else if constexpr (_Id == __encoding_id::__utf32le) { | |
// TODO: beef up encoding_scheme to handle this better...! | |
return basic_utf32_le<_CharType> {}; | |
} | |
else if constexpr (_Id == __encoding_id::__utf32be) { | |
// TODO: beef up encoding_scheme to handle this better...! | |
return basic_utf32_be<_CharType> {}; | |
} | |
else if constexpr (_Id == __encoding_id::__ascii) { | |
return basic_ascii<_CharType> {}; | |
} | |
else { | |
return basic_no_encoding<_CharType, unicode_code_point> {}; | |
} | |
} | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/encoding_name.hpp | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_PLATFORM_UNIX_I_) | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_LANGINFO_I_) | |
extern "C" { | |
#include <langinfo.h> | |
} | |
#elif ZTD_TEXT_IS_ON(ZTD_TEXT_NL_LANGINFO_I_) | |
extern "C" { | |
#include <nl_langinfo.h> | |
} | |
#else | |
#include <clocale> | |
#endif | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { namespace __posix { | |
inline __encoding_id __determine_active_code_page() noexcept { | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_LANGINFO_I_) || ZTD_TEXT_IS_ON(ZTD_TEXT_NL_LANGINFO_I_) | |
const char* __name = nl_langinfo(LC_CTYPE); | |
return __to_encoding_id(__name); | |
#else | |
// fallback to stdlib I guess? | |
const char* __ctype_name = setlocale(LC_CTYPE, nullptr); | |
return __to_encoding_id(__ctype_name); | |
#endif | |
} | |
}} // namespace __txt_detail::__posix | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
#endif // POSIX | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/posix.hpp | |
#include <cuchar> | |
#include <cwchar> | |
#include <cstdint> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_encodings Encodings | |
/// @{ | |
////// | |
namespace __txt_detail { | |
class __execution_decode_state { | |
public: | |
::std::mbstate_t __narrow_state; | |
bool __output_pending; | |
__execution_decode_state() noexcept : __narrow_state(), __output_pending(false) { | |
char32_t __ghost_space[2]; | |
::std::size_t __init_result = ::std::mbrtoc32(__ghost_space, "\0", 1, &__narrow_state); | |
// make sure it is initialized | |
ZTD_TEXT_ASSERT_I_(__init_result == 0 && __ghost_space[0] == U'\0'); | |
ZTD_TEXT_ASSERT_I_(::std::mbsinit(&__narrow_state) != 0); | |
} | |
}; | |
class __execution_encode_state { | |
public: | |
::std::mbstate_t __narrow_state; | |
bool __output_pending; | |
__execution_encode_state() noexcept : __narrow_state(), __output_pending(false) { | |
char __ghost_space[MB_LEN_MAX]; | |
::std::size_t __init_result = ::std::c32rtomb(__ghost_space, U'\0', &__narrow_state); | |
// make sure it is initialized | |
ZTD_TEXT_ASSERT_I_(__init_result == 1 && __ghost_space[0] == '\0'); | |
ZTD_TEXT_ASSERT_I_(::std::mbsinit(&__narrow_state) != 0); | |
} | |
}; | |
} // namespace __txt_detail | |
////// | |
/// @brief The Encoding that represents the "Execution" (narrow locale-based) encoding. The execution encoding is | |
/// typically associated with the locale, which is tied to the C standard library's setlocale function. | |
/// | |
/// @remarks Use of this type is subject to the C Standard Library. Some locales (such as the Big5 Hong King | |
/// Supplementary Character Set (Big5-HKSCS)) are broken when accessed without @c ZTD_TEXT_USE_CUNEICODE is not | |
/// defined, due to fundamental design issues in the C Standard Library and bugs in glibc/musl libc's current | |
/// locale encoding support. | |
////// | |
class execution { | |
public: | |
////// | |
/// @brief The state of the execution encoding used between decode calls, which may potentially manage shift | |
/// state. | |
/// | |
/// @remarks This type can potentially have lots of state due to the way the C API is specified. It is | |
/// important it is preserved between calls, or text may become mangled / data may become lost. | |
////// | |
using decode_state = __txt_detail::__execution_decode_state; | |
////// | |
/// @brief The state of the execution encoding used between encode calls, which may potentially manage shift | |
/// state. | |
/// | |
/// @remarks This type can potentially have lots of state due to the way the C API is specified. It is | |
/// important it is preserved between calls, or text may become mangled / data may become lost. | |
////// | |
using encode_state = __txt_detail::__execution_encode_state; | |
////// | |
/// @brief The individual units that result from an encode operation or are used as input to a decode | |
/// operation. | |
/// | |
/// @remarks Please note that char can be either signed or unsigned, and so generally can result in bad | |
/// results when promoted to a plain @c int when working with code units or working with the C Standard | |
/// Library. | |
////// | |
using code_unit = char; | |
////// | |
/// @brief The individual units that result from a decode operation or as used as input to an encode | |
/// operation. For most encodings, this is going to be a Unicode Code Point or a Unicode Scalar Value. | |
////// | |
using code_point = unicode_code_point; | |
////// | |
/// @brief Whether or not the decode operation can process all forms of input into code point values. | |
/// | |
/// @remarks All known execution encodings can decode into Unicode just fine. However, someone may define a | |
/// platform encoding on their machine that does not transform cleanly. Therefore, decoding is not marked as | |
/// injective. | |
////// | |
using is_decode_injective = ::std::false_type; | |
////// | |
/// @brief Whether or not the encode operation can process all forms of input into code unit values. This is | |
/// absolutely not true: many unicode code point values cannot be safely converted to a large number of | |
/// existing (legacy) encodings. | |
////// | |
using is_encode_injective = ::std::false_type; | |
////// | |
/// @brief The maximum code units a single complete operation of encoding can produce. | |
/// | |
/// @remarks There are encodings for which one input can produce 3 code points (some Tamil encodings) and | |
/// there are rumours of an encoding that can produce 7 code points from a handful of input. We use a | |
/// conservative "7", here. | |
////// | |
inline static constexpr ::std::size_t max_code_points = 7; | |
////// | |
/// @brief The maximum number of code points a single complete operation of decoding can produce. | |
/// | |
/// @remarks This is bounded by the platform's @c MB_LEN_MAX macro, which is an integral constant expression | |
/// representing the maximum value of output all C locales can produce from a single complete operation. | |
////// | |
inline static constexpr ::std::size_t max_code_units = MB_LEN_MAX; | |
////// | |
/// @brief A range of code unit values that can be used as a replacement value, instead of the ones used in | |
/// ztd::text::default_handler. | |
/// | |
/// @remarks The default replacement code point / code unit is U+FFFD (). This, obviously, does not fit in the | |
/// majority of the (legacy) locale encodings in C and C++. '?' is a much more conservative option, here, and | |
/// most (all?) locale encodings have some form of representation for it. | |
////// | |
inline static constexpr code_unit replacement_code_units[1] = { '?' }; | |
////// | |
/// @brief Returns whether or not this encoding is a unicode encoding. | |
/// | |
/// @remarks This function operates at runtime and queries the existing locale through a variety of | |
/// platform-specific means (such as @c nl_langinfo for POSIX, ACP probing on Windows, or fallin back to @c | |
/// std::setlocale name checking otherwise). | |
////// | |
static bool contains_unicode_encoding() noexcept { | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_PLATFORM_WINDOWS_I_) | |
int __codepage_id = __txt_detail::__windows::__determine_active_code_page(); | |
return __txt_detail::__windows::__is_unicode_code_page(__codepage_id); | |
#elif ZTD_TEXT_IS_ON(ZTD_TEXT_NL_LANGINFO_I_) || ZTD_TEXT_IS_ON(ZTD_TEXT_LANGINFO_I_) | |
const char* __ctype_name = nl_langinfo(CODESET); | |
return __txt_detail::__is_unicode_encoding_name(__ctype_name); | |
#else | |
const char* __ctype_name = setlocale(LC_CTYPE, nullptr); | |
return __txt_detail::__is_encoding_name_unicode(__ctype_name); | |
#endif | |
} | |
////// | |
/// @brief Encodes a single complete unit of information as code units and produces a result with the | |
/// input and output ranges moved past what was successfully read and written; or, produces an error and | |
/// returns the input and output ranges untouched. | |
/// | |
/// @param[in] __input The input view to read code uunits from. | |
/// @param[in] __output The output view to write code points into. | |
/// @param[in] __error_handler The error handler to invoke if encoding fails. | |
/// @param[in, out] __s The necessary state information. Most encodings have no state, but because this is | |
/// effectively a runtime encoding and therefore it is important to preserve and manage this state. | |
/// | |
/// @returns A ztd::text::encode_result object that contains the reconstructed input range, | |
/// reconstructed output range, error handler, and a reference to the passed-in state. | |
/// | |
/// @remarks Platform APIs and/or the C Standard Library may be used to properly decode one complete unit of | |
/// information (alongside std::mbstate_t usage). Whether or not the state is used is based on the | |
/// implementation and what it chooses. If @c ZTD_TEXT_USE_CUNEICODE is defined, the ztd.cuneicode library may | |
/// be used to fulfill this functionality. | |
/// | |
/// @remarks To the best ability of the implementation, the iterators will be | |
/// returned untouched (e.g., the input models at least a view and a forward_range). If it is not possible, | |
/// returned ranges may be incremented even if an error occurs due to the semantics of any view that models an | |
/// input_range. | |
////// | |
template <typename _InputRange, typename _OutputRange, typename _ErrorHandler> | |
static constexpr auto encode_one( | |
_InputRange&& __input, _OutputRange&& __output, _ErrorHandler&& __error_handler, encode_state& __s) { | |
using _UInputRange = __txt_detail::__remove_cvref_t<_InputRange>; | |
using _UOutputRange = __txt_detail::__remove_cvref_t<_OutputRange>; | |
using _UErrorHandler = __txt_detail::__remove_cvref_t<_ErrorHandler>; | |
using _Result = __txt_detail::__reconstruct_encode_result_t<_InputRange, _OutputRange, encode_state>; | |
constexpr bool __call_error_handler = !is_ignorable_error_handler_v<_UErrorHandler>; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_PLATFORM_WINDOWS_I_) | |
if (__txt_detail::__windows::__determine_active_code_page() == CP_UTF8) { | |
// just go straight to UTF8 | |
using __exec_utf8 = __impl::__utf8_with<void, code_unit, code_point>; | |
__exec_utf8 __u8enc {}; | |
encode_state_t<__exec_utf8> __intermediate_s {}; | |
__txt_detail::__progress_handler<!__call_error_handler, execution> __intermediate_handler {}; | |
auto __intermediate_result = __u8enc.encode_one(::std::forward<_InputRange>(__input), | |
::std::forward<_OutputRange>(__output), __intermediate_handler, __intermediate_s); | |
if constexpr (__call_error_handler) { | |
if (__intermediate_result.error_code != encoding_error::ok) { | |
execution __self {}; | |
return __error_handler(__self, | |
_Result(::std::move(__intermediate_result.input), | |
::std::move(__intermediate_result.output), __s, | |
__intermediate_result.error_code), | |
::ztd::text::span<code_point>(__intermediate_handler._M_code_points.data(), | |
__intermediate_handler._M_code_points_size)); | |
} | |
} | |
return _Result(::std::move(__intermediate_result.input), ::std::move(__intermediate_result.output), | |
__s, __intermediate_result.error_code); | |
} | |
#endif // Windows Hell | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_PLATFORM_WINDOWS_I_) | |
auto __outit = __txt_detail::__adl::__adl_begin(__output); | |
auto __outlast = __txt_detail::__adl::__adl_end(__output); | |
if constexpr (__call_error_handler) { | |
if (__outit == __outlast) { | |
return __error_handler(execution {}, | |
_Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::forward<_InputRange>(__input)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::insufficient_output_space), | |
::ztd::text::span<code_point, 0>()); | |
} | |
} | |
using __u16e = __impl::__utf16_with<void, wchar_t, code_point, false>; | |
using __intermediate_state = encode_state_t<__u16e>; | |
__u16e __u16enc {}; | |
__intermediate_state __intermediate_s {}; | |
__txt_detail::__progress_handler<!__call_error_handler, execution> __intermediate_handler {}; | |
wchar_t __wide_intermediary[8] {}; | |
::ztd::text::span<wchar_t> __wide_write_buffer(__wide_intermediary); | |
auto __intermediate_result = __u16enc.encode_one(::std::forward<_InputRange>(__input), | |
__wide_write_buffer, __intermediate_handler, __intermediate_s); | |
if constexpr (__call_error_handler) { | |
if (__intermediate_result.error_code != encoding_error::ok) { | |
execution __self {}; | |
return __error_handler(__self, | |
_Result(::std::move(__intermediate_result.input), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::forward<_OutputRange>(__output)), | |
__s, __intermediate_result.error_code), | |
::ztd::text::span<code_point>(__intermediate_handler._M_code_points.data(), | |
__intermediate_handler._M_code_points_size)); | |
} | |
} | |
constexpr const ::std::size_t __state_count_max = 12; | |
code_unit __intermediary_output[__state_count_max] {}; | |
int __used_default_char = false; | |
::ztd::text::span<const wchar_t> __wide_read_buffer( | |
__wide_intermediary, __intermediate_result.output.data()); | |
int __res | |
= ::WideCharToMultiByte(static_cast<UINT>(__txt_detail::__windows::__determine_active_code_page()), | |
WC_ERR_INVALID_CHARS, __wide_read_buffer.data(), static_cast<int>(__wide_read_buffer.size()), | |
__intermediary_output, __state_count_max, ::std::addressof(replacement_code_units[0]), | |
::std::addressof(__used_default_char)); | |
if constexpr (__call_error_handler) { | |
if (__res == 0) { | |
execution __self {}; | |
return __error_handler(__self, | |
_Result(::std::move(__intermediate_result.input), ::std::forward<_OutputRange>(__output), | |
__s, | |
::GetLastError() == ERROR_INSUFFICIENT_BUFFER | |
? encoding_error::insufficient_output_space | |
: encoding_error::invalid_sequence), | |
::ztd::text::span<code_point>(__intermediate_handler._M_code_points.data(), | |
__intermediate_handler._M_code_points_size)); | |
} | |
} | |
for (auto __intermediary_it = __intermediary_output; __res-- > 0;) { | |
if constexpr (__call_error_handler) { | |
if (__outit == __outlast) { | |
execution __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
__txt_detail::__adl::__adl_begin(__intermediate_result.input), | |
__txt_detail::__adl::__adl_end(__intermediate_result.input)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::insufficient_output_space), | |
::ztd::text::span<code_point>(__intermediate_handler._M_code_points.data(), | |
__intermediate_handler._M_code_points_size)); | |
} | |
} | |
__txt_detail::__dereference(__outit) = __txt_detail::__dereference(__intermediary_it); | |
__txt_detail::__advance(__outit); | |
} | |
return _Result(::std::move(__intermediate_result.input), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::move(__outit), ::std::move(__outlast)), | |
__s, __intermediate_result.error_code); | |
#else | |
auto __init = __txt_detail::__adl::__adl_begin(__input); | |
auto __inlast = __txt_detail::__adl::__adl_end(__input); | |
if (__init == __inlast) { | |
// an exhausted sequence is fine | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::forward<_OutputRange>(__output)), | |
__s, encoding_error::ok); | |
} | |
auto __outit = __txt_detail::__adl::__adl_begin(__output); | |
auto __outlast = __txt_detail::__adl::__adl_end(__output); | |
if constexpr (__call_error_handler) { | |
if (__outit == __outlast) { | |
execution __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::insufficient_output_space), | |
::ztd::text::span<code_point, 0>()); | |
} | |
} | |
code_point __codepoint = __txt_detail::__dereference(__init); | |
__txt_detail::__advance(__init); | |
code_unit __intermediary_output[MB_LEN_MAX] {}; | |
::std::size_t __res | |
= ::std::c32rtomb(__intermediary_output, __codepoint, ::std::addressof(__s.__narrow_state)); | |
if constexpr (__call_error_handler) { | |
if (__res == static_cast<::std::size_t>(-1)) { | |
execution __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::invalid_sequence), | |
::ztd::text::span<code_point, 1>(&__codepoint, 1)); | |
} | |
} | |
for (auto __intermediary_it = __intermediary_output; __res-- > 0; ++__intermediary_it) { | |
if constexpr (__call_error_handler) { | |
if (__outit == __outlast) { | |
execution __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::insufficient_output_space), | |
::ztd::text::span<code_point, 1>(&__codepoint, 1)); | |
} | |
} | |
__txt_detail::__dereference(__outit) = __txt_detail::__dereference(__intermediary_it); | |
__txt_detail::__advance(__outit); | |
} | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::ok); | |
#endif // Windows is hell | |
} | |
////// | |
/// @brief Decodes a single complete unit of information as code points and produces a result with the | |
/// input and output ranges moved past what was successfully read and written; or, produces an error and | |
/// returns the input and output ranges untouched. | |
/// | |
/// @param[in] __input The input view to read code uunits from. | |
/// @param[in] __output The output view to write code points into. | |
/// @param[in] __error_handler The error handler to invoke if encoding fails. | |
/// @param[in, out] __s The necessary state information. Most encodings have no state, but because this is | |
/// effectively a runtime encoding and therefore it is important to preserve and manage this state. | |
/// | |
/// @returns A ztd::text::decode_result object that contains the reconstructed input range, | |
/// reconstructed output range, error handler, and a reference to the passed-in state. | |
/// | |
/// @remarks Platform APIs and/or the C Standard Library may be used to properly decode one complete unit of | |
/// information (alongside std::mbstate_t usage). Whether or not the state is used is based on the | |
/// implementation and what it chooses. If @c ZTD_TEXT_USE_CUNEICODE is defined, the ztd.cuneicode library may | |
/// be used to fulfill this functionality. | |
/// | |
/// @remarks To the best ability of the implementation, the iterators will be | |
/// returned untouched (e.g., the input models at least a view and a forward_range). If it is not possible, | |
/// returned ranges may be incremented even if an error occurs due to the semantics of any view that models an | |
/// input_range. | |
////// | |
template <typename _InputRange, typename _OutputRange, typename _ErrorHandler> | |
static constexpr auto decode_one( | |
_InputRange&& __input, _OutputRange&& __output, _ErrorHandler&& __error_handler, decode_state& __s) { | |
using _UInputRange = __txt_detail::__remove_cvref_t<_InputRange>; | |
using _UOutputRange = __txt_detail::__remove_cvref_t<_OutputRange>; | |
using _UErrorHandler = __txt_detail::__remove_cvref_t<_ErrorHandler>; | |
using _Result = __txt_detail::__reconstruct_decode_result_t<_InputRange, _OutputRange, decode_state>; | |
constexpr bool __call_error_handler = !is_ignorable_error_handler_v<_UErrorHandler>; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_PLATFORM_WINDOWS_I_) | |
if (__txt_detail::__windows::__determine_active_code_page() == CP_UTF8) { | |
// just use utf8 directly | |
// just go straight to UTF8 | |
using __char_utf8 = __impl::__utf8_with<void, code_unit, code_point>; | |
__char_utf8 __u8enc {}; | |
decode_state_t<__char_utf8> __intermediate_s {}; | |
__txt_detail::__progress_handler<!__call_error_handler, execution> __intermediate_handler {}; | |
auto __intermediate_result = __u8enc.decode_one(::std::forward<_InputRange>(__input), | |
::std::forward<_OutputRange>(__output), __intermediate_handler, __intermediate_s); | |
if constexpr (__call_error_handler) { | |
if (__intermediate_result.error_code != encoding_error::ok) { | |
execution __self {}; | |
return __error_handler(__self, | |
_Result(::std::move(__intermediate_result.input), | |
::std::move(__intermediate_result.output), __s, | |
__intermediate_result.error_code), | |
::ztd::text::span<code_unit>(__intermediate_handler._M_code_units.data(), | |
__intermediate_handler._M_code_units_size)); | |
} | |
} | |
return _Result(::std::move(__intermediate_result.input), ::std::move(__intermediate_result.output), | |
__s, __intermediate_result.error_code); | |
} | |
#endif | |
auto __init = __txt_detail::__adl::__adl_begin(__input); | |
auto __inlast = __txt_detail::__adl::__adl_end(__input); | |
if (__init == __inlast) { | |
// an exhausted sequence is fine | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::forward<_OutputRange>(__output)), | |
__s, encoding_error::ok); | |
} | |
auto __outit = __txt_detail::__adl::__adl_begin(__output); | |
auto __outlast = __txt_detail::__adl::__adl_end(__output); | |
if constexpr (__call_error_handler) { | |
if (__outit == __outlast) { | |
execution __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::insufficient_output_space), | |
::ztd::text::span<code_unit, 0>()); | |
} | |
} | |
code_unit __intermediary_input[max_code_units] {}; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_PLATFORM_WINDOWS_I_) && ZTD_TEXT_IS_OFF(ZTD_TEXT_COMPILER_MINGW_I_) | |
__intermediary_input[0] = __txt_detail::__dereference(__init); | |
__txt_detail::__advance(__init); | |
::std::size_t __state_count = 1; | |
for (; __state_count < max_code_units; ++__state_count) { | |
using __u16e = __impl::__utf16_with<void, wchar_t, code_point, false>; | |
using __intermediate_state = decode_state_t<__u16e>; | |
constexpr const int __wide_intermediary_size = 4; | |
wchar_t __wide_intermediary[__wide_intermediary_size] {}; | |
int __res = ::MultiByteToWideChar( | |
static_cast<UINT>(__txt_detail::__windows::__determine_active_code_page()), | |
MB_ERR_INVALID_CHARS, __intermediary_input, static_cast<int>(__state_count), | |
__wide_intermediary, __wide_intermediary_size); | |
if (__res == 0) { | |
if (::GetLastError() == ERROR_NO_UNICODE_TRANSLATION) { | |
// loopback; we might just not have enough code units | |
if constexpr (__call_error_handler) { | |
if (__init == __inlast) { | |
execution __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::incomplete_sequence), | |
::ztd::text::span<code_unit>(__intermediary_input, __state_count)); | |
} | |
} | |
__intermediary_input[__state_count] = __txt_detail::__dereference(__init); | |
__txt_detail::__advance(__init); | |
continue; | |
} | |
if constexpr (__call_error_handler) { | |
execution __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::invalid_sequence), | |
::ztd::text::span<code_unit>(__intermediary_input, __state_count)); | |
} | |
} | |
__u16e __u16enc {}; | |
__intermediate_state __intermediate_s {}; | |
__txt_detail::__pass_through_handler_with<!__call_error_handler> __intermediate_handler {}; | |
::ztd::text::span<wchar_t, sizeof(__wide_intermediary) / sizeof(wchar_t)> __wide_intermediary_view( | |
__wide_intermediary); | |
auto __intermediate_result = __u16enc.encode_one(__wide_intermediary_view, | |
::std::forward<_OutputRange>(__output), __intermediate_handler, __intermediate_s); | |
if constexpr (__call_error_handler) { | |
if (__intermediate_result.error_code != encoding_error::ok) { | |
return __error_handler(execution {}, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
::std::move(__intermediate_result.output), __s, | |
__intermediate_result.error_code), | |
::ztd::text::span<code_unit>(__intermediary_input, __state_count)); | |
} | |
} | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__init), ::std::move(__inlast)), | |
::std::move(__intermediate_result.output), __s, __intermediate_result.error_code); | |
#else | |
if (__s.__output_pending) { | |
// need to drain potential mbstate_t of any leftover code points? | |
char32_t __intermediary_output[max_code_points] {}; | |
::std::size_t __res = ::std::mbrtoc32( | |
::std::addressof(__intermediary_output[0]), nullptr, 0, ::std::addressof(__s.__narrow_state)); | |
if constexpr (__call_error_handler) { | |
if (__res == static_cast<::std::size_t>(-1)) { | |
execution __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::invalid_sequence), | |
::ztd::text::span<code_unit, 0>()); | |
} | |
} | |
__txt_detail::__dereference(__outit) = __intermediary_output[0]; | |
__txt_detail::__advance(__outit); | |
__s.__output_pending = __res == static_cast<::std::size_t>(-3); | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::ok); | |
} | |
::std::size_t __state_offset = 0; | |
::std::size_t __state_count = 1; | |
for (; __state_offset < max_code_units; (void)++__state_offset, (void)++__state_count) { | |
::std::mbstate_t __preserved_state = __s.__narrow_state; | |
__intermediary_input[__state_offset] = __txt_detail::__dereference(__init); | |
__txt_detail::__advance(__init); | |
char32_t __intermediary_output[1] {}; | |
::std::size_t __res = ::std::mbrtoc32(::std::addressof(__intermediary_output[0]), | |
::std::addressof(__intermediary_input[0]), __state_count, ::std::addressof(__preserved_state)); | |
switch (__res) { | |
case static_cast<::std::size_t>(-2): | |
// cycle around and continue | |
if constexpr (__call_error_handler) { | |
if (__init == __inlast) { | |
execution __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::incomplete_sequence), | |
::ztd::text::span<code_unit>(__intermediary_input, __state_count)); | |
} | |
} | |
break; | |
case static_cast<::std::size_t>(-3): | |
__txt_detail::__dereference(__outit) = __intermediary_output[0]; | |
__txt_detail::__advance(__outit); | |
__s.__narrow_state = __preserved_state; | |
__s.__output_pending = true; | |
__state_offset = __state_count; | |
return _Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::ok); | |
case static_cast<::std::size_t>(-1): | |
if constexpr (__call_error_handler) { | |
// OH GOD PANIC AAAAAAH | |
// seriously we're out of spec here: | |
// everything has gone to shit | |
// even the __narrow_state is unspecified ;; | |
execution __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::invalid_sequence), | |
::ztd::text::span<code_unit>( | |
::std::addressof(__intermediary_input[0]), __state_count)); | |
} | |
else { | |
break; | |
} | |
case static_cast<::std::size_t>(0): | |
// 0 means null character; ok | |
__txt_detail::__dereference(__outit) = __intermediary_output[0]; | |
__txt_detail::__advance(__outit); | |
return _Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::ok); | |
default: | |
__txt_detail::__dereference(__outit) = __intermediary_output[0]; | |
__txt_detail::__advance(__outit); | |
__s.__narrow_state = __preserved_state; | |
return _Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::ok); | |
} | |
#endif | |
} | |
if constexpr (__call_error_handler) { | |
// if it was invalid, we would have caught it before | |
// this is for incomplete sequences only | |
execution __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::incomplete_sequence), | |
::ztd::text::span<code_unit>(::std::addressof(__intermediary_input[0]), __state_count)); | |
} | |
else { | |
// ... I mean. | |
// You asked for it??? | |
_Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::ok); | |
} | |
} | |
}; | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/execution.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/wide_execution.hpp | |
#include <cuchar> | |
#include <cwchar> | |
#include <iterator> | |
#include <utility> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_encodings Encodings | |
/// @{ | |
////// | |
namespace __txt_detail { | |
class __wide_execution_decode_state { | |
public: | |
::std::mbstate_t __wide_state; | |
decode_state_t<execution> __narrow_state; | |
// TODO: states need to be split into 2 | |
// different states, optionally... | |
__wide_execution_decode_state() noexcept : __wide_state(), __narrow_state() { | |
char __ghost_space[MB_LEN_MAX]; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_LIBVCXX_I_) | |
::std::size_t __init_result {}; | |
errno_t err = wcrtomb_s(&__init_result, __ghost_space, MB_LEN_MAX, L'\0', &__wide_state); | |
ZTD_TEXT_ASSERT_I_(err == 0); | |
#else | |
::std::size_t __init_result = ::std::wcrtomb(__ghost_space, L'\0', &__wide_state); | |
#endif | |
// make sure it is initialized | |
ZTD_TEXT_ASSERT_I_(__init_result == 1 && __ghost_space[0] == '\0'); | |
ZTD_TEXT_ASSERT_I_(::std::mbsinit(&__wide_state) != 0); | |
} | |
}; | |
class __wide_execution_encode_state { | |
public: | |
::std::mbstate_t __wide_state; | |
encode_state_t<execution> __narrow_state; | |
// TODO: states need to be split into 2 | |
// different states, optionally... | |
__wide_execution_encode_state() noexcept : __wide_state(), __narrow_state() { | |
wchar_t __ghost_space[2]; | |
::std::size_t __init_result = ::std::mbrtowc(__ghost_space, "", 1, &__wide_state); | |
// make sure it is initialized | |
ZTD_TEXT_ASSERT_I_(__init_result == 0 && __ghost_space[0] == L'\0'); | |
ZTD_TEXT_ASSERT_I_(::std::mbsinit(&__wide_state) != 0); | |
} | |
}; | |
} // namespace __txt_detail | |
////// | |
/// @brief The Encoding that represents the "Wide Execution" (wide locale-based) encoding. The wide execution | |
/// encoding is typically associated with the locale, which is tied to the C standard library's setlocale function. | |
/// @remarks Windows uses UTF-16, unless you call the C Standard Library directly. If @c ZTD_TEXT_USE_CUNEICODE is | |
/// not defined, this object may use the C Standard Library to perform transcoding if certain platform facilities | |
/// are disabled or not available. If this is the case, the C Standard Library has fundamental limitations which | |
/// may treat your UTF-16 data like UCS-2, and result in broken input/output. This object uses UTF-16 directly on | |
/// Windows when possible to avoid some of the platform-specific shenanigans. | |
////// | |
class wide_execution { | |
public: | |
////// | |
/// @brief The individual units that result from an encode operation or are used as input to a decode | |
/// operation. | |
/// | |
/// @remarks Please note that wchar_t is a variably sized type across platforms and may not represent either | |
/// UTF-16 or UTF-32, including on *nix or POSIX platforms. | |
////// | |
using code_unit = wchar_t; | |
////// | |
/// @brief The individual units that result from a decode operation or as used as input to an encode | |
/// operation. For most encodings, this is going to be a Unicode Code Point or a Unicode Scalar Value. | |
////// | |
using code_point = unicode_code_point; | |
private: | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_PLATFORM_WINDOWS_I_) | |
using __wide_decode_state = decode_state_t<__impl::__utf16_with<void, wchar_t, code_point, false>>; | |
using __wide_encode_state = encode_state_t<__impl::__utf16_with<void, wchar_t, code_point, false>>; | |
#else | |
using __wide_decode_state = __txt_detail::__wide_execution_decode_state; | |
using __wide_encode_state = __txt_detail::__wide_execution_encode_state; | |
#endif // Windows | |
public: | |
////// | |
/// @brief The state of the wide execution encoding used between calls, which may potentially manage shift | |
/// state. | |
/// | |
/// @remarks This type can potentially have lots of state due to the way the C API is specified. | |
////// | |
using decode_state = __wide_decode_state; | |
////// | |
/// @brief The state of the wide execution encoding used between calls, which may potentially manage shift | |
/// state. | |
/// | |
/// @remarks This type can potentially have lots of state due to the way the C API is specified. | |
////// | |
using encode_state = __wide_encode_state; | |
////// | |
/// @brief Whether or not the decode operation can process all forms of input into code point values. | |
/// | |
/// @remarks All known wide execution encodings can decode into Unicode just fine. | |
////// | |
using is_decode_injective = | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_PLATFORM_WINDOWS_I_) | |
::std::true_type; | |
#else | |
::std::false_type; | |
#endif | |
////// | |
/// @brief Whether or not the encode operation can process all forms of input into code unit values. On | |
/// Windows, this is guaranteed to be UTF-16 encoding for the platform. Normally, this is UTF-32 on *nix/POSIX | |
/// machines, but it can (and has been) changed before, sometimes even at runtime. | |
/// | |
/// @remarks IBM encodings/computers make life interesting... | |
////// | |
using is_encode_injective = | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_PLATFORM_WINDOWS_I_) | |
::std::true_type; | |
#else | |
::std::false_type; | |
#endif | |
////// | |
/// @brief Whether or not this encoding a Unicode encoding of some type. | |
/// | |
/// @remarks On Windows, this is always true. On other platforms, the guarantees are not quite there. IBM | |
/// encodings/computers make life interesting... | |
////// | |
using is_unicode_encoding = | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_PLATFORM_WINDOWS_I_) | |
::std::true_type; | |
#else | |
::std::false_type; | |
#endif | |
////// | |
/// @brief The maximum code units a single complete operation of encoding can produce. | |
/// | |
////// | |
inline static constexpr const ::std::size_t max_code_units = 8; | |
////// | |
/// @brief The maximum number of code points a single complete operation of decoding can produce. | |
/// | |
////// | |
inline static constexpr const ::std::size_t max_code_points = 4; | |
////// | |
/// @brief Returns whether or not this encoding is a unicode encoding. | |
/// | |
/// @remarks This function operates at runtime and queries the existing locale through a variety of | |
/// platform-specific means (such as @c nl_langinfo for POSIX, ACP probing on Windows, or fallin back to @c | |
/// std::setlocale name checking otherwise). | |
////// | |
static bool contains_unicode_encoding() noexcept { | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_PLATFORM_WINDOWS_I_) | |
return true; | |
#elif ZTD_TEXT_IS_ON(ZTD_TEXT_LOCALE_DEPENDENT_WIDE_EXECUTION_I_) | |
// On very specific platforms, we must probe...... | |
// ... but we don't have the code right now to do that properly. | |
// When we do, it'll go in the detail/posix.hpp ! | |
return false; | |
#else | |
return false; | |
#endif | |
} | |
////// | |
/// @brief Encodes a single complete unit of information as code units and produces a result with the | |
/// input and output ranges moved past what was successfully read and written; or, produces an error and | |
/// returns the input and output ranges untouched. | |
/// | |
/// @param[in] __input The input view to read code uunits from. | |
/// @param[in] __output The output view to write code points into. | |
/// @param[in] __error_handler The error handler to invoke if encoding fails. | |
/// @param[in, out] __s The necessary state information. Most encodings have no state, but because this is | |
/// effectively a runtime encoding and therefore it is important to preserve and manage this state. | |
/// | |
/// @returns A ztd::text::encode_result object that contains the reconstructed input range, | |
/// reconstructed output range, error handler, and a reference to the passed-in state. | |
/// | |
/// @remarks Platform APIs and/or the C Standard Library may be used to properly decode one complete unit of | |
/// information (alongside std::mbstate_t usage). Whether or not the state is used is based on the | |
/// implementation and what it chooses. If ZTD_TEXT_USE_CUNEICODE is defined, the ztd.cuneicode library may be | |
/// used to fulfill this functionality. | |
/// | |
/// @remarks To the best ability of the implementation, the iterators will be | |
/// returned untouched (e.g., the input models at least a view and a forward_range). If it is not possible, | |
/// returned ranges may be incremented even if an error occurs due to the semantics of any view that models an | |
/// input_range. | |
////// | |
template <typename _InputRange, typename _OutputRange, typename _ErrorHandler> | |
static constexpr auto encode_one( | |
_InputRange&& __input, _OutputRange&& __output, _ErrorHandler&& __error_handler, encode_state& __s) { | |
using _UErrorHandler = __txt_detail::__remove_cvref_t<_ErrorHandler>; | |
using _Result = __txt_detail::__reconstruct_encode_result_t<_InputRange, _OutputRange, encode_state>; | |
constexpr bool __call_error_handler = !is_ignorable_error_handler_v<_UErrorHandler>; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_PLATFORM_WINDOWS_I_) | |
using __u16e = __impl::__utf16_with<void, wchar_t, code_point, false>; | |
using __intermediate_state = encode_state_t<__u16e>; | |
__u16e __u16enc {}; | |
__intermediate_state __intermediate_s {}; | |
__txt_detail::__progress_handler<!__call_error_handler, wide_execution> __intermediate_handler {}; | |
auto __result = __u16enc.encode_one(::std::forward<_InputRange>(__input), | |
::std::forward<_OutputRange>(__output), __intermediate_handler, __intermediate_s); | |
if (__result.error_code != encoding_error::ok) { | |
wide_execution __self {}; | |
return __error_handler(__self, | |
_Result(::std::move(__result.input), ::std::move(__result.output), __s, __result.error_code), | |
::ztd::text::span<code_point>(__intermediate_handler._M_code_points.data(), | |
__intermediate_handler._M_code_points_size)); | |
} | |
return _Result(::std::move(__result.input), ::std::move(__result.output), __s, __result.error_code); | |
#else | |
using _UInputRange = __txt_detail::__remove_cvref_t<_InputRange>; | |
using _UOutputRange = __txt_detail::__remove_cvref_t<_OutputRange>; | |
auto __init = __txt_detail::__adl::__adl_begin(__input); | |
auto __inlast = __txt_detail::__adl::__adl_end(__input); | |
if (__init == __inlast) { | |
// an exhausted sequence is fine | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::forward<_OutputRange>(__output)), | |
__s, encoding_error::ok); | |
} | |
auto __outit = __txt_detail::__adl::__adl_begin(__output); | |
auto __outlast = __txt_detail::__adl::__adl_end(__output); | |
constexpr const ::std::size_t __state_max = 32; | |
char __intermediate_buffer[__state_max + 1] {}; | |
char* __intermediate_start = &__intermediate_buffer[0]; | |
::ztd::text::span<char, __state_max> __intermediate_output(__intermediate_start, __state_max); | |
execution __exec {}; | |
__txt_detail::__progress_handler<!__call_error_handler, wide_execution> __intermediate_handler {}; | |
auto __result = __exec.encode_one(::std::forward<_InputRange>(__input), __intermediate_output, | |
__intermediate_handler, __s.__narrow_state); | |
if constexpr (__call_error_handler) { | |
if (__result.error_code != encoding_error::ok) { | |
wide_execution __self {}; | |
return __error_handler(__self, | |
_Result(::std::move(__result.input), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, __result.error_code), | |
::ztd::text::span<code_point>(__intermediate_handler._M_code_points.data(), | |
__intermediate_handler._M_code_points_size)); | |
} | |
} | |
auto __current_input = ::ztd::text::span<char>(__intermediate_output.data(), | |
::std::distance(__intermediate_output.data(), __result.output.data())); | |
code_unit __units[1] {}; | |
::std::size_t __res = ::std::mbrtowc(::std::addressof(__units[0]), __current_input.data(), | |
__current_input.size(), ::std::addressof(__s.__wide_state)); | |
if (__res == static_cast<::std::size_t>(-1)) { | |
// error: cry about it | |
if constexpr (__call_error_handler) { | |
wide_execution __self {}; | |
return __error_handler(__self, | |
_Result(::std::move(__result.input), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::invalid_sequence), | |
::ztd::text::span<code_point>(__intermediate_handler._M_code_points.data(), | |
__intermediate_handler._M_code_points_size)); | |
} | |
} | |
else if (__res == static_cast<::std::size_t>(-2)) { | |
// incomplete sequence | |
if constexpr (__call_error_handler) { | |
wide_execution __self {}; | |
return __error_handler(__self, | |
_Result(::std::move(__result.input), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::incomplete_sequence), | |
::ztd::text::span<code_point>(__intermediate_handler._M_code_points.data(), | |
__intermediate_handler._M_code_points_size)); | |
} | |
} | |
__txt_detail::__dereference(__outit) = __units[0]; | |
__txt_detail::__advance(__outit); | |
return _Result(::std::move(__result.input), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::move(__outit), ::std::move(__outlast)), | |
__s, __result.error_code); | |
#endif // Windows | |
} | |
////// | |
/// @brief Decodes a single complete unit of information as code points and produces a result with the | |
/// input and output ranges moved past what was successfully read and written; or, produces an error and | |
/// returns the input and output ranges untouched. | |
/// | |
/// @param[in] __input The input view to read code uunits from. | |
/// @param[in] __output The output view to write code points into. | |
/// @param[in] __error_handler The error handler to invoke if encoding fails. | |
/// @param[in, out] __s The necessary state information. Most encodings have no state, but because this is | |
/// effectively a runtime encoding and therefore it is important to preserve and manage this state. | |
/// | |
/// @returns A ztd::text::decode_result object that contains the reconstructed input range, | |
/// reconstructed output range, error handler, and a reference to the passed-in state. | |
/// | |
/// @remarks Platform APIs and/or the C Standard Library may be used to properly decode one complete unit of | |
/// information (alongside std::mbstate_t usage). Whether or not the state is used is based on the | |
/// implementation and what it chooses. If @c ZTD_TEXT_USE_CUNEICODE is defined, the ztd.cuneicode library may | |
/// be used to fulfill this functionality. | |
/// | |
/// @remarks To the best ability of the implementation, the iterators will be | |
/// returned untouched (e.g., the input models at least a view and a forward_range). If it is not possible, | |
/// returned ranges may be incremented even if an error occurs due to the semantics of any view that models an | |
/// input_range. | |
////// | |
template <typename _InputRange, typename _OutputRange, typename _ErrorHandler> | |
static constexpr auto decode_one( | |
_InputRange&& __input, _OutputRange&& __output, _ErrorHandler&& __error_handler, decode_state& __s) { | |
using _UErrorHandler = __txt_detail::__remove_cvref_t<_ErrorHandler>; | |
using _Result = __txt_detail::__reconstruct_decode_result_t<_InputRange, _OutputRange, decode_state>; | |
constexpr bool __call_error_handler = !is_ignorable_error_handler_v<_UErrorHandler>; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_PLATFORM_WINDOWS_I_) | |
using __u16e = __impl::__utf16_with<void, wchar_t, code_point, false>; | |
using __intermediate_state = decode_state_t<__u16e>; | |
__u16e __u16enc {}; | |
__txt_detail::__progress_handler<!__call_error_handler, wide_execution> __intermediate_handler {}; | |
__intermediate_state __intermediate_s {}; | |
auto __result = __u16enc.decode_one(::std::forward<_InputRange>(__input), | |
::std::forward<_OutputRange>(__output), __intermediate_handler, __intermediate_s); | |
if constexpr (__call_error_handler) { | |
if (__result.error_code != encoding_error::ok) { | |
return __error_handler(wide_execution {}, | |
_Result( | |
::std::move(__result.input), ::std::move(__result.output), __s, __result.error_code), | |
::ztd::text::span<code_point>(__intermediate_handler._M_code_points.data(), | |
__intermediate_handler._M_code_points_size)); | |
} | |
} | |
return _Result(::std::move(__result.input), ::std::move(__result.output), __s, __result.error_code, | |
__result.handled_errors); | |
#else | |
using _UInputRange = __txt_detail::__remove_cvref_t<_InputRange>; | |
using _UOutputRange = __txt_detail::__remove_cvref_t<_OutputRange>; | |
auto __init = __txt_detail::__adl::__adl_begin(__input); | |
auto __inlast = __txt_detail::__adl::__adl_end(__input); | |
if (__init == __inlast) { | |
// an exhausted sequence is fine | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct( | |
::std::in_place_type<_UOutputRange>, ::std::forward<_OutputRange>(__output)), | |
__s, encoding_error::ok); | |
} | |
auto __outit = __txt_detail::__adl::__adl_begin(__output); | |
auto __outlast = __txt_detail::__adl::__adl_end(__output); | |
if constexpr (__call_error_handler) { | |
if (__outit == __outlast) { | |
wide_execution __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::insufficient_output_space), | |
::ztd::text::span<code_unit, 0>()); | |
} | |
} | |
constexpr const ::std::size_t __state_max = 32; | |
char __intermediate_buffer[__state_max + 1] {}; | |
::std::size_t __state_count = 0; | |
code_unit __units[__state_max] {}; | |
::std::size_t __units_count = 0; | |
for (; __state_count < __state_max;) { | |
__units[__units_count] = __txt_detail::__dereference(__init); | |
const code_unit& __unit = __units[__units_count]; | |
++__units_count; | |
__txt_detail::__advance(__init); | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_LIBVCXX_I_) | |
::std::size_t __res; | |
errno_t __err = wcrtomb_s(::std::addressof(__res), __intermediate_buffer, __state_max, __unit, | |
::std::addressof(__s.__wide_state)); | |
if constexpr (__call_error_handler) { | |
if (__err != 0) { | |
// error: cry about it | |
wide_execution __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::invalid_sequence), | |
::ztd::text::span<code_unit>(::std::addressof(__units[0]), __units_count)); | |
} | |
} | |
else { | |
(void)__err; | |
} | |
#else | |
::std::size_t __res | |
= ::std::wcrtomb(__intermediate_buffer, __unit, ::std::addressof(__s.__wide_state)); | |
#endif | |
if (__res == static_cast<::std::size_t>(-1)) { | |
if constexpr (__call_error_handler) { | |
// error: cry about it | |
wide_execution __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
__txt_detail::__reconstruct(::std::in_place_type<_UOutputRange>, | |
::std::move(__outit), ::std::move(__outlast)), | |
__s, encoding_error::invalid_sequence), | |
::ztd::text::span<code_unit>(::std::addressof(__units[0]), __units_count)); | |
} | |
} | |
else if (__res == 0) { | |
if (::std::mbsinit(::std::addressof(__s.__wide_state)) == 0) { | |
// mixed conversion potential?! | |
// technically, not standard behavior, but I don't really care? | |
// Mr. Steve Downey points out I'm slightly right | |
// about my assumption here: C has an open DR for this | |
// (DR 488, http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2059.htm#dr_488) | |
// Another DR, DR 499 (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2059.htm#dr_498) | |
// addresses thread safety issues, both should be | |
// solved is this is to be anywhere near usable | |
if constexpr (__call_error_handler) { | |
if (__init == __inlast) { | |
wide_execution __self {}; | |
return __error_handler(__self, | |
_Result(::std::forward<_InputRange>(__input), | |
::std::forward<_OutputRange>(__output), __s, | |
encoding_error::incomplete_sequence), | |
::ztd::text::span<code_unit>(::std::addressof(__units[0]), __units_count)); | |
} | |
} | |
continue; | |
} | |
} | |
__state_count += __res; | |
break; | |
} | |
execution __exec {}; | |
__txt_detail::__pass_through_handler_with<!__call_error_handler> __exec_handler {}; | |
::ztd::text::span<char, __state_max> __intermediate_input(__intermediate_buffer, __state_max); | |
auto __result = __exec.decode_one( | |
__intermediate_input, ::std::forward<_OutputRange>(__output), __exec_handler, __s.__narrow_state); | |
if constexpr (__call_error_handler) { | |
if (__result.error_code != encoding_error::ok) { | |
wide_execution __self {}; | |
return __error_handler(__self, | |
_Result(__txt_detail::__reconstruct(::std::in_place_type<_UInputRange>, | |
::std::move(__init), ::std::move(__inlast)), | |
::std::move(__result.output), __s, __result.error_code), | |
::ztd::text::span<code_unit>(::std::addressof(__units[0]), __units_count)); | |
} | |
} | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_UInputRange>, ::std::move(__init), ::std::move(__inlast)), | |
::std::move(__result.output), __s, __result.error_code); | |
#endif | |
} | |
}; | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/wide_execution.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/literal.hpp | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
inline constexpr __encoding_id __literal_id = __to_encoding_id(ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_GET_I_()); | |
using __literal = decltype(__select_encoding<char, __literal_id>()); | |
} // namespace __txt_detail | |
////// | |
/// @brief The encoding of string literals ( e.g. @c "👍" ) at compile time. | |
/// | |
////// | |
class literal : private __txt_detail::__ebco<__txt_detail::__literal> { | |
private: | |
using __underlying_t = __txt_detail::__literal; | |
using __base_t = __txt_detail::__ebco<__underlying_t>; | |
public: | |
////// | |
/// @brief Whether or not this literal encoding is a Unicode Transformation Format, such as UTF-8, | |
/// UTF-EBCDIC, or GB18030. | |
////// | |
using is_unicode_encoding | |
= ::std::integral_constant<bool, __txt_detail::__is_unicode_encoding_id(__txt_detail::__literal_id)>; | |
////// | |
/// @brief The individual units that result from an encode operation or are used as input to a decode | |
/// operation. | |
////// | |
using code_unit = code_unit_t<__underlying_t>; | |
////// | |
/// @brief The individual units that result from a decode operation or as used as input to an encode | |
/// operation. For most encodings, this is going to be a Unicode Code Point or a Unicode Scalar Value. | |
////// | |
using code_point = code_point_t<__underlying_t>; | |
////// | |
/// @brief The state that can be used between calls to encode_one. | |
/// | |
////// | |
using encode_state = encode_state_t<__underlying_t>; | |
////// | |
/// @brief The state that can be used between calls to decode_one. | |
/// | |
////// | |
using decode_state = decode_state_t<__underlying_t>; | |
////// | |
/// @brief Whether or not the decode operation can process all forms of input into code point values. | |
/// | |
/// @remarks The decode step should always be injective because every encoding used for literals in C++ | |
/// needs to be capable of being represented by UCNs. Whether or not a platform is a jerk, who knows? | |
////// | |
using is_decode_injective = ::std::integral_constant<bool, is_decode_injective_v<__underlying_t>>; | |
////// | |
/// @brief Whether or not the encode operation can process all forms of input into code unit values. | |
/// | |
/// @remarks This is absolutely not guaranteed to be the case, and as such we must check the provided encoding | |
/// name for us to be sure. | |
////// | |
using is_encode_injective = ::std::integral_constant<bool, is_encode_injective_v<__underlying_t>>; | |
////// | |
/// @brief The maximum number of code points a single complete operation of decoding can produce. | |
/// | |
////// | |
inline static constexpr ::std::size_t max_code_points = 16; | |
////// | |
/// @brief The maximum code units a single complete operation of encoding can produce. | |
/// | |
////// | |
inline static constexpr ::std::size_t max_code_units = 32; | |
////// | |
/// @brief Default constructs a ztd::text::literal. | |
/// | |
////// | |
constexpr literal() noexcept = default; | |
////// | |
/// @brief Copy constructs a ztd::text::literal. | |
/// | |
////// | |
constexpr literal(const literal&) noexcept = default; | |
////// | |
/// @brief Move constructs a ztd::text::literal. | |
/// | |
////// | |
constexpr literal(literal&&) noexcept = default; | |
////// | |
/// @brief Copy assigns into a ztd::text::literal object. | |
/// | |
////// | |
constexpr literal& operator=(const literal&) noexcept = default; | |
////// | |
/// @brief Move assigns into a ztd::text::literal object. | |
/// | |
////// | |
constexpr literal& operator=(literal&&) noexcept = default; | |
////// | |
/// @brief Decodes a single complete unit of information as code points and produces a result with the | |
/// input and output ranges moved past what was successfully read and written; or, produces an error and | |
/// returns the input and output ranges untouched. | |
/// | |
/// @param[in] __input The input view to read code uunits from. | |
/// @param[in] __output The output view to write code points into. | |
/// @param[in] __error_handler The error handler to invoke if encoding fails. | |
/// @param[in, out] __state The necessary state information. For this encoding, the state is empty and means | |
/// very little. | |
/// | |
/// @returns A ztd::text::decode_result object that contains the reconstructed input range, | |
/// reconstructed output range, error handler, and a reference to the passed-in state. | |
/// | |
/// @remarks To the best ability of the implementation, the iterators will be returned untouched (e.g., | |
/// the input models at least a view and a forward_range). If it is not possible, returned ranges may be | |
/// incremented even if an error occurs due to the semantics of any view that models an input_range. | |
////// | |
template <typename _Input, typename _Output, typename _ErrorHandler> | |
constexpr auto decode_one( | |
_Input&& __input, _Output&& __output, _ErrorHandler&& __error_handler, decode_state& __state) const { | |
#if ZTD_TEXT_IS_OFF(ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_I_) \ | |
&& ZTD_TEXT_IS_OFF(ZTD_TEXT_YES_PLEASE_DESTROY_MY_LITERALS_UTTERLY_I_MEAN_IT_I_) | |
// Cry bitter tears, I guess? | |
static_assert(__txt_detail::__always_false_v<_Input>, | |
"[[ PLEASE. READ. ]] Your compiler does not implement any known way of getting the string literal " | |
"encoding from the machine at compile time and you are trying to use the literal encoding " | |
"type, somewhere. If this is the Microsoft Visual C/C++ Compiler (MSVC), then go upvote this issue " | |
"here (https://developercommunity.visualstudio.com/content/idea/1160821/" | |
"-compiler-feature-macro-for-narrow-literal-foo-enc.html) and leave a (strong, but very nicely " | |
"spoken) request to implement the functionality. If you are part of the C++ Standards Committee, " | |
"please make sure p1885 (https://wg21.link/p1885) gets passed so we don't need to keep doing this " | |
"nonsense. If you are on some other compiler,\n\n" | |
"God's Speed.\n\n" | |
"This could mangle all of your compile time string literal conversions you are performing. To " | |
"prevent that from happening, this error is being printed out, so that you have the explicit " | |
"understanding that your life may indeed suck after doing this.\n\n" | |
"Please add ZTD_TEXT_YES_PLEASE_DESTROY_MY_LITERALS_UTTERLY_I_MEAN_IT to your command line to " | |
"ignore this error and we will get right on doing exactly that for you."); | |
#endif | |
#if ZTD_TEXT_IS_OFF(ZTD_TEXT_YES_PLEASE_DESTROY_MY_LITERALS_UTTERLY_I_MEAN_IT_I_) | |
static_assert(__txt_detail::__always_true_v<_Input> | |
&& !__txt_detail::__is_specialization_of_v<__base_t, basic_no_encoding>, | |
"[[ Please read! ]] This text encoding (" | |
ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_DESCRIPTION_I_() "), while recognized, is not " | |
"supported because it hasn't yet been implemented! You can see all the encodings we have " | |
"support for in our documentation (https://ztdtext.rtfd.io/en/latest/encodings.html).\n\n" | |
"If you need this to be implemented, please reach out at the repository or to the contact " | |
"addresses in the repository. If you absolutely don't give a damn, specify please add " | |
"ZTD_TEXT_YES_PLEASE_DESTROY_MY_LITERALS_UTTERLY_I_MEAN_IT to your command line to " | |
"ignore this error and we will get right on doing exactly that for you."); | |
#endif | |
__txt_detail::__forwarding_handler<const literal, __txt_detail::__remove_cvref_t<_ErrorHandler>> | |
__underlying_handler(*this, __error_handler); | |
return this->__base_t::__get_value().decode_one( | |
::std::forward<_Input>(__input), ::std::forward<_Output>(__output), __underlying_handler, __state); | |
} | |
////// | |
/// @brief Encodes a single complete unit of information as code units and produces a result with the | |
/// input and output ranges moved past what was successfully read and written; or, produces an error and | |
/// returns the input and output ranges untouched. | |
/// | |
/// @param[in] __input The input view to read code points from. | |
/// @param[in] __output The output view to write code units into. | |
/// @param[in] __error_handler The error handler to invoke if encoding fails. | |
/// @param[in, out] __state The necessary state information. For this encoding, the state is empty and means | |
/// very little. | |
/// | |
/// @returns A ztd::text::encode_result object that contains the reconstructed input range, | |
/// reconstructed output range, error handler, and a reference to the passed-in state. | |
/// | |
/// @remarks To the best ability of the implementation, the iterators will be returned untouched (e.g., | |
/// the input models at least a view and a forward_range). If it is not possible, returned ranges may be | |
/// incremented even if an error occurs due to the semantics of any view that models an input_range. | |
////// | |
template <typename _Input, typename _Output, typename _ErrorHandler> | |
constexpr auto encode_one( | |
_Input&& __input, _Output&& __output, _ErrorHandler&& __error_handler, encode_state& __state) const { | |
#if ZTD_TEXT_IS_OFF(ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_I_) \ | |
&& ZTD_TEXT_IS_OFF(ZTD_TEXT_YES_PLEASE_DESTROY_MY_LITERALS_UTTERLY_I_MEAN_IT_I_) | |
// Cry bitter tears, I guess? | |
static_assert(__txt_detail::__always_false_v<_Input>, | |
"[[ PLEASE. READ. ]] Your compiler does not implement any known way of getting the string literal " | |
"encoding from the machine at compile time and you are trying to use the literal encoding " | |
"type, somewhere. If this is the Microsoft Visual C/C++ Compiler (MSVC), then go upvote this issue " | |
"here (https://developercommunity.visualstudio.com/content/idea/1160821/" | |
"-compiler-feature-macro-for-narrow-literal-foo-enc.html) and leave a (strong, but very nicely " | |
"spoken) request to implement the functionality. If you are part of the C++ Standards Committee, " | |
"please make sure p1885 (https://wg21.link/p1885) gets passed so we don't need to keep doing this " | |
"nonsense. If you are on some other compiler,\n\n" | |
"God's Speed.\n\n" | |
"This could mangle all of your compile time string literal conversions you are performing. To " | |
"prevent that from happening, this error is being printed out, so that you have the explicit " | |
"understanding that your life may indeed suck after doing this.\n\n" | |
"Please add ZTD_TEXT_YES_PLEASE_DESTROY_MY_LITERALS_UTTERLY_I_MEAN_IT to your command line to " | |
"ignore this error and we will get right on doing exactly that for you."); | |
#endif | |
#if ZTD_TEXT_IS_OFF(ZTD_TEXT_YES_PLEASE_DESTROY_MY_LITERALS_UTTERLY_I_MEAN_IT_I_) | |
static_assert(__txt_detail::__always_true_v<_Input> && !__txt_detail::__is_specialization_of_v<__base_t, basic_no_encoding>, | |
"[[ Please read! ]] This text encoding (" | |
ZTD_TEXT_COMPILE_TIME_ENCODING_NAME_DESCRIPTION_I_() "), while recognized, is not " | |
"supported because it hasn't yet been implemented! You can see all the encodings we have " | |
"support for in our documentation (https://ztdtext.rtfd.io/en/latest/encodings.html).\n\n" | |
"If you need this to be implemented, please reach out at the repository or to the contact " | |
"addresses in the repository. If you absolutely don't give a damn, specify please add " | |
"ZTD_TEXT_YES_PLEASE_DESTROY_MY_LITERALS_UTTERLY_I_MEAN_IT to your command line to " | |
"ignore this error and we will get right on doing exactly that for you."); | |
#endif | |
__txt_detail::__forwarding_handler<const literal, __txt_detail::__remove_cvref_t<_ErrorHandler>> | |
__underlying_handler(*this, __error_handler); | |
return this->__base_t::__get_value().encode_one( | |
::std::forward<_Input>(__input), ::std::forward<_Output>(__output), __underlying_handler, __state); | |
} | |
}; | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/literal.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/wide_literal.hpp | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
inline constexpr __encoding_id __wide_literal_id | |
= __to_encoding_id(ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_GET_I_()); | |
using __wide_literal = decltype(__select_encoding<wchar_t, __wide_literal_id>()); | |
} // namespace __txt_detail | |
////// | |
/// @brief The encoding of wide string literals ( e.g. @c "👍" ) at compile time. | |
/// | |
////// | |
class wide_literal : private __txt_detail::__ebco<__txt_detail::__wide_literal, 0> { | |
private: | |
using __underlying_t = __txt_detail::__wide_literal; | |
using __base_t = __txt_detail::__ebco<__underlying_t, 0>; | |
public: | |
////// | |
/// @brief Whether or not this wide_literal encoding is a Unicode Transformation Format, such as UTF-GB18030, | |
/// UTF-16, or UTF-32. | |
////// | |
using is_unicode_encoding = ::std::integral_constant<bool, | |
__txt_detail::__is_unicode_encoding_id(__txt_detail::__wide_literal_id)>; | |
////// | |
/// @brief The individual units that result from an encode operation or are used as input to a decode | |
/// operation. | |
////// | |
using code_unit = code_unit_t<__underlying_t>; | |
////// | |
/// @brief The individual units that result from a decode operation or as used as input to an encode | |
/// operation. For most encodings, this is going to be a Unicode Code Point or a Unicode Scalar Value. | |
////// | |
using code_point = code_point_t<__underlying_t>; | |
////// | |
/// @brief The state that can be used between calls to encode_one. | |
/// | |
////// | |
using encode_state = encode_state_t<__underlying_t>; | |
////// | |
/// @brief The state that can be used between calls to decode_one. | |
/// | |
////// | |
using decode_state = decode_state_t<__underlying_t>; | |
////// | |
/// @brief Whether or not the decode operation can process all forms of input into code point values. | |
/// | |
/// @remarks The decode step is always injective because every encoding used for literals in C++ needs to be | |
/// capable of being represented by UCNs. | |
////// | |
using is_decode_injective = ::std::integral_constant<bool, is_decode_injective_v<__underlying_t>>; | |
////// | |
/// @brief Whether or not the encode operation can process all forms of input into code unit values. | |
/// | |
/// @remarks This is absolutely not guaranteed to be the case, and as such we must check the provided encoding | |
/// name for wide to be sure. | |
////// | |
using is_encode_injective = ::std::integral_constant<bool, is_encode_injective_v<__underlying_t>>; | |
////// | |
/// @brief The maximum number of code points a single complete operation of decoding can produce. | |
/// | |
////// | |
inline static constexpr ::std::size_t max_code_points = 8; | |
////// | |
/// @brief The maximum code units a single complete operation of encoding can produce. | |
/// | |
////// | |
inline static constexpr ::std::size_t max_code_units = 16; | |
////// | |
/// @brief Default constructs a ztd::text::wide_literal. | |
/// | |
////// | |
constexpr wide_literal() noexcept = default; | |
////// | |
/// @brief Copy constructs a ztd::text::wide_literal. | |
/// | |
////// | |
constexpr wide_literal(const wide_literal&) noexcept = default; | |
////// | |
/// @brief Move constructs a ztd::text::wide_literal. | |
/// | |
////// | |
constexpr wide_literal(wide_literal&&) noexcept = default; | |
////// | |
/// @brief Copy assigns into a ztd::text::wide_literal object. | |
/// | |
////// | |
constexpr wide_literal& operator=(const wide_literal&) noexcept = default; | |
////// | |
/// @brief Move assigns into a ztd::text::wide_literal object. | |
/// | |
////// | |
constexpr wide_literal& operator=(wide_literal&&) noexcept = default; | |
////// | |
/// @brief Decodes a single complete unit of information as code points and produces a result with the | |
/// input and output ranges moved past what was successfully read and written; or, produces an error and | |
/// returns the input and output ranges untouched. | |
/// | |
/// @param[in] __input The input view to read code uunits from. | |
/// @param[in] __output The output view to write code points into. | |
/// @param[in] __error_handler The error handler to invoke if encoding fails. | |
/// @param[in, out] __state The necessary state information. For this encoding, the state is empty and means | |
/// very little. | |
/// | |
/// @returns A ztd::text::decode_result object that contains the reconstructed input range, | |
/// reconstructed output range, error handler, and a reference to the passed-in state. | |
/// | |
/// @remarks To the best ability of the implementation, the iterators will be returned untouched (e.g., | |
/// the input models at least a view and a forward_range). If it is not possible, returned ranges may be | |
/// incremented even if an error occurs due to the semantics of any view that models an input_range. | |
////// | |
template <typename _Input, typename _Output, typename _ErrorHandler> | |
constexpr auto decode_one( | |
_Input&& __input, _Output&& __output, _ErrorHandler&& __error_handler, decode_state& __state) const { | |
#if ZTD_TEXT_IS_OFF(ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_I_) \ | |
&& ZTD_TEXT_IS_OFF(ZTD_TEXT_YES_PLEASE_DESTROY_MY_WIDE_LITERALS_UTTERLY_I_MEAN_IT_I_) | |
// Cry bitter tears, I guess? | |
static_assert(__txt_detail::__always_false_v<_Input>, | |
"[[ PLEASE. READ. ]] Your compiler does not implement any known way of getting the string " | |
"wide_literal " | |
"encoding from the machine at compile time and you are trying to use the wide_literal encoding " | |
"type, somewhere. If this is the Microsoft Visual C/C++ Compiler (MSVC), then go upvote this issue " | |
"here (https://developercommunity.visualstudio.com/content/idea/1160821/" | |
"-compiler-feature-macro-for-narrow-wide_literal-foo-enc.html) and leave a (strong, but very " | |
"nicely " | |
"spoken) request to implement the functionality. If you are part of the C++ Standards Committee, " | |
"please make sure p1885 (https://wg21.link/p1885) gets passed so we don't need to keep doing this " | |
"nonsense. If you are on some other compiler,\n\n" | |
"God's Speed.\n\n" | |
"This could mangle all of your compile time wide string literal conversions you are performing. To " | |
"prevent that from happening, this error is being printed out, so that you have the explicit " | |
"understanding that your life may indeed suck after doing this.\n\n" | |
"Please add ZTD_TEXT_YES_PLEASE_DESTROY_MY_WIDE_LITERALS_UTTERLY_I_MEAN_IT to your command " | |
"line to ignore this error and we will get right on doing exactly that for you."); | |
#endif | |
#if ZTD_TEXT_IS_OFF(ZTD_TEXT_YES_PLEASE_DESTROY_MY_WIDE_LITERALS_UTTERLY_I_MEAN_IT_I_) | |
static_assert(__txt_detail::__always_true_v<_Input> | |
&& !__txt_detail::__is_specialization_of_v<__base_t, basic_no_encoding>, | |
"[[ Please read! ]] This text encoding (" | |
ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_DESCRIPTION_I_() "), while recognized, is not " | |
"supported because it hasn't yet been implemented! You can see all the encodings we have " | |
"support for in our documentation (https://ztdtext.rtfd.io/en/latest/encodings.html).\n\n" | |
"If you need this to be implemented, please reach out at the repository or to the contact " | |
"addresses in the repository. If you absolutely don't give a damn, specify please add " | |
"ZTD_TEXT_YES_PLEASE_DESTROY_MY_WIDE_LITERALS_UTTERLY_I_MEAN_IT to your command line to " | |
"ignore this error and we will get right on doing exactly that for you."); | |
#endif | |
__txt_detail::__forwarding_handler<const wide_literal, __txt_detail::__remove_cvref_t<_ErrorHandler>> | |
__underlying_handler(*this, __error_handler); | |
return this->__base_t::__get_value().decode_one( | |
::std::forward<_Input>(__input), ::std::forward<_Output>(__output), __underlying_handler, __state); | |
} | |
////// | |
/// @brief Encodes a single complete unit of information as code units and produces a result with the | |
/// input and output ranges moved past what was successfully read and written; or, produces an error and | |
/// returns the input and output ranges untouched. | |
/// | |
/// @param[in] __input The input view to read code points from. | |
/// @param[in] __output The output view to write code units into. | |
/// @param[in] __error_handler The error handler to invoke if encoding fails. | |
/// @param[in, out] __state The necessary state information. For this encoding, the state is empty and means | |
/// very little. | |
/// | |
/// @returns A ztd::text::encode_result object that contains the reconstructed input range, | |
/// reconstructed output range, error handler, and a reference to the passed-in state. | |
/// | |
/// @remarks To the best ability of the implementation, the iterators will be returned untouched (e.g., | |
/// the input models at least a view and a forward_range). If it is not possible, returned ranges may be | |
/// incremented even if an error occurs due to the semantics of any view that models an input_range. | |
////// | |
template <typename _Input, typename _Output, typename _ErrorHandler> | |
constexpr auto encode_one( | |
_Input&& __input, _Output&& __output, _ErrorHandler&& __error_handler, encode_state& __state) const { | |
#if ZTD_TEXT_IS_OFF(ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_I_) \ | |
&& ZTD_TEXT_IS_OFF(ZTD_TEXT_YES_PLEASE_DESTROY_MY_WIDE_LITERALS_UTTERLY_I_MEAN_IT_I_) | |
// Cry bitter tears, I guess? | |
static_assert(__txt_detail::__always_false_v<_Input>, | |
"[[ PLEASE. READ. ]] Your compiler does not implement any known way of getting the string " | |
"wide_literal " | |
"encoding from the machine at compile time and you are trying to use the wide_literal encoding " | |
"type, somewhere. If this is the Microsoft Visual C/C++ Compiler (MSVC), then go upvote this issue " | |
"here (https://developercommunity.visualstudio.com/content/idea/1160821/" | |
"-compiler-feature-macro-for-narrow-wide_literal-foo-enc.html) and leave a (strong, but very " | |
"nicely " | |
"spoken) request to implement the functionality. If you are part of the C++ Standards Committee, " | |
"please make sure p1885 (https://wg21.link/p1885) gets passed so we don't need to keep doing this " | |
"nonsense. If you are on some other compiler,\n\n" | |
"God's Speed.\n\n" | |
"This could mangle all of your compile time wide string literal conversions you are performing. To " | |
"prevent that from happening, this error is being printed out, so that you have the explicit " | |
"understanding that your life may indeed suck after doing this.\n\n" | |
"Please add ZTD_TEXT_YES_PLEASE_DESTROY_MY_WIDE_LITERALS_UTTERLY_I_MEAN_IT to your command " | |
"line to ignore this error and we will get right on doing exactly that for you."); | |
#endif | |
#if ZTD_TEXT_IS_OFF(ZTD_TEXT_YES_PLEASE_DESTROY_MY_WIDE_LITERALS_UTTERLY_I_MEAN_IT_I_) | |
static_assert(__txt_detail::__always_true_v<_Input> | |
&& !__txt_detail::__is_specialization_of_v<__base_t, basic_no_encoding>, | |
"[[ Please read! ]] This text encoding (" | |
ZTD_TEXT_COMPILE_TIME_WIDE_ENCODING_NAME_DESCRIPTION_I_() "), while recognized, is not " | |
"supported because it hasn't yet been implemented! You can see all the encodings we have " | |
"support for in our documentation (https://ztdtext.rtfd.io/en/latest/encodings.html).\n\n" | |
"If you need this to be implemented, please reach out at the repository or to the contact " | |
"addresses in the repository. If you absolutely don't give a damn, specify please add " | |
"ZTD_TEXT_YES_PLEASE_DESTROY_MY_WIDE_LITERALS_UTTERLY_I_MEAN_IT to your command line to " | |
"ignore this error and we will get right on doing exactly that for you."); | |
#endif | |
__txt_detail::__forwarding_handler<const wide_literal, __txt_detail::__remove_cvref_t<_ErrorHandler>> | |
__underlying_handler(*this, __error_handler); | |
return this->__base_t::__get_value().encode_one( | |
::std::forward<_Input>(__input), ::std::forward<_Output>(__output), __underlying_handler, __state); | |
} | |
}; | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/wide_literal.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/any_encoding.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/default_encoding.hpp | |
#include <cstdint> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _Type, bool _CompileTime> | |
class __default_code_unit_encoding { | |
private: | |
// clang-format off | |
using _ChosenType = ::std::conditional_t< | |
::std::is_same_v<_Type, char>, | |
::std::conditional_t<_CompileTime, literal, execution>, | |
::std::conditional_t<::std::is_same_v<_Type, wchar_t>, | |
::std::conditional_t<_CompileTime, wide_literal, wide_execution>, | |
::std::conditional_t<::std::is_same_v<_Type, signed char>, basic_ascii<signed char>, | |
::std::conditional_t<::std::is_same_v<_Type, uchar8_t>, utf8, | |
::std::conditional_t<::std::is_same_v<_Type, unsigned char>, basic_utf8<unsigned char>, | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_NATIVE_CHAR8_T_I_) | |
::std::conditional_t<::std::is_same_v<_Type, char8_t>, basic_utf8<char8_t>, | |
#endif | |
::std::conditional_t<::std::is_same_v<_Type, char16_t>, utf16, | |
::std::conditional_t<::std::is_same_v<_Type, char32_t>, utf32, | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_UNICODE_CODE_POINT_DISTINCT_TYPE_I_) | |
::std::conditional_t<::std::is_same_v<_Type, unicode_code_point>, basic_utf32<unicode_code_point>, | |
#endif | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_UNICODE_SCALAR_VALUE_DISTINCT_TYPE_I_) | |
::std::conditional_t<::std::is_same_v<_Type, unicode_scalar_value>, basic_utf32<unicode_scalar_value>, | |
#endif | |
::std::conditional_t<::std::is_same_v<_Type, ::std::byte>, encoding_scheme<utf8, endian::native, ::std::byte>, basic_no_encoding<_Type, unicode_code_point>> | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_UNICODE_SCALAR_VALUE_DISTINCT_TYPE_I_) | |
> | |
#endif | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_UNICODE_CODE_POINT_DISTINCT_TYPE_I_) | |
> | |
#endif | |
> | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_NATIVE_CHAR8_T_I_) | |
> | |
#endif | |
> | |
> | |
> | |
> | |
> | |
>; | |
// clang-format on | |
static_assert(!__txt_detail::__is_specialization_of_v<_ChosenType, basic_no_encoding>, | |
"there is no default encoding for the given code unit type"); | |
public: | |
////// | |
/// @brief The chosen type for the given code unit. | |
/// | |
/// @remarks The default encodings for code unit types are as follows | |
/// - @c char ➡ ztd::text::execution (runtime), ztd::text::literal (compiletime) | |
/// - @c wchar_t ➡ ztd::text::wide_execution (runtime), ztd::text::wide_literal (compiletime) | |
/// - @c char8_t ➡ ztd::text::utf8 | |
/// - @c ztd::text::uchar8_t ➡ ztd::text::utf8 (if different from @c char8_t type) | |
/// - @c std::byte ➡ ztd::text::basic_utf8<std::byte> | |
/// - @c signed char ➡ ztd::text::basic_ascii<signed char> | |
/// - @c char16_t ➡ ztd::text::utf16 | |
/// - @c char32_t ➡ ztd::text::utf32 | |
/// - @c unicode_code_point ➡ ztd::text::utf32 (if different from @c char32_t type) | |
/// - @c unicode_scalar_value ➡ ztd::text::utf32 (if different from @c char32_t type) | |
////// | |
using type = _ChosenType; | |
}; | |
template <typename _Type, bool> | |
class __default_code_point_encoding { | |
private: | |
static_assert(is_unicode_code_point_v<_Type> || ::std::is_same_v<_Type, char32_t>, | |
"there is no default encoding for the given code point type"); | |
public: | |
////// | |
/// @brief The chosen type for the given code unit. | |
/// | |
/// @remarks The default encodings for code point types are as follows | |
/// - @c char32_t ➡ ztd::text::utf8 | |
/// - @c unicode_code_point ➡ ztd::text::utf8 | |
/// - @c unicode_scalar_value ➡ ztd::text::utf8 | |
////// | |
using type = utf8; | |
}; | |
} // namespace __txt_detail | |
////// | |
/// @addtogroup ztd_text_properties Property and Trait Helpers | |
/// @{ | |
///// | |
////// | |
/// @brief The default encoding associated with a given code unit type, that serves as either input to a decode | |
/// operation or output from an encode operation. | |
/// | |
/// @tparam _Type The code unit type, with no cv-qualifiers | |
////// | |
template <typename _Type> | |
class default_code_unit_encoding : public __txt_detail::__default_code_unit_encoding<_Type, false> { }; | |
////// | |
/// @brief A @c typename alias for ztd::text::default_code_unit_encoding. | |
/// | |
/// @tparam _Type The code unit type, with no cv-qualifiers | |
////// | |
template <typename _Type> | |
using default_code_unit_encoding_t = typename default_code_unit_encoding<_Type>::type; | |
////// | |
/// @brief The default encoding associated with a given code unit type, that serves as either input to a decode | |
/// operation or output from an encode operation. This uses the additional information that this is compiletime, | |
/// not runtime, to help make the decision on what to do. | |
/// | |
/// @tparam _Type The code unit type, with no cv-qualifiers | |
////// | |
template <typename _Type> | |
class default_consteval_code_unit_encoding : public __txt_detail::__default_code_unit_encoding<_Type, true> { }; | |
////// | |
/// @brief A @c typename alias for ztd::text::default_consteval_code_unit_encoding. | |
/// | |
/// @tparam _Type The code unit type, with no cv-qualifiers | |
////// | |
template <typename _Type> | |
using default_consteval_code_unit_encoding_t = typename default_consteval_code_unit_encoding<_Type>::type; | |
////// | |
/// @brief The default encoding associated with a given code point type, that serves as either input to an encode | |
/// operation or output from decode operation. | |
/// | |
/// @tparam _Type The code point type, with no cv-qualifiers | |
////// | |
template <typename _Type> | |
class default_code_point_encoding : public __txt_detail::__default_code_point_encoding<_Type, false> { }; | |
////// | |
/// @brief A @c typename alias for ztd::text::default_code_point_encoding. | |
/// | |
/// @tparam _Type The code point type, with no cv-qualifiers | |
////// | |
template <typename _Type> | |
using default_code_point_encoding_t = typename default_code_point_encoding<_Type>::type; | |
////// | |
/// @brief The default encoding associated with a given code point type, that serves as either input to an encode | |
/// operation or output from decode operation. This uses additional information that this is at compile time, not | |
/// run time, to help make a decision as to what to do. | |
/// | |
/// @tparam _Type The code point type, with no cv-qualifiers | |
////// | |
template <typename _Type> | |
class default_consteval_code_point_encoding : public __txt_detail::__default_code_point_encoding<_Type, true> { }; | |
////// | |
/// @brief A @c typename alias for ztd::text::default_consteval_code_point_encoding. | |
/// | |
/// @tparam _Type The code point type, with no cv-qualifiers | |
////// | |
template <typename _Type> | |
using default_consteval_code_point_encoding_t = typename default_consteval_code_point_encoding<_Type>::type; | |
////// | |
/// @} | |
///// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/default_encoding.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/encode.hpp | |
#include <string> | |
#include <vector> | |
#include <string_view> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_encode ztd::text::encode[_into] | |
/// @brief These functions convert from a view of input code points into a view of output code units using | |
/// either the inferred or specified encoding. If no error handler is provided, the equivalent of the | |
/// ztd::text::default_handler is used by default. If no associated state is provided for the encoding, one will be | |
/// created with automatic storage duration (as a "stack" variable) for the provided encoding. | |
/// @{ | |
////// | |
////// | |
/// @brief Converts the code points of the given @p __input view through the encoding to code units into the | |
/// @p | |
/// __output view. | |
/// | |
/// @param[in] __input An input_view to read code points from and use in the encode operation that will | |
/// produce code units. | |
/// @param[in] __encoding The encoding that will be used to encode the input's code points into | |
/// output code units. | |
/// @param[in] __output An output_view to write code units to as the result of the encode operation from | |
/// the intermediate code points. | |
/// @param[in] __error_handler The error handlers for the from and to encodings, | |
/// respectively. | |
/// @param[in,out] __state A reference to the associated state for the @p __encoding 's encode step. | |
/// | |
/// @result A ztd::text::encode_result object that contains references to @p __state. | |
/// | |
/// @remarks This function does not attempt to call any extension points for encoding. It simply uses the | |
/// encoding and attempts to encode by repeatedly calling the encoding's required @c encode_one function. | |
////// | |
template <typename _Input, typename _Encoding, typename _Output, typename _ErrorHandler, typename _State> | |
constexpr auto basic_encode_into(_Input&& __input, _Encoding&& __encoding, _Output&& __output, | |
_ErrorHandler&& __error_handler, _State& __state) { | |
using _IntermediateInput = __txt_detail::__string_view_or_span_or_reconstruct_t<_Input>; | |
using _IntermediateOutput = __txt_detail::__reconstruct_t<_Output>; | |
using _Result = decltype(__encoding.encode_one( | |
::std::declval<_IntermediateInput>(), ::std::declval<_IntermediateOutput>(), __error_handler, __state)); | |
using _WorkingInput = __txt_detail::__remove_cvref_t<decltype(::std::declval<_Result>().input)>; | |
using _WorkingOutput = __txt_detail::__remove_cvref_t<decltype(::std::declval<_Result>().output)>; | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
using _UErrorHandler = __txt_detail::__remove_cvref_t<_ErrorHandler>; | |
static_assert(__txt_detail::__is_encode_lossless_or_deliberate_v<_UEncoding, _UErrorHandler>, | |
"This encode is a lossy, non-injective operation. This means you may lose data that you did not " | |
"intend " | |
"to lose; specify a 'handler' error handler parameter to encode(in, encoding, handler, ...) or " | |
"encode_into(in, encoding, out, handler, ...) explicitly in order to bypass this."); | |
_WorkingInput __working_input | |
= __txt_detail::__string_view_or_span_or_reconstruct(::std::forward<_Input>(__input)); | |
_WorkingOutput __working_output | |
= __txt_detail::__reconstruct(::std::in_place_type<_WorkingOutput>, ::std::forward<_Output>(__output)); | |
::std::size_t __handled_errors = false; | |
for (;;) { | |
auto __result = __encoding.encode_one( | |
::std::move(__working_input), ::std::move(__working_output), __error_handler, __state); | |
if (__result.error_code != encoding_error::ok) { | |
return __result; | |
} | |
__handled_errors += __result.handled_errors; | |
__working_input = ::std::move(__result.input); | |
__working_output = ::std::move(__result.output); | |
if (__txt_detail::__adl::__adl_empty(__result.input)) { | |
break; | |
} | |
} | |
return _Result(::std::move(__working_input), ::std::move(__working_output), __state, encoding_error::ok, | |
__handled_errors); | |
} | |
////// | |
/// @brief Converts the code points of the given @p __input view through the encoding to code units into the | |
/// @p | |
/// __output view. | |
/// | |
/// @param[in] __input An input_view to read code points from and use in the encode operation that will | |
/// produce code units. | |
/// @param[in] __encoding The encoding that will be used to encode the input's code points into | |
/// output code units. | |
/// @param[in] __output An output_view to write code units to as the result of the encode operation from | |
/// the intermediate code points. | |
/// @param[in] __error_handler The error handlers for the from and to encodings, | |
/// respectively. | |
/// @param[in,out] __state A reference to the associated state for the @p __encoding 's encode step. | |
/// | |
/// @result A ztd::text::encode_result object that contains references to @p __state. | |
/// | |
/// @remarks This function detects whether or not the ADL extension point @c text_encode can be called with | |
/// the provided parameters. If so, it will use that ADL extension point over the default implementation. | |
/// Otherwise, it will loop over the two encodings and attempt to encode by repeatedly calling the encoding's | |
/// required @c encode_one function. | |
////// | |
template <typename _Input, typename _Encoding, typename _Output, typename _ErrorHandler, typename _State> | |
constexpr auto encode_into(_Input&& __input, _Encoding&& __encoding, _Output&& __output, | |
_ErrorHandler&& __error_handler, _State& __state) { | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_text_encode, _Input, _Encoding, | |
_Output, _ErrorHandler, _State>) { | |
return text_encode(tag<__txt_detail::__remove_cvref_t<_Encoding>> {}, ::std::forward<_Input>(__input), | |
::std::forward<_Encoding>(__encoding), ::std::forward<_Output>(__output), | |
::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
else if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_internal_text_encode, _Input, | |
_Encoding, _Output, _ErrorHandler, _State>) { | |
return __text_encode(tag<__txt_detail::__remove_cvref_t<_Encoding>> {}, ::std::forward<_Input>(__input), | |
::std::forward<_Encoding>(__encoding), ::std::forward<_Output>(__output), | |
::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
else { | |
return basic_encode_into(::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), | |
::std::forward<_Output>(__output), ::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
} | |
namespace __txt_detail { | |
template <typename _Input, typename _Encoding, typename _OutputContainer, typename _ErrorHandler, | |
typename _State> | |
constexpr auto __intermediate_encode_to_storage(_Input&& __input, _Encoding&& __encoding, | |
_OutputContainer& __output, _ErrorHandler&& __error_handler, _State& __state) { | |
// Well, SHIT. Write into temporary, then serialize one-by-one/bulk to output. | |
// I'll admit, this is HELLA work to support... | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
constexpr ::std::size_t __intermediate_buffer_max | |
= ZTD_TEXT_INTERMEDIATE_BUFFER_SIZE_I_ < max_code_units_v<_UEncoding> | |
? max_code_units_v<_UEncoding> | |
: ZTD_TEXT_INTERMEDIATE_BUFFER_SIZE_I_; | |
using _IntermediateValueType = code_unit_t<_UEncoding>; | |
using _IntermediateInput = __txt_detail::__string_view_or_span_or_reconstruct_t<_Input>; | |
using _InitialOutput = ::ztd::text::span<_IntermediateValueType, __intermediate_buffer_max>; | |
using _Output = ::ztd::text::span<_IntermediateValueType>; | |
using _Result = decltype(__encoding.encode_one( | |
::std::declval<_IntermediateInput>(), ::std::declval<_Output>(), __error_handler, __state)); | |
using _WorkingInput = __txt_detail::__remove_cvref_t<decltype(::std::declval<_Result>().input)>; | |
_WorkingInput __working_input | |
= __txt_detail::__string_view_or_span_or_reconstruct(::std::forward<_Input>(__input)); | |
_IntermediateValueType __intermediate_translation_buffer[__intermediate_buffer_max] {}; | |
for (;;) { | |
// Ignore "out of output" errors and do our best to recover properly along the way... | |
_InitialOutput __intermediate_initial_output(__intermediate_translation_buffer); | |
auto __result = encode_into(::std::move(__working_input), ::std::forward<_Encoding>(__encoding), | |
__intermediate_initial_output, ::std::forward<_ErrorHandler>(__error_handler), __state); | |
_Output __intermediate_output(__intermediate_initial_output.data(), __result.output.data()); | |
using _SpanIterator = typename _Output::iterator; | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_insert_bulk, _OutputContainer, | |
_SpanIterator, _SpanIterator>) { | |
// inserting in bulk | |
// can be faster, more performant, | |
// save us some coding too | |
__output.insert(__output.cend(), __intermediate_output.begin(), __intermediate_output.end()); | |
} | |
else { | |
// O O F! we have to insert one at a time. | |
for (auto&& __intermediate_code_unit : __intermediate_output) { | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_push_back, | |
_OutputContainer, _IntermediateValueType>) { | |
__output.push_back(__intermediate_code_unit); | |
} | |
else { | |
__output.insert(__output.cend(), __intermediate_code_unit); | |
} | |
} | |
} | |
if (__result.error_code == encoding_error::insufficient_output_space) { | |
// loop around, we've got S P A C E for more | |
__working_input = ::std::move(__result.input); | |
continue; | |
} | |
if (__result.error_code != encoding_error::ok) { | |
return __result; | |
} | |
if (__txt_detail::__adl::__adl_empty(__result.input)) { | |
return __result; | |
} | |
} | |
} | |
template <typename _OutputContainer, typename _Input, typename _Encoding, typename _ErrorHandler, | |
typename _State> | |
constexpr auto __encode_dispatch( | |
_Input&& __input, _Encoding&& __encoding, _ErrorHandler&& __error_handler, _State& __state) { | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
_OutputContainer __output {}; | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_size, _Input>) { | |
using _SizeType = decltype(__txt_detail::__adl::__adl_size(__input)); | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_reserve_with_size_type, | |
_OutputContainer, _SizeType>) { | |
auto __output_size_hint = __txt_detail::__adl::__adl_size(__input); | |
__output_size_hint *= max_code_points_v<_UEncoding>; | |
__output.reserve(__output_size_hint); | |
} | |
} | |
if constexpr (__txt_detail::__is_encode_range_category_output_v<_UEncoding>) { | |
// We can use the unbounded stuff | |
using _BackInserterIterator = decltype(::std::back_inserter(::std::declval<_OutputContainer&>())); | |
using _Unbounded = unbounded_view<_BackInserterIterator>; | |
_Unbounded __insert_view(::std::back_inserter(__output)); | |
auto __stateful_result | |
= encode_into(::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), | |
::std::move(__insert_view), ::std::forward<_ErrorHandler>(__error_handler), __state); | |
(void)__stateful_result; | |
return __output; | |
} | |
else { | |
auto __stateful_result = __txt_detail::__intermediate_encode_to_storage( | |
::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), __output, | |
::std::forward<_ErrorHandler>(__error_handler), __state); | |
(void)__stateful_result; | |
return __output; | |
} | |
} | |
} // namespace __txt_detail | |
////// | |
/// @brief Converts the code points of the given @p __input view through the encoding to code units into the | |
/// @p | |
/// __output view. | |
/// | |
/// @param[in] __input An input_view to read code points from and use in the encode operation that will | |
/// produce code units. | |
/// @param[in] __encoding The encoding that will be used to encode the input's code points into | |
/// output code units. | |
/// @param[in] __output An output_view to write code units to as the result of the encode operation from | |
/// the intermediate code points. | |
/// @param[in] __error_handler The error handlers for the from and to encodings, | |
/// respectively. | |
/// | |
/// @result A ztd::text::stateless_encode_result object that contains references to @p __state. | |
/// | |
/// @remarks Creates a default @c state using ztd::text::make_encode_state. | |
////// | |
template <typename _Input, typename _Encoding, typename _Output, typename _ErrorHandler> | |
constexpr auto encode_into( | |
_Input&& __input, _Encoding&& __encoding, _Output&& __output, _ErrorHandler&& __error_handler) { | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
using _State = encode_state_t<_UEncoding>; | |
_State __state = make_encode_state(__encoding); | |
auto __stateful_result = encode_into(::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), | |
::std::forward<_Output>(__output), ::std::forward<_ErrorHandler>(__error_handler), __state); | |
return __txt_detail::__slice_to_stateless(::std::move(__stateful_result)); | |
} | |
////// | |
/// @brief Converts the code points of the given @p __input view through the encoding to code units into the | |
/// @p | |
/// __output view. | |
/// | |
/// @param[in] __input An input_view to read code points from and use in the encode operation that will | |
/// produce code units. | |
/// @param[in] __encoding The encoding that will be used to encode the input's code points into | |
/// output code units. | |
/// @param[in] __output An output_view to write code units to as the result of the encode operation from | |
/// the intermediate code points. | |
/// | |
/// @result A ztd::text::stateless_encode_result object that contains references to @p __state. | |
/// | |
/// @remarks Creates a default @c error_handler that is similar to ztd::text::default_handler, but marked as | |
/// careless. | |
////// | |
template <typename _Input, typename _Encoding, typename _Output> | |
constexpr auto encode_into(_Input&& __input, _Encoding&& __encoding, _Output&& __output) { | |
default_handler __handler {}; | |
return encode_into(::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), | |
::std::forward<_Output>(__output), __handler); | |
} | |
////// | |
/// @brief Converts the code points of the given @p __input view through the encoding to code units into the | |
/// @p | |
/// __output view. | |
/// | |
/// @param[in] __input An input_view to read code points from and use in the encode operation that will | |
/// produce code units. | |
/// @param[in] __output An output_view to write code units to as the result of the encode operation from | |
/// the intermediate code points. | |
/// | |
/// @result A ztd::text::stateless_encode_result object that contains references to @p __state. | |
/// | |
/// @remarks Creates a default @c encoding by figuring out the @c value_type of the @p __input, then passing | |
/// that type into ztd::text::default_code_point_encoding_t. That encoding is that used to encode the input | |
/// code points, by default. | |
////// | |
template <typename _Input, typename _Output> | |
constexpr auto encode_into(_Input&& __input, _Output&& __output) { | |
using _UInput = __txt_detail::__remove_cvref_t<_Input>; | |
using _CodePoint = __txt_detail::__range_value_type_t<_UInput>; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED_I_) | |
if (::std::is_constant_evaluated()) { | |
// Use literal encoding instead, if we meet the right criteria | |
using _Encoding = default_consteval_code_point_encoding_t<_CodePoint>; | |
_Encoding __encoding {}; | |
return encode_into(::std::forward<_Input>(__input), __encoding, ::std::forward<_Output>(__output)); | |
} | |
else | |
#endif | |
{ | |
using _Encoding = default_code_point_encoding_t<_CodePoint>; | |
_Encoding __encoding {}; | |
return encode_into(::std::forward<_Input>(__input), __encoding, ::std::forward<_Output>(__output)); | |
} | |
} | |
////// | |
/// @brief Converts the code points of the given @p __input view through the encoding to code units in the | |
/// specified @p _OutputContainer type. | |
/// | |
/// @tparam _OutputContainer The container type to serialize data into. | |
/// | |
/// @param[in] __input An input_view to read code points from and use in the encode operation that will | |
/// produce code units. | |
/// @param[in] __encoding The encoding that will be used to encode the input's code points into | |
/// output code units. | |
/// @param[in] __error_handler The error handlers for the from and to encodings, | |
/// respectively. | |
/// @param[in,out] __state A reference to the associated state for the @p __encoding 's encode step. | |
/// | |
/// @result A ztd::text::encode_result object that contains references to @p __state and an output of type | |
/// @p _OutputContainer. | |
/// | |
/// @remarks This function detects creates a container of type @p _OutputContainer and uses a typical @c | |
/// std::back_inserter or @c std::push_back_inserter to fill in elements as it is written to. The result is | |
/// then returned, with the @c .output value put into the container. | |
////// | |
template <typename _OutputContainer, typename _Input, typename _Encoding, typename _ErrorHandler, typename _State> | |
constexpr auto encode_to( | |
_Input&& __input, _Encoding&& __encoding, _ErrorHandler&& __error_handler, _State& __state) { | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
_OutputContainer __output {}; | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_size, _Input>) { | |
using _SizeType = decltype(__txt_detail::__adl::__adl_size(__input)); | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_reserve_with_size_type, | |
_OutputContainer, _SizeType>) { | |
auto __output_size_hint = __txt_detail::__adl::__adl_size(__input); | |
__output_size_hint *= max_code_points_v<_UEncoding>; | |
__output.reserve(__output_size_hint); | |
} | |
} | |
if constexpr (__txt_detail::__is_encode_range_category_output_v<_Encoding>) { | |
// We can use the unbounded stuff | |
using _BackInserterIterator = decltype(::std::back_inserter(::std::declval<_OutputContainer&>())); | |
using _Unbounded = unbounded_view<_BackInserterIterator>; | |
_Unbounded __insert_view(::std::back_inserter(__output)); | |
auto __stateful_result | |
= encode_into(::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), | |
::std::move(__insert_view), ::std::forward<_ErrorHandler>(__error_handler), __state); | |
return __txt_detail::__replace_result_output(::std::move(__stateful_result), ::std::move(__output)); | |
} | |
else { | |
auto __stateful_result = __txt_detail::__intermediate_encode_to_storage(::std::forward<_Input>(__input), | |
::std::forward<_Encoding>(__encoding), __output, ::std::forward<_ErrorHandler>(__error_handler), | |
__state); | |
return __txt_detail::__replace_result_output(::std::move(__stateful_result), ::std::move(__output)); | |
} | |
} | |
////// | |
/// @brief Converts the code points of the given @p __input view through the encoding to code units in the | |
/// specified @p _OutputContainer type. | |
/// | |
/// @tparam _OutputContainer The container type to serialize data into. | |
/// | |
/// @param[in] __input An input_view to read code points from and use in the encode operation that will | |
/// produce code units. | |
/// @param[in] __encoding The encoding that will be used to encode the input's code points into | |
/// output code units. | |
/// @param[in] __error_handler The error handlers for the from and to encodings, | |
/// respectively. | |
/// | |
/// @result A ztd::text::stateless_encode_result object whose output is of type @p _OutputContainer. | |
/// | |
/// @remarks This function creates a @c state using ztd::text::make_encode_state. | |
////// | |
template <typename _OutputContainer, typename _Input, typename _Encoding, typename _ErrorHandler> | |
constexpr auto encode_to(_Input&& __input, _Encoding&& __encoding, _ErrorHandler&& __error_handler) { | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
using _State = encode_state_t<_UEncoding>; | |
_State __state = make_encode_state(__encoding); | |
auto __stateful_result = encode_to<_OutputContainer>(::std::forward<_Input>(__input), | |
::std::forward<_Encoding>(__encoding), ::std::forward<_ErrorHandler>(__error_handler), __state); | |
return __txt_detail::__slice_to_stateless(::std::move(__stateful_result)); | |
} | |
////// | |
/// @brief Converts the code points of the given @p __input view through the encoding to code units in the | |
/// specified @p _OutputContainer type. | |
/// | |
/// @tparam _OutputContainer The container type to serialize data into. | |
/// | |
/// @param[in] __input An input_view to read code points from and use in the encode operation that will | |
/// produce code units. | |
/// @param[in] __encoding The encoding that will be used to encode the input's code points into | |
/// output code units. | |
/// | |
/// @result A ztd::text::stateless_encode_result object whose output is of type @p _OutputContainer. | |
/// | |
/// @remarks This function creates a @c handler using ztd::text::default_handler, but marks it as careless. | |
////// | |
template <typename _OutputContainer, typename _Input, typename _Encoding> | |
constexpr auto encode_to(_Input&& __input, _Encoding&& __encoding) { | |
default_handler __handler {}; | |
return encode_to<_OutputContainer>( | |
::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), __handler); | |
} | |
////// | |
/// @brief Converts the code points of the given @p __input view through the encoding to code units in the | |
/// specified @p _OutputContainer type. | |
/// | |
/// @tparam _OutputContainer The container type to serialize data into. | |
/// | |
/// @param[in] __input An input_view to read code points from and use in the encode operation that will | |
/// produce code units. | |
/// | |
/// @result A ztd::text::stateless_encode_result object whose output is of type @p _OutputContainer. | |
/// | |
/// @remarks This function creates an @c encoding by using the @c value_type of the @p __input which is then | |
/// passed through the ztd::text::default_code_point_encoding type to get the default desired encoding. | |
////// | |
template <typename _OutputContainer, typename _Input> | |
constexpr auto encode_to(_Input&& __input) { | |
using _UInput = __txt_detail::__remove_cvref_t<_Input>; | |
using _CodePoint = __txt_detail::__range_value_type_t<_UInput>; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED_I_) | |
if (::std::is_constant_evaluated()) { | |
// Use literal encoding instead, if we meet the right criteria | |
using _Encoding = default_consteval_code_point_encoding_t<_CodePoint>; | |
_Encoding __encoding {}; | |
return encode_to<_OutputContainer>(::std::forward<_Input>(__input), __encoding); | |
} | |
else | |
#endif | |
{ | |
using _Encoding = default_code_point_encoding_t<_CodePoint>; | |
_Encoding __encoding {}; | |
return encode_to<_OutputContainer>(::std::forward<_Input>(__input), __encoding); | |
} | |
} | |
////// | |
/// @brief Converts the code points of the given @p __input view through the encoding to code units in the | |
/// specified @p _OutputContainer type. | |
/// | |
/// @tparam _OutputContainer The container type to serialize data into. | |
/// | |
/// @param[in] __input An input_view to read code points from and use in the encode operation that will | |
/// produce code units. | |
/// @param[in] __encoding The encoding that will be used to encode the input's code points into | |
/// output code units. | |
/// @param[in] __error_handler The error handlers for the from and to encodings, | |
/// respectively. | |
/// @param[in,out] __state A reference to the associated state for the @p __encoding 's encode step. | |
/// | |
/// @result An object of type @p _OutputContainer . | |
/// | |
/// @remarks This function detects creates a container of type @p _OutputContainer and uses a typical @c | |
/// std::back_inserter or @c std::push_back_inserter to fill in elements as it is written to. | |
////// | |
template <typename _OutputContainer = void, typename _Input, typename _Encoding, typename _ErrorHandler, | |
typename _State> | |
constexpr auto encode(_Input&& __input, _Encoding&& __encoding, _ErrorHandler&& __error_handler, _State& __state) { | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
using _UOutputContainer = __txt_detail::__remove_cvref_t<_OutputContainer>; | |
using _OutputCodeUnit = code_unit_t<_UEncoding>; | |
constexpr bool _IsVoidContainer = ::std::is_void_v<_UOutputContainer>; | |
constexpr bool _IsStringable | |
= (__txt_detail::__is_character_v<_OutputCodeUnit> || is_unicode_code_point_v<_OutputCodeUnit>); | |
if constexpr (_IsVoidContainer && _IsStringable) { | |
// prevent instantiation errors with basic_string by boxing it inside of an "if constexpr" | |
using _RealOutputContainer = ::std::basic_string<_OutputCodeUnit>; | |
return __txt_detail::__encode_dispatch<_RealOutputContainer>(::std::forward<_Input>(__input), | |
::std::forward<_Encoding>(__encoding), ::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
else { | |
using _RealOutputContainer | |
= ::std::conditional_t<_IsVoidContainer, ::std::vector<_OutputCodeUnit>, _OutputContainer>; | |
return __txt_detail::__encode_dispatch<_RealOutputContainer>(::std::forward<_Input>(__input), | |
::std::forward<_Encoding>(__encoding), ::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
} | |
////// | |
/// @brief Converts the code points of the given @p __input view through the encoding to code units in the | |
/// specified @p _OutputContainer type. | |
/// | |
/// @tparam _OutputContainer The container type to serialize data into. | |
/// | |
/// @param[in] __input An input_view to read code points from and use in the encode operation that will | |
/// produce code units. | |
/// @param[in] __encoding The encoding that will be used to encode the input's code points into | |
/// output code units. | |
/// @param[in] __error_handler The error handlers for the from and to encodings, | |
/// respectively. | |
/// | |
/// @result An object of type @p _OutputContainer . | |
/// | |
/// @remarks This function creates a @c state using ztd::text::make_encode_state. | |
////// | |
template <typename _OutputContainer = void, typename _Input, typename _Encoding, typename _ErrorHandler> | |
constexpr auto encode(_Input&& __input, _Encoding&& __encoding, _ErrorHandler&& __error_handler) { | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
using _State = encode_state_t<_UEncoding>; | |
_State __state = make_encode_state(__encoding); | |
return encode<_OutputContainer>(::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), | |
::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
////// | |
/// @brief Converts the code points of the given @p __input view through the encoding to code units in the | |
/// specified @p _OutputContainer type. | |
/// | |
/// @tparam _OutputContainer The container type to serialize data into. | |
/// | |
/// @param[in] __input An input_view to read code points from and use in the encode operation that will | |
/// produce code units. | |
/// @param[in] __encoding The encoding that will be used to encode the input's code points into | |
/// output code units. | |
/// | |
/// @result An object of type @p _OutputContainer . | |
/// | |
/// @remarks This function creates a @c handler using ztd::text::default_handler, but marks it as careless. | |
////// | |
template <typename _OutputContainer = void, typename _Input, typename _Encoding> | |
constexpr auto encode(_Input&& __input, _Encoding&& __encoding) { | |
default_handler __handler {}; | |
return encode<_OutputContainer>( | |
::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), __handler); | |
} | |
////// | |
/// @brief Converts the code points of the given @p __input view through the encoding to code units in the | |
/// specified @p _OutputContainer type. | |
/// | |
/// @tparam _OutputContainer The container type to serialize data into. | |
/// | |
/// @param[in] __input An input_view to read code points from and use in the encode operation that will | |
/// produce code units. | |
/// | |
/// @result An object of type @p _OutputContainer . | |
/// | |
/// @remarks This function creates an @c encoding by using the @c value_type of the @p __input which is then | |
/// passed through the ztd::text::default_code_point_encoding type to get the default desired encoding. | |
////// | |
template <typename _OutputContainer = void, typename _Input> | |
constexpr auto encode(_Input&& __input) { | |
using _UInput = __txt_detail::__remove_cvref_t<_Input>; | |
using _CodePoint = __txt_detail::__range_value_type_t<_UInput>; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED_I_) | |
if (::std::is_constant_evaluated()) { | |
// Use literal encoding instead, if we meet the right criteria | |
using _Encoding = default_consteval_code_point_encoding_t<_CodePoint>; | |
_Encoding __encoding {}; | |
return encode<_OutputContainer>(::std::forward<_Input>(__input), __encoding); | |
} | |
else | |
#endif | |
{ | |
using _Encoding = default_code_point_encoding_t<_CodePoint>; | |
_Encoding __encoding {}; | |
return encode<_OutputContainer>(::std::forward<_Input>(__input), __encoding); | |
} | |
} | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/encode.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/decode.hpp | |
#include <string> | |
#include <vector> | |
#include <string_view> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_decode ztd::text::decode[_into] | |
/// @brief These functions convert from a view of input into a view of output using either the inferred or | |
/// specified encodings. If no error handler is provided, the equivalent of the ztd::text::default_handler is | |
/// used by default. If no associated state is provided for either the "to" or "from" encodings, one will be | |
/// created with automatic storage duration (as a "stack" variable) for the provided encoding. | |
/// @{ | |
////// | |
////// | |
/// @brief Converts the code units of the given @p __input view through the encoding to code points into the @p | |
/// __output view. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce code points. | |
/// @param[in] __encoding The encoding that will be used to decode the input's code points into | |
/// output code units. | |
/// @param[in] __output An output_view to write code points to as the result of the decode operation from the | |
/// intermediate code units. | |
/// @param[in] __error_handler The error handlers for the from and to encodings, | |
/// respectively. | |
/// @param[in,out] __state A reference to the associated state for the @p __encoding 's decode step. | |
/// | |
/// @result A ztd::text::decode_result object that contains references to @p __state. | |
/// | |
/// @remarks This function performs the bog-standard, basic loop for decoding. It talks to no ADL extension points. | |
////// | |
template <typename _Input, typename _Encoding, typename _Output, typename _ErrorHandler, typename _State> | |
constexpr auto basic_decode_into(_Input&& __input, _Encoding&& __encoding, _Output&& __output, | |
_ErrorHandler&& __error_handler, _State& __state) { | |
using _IntermediateInput = __txt_detail::__string_view_or_span_or_reconstruct_t<_Input>; | |
using _IntermediateOutput = __txt_detail::__range_reconstruct_t<_Output>; | |
using _Result = decltype(__encoding.decode_one( | |
::std::declval<_IntermediateInput>(), ::std::declval<_IntermediateOutput>(), __error_handler, __state)); | |
using _WorkingInput = __txt_detail::__remove_cvref_t<decltype(::std::declval<_Result>().input)>; | |
using _WorkingOutput = __txt_detail::__remove_cvref_t<decltype(::std::declval<_Result>().output)>; | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
using _UErrorHandler = __txt_detail::__remove_cvref_t<_ErrorHandler>; | |
static_assert(__txt_detail::__is_decode_lossless_or_deliberate_v<_UEncoding, _UErrorHandler>, | |
"This decode is a lossy, non-injective operation. This means you may lose data that you did " | |
"not " | |
"intend " | |
"to lose; specify a 'handler' error handler parameter to decode(in, encoding, handler, ...) " | |
"or " | |
"decode_into(in, encoding, out, handler, ...) explicitly in order to bypass this."); | |
_WorkingInput __working_input | |
= __txt_detail::__string_view_or_span_or_reconstruct(::std::forward<_Input>(__input)); | |
_WorkingOutput __working_output( | |
__txt_detail::__reconstruct(::std::in_place_type<_WorkingOutput>, ::std::forward<_Output>(__output))); | |
::std::size_t __handled_errors = 0; | |
for (;;) { | |
auto __result = __encoding.decode_one( | |
::std::move(__working_input), ::std::move(__working_output), __error_handler, __state); | |
if (__result.error_code != encoding_error::ok) { | |
return __result; | |
} | |
__handled_errors += __result.handled_errors; | |
__working_input = ::std::move(__result.input); | |
__working_output = ::std::move(__result.output); | |
if (__txt_detail::__adl::__adl_empty(__result.input)) { | |
break; | |
} | |
} | |
return _Result(::std::move(__working_input), ::std::move(__working_output), __state, encoding_error::ok, | |
__handled_errors); | |
} | |
////// | |
/// @brief Converts the code units of the given @p __input view through the encoding to code points into the @p | |
/// __output view. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce code points. | |
/// @param[in] __encoding The encoding that will be used to decode the input's code points into | |
/// output code units. | |
/// @param[in] __output An output_view to write code points to as the result of the decode operation from the | |
/// intermediate code units. | |
/// @param[in] __error_handler The error handlers for the from and to encodings, | |
/// respectively. | |
/// @param[in,out] __state A reference to the associated state for the @p __encoding 's decode step. | |
/// | |
/// @result A ztd::text::decode_result object that contains references to @p __state. | |
/// | |
/// @remarks This function detects whether or not the ADL extension point @c text_decode can be called with the | |
/// provided parameters. If so, it will use that ADL extension point over the default implementation. Otherwise, it | |
/// will loop over the two encodings and attempt to decode by repeatedly calling the encoding's required @c | |
/// decode_one function. | |
////// | |
template <typename _Input, typename _Encoding, typename _Output, typename _ErrorHandler, typename _State> | |
constexpr auto decode_into(_Input&& __input, _Encoding&& __encoding, _Output&& __output, | |
_ErrorHandler&& __error_handler, _State& __state) { | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_text_decode, _Input, _Encoding, | |
_Output, _ErrorHandler, _State>) { | |
return text_decode(tag<__txt_detail::__remove_cvref_t<_Encoding>> {}, ::std::forward<_Input>(__input), | |
::std::forward<_Encoding>(__encoding), ::std::forward<_Output>(__output), | |
::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
else if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_internal_text_decode, _Input, | |
_Encoding, _Output, _ErrorHandler, _State>) { | |
return __text_decode(tag<__txt_detail::__remove_cvref_t<_Encoding>> {}, ::std::forward<_Input>(__input), | |
::std::forward<_Encoding>(__encoding), ::std::forward<_Output>(__output), | |
::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
else { | |
return basic_decode_into(::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), | |
::std::forward<_Output>(__output), ::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
} | |
namespace __txt_detail { | |
template <typename _Input, typename _Encoding, typename _OutputContainer, typename _ErrorHandler, | |
typename _State> | |
constexpr auto __intermediate_decode_to_storage(_Input&& __input, _Encoding&& __encoding, | |
_OutputContainer& __output, _ErrorHandler&& __error_handler, _State& __state) { | |
// Well, SHIT. Write into temporary, then serialize one-by-one/bulk to output. | |
// I'll admit, this is HELLA work to support... | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
constexpr ::std::size_t __intermediate_buffer_max | |
= ZTD_TEXT_INTERMEDIATE_BUFFER_SIZE_I_ < max_code_points_v<_UEncoding> | |
? max_code_points_v<_UEncoding> | |
: ZTD_TEXT_INTERMEDIATE_BUFFER_SIZE_I_; | |
using _IntermediateValueType = code_point_t<_UEncoding>; | |
using _IntermediateInput = __txt_detail::__string_view_or_span_or_reconstruct_t<_Input>; | |
using _OutputInitial = ::ztd::text::span<_IntermediateValueType, __intermediate_buffer_max>; | |
using _Output = ::ztd::text::span<_IntermediateValueType>; | |
using _Result = decltype(__encoding.decode_one( | |
::std::declval<_IntermediateInput>(), ::std::declval<_Output>(), __error_handler, __state)); | |
using _WorkingInput = __txt_detail::__remove_cvref_t<decltype(::std::declval<_Result>().input)>; | |
_WorkingInput __working_input( | |
__txt_detail::__string_view_or_span_or_reconstruct(::std::forward<_Input>(__input))); | |
_IntermediateValueType __intermediate_translation_buffer[__intermediate_buffer_max] {}; | |
for (;;) { | |
// Ignore "out of output" errors and do our best to recover properly along the way... | |
_OutputInitial __intermediate_initial_output(__intermediate_translation_buffer); | |
auto __result = decode_into(::std::move(__working_input), ::std::forward<_Encoding>(__encoding), | |
__intermediate_initial_output, ::std::forward<_ErrorHandler>(__error_handler), __state); | |
_Output __intermediate_output(__intermediate_initial_output.data(), __result.output.data()); | |
using _SpanIterator = typename _Output::iterator; | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_insert_bulk, _OutputContainer, | |
_SpanIterator, _SpanIterator>) { | |
// inserting in bulk | |
// can be faster, more performant, | |
// save us some coding too | |
__output.insert(__output.cend(), __intermediate_output.begin(), __intermediate_output.end()); | |
} | |
else { | |
// O O F! we have to insert one at a time. | |
for (auto&& __intermediate_code_point : __intermediate_output) { | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_push_back, | |
_OutputContainer, _IntermediateValueType>) { | |
__output.push_back(__intermediate_code_point); | |
} | |
else { | |
__output.insert(__output.cend(), __intermediate_code_point); | |
} | |
} | |
} | |
if (__result.error_code == encoding_error::insufficient_output_space) { | |
// loop around, we've got S P A C E for more | |
__working_input = ::std::move(__result.input); | |
continue; | |
} | |
if (__result.error_code != encoding_error::ok) { | |
return __result; | |
} | |
if (__txt_detail::__adl::__adl_empty(__result.input)) { | |
return __result; | |
} | |
} | |
} | |
} // namespace __txt_detail | |
////// | |
/// @brief Converts the code units of the given @p __input view through the encoding to code points into the @p | |
/// __output view. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce code points. | |
/// @param[in] __encoding The encoding that will be used to decode the input's code points into | |
/// output code units. | |
/// @param[in] __output An output_view to write code points to as the result of the decode operation from the | |
/// intermediate code units. | |
/// @param[in] __error_handler The error handlers for the from and to encodings, | |
/// respectively. | |
/// | |
/// @result A ztd::text::stateless_decode_result object that contains references to @p __state. | |
/// | |
/// @remarks Creates a default @c state using ztd::text::make_decode_state. | |
////// | |
template <typename _Input, typename _Encoding, typename _Output, typename _ErrorHandler> | |
constexpr auto decode_into( | |
_Input&& __input, _Encoding&& __encoding, _Output&& __output, _ErrorHandler&& __error_handler) { | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
using _State = decode_state_t<_UEncoding>; | |
_State __state = make_decode_state(__encoding); | |
auto __stateful_result = decode_into(::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), | |
::std::forward<_Output>(__output), ::std::forward<_ErrorHandler>(__error_handler), __state); | |
return __txt_detail::__slice_to_stateless(::std::move(__stateful_result)); | |
} | |
////// | |
/// @brief Converts the code units of the given @p __input view through the encoding to code points into the @p | |
/// __output view. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce code points. | |
/// @param[in] __encoding The encoding that will be used to decode the input's code points into | |
/// output code units. | |
/// @param[in] __output An output_view to write code points to as the result of the decode operation from the | |
/// intermediate code units. | |
/// | |
/// @result A ztd::text::stateless_decode_result object that contains references to @p __state. | |
/// | |
/// @remarks Creates a default @c error_handler that is similar to ztd::text::default_handler, but marked as | |
/// careless. | |
////// | |
template <typename _Input, typename _Encoding, typename _Output> | |
constexpr auto decode_into(_Input&& __input, _Encoding&& __encoding, _Output&& __output) { | |
default_handler __handler {}; | |
return decode_into(::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), | |
::std::forward<_Output>(__output), __handler); | |
} | |
////// | |
/// @brief Converts the code units of the given @p __input view through the encoding to code points into the @p | |
/// __output view. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce code points. | |
/// @param[in] __output An output_view to write code points to as the result of the decode operation from the | |
/// intermediate code units. | |
/// | |
/// @result A ztd::text::stateless_decode_result object that contains references to @p __state. | |
/// | |
/// @remarks Creates a default @c encoding by figuring out the @c value_type of the @p __input, then passing that | |
/// type into ztd::text::default_code_point_encoding_t. That encoding is that used to decode the input code units, | |
/// by default. | |
////// | |
template <typename _Input, typename _Output> | |
constexpr auto decode_into(_Input&& __input, _Output&& __output) { | |
using _UInput = __txt_detail::__remove_cvref_t<_Input>; | |
using _CodeUnit = __txt_detail::__range_value_type_t<_UInput>; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED_I_) | |
if (::std::is_constant_evaluated()) { | |
// Use literal encoding instead, if we meet the right criteria | |
using _Encoding = default_consteval_code_unit_encoding_t<_CodeUnit>; | |
_Encoding __encoding {}; | |
return decode_into(::std::forward<_Input>(__input), __encoding, ::std::forward<_Output>(__output)); | |
} | |
else | |
#endif | |
{ | |
using _Encoding = default_code_unit_encoding_t<_CodeUnit>; | |
_Encoding __encoding {}; | |
return decode_into(::std::forward<_Input>(__input), __encoding, ::std::forward<_Output>(__output)); | |
} | |
} | |
////// | |
/// @brief Converts the code units of the given @p __input view through the encoding to code points the | |
/// specified | |
/// @p _OutputContainer type. | |
/// | |
/// @tparam _OutputContainer The container type to serialize data into. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce code points. | |
/// @param[in] __encoding The encoding that will be used to decode the input's code points into | |
/// output code units. | |
/// @param[in] __error_handler The error handlers for the from and to encodings, | |
/// respectively. | |
/// @param[in,out] __state A reference to the associated state for the @p __encoding 's decode step. | |
/// | |
/// @result A ztd::text::decode_result object that contains references to @p __state and an output of type | |
/// @p _OutputContainer. | |
/// | |
/// @remarks This function detects creates a container of type @p _OutputContainer and uses a typical @c | |
/// std::back_inserter or @c std::push_back_inserter to fill in elements as it is written to. The result is | |
/// then returned, with the @c .output value put into the container. | |
////// | |
template <typename _OutputContainer, typename _Input, typename _Encoding, typename _ErrorHandler, typename _State> | |
constexpr auto decode_to( | |
_Input&& __input, _Encoding&& __encoding, _ErrorHandler&& __error_handler, _State& __state) { | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
_OutputContainer __output {}; | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_size, _Input>) { | |
using _SizeType = decltype(__txt_detail::__adl::__adl_size(__input)); | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_reserve_with_size_type, | |
_OutputContainer, _SizeType>) { | |
auto __output_size_hint = __txt_detail::__adl::__adl_size(__input); | |
__output_size_hint *= max_code_points_v<_UEncoding>; | |
__output.reserve(__output_size_hint); | |
} | |
} | |
if constexpr (__txt_detail::__is_decode_range_category_output_v<_UEncoding>) { | |
// We can use the unbounded stuff | |
using _BackInserterIterator = decltype(::std::back_inserter(::std::declval<_OutputContainer&>())); | |
using _Unbounded = unbounded_view<_BackInserterIterator>; | |
_Unbounded __insert_view(::std::back_inserter(__output)); | |
auto __stateful_result | |
= decode_into(::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), | |
::std::move(__insert_view), ::std::forward<_ErrorHandler>(__error_handler), __state); | |
return __txt_detail::__replace_result_output(::std::move(__stateful_result), ::std::move(__output)); | |
} | |
else { | |
auto __stateful_result = __txt_detail::__intermediate_decode_to_storage(::std::forward<_Input>(__input), | |
::std::forward<_Encoding>(__encoding), __output, ::std::forward<_ErrorHandler>(__error_handler), | |
__state); | |
return __txt_detail::__replace_result_output(::std::move(__stateful_result), ::std::move(__output)); | |
} | |
} | |
////// | |
/// @brief Converts the code units of the given @p __input view through the encoding to code points the | |
/// specified | |
/// @p _OutputContainer type. | |
/// | |
/// @tparam _OutputContainer The container type to serialize data into. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce code points. | |
/// @param[in] __encoding The encoding that will be used to decode the input's code points into | |
/// output code units. | |
/// @param[in] __error_handler The error handlers for the from and to encodings, | |
/// respectively. | |
/// | |
/// @result A ztd::text::stateless_decode_result object whose output is of type @p _OutputContainer. | |
/// | |
/// @remarks This function creates a @c state using ztd::text::make_decode_state. | |
////// | |
template <typename _OutputContainer, typename _Input, typename _Encoding, typename _ErrorHandler> | |
constexpr auto decode_to(_Input&& __input, _Encoding&& __encoding, _ErrorHandler&& __error_handler) { | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
using _State = decode_state_t<_UEncoding>; | |
_State __state = make_decode_state(__encoding); | |
return decode_to<_OutputContainer>(::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), | |
::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
////// | |
/// @brief Converts the code units of the given @p __input view through the encoding to code points the | |
/// specified | |
/// @p _OutputContainer type. | |
/// | |
/// @tparam _OutputContainer The container type to serialize data into. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce code points. | |
/// @param[in] __encoding The encoding that will be used to decode the input's code points into | |
/// output code units. | |
/// | |
/// @result A ztd::text::stateless_decode_result object whose output is of type @p _OutputContainer. | |
/// | |
/// @remarks This function creates a @c handler using ztd::text::default_handler, but marks it as careless. | |
////// | |
template <typename _OutputContainer, typename _Input, typename _Encoding> | |
constexpr auto decode_to(_Input&& __input, _Encoding&& __encoding) { | |
default_handler __handler {}; | |
return decode_to<_OutputContainer>( | |
::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), __handler); | |
} | |
////// | |
/// @brief Converts the code units of the given @p __input view through the encoding to code points the | |
/// specified | |
/// @p _OutputContainer type. | |
/// | |
/// @tparam _OutputContainer The container type to serialize data into. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce code points. | |
/// | |
/// @result A ztd::text::stateless_decode_result object whose output is of type @p _OutputContainer. | |
/// | |
/// @remarks This function creates an @c encoding by using the @c value_type of the @p __input which is then | |
/// passed through the ztd::text::default_code_point_encoding type to get the default desired encoding. | |
////// | |
template <typename _OutputContainer, typename _Input> | |
constexpr auto decode_to(_Input&& __input) { | |
using _UInput = __txt_detail::__remove_cvref_t<_Input>; | |
using _CodeUnit = __txt_detail::__range_value_type_t<_UInput>; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED_I_) | |
if (::std::is_constant_evaluated()) { | |
// Use literal encoding instead, if we meet the right criteria | |
using _Encoding = default_consteval_code_unit_encoding_t<_CodeUnit>; | |
_Encoding __encoding {}; | |
return decode_to<_OutputContainer>(::std::forward<_Input>(__input), __encoding); | |
} | |
else | |
#endif | |
{ | |
using _Encoding = default_code_unit_encoding_t<_CodeUnit>; | |
_Encoding __encoding {}; | |
return decode_to<_OutputContainer>(::std::forward<_Input>(__input), __encoding); | |
} | |
} | |
namespace __txt_detail { | |
template <typename _OutputContainer, typename _Input, typename _Encoding, typename _ErrorHandler, | |
typename _State> | |
constexpr auto __decode_dispatch( | |
_Input&& __input, _Encoding&& __encoding, _ErrorHandler&& __error_handler, _State& __state) { | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
_OutputContainer __output {}; | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_size, _Input>) { | |
using _SizeType = decltype(__txt_detail::__adl::__adl_size(__input)); | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_reserve_with_size_type, | |
_OutputContainer, _SizeType>) { | |
auto __output_size_hint = __txt_detail::__adl::__adl_size(__input); | |
__output_size_hint *= max_code_points_v<_UEncoding>; | |
__output.reserve(__output_size_hint); | |
} | |
} | |
if constexpr (__txt_detail::__is_decode_range_category_output_v<_Encoding>) { | |
using _BackInserterIterator = decltype(::std::back_inserter(::std::declval<_OutputContainer&>())); | |
using _Unbounded = unbounded_view<_BackInserterIterator>; | |
_Unbounded __insert_view(::std::back_inserter(__output)); | |
auto __stateful_result | |
= decode_into(::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), | |
::std::move(__insert_view), ::std::forward<_ErrorHandler>(__error_handler), __state); | |
// We are explicitly discarding this information with this function call. | |
(void)__stateful_result; | |
return __output; | |
} | |
else { | |
auto __stateful_result = __txt_detail::__intermediate_decode_to_storage( | |
::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), __output, | |
::std::forward<_ErrorHandler>(__error_handler), __state); | |
(void)__stateful_result; | |
return __output; | |
} | |
} | |
} // namespace __txt_detail | |
////// | |
/// @brief Converts the code units of the given @p __input view through the encoding to code points the | |
/// specified | |
/// @p _OutputContainer type. | |
/// | |
/// @tparam _OutputContainer The container type to serialize data into. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce code points. | |
/// @param[in] __encoding The encoding that will be used to decode the input's code points into | |
/// output code units. | |
/// @param[in] __error_handler The error handlers for the from and to encodings, | |
/// respectively. | |
/// @param[in,out] __state A reference to the associated state for the @p __encoding 's decode step. | |
/// | |
/// @result An object of type @p _OutputContainer . | |
/// | |
/// @remarks This function detects creates a container of type @p _OutputContainer and uses a typical @c | |
/// std::back_inserter or @c std::push_back_inserter to fill in elements as it is written to. | |
////// | |
template <typename _OutputContainer = void, typename _Input, typename _Encoding, typename _ErrorHandler, | |
typename _State> | |
constexpr auto decode(_Input&& __input, _Encoding&& __encoding, _ErrorHandler&& __error_handler, _State& __state) { | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
using _UOutputContainer = __txt_detail::__remove_cvref_t<_OutputContainer>; | |
using _OutputCodePoint = code_point_t<_UEncoding>; | |
constexpr bool _IsVoidContainer = ::std::is_void_v<_UOutputContainer>; | |
constexpr bool _IsStringable | |
= (__txt_detail::__is_character_v<_OutputCodePoint> || is_unicode_code_point_v<_OutputCodePoint>); | |
if constexpr (_IsVoidContainer && _IsStringable) { | |
// prevent instantiation errors with basic_string by boxing it inside of an "if constexpr" | |
using _RealOutputContainer = ::std::basic_string<_OutputCodePoint>; | |
return __txt_detail::__decode_dispatch<_RealOutputContainer>(::std::forward<_Input>(__input), | |
::std::forward<_Encoding>(__encoding), ::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
else { | |
using _RealOutputContainer | |
= ::std::conditional_t<_IsVoidContainer, ::std::vector<_OutputCodePoint>, _OutputContainer>; | |
return __txt_detail::__decode_dispatch<_RealOutputContainer>(::std::forward<_Input>(__input), | |
::std::forward<_Encoding>(__encoding), ::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
} | |
////// | |
/// @brief Converts the code units of the given @p __input view through the encoding to code points the | |
/// specified | |
/// @p _OutputContainer type. | |
/// | |
/// @tparam _OutputContainer The container type to serialize data into. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce code points. | |
/// @param[in] __encoding The encoding that will be used to decode the input's code points into | |
/// output code units. | |
/// @param[in] __error_handler The error handlers for the from and to encodings, | |
/// respectively. | |
/// | |
/// @result An object of type @p _OutputContainer . | |
/// | |
/// @remarks This function creates a @c state using ztd::text::make_decode_state. | |
////// | |
template <typename _OutputContainer = void, typename _Input, typename _Encoding, typename _ErrorHandler> | |
constexpr auto decode(_Input&& __input, _Encoding&& __encoding, _ErrorHandler&& __error_handler) { | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
using _State = decode_state_t<_UEncoding>; | |
_State __state = make_decode_state(__encoding); | |
return decode<_OutputContainer>(::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), | |
::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
////// | |
/// @brief Converts the code units of the given @p __input view through the encoding to code points the | |
/// specified | |
/// @p _OutputContainer type. | |
/// | |
/// @tparam _OutputContainer The container type to serialize data into. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce code points. | |
/// @param[in] __encoding The encoding that will be used to decode the input's code points into | |
/// output code units. | |
/// | |
/// @result An object of type @p _OutputContainer . | |
/// | |
/// @remarks This function creates a @c handler using ztd::text::default_handler, but marks it as careless. | |
////// | |
template <typename _OutputContainer = void, typename _Input, typename _Encoding> | |
constexpr auto decode(_Input&& __input, _Encoding&& __encoding) { | |
default_handler __handler {}; | |
return decode<_OutputContainer>( | |
::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), __handler); | |
} | |
////// | |
/// @brief Converts the code units of the given @p __input view through the encoding to code points the | |
/// specified | |
/// @p _OutputContainer type. | |
/// | |
/// @tparam _OutputContainer The container type to serialize data into. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce code points. | |
/// | |
/// @result An object of type @p _OutputContainer . | |
/// | |
/// @remarks This function creates an @c encoding by using the @c value_type of the @p __input which is then | |
/// passed through the ztd::text::default_code_point_encoding type to get the default desired encoding. | |
////// | |
template <typename _OutputContainer = void, typename _Input> | |
constexpr auto decode(_Input&& __input) { | |
using _UInput = __txt_detail::__remove_cvref_t<_Input>; | |
using _CodeUnit = __txt_detail::__range_value_type_t<_UInput>; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED_I_) | |
if (::std::is_constant_evaluated()) { | |
// Use literal encoding instead, if we meet the right criteria | |
using _Encoding = default_consteval_code_unit_encoding_t<_CodeUnit>; | |
_Encoding __encoding {}; | |
return decode<_OutputContainer>(::std::forward<_Input>(__input), __encoding); | |
} | |
else | |
#endif | |
{ | |
using _Encoding = default_code_unit_encoding_t<_CodeUnit>; | |
_Encoding __encoding {}; | |
return decode<_OutputContainer>(::std::forward<_Input>(__input), __encoding); | |
} | |
} | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/decode.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/validate_decodable_as.hpp | |
#include <algorithm> | |
#include <string_view> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_validate_decodable_as ztd::text::validate_decodable_as | |
/// @brief These functions check if the given input of code points will decode without an error. Note that this | |
/// does not mean that an error handler will be invoked that can "smooth over" any possible errors: this checks | |
/// solely if it will decode from code units into code points cleanly. | |
/// @{ | |
////// | |
////// | |
/// @brief Validates the code units of the @p __input according to the @p __encoding with the given states @p | |
/// __decode_state and @p __encode_state to see if it can be turned into code points. | |
/// | |
/// @param[in] __input The input range of code units to validate is possible for encoding into code points. | |
/// @param[in] __encoding The encoding to verify can properly encode the input of code units. | |
/// @param[in] __decode_state The state to use for the decoding portion of the validation check. | |
/// @param[in] __encode_state The state to use for the encoding portion of the validation check. | |
/// | |
/// @remarks This function explicitly does not call any extension points. It defers to doing a typical loop over | |
/// the code points to verify it can be decoded into code points, and then encoded back into code units, with no | |
/// errors and with the exact same value sequence as the original. | |
////// | |
template <typename _Input, typename _Encoding, typename _DecodeState, typename _EncodeState> | |
constexpr auto basic_validate_decodable_as( | |
_Input&& __input, _Encoding&& __encoding, _DecodeState& __decode_state, _EncodeState& __encode_state) { | |
using _UInput = __txt_detail::__remove_cvref_t<_Input>; | |
using _InputValueType = __txt_detail::__range_value_type_t<_UInput>; | |
using _WorkingInput = __txt_detail::__range_reconstruct_t<::std::conditional_t<::std::is_array_v<_UInput>, | |
::std::conditional_t<__txt_detail::__is_character_v<_InputValueType>, | |
::std::basic_string_view<_InputValueType>, ::ztd::text::span<const _InputValueType>>, | |
_UInput>>; | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
using _Result = validate_transcode_result<_WorkingInput, _DecodeState, _EncodeState>; | |
_WorkingInput __working_input( | |
__txt_detail::__reconstruct(::std::in_place_type<_WorkingInput>, ::std::forward<_Input>(__input))); | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_text_validate_decodable_as_one, | |
_WorkingInput, _Encoding, _DecodeState, _EncodeState>) { | |
using _Result = validate_transcode_result<_WorkingInput, _DecodeState, _EncodeState>; | |
for (;;) { | |
auto __result = text_validate_decodable_as_one( | |
tag<_UEncoding> {}, __encoding, __working_input, __decode_state, __encode_state); | |
if (!__result.valid) { | |
return _Result(::std::move(__result.input), false, __decode_state, __encode_state); | |
} | |
__working_input = ::std::move(__result.input); | |
if (__txt_detail::__adl::__adl_empty(__working_input)) { | |
break; | |
} | |
} | |
return _Result(::std::move(__working_input), true, __decode_state, __encode_state); | |
} | |
else if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_text_validate_decodable_as_one, | |
_WorkingInput, _Encoding, _DecodeState>) { | |
for (;;) { | |
auto __result = text_validate_decodable_as_one( | |
tag<_UEncoding> {}, __encoding, __working_input, __decode_state); | |
if (!__result.valid) { | |
return _Result(::std::move(__result.input), false, __decode_state, __encode_state); | |
} | |
__working_input = ::std::move(__result.input); | |
if (__txt_detail::__adl::__adl_empty(__working_input)) { | |
break; | |
} | |
} | |
return _Result(::std::move(__working_input), true, __decode_state, __encode_state); | |
} | |
else if constexpr (__txt_detail::__is_detected_v< | |
__txt_detail::__detect_adl_internal_text_validate_decodable_as_one, _WorkingInput, | |
_Encoding, _DecodeState, _EncodeState>) { | |
for (;;) { | |
auto __result = __text_validate_decodable_as_one( | |
tag<_UEncoding> {}, __encoding, __working_input, __decode_state, __encode_state); | |
if (!__result.valid) { | |
return _Result(::std::move(__result.input), false, __decode_state, __encode_state); | |
} | |
__working_input = ::std::move(__result.input); | |
if (__txt_detail::__adl::__adl_empty(__working_input)) { | |
break; | |
} | |
} | |
return _Result(::std::move(__working_input), true, __decode_state, __encode_state); | |
} | |
else if constexpr (__txt_detail::__is_detected_v< | |
__txt_detail::__detect_adl_internal_text_validate_decodable_as_one, _WorkingInput, | |
_Encoding, _DecodeState>) { | |
for (;;) { | |
auto __result = __text_validate_decodable_as_one( | |
tag<_UEncoding> {}, __encoding, __working_input, __decode_state); | |
if (!__result.valid) { | |
return _Result(::std::move(__result.input), false, __decode_state, __encode_state); | |
} | |
__working_input = ::std::move(__result.input); | |
if (__txt_detail::__adl::__adl_empty(__working_input)) { | |
break; | |
} | |
} | |
return _Result(::std::move(__working_input), true, __decode_state, __encode_state); | |
} | |
else { | |
using _CodeUnit = code_unit_t<_UEncoding>; | |
using _CodePoint = code_point_t<_UEncoding>; | |
_CodePoint __intermediate_storage[max_code_points_v<_UEncoding>] {}; | |
::ztd::text::span<_CodePoint, max_code_points_v<_UEncoding>> __intermediate(__intermediate_storage); | |
_CodeUnit __output_storage[max_code_units_v<_UEncoding>] {}; | |
::ztd::text::span<_CodeUnit, max_code_units_v<_UEncoding>> __output(__output_storage); | |
for (;;) { | |
auto __stateless_validate_result = __txt_detail::__basic_validate_decodable_as_one( | |
__working_input, __encoding, __output, __decode_state, __encode_state, __intermediate); | |
if (!__stateless_validate_result.valid) { | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_WorkingInput>, ::std::move(__working_input)), | |
false, __decode_state, __encode_state); | |
} | |
__working_input = ::std::move(__stateless_validate_result.input); | |
if (__txt_detail::__adl::__adl_empty(__working_input)) { | |
break; | |
} | |
} | |
return _Result( | |
__txt_detail::__reconstruct(::std::in_place_type<_WorkingInput>, ::std::move(__working_input)), | |
true, __decode_state, __encode_state); | |
} | |
} | |
////// | |
/// @brief Validates the code units of the @p __input according to the @p __encoding with the given states @p | |
/// __decode_state and @p __encode_state to see if it can be turned into code points. | |
/// | |
/// @param[in] __input The input range of code units to validate is possible for encoding into code points. | |
/// @param[in] __encoding The encoding to verify can properly encode the input of code units. | |
/// @param[in] __decode_state The state to use for the decoding portion of the validation check. | |
/// @param[in] __encode_state The state to use for the encoding portion of the validation check. | |
/// | |
/// @remarks This functions checks to see if extension points for @c text_validate_decodable_as is available taking | |
/// the available 4 parameters. If so, it calls this. Otherwise, it defers to ztd::text::validate_decodable_as. | |
////// | |
template <typename _Input, typename _Encoding, typename _DecodeState, typename _EncodeState> | |
constexpr auto validate_decodable_as( | |
_Input&& __input, _Encoding&& __encoding, _DecodeState& __decode_state, _EncodeState& __encode_state) { | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_text_validate_decodable_as, _Input, | |
_Encoding, _DecodeState>) { | |
return text_validate_decodable_as(tag<__txt_detail::__remove_cvref_t<_Encoding>> {}, | |
::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), __decode_state, | |
__encode_state); | |
} | |
else if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_text_validate_decodable_as, | |
_Input, _Encoding, _DecodeState>) { | |
(void)__encode_state; | |
return text_validate_decodable_as(tag<__txt_detail::__remove_cvref_t<_Encoding>> {}, | |
::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), __decode_state); | |
} | |
else if constexpr (__txt_detail::__is_detected_v< | |
__txt_detail::__detect_adl_internal_text_validate_decodable_as, _Input, _Encoding, | |
_DecodeState>) { | |
return __text_validate_decodable_as(tag<__txt_detail::__remove_cvref_t<_Encoding>> {}, | |
::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), __decode_state, | |
__encode_state); | |
} | |
else if constexpr (__txt_detail::__is_detected_v< | |
__txt_detail::__detect_adl_internal_text_validate_decodable_as, _Input, _Encoding, | |
_DecodeState>) { | |
(void)__encode_state; | |
return __text_validate_decodable_as(tag<__txt_detail::__remove_cvref_t<_Encoding>> {}, | |
::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), __decode_state); | |
} | |
else { | |
return basic_validate_decodable_as(::std::forward<_Input>(__input), | |
::std::forward<_Encoding>(__encoding), __decode_state, __encode_state); | |
} | |
} | |
////// | |
/// @brief Validates the code units of the @p __input according to the @p __encoding with the given state @p | |
/// __decode_state to see if it can be turned into code points. | |
/// | |
/// @param[in] __input The input range of code units to validate is possible for encoding into code points. | |
/// @param[in] __encoding The encoding to verify can properly encode the input of code units. | |
/// @param[in] __decode_state The state to use for the decoding portion of the validation check. | |
/// | |
/// @remarks This functions checks to see if extension points for @c text_validate_decodable_as is available taking | |
/// the available 3 parameters. If so, it calls this. Otherwise, it creates an encoding state through | |
/// ztd::text::make_encode_state before calling ztd::text::validate_decodable_as(__input, __encoding, | |
/// __decode_state, | |
/// __encode_state). | |
////// | |
template <typename _Input, typename _Encoding, typename _DecodeState> | |
constexpr auto validate_decodable_as(_Input&& __input, _Encoding&& __encoding, _DecodeState& __decode_state) { | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_text_validate_decodable_as, _Input, | |
_Encoding, _DecodeState>) { | |
return text_validate_decodable_as(tag<__txt_detail::__remove_cvref_t<_Encoding>> {}, | |
::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), __decode_state); | |
} | |
else if constexpr (__txt_detail::__is_detected_v< | |
__txt_detail::__detect_adl_internal_text_validate_decodable_as, _Input, _Encoding, | |
_DecodeState>) { | |
return __text_validate_decodable_as(tag<__txt_detail::__remove_cvref_t<_Encoding>> {}, | |
::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), __decode_state); | |
} | |
else { | |
using _State = encode_state_t<_UEncoding>; | |
_State __encode_state = make_encode_state_with(__encoding, __decode_state); | |
auto __stateful_result = validate_decodable_as(::std::forward<_Input>(__input), | |
::std::forward<_Encoding>(__encoding), __decode_state, __encode_state); | |
if constexpr (__txt_detail::__is_specialization_of_v<decltype(__stateful_result), validate_result>) { | |
return __stateful_result; | |
} | |
else { | |
return __txt_detail::__drop_single_state(::std::move(__stateful_result)); | |
} | |
} | |
} | |
////// | |
/// @brief Validates the code units of the @p __input according to the @p __encoding to see if they can be turned | |
/// into code points. | |
/// | |
/// @param[in] __input The input range of code units to validate is possible for encoding into code points. | |
/// @param[in] __encoding The encoding to verify can properly encode the input of code units. | |
/// | |
/// @remarks This functions creates an encoding @c state through ztd::text::make_decode_state before calling | |
/// the next overload of ztd::text::validate_decodable_as. | |
////// | |
template <typename _Input, typename _Encoding> | |
constexpr auto validate_decodable_as(_Input&& __input, _Encoding&& __encoding) { | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
using _State = decode_state_t<_UEncoding>; | |
_State __state = make_decode_state(__encoding); | |
auto __stateful_result | |
= validate_decodable_as(::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), __state); | |
return __txt_detail::__slice_to_stateless(::std::move(__stateful_result)); | |
} | |
////// | |
/// @brief Validates the code units of the @p __input to see if it can be turned into code points. | |
/// | |
/// @param[in] __input The input range of code units to validate is possible for encoding into code points. | |
/// | |
/// @returns A ztd::text::stateless_validate_result detailing whether or not the input code points can be turned | |
/// into code units of the corresponding encoding. | |
/// | |
/// @remarks This functions creates an @c encoding by passing the @c value_type of the @c __input range through | |
/// ztd::text::default_code_unit_encoding. | |
////// | |
template <typename _Input> | |
constexpr auto validate_decodable_as(_Input&& __input) { | |
using _UInput = __txt_detail::__remove_cvref_t<_Input>; | |
using _CodeUnit = __txt_detail::__remove_cvref_t<__txt_detail::__range_value_type_t<_UInput>>; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED_I_) | |
if (::std::is_constant_evaluated()) { | |
// Use literal encoding instead, if we meet the right criteria | |
using _Encoding = default_consteval_code_unit_encoding_t<_CodeUnit>; | |
_Encoding __encoding {}; | |
return validate_decodable_as(::std::forward<_Input>(__input), __encoding); | |
} | |
else | |
#endif | |
{ | |
using _Encoding = default_code_unit_encoding_t<_CodeUnit>; | |
_Encoding __encoding {}; | |
return validate_decodable_as(::std::forward<_Input>(__input), __encoding); | |
} | |
} | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/validate_decodable_as.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/validate_encodable_as.hpp | |
#include <algorithm> | |
#include <string_view> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_validate_encodable_as ztd::text::validate_encodable_as | |
/// @brief These functions check if the given input of code points will encode without an error. Note that this | |
/// does not mean that an error handler will be invoked that can "smooth over" any possible errors: this checks | |
/// solely if it will encode from code points into code units cleanly. | |
/// @{ | |
////// | |
////// | |
/// @brief Validates the code points of the @p __input according to the @p __encoding with the given states @p | |
/// __encode_state and @p __decode_state. | |
/// | |
/// @param[in] __input The input range of code points to validate is possible for encoding into code units. | |
/// @param[in] __encoding The encoding to verify can properly encode the input of code units. | |
/// @param[in] __encode_state The state to use for the encoding portion of the validation check. | |
/// @param[in] __decode_state The state to use for the decoding portion of the validation check, if needed. | |
/// | |
/// @remarks This function explicitly does not check any of the extension points. It defers to doing a typical loop | |
/// over the code points to verify it can be encoded into code units, and then decoded into code points, with no | |
/// errors. | |
////// | |
template <typename _Input, typename _Encoding, typename _EncodeState, typename _DecodeState> | |
constexpr auto basic_validate_encodable_as( | |
_Input&& __input, _Encoding&& __encoding, _EncodeState& __encode_state, _DecodeState& __decode_state) { | |
using _UInput = __txt_detail::__remove_cvref_t<_Input>; | |
using _InputValueType = __txt_detail::__range_value_type_t<_UInput>; | |
using _WorkingInput = __txt_detail::__range_reconstruct_t<::std::conditional_t<::std::is_array_v<_UInput>, | |
::std::conditional_t<__txt_detail::__is_character_v<_InputValueType>, | |
::std::basic_string_view<_InputValueType>, ::ztd::text::span<const _InputValueType>>, | |
_UInput>>; | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
using _Result = validate_transcode_result<_WorkingInput, _EncodeState, _DecodeState>; | |
_WorkingInput __working_input( | |
__txt_detail::__reconstruct(::std::in_place_type<_WorkingInput>, ::std::forward<_Input>(__input))); | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_text_validate_encodable_as_one, | |
_WorkingInput, _Encoding, _EncodeState, _DecodeState>) { | |
for (;;) { | |
auto __result = text_validate_encodable_as_one( | |
tag<_UEncoding> {}, ::std::move(__working_input), __encoding, __encode_state, __decode_state); | |
if (!__result.valid) { | |
return _Result(::std::move(__result.input), false, __encode_state, __decode_state); | |
} | |
__working_input = ::std::move(__result.input); | |
if (__txt_detail::__adl::__adl_empty(__working_input)) { | |
break; | |
} | |
} | |
return _Result(::std::move(__working_input), true, __encode_state, __decode_state); | |
} | |
else if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_text_validate_encodable_as_one, | |
_WorkingInput, _Encoding, _EncodeState>) { | |
for (;;) { | |
auto __result = text_validate_encodable_as_one( | |
tag<_UEncoding> {}, ::std::move(__working_input), __encoding, __encode_state); | |
if (!__result.valid) { | |
return _Result(::std::move(__result.input), false, __encode_state, __decode_state); | |
} | |
__working_input = ::std::move(__result.input); | |
if (__txt_detail::__adl::__adl_empty(__working_input)) { | |
break; | |
} | |
} | |
return _Result(::std::move(__working_input), true, __encode_state, __decode_state); | |
} | |
else if constexpr (__txt_detail::__is_detected_v< | |
__txt_detail::__detect_adl_internal_text_validate_encodable_as_one, _WorkingInput, | |
_Encoding, _EncodeState, _DecodeState>) { | |
for (;;) { | |
auto __result = text_validate_encodable_as_one( | |
tag<_UEncoding> {}, ::std::move(__working_input), __encoding, __encode_state, __decode_state); | |
if (!__result.valid) { | |
return _Result(::std::move(__result.input), false, __encode_state, __decode_state); | |
} | |
__working_input = ::std::move(__result.input); | |
if (__txt_detail::__adl::__adl_empty(__working_input)) { | |
break; | |
} | |
} | |
return _Result(::std::move(__working_input), true, __encode_state, __decode_state); | |
} | |
else if constexpr (__txt_detail::__is_detected_v< | |
__txt_detail::__detect_adl_internal_text_validate_encodable_as_one, _WorkingInput, | |
_Encoding, _EncodeState>) { | |
for (;;) { | |
auto __result = __text_validate_encodable_as_one( | |
tag<_UEncoding> {}, ::std::move(__working_input), __encoding, __encode_state); | |
if (!__result.valid) { | |
return _Result(::std::move(__result.input), false, __encode_state, __decode_state); | |
} | |
__working_input = ::std::move(__result.input); | |
if (__txt_detail::__adl::__adl_empty(__working_input)) { | |
break; | |
} | |
} | |
return _Result(::std::move(__working_input), true, __encode_state, __decode_state); | |
} | |
else if constexpr (__txt_detail::__is_detected_v< | |
__txt_detail::__detect_adl_internal_text_validate_encodable_as_one, _WorkingInput, | |
_Encoding, _EncodeState>) { | |
for (;;) { | |
auto __result = __text_validate_encodable_as_one( | |
tag<_UEncoding> {}, ::std::move(__working_input), __encoding, __encode_state); | |
if (!__result.valid) { | |
return _Result(::std::move(__result.input), false, __encode_state, __decode_state); | |
} | |
__working_input = ::std::move(__result.input); | |
if (__txt_detail::__adl::__adl_empty(__working_input)) { | |
break; | |
} | |
} | |
return _Result(::std::move(__working_input), true, __encode_state, __decode_state); | |
} | |
else { | |
using _CodeUnit = code_unit_t<_UEncoding>; | |
using _CodePoint = code_point_t<_UEncoding>; | |
_CodePoint __code_point_buf[max_code_points_v<_UEncoding>] {}; | |
_CodeUnit __code_unit_buf[max_code_units_v<_UEncoding>] {}; | |
::ztd::text::span<_CodePoint, max_code_points_v<_UEncoding>> __code_point_view(__code_point_buf); | |
::ztd::text::span<_CodeUnit, max_code_units_v<_UEncoding>> __code_unit_view(__code_unit_buf); | |
for (;;) { | |
auto __stateless_validate_result = __txt_detail::__basic_validate_encodable_as_one(__working_input, | |
__encoding, __code_unit_view, __encode_state, __decode_state, __code_point_view); | |
if (!__stateless_validate_result.valid) { | |
return _Result(__txt_detail::__reconstruct( | |
::std::in_place_type<_WorkingInput>, ::std::move(__working_input)), | |
false, __encode_state, __decode_state); | |
} | |
__working_input = ::std::move(__stateless_validate_result.input); | |
if (__txt_detail::__adl::__adl_empty(__working_input)) { | |
break; | |
} | |
} | |
return _Result( | |
__txt_detail::__reconstruct(::std::in_place_type<_WorkingInput>, ::std::move(__working_input)), | |
true, __encode_state, __decode_state); | |
} | |
} | |
////// | |
/// @brief Validates the code points of the @p __input according to the @p __encoding with the given states @p | |
/// __encode_state and @p __decode_state. | |
/// | |
/// @param[in] __input The input range of code points to validate is possible for encoding into code units. | |
/// @param[in] __encoding The encoding to verify can properly encode the input of code units. | |
/// @param[in] __encode_state The state to use for the encoding portion of the validation check. | |
/// @param[in] __decode_state The state to use for the decoding portion of the validation check, if needed. | |
/// | |
/// @remarks This functions checks to see if extension points for @c text_validate_encodable_as is available taking | |
/// the available 4 parameters. If so, it calls this. Otherwise, it defers to doing a typical loop over the code | |
/// points to verify it can be encoded into code units, and then decoded into code points, with no errors. | |
////// | |
template <typename _Input, typename _Encoding, typename _EncodeState, typename _DecodeState> | |
constexpr auto validate_encodable_as( | |
_Input&& __input, _Encoding&& __encoding, _EncodeState& __encode_state, _DecodeState& __decode_state) { | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_text_validate_encodable_as, _Input, | |
_Encoding, _EncodeState, _DecodeState>) { | |
return text_validate_encodable_as(tag<__txt_detail::__remove_cvref_t<_Encoding>> {}, | |
::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), __encode_state, | |
__decode_state); | |
} | |
else if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_text_validate_encodable_as, | |
_Input, _Encoding, _EncodeState>) { | |
(void)__decode_state; | |
return text_validate_encodable_as(tag<__txt_detail::__remove_cvref_t<_Encoding>> {}, | |
::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), __encode_state); | |
} | |
else if constexpr (__txt_detail::__is_detected_v< | |
__txt_detail::__detect_adl_internal_text_validate_encodable_as, _Input, _Encoding, | |
_EncodeState>) { | |
(void)__decode_state; | |
return __text_validate_encodable_as(tag<__txt_detail::__remove_cvref_t<_Encoding>> {}, | |
::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), __encode_state); | |
} | |
else if constexpr (__txt_detail::__is_detected_v< | |
__txt_detail::__detect_adl_internal_text_validate_encodable_as, _Input, _Encoding, | |
_EncodeState, _DecodeState>) { | |
return __text_validate_encodable_as(tag<__txt_detail::__remove_cvref_t<_Encoding>> {}, | |
::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), __encode_state, | |
__decode_state); | |
} | |
else { | |
return basic_validate_encodable_as(::std::forward<_Input>(__input), | |
::std::forward<_Encoding>(__encoding), __encode_state, __decode_state); | |
} | |
} | |
////// | |
/// @brief Validates the code points of the @p __input according to the @p __encoding with the given states @p | |
/// "__encode_state". | |
/// | |
/// @param[in] __input The input range of code points to validate is possible for encoding into code units. | |
/// @param[in] __encoding The encoding to verify can properly encode the input of code units. | |
/// @param[in] __encode_state The state for encoding to use. | |
/// | |
/// @remarks This functions checks to see if extension points for @c text_validate_encodable_as is available taking | |
/// the available 3 parameters. If so, it calls this. Otherwise, it defers to ztd::text::validate_encodable_as. | |
////// | |
template <typename _Input, typename _Encoding, typename _EncodeState> | |
constexpr auto validate_encodable_as(_Input&& __input, _Encoding&& __encoding, _EncodeState& __encode_state) { | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_text_validate_encodable_as, _Input, | |
_Encoding, _EncodeState>) { | |
return text_validate_encodable_as(tag<__txt_detail::__remove_cvref_t<_Encoding>> {}, | |
::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), __encode_state); | |
} | |
else if constexpr (__txt_detail::__is_detected_v< | |
__txt_detail::__detect_adl_internal_text_validate_encodable_as, _Input, _Encoding, | |
_EncodeState>) { | |
return __text_validate_encodable_as(tag<__txt_detail::__remove_cvref_t<_Encoding>> {}, | |
::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), __encode_state); | |
} | |
else { | |
using _State = decode_state_t<_UEncoding>; | |
_State __decode_state = make_decode_state_with(__encoding, __encode_state); | |
auto __stateful_result = validate_encodable_as(::std::forward<_Input>(__input), | |
::std::forward<_Encoding>(__encoding), __encode_state, __decode_state); | |
if constexpr (__txt_detail::__is_specialization_of_v<decltype(__stateful_result), validate_result>) { | |
return __stateful_result; | |
} | |
else { | |
return __txt_detail::__drop_single_state(::std::move(__stateful_result)); | |
} | |
} | |
} | |
////// | |
/// @brief Validates the code points of the @p __input according to the @p "__encoding". | |
/// | |
/// @param[in] __input The input range of code points to validate is possible for encoding into code units. | |
/// @param[in] __encoding The encoding to verify can properly encode the input of code units. | |
////// | |
template <typename _Input, typename _Encoding> | |
constexpr auto validate_encodable_as(_Input&& __input, _Encoding&& __encoding) { | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
using _State = encode_state_t<_UEncoding>; | |
_State __state = make_encode_state(__encoding); | |
auto __stateful_result | |
= validate_encodable_as(::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), __state); | |
return __txt_detail::__slice_to_stateless(::std::move(__stateful_result)); | |
} | |
////// | |
/// @brief Validates the code points of the input. | |
/// | |
/// @param[in] __input The input range of code points to validate is possible for encoding into code units. | |
/// | |
/// @remarks This passes the default encoding as inferred from the discernible @c value_type of the input range | |
/// input into the ztd::text::default_code_point_encoding. | |
////// | |
template <typename _Input> | |
constexpr auto validate_encodable_as(_Input&& __input) { | |
using _UInput = __txt_detail::__remove_cvref_t<_Input>; | |
using _CodePoint = __txt_detail::__remove_cvref_t<__txt_detail::__range_value_type_t<_UInput>>; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED_I_) | |
if (::std::is_constant_evaluated()) { | |
// Use literal encoding instead, if we meet the right criteria | |
using _Encoding = default_consteval_code_point_encoding_t<_CodePoint>; | |
_Encoding __encoding {}; | |
return validate_encodable_as(::std::forward<_Input>(__input), __encoding); | |
} | |
else | |
#endif | |
{ | |
using _Encoding = default_code_point_encoding_t<_CodePoint>; | |
_Encoding __encoding {}; | |
return validate_encodable_as(::std::forward<_Input>(__input), __encoding); | |
} | |
} | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/validate_encodable_as.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/count_encodable.hpp | |
#include <string_view> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_count_encodable ztd::text::count_encodable | |
/// @brief These functions use a variety of means to count the number of code points that will result from the | |
/// input code units. | |
/// @{ | |
////// | |
////// | |
/// @brief Counts the number of code units that will result from attempting an encode operation on the input code | |
/// points. | |
/// | |
/// @param[in] __input The input range (of code points) to find out how many code units there are. | |
/// @param[in] __encoding The encoding to count the input with. | |
/// @param[in] __error_handler The error handler to invoke when an encode operation fails. | |
/// @param[in,out] __state The state that will be used to count code units. | |
/// | |
/// @returns A ztd::text::count_result that includes information about how many code units are present, | |
/// taking into account any invoked errors (like replacement from ztd::text::replacement_handler) and a reference | |
/// to the provided @p __state. | |
/// | |
/// @remarks This method will not check any ADL extension points. A combination of implementation techniques will | |
/// be used to count code units, with a loop over the @c .encode call into an intermediate, unseen buffer being the | |
/// most basic choice. | |
////// | |
template <typename _Input, typename _Encoding, typename _ErrorHandler, typename _State> | |
constexpr auto basic_count_encodable( | |
_Input&& __input, _Encoding&& __encoding, _ErrorHandler&& __error_handler, _State& __state) { | |
using _UInput = __txt_detail::__remove_cvref_t<_Input>; | |
using _InputValueType = __txt_detail::__range_value_type_t<_UInput>; | |
using _WorkingInput = __txt_detail::__range_reconstruct_t<::std::conditional_t<::std::is_array_v<_UInput>, | |
::std::conditional_t<__txt_detail::__is_character_v<_InputValueType>, | |
::std::basic_string_view<_InputValueType>, ::ztd::text::span<const _InputValueType>>, | |
_UInput>>; | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
using _Result = count_result<_WorkingInput, _State>; | |
_WorkingInput __working_input( | |
__txt_detail::__reconstruct(::std::in_place_type<_WorkingInput>, ::std::forward<_Input>(__input))); | |
::std::size_t __code_unit_count = 0; | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_text_count_encodable_one, _Encoding, | |
_WorkingInput, _ErrorHandler, _State>) { | |
for (;;) { | |
auto __result = text_count_encodable_one( | |
tag<_UEncoding> {}, ::std::move(__working_input), __encoding, __error_handler, __state); | |
if (__result.error_code != encoding_error::ok) { | |
return _Result( | |
::std::move(__result.input), __code_unit_count, __state, __result.error_code, false); | |
} | |
__code_unit_count += __result.count; | |
__working_input = ::std::move(__result.input); | |
if (__txt_detail::__adl::__adl_empty(__working_input)) { | |
break; | |
} | |
} | |
} | |
else if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_internal_text_count_encodable_one, | |
_Encoding, _WorkingInput, _ErrorHandler, _State>) { | |
for (;;) { | |
auto __result = __text_count_encodable_one( | |
tag<_UEncoding> {}, ::std::move(__working_input), __encoding, __error_handler, __state); | |
if (__result.error_code != encoding_error::ok) { | |
return _Result( | |
::std::move(__result.input), __code_unit_count, __state, __result.error_code, false); | |
} | |
__code_unit_count += __result.count; | |
__working_input = ::std::move(__result.input); | |
if (__txt_detail::__adl::__adl_empty(__working_input)) { | |
break; | |
} | |
} | |
} | |
else { | |
using _CodeUnit = code_unit_t<_UEncoding>; | |
_CodeUnit __intermediate_storage[max_code_units_v<_UEncoding>] {}; | |
::ztd::text::span<_CodeUnit, max_code_units_v<_UEncoding>> __intermediate(__intermediate_storage); | |
for (;;) { | |
auto __result = __txt_detail::__basic_count_encodable_one( | |
::std::move(__working_input), __encoding, __error_handler, __state, __intermediate); | |
if (__result.error_code != encoding_error::ok) { | |
return _Result( | |
::std::move(__result.input), __code_unit_count, __state, __result.error_code, false); | |
} | |
__code_unit_count += __result.count; | |
__working_input = ::std::move(__result.input); | |
if (__txt_detail::__adl::__adl_empty(__working_input)) { | |
break; | |
} | |
} | |
} | |
return _Result(::std::move(__working_input), __code_unit_count, __state, encoding_error::ok, false); | |
} | |
////// | |
/// @brief Counts the number of code units that will result from attempting an encode operation on the input code | |
/// points. | |
/// | |
/// @param[in] __input The input range (of code points) to find out how many code units there are. | |
/// @param[in] __encoding The encoding to count the input with. | |
/// @param[in] __error_handler The error handler to invoke when an encode operation fails. | |
/// @param[in,out] __state The state that will be used to count code units. | |
/// | |
/// @returns A ztd::text::count_result that includes information about how many code units are present, | |
/// taking into account any invoked errors (like replacement from ztd::text::replacement_handler) and a reference | |
/// to the provided @p __state. | |
/// | |
/// @remarks This method will first check if an ADL Extension Point @c text_count_encodable is callable with | |
/// the given arguments. If it is, then that method will be used to do the work after forwarding all four arguments | |
/// to that function call. Otherwise, this defers to ztd::text::basic_count_encodable. | |
////// | |
template <typename _Input, typename _Encoding, typename _ErrorHandler, typename _State> | |
constexpr auto count_encodable( | |
_Input&& __input, _Encoding&& __encoding, _ErrorHandler&& __error_handler, _State& __state) { | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_text_count_encodable, _Input, | |
_Encoding, _ErrorHandler, _State>) { | |
return text_count_encodable(tag<__txt_detail::__remove_cvref_t<_Encoding>> {}, | |
::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), | |
::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
else if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_internal_text_count_encodable, | |
_Input, _Encoding, _ErrorHandler, _State>) { | |
return __text_count_encodable(tag<__txt_detail::__remove_cvref_t<_Encoding>> {}, | |
::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), | |
::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
else { | |
return basic_count_encodable(::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), | |
::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
} | |
////// | |
/// @brief Counts the number of code units that will result from attempting an encode operation on the input code | |
/// points. | |
/// | |
/// @param[in] __input The input range (of code points) to find out how many code units there are. | |
/// @param[in] __encoding The encoding to count the input with. | |
/// @param[in] __error_handler The error handler to invoke when an encode operation fails. | |
/// | |
/// @returns A ztd::text::stateless_count_result that includes information about how many code units are present, | |
/// taking into account any invoked errors (like replacement from ztd::text::replacement_handler). | |
/// | |
/// @remarks This method will call ztd::text::count_encodable(Input, Encoding, ErrorHandler, State) with an | |
/// @c state created by ztd::text::make_encode_state(Encoding). | |
////// | |
template <typename _Input, typename _Encoding, typename _ErrorHandler> | |
constexpr auto count_encodable(_Input&& __input, _Encoding&& __encoding, _ErrorHandler&& __error_handler) { | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
using _State = encode_state_t<_UEncoding>; | |
_State __state = make_encode_state(__encoding); | |
return count_encodable(::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), | |
::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
////// | |
/// @brief Counts the number of code units that will result from attempting an encode operation. | |
/// | |
/// @param[in] __input The input range (of code points) to find out how many code units there are. | |
/// @param[in] __encoding The encoding to count the input with. | |
/// | |
/// @returns A ztd::text::stateless_count_result that includes information about how many code units are present, | |
/// taking into account any invoked errors (like replacement from ztd::text::replacement_handler). | |
/// | |
/// @remarks This method will call ztd::text::count_encodable(Input, Encoding, ErrorHandler) by creating an | |
/// @c error_handler similar to ztd::text::default_handler. | |
////// | |
template <typename _Input, typename _Encoding> | |
constexpr auto count_encodable(_Input&& __input, _Encoding&& __encoding) { | |
default_handler __handler {}; | |
return count_encodable(::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), __handler); | |
} | |
////// | |
/// @brief Counts the number of code units that will result from attempting an encode operation on the input code | |
/// points. | |
/// | |
/// @param[in] __input The input range (of code points) to find out how many code units there are. | |
/// | |
/// @returns A ztd::text::stateless_count_result that includes information about how many code units are present, | |
/// taking into account any invoked errors (like replacement from ztd::text::replacement_handler). | |
/// | |
/// @remarks Calls ztd::text::count_encodable(Input, Encoding) with an @c encoding that is derived from | |
/// ztd::text::default_code_unit_encoding. | |
////// | |
template <typename _Input> | |
constexpr auto count_encodable(_Input&& __input) { | |
using _UInput = __txt_detail::__remove_cvref_t<_Input>; | |
using _CodePoint = __txt_detail::__remove_cvref_t<__txt_detail::__range_value_type_t<_UInput>>; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED_I_) | |
if (::std::is_constant_evaluated()) { | |
// Use literal encoding instead, if we meet the right criteria | |
using _Encoding = default_consteval_code_point_encoding_t<_CodePoint>; | |
_Encoding __encoding {}; | |
return count_encodable(::std::forward<_Input>(__input), __encoding); | |
} | |
else | |
#endif | |
{ | |
using _Encoding = default_consteval_code_point_encoding_t<_CodePoint>; | |
_Encoding __encoding {}; | |
return count_encodable(::std::forward<_Input>(__input), __encoding); | |
} | |
} | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/count_encodable.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/count_decodable.hpp | |
#include <string_view> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_count_decodable ztd::text::count_decodable | |
/// @brief These functions use a variety of means to count the number of code units that will result from the input | |
/// code points. | |
/// @{ | |
////// | |
////// | |
/// @brief Counts the number of code units that will result from attempting a decode operation. | |
/// | |
/// @param[in] __input The input range (of code units) to find out how many code points there are. | |
/// @param[in] __encoding The encoding to count the input with. | |
/// @param[in] __error_handler The error handler to invoke when an encode operation fails. | |
/// @param[in,out] __state The state that will be used to count code units. | |
/// | |
/// @returns A ztd::text::count_result that includes information about how many code units are present, | |
/// taking into account any invoked errors (like replacement from ztd::text::replacement_handler) and a reference | |
/// to the provided @p __state. | |
/// | |
/// @remarks This method does not call ADL extension points. It attempts a combination of implementation techniques | |
/// to count code units, with a loop over the @c .decode call into an intermediate, unseen buffer being the most | |
/// basic guaranteed implementation attempt. | |
////// | |
template <typename _Input, typename _Encoding, typename _ErrorHandler, typename _State> | |
constexpr auto basic_count_decodable( | |
_Input&& __input, _Encoding&& __encoding, _ErrorHandler&& __error_handler, _State& __state) { | |
using _UInput = __txt_detail::__remove_cvref_t<_Input>; | |
using _InputValueType = __txt_detail::__range_value_type_t<_UInput>; | |
using _WorkingInput = __txt_detail::__range_reconstruct_t<::std::conditional_t<::std::is_array_v<_UInput>, | |
::std::conditional_t<__txt_detail::__is_char_traitable_v<_InputValueType>, | |
::std::basic_string_view<_InputValueType>, ::ztd::text::span<const _InputValueType>>, | |
_UInput>>; | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
using _Result = count_result<_WorkingInput, _State>; | |
_WorkingInput __working_input( | |
__txt_detail::__reconstruct(::std::in_place_type<_WorkingInput>, ::std::forward<_Input>(__input))); | |
::std::size_t __code_point_count = 0; | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_text_count_decodable_one, | |
_WorkingInput, _Encoding, _ErrorHandler, _State>) { | |
for (;;) { | |
auto __result = text_count_decodable_one( | |
tag<_UEncoding> {}, ::std::move(__working_input), __encoding, __error_handler, __state); | |
if (__result.error_code != encoding_error::ok) { | |
return _Result( | |
::std::move(__result.input), __code_point_count, __state, __result.error_code, false); | |
} | |
__code_point_count += __result.count; | |
__working_input = ::std::move(__result.input); | |
if (__txt_detail::__adl::__adl_empty(__working_input)) { | |
break; | |
} | |
} | |
return _Result(::std::move(__working_input), __code_point_count, __state, encoding_error::ok, false); | |
} | |
else if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_internal_text_count_decodable_one, | |
_WorkingInput, _Encoding, _ErrorHandler, _State>) { | |
for (;;) { | |
auto __result = __text_count_decodable_one( | |
tag<_UEncoding> {}, ::std::move(__working_input), __encoding, __error_handler, __state); | |
if (__result.error_code != encoding_error::ok) { | |
return _Result( | |
::std::move(__result.input), __code_point_count, __state, __result.error_code, false); | |
} | |
__code_point_count += __result.count; | |
__working_input = ::std::move(__result.input); | |
if (__txt_detail::__adl::__adl_empty(__working_input)) { | |
break; | |
} | |
} | |
return _Result(::std::move(__working_input), __code_point_count, __state, encoding_error::ok, false); | |
} | |
else { | |
using _CodePoint = code_point_t<_UEncoding>; | |
_CodePoint __intermediate_storage[max_code_points_v<_UEncoding>] {}; | |
::ztd::text::span<_CodePoint, max_code_points_v<_UEncoding>> __intermediate(__intermediate_storage); | |
for (;;) { | |
auto __result = __txt_detail::__basic_count_decodable_one( | |
__working_input, __encoding, __error_handler, __state, __intermediate); | |
if (__result.error_code != encoding_error::ok) { | |
return _Result( | |
::std::move(__result.input), __code_point_count, __state, __result.error_code, false); | |
} | |
__code_point_count += __result.count; | |
__working_input = ::std::move(__result.input); | |
if (__txt_detail::__adl::__adl_empty(__working_input)) { | |
break; | |
} | |
} | |
return _Result(::std::move(__working_input), __code_point_count, __state, encoding_error::ok, false); | |
} | |
} | |
////// | |
/// @brief Counts the number of code units that will result from attempting a decode operation. | |
/// | |
/// @param[in] __input The input range (of code units) to find out how many code points there are. | |
/// @param[in] __encoding The encoding to count the input with. | |
/// @param[in] __error_handler The error handler to invoke when an encode operation fails. | |
/// @param[in,out] __state The state that will be used to count code units. | |
/// | |
/// @returns A ztd::text::count_result that includes information about how many code units are present, | |
/// taking into account any invoked errors (like replacement from ztd::text::replacement_handler) and a reference | |
/// to the provided @p __state. | |
/// | |
/// @remarks This method will first check if an ADL Extension Point @c text_count_decodable is callable with | |
/// the given arguments. If it is, then that method will be used to do the work after forwarding all four arguments | |
/// to that function call. Otherwise, it defers to ztd::text::basic_count_decodable. | |
////// | |
template <typename _Input, typename _Encoding, typename _ErrorHandler, typename _State> | |
constexpr auto count_decodable( | |
_Input&& __input, _Encoding&& __encoding, _ErrorHandler&& __error_handler, _State& __state) { | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_text_count_decodable, _Input, | |
_Encoding, _ErrorHandler, _State>) { | |
return text_count_decodable(tag<__txt_detail::__remove_cvref_t<_Encoding>> {}, | |
::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), | |
::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
else if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_internal_text_count_decodable, | |
_Input, _Encoding, _ErrorHandler, _State>) { | |
return __text_count_decodable(tag<__txt_detail::__remove_cvref_t<_Encoding>> {}, | |
::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), | |
::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
else { | |
return basic_count_decodable(::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), | |
::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
} | |
////// | |
/// @brief Counts the number of code units that will result from attempting a decode operation. | |
/// | |
/// @param[in] __input The input range (of code units) to find out how many code points there are. | |
/// @param[in] __encoding The encoding to count the input with. | |
/// @param[in] __error_handler The error handler to invoke when an encode operation fails. | |
/// | |
/// @returns A ztd::text::stateless_count_result that includes information about how many code units are present, | |
/// taking into account any invoked errors (like replacement from ztd::text::replacement_handler). | |
/// | |
/// @remarks Calls ztd::text::count_decodable(Input, Encoding, ErrorHandler, State) with an @c state that is | |
/// created by ztd::text::make_decode_state(Encoding). | |
////// | |
template <typename _Input, typename _Encoding, typename _ErrorHandler> | |
constexpr auto count_decodable(_Input&& __input, _Encoding&& __encoding, _ErrorHandler&& __error_handler) { | |
using _UEncoding = __txt_detail::__remove_cvref_t<_Encoding>; | |
using _State = decode_state_t<_UEncoding>; | |
_State __state = make_decode_state(__encoding); | |
auto __stateful_result = count_decodable(::std::forward<_Input>(__input), | |
::std::forward<_Encoding>(__encoding), ::std::forward<_ErrorHandler>(__error_handler), __state); | |
return __txt_detail::__slice_to_stateless(::std::move(__stateful_result)); | |
} | |
////// | |
/// @brief Counts the number of code units that will result from attempting a decode operation. | |
/// | |
/// @param[in] __input The input range (of code units) to find out how many code points there are. | |
/// @param[in] __encoding The encoding to count the input with. | |
/// | |
/// @returns A ztd::text::stateless_count_result that includes information about how many code units are present, | |
/// taking into account any invoked errors (like replacement from ztd::text::replacement_handler). | |
/// | |
/// @remarks Calls ztd::text::count_decodable(Input, Encoding, ErrorHandler) with an @c error_handler that is | |
/// similar to ztd::text::default_handler. | |
////// | |
template <typename _Input, typename _Encoding> | |
constexpr auto count_decodable(_Input&& __input, _Encoding&& __encoding) { | |
default_handler __handler {}; | |
return count_decodable(::std::forward<_Input>(__input), ::std::forward<_Encoding>(__encoding), __handler); | |
} | |
////// | |
/// @brief Counts the number of code units that will result from attempting a decode operation. | |
/// | |
/// @param[in] __input The input range (of code units) to find out how many code points there are. | |
/// | |
/// @returns A ztd::text::stateless_count_result that includes information about how many code units are present, | |
/// taking into account any invoked errors (like replacement from ztd::text::replacement_handler). | |
/// | |
/// @remarks Calls ztd::text::count_decodable(Input, Encoding) with an @c encoding that is derived from | |
/// ztd::text::default_code_unit_encoding. | |
////// | |
template <typename _Input> | |
constexpr auto count_decodable(_Input&& __input) { | |
using _UInput = __txt_detail::__remove_cvref_t<_Input>; | |
using _CodeUnit = __txt_detail::__range_value_type_t<_UInput>; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED_I_) | |
if (::std::is_constant_evaluated()) { | |
// Use literal encoding instead, if we meet the right criteria | |
using _Encoding = default_consteval_code_unit_encoding_t<_CodeUnit>; | |
_Encoding __encoding {}; | |
return count_decodable(::std::forward<_Input>(__input), __encoding); | |
} | |
else | |
#endif | |
{ | |
using _Encoding = default_code_unit_encoding_t<_CodeUnit>; | |
_Encoding __encoding {}; | |
return count_decodable(::std::forward<_Input>(__input), __encoding); | |
} | |
} | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/count_decodable.hpp | |
#include <cstdint> | |
#include <cstddef> | |
#include <utility> | |
#include <functional> | |
#include <memory> | |
#include <cassert> | |
#include <optional> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
inline constexpr ::std::size_t __default_max_code_points_any_encoding = 32; | |
inline constexpr ::std::size_t __default_max_code_units_any_encoding = 128; | |
} // namespace __txt_detail | |
////// | |
/// @addtogroup ztd_text_encodings Encodings | |
/// @{ | |
////// | |
////// | |
/// @brief An encoding class which has the given encode output and input, as well as the decode input and output | |
/// ranges, provided as fixed types alongside the maximum number of code units put in and pushed out. | |
/// | |
/// @tparam _EncodeCodeUnits The output of @c encode_one and related operations. | |
/// @tparam _EncodeCodePoints The input of @c encode_one and related operations. | |
/// @tparam _DecodeCodeUnits The input of @c decode_one and related operations. | |
/// @tparam _DecodeCodePoints The output of @c decode_one and related operations. | |
/// @tparam _MaxCodeUnits The maximum number of code units that can be output through a given operation. Directly | |
/// related to the maximum_code_units inline constexpr variable definition. | |
/// @tparam _MaxCodePoints The maximum number of code points that can be output through a given operation. Directly | |
/// related to the maximum_code_points inline constexpr variable definition. | |
/// | |
/// @remarks This class is generally interacted with by using its derivate class, ztd::text::any_byte_encoding, and | |
/// its convenience alias, ztd::text::any_encoding. This class's use is recommended only for power users who have | |
/// encoding ranges that cannot be interacted with through @c ztd::text::span and therefore need other ways. We are | |
/// looking into ways to produce a subrange<any_iterator> as a completely generic range to aid those individuals | |
/// who do not want to deal in just @c ztd::text::span s. | |
////// | |
template <typename _EncodeCodeUnits, typename _EncodeCodePoints, typename _DecodeCodeUnits, | |
typename _DecodeCodePoints, ::std::size_t _MaxCodeUnits = __txt_detail::__default_max_code_units_any_encoding, | |
::std::size_t _MaxCodePoints = __txt_detail::__default_max_code_points_any_encoding> | |
class any_encoding_with { | |
public: | |
class any_encode_state; | |
class any_decode_state; | |
public: | |
////// | |
/// @brief The state that can be used between calls to @c decode. | |
/// | |
/// @remarks This is an opaque struct with no members. It follows the "encoding-dependent state" model, which | |
/// means it has a constructor that takes an ztd::text::any_encoding_with so it can properly initialize its | |
/// state. | |
////// | |
using decode_state = any_decode_state; | |
////// | |
/// @brief The state that can be used between calls to @c encode. | |
/// | |
/// @remarks This is an opaque struct with no members. It follows the "encoding-dependent state" model, which | |
/// means it has a constructor that takes an ztd::text::any_encoding_with so it can properly initialize its | |
/// state. | |
////// | |
using encode_state = any_encode_state; | |
////// | |
/// @brief The individual units that result from an encode operation or are used as input to a decode | |
/// operation. | |
////// | |
using code_unit = __txt_detail::__range_value_type_t<_EncodeCodeUnits>; | |
////// | |
/// @brief The individual units that result from a decode operation or as used as input to an encode | |
/// operation. | |
////// | |
using code_point = __txt_detail::__range_value_type_t<_DecodeCodePoints>; | |
////// | |
/// @brief Whether or not the encode operation can process all forms of input into code point values. | |
/// | |
/// @remarks This is always going to be false because this is a type-erased encoding; this value is determined | |
/// by a runtime decision, which means that the most conservative and truthful answer is selected for this | |
/// property. | |
////// | |
using is_encode_injective = ::std::false_type; | |
////// | |
/// @brief Whether or not the decode operation can process all forms of input into code point values. | |
/// | |
/// @remarks This is always going to be false because this is a type-erased encoding; this value is determined | |
/// by a runtime decision, which means that the most conservative and truthful answer is selected for this | |
/// property. | |
////// | |
using is_decode_injective = ::std::false_type; | |
////// | |
/// @brief The maximum number of code points a single complete operation of decoding can produce. This is | |
/// 1 for all Unicode Transformation Format (UTF) encodings. | |
////// | |
static inline constexpr ::std::size_t max_code_points = _MaxCodePoints; | |
////// | |
/// @brief The maximum code units a single complete operation of encoding can produce. | |
/// | |
////// | |
static inline constexpr ::std::size_t max_code_units = _MaxCodeUnits; | |
private: | |
using __decode_result = decode_result<_DecodeCodeUnits, _DecodeCodePoints, decode_state>; | |
using __encode_result = encode_result<_EncodeCodePoints, _EncodeCodeUnits, encode_state>; | |
using __count_decodable_result = count_result<_DecodeCodeUnits, decode_state>; | |
using __count_encodable_result = count_result<_EncodeCodePoints, encode_state>; | |
using __validate_decodable_as_result = validate_result<_DecodeCodeUnits, decode_state>; | |
using __validate_encodable_as_result = validate_result<_EncodeCodePoints, encode_state>; | |
using __decode_error_handler = ::std::function<__decode_result( | |
const any_encoding_with&, __decode_result, const ::ztd::text::span<const code_unit>&)>; | |
using __encode_error_handler = ::std::function<__encode_result( | |
const any_encoding_with&, __encode_result, const ::ztd::text::span<const code_point>&)>; | |
using __count_decodable_error_handler = ::std::function<__decode_result( | |
const any_encoding_with&, __decode_result, const ::ztd::text::span<const code_point>&)>; | |
using __count_encodable_error_handler = ::std::function<__encode_result( | |
const any_encoding_with&, __encode_result, const ::ztd::text::span<const code_unit>&)>; | |
struct __erased_state { | |
virtual ~__erased_state() { | |
} | |
}; | |
struct __erased { | |
virtual bool __contains_unicode_encoding() const noexcept = 0; | |
virtual ::std::optional<::ztd::text::span<const code_point>> | |
__maybe_replacement_code_points() const noexcept = 0; | |
virtual ::std::optional<::ztd::text::span<const code_unit>> | |
__maybe_replacement_code_units() const noexcept = 0; | |
virtual __decode_result __decode_one(_DecodeCodeUnits __input, _DecodeCodePoints __output, | |
__decode_error_handler __error_handler, decode_state& __state) const = 0; | |
virtual __encode_result __encode_one(_EncodeCodePoints __input, _EncodeCodeUnits __output, | |
__encode_error_handler __error_handler, encode_state& __state) const = 0; | |
virtual __validate_decodable_as_result __validate_decodable_as_one( | |
_DecodeCodeUnits __input, decode_state& __state) const = 0; | |
virtual __validate_encodable_as_result __validate_encodable_as_one( | |
_EncodeCodePoints __input, encode_state& __state) const = 0; | |
virtual __count_encodable_result __count_encodable_one(_EncodeCodePoints __input, | |
__count_encodable_error_handler __error_handler, encode_state& __state) const = 0; | |
virtual __count_decodable_result __count_decodable_one(_DecodeCodeUnits __input, | |
__count_decodable_error_handler __error_handler, decode_state& __state) const = 0; | |
virtual __decode_result __decode(_DecodeCodeUnits __input, _DecodeCodePoints __output, | |
__decode_error_handler __error_handler, decode_state& __state) const = 0; | |
virtual __encode_result __encode(_EncodeCodePoints __input, _EncodeCodeUnits __output, | |
__encode_error_handler __error_handler, encode_state& __state) const = 0; | |
virtual __validate_decodable_as_result __validate_decodable_as( | |
_DecodeCodeUnits __input, decode_state& __state) const = 0; | |
virtual __validate_encodable_as_result __validate_encodable_as( | |
_EncodeCodePoints __input, encode_state& __state) const = 0; | |
virtual __count_encodable_result __count_encodable(_EncodeCodePoints __input, | |
__count_encodable_error_handler __error_handler, encode_state& __state) const = 0; | |
virtual __count_decodable_result __count_decodable(_DecodeCodeUnits __input, | |
__count_decodable_error_handler __error_handler, decode_state& __state) const = 0; | |
virtual ::std::unique_ptr<__erased_state> __create_encode_state() const = 0; | |
virtual ::std::unique_ptr<__erased_state> __create_decode_state() const = 0; | |
virtual ~__erased() { | |
} | |
}; | |
public: | |
////// | |
/// @brief The state for any encoding's decode state. | |
/// | |
////// | |
class any_decode_state { | |
public: | |
////// | |
/// @brief Creates a state properly initialized from the stored encoding. | |
/// | |
////// | |
any_decode_state(const any_encoding_with& __encoding) | |
: _M_state(__encoding._M_storage->__create_decode_state()) { | |
} | |
////// | |
/// @brief You cannot copy construct an any_decode_state. | |
/// | |
////// | |
any_decode_state(const any_decode_state&) = delete; | |
////// | |
/// @brief You cannot copy assign an any_decode_state. | |
/// | |
////// | |
any_decode_state& operator=(const any_decode_state&) = delete; | |
////// | |
/// @brief Move constructs an any_decode_state. | |
/// | |
////// | |
any_decode_state(any_decode_state&&) = default; | |
////// | |
/// @brief Move assigns an any_decode_state. | |
/// | |
////// | |
any_decode_state& operator=(any_decode_state&&) = default; | |
__erased_state* _M_get_erased_state() const noexcept { | |
return _M_state.get(); | |
} | |
private: | |
template <typename> | |
friend struct __typed; | |
::std::unique_ptr<__erased_state> _M_state; | |
}; | |
////// | |
/// @brief The state for any encoding's encode state. | |
/// | |
////// | |
class any_encode_state { | |
public: | |
////// | |
/// @brief Creates a state properly initialized from the stored encoding. | |
/// | |
////// | |
any_encode_state(const any_encoding_with& __encoding) | |
: _M_state(__encoding._M_storage->__create_encode_state()) { | |
} | |
////// | |
/// @brief You cannot copy construct an any_encode_state. | |
/// | |
////// | |
any_encode_state(const any_encode_state&) = delete; | |
////// | |
/// @brief You cannot copy assign an any_encode_state. | |
/// | |
////// | |
any_encode_state& operator=(const any_encode_state&) = delete; | |
////// | |
/// @brief Move constructs an any_encode_state. | |
/// | |
////// | |
any_encode_state(any_encode_state&&) = default; | |
////// | |
/// @brief Move assigns an any_encode_state. | |
/// | |
////// | |
any_encode_state& operator=(any_encode_state&&) = default; | |
__erased_state* _M_get_erased_state() const noexcept { | |
return _M_state.get(); | |
} | |
private: | |
/* broken in Clang/GCC */ | |
template <typename> | |
friend struct __typed; | |
::std::unique_ptr<__erased_state> _M_state; | |
}; | |
private: | |
template <typename _State> | |
struct __typed_state : public __erased_state, public __txt_detail::__ebco<_State, 0> { | |
private: | |
using __base_t = __txt_detail::__ebco<_State, 0>; | |
public: | |
using __base_t::__base_t; | |
}; | |
template <typename _Encoding> | |
struct __typed : public __erased, private __txt_detail::__ebco<_Encoding> { | |
private: | |
static_assert(max_code_points_v<_Encoding> <= max_code_points, | |
"encoding must have less than or equal to the number of max potential output code points"); | |
static_assert(max_code_units_v<_Encoding> <= max_code_units, | |
"encoding must have less than or equal to the number of max potential output code units"); | |
using __real_decode_state = decode_state_t<_Encoding>; | |
using __real_encode_state = encode_state_t<_Encoding>; | |
using __encoding_t = _Encoding; | |
using __base_t = __txt_detail::__ebco<_Encoding>; | |
public: | |
using __base_t::__base_t; | |
virtual ::std::optional<::ztd::text::span<const code_point>> | |
__maybe_replacement_code_points() const noexcept override { | |
if constexpr (is_code_points_replaceable_v<_Encoding>) { | |
using __inner_type = ::ztd::text::span<const code_point>; | |
const _Encoding& __real_encoding = this->__base_t::__get_value(); | |
decltype(auto) __real_replacement = __real_encoding.replacement_code_points(); | |
return __inner_type(__txt_detail::__adl::__adl_data(__real_replacement), | |
__txt_detail::__adl::__adl_size(__real_replacement)); | |
} | |
else if constexpr (is_code_points_maybe_replaceable_v<_Encoding>) { | |
const _Encoding& __real_encoding = this->__base_t::__get_value(); | |
return __real_encoding.maybe_replacement_code_points(); | |
} | |
else { | |
return ::std::nullopt; | |
} | |
} | |
virtual ::std::optional<::ztd::text::span<const code_unit>> | |
__maybe_replacement_code_units() const noexcept override { | |
if constexpr (is_code_units_replaceable_v<_Encoding>) { | |
using __inner_type = ::ztd::text::span<const code_unit>; | |
const _Encoding& __real_encoding = this->__base_t::__get_value(); | |
decltype(auto) __real_replacement = __real_encoding.replacement_code_units(); | |
return __inner_type(__txt_detail::__adl::__adl_data(__real_replacement), | |
__txt_detail::__adl::__adl_size(__real_replacement)); | |
} | |
else if constexpr (is_code_units_maybe_replaceable_v<_Encoding>) { | |
const _Encoding& __real_encoding = this->__base_t::__get_value(); | |
return __real_encoding.maybe_replacement_code_units(); | |
} | |
else { | |
return ::std::nullopt; | |
} | |
} | |
virtual bool __contains_unicode_encoding() const noexcept override { | |
const auto& __real_encoding = this->__base_t::__get_value(); | |
return ::ztd::text::contains_unicode_encoding(__real_encoding); | |
} | |
// TODO: use proper wrapping handlers, | |
// not the pass-through handlers here (so that the functions get called correctly) | |
// modifiers: single operations | |
virtual __decode_result __decode_one(_DecodeCodeUnits __input, _DecodeCodePoints __output, | |
__decode_error_handler __error_handler, decode_state& __state) const override { | |
__real_decode_state& __actual_state = this->_M_get_state(__state); | |
__txt_detail::__pass_through_handler __pass_handler; | |
auto __raw_result = this->__base_t::__get_value().decode_one( | |
::std::move(__input), ::std::move(__output), __pass_handler, __actual_state); | |
return __decode_result(::std::move(__raw_result.input), ::std::move(__raw_result.output), __state, | |
__raw_result.error_code, __raw_result.handled_errors); | |
} | |
virtual __encode_result __encode_one(_EncodeCodePoints __input, _EncodeCodeUnits __output, | |
__encode_error_handler __error_handler, encode_state& __state) const override { | |
__real_encode_state& __actual_state = this->_M_get_state(__state); | |
__txt_detail::__pass_through_handler __pass_handler; | |
auto __raw_result = this->__base_t::__get_value().encode_one( | |
::std::move(__input), ::std::move(__output), __pass_handler, __actual_state); | |
return __encode_result(::std::move(__raw_result.input), ::std::move(__raw_result.output), __state, | |
__raw_result.error_code, __raw_result.handled_errors); | |
} | |
virtual __validate_decodable_as_result __validate_decodable_as_one( | |
_DecodeCodeUnits __input, decode_state& __state) const override { | |
__real_decode_state& __actual_state = this->_M_get_state(__state); | |
auto& __encoding = this->__base_t::__get_value(); | |
if constexpr (__txt_detail::__is_detected_v< | |
__txt_detail::__detect_adl_text_validate_decodable_as_one, _Encoding, | |
_DecodeCodePoints, __real_decode_state>) { | |
auto __raw_result | |
= text_validate_decodable_as_one(__encoding, ::std::move(__input), __actual_state); | |
return __validate_decodable_as_result( | |
::std::move(__raw_result.input), __raw_result.valid, __state); | |
} | |
else if constexpr (__txt_detail::__is_detected_v< | |
__txt_detail::__detect_adl_internal_text_validate_decodable_as_one, | |
_Encoding, _DecodeCodePoints, __real_decode_state>) { | |
auto __raw_result | |
= __text_validate_decodable_as_one(__encoding, ::std::move(__input), __actual_state); | |
return __validate_decodable_as_result( | |
::std::move(__raw_result.input), __raw_result.valid, __state); | |
} | |
else { | |
__real_encode_state __encode_state = make_encode_state(__encoding); | |
auto __raw_result = __txt_detail::__basic_validate_decodable_as_one( | |
::std::move(__input), __encoding, __actual_state, __encode_state); | |
return __validate_decodable_as_result( | |
::std::move(__raw_result.input), __raw_result.valid, __state); | |
} | |
} | |
virtual __validate_encodable_as_result __validate_encodable_as_one( | |
_EncodeCodePoints __input, encode_state& __state) const override { | |
__real_encode_state& __actual_state = this->_M_get_state(__state); | |
auto& __encoding = this->__base_t::__get_value(); | |
if constexpr (__txt_detail::__is_detected_v< | |
__txt_detail::__detect_adl_text_validate_encodable_as_one, _Encoding, | |
_EncodeCodePoints, __real_encode_state>) { | |
auto __raw_result | |
= text_validate_encodable_as_one(__encoding, ::std::move(__input), __actual_state); | |
return __validate_encodable_as_result( | |
::std::move(__raw_result.input), __raw_result.valid, __state); | |
} | |
else if constexpr (__txt_detail::__is_detected_v< | |
__txt_detail::__detect_adl_internal_text_validate_encodable_as_one, | |
_Encoding, _EncodeCodePoints, __real_encode_state>) { | |
auto __raw_result | |
= __text_validate_encodable_as_one(__encoding, ::std::move(__input), __actual_state); | |
return __validate_encodable_as_result( | |
::std::move(__raw_result.input), __raw_result.valid, __state); | |
} | |
else { | |
__real_decode_state __decode_state = make_decode_state(__encoding); | |
auto __raw_result = __txt_detail::__basic_validate_encodable_as_one( | |
::std::move(__input), __encoding, __actual_state, __decode_state); | |
return __validate_encodable_as_result( | |
::std::move(__raw_result.input), __raw_result.valid, __state); | |
} | |
} | |
virtual __count_decodable_result __count_decodable_one(_DecodeCodeUnits __input, | |
__count_decodable_error_handler __error_handler, decode_state& __state) const override { | |
__real_decode_state& __actual_state = this->_M_get_state(__state); | |
__txt_detail::__pass_through_handler __pass_handler; | |
auto& __encoding = this->__base_t::__get_value(); | |
if constexpr (__txt_detail::__is_detected_v< | |
__txt_detail::__detect_adl_internal_text_count_decodable_one, _Encoding, | |
_DecodeCodeUnits, __txt_detail::__pass_through_handler, __real_decode_state>) { | |
auto __raw_result = text_count_decodable_one( | |
__encoding, ::std::move(__input), __pass_handler, __actual_state); | |
return __count_decodable_result(::std::move(__raw_result.input), __raw_result.count, __state, | |
__raw_result.error_code, __raw_result.handled_errors); | |
} | |
else if constexpr (__txt_detail::__is_detected_v< | |
__txt_detail::__detect_adl_internal_text_count_decodable_one, _Encoding, | |
_DecodeCodeUnits, __txt_detail::__pass_through_handler, | |
__real_decode_state>) { | |
auto __raw_result = __text_count_decodable_one( | |
__encoding, ::std::move(__input), __pass_handler, __actual_state); | |
return __count_decodable_result(::std::move(__raw_result.input), __raw_result.count, __state, | |
__raw_result.error_code, __raw_result.handled_errors); | |
} | |
else { | |
auto __raw_result = __txt_detail::__basic_count_decodable_one( | |
::std::move(__input), __encoding, __pass_handler, __actual_state); | |
return __count_decodable_result(::std::move(__raw_result.input), __raw_result.count, __state, | |
__raw_result.error_code, __raw_result.handled_errors); | |
} | |
} | |
virtual __count_encodable_result __count_encodable_one(_EncodeCodePoints __input, | |
__count_encodable_error_handler __error_handler, encode_state& __state) const override { | |
__real_encode_state& __actual_state = this->_M_get_state(__state); | |
__txt_detail::__pass_through_handler __pass_handler; | |
auto& __encoding = this->__base_t::__get_value(); | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_text_count_encodable_one, | |
_Encoding, _EncodeCodePoints, __txt_detail::__pass_through_handler, | |
__real_encode_state>) { | |
auto __raw_result = text_count_encodable_one( | |
__encoding, ::std::move(__input), __pass_handler, __actual_state); | |
return __count_encodable_result(::std::move(__raw_result.input), __raw_result.count, __state, | |
__raw_result.error_code, __raw_result.handled_errors); | |
} | |
else if constexpr (__txt_detail::__is_detected_v< | |
__txt_detail::__detect_adl_internal_text_count_encodable_one, _Encoding, | |
_EncodeCodePoints, __txt_detail::__pass_through_handler, | |
__real_encode_state>) { | |
auto __raw_result = __text_count_encodable_one( | |
__encoding, ::std::move(__input), __pass_handler, __actual_state); | |
return __count_encodable_result(::std::move(__raw_result.input), __raw_result.count, __state, | |
__raw_result.error_code, __raw_result.handled_errors); | |
} | |
else { | |
auto __raw_result = __txt_detail::__basic_count_encodable_one( | |
::std::move(__input), __encoding, __pass_handler, __actual_state); | |
return __count_encodable_result(::std::move(__raw_result.input), __raw_result.count, __state); | |
} | |
} | |
// modifiers: bulk | |
virtual __decode_result __decode(_DecodeCodeUnits __input, _DecodeCodePoints __output, | |
__decode_error_handler __error_handler, decode_state& __state) const override { | |
__real_decode_state& __actual_state = this->_M_get_state(__state); | |
__txt_detail::__pass_through_handler __pass_handler; | |
auto __raw_result = ::ztd::text::decode_into(::std::move(__input), this->__base_t::__get_value(), | |
::std::move(__output), __pass_handler, __actual_state); | |
return __decode_result(::std::move(__raw_result.input), ::std::move(__raw_result.output), __state, | |
__raw_result.error_code, __raw_result.handled_errors); | |
} | |
virtual __encode_result __encode(_EncodeCodePoints __input, _EncodeCodeUnits __output, | |
__encode_error_handler __error_handler, encode_state& __state) const override { | |
__real_encode_state& __actual_state = this->_M_get_state(__state); | |
__txt_detail::__pass_through_handler __pass_handler; | |
auto __raw_result = ::ztd::text::encode_into(::std::move(__input), this->__base_t::__get_value(), | |
::std::move(__output), __pass_handler, __actual_state); | |
return __encode_result(::std::move(__raw_result.input), ::std::move(__raw_result.output), __state, | |
__raw_result.error_code, __raw_result.handled_errors); | |
} | |
virtual __validate_decodable_as_result __validate_decodable_as( | |
_DecodeCodeUnits __input, decode_state& __state) const override { | |
__real_decode_state& __actual_state = this->_M_get_state(__state); | |
auto __raw_result = ::ztd::text::validate_decodable_as( | |
::std::move(__input), this->__base_t::__get_value(), __actual_state); | |
return __validate_decodable_as_result(::std::move(__raw_result.input), __raw_result.valid, __state); | |
} | |
virtual __validate_encodable_as_result __validate_encodable_as( | |
_EncodeCodePoints __input, encode_state& __state) const override { | |
__real_encode_state& __actual_state = this->_M_get_state(__state); | |
auto __raw_result = ::ztd::text::validate_encodable_as( | |
::std::move(__input), this->__base_t::__get_value(), __actual_state); | |
return __validate_encodable_as_result(::std::move(__raw_result.input), __raw_result.valid, __state); | |
} | |
virtual __count_decodable_result __count_decodable(_DecodeCodeUnits __input, | |
__count_decodable_error_handler __error_handler, decode_state& __state) const override { | |
__real_decode_state& __actual_state = this->_M_get_state(__state); | |
auto& __encoding = this->__base_t::__get_value(); | |
__txt_detail::__pass_through_handler __pass_handler; | |
auto __raw_result = ::ztd::text::count_decodable( | |
::std::move(__input), __encoding, __pass_handler, __actual_state); | |
return __count_decodable_result(::std::move(__raw_result.input), __raw_result.count, __state, | |
__raw_result.error_code, __raw_result.handled_errors); | |
} | |
virtual __count_encodable_result __count_encodable(_EncodeCodePoints __input, | |
__count_encodable_error_handler __error_handler, encode_state& __state) const override { | |
__real_encode_state& __actual_state = this->_M_get_state(__state); | |
__txt_detail::__pass_through_handler __pass_handler; | |
auto __raw_result = ::ztd::text::count_encodable( | |
::std::move(__input), this->__base_t::__get_value(), __pass_handler, __actual_state); | |
return __count_encodable_result(::std::move(__raw_result.input), __raw_result.count, __state, | |
__raw_result.error_code, __raw_result.handled_errors); | |
} | |
virtual ::std::unique_ptr<__erased_state> __create_encode_state() const override { | |
auto& __encoding = this->__base_t::__get_value(); | |
return ::std::make_unique<__typed_state<__real_encode_state>>(make_encode_state(__encoding)); | |
} | |
virtual ::std::unique_ptr<__erased_state> __create_decode_state() const override { | |
auto& __encoding = this->__base_t::__get_value(); | |
return ::std::make_unique<__typed_state<__real_decode_state>>(make_decode_state(__encoding)); | |
} | |
private: | |
__real_encode_state& _M_get_state(encode_state& __state) const { | |
__erased_state* __erased_ptr = __state._M_get_erased_state(); | |
__typed_state<__real_encode_state>* __typed_ptr | |
= static_cast<__typed_state<__real_encode_state>*>(__erased_ptr); | |
return __typed_ptr->__get_value(); | |
} | |
__real_decode_state& _M_get_state(decode_state& __state) const { | |
__erased_state* __erased_ptr = __state._M_get_erased_state(); | |
__typed_state<__real_decode_state>* __typed_ptr | |
= static_cast<__typed_state<__real_decode_state>*>(__erased_ptr); | |
return __typed_ptr->__get_value(); | |
} | |
}; | |
::std::unique_ptr<__erased> _M_storage; | |
public: | |
////// | |
/// @brief Cannot default-construct a ztd::text::any_encoding_with object. | |
/// | |
////// | |
any_encoding_with() = delete; | |
////// | |
/// @brief Constructs a ztd::text::any_encoding_with with the encoding object and any additional arguments. | |
/// | |
/// @tparam _Encoding The Encoding specified by the first argument. | |
/// | |
/// @param[in] __encoding The encoding object that informs the ztd::text::any_encoding_with what encoding | |
/// object to store. | |
/// @param[in] __args Any additional arguments used to construct the encoding in the erased storage. | |
////// | |
template <typename _Encoding, typename... _Args, | |
::std::enable_if_t< | |
!::std::is_same_v<_Encoding, | |
any_encoding_with> && !__txt_detail::__is_specialization_of_v<__txt_detail::__remove_cvref_t<_Encoding>, ::std::in_place_type_t>>* = nullptr> | |
any_encoding_with(_Encoding&& __encoding, _Args&&... __args) | |
: any_encoding_with(::std::in_place_type<__txt_detail::__remove_cvref_t<_Encoding>>, | |
::std::forward<_Encoding>(__encoding), ::std::forward<_Args>(__args)...) { | |
} | |
////// | |
/// @brief Constructs a ztd::text::any_encoding_with with the encoding type specified in the @p __tag | |
/// argument. | |
/// | |
/// @tparam _Encoding The Encoding specified by the @p __tag argument. | |
/// | |
/// @param[in] __tag The type marker that informs the ztd::text::any_encoding_with what encoding object to | |
/// store. | |
/// @param[in] __args Any additional arguments used to construct the encoding in the erased storage. | |
////// | |
template <typename _Encoding, typename... _Args> | |
any_encoding_with(::std::in_place_type_t<_Encoding> __tag, _Args&&... __args) | |
: _M_storage(::std::make_unique<__typed<_Encoding>>(::std::forward<_Args>(__args)...)) { | |
(void)__tag; | |
} | |
////// | |
/// @brief Cannot copy-construct a ztd::text::any_encoding_with object. | |
/// | |
////// | |
any_encoding_with(const any_encoding_with&) = delete; | |
////// | |
/// @brief Cannot copy-assign a ztd::text::any_encoding_with object. | |
/// | |
////// | |
any_encoding_with& operator=(const any_encoding_with&) = delete; | |
////// | |
/// @brief Move-constructs a ztd::text::any_encoding_with from the provided r-value reference. | |
/// | |
/// @remarks This leaves the passed-in r-value reference without an encoding object. Calling any function on a | |
/// moved-fron ztd::text::any_encoding_with, except for destruction, is a violation and invokes Undefined | |
/// Behavior (generally, a crash). | |
////// | |
any_encoding_with(any_encoding_with&&) = default; | |
////// | |
/// @brief Move-assigns a ztd::text::any_encoding_with from the provided r-value reference. | |
/// | |
/// @remarks This leaves the passed-in r-value reference without an encoding object. Calling any function on a | |
/// moved-fron ztd::text::any_encoding_with, except for destruction, is a violation and invokes Undefined | |
/// Behavior (generally, a crash). | |
////// | |
any_encoding_with& operator=(any_encoding_with&&) = default; | |
////// | |
/// @brief Retrieves the replacement code points for when conversions fail and ztd::text::replacement_handler | |
/// (or equivalent) needs to make a substitution. | |
/// | |
/// @return A @c std::optional of @c ztd::text::span of @c const @c code_point\ s. The returned @c | |
/// std::optional value is engaged (has a value) if the stored encoding has a valid @c replacement_code_points | |
/// function and it can be called. If it does not, then the library checks to see if the @c | |
/// maybe_replacement_code_points function exists, and returns the @c std::optional from that type directly. | |
/// If neither are present, an unengaged @c std::optional is returned. | |
////// | |
::std::optional<::ztd::text::span<const code_point>> maybe_replacement_code_points() const noexcept { | |
return this->_M_storage->__maybe_replacement_code_points(); | |
} | |
////// | |
/// @brief Retrieves the replacement code units for when conversions fail and ztd::text::replacement_handler | |
/// (or equivalent) needs to make a substitution. | |
/// | |
/// @return A @c std::optional of @c ztd::text::span of @c const @c code_unit s. The returned @c std::optional | |
/// value is engaged (has a value) if the stored encoding has a valid @c replacement_code_units function and | |
/// it can be called. If it does not, then the library checks to see if the @c maybe_replacement_code_units | |
/// function exists, and returns the @c std::optional from that type directly. If neither are present, an | |
/// unengaged @c std::optional is returned. | |
////// | |
::std::optional<::ztd::text::span<const code_unit>> maybe_replacement_code_units() const noexcept { | |
return this->_M_storage->__maybe_replacement_code_units(); | |
} | |
////// | |
/// @brief Returns whether or not the encoding stored in this ztd::text::any_encoding_with is a Unicode | |
/// encoding. | |
/// | |
/// @remarks This can be useful to know, in advance, whether or not there is a chance for lossy behavior. Even | |
/// if, at compile time, various functions will demand you use an error handler, this runtime property can | |
/// help you get a decent idea of just how bad and lossy this conversion might be compared to normal UTF | |
/// conversion formats. | |
////// | |
bool contains_unicode_encoding() const noexcept { | |
return this->_M_storage->__contains_unicode_encoding(); | |
} | |
////// | |
/// @brief Decodes a single complete unit of information as code points and produces a result with the | |
/// input and output ranges moved past what was successfully read and written; or, produces an error and | |
/// returns the input and output ranges untouched. | |
/// | |
/// @param[in] __input The input view to read code uunits from. | |
/// @param[in] __output The output view to write code points into. | |
/// @param[in] __error_handler The error handler to invoke if encoding fails. | |
/// @param[in, out] __state The necessary state information. For this encoding, the state is empty and means | |
/// very little. | |
/// | |
/// @returns A ztd::text::decode_result object that contains the reconstructed input range, | |
/// reconstructed output range, error handler, and a reference to the passed-in state. | |
/// | |
/// @remarks To the best ability of the implementation, the iterators will be returned untouched (e.g., | |
/// the input models at least a view and a forward_range). If it is not possible, returned ranges may be | |
/// incremented even if an error occurs due to the semantics of any view that models an input_range. | |
////// | |
__decode_result decode_one(_DecodeCodeUnits __input, _DecodeCodePoints __output, | |
__decode_error_handler __error_handler, decode_state& __state) const { | |
return this->_M_storage->__decode_one( | |
::std::move(__input), ::std::move(__output), ::std::move(__error_handler), __state); | |
} | |
////// | |
/// @brief Encodes a single complete unit of information as code units and produces a result with the | |
/// input and output ranges moved past what was successfully read and written; or, produces an error and | |
/// returns the input and output ranges untouched. | |
/// | |
/// @param[in] __input The input view to read code points from. | |
/// @param[in] __output The output view to write code units into. | |
/// @param[in] __error_handler The error handler to invoke if encoding fails. | |
/// @param[in, out] __state The necessary state information. For this encoding, the state is empty and means | |
/// very little. | |
/// | |
/// @returns A ztd::text::encode_result object that contains the reconstructed input range, | |
/// reconstructed output range, error handler, and a reference to the passed-in state. | |
/// | |
/// @remarks To the best ability of the implementation, the iterators will be returned untouched (e.g., | |
/// the input models at least a view and a forward_range). If it is not possible, returned ranges may be | |
/// incremented even if an error occurs due to the semantics of any view that models an input_range. | |
////// | |
__encode_result encode_one(_EncodeCodePoints __input, _EncodeCodeUnits __output, | |
__encode_error_handler __error_handler, encode_state& __state) const { | |
return this->_M_storage->__encode_one( | |
::std::move(__input), ::std::move(__output), ::std::move(__error_handler), __state); | |
} | |
private: | |
__validate_decodable_as_result __validate_decodable_as_one( | |
_DecodeCodeUnits __input, decode_state& __state) const { | |
return this->_M_storage->__validate_decodable_as_one(::std::move(__input), __state); | |
} | |
__validate_encodable_as_result __validate_encodable_as_one( | |
_EncodeCodePoints __input, encode_state& __state) const { | |
return this->_M_storage->__validate_encodable_as_one(::std::move(__input), __state); | |
} | |
__count_encodable_result __count_encodable_one(_EncodeCodePoints __input, | |
__count_encodable_error_handler __error_handler, encode_state& __state) const { | |
return this->_M_storage->__count_encodable_one( | |
::std::move(__input), ::std::move(__error_handler), __state); | |
} | |
__count_decodable_result __count_decodable_one( | |
_DecodeCodeUnits __input, __encode_error_handler __error_handler, decode_state& __state) const { | |
return this->_M_storage->__count_decodable_one( | |
::std::move(__input), ::std::move(__error_handler), __state); | |
} | |
__decode_result __decode(_DecodeCodeUnits __input, _DecodeCodePoints __output, | |
__decode_error_handler __error_handler, decode_state& __state) const { | |
return this->_M_storage->__decode( | |
::std::move(__input), ::std::move(__output), ::std::move(__error_handler), __state); | |
} | |
__encode_result __encode(_EncodeCodePoints __input, _EncodeCodeUnits __output, | |
__encode_error_handler __error_handler, encode_state& __state) const { | |
return this->_M_storage->__encode( | |
::std::move(__input), ::std::move(__output), ::std::move(__error_handler), __state); | |
} | |
__validate_decodable_as_result __validate_decodable_as( | |
_DecodeCodeUnits __input, __decode_error_handler __error_handler, decode_state& __state) const { | |
return this->_M_storage->__validate_decodable_as( | |
::std::move(__input), ::std::move(__error_handler), __state); | |
} | |
__validate_encodable_as_result __validate_encodable_as( | |
_EncodeCodePoints __input, __encode_error_handler __error_handler, encode_state& __state) const { | |
return this->_M_storage->__validate_encodable_as( | |
::std::move(__input), ::std::move(__error_handler), __state); | |
} | |
__count_encodable_result __count_encodable( | |
_EncodeCodePoints __input, __decode_error_handler __error_handler, encode_state& __state) const { | |
return this->_M_storage->__count_encodable(::std::move(__input), ::std::move(__error_handler), __state); | |
} | |
__count_decodable_result __count_decodable( | |
_DecodeCodeUnits __input, __encode_error_handler __error_handler, decode_state& __state) const { | |
return this->_M_storage->__count_decodable(::std::move(__input), ::std::move(__error_handler), __state); | |
} | |
////// | |
/// @internal | |
/// | |
/// @brief Extension point hooks for the implementation-side only. | |
////// | |
template <typename _Output, typename _ErrorHandler, typename _State> | |
constexpr friend auto __text_decode(tag<any_encoding_with>, _DecodeCodeUnits __input, | |
__txt_detail::__type_identity_t<const any_encoding_with&> __encoding, _Output&& __output, | |
_ErrorHandler&& __error_handler, _State& __state) { | |
return __encoding.__decode(::std::move(__input), ::std::forward<_Output>(__output), | |
::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
////// | |
/// @internal | |
/// | |
/// @brief Extension point hooks for the implementation-side only. | |
////// | |
template <typename _Output, typename _ErrorHandler, typename _State> | |
constexpr friend auto __text_encode(tag<any_encoding_with>, _EncodeCodePoints __input, | |
__txt_detail::__type_identity_t<const any_encoding_with&> __encoding, _Output&& __output, | |
_ErrorHandler&& __error_handler, _State& __state) { | |
return __encoding.__encode(::std::move(__input), ::std::forward<_Output>(__output), | |
::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
////// | |
/// @internal | |
/// | |
/// @brief Extension point hooks for the implementation-side only. | |
////// | |
template <typename _EncodeState> | |
constexpr friend auto __text_validate_encodable_as_one(tag<any_encoding_with>, _DecodeCodeUnits __input, | |
__txt_detail::__type_identity_t<const any_encoding_with&> __encoding, _EncodeState& __state) { | |
return __encoding.__validate_encodable_as_one(::std::move(__input), __state); | |
} | |
////// | |
/// @internal | |
/// | |
/// @brief Extension point hooks for the implementation-side only. | |
////// | |
template <typename _DecodeState> | |
constexpr friend auto __text_validate_decodable_as_one(tag<any_encoding_with>, _EncodeCodePoints __input, | |
__txt_detail::__type_identity_t<const any_encoding_with&> __encoding, _DecodeState& __state) { | |
return __encoding.__validate_decodable_as_one(::std::move(__input), __state); | |
} | |
////// | |
/// @internal | |
/// | |
/// @brief Extension point hooks for the implementation-side only. | |
////// | |
template <typename _EncodeState> | |
constexpr friend auto __text_validate_encodable_as(tag<any_encoding_with>, _DecodeCodeUnits __input, | |
__txt_detail::__type_identity_t<const any_encoding_with&> __encoding, _EncodeState& __state) { | |
return __encoding.__validate_encodable_as(::std::move(__input), __state); | |
} | |
////// | |
/// @internal | |
/// | |
/// @brief Extension point hooks for the implementation-side only. | |
////// | |
template <typename _Input, typename _DecodeState> | |
constexpr friend auto __text_validate_decodable_as(tag<any_encoding_with>, _EncodeCodePoints __input, | |
__txt_detail::__type_identity_t<const any_encoding_with&> __encoding, _DecodeState& __state) { | |
return __encoding.__validate_decodable_as(::std::move(__input), __state); | |
} | |
////// | |
/// @internal | |
/// | |
/// @brief Extension point hooks for the implementation-side only. | |
////// | |
template <typename _ErrorHandler, typename _State> | |
constexpr friend auto __text_count_encodable_one(tag<any_encoding_with>, _EncodeCodePoints __input, | |
__txt_detail::__type_identity_t<const any_encoding_with&> __encoding, _ErrorHandler&& __error_handler, | |
_State& __state) { | |
return __encoding.__count_encodable_one( | |
::std::move(__input), ::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
////// | |
/// @internal | |
/// | |
/// @brief Extension point hooks for the implementation-side only. | |
////// | |
template <typename _ErrorHandler, typename _State> | |
constexpr friend auto __text_count_decodable_one(tag<any_encoding_with>, _DecodeCodeUnits __input, | |
__txt_detail::__type_identity_t<const any_encoding_with&> __encoding, _ErrorHandler&& __error_handler, | |
_State& __state) { | |
return __encoding.__count_decodable_one( | |
::std::move(__input), ::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
////// | |
/// @internal | |
/// | |
/// @brief Extension point hooks for the implementation-side only. | |
////// | |
template <typename _ErrorHandler, typename _State> | |
constexpr friend auto __text_count_encodable(tag<any_encoding_with>, _EncodeCodePoints __input, | |
__txt_detail::__type_identity_t<const any_encoding_with&> __encoding, _ErrorHandler&& __error_handler, | |
_State& __state) { | |
return __encoding.__count_encodable(::std::move(__input), ::std::move(__error_handler), __state); | |
} | |
////// | |
/// @internal | |
/// | |
/// @brief Extension point hooks for the implementation-side only. | |
////// | |
template <typename _ErrorHandler, typename _State> | |
constexpr friend auto __text_count_decodable(tag<any_encoding_with>, _DecodeCodeUnits __input, | |
__txt_detail::__type_identity_t<const any_encoding_with&> __encoding, _ErrorHandler&& __error_handler, | |
_State& __state) { | |
return __encoding.__count_decodable( | |
::std::move(__input), ::std::forward<_ErrorHandler>(__error_handler), __state); | |
} | |
}; | |
////// | |
/// @brief A type-erased encoding that uses the specified code unit, code point, and input/output ranges for the | |
/// various operations. | |
////// | |
template <typename _EncodeCodeUnit, typename _EncodeCodePoint = const unicode_code_point, | |
typename _DecodeCodeUnit = ::std::add_const_t<_EncodeCodeUnit>, | |
typename _DecodeCodePoint = ::std::remove_const_t<_EncodeCodePoint>, | |
::std::size_t _MaxCodeUnits = __txt_detail::__default_max_code_units_any_encoding, | |
::std::size_t _MaxCodePoints = __txt_detail::__default_max_code_points_any_encoding> | |
using any_encoding_of = any_encoding_with<::ztd::text::span<_EncodeCodeUnit>, ::ztd::text::span<_EncodeCodePoint>, | |
::ztd::text::span<_DecodeCodeUnit>, ::ztd::text::span<_DecodeCodePoint>, _MaxCodeUnits, _MaxCodePoints>; | |
////// | |
/// @brief An encoding type that wraps up other encodings to specifically traffic in the given @p _Byte type | |
/// provided, which is typically set to @c std::byte . | |
/// | |
/// @tparam _Byte The byte type to use. Typically, this is either <tt>unsigned char</tt> or @c std::byte . | |
/// | |
/// @remarks This type traffics solely in @c std::span s, which for most people is fine. Others may want to | |
/// interface with different iterator types (e.g., from a custom Rope implementation or other). For those, one must | |
/// first create ranges that can operate with those iterators, then use them themselves. (It's not an ideal process | |
/// at the moment, and we are looking to make this experience better.) It is recommended to use the provided | |
/// ztd::text::any_encoding type definition instead of accessing this directly, unless you have a reason for using | |
/// a different byte type (e.g., interfacing with legacy APIs). | |
////// | |
template <typename _Byte, typename _CodePoint = unicode_code_point> | |
class any_byte_encoding : public any_encoding_of<_Byte, const _CodePoint, const _Byte, _CodePoint> { | |
private: | |
using __base_t = any_encoding_of<_Byte, const _CodePoint, const _Byte, _CodePoint>; | |
public: | |
////// | |
/// @brief Cannot default-construct a ztd::text::any_byte_encoding object. | |
/// | |
////// | |
any_byte_encoding() = delete; | |
////// | |
/// @brief Constructs a ztd::text::any_byte_encoding with the encoding object and any additional arguments. | |
/// | |
/// @param[in] __encoding The encoding object that informs the ztd::text::any_byte_encoding what encoding | |
/// object to store. | |
/// @param[in] __args Any additional arguments used to construct the encoding in the erased storage. | |
/// | |
/// @remarks If the provided encoding does not have a byte code_unit type, it is wrapped in an | |
/// ztd::text::encoding_scheme first. | |
////// | |
template <typename _Encoding, typename... _Args, | |
::std::enable_if_t< | |
!::std::is_same_v<_Encoding, | |
any_byte_encoding> && !::std::is_same_v<_Encoding, __base_t> && !__txt_detail::__is_specialization_of_v<__txt_detail::__remove_cvref_t<_Encoding>, ::std::in_place_type_t>>* = nullptr> | |
any_byte_encoding(_Encoding&& __encoding, _Args&&... __args) | |
: any_byte_encoding(::std::in_place_type<__txt_detail::__remove_cvref_t<_Encoding>>, | |
::std::forward<_Encoding>(__encoding), ::std::forward<_Args>(__args)...) { | |
} | |
////// | |
/// @brief Constructs a ztd::text::any_byte_encoding with the encoding object and any additional arguments. | |
/// | |
/// @tparam _Encoding The Encoding specified by the tag argument. | |
/// | |
/// @param[in] __args Any additional arguments used to construct the encoding in the erased storage. | |
/// | |
/// @remarks If the provided encoding does not have a byte code_unit type, it is wrapped in an | |
/// ztd::text::encoding_scheme first. | |
////// | |
template <typename _Encoding, typename... _Args, | |
::std::enable_if_t< | |
!::std::is_same_v<_Byte, code_unit_t<__txt_detail::__remove_cvref_t<_Encoding>>>>* = nullptr> | |
any_byte_encoding(::std::in_place_type_t<_Encoding>, _Args&&... __args) | |
: __base_t(::std::in_place_type_t< | |
encoding_scheme<__txt_detail::__remove_cvref_t<_Encoding>, endian::native, _Byte>> {}, | |
::std::forward<_Args>(__args)...) { | |
} | |
////// | |
/// @brief Constructs a ztd::text::any_byte_encoding with the encoding object and any additional arguments. | |
/// | |
/// @tparam _Encoding The Encoding specified by the tag argument. | |
/// | |
/// @param[in] __tag A tag containing the encoding type. | |
/// @param[in] __args Any additional arguments used to construct the encoding in the erased storage. | |
/// | |
/// @remarks If the provided encoding does not have a byte code_unit type, it is wrapped in an | |
/// ztd::text::encoding_scheme first. | |
////// | |
template <typename _Encoding, typename... _Args, | |
::std::enable_if_t< | |
::std::is_same_v<_Byte, code_unit_t<__txt_detail::__remove_cvref_t<_Encoding>>>>* = nullptr> | |
any_byte_encoding(::std::in_place_type_t<_Encoding> __tag, _Args&&... __args) | |
: __base_t(::std::move(__tag), ::std::forward<_Args>(__args)...) { | |
} | |
////// | |
/// @brief Cannot copy-construct a ztd::text::any_byte_encoding object. | |
/// | |
////// | |
any_byte_encoding(const any_byte_encoding&) = delete; | |
////// | |
/// @brief Cannot copy-assign a ztd::text::any_byte_encoding object. | |
/// | |
////// | |
any_byte_encoding& operator=(const any_byte_encoding&) = delete; | |
////// | |
/// @brief Move-constructs a ztd::text::any_byte_encoding from the provided r-value reference. | |
/// | |
/// @remarks This leaves the passed-in r-value reference without an encoding object. Calling any function on a | |
/// moved-fron ztd::text::any_byte_encoding, except for destruction, is a violation and invokes Undefined | |
/// Behavior (generally, a crash). | |
////// | |
any_byte_encoding(any_byte_encoding&&) = default; | |
////// | |
/// @brief Move-assigns a ztd::text::any_byte_encoding from the provided r-value reference. | |
/// | |
/// @remarks This leaves the passed-in r-value reference without an encoding object. Calling any function on a | |
/// moved-fron ztd::text::any_byte_encoding, except for destruction, is a violation and invokes Undefined | |
/// Behavior (generally, a crash). | |
////// | |
any_byte_encoding& operator=(any_byte_encoding&&) = default; | |
}; | |
////// | |
/// @brief The canonical erased encoding type which uses a @c std::byte as its code unit type and an @c | |
/// unicode_code_point as its code point type, with spans for input and output operations. | |
/// | |
/// @remarks If the input encoding does not match @c std::byte, it will be first wrapped in a | |
/// ztd::text::encoding_scheme first. | |
////// | |
using any_encoding = any_byte_encoding<::std::byte>; | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/any_encoding.hpp | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/encoding.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/transcode.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/transcode_extension_points.hpp | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
// These optimizations can only be applied when the encodings are identical AND both | |
// is_ignorable_error_handler_v<FromErrorHandler> and is_ignorable_error_handler_v<ToErrorHandler> are true. In the | |
// other case, at the very least a decode needs to be performed. If it's successful, THEN we memcpy the used bits | |
// from the input directly to the output. This relies on the operation being symmetric for decode and encode, | |
// which is not EXACTLY a requirement, but it's worth doing anyhow. | |
#if 0 | |
template <typename _Input, typename _Output, typename _FromEncoding, typename _ToEncoding, | |
typename _FromErrorHandler, typename _ToErrorHandler, | |
::std::enable_if_t<::std::is_same_v<__txt_detail::__remove_cvref_t<_FromEncoding>, | |
__txt_detail::__remove_cvref_t<_ToEncoding>>>* = nullptr> | |
constexpr auto __text_transcode_one( | |
tag<__txt_detail::__remove_cvref_t<_FromEncoding>, __txt_detail::__remove_cvref_t<_ToEncoding>>, | |
_Input&& __input, _FromEncoding&& __from_encoding, _Output&& __output, _ToEncoding&& __to_encoding, | |
_FromErrorHandler&& __from_error_handler, _ToErrorHandler&& __to_error_handler, | |
decode_state_t<__txt_detail::__remove_cvref_t<_FromEncoding>>& __from_state, | |
encode_state_t<__txt_detail::__remove_cvref_t<_ToEncoding>>& __to_state) { | |
using _FromState = decode_state_t<__txt_detail::__remove_cvref_t<_FromEncoding>>; | |
using _ToState = encode_state_t<__txt_detail::__remove_cvref_t<_ToEncoding>>; | |
__txt_detail::__copy(__txt_detail::__adl::__adl_begin(__input), __txt_detail::__adl::__adl_end(__input), | |
__txt_detail::__adl::__adl_begin(__output), __txt_detail::__adl::__adl_end(__output)); | |
return transcode_result<_Input, _Output, _FromState, _ToState>(::std::forward<_Input>(__input), | |
::std::forward<_Output>(__output), __from_state, __to_state, encoding_error::ok); | |
} | |
template <typename _Input, typename _Output, typename _FromEncoding, typename _ToEncoding, | |
typename _FromErrorHandler, typename _ToErrorHandler, | |
::std::enable_if_t<::std::is_same_v<__txt_detail::__remove_cvref_t<_FromEncoding>, | |
__txt_detail::__remove_cvref_t<_ToEncoding>>>* = nullptr> | |
constexpr auto __text_transcode( | |
tag<__txt_detail::__remove_cvref_t<_FromEncoding>, __txt_detail::__remove_cvref_t<_ToEncoding>>, | |
_Input&& __input, _FromEncoding&& __from_encoding, _Output&& __output, _ToEncoding&& __to_encoding, | |
_FromErrorHandler&& __from_error_handler, _ToErrorHandler&& __to_error_handler, | |
decode_state_t<__txt_detail::__remove_cvref_t<_FromEncoding>>& __from_state, | |
encode_state_t<__txt_detail::__remove_cvref_t<_ToEncoding>>& __to_state) { | |
using _FromState = decode_state_t<__txt_detail::__remove_cvref_t<_FromEncoding>>; | |
using _ToState = encode_state_t<__txt_detail::__remove_cvref_t<_ToEncoding>>; | |
__txt_detail::__copy(__txt_detail::__adl::__adl_begin(__input), __txt_detail::__adl::__adl_end(__input), | |
__txt_detail::__adl::__adl_begin(__output), __txt_detail::__adl::__adl_end(__output)); | |
return transcode_result<_Input, _Output, _FromState, _ToState>(::std::forward<_Input>(__input), | |
::std::forward<_Output>(__output), __from_state, __to_state, encoding_error::ok); | |
} | |
#endif | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/transcode_extension_points.hpp | |
#include <string> | |
#include <vector> | |
#include <string_view> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_transcode ztd::text::transcode[_into] | |
/// | |
/// @brief These functions convert from a view of input code units into a view of output code units (typically, | |
/// through an intermediary code point type that is similar between the two) using either the inferred or specified | |
/// encodings. If no error handler is provided, the equivalent of the ztd::text::default_handler is used by | |
/// default, but it is marked as careless. If no associated state is provided for either the "to" or "from" | |
/// encodings, one will be created with automatic storage duration (as a "stack" variable) for the provided | |
/// encoding. | |
/// @{ | |
////// | |
////// | |
/// @brief Converts the code units of the given input view through the from encoding to code units of the to | |
/// encoding into the output view. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce intermediate code points. | |
/// @param[in] __from_encoding The encoding that will be used to decode the input's code units into | |
/// intermediate code points. | |
/// @param[in] __output An output_view to write code units to as the result of the encode operation from the | |
/// intermediate code points. | |
/// @param[in] __to_encoding The encoding that will be used to encode the intermediate code points into the | |
/// final code units. | |
/// @param[in] __from_error_handler The error handlers for the from and to encodings, | |
/// respectively. | |
/// @param[in] __to_error_handler The error handlers for the from and to encodings, | |
/// respectively. | |
/// @param[in,out] __from_state A reference to the associated state for the @p __from_encoding 's decode step. | |
/// @param[in,out] __to_state A reference to the associated state for the @p __to_encoding 's encode step. | |
/// | |
/// @result A ztd::text::transcode_result object that contains references to @p __from_state and @p | |
/// __to_state. | |
/// | |
/// @remark This function detects whether or not the ADL extension point @c text_transcode can be called with the | |
/// provided parameters. If so, it will use that ADL extension point over the default implementation. Otherwise, it | |
/// will loop over the two encodings and attempt to transcode by first decoding the input code units to code | |
/// points, then encoding the intermediate code points to the desired, output code units. | |
////// | |
template <typename _Input, typename _Output, typename _FromEncoding, typename _ToEncoding, | |
typename _FromErrorHandler, typename _ToErrorHandler, typename _FromState, typename _ToState> | |
constexpr auto basic_transcode_into(_Input&& __input, _FromEncoding&& __from_encoding, _Output&& __output, | |
_ToEncoding&& __to_encoding, _FromErrorHandler&& __from_error_handler, _ToErrorHandler&& __to_error_handler, | |
_FromState& __from_state, _ToState& __to_state) { | |
using _InitialInput = __txt_detail::__string_view_or_span_or_reconstruct_t<_Input>; | |
using _InitialOutput = __txt_detail::__range_reconstruct_t<_Output>; | |
using _UFromEncoding = __txt_detail::__remove_cvref_t<_FromEncoding>; | |
using _IntermediateCodePoint = code_point_t<_UFromEncoding>; | |
constexpr ::std::size_t _IntermediateCodePointMax = max_code_points_v<_UFromEncoding>; | |
using _IntermediateStorage = _IntermediateCodePoint[_IntermediateCodePointMax]; | |
using _Intermediate = ::ztd::text::span<_IntermediateCodePoint, _IntermediateCodePointMax>; | |
using _Result = decltype(__txt_detail::__basic_transcode_one<__txt_detail::__consume::__no>( | |
::std::declval<_InitialInput>(), __from_encoding, ::std::declval<_InitialOutput>(), __to_encoding, | |
__from_error_handler, __to_error_handler, __from_state, __to_state, ::std::declval<_Intermediate&>())); | |
using _WorkingInput = decltype(::std::declval<_Result>().input); | |
using _WorkingOutput = decltype(::std::declval<_Result>().output); | |
_WorkingInput __working_input( | |
__txt_detail::__string_view_or_span_or_reconstruct(::std::forward<_Input>(__input))); | |
_WorkingOutput __working_output | |
= __txt_detail::__reconstruct(::std::in_place_type<_WorkingOutput>, ::std::forward<_Output>(__output)); | |
_IntermediateStorage __intermediate_storage {}; | |
_Intermediate __intermediate(__intermediate_storage); | |
::std::size_t __handled_errors = 0; | |
for (;;) { | |
auto __transcode_result = __txt_detail::__basic_transcode_one<__txt_detail::__consume::__no>( | |
::std::move(__working_input), __from_encoding, ::std::move(__working_output), __to_encoding, | |
__from_error_handler, __to_error_handler, __from_state, __to_state, __intermediate); | |
if (__transcode_result.error_code != encoding_error::ok) { | |
return _Result(::std::move(__working_input), ::std::move(__working_output), __from_state, | |
__to_state, __transcode_result.error_code, __transcode_result.handled_errors); | |
} | |
__handled_errors += __transcode_result.handled_errors; | |
__working_input = ::std::move(__transcode_result.input); | |
__working_output = ::std::move(__transcode_result.output); | |
if (__txt_detail::__adl::__adl_empty(__working_input)) { | |
break; | |
} | |
} | |
return _Result(::std::move(__working_input), ::std::move(__working_output), __from_state, __to_state, | |
encoding_error::ok, __handled_errors); | |
} | |
////// | |
/// @brief Converts the code units of the given input view through the from encoding to code units of the to | |
/// encoding into the output view. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce intermediate code points. | |
/// @param[in] __from_encoding The encoding that will be used to decode the input's code units into | |
/// intermediate code points. | |
/// @param[in] __output An output_view to write code units to as the result of the encode operation from the | |
/// intermediate code points. | |
/// @param[in] __to_encoding The encoding that will be used to encode the intermediate code points into the | |
/// final code units. | |
/// @param[in] __from_error_handler The error handlers for the from and to encodings, | |
/// respectively. | |
/// @param[in] __to_error_handler The error handlers for the from and to encodings, | |
/// respectively. | |
/// @param[in,out] __from_state A reference to the associated state for the @p __from_encoding 's decode step. | |
/// @param[in,out] __to_state A reference to the associated state for the @p __to_encoding 's encode step. | |
/// | |
/// @result A ztd::text::transcode_result object that contains references to @p __from_state and @p | |
/// __to_state. | |
/// | |
/// @remark This function detects whether or not the ADL extension point @c text_transcode can be called with the | |
/// provided parameters. If so, it will use that ADL extension point over the default implementation. Otherwise, it | |
/// will loop over the two encodings and attempt to transcode by first decoding the input code units to code | |
/// points, then encoding the intermediate code points to the desired, output code units. | |
////// | |
template <typename _Input, typename _Output, typename _FromEncoding, typename _ToEncoding, | |
typename _FromErrorHandler, typename _ToErrorHandler, typename _FromState, typename _ToState> | |
constexpr auto transcode_into(_Input&& __input, _FromEncoding&& __from_encoding, _Output&& __output, | |
_ToEncoding&& __to_encoding, _FromErrorHandler&& __from_error_handler, _ToErrorHandler&& __to_error_handler, | |
_FromState& __from_state, _ToState& __to_state) { | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_text_transcode, _Input, _Output, | |
_FromEncoding, _ToEncoding, _FromErrorHandler, _ToErrorHandler, _FromState, _ToState>) { | |
return text_transcode( | |
tag<__txt_detail::__remove_cvref_t<_FromEncoding>, __txt_detail::__remove_cvref_t<_ToEncoding>> {}, | |
::std::forward<_Input>(__input), ::std::forward<_FromEncoding>(__from_encoding), | |
::std::forward<_Output>(__output), ::std::forward<_ToEncoding>(__to_encoding), | |
::std::forward<_FromErrorHandler>(__from_error_handler), | |
::std::forward<_ToErrorHandler>(__to_error_handler), __from_state, __to_state); | |
} | |
else if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_internal_text_transcode, _Input, | |
_FromEncoding, _Output, _ToEncoding, _FromErrorHandler, _ToErrorHandler, _FromState, | |
_ToState>) { | |
return __text_transcode( | |
tag<__txt_detail::__remove_cvref_t<_FromEncoding>, __txt_detail::__remove_cvref_t<_ToEncoding>> {}, | |
::std::forward<_Input>(__input), ::std::forward<_FromEncoding>(__from_encoding), | |
::std::forward<_Output>(__output), ::std::forward<_ToEncoding>(__to_encoding), | |
::std::forward<_FromErrorHandler>(__from_error_handler), | |
::std::forward<_ToErrorHandler>(__to_error_handler), __from_state, __to_state); | |
} | |
else { | |
return basic_transcode_into(::std::forward<_Input>(__input), | |
::std::forward<_FromEncoding>(__from_encoding), ::std::forward<_Output>(__output), | |
::std::forward<_ToEncoding>(__to_encoding), ::std::forward<_FromErrorHandler>(__from_error_handler), | |
::std::forward<_ToErrorHandler>(__to_error_handler), __from_state, __to_state); | |
} | |
} | |
////// | |
/// @brief Converts the code units of the given input view through the from encoding to code units of the to | |
/// encoding into the output view. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce intermediate code points. | |
/// @param[in] __from_encoding The encoding that will be used to decode the input's code units into | |
/// intermediate code points. | |
/// @param[in] __output An output_view to write code units to as the result of the encode operation from the | |
/// intermediate code points. | |
/// @param[in] __to_encoding The encoding that will be used to encode the intermediate code points into the | |
/// final code units. | |
/// @param[in] __from_error_handler The error handler for the @p __from_encoding 's decode step. | |
/// @param[in] __to_error_handler The error handler for the @p __to_encoding 's encode step. | |
/// @param[in,out] __from_state A reference to the associated state for the @p __from_encoding 's decode step. | |
/// | |
/// @result A ztd::text::stateless_transcode_result object. | |
/// | |
/// @remarks This function calls the base reference, the ztd::text::transcode_into after creating a @c to_state | |
/// from ztd::text::make_encode_state. The result from this function returns a | |
/// ztd::text::stateless_transcode_result as opposed to a ztd::text::transcode_result because the state | |
/// information is on the stack, and returning the state in those types by reference will result in references to | |
/// memory that has already been cleaned up. If you need access to the state parameters, call the lower-level | |
/// functionality with your own created states. | |
////// | |
template <typename _Input, typename _FromEncoding, typename _Output, typename _ToEncoding, | |
typename _FromErrorHandler, typename _ToErrorHandler, typename _FromState> | |
constexpr auto transcode_into(_Input&& __input, _FromEncoding&& __from_encoding, _Output&& __output, | |
_ToEncoding&& __to_encoding, _FromErrorHandler&& __from_error_handler, _ToErrorHandler&& __to_error_handler, | |
_FromState& __from_state) { | |
using _UToEncoding = __txt_detail::__remove_cvref_t<_ToEncoding>; | |
using _ToState = encode_state_t<_UToEncoding>; | |
_ToState __to_state = make_encode_state(__to_encoding); | |
auto __stateful_result = transcode_into(::std::forward<_Input>(__input), | |
::std::forward<_FromEncoding>(__from_encoding), ::std::forward<_Output>(__output), | |
::std::forward<_ToEncoding>(__to_encoding), ::std::forward<_FromErrorHandler>(__from_error_handler), | |
::std::forward<_ToErrorHandler>(__to_error_handler), __from_state, __to_state); | |
return __txt_detail::__slice_to_stateless(::std::move(__stateful_result)); | |
} | |
////// | |
/// @brief Converts the code units of the given input view through the | |
/// from encoding to code units of the to encoding into the output | |
/// view. | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce intermediate code points. | |
/// @param[in] __from_encoding The encoding that will be used to decode the input's code units into | |
/// intermediate code points. | |
/// @param[in] __output An output_view to write code units to as the result of the encode operation from the | |
/// intermediate code points. | |
/// @param[in] __to_encoding The encoding that will be used to encode the intermediate code points into the | |
/// final code units. | |
/// @param[in] __from_error_handler The error handler for the @p __from_encoding 's decode step. | |
/// @param[in] __to_error_handler The error handler for the @p __to_encoding 's encode step. | |
/// | |
/// @remarks This function creates a decode state @c from_state by calling ztd::text::make_decode_state. The | |
/// result from this function returns a ztd::text::stateless_transcode_result as opposed to a | |
/// ztd::text::transcode_result because the state information is on the stack, and returning the state in | |
/// those types by reference will result in references to memory that has already been cleaned up. If you need | |
/// access to the state parameters, call the lower-level functionality with your own created states. | |
////// | |
template <typename _Input, typename _FromEncoding, typename _Output, typename _ToEncoding, | |
typename _FromErrorHandler, typename _ToErrorHandler> | |
constexpr auto transcode_into(_Input&& __input, _FromEncoding&& __from_encoding, _Output&& __output, | |
_ToEncoding&& __to_encoding, _FromErrorHandler&& __from_error_handler, _ToErrorHandler&& __to_error_handler) { | |
using _UFromEncoding = __txt_detail::__remove_cvref_t<_FromEncoding>; | |
using _FromState = decode_state_t<_UFromEncoding>; | |
_FromState __from_state = make_decode_state(__from_encoding); | |
return transcode_into(::std::forward<_Input>(__input), ::std::forward<_FromEncoding>(__from_encoding), | |
::std::forward<_Output>(__output), ::std::forward<_ToEncoding>(__to_encoding), | |
::std::forward<_FromErrorHandler>(__from_error_handler), | |
::std::forward<_ToErrorHandler>(__to_error_handler), __from_state); | |
} | |
////// | |
/// @brief Converts the code units of the given input view through the | |
/// from encoding to code units of the to encoding into the output | |
/// view. | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce intermediate code points. | |
/// @param[in] __from_encoding The encoding that will be used to decode the input's code units into | |
/// intermediate code points. | |
/// @param[in] __output An output_view to write code units to as the result of the encode operation from the | |
/// intermediate code points. | |
/// @param[in] __to_encoding The encoding that will be used to encode the intermediate code points into the | |
/// final code units. | |
/// @param[in] __from_error_handler The error handler for the @p __from_encoding 's decode step. | |
/// | |
/// @remarks This function creates an @c to_error_handler from a class like ztd::text::default_handler, but that is | |
/// marked as careless since you did not explicitly provide it. This matters for lossy conversions that are not | |
/// injective. The result from this function returns a ztd::text::stateless_transcode_result as opposed to a | |
/// ztd::text::transcode_result because the state information is on the stack, and returning the state in | |
/// those types by reference will result in references to memory that has already been cleaned up. If you need | |
/// access to the state parameters, call the lower-level functionality with your own created states. | |
////// | |
template <typename _Input, typename _FromEncoding, typename _Output, typename _ToEncoding, | |
typename _FromErrorHandler> | |
constexpr auto transcode_into(_Input&& __input, _FromEncoding&& __from_encoding, _Output&& __output, | |
_ToEncoding&& __to_encoding, _FromErrorHandler&& __from_error_handler) { | |
auto __handler = __txt_detail::__duplicate_or_be_careless(__from_error_handler); | |
return transcode_into(::std::forward<_Input>(__input), ::std::forward<_FromEncoding>(__from_encoding), | |
::std::forward<_Output>(__output), ::std::forward<_ToEncoding>(__to_encoding), | |
::std::forward<_FromErrorHandler>(__from_error_handler), __handler); | |
} | |
////// | |
/// @brief Converts the code units of the given input view through the | |
/// from encoding to code units of the to encoding into the output | |
/// view. | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce intermediate code points. | |
/// @param[in] __from_encoding The encoding that will be used to decode the input's code units into | |
/// intermediate code points. | |
/// @param[in] __output An output_view to write code units to as the result of the encode operation from the | |
/// intermediate code points. | |
/// @param[in] __to_encoding The encoding that will be used to encode the intermediate code points into the | |
/// final code units. | |
/// | |
/// @remarks This function creates an @c from_error_handler from a class like ztd::text::default_handler, but that | |
/// is marked as careless since you did not explicitly provide it. This matters for lossy conversions that are | |
/// not injective. The result from this function returns a ztd::text::stateless_transcode_result as opposed to a | |
/// ztd::text::transcode_result because the state information is on the stack, and returning the state in | |
/// those types by reference will result in references to memory that has already been cleaned up. If you need | |
/// access to the state parameters, call the lower-level functionality with your own created states. | |
////// | |
template <typename _Input, typename _FromEncoding, typename _Output, typename _ToEncoding> | |
constexpr auto transcode_into( | |
_Input&& __input, _FromEncoding&& __from_encoding, _Output&& __output, _ToEncoding&& __to_encoding) { | |
default_handler __handler {}; | |
return transcode_into(::std::forward<_Input>(__input), ::std::forward<_FromEncoding>(__from_encoding), | |
::std::forward<_Output>(__output), ::std::forward<_ToEncoding>(__to_encoding), __handler); | |
} | |
////// | |
/// @brief Converts the code units of the given input view through the | |
/// from encoding to code units of the to encoding into the output | |
/// view. | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce intermediate code points. | |
/// @param[in] __to_encoding The encoding that will be used to encode the intermediate code points into the | |
/// final code units. | |
/// @param[in] __output An output_view to write code units to as the result of the encode operation from the | |
/// intermediate code points. | |
/// | |
/// @remarks This function creates both: a @c from_error_handler using a ztd::text::default_handler that is marked | |
/// as careless to pass to the next function overload; and, a @c from_encoding to interpret the @p __input by | |
/// checking the @p __input 's @c value_type. This matters for lossy conversions that are not injective. The | |
/// result from this function returns a ztd::text::stateless_transcode_result as opposed to a | |
/// ztd::text::transcode_result because the state information is on the stack, and returning the state in | |
/// those types by reference will result in references to memory that has already been cleaned up. If you need | |
/// access to the state parameters, call the lower-level functionality with your own created states. | |
////// | |
template <typename _Input, typename _ToEncoding, typename _Output> | |
constexpr auto transcode_into(_Input&& __input, _ToEncoding&& __to_encoding, _Output&& __output) { | |
using _UInput = __txt_detail::__remove_cvref_t<_Input>; | |
using _UFromEncoding = default_code_unit_encoding_t<__txt_detail::__range_value_type_t<_UInput>>; | |
_UFromEncoding __from_encoding {}; | |
default_handler __handler {}; | |
return transcode_into(::std::forward<_Input>(__input), __from_encoding, ::std::forward<_Output>(__output), | |
::std::forward<_ToEncoding>(__to_encoding), __handler); | |
} | |
namespace __txt_detail { | |
template <typename _Input, typename _FromEncoding, typename _OutputContainer, typename _ToEncoding, | |
typename _FromErrorHandler, typename _ToErrorHandler, typename _FromState, typename _ToState> | |
constexpr auto __intermediate_transcode_to_storage(_Input&& __input, _FromEncoding&& __from_encoding, | |
_OutputContainer& __output, _ToEncoding&& __to_encoding, _FromErrorHandler&& __from_error_handler, | |
_ToErrorHandler&& __to_error_handler, _FromState& __from_state, _ToState& __to_state) { | |
// … Weeeellll. Here we go … | |
using _UToEncoding = __txt_detail::__remove_cvref_t<_ToEncoding>; | |
using _UFromEncoding = __txt_detail::__remove_cvref_t<_FromEncoding>; | |
constexpr ::std::size_t _IntermediateOutputMax | |
= ZTD_TEXT_INTERMEDIATE_BUFFER_SIZE_I_ < max_code_units_v<_UToEncoding> | |
? max_code_units_v<_UToEncoding> | |
: ZTD_TEXT_INTERMEDIATE_BUFFER_SIZE_I_; | |
using _IntermediateOutputValueType = code_unit_t<_UToEncoding>; | |
using _InitialInput = __string_view_or_span_or_reconstruct_t<_Input>; | |
using _IntermediateInputValueType = code_point_t<_UFromEncoding>; | |
using _IntermediateInput = ::ztd::text::span<_IntermediateInputValueType>; | |
using _IntermediateOutputInitial | |
= ::ztd::text::span<_IntermediateOutputValueType, _IntermediateOutputMax>; | |
using _IntermediateOutput = ::ztd::text::span<_IntermediateOutputValueType>; | |
using _DecodeResult = decltype(__txt_detail::__basic_decode_one<__txt_detail::__consume::__no>( | |
::std::declval<_InitialInput>(), ::std::forward<_FromEncoding>(__from_encoding), | |
::std::declval<_IntermediateInput>(), __from_error_handler, __from_state)); | |
using _WorkingInput = decltype(::std::declval<_DecodeResult>().input); | |
_WorkingInput __working_input( | |
__txt_detail::__string_view_or_span_or_reconstruct(::std::forward<_Input>(__input))); | |
_IntermediateOutputValueType __intermediate_output_storage[_IntermediateOutputMax] {}; | |
_IntermediateOutputInitial __intermediate_initial(__intermediate_output_storage); | |
for (;;) { | |
auto __result | |
= transcode_into(::std::move(__working_input), __from_encoding, __intermediate_initial, | |
__to_encoding, __from_error_handler, __to_error_handler, __from_state, __to_state); | |
_IntermediateOutput __intermediate_output( | |
__intermediate_initial.data(), __result.output.data() - __intermediate_initial.data()); | |
using _SpanIterator = typename _IntermediateOutput::iterator; | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_insert_bulk, _OutputContainer, | |
_SpanIterator, _SpanIterator>) { | |
// inserting in bulk | |
// can be faster, more performant, | |
// save us some coding too | |
__output.insert(__output.cend(), __intermediate_output.begin(), __intermediate_output.end()); | |
} | |
else { | |
// O O F! we have to insert one at a time. | |
for (auto&& __intermediate_code_unit : __intermediate_output) { | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_push_back, | |
_OutputContainer, _IntermediateOutputValueType>) { | |
__output.push_back(__intermediate_code_unit); | |
} | |
else { | |
__output.insert(__output.cend(), __intermediate_code_unit); | |
} | |
} | |
} | |
if (__result.error_code == encoding_error::insufficient_output_space) { | |
// loop around, we've got S P A C E for more | |
__working_input = ::std::move(__result.input); | |
continue; | |
} | |
if (__result.error_code != encoding_error::ok) { | |
return __result; | |
} | |
if (__txt_detail::__adl::__adl_empty(__result.input)) { | |
return __result; | |
} | |
} | |
} | |
template <typename _OutputContainer, typename _Input, typename _FromEncoding, typename _ToEncoding, | |
typename _FromErrorHandler, typename _ToErrorHandler, typename _FromState, typename _ToState> | |
constexpr auto __transcode_dispatch(_Input&& __input, _FromEncoding&& __from_encoding, | |
_ToEncoding&& __to_encoding, _FromErrorHandler&& __from_error_handler, | |
_ToErrorHandler&& __to_error_handler, _FromState& __from_state, _ToState& __to_state) { | |
using _UFromEncoding = __remove_cvref_t<_FromEncoding>; | |
_OutputContainer __output {}; | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_size, _Input>) { | |
using _SizeType = decltype(__txt_detail::__adl::__adl_size(__input)); | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_reserve_with_size_type, | |
_OutputContainer, _SizeType>) { | |
// TODO: better estimates | |
__output.reserve(__txt_detail::__adl::__adl_size(__input)); | |
} | |
} | |
if constexpr (__txt_detail::__is_decode_range_category_output_v<_UFromEncoding>) { | |
using _BackInserterIterator = decltype(::std::back_inserter(::std::declval<_OutputContainer&>())); | |
using _Unbounded = unbounded_view<_BackInserterIterator>; | |
// We can use the unbounded stuff | |
_Unbounded __insert_view(::std::back_inserter(__output)); | |
auto __stateful_result = transcode_into(::std::forward<_Input>(__input), | |
::std::forward<_FromEncoding>(__from_encoding), ::std::move(__insert_view), | |
::std::forward<_ToEncoding>(__to_encoding), | |
::std::forward<_FromErrorHandler>(__from_error_handler), | |
::std::forward<_ToErrorHandler>(__to_error_handler), __from_state, __to_state); | |
(void)__stateful_result; | |
return __output; | |
} | |
else { | |
auto __stateful_result = __txt_detail::__intermediate_transcode_to_storage( | |
::std::forward<_Input>(__input), ::std::forward<_FromEncoding>(__from_encoding), __output, | |
::std::forward<_ToEncoding>(__to_encoding), | |
::std::forward<_FromErrorHandler>(__from_error_handler), | |
::std::forward<_ToErrorHandler>(__to_error_handler), __from_state, __to_state); | |
(void)__stateful_result; | |
return __output; | |
} | |
} | |
} // namespace __txt_detail | |
////// | |
/// @brief Converts the code units of the given input view through the from encoding to code units of the to | |
/// encoding for the output, which is then returned in a result structure with additional information about | |
/// success. | |
/// | |
/// @tparam _OutputContainer The container to default-construct and serialize data into. Typically, a @c | |
/// std::basic_string or a @c std::vector of some sort. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce intermediate code points. | |
/// @param[in] __from_encoding The encoding that will be used to decode the input's code units into | |
/// intermediate code points. | |
/// @param[in] __to_encoding The encoding that will be used to encode the intermediate code points into the | |
/// final code units. | |
/// @param[in] __from_error_handler The error handler for the @p __from_encoding 's decode step. | |
/// @param[in] __to_error_handler The error handler for the @p __to_encoding 's encode step. | |
/// @param[in,out] __from_state A reference to the associated state for the @p __from_encoding 's decode step. | |
/// @param[in,out] __to_state A reference to the associated state for the @p __to_encoding 's encode step. | |
/// | |
/// @returns A ztd::text::transcode_result object that contains references to @p __from_state and @p | |
/// __to_state and an @c output parameter that contains the @p _OutputContainer specified. If the container has a | |
/// @c container.reserve function, it is and some multiple of the input's size is used to pre-size the container, | |
/// to aid with @c push_back / @c insert reallocation pains. | |
////// | |
template <typename _OutputContainer, typename _Input, typename _FromEncoding, typename _ToEncoding, | |
typename _FromErrorHandler, typename _ToErrorHandler, typename _FromState, typename _ToState> | |
constexpr auto transcode_to(_Input&& __input, _FromEncoding&& __from_encoding, _ToEncoding&& __to_encoding, | |
_FromErrorHandler&& __from_error_handler, _ToErrorHandler&& __to_error_handler, _FromState& __from_state, | |
_ToState& __to_state) { | |
using _UFromEncoding = __txt_detail::__remove_cvref_t<_FromEncoding>; | |
_OutputContainer __output {}; | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_adl_size, _Input>) { | |
using _SizeType = decltype(__txt_detail::__adl::__adl_size(__input)); | |
if constexpr (__txt_detail::__is_detected_v<__txt_detail::__detect_reserve_with_size_type, | |
_OutputContainer, _SizeType>) { | |
// TODO: better estimates | |
__output.reserve(__txt_detail::__adl::__adl_size(__input)); | |
} | |
} | |
if constexpr (__txt_detail::__is_decode_range_category_output_v<_UFromEncoding>) { | |
using _BackInserterIterator = decltype(::std::back_inserter(::std::declval<_OutputContainer&>())); | |
using _Unbounded = unbounded_view<_BackInserterIterator>; | |
auto __insert_view = _Unbounded(::std::back_inserter(__output)); | |
auto __stateful_result = transcode_into(::std::forward<_Input>(__input), | |
::std::forward<_FromEncoding>(__from_encoding), ::std::move(__insert_view), | |
::std::forward<_ToEncoding>(__to_encoding), ::std::forward<_FromErrorHandler>(__from_error_handler), | |
::std::forward<_ToErrorHandler>(__to_error_handler), __from_state, __to_state); | |
return __txt_detail::__replace_result_output(::std::move(__stateful_result), ::std::move(__output)); | |
} | |
else { | |
auto __stateful_result = __txt_detail::__intermediate_transcode_to_storage( | |
::std::forward<_Input>(__input), ::std::forward<_FromEncoding>(__from_encoding), __output, | |
::std::forward<_ToEncoding>(__to_encoding), ::std::forward<_FromErrorHandler>(__from_error_handler), | |
::std::forward<_ToErrorHandler>(__to_error_handler), __from_state, __to_state); | |
return __txt_detail::__replace_result_output(::std::move(__stateful_result), ::std::move(__output)); | |
} | |
} | |
////// | |
/// @brief Converts the code units of the given input view through the from encoding to code units of the to | |
/// encoding for the output, which is then returned in a result structure with additional information about | |
/// success. | |
/// | |
/// @tparam _OutputContainer The container to default-construct and serialize data into. Typically, a @c | |
/// std::basic_string or a @c std::vector of some sort. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce intermediate code points. | |
/// @param[in] __from_encoding The encoding that will be used to decode the input's code units into | |
/// intermediate code points. | |
/// @param[in] __to_encoding The encoding that will be used to encode the intermediate code points into the | |
/// final code units. | |
/// @param[in] __from_error_handler The error handler for the @p __from_encoding 's decode step. | |
/// @param[in] __to_error_handler The error handler for the @p __to_encoding 's encode step. | |
/// @param[in,out] __from_state A reference to the associated state for the @p __from_encoding 's decode step. | |
/// | |
/// @returns A ztd::text::stateless_transcode_result object that contains references to an @c container.output | |
/// parameter that contains the @p _OutputContainer specified. | |
/// | |
/// @remarks A default state for the encode step of the operation is create using ztd::text::make_encode_state. The | |
/// return type is stateless since both states must be passed in. If you want to have access to the states, create | |
/// both of them yourself and pass them into a lower-level function that accepts those parameters. | |
////// | |
template <typename _OutputContainer, typename _Input, typename _FromEncoding, typename _ToEncoding, | |
typename _FromErrorHandler, typename _ToErrorHandler, typename _FromState> | |
constexpr auto transcode_to(_Input&& __input, _FromEncoding&& __from_encoding, _ToEncoding&& __to_encoding, | |
_FromErrorHandler&& __from_error_handler, _ToErrorHandler&& __to_error_handler, _FromState& __from_state) { | |
using _UToEncoding = __txt_detail::__remove_cvref_t<_ToEncoding>; | |
using _ToState = encode_state_t<_UToEncoding>; | |
_ToState __to_state = make_encode_state(__to_encoding); | |
return transcode_to<_OutputContainer>(::std::forward<_Input>(__input), | |
::std::forward<_FromEncoding>(__from_encoding), ::std::forward<_ToEncoding>(__to_encoding), | |
::std::forward<_FromErrorHandler>(__from_error_handler), | |
::std::forward<_ToErrorHandler>(__to_error_handler), __from_state, __to_state); | |
} | |
////// | |
/// @brief Converts the code units of the given input view through the from encoding to code units of the to | |
/// encoding for the output, which is then returned in a result structure with additional information about | |
/// success. | |
/// | |
/// @tparam _OutputContainer The container to default-construct and serialize data into. Typically, a @c | |
/// std::basic_string or a @c std::vector of some sort. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce intermediate code points. | |
/// @param[in] __from_encoding The encoding that will be used to decode the input's code units into | |
/// intermediate code points. | |
/// @param[in] __to_encoding The encoding that will be used to encode the intermediate code points into the | |
/// final code units. | |
/// @param[in] __from_error_handler The error handler for the @p __from_encoding 's decode step. | |
/// @param[in] __to_error_handler The error handler for the @p __to_encoding 's encode step. | |
/// | |
/// @returns A ztd::text::stateless_transcode_result object that contains references to an @c container.output | |
/// parameter that contains the @p _OutputContainer specified. | |
/// | |
/// @remarks A default state for the decode step of the operation is create using ztd::text::make_decode_state. The | |
/// return type is stateless since both states must be passed in. If you want to have access to the states, create | |
/// both of them yourself and pass them into a lower-level function that accepts those parameters. | |
////// | |
template <typename _OutputContainer, typename _Input, typename _FromEncoding, typename _ToEncoding, | |
typename _FromErrorHandler, typename _ToErrorHandler> | |
constexpr auto transcode_to(_Input&& __input, _FromEncoding&& __from_encoding, _ToEncoding&& __to_encoding, | |
_FromErrorHandler&& __from_error_handler, _ToErrorHandler&& __to_error_handler) { | |
using _UFromEncoding = __txt_detail::__remove_cvref_t<_FromEncoding>; | |
using _FromState = decode_state_t<_UFromEncoding>; | |
_FromState __from_state = make_decode_state(__from_encoding); | |
return transcode_to<_OutputContainer>(::std::forward<_Input>(__input), | |
::std::forward<_FromEncoding>(__from_encoding), ::std::forward<_ToEncoding>(__to_encoding), | |
::std::forward<_FromErrorHandler>(__from_error_handler), | |
::std::forward<_ToErrorHandler>(__to_error_handler), __from_state); | |
} | |
////// | |
/// @brief Converts the code units of the given input view through the from encoding to code units of the to | |
/// encoding for the output, which is then returned in a result structure with additional information about | |
/// success. | |
/// | |
/// @tparam _OutputContainer The container to default-construct and serialize data into. Typically, a @c | |
/// std::basic_string or a @c std::vector of some sort. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce intermediate code points. | |
/// @param[in] __from_encoding The encoding that will be used to decode the input's code units into | |
/// intermediate code points. | |
/// @param[in] __to_encoding The encoding that will be used to encode the intermediate code points into the | |
/// final code units. | |
/// @param[in] __from_error_handler The error handler for the @p __from_encoding 's decode step. | |
/// | |
/// @returns A ztd::text::stateless_transcode_result object that contains references to an @c container.output | |
/// parameter that contains the @p _OutputContainer specified. | |
/// | |
/// @remarks A @c to_error_handler for the encode step of the operation is created using default construction of a | |
/// ztd::text::default_handler that is marked as careless. The return type is stateless since both states must be | |
/// passed in. If you want to have access to the states, create both of them yourself and pass them into a | |
/// lower-level function that accepts those parameters. | |
////// | |
template <typename _OutputContainer, typename _Input, typename _FromEncoding, typename _ToEncoding, | |
typename _FromErrorHandler> | |
constexpr auto transcode_to(_Input&& __input, _FromEncoding&& __from_encoding, _ToEncoding&& __to_encoding, | |
_FromErrorHandler&& __from_error_handler) { | |
auto __handler = __txt_detail::__duplicate_or_be_careless(__from_error_handler); | |
return transcode_to<_OutputContainer>(::std::forward<_Input>(__input), | |
::std::forward<_FromEncoding>(__from_encoding), ::std::forward<_ToEncoding>(__to_encoding), | |
::std::forward<_FromErrorHandler>(__from_error_handler), __handler); | |
} | |
////// | |
/// @brief Converts the code units of the given input view through the from encoding to code units of the to | |
/// encoding for the output, which is then returned in a result structure with additional information about | |
/// success. | |
/// | |
/// @tparam _OutputContainer The container to default-construct and serialize data into. Typically, a @c | |
/// std::basic_string or a @c std::vector of some sort. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce intermediate code points. | |
/// @param[in] __from_encoding The encoding that will be used to decode the input's code units into | |
/// intermediate code points. | |
/// @param[in] __to_encoding The encoding that will be used to encode the intermediate code points into the | |
/// final code units. | |
/// | |
/// @returns A ztd::text::stateless_transcode_result object that contains references to an @c container.output | |
/// parameter that contains the @p _OutputContainer specified. | |
/// | |
/// @remarks A @c from_error_handler for the encode step of the operation is created using default construction of | |
/// a ztd::text::default_handler that is marked as careless. The return type is stateless since both states must be | |
/// passed in. If you want to have access to the states, create both of them yourself and pass them into a | |
/// lower-level function that accepts those parameters. | |
////// | |
template <typename _OutputContainer, typename _Input, typename _FromEncoding, typename _ToEncoding> | |
constexpr auto transcode_to(_Input&& __input, _FromEncoding&& __from_encoding, _ToEncoding&& __to_encoding) { | |
default_handler __handler {}; | |
return transcode_to<_OutputContainer>(::std::forward<_Input>(__input), | |
::std::forward<_FromEncoding>(__from_encoding), ::std::forward<_ToEncoding>(__to_encoding), __handler); | |
} | |
////// | |
/// @brief Converts the code units of the given input view through the from encoding to code units of the to | |
/// encoding for the output, which is then returned in a result structure with additional information about | |
/// success. | |
/// | |
/// @tparam _OutputContainer The container to default-construct and serialize data into. Typically, a @c | |
/// std::basic_string or a @c std::vector of some sort. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce intermediate code points. | |
/// @param[in] __to_encoding The encoding that will be used to encode the intermediate code points into the | |
/// final code units. | |
/// | |
/// @returns A ztd::text::stateless_transcode_result object that contains references to an @c container.output | |
/// parameter that contains the @p _OutputContainer specified. | |
/// | |
/// @remarks A @c from_error_handler for the encode step of the operation is created using default construction of | |
/// a ztd::text::default_handler that is marked as careless. The return type is stateless since both states must be | |
/// passed in. If you want to have access to the states, create both of them yourself and pass them into a | |
/// lower-level function that accepts those parameters. | |
////// | |
template <typename _OutputContainer, typename _Input, typename _ToEncoding> | |
constexpr auto transcode_to(_Input&& __input, _ToEncoding&& __to_encoding) { | |
using _UInput = __txt_detail::__remove_cvref_t<_Input>; | |
using _CodeUnit = __txt_detail::__range_value_type_t<_UInput>; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED_I_) | |
if (::std::is_constant_evaluated()) { | |
using _UFromEncoding = default_consteval_code_unit_encoding_t<_CodeUnit>; | |
default_handler __handler {}; | |
_UFromEncoding __from_encoding {}; | |
return transcode_to<_OutputContainer>(::std::forward<_Input>(__input), __from_encoding, | |
::std::forward<_ToEncoding>(__to_encoding), __handler); | |
} | |
else | |
#endif | |
{ | |
using _UFromEncoding = default_code_unit_encoding_t<_CodeUnit>; | |
default_handler __handler {}; | |
_UFromEncoding __from_encoding {}; | |
return transcode_to<_OutputContainer>(::std::forward<_Input>(__input), __from_encoding, | |
::std::forward<_ToEncoding>(__to_encoding), __handler); | |
} | |
} | |
////// | |
/// @brief Converts the code units of the given input view through the from encoding to code units of the to | |
/// encoding for the output, which is then returned in a result structure with additional information about | |
/// success. | |
/// | |
/// @tparam _OutputContainer The container to default-construct and serialize data into. Typically, a @c | |
/// std::basic_string or a @c std::vector of some sort. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce intermediate code points. | |
/// @param[in] __from_encoding The encoding that will be used to decode the input's code units into | |
/// intermediate code points. | |
/// @param[in] __to_encoding The encoding that will be used to encode the intermediate code points into the | |
/// final code units. | |
/// @param[in] __from_error_handler The error handler for the @p __from_encoding 's decode step. | |
/// @param[in] __to_error_handler The error handler for the @p __to_encoding 's encode step. | |
/// @param[in,out] __from_state A reference to the associated state for the @p __from_encoding 's decode step. | |
/// @param[in,out] __to_state A reference to the associated state for the @p __to_encoding 's encode step. | |
/// | |
/// @returns An @p _OutputContainer with the result, regardless of whether an error occurs or not. If you are | |
/// looking for error information and not just a quick one-off conversion function, please use | |
/// ztd::text::transcode_to or ztd::text::transcode_into. | |
////// | |
template <typename _OutputContainer = void, typename _Input, typename _FromEncoding, typename _ToEncoding, | |
typename _FromErrorHandler, typename _ToErrorHandler, typename _FromState, typename _ToState> | |
constexpr auto transcode(_Input&& __input, _FromEncoding&& __from_encoding, _ToEncoding&& __to_encoding, | |
_FromErrorHandler&& __from_error_handler, _ToErrorHandler&& __to_error_handler, _FromState& __from_state, | |
_ToState& __to_state) { | |
using _UToEncoding = __txt_detail::__remove_cvref_t<_ToEncoding>; | |
using _UOutputContainer = __txt_detail::__remove_cvref_t<_OutputContainer>; | |
using _OutputCodeUnit = code_unit_t<_UToEncoding>; | |
constexpr bool _IsVoidContainer = ::std::is_void_v<_UOutputContainer>; | |
constexpr bool _IsStringable | |
= (__txt_detail::__is_character_v<_OutputCodeUnit> || is_unicode_code_point_v<_OutputCodeUnit>); | |
if constexpr (_IsVoidContainer && _IsStringable) { | |
// prevent instantiation errors with basic_string by boxing it inside of an "if constexpr" | |
using _RealOutputContainer = ::std::basic_string<_OutputCodeUnit>; | |
return __txt_detail::__transcode_dispatch<_RealOutputContainer>(::std::forward<_Input>(__input), | |
::std::forward<_FromEncoding>(__from_encoding), ::std::forward<_ToEncoding>(__to_encoding), | |
::std::forward<_FromErrorHandler>(__from_error_handler), | |
::std::forward<_ToErrorHandler>(__to_error_handler), __from_state, __to_state); | |
} | |
else { | |
using _RealOutputContainer | |
= ::std::conditional_t<_IsVoidContainer, ::std::vector<_OutputCodeUnit>, _OutputContainer>; | |
return __txt_detail::__transcode_dispatch<_RealOutputContainer>(::std::forward<_Input>(__input), | |
::std::forward<_FromEncoding>(__from_encoding), ::std::forward<_ToEncoding>(__to_encoding), | |
::std::forward<_FromErrorHandler>(__from_error_handler), | |
::std::forward<_ToErrorHandler>(__to_error_handler), __from_state, __to_state); | |
} | |
} | |
////// | |
/// @brief Converts the code units of the given input view through the from encoding to code units of the to | |
/// encoding for the output, which is then returned in a result structure with additional information about | |
/// success. | |
/// | |
/// @tparam _OutputContainer The container to default-construct and serialize data into. Typically, a @c | |
/// std::basic_string or a @c std::vector of some sort. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce intermediate code points. | |
/// @param[in] __from_encoding The encoding that will be used to decode the input's code units into | |
/// intermediate code points. | |
/// @param[in] __to_encoding The encoding that will be used to encode the intermediate code points into the | |
/// final code units. | |
/// @param[in] __from_error_handler The error handler for the @p __from_encoding 's decode step. | |
/// @param[in] __to_error_handler The error handler for the @p __to_encoding 's encode step. | |
/// @param[in,out] __from_state A reference to the associated state for the @p __from_encoding 's decode step. | |
/// | |
/// @returns An @p _OutputContainer with the result, regardless of whether an error occurs or not. If you are | |
/// looking for error information and not just a quick one-off conversion function, please use | |
/// ztd::text::transcode_to or ztd::text::transcode_into. | |
/// | |
/// @remarks This function creates an @c to_state for the encoding step of the operation using | |
/// ztd::text::make_encode_state. | |
////// | |
template <typename _OutputContainer = void, typename _Input, typename _FromEncoding, typename _ToEncoding, | |
typename _FromErrorHandler, typename _ToErrorHandler, typename _FromState> | |
constexpr auto transcode(_Input&& __input, _FromEncoding&& __from_encoding, _ToEncoding&& __to_encoding, | |
_FromErrorHandler&& __from_error_handler, _ToErrorHandler&& __to_error_handler, _FromState& __from_state) { | |
using _UToEncoding = __txt_detail::__remove_cvref_t<_ToEncoding>; | |
using _ToState = encode_state_t<_UToEncoding>; | |
_ToState __to_state = make_encode_state(__to_encoding); | |
return transcode<_OutputContainer>(::std::forward<_Input>(__input), | |
::std::forward<_FromEncoding>(__from_encoding), ::std::forward<_ToEncoding>(__to_encoding), | |
::std::forward<_FromErrorHandler>(__from_error_handler), | |
::std::forward<_ToErrorHandler>(__to_error_handler), __from_state, __to_state); | |
} | |
////// | |
/// @brief Converts the code units of the given input view through the from encoding to code units of the to | |
/// encoding for the output, which is then returned in a result structure with additional information about | |
/// success. | |
/// | |
/// @tparam _OutputContainer The container to default-construct and serialize data into. Typically, a @c | |
/// std::basic_string or a @c std::vector of some sort. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce intermediate code points. | |
/// @param[in] __from_encoding The encoding that will be used to decode the input's code units into | |
/// intermediate code points. | |
/// @param[in] __to_encoding The encoding that will be used to encode the intermediate code points into the | |
/// final code units. | |
/// @param[in] __from_error_handler The error handler for the @p __from_encoding 's decode step. | |
/// @param[in] __to_error_handler The error handler for the @p __to_encoding 's encode step. | |
/// | |
/// @returns An @p _OutputContainer with the result, regardless of whether an error occurs or not. If you are | |
/// looking for error information and not just a quick one-off conversion function, please use | |
/// ztd::text::transcode_to or ztd::text::transcode_into. | |
/// | |
/// @remarks This function creates an @c from_state for the encoding step of the operation using | |
/// ztd::text::make_decode_state. | |
////// | |
template <typename _OutputContainer = void, typename _Input, typename _FromEncoding, typename _ToEncoding, | |
typename _FromErrorHandler, typename _ToErrorHandler> | |
constexpr auto transcode(_Input&& __input, _FromEncoding&& __from_encoding, _ToEncoding&& __to_encoding, | |
_FromErrorHandler&& __from_error_handler, _ToErrorHandler&& __to_error_handler) { | |
using _UFromEncoding = __txt_detail::__remove_cvref_t<_FromEncoding>; | |
using _FromState = decode_state_t<_UFromEncoding>; | |
_FromState __from_state = make_decode_state(__from_encoding); | |
return transcode<_OutputContainer>(::std::forward<_Input>(__input), | |
::std::forward<_FromEncoding>(__from_encoding), ::std::forward<_ToEncoding>(__to_encoding), | |
::std::forward<_FromErrorHandler>(__from_error_handler), | |
::std::forward<_ToErrorHandler>(__to_error_handler), __from_state); | |
} | |
////// | |
/// @brief Converts the code units of the given input view through the from encoding to code units of the to | |
/// encoding for the output, which is then returned in a result structure with additional information about | |
/// success. | |
/// | |
/// @tparam _OutputContainer The container to default-construct and serialize data into. Typically, a @c | |
/// std::basic_string or a @c std::vector of some sort. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce intermediate code points. | |
/// @param[in] __from_encoding The encoding that will be used to decode the input's code units into | |
/// intermediate code points. | |
/// @param[in] __to_encoding The encoding that will be used to encode the intermediate code points into the | |
/// final code units. | |
/// @param[in] __from_error_handler The error handler for the @p __from_encoding 's decode step. | |
/// | |
/// @returns An @p _OutputContainer with the result, regardless of whether an error occurs or not. If you are | |
/// looking for error information and not just a quick one-off conversion function, please use | |
/// ztd::text::transcode_to or ztd::text::transcode_into. | |
/// | |
/// @remarks This function creates a @c to_error_handler from a class like ztd::text::default_handler, but that is | |
/// marked as careless since you did not explicitly provide it. This matters for lossy conversions that are not | |
/// injective. | |
////// | |
template <typename _OutputContainer = void, typename _Input, typename _FromEncoding, typename _ToEncoding, | |
typename _FromErrorHandler> | |
constexpr auto transcode(_Input&& __input, _FromEncoding&& __from_encoding, _ToEncoding&& __to_encoding, | |
_FromErrorHandler&& __from_error_handler) { | |
auto __handler = __txt_detail::__duplicate_or_be_careless(__from_error_handler); | |
return transcode<_OutputContainer>(::std::forward<_Input>(__input), | |
::std::forward<_FromEncoding>(__from_encoding), ::std::forward<_ToEncoding>(__to_encoding), | |
::std::forward<_FromErrorHandler>(__from_error_handler), __handler); | |
} | |
////// | |
/// @brief Converts the code units of the given input view through the from encoding to code units of the to | |
/// encoding for the output, which is then returned in a result structure with additional information about | |
/// success. | |
/// | |
/// @tparam _OutputContainer The container to default-construct and serialize data into. Typically, a @c | |
/// std::basic_string or a @c std::vector of some sort. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce intermediate code points. | |
/// @param[in] __from_encoding The encoding that will be used to decode the input's code units into | |
/// intermediate code points. | |
/// @param[in] __to_encoding The encoding that will be used to encode the intermediate code points into the | |
/// final code units. | |
/// | |
/// @returns An @p _OutputContainer with the result, regardless of whether an error occurs or not. If you are | |
/// looking for error information and not just a quick one-off conversion function, please use | |
/// ztd::text::transcode_to or ztd::text::transcode_into. | |
/// | |
/// @remarks This function creates a @c from_error_handler from a class like ztd::text::default_handler, but that | |
/// is marked as careless since you did not explicitly provide it. This matters for lossy conversions that are not | |
/// injective. | |
////// | |
template <typename _OutputContainer = void, typename _Input, typename _FromEncoding, typename _ToEncoding> | |
constexpr auto transcode(_Input&& __input, _FromEncoding&& __from_encoding, _ToEncoding&& __to_encoding) { | |
default_handler __handler {}; | |
return transcode<_OutputContainer>(::std::forward<_Input>(__input), | |
::std::forward<_FromEncoding>(__from_encoding), ::std::forward<_ToEncoding>(__to_encoding), __handler); | |
} | |
////// | |
/// @brief Converts the code units of the given input view through the from encoding to code units of the to | |
/// encoding for the output, which is then returned in a result structure with additional information about | |
/// success. | |
/// | |
/// @tparam _OutputContainer The container to default-construct and serialize data into. Typically, a @c | |
/// std::basic_string or a @c std::vector of some sort. | |
/// | |
/// @param[in] __input An input_view to read code units from and use in the decode operation that will | |
/// produce intermediate code points. | |
/// @param[in] __to_encoding The encoding that will be used to encode the intermediate code points into the | |
/// final code units. | |
/// | |
/// @returns An @p _OutputContainer with the result, regardless of whether an error occurs or not. If you are | |
/// looking for error information and not just a quick one-off conversion function, please use | |
/// ztd::text::transcode_to or ztd::text::transcode_into. | |
/// | |
/// @remarks This function creates both: a @c from_error_handler from a class like ztd::text::default_handler, but | |
/// that is marked as careless since you did not explicitly provide it; and, a @c from_encoding derived from the @p | |
/// "__input"'s @c value_type. The careless marking matters for lossy conversions that are not injective. | |
////// | |
template <typename _OutputContainer = void, typename _Input, typename _ToEncoding> | |
constexpr auto transcode(_Input&& __input, _ToEncoding&& __to_encoding) { | |
using _UInput = __txt_detail::__remove_cvref_t<_Input>; | |
using _CodeUnit = __txt_detail::__range_value_type_t<_UInput>; | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_IS_CONSTANT_EVALUATED_I_) | |
if (::std::is_constant_evaluated()) { | |
using _UFromEncoding = default_consteval_code_unit_encoding_t<_CodeUnit>; | |
_UFromEncoding __from_encoding {}; | |
return transcode<_OutputContainer>( | |
::std::forward<_Input>(__input), __from_encoding, ::std::forward<_ToEncoding>(__to_encoding)); | |
} | |
else | |
#endif | |
{ | |
using _UFromEncoding = default_code_unit_encoding_t<_CodeUnit>; | |
_UFromEncoding __from_encoding {}; | |
return transcode<_OutputContainer>( | |
::std::forward<_Input>(__input), __from_encoding, ::std::forward<_ToEncoding>(__to_encoding)); | |
} | |
} | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/transcode.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/encode_view.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/encode_iterator.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/detail/encoding_iterator.hpp | |
#include <array> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
namespace __txt_detail { | |
template <typename _Encoding, typename _Input, typename _ErrorHandler> | |
inline constexpr bool __is_encoding_with_error_handler_never_returns_error_v = false; | |
using __encoding_sentinel_t = default_sentinel_t; | |
template <__transaction _EncodeOrDecode, typename _Derived, typename _Encoding, typename _Range, | |
typename _ErrorHandler, typename _State> | |
class __encoding_iterator | |
: private __ebco<__remove_cvref_t<_Encoding>, 0>, | |
private __ebco<__remove_cvref_t<_ErrorHandler>, 1>, | |
private __state_storage<__remove_cvref_t<__unwrap_t<_Encoding>>, __remove_cvref_t<_State>>, | |
private __cursor_cache<(_EncodeOrDecode == __transaction::__decode | |
? max_code_points_v<__remove_cvref_t<__unwrap_t<_Encoding>>> | |
: max_code_units_v<__remove_cvref_t<__unwrap_t<_Encoding>>>), | |
__is_range_input_or_output_range_v<__remove_cvref_t<__unwrap_t<_Range>>>>, | |
private __error_cache<(_EncodeOrDecode == __transaction::__decode | |
? decode_error_handler_always_returns_ok_v<__remove_cvref_t<__unwrap_t<_Encoding>>, | |
__remove_cvref_t<__unwrap_t<_ErrorHandler>>> | |
: encode_error_handler_always_returns_ok_v<__remove_cvref_t<__unwrap_t<_Encoding>>, | |
__remove_cvref_t<__unwrap_t<_ErrorHandler>>>)>, | |
private __ebco<_Range, 2> { | |
private: | |
using _URange = __remove_cvref_t<__unwrap_t<_Range>>; | |
using _UEncoding = __remove_cvref_t<__unwrap_t<_Encoding>>; | |
using _UErrorHandler = __remove_cvref_t<__unwrap_t<_ErrorHandler>>; | |
using _UState = __remove_cvref_t<__unwrap_t<_State>>; | |
using _BaseIterator = __range_iterator_t<_URange>; | |
inline static constexpr ::std::size_t _MaxValues = (_EncodeOrDecode == __transaction::__decode | |
? max_code_points_v<__remove_cvref_t<__unwrap_t<_Encoding>>> | |
: max_code_units_v<__remove_cvref_t<__unwrap_t<_Encoding>>>); | |
inline static constexpr bool _IsSingleValueType = _MaxValues == 1; | |
inline static constexpr bool _IsInputOrOutput = __is_range_input_or_output_range_v<_URange>; | |
inline static constexpr bool _IsCursorless = _IsSingleValueType && !_IsInputOrOutput; | |
inline static constexpr bool _IsErrorless = _EncodeOrDecode == __transaction::__decode | |
? decode_error_handler_always_returns_ok_v<_UEncoding, _UErrorHandler> | |
: encode_error_handler_always_returns_ok_v<_UEncoding, _UErrorHandler>; | |
using __base_cursor_cache_t = __cursor_cache<_MaxValues, _IsInputOrOutput>; | |
using __base_cursor_cache_size_t = typename __base_cursor_cache_t::_SizeType; | |
using __base_error_cache_t = __error_cache<_IsErrorless>; | |
using __base_encoding_t = __ebco<__remove_cvref_t<_Encoding>, 0>; | |
using __base_error_handler_t = __ebco<__remove_cvref_t<_ErrorHandler>, 1>; | |
using __base_range_t = __ebco<_Range, 2>; | |
using __base_state_t = __state_storage<__remove_cvref_t<_Encoding>, __remove_cvref_t<_State>>; | |
inline static constexpr bool _IsBackwards = __is_detected_v<__detect_object_encode_one_backwards, | |
_UEncoding, _URange, _UErrorHandler, _UState>; | |
public: | |
////// | |
/// @brief The underlying range type. | |
/// | |
////// | |
using range_type = _Range; | |
////// | |
/// @brief The base iterator type. | |
/// | |
////// | |
using iterator = _BaseIterator; | |
////// | |
/// @brief The encoding type used for transformations. | |
/// | |
////// | |
using encoding_type = _Encoding; | |
////// | |
/// @brief The error handler when an encode operation fails. | |
/// | |
////// | |
using error_handler_type = _ErrorHandler; | |
////// | |
/// @brief The state type used for encode operations. | |
/// | |
////// | |
using state_type = __remove_cvref_t<_State>; | |
////// | |
/// @brief The strength of the iterator category, as defined in relation to the base. | |
/// | |
////// | |
using iterator_category = ::std::conditional_t< | |
__is_iterator_concept_or_better_v<::std::bidirectional_iterator_tag, _BaseIterator>, | |
::std::conditional_t<_IsBackwards, ::std::bidirectional_iterator_tag, ::std::forward_iterator_tag>, | |
__iterator_category_t<_BaseIterator>>; | |
////// | |
/// @brief The strength of the iterator concept, as defined in relation to the base. | |
/// | |
////// | |
using iterator_concept = ::std::conditional_t< | |
__is_iterator_concept_or_better_v<::std::bidirectional_iterator_tag, _BaseIterator>, | |
::std::conditional_t<_IsBackwards, ::std::bidirectional_iterator_tag, ::std::forward_iterator_tag>, | |
__iterator_concept_t<_BaseIterator>>; | |
////// | |
/// @brief The object type that gets output on every dereference. | |
/// | |
////// | |
using value_type = ::std::conditional_t<_EncodeOrDecode == __transaction::__encode, | |
code_unit_t<_Encoding>, code_point_t<_Encoding>>; | |
////// | |
/// @brief A pointer type to the value_type. | |
/// | |
////// | |
using pointer = value_type*; | |
////// | |
/// @brief The value returned from derefencing the iterator. | |
/// | |
/// @remarks This is a proxy iterator, so the @c reference is a non-reference @c value_type. | |
////// | |
using reference = value_type; | |
////// | |
/// @brief The type returned when two of these pointers are subtracted from one another. | |
/// | |
/// @remarks It's not a very useful type... | |
////// | |
using difference_type = __iterator_difference_type_t<_BaseIterator>; | |
constexpr __encoding_iterator() noexcept(::std::is_nothrow_default_constructible_v< | |
encoding_type>&& ::std::is_nothrow_default_constructible_v<error_handler_type>&& ::std:: | |
is_nothrow_default_constructible_v<range_type>&& noexcept( | |
__base_state_t(::std::declval<encoding_type&>()))) | |
: __base_encoding_t() | |
, __base_error_handler_t() | |
, __base_state_t(this->encoding()) | |
, __base_cursor_cache_t() | |
, __base_error_cache_t() | |
, __base_range_t() | |
, _M_cache() { | |
} | |
constexpr __encoding_iterator(const __encoding_iterator&) = default; | |
constexpr __encoding_iterator(__encoding_iterator&&) = default; | |
template <typename _ArgRange, | |
::std::enable_if_t< | |
!::std::is_same_v<__txt_detail::__remove_cvref_t<_ArgRange>, __encoding_iterator>>* = nullptr> | |
constexpr __encoding_iterator(_ArgRange&& __range) noexcept( | |
noexcept(__encoding_iterator(::std::declval<range_type>(), ::std::declval<encoding_type>(), | |
::std::declval<error_handler_type>()))) | |
: __encoding_iterator(::std::forward<_ArgRange>(__range), encoding_type {}, error_handler_type {}) { | |
} | |
constexpr __encoding_iterator(range_type __range, encoding_type __encoding) noexcept( | |
noexcept(__encoding_iterator(::std::declval<range_type>(), ::std::declval<encoding_type>(), | |
::std::declval<error_handler_type>()))) | |
: __encoding_iterator(::std::move(__range), ::std::move(__encoding), error_handler_type {}) { | |
} | |
constexpr __encoding_iterator(range_type __range, error_handler_type __error_handler) noexcept( | |
noexcept(__encoding_iterator(::std::declval<range_type>(), ::std::declval<encoding_type>(), | |
::std::declval<error_handler_type>()))) | |
: __encoding_iterator(::std::move(__range), encoding_type {}, ::std::move(__error_handler)) { | |
} | |
constexpr __encoding_iterator(range_type __range, encoding_type __encoding, | |
error_handler_type | |
__error_handler) noexcept(::std::is_nothrow_move_constructible_v<encoding_type>&& ::std:: | |
is_nothrow_move_constructible_v<error_handler_type>&& ::std::is_nothrow_move_constructible_v< | |
range_type>&& noexcept(__base_state_t(::std::declval<encoding_type&>()))) | |
: __base_encoding_t(::std::move(__encoding)) | |
, __base_error_handler_t(::std::move(__error_handler)) | |
, __base_state_t(this->encoding()) | |
, __base_cursor_cache_t() | |
, __base_error_cache_t() | |
, __base_range_t(::std::move(__range)) | |
, _M_cache() { | |
this->_M_read_one(); | |
} | |
constexpr __encoding_iterator(range_type __range, encoding_type __encoding, | |
error_handler_type __error_handler, | |
state_type __state) noexcept(::std::is_nothrow_move_constructible_v<encoding_type>&& ::std:: | |
is_nothrow_move_constructible_v<error_handler_type>&& ::std::is_nothrow_move_constructible_v< | |
range_type>&& noexcept(__base_state_t(::std::declval<encoding_type&>(), | |
::std::declval<state_type>()))) | |
: __base_encoding_t(::std::move(__encoding)) | |
, __base_error_handler_t(::std::move(__error_handler)) | |
, __base_state_t(this->encoding(), ::std::move(__state)) | |
, __base_cursor_cache_t() | |
, __base_error_cache_t() | |
, __base_range_t(::std::move(__range)) | |
, _M_cache() { | |
this->_M_read_one(); | |
} | |
// assignment | |
constexpr __encoding_iterator& operator=(const __encoding_iterator&) = default; | |
constexpr __encoding_iterator& operator=(__encoding_iterator&&) = default; | |
////// | |
/// @brief The encoding object. | |
/// | |
/// @returns A const l-value reference to the encoding object used to construct this iterator. | |
////// | |
constexpr const encoding_type& encoding() const noexcept { | |
return this->__base_encoding_t::__get_value(); | |
} | |
////// | |
/// @brief The encoding object. | |
/// | |
/// @returns An l-value reference to the encoding object used to construct this iterator. | |
////// | |
constexpr encoding_type& encoding() noexcept { | |
return this->__base_encoding_t::__get_value(); | |
} | |
////// | |
/// @brief The state object. | |
/// | |
/// @returns A const l-value reference to the state object used to construct this iterator. | |
////// | |
constexpr const state_type& state() const noexcept { | |
return this->__base_state_t::_M_get_state(); | |
} | |
////// | |
/// @brief The state object. | |
/// | |
/// @returns An l-value reference to the state object used to construct this iterator. | |
////// | |
constexpr state_type& state() noexcept { | |
return this->__base_state_t::_M_get_state(); | |
} | |
////// | |
/// @brief The error handler object. | |
/// | |
/// @returns A const l-value reference to the error handler used to construct this iterator. | |
////// | |
constexpr const error_handler_type& handler() const& noexcept { | |
return this->__base_error_handler_t::__get_value(); | |
} | |
////// | |
/// @brief The error handler object. | |
/// | |
/// @returns An l-value reference to the error handler used to construct this iterator. | |
////// | |
constexpr error_handler_type& handler() & noexcept { | |
return this->__base_error_handler_t::__get_value(); | |
} | |
////// | |
/// @brief The error handler object. | |
/// | |
/// @returns An l-value reference to the error handler used to construct this iterator. | |
////// | |
constexpr error_handler_type&& handler() && noexcept { | |
return ::std::move(this->__base_error_handler_t::__get_value()); | |
} | |
////// | |
/// @brief The input range used to construct this object. | |
/// | |
/// @returns A const l-value reference to the input range used to construct this iterator. | |
////// | |
constexpr range_type range() const& noexcept(::std::is_nothrow_move_constructible_v<range_type>) { | |
return this->__base_range_t::__get_value(); | |
} | |
////// | |
/// @brief The input range used to construct this object. | |
/// | |
////// | |
constexpr range_type range() & noexcept(::std::is_copy_constructible_v<range_type> | |
? ::std::is_nothrow_copy_constructible_v<range_type> | |
: ::std::is_nothrow_move_constructible_v<range_type>) { | |
if constexpr (::std::is_copy_constructible_v<range_type>) { | |
return this->__base_range_t::__get_value(); | |
} | |
else { | |
return ::std::move(this->__base_range_t::__get_value()); | |
} | |
} | |
////// | |
/// @brief The input range used to construct this object. | |
/// | |
/// @returns An r-value reference to the input range used to construct this iterator. | |
////// | |
constexpr range_type range() && noexcept(::std::is_nothrow_move_constructible_v<range_type>) { | |
return ::std::move(this->__base_range_t::__get_value()); | |
} | |
////// | |
/// @brief Returns whether the last read operation had an encoding error or not. | |
/// | |
/// @returns The ztd::text::encoding_error that occurred. This can be ztd::text::encoding_error::ok for | |
/// an operation that went just fine. | |
/// | |
/// @remarks If the error handler is identified as an error handler that, if given a suitably sized | |
/// buffer, will never return an error. This is the case with specific encoding operations with | |
/// ztd::text::replacement_handler, or ztd::text::throw_handler. | |
////// | |
constexpr encoding_error error_code() const noexcept { | |
if constexpr (_IsErrorless) { | |
return encoding_error::ok; | |
} | |
else { | |
return this->__base_error_cache_t::_M_error_code; | |
} | |
} | |
////// | |
/// @brief Increment a copy of the iterator. | |
/// | |
/// @returns A copy to the incremented iterator. | |
////// | |
constexpr _Derived operator++(int) { | |
_Derived __copy = this->_M_derived(); | |
++__copy; | |
return __copy; | |
} | |
////// | |
/// @brief Increment the iterator. | |
/// | |
/// @returns A reference to *this, after incrementing the iterator. | |
////// | |
constexpr _Derived& operator++() { | |
if constexpr (_IsSingleValueType) { | |
this->_M_read_one(); | |
} | |
else { | |
++this->__base_cursor_cache_t::_M_position; | |
if (this->__base_cursor_cache_t::_M_position == this->__base_cursor_cache_t::_M_size) { | |
this->_M_read_one(); | |
} | |
} | |
return this->_M_derived(); | |
} | |
////// | |
/// @brief Dereference the iterator. | |
/// | |
/// @remarks This is a proxy iterator, and therefore only returns a const value_type& object and not a | |
/// non-const reference object. This is deliberately to work around the standard not allowing stand-alone | |
/// proxy iterators that do not return reference types. Encoding iterators are only readable, not | |
/// writable. | |
////// | |
constexpr reference operator*() const noexcept { | |
if constexpr (_IsSingleValueType) { | |
return this->_M_cache[0]; | |
} | |
else { | |
return this->_M_cache[this->__base_cursor_cache_t::_M_position]; | |
} | |
} | |
// observers: comparison | |
////// | |
/// @brief Compares whether or not this iterator has truly reached the end. | |
/// | |
////// | |
friend constexpr bool operator==(const _Derived& __it, const __encoding_sentinel_t&) { | |
if constexpr (_IsCursorless || (_IsInputOrOutput && _IsSingleValueType)) { | |
return __it._M_base_is_empty() | |
&& static_cast<__base_cursor_cache_size_t>(__txt_detail::_CursorlessSizeSentinel) | |
== __it.__base_cursor_cache_t::_M_size; | |
} | |
else { | |
return __it._M_base_is_empty() | |
&& __it.__base_cursor_cache_t::_M_position == __it.__base_cursor_cache_t::_M_size; | |
} | |
} | |
////// | |
/// @brief Compares whether or not this iterator has truly reached the end. | |
/// | |
////// | |
friend constexpr bool operator==(const __encoding_sentinel_t& __sen, const _Derived& __it) { | |
return __it == __sen; | |
} | |
////// | |
/// @brief Compares whether or not this iterator has truly reached the end. | |
/// | |
////// | |
friend constexpr bool operator!=(const _Derived& __it, const __encoding_sentinel_t&) { | |
if constexpr (_IsCursorless || (_IsInputOrOutput && _IsSingleValueType)) { | |
return !__it._M_base_is_empty() | |
|| static_cast<__base_cursor_cache_size_t>(__txt_detail::_CursorlessSizeSentinel) | |
!= __it.__base_cursor_cache_t::_M_size; | |
} | |
else { | |
return !__it._M_base_is_empty() | |
|| __it.__base_cursor_cache_t::_M_position != __it.__base_cursor_cache_t::_M_size; | |
} | |
} | |
////// | |
/// @brief Compares whether or not this iterator has truly reached the end. | |
/// | |
////// | |
friend constexpr bool operator!=(const __encoding_sentinel_t& __sen, const _Derived& __it) noexcept { | |
return __it != __sen; | |
} | |
private: | |
constexpr bool _M_base_is_empty() const noexcept { | |
if constexpr (__is_detected_v<__detect_adl_empty, _Range>) { | |
return __adl::__adl_empty(this->__base_range_t::__get_value()); | |
} | |
else { | |
return __adl::__adl_begin(this->__base_range_t::__get_value()) | |
== __adl::__adl_end(this->__base_range_t::__get_value()); | |
} | |
} | |
constexpr void _M_read_one() { | |
if (this->_M_base_is_empty()) { | |
if constexpr (_IsCursorless || (_IsSingleValueType && _IsInputOrOutput)) { | |
this->__base_cursor_cache_t::_M_size | |
= static_cast<__base_cursor_cache_size_t>(_CursorlessSizeSentinel); | |
} | |
else { | |
this->__base_cursor_cache_t::_M_size | |
= static_cast<__base_cursor_cache_size_t>(this->_M_cache.size()); | |
this->__base_cursor_cache_t::_M_position | |
= static_cast<__base_cursor_cache_size_t>(this->_M_cache.size()); | |
} | |
return; | |
} | |
auto& __this_input_range = this->_M_range(); | |
auto __this_cache_begin = this->_M_cache.data(); | |
[[maybe_unused]] decltype(__this_cache_begin) __this_cache_end {}; | |
::ztd::text::span<value_type, _MaxValues> __cache_view(this->_M_cache); | |
if constexpr (_IsInputOrOutput) { | |
auto __result = __basic_encode_or_decode_one<__consume::__no, _EncodeOrDecode>( | |
::std::move(__this_input_range), this->encoding(), __cache_view, this->handler(), | |
this->state()); | |
__this_cache_end = __adl::__adl_to_address(__adl::__adl_begin(__result.output)); | |
if constexpr (!_IsErrorless) { | |
this->__base_error_cache_t::_M_error_code = __result.error_code; | |
} | |
this->__base_range_t::__get_value() = ::std::move(__result.input); | |
} | |
else { | |
auto __result = __basic_encode_or_decode_one<__consume::__no, _EncodeOrDecode>( | |
::std::move(__this_input_range), this->encoding(), __cache_view, this->handler(), | |
this->state()); | |
__this_cache_end = __adl::__adl_to_address(__adl::__adl_begin(__result.output)); | |
if constexpr (!_IsErrorless) { | |
this->__base_error_cache_t::_M_error_code = __result.error_code; | |
} | |
this->__base_range_t::__get_value() = ::std::move(__result.input); | |
} | |
if constexpr (!_IsSingleValueType) { | |
__base_cursor_cache_size_t __data_size | |
= static_cast<__base_cursor_cache_size_t>(__this_cache_end - __this_cache_begin); | |
ZTD_TEXT_ASSERT_MESSAGE_I_("size of produced value can never be bigger thanthe cache", | |
static_cast<::std::size_t>(__data_size) <= this->_M_cache.size()); | |
this->__base_cursor_cache_t::_M_position = static_cast<__base_cursor_cache_size_t>(0); | |
this->__base_cursor_cache_t::_M_size = __data_size; | |
} | |
} | |
constexpr _Derived& _M_derived() noexcept { | |
return static_cast<_Derived&>(*this); | |
} | |
constexpr const _Derived& _M_derived() const noexcept { | |
return static_cast<const _Derived&>(*this); | |
} | |
constexpr _URange& _M_range() noexcept { | |
return this->__base_range_t::__get_value(); | |
} | |
constexpr const _URange& _M_range() const noexcept { | |
return this->__base_range_t::__get_value(); | |
} | |
::std::array<value_type, _MaxValues> _M_cache; | |
}; | |
} // namespace __txt_detail | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/detail/encoding_iterator.hpp | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @brief The encode sentinel to use as the @c end value for a ztd::text::encode_iterator. | |
/// | |
////// | |
using encode_sentinel_t = __txt_detail::__encoding_sentinel_t; | |
////// | |
/// @brief An iterator over an iterator of code points, presenting the code points as code units. Uses the @p | |
/// _Encoding specified to do so. | |
/// | |
/// @tparam _Encoding The encoding to read the underlying range of code points as. | |
/// @tparam _Range The range of input that will be fed into the _FromEncoding's decode operation. | |
/// @tparam _ErrorHandler The error handler for any encode-step failures. | |
/// @tparam _State The state type to use for the encode operations to intermediate code points. | |
/// | |
/// @remarks This type produces proxies as their reference type, and are only readable, not writable iterators. The | |
/// iterator presents code units one at a time, regardless of how many code units are output by one decode | |
/// operation. This means if, for example, one (1) UTF-32 code point becomes four (4) UTF-8 code units, it will | |
/// present each code unit one at a time. If you are looking to explicitly know what a single encode operation maps | |
/// into as far as number of code points to code units (and vice-versa), you will have to use lower-level | |
/// interfaces. | |
////// | |
template <typename _Encoding, typename _Range, typename _ErrorHandler = default_handler, | |
typename _State = encode_state_t<_Encoding>> | |
class encode_iterator | |
: public __txt_detail::__encoding_iterator<__txt_detail::__transaction::__encode, | |
encode_iterator<_Encoding, _Range, _ErrorHandler, _State>, _Encoding, _Range, _ErrorHandler, _State> { | |
private: | |
using __iterator_base_it = __txt_detail::__encoding_iterator<__txt_detail::__transaction::__encode, | |
encode_iterator<_Encoding, _Range, _ErrorHandler, _State>, _Encoding, _Range, _ErrorHandler, _State>; | |
public: | |
////// | |
/// @brief The underlying range type. | |
/// | |
////// | |
using range_type = typename __iterator_base_it::range_type; | |
////// | |
/// @brief The base iterator type. | |
/// | |
////// | |
using iterator = typename __iterator_base_it::iterator; | |
////// | |
/// @brief The encoding type used for transformations. | |
/// | |
////// | |
using encoding_type = typename __iterator_base_it::encoding_type; | |
////// | |
/// @brief The error handler when an encode operation fails. | |
/// | |
////// | |
using error_handler_type = typename __iterator_base_it::error_handler_type; | |
////// | |
/// @brief The state type used for encode operations. | |
/// | |
////// | |
using state_type = typename __iterator_base_it::state_type; | |
////// | |
/// @brief The strength of the iterator category, as defined in relation to the base. | |
/// | |
////// | |
using iterator_category = typename __iterator_base_it::iterator_category; | |
////// | |
/// @brief The strength of the iterator concept, as defined in relation to the base. | |
/// | |
////// | |
using iterator_concept = typename __iterator_base_it::iterator_concept; | |
////// | |
/// @brief The object type that gets output on every dereference. | |
/// | |
////// | |
using value_type = typename __iterator_base_it::value_type; | |
////// | |
/// @brief A pointer type to the value_type. | |
/// | |
////// | |
using pointer = typename __iterator_base_it::pointer; | |
////// | |
/// @brief The value returned from derefencing the iterator. | |
/// | |
/// @remarks This is a proxy iterator, so the @c reference is a non-reference @c value_type. | |
////// | |
using reference = typename __iterator_base_it::value_type; | |
////// | |
/// @brief The type returned when two of these pointers are subtracted from one another. | |
/// | |
/// @remarks It's not a very useful type... | |
////// | |
using difference_type = typename __iterator_base_it::difference_type; | |
////// | |
/// @brief Default constructor. Defaulted. | |
/// | |
////// | |
constexpr encode_iterator() = default; | |
////// | |
/// @brief Copy constructor. Defaulted. | |
/// | |
////// | |
constexpr encode_iterator(const encode_iterator&) = default; | |
////// | |
/// @brief Move constructor. Defaulted. | |
/// | |
////// | |
constexpr encode_iterator(encode_iterator&&) = default; | |
////// | |
/// @brief Constructs a ztd::text::decode_iterator from the explicitly given @p __range. | |
/// | |
/// @param[in] __range The range value that will be read from. | |
/// | |
/// @remarks Each argument is moved/forwarded in. | |
////// | |
template <typename _ArgRange, | |
::std::enable_if_t< | |
!::std::is_same_v<__txt_detail::__remove_cvref_t<_ArgRange>, encode_iterator>>* = nullptr> | |
constexpr encode_iterator(_ArgRange&& __range) noexcept( | |
::std::is_nothrow_constructible_v<__iterator_base_it, range_type>) | |
: __iterator_base_it(::std::forward<_ArgRange>(__range)) { | |
} | |
////// | |
/// @brief Constructs a ztd::text::encode_iterator from the explicitly given @p __range, and @p __encoding. | |
/// | |
/// @param[in] __range The range value that will be read from. | |
/// @param[in] __encoding The encoding object to use. | |
/// | |
/// @remarks Each argument is moved in. | |
////// | |
constexpr encode_iterator(range_type __range, encoding_type __encoding) noexcept( | |
::std::is_nothrow_constructible_v<__iterator_base_it, range_type, encoding_type>) | |
: __iterator_base_it(::std::move(__range), ::std::move(__encoding), error_handler_type {}) { | |
} | |
////// | |
/// @brief Constructs a ztd::text::encode_iterator from the explicitly given @p __range, and @p | |
/// __error_handler. | |
/// | |
/// @param[in] __range The range value that will be read from. | |
/// @param[in] __error_handler The error handler to use for reporting errors. | |
/// | |
/// @remarks Each argument is moved in. | |
////// | |
constexpr encode_iterator(range_type __range, error_handler_type __error_handler) noexcept( | |
::std::is_nothrow_constructible_v<__iterator_base_it, range_type, error_handler_type>) | |
: __iterator_base_it(::std::move(__range), encoding_type {}, ::std::move(__error_handler)) { | |
} | |
////// | |
/// @brief Constructs a ztd::text::encode_iterator from the explicitly given @p __range, @p __encoding, and | |
/// @p __error_handler. | |
/// | |
/// @param[in] __range The range value that will be read from. | |
/// @param[in] __encoding The encoding object to use. | |
/// @param[in] __error_handler The error handler to use for reporting errors. | |
/// | |
/// @remarks Each argument is moved in. | |
////// | |
constexpr encode_iterator(range_type __range, encoding_type __encoding, | |
error_handler_type __error_handler) noexcept(::std::is_nothrow_constructible_v<__iterator_base_it, | |
range_type, encoding_type, error_handler_type>) | |
: __iterator_base_it(::std::move(__range), ::std::move(__encoding), ::std::move(__error_handler)) { | |
} | |
////// | |
/// @brief Constructs a ztd::text::encode_iterator from the explicitly given @p __range, @p __encoding, @p | |
/// __error_handler and @p __state. | |
/// | |
/// @param[in] __range The range value that will be read from. | |
/// @param[in] __encoding The encoding object to use. | |
/// @param[in] __error_handler The error handler to use for reporting errors. | |
/// @param[in] __state The current state. | |
/// | |
/// @remarks Each argument is moved in. | |
////// | |
constexpr encode_iterator(range_type __range, encoding_type __encoding, error_handler_type __error_handler, | |
state_type __state) noexcept(::std::is_nothrow_constructible_v<__iterator_base_it, range_type, | |
encoding_type, error_handler_type, state_type>) | |
: __iterator_base_it( | |
::std::move(__range), ::std::move(__encoding), ::std::move(__error_handler), ::std::move(__state)) { | |
} | |
////// | |
/// @brief Copy assignment operator. Defaulted. | |
/// | |
////// | |
constexpr encode_iterator& operator=(const encode_iterator&) = default; | |
////// | |
/// @brief Move assignment operator. Defaulted. | |
/// | |
////// | |
constexpr encode_iterator& operator=(encode_iterator&&) = default; | |
}; | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/encode_iterator.hpp | |
#include <string_view> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_ranges Ranges, Views, and Iterators | |
/// @{ | |
////// | |
////// | |
/// @brief A view over a range of code points, presenting the code points as code units. Uses the @p _Encoding | |
/// specified to do so. | |
/// | |
/// @tparam _Encoding The encoding to read the underlying range of code points as. | |
/// @tparam _Range The range of input that will be fed into the _FromEncoding's decode operation. | |
/// @tparam _ErrorHandler The error handler for any encode-step failures. | |
/// @tparam _State The state type to use for the encode operations to intermediate code points. | |
/// | |
/// @remarks The view presents code units one at a time, regardless of how many code units are output by one decode | |
/// operation. This means if, for example, one (1) UTF-32 code point becomes four (4) UTF-8 code units, it will | |
/// present each code unit one at a time. If you are looking to explicitly know what a single encode operation maps | |
/// into as far as number of code points to code units (and vice-versa), you will have to use lower-level | |
/// interfaces. | |
////// | |
template <typename _Encoding, typename _Range = ::std::basic_string_view<code_point_t<_Encoding>>, | |
typename _ErrorHandler = default_handler, typename _State = encode_state_t<_Encoding>> | |
class encode_view { | |
private: | |
using _StoredRange = __txt_detail::__range_reconstruct_t<__txt_detail::__remove_cvref_t<_Range>>; | |
public: | |
////// | |
/// @brief The iterator type for this view. | |
/// | |
////// | |
using iterator = encode_iterator<_Encoding, _StoredRange, _ErrorHandler, _State>; | |
////// | |
/// @brief The sentinel type for this view. | |
/// | |
////// | |
using sentinel = encode_sentinel_t; | |
////// | |
/// @brief The underlying range type. | |
/// | |
////// | |
using range_type = _Range; | |
////// | |
/// @brief The encoding type used for transformations. | |
/// | |
////// | |
using encoding_type = _Encoding; | |
////// | |
/// @brief The error handler when an encode operation fails. | |
/// | |
////// | |
using error_handler_type = _ErrorHandler; | |
////// | |
/// @brief The state type used for encode operations. | |
/// | |
////// | |
using state_type = encode_state_t<encoding_type>; | |
////// | |
/// @brief Default constructor. Defaulted. | |
/// | |
////// | |
constexpr encode_view() = default; | |
////// | |
/// @brief Copy constructor. Defaulted. | |
/// | |
////// | |
constexpr encode_view(const encode_view&) = default; | |
////// | |
/// @brief Move constructor. Defaulted. | |
/// | |
////// | |
constexpr encode_view(encode_view&&) = default; | |
////// | |
/// @brief Constructs an encode_view from the underlying range. | |
/// | |
/// @param[in] __range The input range to wrap and iterate over. | |
/// | |
/// @remarks the stored encoding, error handler, and state type are default-constructed. | |
////// | |
template <typename _ArgRange, | |
::std::enable_if_t< | |
!::std::is_same_v<__txt_detail::__remove_cvref_t<_ArgRange>, | |
encode_view> && !::std::is_same_v<__txt_detail::__remove_cvref_t<_ArgRange>, iterator>>* = nullptr> | |
constexpr encode_view(_ArgRange&& __range) noexcept(::std::is_nothrow_constructible_v<iterator, _ArgRange>) | |
: _M_it(::std::forward<_ArgRange>(__range)) { | |
} | |
////// | |
/// @brief Constructs an encode_view from the underlying range. | |
/// | |
/// @param[in] __range The input range to wrap and iterate over. | |
/// @param[in] __encoding The encoding object to call `.encode` or equivalent functionality on. | |
////// | |
constexpr encode_view(range_type __range, encoding_type __encoding) noexcept( | |
::std::is_nothrow_constructible_v<iterator, range_type, encoding_type>) | |
: _M_it(::std::move(__range), ::std::move(__encoding)) { | |
} | |
////// | |
/// @brief Constructs an encode_view from the underlying range. | |
/// | |
/// @param[in] __range The input range to wrap and iterate over. | |
/// @param[in] __encoding The encoding object to call `.encode` or equivalent functionality on. | |
/// @param[in] __error_handler A previously-made encode_view iterator. | |
////// | |
constexpr encode_view(range_type __range, encoding_type __encoding, | |
error_handler_type __error_handler) noexcept(::std::is_nothrow_constructible_v<iterator, range_type, | |
encoding_type, error_handler_type>) | |
: _M_it(::std::move(__range), ::std::move(__encoding), ::std::move(__error_handler)) { | |
} | |
////// | |
/// @brief Constructs an encode_view from the underlying range. | |
/// | |
/// @param[in] __range The input range to wrap and iterate over. | |
/// @param[in] __encoding The encoding object to call `.encode` or equivalent functionality on. | |
/// @param[in] __error_handler A previously-made encode_view iterator. | |
/// @param[in] __state The state to user for the encode operation. | |
////// | |
constexpr encode_view(range_type __range, encoding_type __encoding, error_handler_type __error_handler, | |
state_type __state) noexcept(::std::is_nothrow_constructible_v<iterator, range_type, encoding_type, | |
error_handler_type, state_type>) | |
: _M_it(::std::move(__range), ::std::move(__encoding), ::std::move(__error_handler), ::std::move(__state)) { | |
} | |
////// | |
/// @brief Constructs an encoding_view from one of its iterators, reconstituting the range. | |
/// | |
/// @param[in] __it A previously-made decode_view iterator. | |
////// | |
constexpr encode_view(iterator __it) noexcept(::std::is_nothrow_move_constructible_v<iterator>) | |
: _M_it(::std::move(__it)) { | |
} | |
////// | |
/// @brief Copy assignment operator. Defaulted. | |
/// | |
////// | |
constexpr encode_view& operator=(const encode_view&) = default; | |
////// | |
/// @brief Move assignment operator. Defaulted. | |
/// | |
////// | |
constexpr encode_view& operator=(encode_view&&) = default; | |
////// | |
/// @brief The beginning of the range. Uses a sentinel type and not a special iterator. | |
/// | |
////// | |
constexpr iterator begin() & noexcept { | |
if constexpr (::std::is_copy_constructible_v<iterator>) { | |
return this->_M_it; | |
} | |
else { | |
return ::std::move(this->_M_it); | |
} | |
} | |
////// | |
/// @brief The beginning of the range. Uses a sentinel type and not a special iterator. | |
/// | |
////// | |
constexpr iterator begin() const& noexcept { | |
return this->_M_it; | |
} | |
////// | |
/// @brief The beginning of the range. Uses a sentinel type and not a special iterator. | |
////// | |
constexpr iterator begin() && noexcept { | |
return ::std::move(this->_M_it); | |
} | |
////// | |
/// @brief The end of the range. Uses a sentinel type and not a special iterator. | |
////// | |
constexpr sentinel end() const noexcept { | |
return sentinel(); | |
} | |
private: | |
iterator _M_it; | |
}; | |
////// | |
/// @brief The reconstruct extension point for rebuilding an encoding view from its iterator and sentinel | |
/// type. | |
////// | |
template <typename _Encoding, typename _Range, typename _ErrorHandler, typename _State> | |
constexpr encode_view<_Encoding, _Range, _ErrorHandler, _State> reconstruct( | |
::std::in_place_type_t<encode_view<_Encoding, _Range, _ErrorHandler, _State>>, | |
typename encode_view<_Encoding, _Range, _ErrorHandler, _State>::iterator __it, | |
typename encode_view<_Encoding, _Range, _ErrorHandler, _State>::sentinel) noexcept(::std:: | |
is_nothrow_constructible_v<encode_view<_Encoding, _Range, _ErrorHandler, _State>, | |
typename encode_view<_Encoding, _Range, _ErrorHandler, _State>::iterator&&>) { | |
return encode_view<_Encoding, _Range, _ErrorHandler, _State>(::std::move(__it)); | |
} | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_CONCEPTS_I_) && ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_RANGES_I_) | |
namespace std { namespace ranges { | |
template <typename _Encoding, typename _Range, typename _ErrorHandler, typename _State> | |
inline constexpr bool enable_borrowed_range<::ztd::text::encode_view<_Encoding, _Range, _ErrorHandler, | |
_State>> = ::std::ranges::enable_borrowed_range<_Range>; | |
}} // namespace std::ranges | |
#endif | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/encode_view.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/decode_view.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/decode_iterator.hpp | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_ranges Ranges, Views, and Iterators | |
/// @{ | |
////// | |
////// | |
/// @brief The decode sentinel to use as the @c end value for a ztd::text::decode_iterator. | |
/// | |
////// | |
using decode_sentinel_t = __txt_detail::__encoding_sentinel_t; | |
////// | |
/// @brief An iterator over a range of code points, presented as a range of code units, using the @p _Encoding | |
/// specified to do so. | |
/// | |
/// @tparam _Encoding The encoding to read the underlying range of code points as. | |
/// @tparam _Range The range of input that will be fed into the _FromEncoding's decode operation. | |
/// @tparam _ErrorHandler The error handler for any encode-step failures. | |
/// @tparam _State The state type to use for the encode operations to intermediate code points. | |
/// | |
/// @remarks This type produces proxies as their reference type, and are only readable, not writable iterators. The | |
/// iterator presents code point one at a time, regardless of how many code points are output by one decode | |
/// operation. This means if, for example, four (4) UTF-8 code units becomes two (2) UTF-16 code points, it will | |
/// present one code point at a time. If you are looking to explicitly know what a single decode operation maps | |
/// into as far as number of code points to code units (and vice-versa), you will have to use lower-level | |
/// interfaces. | |
////// | |
template <typename _Encoding, typename _Range, typename _ErrorHandler = default_handler, | |
typename _State = decode_state_t<_Encoding>> | |
class decode_iterator | |
: public __txt_detail::__encoding_iterator<__txt_detail::__transaction::__decode, | |
decode_iterator<_Encoding, _Range, _ErrorHandler, _State>, _Encoding, _Range, _ErrorHandler, _State> { | |
private: | |
using __iterator_base_it = __txt_detail::__encoding_iterator<__txt_detail::__transaction::__decode, | |
decode_iterator<_Encoding, _Range, _ErrorHandler, _State>, _Encoding, _Range, _ErrorHandler, _State>; | |
public: | |
////// | |
/// @brief The underlying range type. | |
/// | |
////// | |
using range_type = typename __iterator_base_it::range_type; | |
////// | |
/// @brief The base iterator type. | |
/// | |
////// | |
using iterator = typename __iterator_base_it::iterator; | |
////// | |
/// @brief The encoding type used for transformations. | |
/// | |
////// | |
using encoding_type = typename __iterator_base_it::encoding_type; | |
////// | |
/// @brief The error handler when an encode operation fails. | |
/// | |
////// | |
using error_handler_type = typename __iterator_base_it::error_handler_type; | |
////// | |
/// @brief The state type used for encode operations. | |
/// | |
////// | |
using state_type = typename __iterator_base_it::state_type; | |
////// | |
/// @brief The strength of the iterator category, as defined in relation to the base. | |
/// | |
////// | |
using iterator_category = typename __iterator_base_it::iterator_category; | |
////// | |
/// @brief The strength of the iterator concept, as defined in relation to the base. | |
/// | |
////// | |
using iterator_concept = typename __iterator_base_it::iterator_concept; | |
////// | |
/// @brief The object type that gets output on every dereference. | |
/// | |
////// | |
using value_type = typename __iterator_base_it::value_type; | |
////// | |
/// @brief A pointer type to the value_type. | |
/// | |
////// | |
using pointer = typename __iterator_base_it::pointer; | |
////// | |
/// @brief The value returned from derefencing the iterator. | |
/// | |
/// @remarks This is a proxy iterator, so the @c reference is a non-reference @c value_type. | |
////// | |
using reference = typename __iterator_base_it::value_type; | |
////// | |
/// @brief The type returned when two of these pointers are subtracted from one another. | |
/// | |
/// @remarks It's not a very useful type... | |
////// | |
using difference_type = typename __iterator_base_it::difference_type; | |
////// | |
/// @brief Default constructor. Defaulted. | |
/// | |
////// | |
constexpr decode_iterator() = default; | |
////// | |
/// @brief Copy constructor. Defaulted. | |
/// | |
////// | |
constexpr decode_iterator(const decode_iterator&) = default; | |
////// | |
/// @brief Move constructor. Defaulted. | |
/// | |
////// | |
constexpr decode_iterator(decode_iterator&&) = default; | |
////// | |
/// @brief Constructs a ztd::text::decode_iterator from the explicitly given @p __range. | |
/// | |
/// @param[in] __range The range value that will be read from. | |
/// | |
/// @remarks Each argument is moved/forwarded in. | |
////// | |
template <typename _ArgRange, | |
::std::enable_if_t< | |
!::std::is_same_v<__txt_detail::__remove_cvref_t<_ArgRange>, decode_iterator>>* = nullptr> | |
constexpr decode_iterator(_ArgRange&& __range) noexcept( | |
::std::is_nothrow_constructible_v<__iterator_base_it, range_type>) | |
: __iterator_base_it(::std::forward<_ArgRange>(__range)) { | |
} | |
////// | |
/// @brief Constructs a ztd::text::decode_iterator from the explicitly given @p __range, and @p __encoding. | |
/// | |
/// @param[in] __range The range value that will be read from. | |
/// @param[in] __encoding The encoding object to use. | |
/// | |
/// @remarks Each argument is moved in. | |
////// | |
constexpr decode_iterator(range_type __range, encoding_type __encoding) noexcept( | |
::std::is_nothrow_constructible_v<__iterator_base_it, range_type, encoding_type>) | |
: __iterator_base_it(::std::move(__range), ::std::move(__encoding)) { | |
} | |
////// | |
/// @brief Constructs a ztd::text::decode_iterator from the explicitly given @p __range, and @p | |
/// __error_handler. | |
/// | |
/// @param[in] __range The range value that will be read from. | |
/// @param[in] __error_handler The error handler to use for reporting errors. | |
/// | |
/// @remarks Each argument is moved in. | |
////// | |
constexpr decode_iterator(range_type __range, error_handler_type __error_handler) noexcept( | |
::std::is_nothrow_constructible_v<__iterator_base_it, range_type, error_handler_type>) | |
: __iterator_base_it(::std::move(__range), ::std::move(__error_handler)) { | |
} | |
////// | |
/// @brief Constructs a ztd::text::decode_iterator from the explicitly given @p __range, @p __encoding, and | |
/// @p __error_handler. | |
/// | |
/// @param[in] __range The range value that will be read from. | |
/// @param[in] __encoding The encoding object to use. | |
/// @param[in] __error_handler The error handler to use for reporting errors. | |
/// | |
/// @remarks Each argument is moved in. | |
////// | |
constexpr decode_iterator(range_type __range, encoding_type __encoding, | |
error_handler_type __error_handler) noexcept(::std::is_nothrow_constructible_v<__iterator_base_it, | |
range_type, encoding_type, error_handler_type>) | |
: __iterator_base_it(::std::move(__range), ::std::move(__encoding), ::std::move(__error_handler)) { | |
} | |
////// | |
/// @brief Constructs a ztd::text::decode_iterator from the explicitly given @p __range, @p __encoding, @p | |
/// __error_handler and @p __state. | |
/// | |
/// @param[in] __range The range value that will be read from. | |
/// @param[in] __encoding The encoding object to use. | |
/// @param[in] __error_handler The error handler to use for reporting errors. | |
/// @param[in] __state The current state. | |
/// | |
/// @remarks Each argument is moved in. | |
////// | |
constexpr decode_iterator(range_type __range, encoding_type __encoding, error_handler_type __error_handler, | |
state_type __state) noexcept(::std::is_nothrow_constructible_v<__iterator_base_it, range_type, | |
encoding_type, error_handler_type, state_type>) | |
: __iterator_base_it( | |
::std::move(__range), ::std::move(__encoding), ::std::move(__error_handler), ::std::move(__state)) { | |
} | |
////// | |
/// @brief Copy assignment operator. Defaulted. | |
/// | |
////// | |
constexpr decode_iterator& operator=(const decode_iterator&) = default; | |
////// | |
/// @brief Move assignment operator. Defaulted. | |
/// | |
////// | |
constexpr decode_iterator& operator=(decode_iterator&&) = default; | |
}; | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/decode_iterator.hpp | |
#include <string_view> | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_ranges Ranges, Views, and Iterators | |
/// @{ | |
////// | |
////// | |
/// @brief A view over a range of code points, presenting the code points as code units. Uses the @p _Encoding | |
/// specified to do so. | |
/// | |
/// @tparam _Encoding The encoding to read the underlying range of code points as. | |
/// @tparam _Range The range of input that will be fed into the _FromEncoding's decode operation. | |
/// @tparam _ErrorHandler The error handler for any encode-step failures. | |
/// @tparam _State The state type to use for the encode operations to intermediate code points. | |
/// | |
/// @remarks The view presents code point one at a time, regardless of how many code points are output by one | |
/// decode operation. This means if, for example, four (4) UTF-8 code units becomes two (2) UTF-16 code points, it | |
/// will present one code point at a time. If you are looking to explicitly know what a single decode operation | |
/// maps into as far as number of code points to code units (and vice-versa), you will have to use lower-level | |
/// interfaces. | |
////// | |
template <typename _Encoding, typename _Range = ::std::basic_string_view<code_unit_t<_Encoding>>, | |
typename _ErrorHandler = default_handler, typename _State = decode_state_t<_Encoding>> | |
class decode_view { | |
private: | |
using _StoredRange = __txt_detail::__range_reconstruct_t<__txt_detail::__remove_cvref_t<_Range>>; | |
public: | |
////// | |
/// @brief The iterator type for this view. | |
/// | |
////// | |
using iterator = decode_iterator<_Encoding, _StoredRange, _ErrorHandler, _State>; | |
////// | |
/// @brief The sentinel type for this view. | |
/// | |
////// | |
using sentinel = decode_sentinel_t; | |
////// | |
/// @brief The underlying range type. | |
/// | |
////// | |
using range_type = _Range; | |
////// | |
/// @brief The encoding type used for transformations. | |
/// | |
////// | |
using encoding_type = _Encoding; | |
////// | |
/// @brief The error handler when a decode operation fails. | |
/// | |
////// | |
using error_handler_type = _ErrorHandler; | |
////// | |
/// @brief The state type used for decode operations. | |
/// | |
////// | |
using state_type = decode_state_t<encoding_type>; | |
////// | |
/// @brief Constructs a decode_view from the underlying range. | |
/// | |
/// @param[in] __range The input range to wrap and iterate over. | |
/// | |
/// @remarks The stored encoding, error handler, and state type are default-constructed. | |
////// | |
template <typename _ArgRange, | |
::std::enable_if_t< | |
!::std::is_same_v<__txt_detail::__remove_cvref_t<_ArgRange>, | |
decode_view> && !::std::is_same_v<__txt_detail::__remove_cvref_t<_ArgRange>, iterator>>* = nullptr> | |
constexpr decode_view(_ArgRange&& __range) noexcept(::std::is_nothrow_constructible_v<iterator, _ArgRange>) | |
: _M_it(::std::forward<_ArgRange>(__range)) { | |
} | |
////// | |
/// @brief Constructs a decode_view from the underlying range. | |
/// | |
/// @param[in] __range The input range to wrap and iterate over. | |
/// @param[in] __encoding The encoding object to call `.decode` or equivalent functionality on. | |
////// | |
constexpr decode_view(range_type __range, encoding_type __encoding) noexcept( | |
::std::is_nothrow_constructible_v<iterator, range_type, encoding_type>) | |
: _M_it(::std::move(__range), ::std::move(__encoding)) { | |
} | |
////// | |
/// @brief Constructs a decode_view from the underlying range. | |
/// | |
/// @param[in] __range The input range to wrap and iterate over. | |
/// @param[in] __encoding The encoding object to call `.decode` or equivalent functionality on. | |
/// @param[in] __error_handler The error handler to store in this view. | |
////// | |
constexpr decode_view(range_type __range, encoding_type __encoding, | |
error_handler_type __error_handler) noexcept(::std::is_nothrow_constructible_v<iterator, range_type, | |
encoding_type, error_handler_type>) | |
: _M_it(::std::move(__range), ::std::move(__encoding), ::std::move(__error_handler)) { | |
} | |
////// | |
/// @brief Constructs a decode_view from the underlying range. | |
/// | |
/// @param[in] __range The input range to wrap and iterate over. | |
/// @param[in] __encoding The encoding object to call `.decode` or equivalent functionality on. | |
/// @param[in] __error_handler The error handler to store in this view. | |
/// @param[in] __state The state to user for the decode operation. | |
////// | |
constexpr decode_view(range_type __range, encoding_type __encoding, error_handler_type __error_handler, | |
state_type __state) noexcept(::std::is_nothrow_constructible_v<iterator, range_type, encoding_type, | |
error_handler_type, state_type>) | |
: _M_it(::std::move(__range), ::std::move(__encoding), ::std::move(__error_handler), ::std::move(__state)) { | |
} | |
////// | |
/// @brief Constructs an encoding_view from one of its iterators, reconstituting the range. | |
/// | |
/// @param[in] __it A previously-made decode_view iterator. | |
////// | |
constexpr decode_view(iterator __it) noexcept(::std::is_nothrow_move_constructible_v<iterator>) | |
: _M_it(::std::move(__it)) { | |
} | |
////// | |
/// @brief Default constructor. Defaulted. | |
/// | |
////// | |
constexpr decode_view() = default; | |
////// | |
/// @brief Copy constructor. Defaulted. | |
/// | |
////// | |
constexpr decode_view(const decode_view&) = default; | |
////// | |
/// @brief Move constructor. Defaulted. | |
/// | |
////// | |
constexpr decode_view(decode_view&&) = default; | |
////// | |
/// @brief Copy assignment operator. Defaulted. | |
/// | |
////// | |
constexpr decode_view& operator=(const decode_view&) = default; | |
////// | |
/// @brief Move assignment operator. Defaulted. | |
/// | |
////// | |
constexpr decode_view& operator=(decode_view&&) = default; | |
////// | |
/// @brief The beginning of the range. Uses a sentinel type and not a special iterator. | |
/// | |
////// | |
constexpr iterator begin() & noexcept { | |
if constexpr (::std::is_copy_constructible_v<iterator>) { | |
return this->_M_it; | |
} | |
else { | |
return ::std::move(this->_M_it); | |
} | |
} | |
////// | |
/// @brief The beginning of the range. Uses a sentinel type and not a special iterator. | |
/// | |
////// | |
constexpr iterator begin() const& noexcept { | |
return this->_M_it; | |
} | |
////// | |
/// @brief The beginning of the range. Uses a sentinel type and not a special iterator. | |
/// | |
////// | |
constexpr iterator begin() && noexcept { | |
return ::std::move(this->_M_it); | |
} | |
////// | |
/// @brief The end of the range. Uses a sentinel type and not a special iterator. | |
/// | |
////// | |
constexpr sentinel end() const noexcept { | |
return sentinel(); | |
} | |
private: | |
iterator _M_it; | |
}; | |
////// | |
/// @brief The reconstruct extension point for rebuilding an encoding view from its iterator and sentinel | |
/// type. | |
////// | |
template <typename _Encoding, typename _Range, typename _ErrorHandler, typename _State> | |
constexpr decode_view<_Encoding, _Range, _ErrorHandler, _State> reconstruct( | |
::std::in_place_type_t<decode_view<_Encoding, _Range, _ErrorHandler, _State>>, | |
typename decode_view<_Encoding, _Range, _ErrorHandler, _State>::iterator __it, | |
typename decode_view<_Encoding, _Range, _ErrorHandler, _State>::sentinel) noexcept(::std:: | |
is_nothrow_constructible_v<decode_view<_Encoding, _Range, _ErrorHandler, _State>, | |
typename decode_view<_Encoding, _Range, _ErrorHandler, _State>::iterator&&>) { | |
return decode_view<_Encoding, _Range, _ErrorHandler, _State>(::std::move(__it)); | |
} | |
////// | |
/// @} | |
////// | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_CLOSE_I_ | |
}} // namespace ztd::text | |
#if ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_CONCEPTS_I_) && ZTD_TEXT_IS_ON(ZTD_TEXT_STD_LIBRARY_RANGES_I_) | |
namespace std { namespace ranges { | |
template <typename _Encoding, typename _Range, typename _ErrorHandler, typename _State> | |
inline constexpr bool enable_borrowed_range<::ztd::text::decode_view<_Encoding, _Range, _ErrorHandler, | |
_State>> = ::std::ranges::enable_borrowed_range<_Range>; | |
}} // namespace std::ranges | |
#endif | |
// end of D:/Sync/Cross/ztd/text/include/ztd/text/decode_view.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/transcode_view.hpp | |
// beginning of D:/Sync/Cross/ztd/text/include/ztd/text/transcode_iterator.hpp | |
namespace ztd { namespace text { | |
ZTD_TEXT_INLINE_ABI_NAMESPACE_OPEN_I_ | |
////// | |
/// @addtogroup ztd_text_ranges Ranges, Views, and Iterators | |
/// @{ | |
////// | |
////// | |
/// @brief A sentinel type that can be used to compare with a ztd::text::transcode_iterator. | |
/// | |
////// | |
using transcode_sentinel_t = __txt_detail::__encoding_sentinel_t; | |
////// | |
/// @brief A transcoding iterator that takes an input of code units and provides an output over the code units of | |
/// the desired @p _ToEncoding after converting from the @p _FromEncoding in a fashion that will never produce a | |
/// ztd::text::encoding_error::insufficient_output error. | |
/// | |
/// @tparam _FromEncoding The encoding to read the underlying range of code points as. | |
/// @tparam _ToEncoding The encoding to read the underlying range of code points as. | |
/// @tparam _Range The range of input that will be fed into the _FromEncoding's decode operation. | |
/// @tparam _FromErrorHandler The error handler for any decode-step failures. | |
/// @tparam _ToErrorHandler The error handler for any encode-step failures. | |
/// @tparam _FromState The state type to use for the decode operations to intermediate code points. | |
/// @tparam _ToState The state type to use for the encode operations to intermediate code points. | |
/// | |
/// @remarks This type produces proxies as their reference type, and are only readable, not writable iterators. The | |
/// type will also try many different shortcuts for decoding the input and encoding the intermediates, | |
/// respectively, including invoking a few customization points for either @c decode_one or @c encode_one . It | |
/// may also call @c transcode_one to bypass having to do the round-trip through two encodings, which an encoding | |
/// pair that a developer is interested in can use to do the conversion more quickly. The view presents code units | |
/// one at a time, regardless of how many code units are output by one decode operation. This means if, for | |
/// example, one (1) UTF-16 code unit becomes two (2) UTF-8 code units, it will present each code unit one at a | |
/// time. If you are looking to explicitly know each collection of characters, you will have to use lower-level | |
/// interfaces. | |
////// | |
template <typename _FromEncoding, typename _ToEncoding, typename _Range, typename _FromErrorHandler, | |
typename _ToErrorHandler, typename _FromState, typename _ToState> | |
class transcode_iterator | |
: private __txt_detail::__ebco<__txt_detail::__remove_cvref_t<_FromEncoding>, 0>, | |
private __txt_detail::__ebco<__txt_detail::__remove_cvref_t<_ToEncoding>, 1>, | |
private __txt_detail::__ebco<__txt_detail::__remove_cvref_t<_FromErrorHandler>, 2>, | |
private __txt_detail::__ebco<__txt_detail::__remove_cvref_t<_ToErrorHandler>, 3>, | |
private __txt_detail::__state_storage<__txt_detail::__remove_cvref_t<_FromEncoding>, | |
__txt_detail::__remove_cvref_t<_FromState>, 0>, | |
private __txt_detail::__state_storage<__txt_detail::__remove_cvref_t<_ToEncoding>, | |
__txt_detail::__remove_cvref_t<_ToState>, 1>, | |
private __txt_detail::__cursor_cache< | |
max_code_units_v<__txt_detail::__remove_cvref_t<__txt_detail::__unwrap_t<_ToEncoding>>>, | |
__txt_detail::__is_range_input_or_output_range_v< | |
__txt_detail::__remove_cvref_t<__txt_detail::__unwrap_t<_Range>>>>, | |
private __txt_detail::__error_cache< | |
decode_error_handler_always_returns_ok_v< | |
__txt_detail::__remove_cvref_t<__txt_detail::__unwrap_t<_FromEncoding>>, | |
__txt_detail::__remove_cvref_t<__txt_detail::__unwrap_t< | |
_FromErrorHandler>>> && encode_error_handler_always_returns_ok_v<__txt_detail::__remove_cvref_t<__txt_detail::__unwrap_t<_ToEncoding>>, __txt_detail::__remove_cvref_t<__txt_detail::__unwrap_t<_ToErrorHandler>>>>, | |
private __txt_detail::__ebco<_Range, 4> { | |
private: | |
using _URange = __txt_detail::__remove_cvref_t<__txt_detail::__unwrap_t<_Range>>; | |
using _UFromEncoding = __txt_detail::__remove_cvref_t<__txt_detail::__unwrap_t<_FromEncoding>>; | |
using _UToEncoding = __txt_detail::__remove_cvref_t<__txt_detail::__unwrap_t<_ToEncoding>>; | |
using _UFromErrorHandler = __txt_detail::__remove_cvref_t<__txt_detail::__unwrap_t<_FromErrorHandler>>; | |
using _UToErrorHandler = __txt_detail::__remove_cvref_t<__txt_detail::__unwrap_t<_ToErrorHandler>>; | |
using _UFromState = __txt_detail::__remove_cvref_t<__txt_detail::__unwrap_t<_FromState>>; | |
using _UToState = __txt_detail::__remove_cvref_t<__txt_detail::__unwrap_t<_ToState>>; | |
using _BaseIterator = __txt_detail::__range_iterator_t<_URange>; | |
using _IntermediateCodePoint = code_point_t<_UToEncoding>; | |
inline static constexpr ::std::size_t _MaxValues = max_code_units_v<_UToEncoding>; | |
inline static constexpr bool _IsSingleValueType = _MaxValues == 1; | |
inline static constexpr bool _IsInputOrOutput = __txt_detail::__is_range_input_or_output_range_v<_URange>; | |
inline static constexpr bool _IsCursorless = _IsSingleValueType && !_IsInputOrOutput; | |
inline static constexpr bool _IsErrorless | |
= decode_error_handler_always_returns_ok_v<_UFromEncoding, | |
_UFromErrorHandler> && encode_error_handler_always_returns_ok_v<_UToEncoding, _UToErrorHandler>; | |
using __base_cursor_cache_t = __txt_detail::__cursor_cache<_MaxValues, _IsInputOrOutput>; | |
using __base_cursor_cache_size_t = typename __base_cursor_cache_t::_SizeType; | |
using __base_error_cache_t = __txt_detail::__error_cache<_IsErrorless>; | |
using __base_from_encoding_t = __txt_detail::__ebco<__txt_detail::__remove_cvref_t<_FromEncoding>, 0>; | |
using __base_to_encoding_t = __txt_detail::__ebco<__txt_detail::__remove_cvref_t<_ToEncoding>, 1>; | |
using __base_from_error_handler_t | |
= __txt_detail::__ebco<__txt_detail::__remove_cvref_t<_FromErrorHandler>, 2>; | |
using __base_to_error_handler_t = __txt_detail::__ebco<__txt_detail::__remove_cvref_t<_ToErrorHandler>, 3>; | |
using __base_from_state_t = __txt_detail::__state_storage<__txt_detail::__remove_cvref_t<_FromEncoding>, | |
__txt_detail::__remove_cvref_t<_FromState>, 0>; | |
using __base_to_state_t = __txt_detail::__state_storage<__txt_detail::__remove_cvref_t<_ToEncoding>, | |
__txt_detail::__remove_cvref_t<_ToState>, 1>; | |
using __base_range_t = __txt_detail::__ebco<_Range, 4>; | |
inline static constexpr bool _IsBackwards | |
= __txt_detail::__is_detected_v<__txt_detail::__detect_object_encode_one_backwards, _UFromEncoding, | |
_URange, _UFromErrorHandler, _UFromState>; | |
public: | |
////// | |
/// @brief The underlying range type. | |
/// | |
////// | |
using range_type = _Range; | |
////// | |
/// @brief The base iterator type. | |
/// | |
////// | |
using iterator_type = _BaseIterator; | |
////// | |
/// @brief The encoding type used for decoding to intermediate code point storage. | |
/// | |
////// | |
using from_encoding_type = _FromEncoding; | |
////// | |
/// @brief The encoding type used for encoding to the final code units storage. | |
/// | |
////// | |
using to_encoding_type = _ToEncoding; | |
////// | |
/// @brief The error handler when a decode operation fails. | |
/// | |
////// | |
using from_error_handler_type = _FromErrorHandler; | |
////// | |
/// @brief The error handler when an encode operation fails. | |
/// | |
////// | |
using to_error_handler_type = _ToErrorHandler; | |
////// | |
/// @brief The state type used for decode operations. | |
/// | |
////// | |
using from_state_type = __txt_detail::__remove_cvref_t<_FromState>; | |
////// | |
/// @brief The state type used for encode operations. | |
/// | |
////// | |
using to_state_type = __txt_detail::__remove_cvref_t<_ToState>; | |
////// | |
/// @brief The strength of the iterator category, as defined in relation to the base. | |
/// | |
////// | |
using iterator_category = ::std::conditional_t< | |
__txt_detail::__is_iterator_concept_or_better_v<::std::bidirectional_iterator_tag, _BaseIterator>, | |
::std::conditional_t<_IsBackwards, ::std::bidirectional_iterator_tag, ::std::forward_iterator_tag>, | |
__txt_detail::__iterator_category_t<_BaseIterator>>; | |
////// | |
/// @brief The strength of the iterator concept, as defined in relation to the base. | |
/// | |
////// | |
using iterator_concept = ::std::conditional_t< | |
__txt_detail::__is_iterator_concept_or_better_v<::std::bidirectional_iterator_tag, _BaseIterator>, | |
::std::conditional_t<_IsBackwards, ::std::bidirectional_iterator_tag, ::std::forward_iterator_tag>, | |
__txt_detail::__iterator_concept_t<_BaseIterator>>; | |
////// | |
/// @brief The object type that gets output on every dereference. | |
/// | |
////// | |
using value_type = code_unit_t<_ToEncoding>; | |
////// | |
/// @brief A pointer type to the value_type. | |
/// | |
////// | |
// TODO: is there such a thing? | |
using pointer = value_type*; | |
////// | |
/// @brief The value returned from derefencing the iterator. | |
/// | |
/// @remarks This is a proxy iterator, so the @c reference is a non-reference @c value_type. | |
////// | |
using reference = value_type; | |
////// | |
/// @brief The type returned when two of these pointers are subtracted from one another. | |
/// | |
/// @remarks It's not a very useful type... | |
////// | |
using difference_type = __txt_detail::__iterator_difference_type_t<_BaseIterator>; | |
////// | |
/// @brief Default constructs a ztd::text::transcode_iterator. | |
/// | |
/// @remarks This can only work if the underlying encodings, error handlers, and states can handle default | |
/// construction. | |
////// | |
constexpr transcode_iterator() noexcept(::std::is_nothrow_default_constructible_v< | |
__base_from_encoding_t>&& ::std::is_nothrow_default_constructible_v<__base_to_encoding_t>&& ::std:: | |
is_nothrow_default_constructible_v<__base_from_error_handler_t>&& ::std:: | |
is_nothrow_default_constructible_v< | |
__base_to_error_handler_t>&& ::std::is_nothrow_constructible_v<__base_from_state_t, | |
_FromEncoding>&& ::std::is_nothrow_constructible_v<__base_to_state_t, | |
_ToEncoding>&& ::std::is_default_constructible_v<__base_range_t>) | |
: __base_from_encoding_t() | |
, __base_to_encoding_t() | |
, __base_from_error_handler_t() | |
, __base_to_error_handler_t() | |
, __base_from_state_t(this->from_encoding()) | |
, __base_to_state_t(this->to_encoding()) | |
, __base_cursor_cache_t() | |
, __base_range_t() | |
, _M_cache() { | |
this->_M_read_one(); | |
} | |
////// | |
/// @brief Copy constructs a transcode_iterator. | |
/// | |
////// | |
constexpr transcode_iterator(const transcode_iterator&) = default; | |
////// | |
/// @brief Move constructs a transcode_iterator. | |
/// | |
////// | |
constexpr transcode_iterator(transcode_iterator&&) = default; | |
////// | |
/// @brief Constructs a transcode_iterator from the underlying range. | |
/// | |
/// @param[in] __range The input range to wrap and iterate over. | |
////// | |
constexpr transcode_iterator(range_type __range) noexcept( | |
noexcept(transcode_iterator(::std::move(__range), to_encoding_type {}))) | |
: transcode_iterator(::std::move(__range), to_encoding_type {}) { | |
} | |
////// | |
/// @brief Constructs a transcode_iterator from the underlying range. | |
/// | |
/// @param[in] __range The input range to wrap and iterate over. | |
/// @param[in] __to_encoding The encoding object to call @c encode_one or equivalent functionality on. | |
////// | |
constexpr transcode_iterator(range_type __range, to_encoding_type __to_encoding) | |
: transcode_iterator(::std::move(__range), from_encoding_type {}, ::std::move(__to_encoding)) { | |
} | |
////// | |
/// @brief Constructs a transcode_iterator from the underlying range. | |
/// | |
/// @param[in] __range The input range to wrap and iterate over. | |
/// @param[in] __from_encoding The encoding object to call @c decode_one or equivalent functionality on. | |
/// @param[in] __to_encoding The encoding object to call @c encode_one or equivalent functionality on. | |
////// | |
constexpr transcode_iterator( | |
range_type __range, from_encoding_type __from_encoding, to_encoding_type __to_encoding) | |
: transcode_iterator(::std::move(__range), ::std::move(__from_encoding), ::std::move(__to_encoding), | |
from_error_handler_type {}, to_error_handler_type {}) { | |
} | |
////// | |
/// @brief Constructs a transcode_iterator from the underlying range. | |
/// | |
/// @param[in] __range The input range to wrap and iterate over. | |
/// @param[in] __from_encoding The encoding object to call @c decode_one or equivalent functionality on. | |
/// @param[in] __to_encoding The encoding object to call @c encode_one or equivalent functionality on. | |
/// @param[in] __from_error_handler The error handler for decode operations to store in this view. | |
/// @param[in] __to_error_handler The error handler for encode operations to store in this view. | |
////// | |
constexpr transcode_iterator(range_type __range, from_encoding_t |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment