Skip to content

Instantly share code, notes, and snippets.

@ThePhD
Last active July 2, 2021 04:22
Show Gist options
  • Save ThePhD/80764f840be25ae05a0c8953a210f0f5 to your computer and use it in GitHub Desktop.
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.
// =============================================================================
//
// 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