#ifndef SIMDUTF_H
#define SIMDUTF_H
#include <cstring>
#ifndef SIMDUTF_COMPILER_CHECK_H
#define SIMDUTF_COMPILER_CHECK_H
#ifndef __cplusplus
#error simdutf requires a C++ compiler
#endif
#ifndef SIMDUTF_CPLUSPLUS
#if defined(_MSVC_LANG) && !defined(__clang__)
#define SIMDUTF_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG)
#else
#define SIMDUTF_CPLUSPLUS __cplusplus
#endif
#endif
#if !defined(SIMDUTF_CPLUSPLUS26) && (SIMDUTF_CPLUSPLUS >= 202602L)
#define SIMDUTF_CPLUSPLUS26 1
#endif
#if !defined(SIMDUTF_CPLUSPLUS23) && (SIMDUTF_CPLUSPLUS >= 202302L)
#define SIMDUTF_CPLUSPLUS23 1
#endif
#if !defined(SIMDUTF_CPLUSPLUS20) && (SIMDUTF_CPLUSPLUS >= 202002L)
#define SIMDUTF_CPLUSPLUS20 1
#endif
#if !defined(SIMDUTF_CPLUSPLUS17) && (SIMDUTF_CPLUSPLUS >= 201703L)
#define SIMDUTF_CPLUSPLUS17 1
#endif
#if !defined(SIMDUTF_CPLUSPLUS14) && (SIMDUTF_CPLUSPLUS >= 201402L)
#define SIMDUTF_CPLUSPLUS14 1
#endif
#if !defined(SIMDUTF_CPLUSPLUS11) && (SIMDUTF_CPLUSPLUS >= 201103L)
#define SIMDUTF_CPLUSPLUS11 1
#endif
#ifndef SIMDUTF_CPLUSPLUS17
#error simdutf requires a compiler compliant with the C++17 standard
#endif
#endif
#ifndef SIMDUTF_COMMON_DEFS_H
#define SIMDUTF_COMMON_DEFS_H
#ifndef SIMDUTF_PORTABILITY_H
#define SIMDUTF_PORTABILITY_H
#include <cfloat>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#ifndef _WIN32
#include <strings.h>
#endif
#if defined(__apple_build_version__)
#if __apple_build_version__ < 14000000
#define SIMDUTF_SPAN_DISABLED \
1
#endif
#endif
#if SIMDUTF_CPLUSPLUS20
#include <version>
#if __cpp_concepts >= 201907L && __cpp_lib_span >= 202002L && \
!defined(SIMDUTF_SPAN_DISABLED)
#define SIMDUTF_SPAN 1
#endif #if __cpp_lib_atomic_ref >= 201806L
#define SIMDUTF_ATOMIC_REF 1
#endif #if __has_cpp_attribute(maybe_unused) >= 201603L
#define SIMDUTF_MAYBE_UNUSED_AVAILABLE 1
#endif #endif
#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
#define SIMDUTF_IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
#elif defined(_WIN32)
#define SIMDUTF_IS_BIG_ENDIAN 0
#else
#if defined(__APPLE__) || \
defined(__FreeBSD__)
#include <machine/endian.h>
#elif defined(sun) || \
defined(__sun)
#include <sys/byteorder.h>
#else
#ifdef __has_include
#if __has_include(<endian.h>)
#include <endian.h>
#endif #endif
#endif
#ifndef !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__)
#define SIMDUTF_IS_BIG_ENDIAN 0
#endif
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define SIMDUTF_IS_BIG_ENDIAN 0
#else
#define SIMDUTF_IS_BIG_ENDIAN 1
#endif
#endif
#ifdef _MSC_VER
#define SIMDUTF_VISUAL_STUDIO 1
#ifdef __clang__
#define SIMDUTF_CLANG_VISUAL_STUDIO 1
#else
#define SIMDUTF_REGULAR_VISUAL_STUDIO 1
#endif #endif
#ifdef SIMDUTF_REGULAR_VISUAL_STUDIO
#include <iso646.h>
#endif
#if (defined(__x86_64__) || defined(_M_AMD64)) && !defined(_M_ARM64EC)
#define SIMDUTF_IS_X86_64 1
#elif defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)
#define SIMDUTF_IS_ARM64 1
#elif defined(__PPC64__) || defined(_M_PPC64)
#if defined(__VEC__) && defined(__ALTIVEC__)
#define SIMDUTF_IS_PPC64 1
#endif
#elif defined(__s390__)
#elif (defined(__riscv) || defined(__riscv__)) && __riscv_xlen == 64
#define SIMDUTF_IS_RISCV64 1
#if __riscv_v_intrinsic >= 11000
#define SIMDUTF_HAS_RVV_INTRINSICS 1
#endif
#define SIMDUTF_HAS_ZVBB_INTRINSICS \
0
#if SIMDUTF_HAS_RVV_INTRINSICS && __riscv_vector && \
__riscv_v_min_vlen >= 128 && __riscv_v_elen >= 64
#define SIMDUTF_IS_RVV 1
#if SIMDUTF_HAS_ZVBB_INTRINSICS && __riscv_zvbb >= 1000000
#define SIMDUTF_IS_ZVBB 1
#endif
#endif
#elif defined(__loongarch_lp64)
#if defined(__loongarch_sx) && defined(__loongarch_asx)
#define SIMDUTF_IS_LSX 1
#define SIMDUTF_IS_LASX 1
#elif defined(__loongarch_sx)
#define SIMDUTF_IS_LSX 1
#if defined(__GNUC__) && !defined(__clang__) && \
!defined(__INTEL_COMPILER) && !defined(__NVCOMPILER)
#if __GNUC__ > 15 || (__GNUC__ == 15 && __GNUC_MINOR__ >= 0)
#else
#define SIMDUTF_IMPLEMENTATION_LASX 0
#endif
#else
#define SIMDUTF_IMPLEMENTATION_LASX 0
#endif
#endif
#else
#define SIMDUTF_IS_32BITS 1
#if defined(_M_IX86) || defined(__i386__)
#define SIMDUTF_IS_X86_32BITS 1
#elif defined(__arm__) || defined(_M_ARM)
#define SIMDUTF_IS_ARM_32BITS 1
#elif defined(__PPC__) || defined(_M_PPC)
#define SIMDUTF_IS_PPC_32BITS 1
#endif
#endif
#ifdef SIMDUTF_IS_32BITS
#ifndef SIMDUTF_NO_PORTABILITY_WARNING
#endif #endif
#define SIMDUTF_STRINGIFY_IMPLEMENTATION_(a) #a
#define SIMDUTF_STRINGIFY(a) SIMDUTF_STRINGIFY_IMPLEMENTATION_(a)
#if defined(SIMDUTF_IS_X86_64) || defined(SIMDUTF_IS_LSX)
#ifdef __clang__
#define SIMDUTF_TARGET_REGION(T) \
_Pragma(SIMDUTF_STRINGIFY(clang attribute push( \
__attribute__((target(T))), apply_to = function)))
#define SIMDUTF_UNTARGET_REGION _Pragma("clang attribute pop")
#elif defined(__GNUC__)
#define SIMDUTF_TARGET_REGION(T) \
_Pragma("GCC push_options") _Pragma(SIMDUTF_STRINGIFY(GCC target(T)))
#define SIMDUTF_UNTARGET_REGION _Pragma("GCC pop_options")
#endif
#endif
#ifndef SIMDUTF_TARGET_REGION
#define SIMDUTF_TARGET_REGION(T)
#define SIMDUTF_UNTARGET_REGION
#endif
#if defined(_REENTRANT) || defined(_MT)
#ifndef SIMDUTF_THREADS_ENABLED
#define SIMDUTF_THREADS_ENABLED
#endif
#endif
#ifdef __APPLE__
#ifndef __OPTIMIZE__
#undef SIMDUTF_THREADS_ENABLED
#endif
#endif
#ifdef SIMDUTF_VISUAL_STUDIO
#define simdutf_strcasecmp _stricmp
#define simdutf_strncasecmp _strnicmp
#else
#define simdutf_strcasecmp strcasecmp
#define simdutf_strncasecmp strncasecmp
#endif
#if defined(__GNUC__) && !defined(__clang__)
#if __GNUC__ >= 11
#define SIMDUTF_GCC11ORMORE 1
#endif #if __GNUC__ == 10
#define SIMDUTF_GCC10 1
#endif #if __GNUC__ < 10
#define SIMDUTF_GCC9OROLDER 1
#endif #endif
#endif
#ifndef SIMDUTF_AVX512_H_
#define SIMDUTF_AVX512_H_
#ifndef SIMDUTF_HAS_AVX512F
#if defined(__AVX512F__) && __AVX512F__ == 1
#define SIMDUTF_HAS_AVX512F 1
#endif
#endif
#ifndef SIMDUTF_HAS_AVX512DQ
#if defined(__AVX512DQ__) && __AVX512DQ__ == 1
#define SIMDUTF_HAS_AVX512DQ 1
#endif
#endif
#ifndef SIMDUTF_HAS_AVX512IFMA
#if defined(__AVX512IFMA__) && __AVX512IFMA__ == 1
#define SIMDUTF_HAS_AVX512IFMA 1
#endif
#endif
#ifndef SIMDUTF_HAS_AVX512CD
#if defined(__AVX512CD__) && __AVX512CD__ == 1
#define SIMDUTF_HAS_AVX512CD 1
#endif
#endif
#ifndef SIMDUTF_HAS_AVX512BW
#if defined(__AVX512BW__) && __AVX512BW__ == 1
#define SIMDUTF_HAS_AVX512BW 1
#endif
#endif
#ifndef SIMDUTF_HAS_AVX512VL
#if defined(__AVX512VL__) && __AVX512VL__ == 1
#define SIMDUTF_HAS_AVX512VL 1
#endif
#endif
#ifndef SIMDUTF_HAS_AVX512VBMI
#if defined(__AVX512VBMI__) && __AVX512VBMI__ == 1
#define SIMDUTF_HAS_AVX512VBMI 1
#endif
#endif
#ifndef SIMDUTF_HAS_AVX512VBMI2
#if defined(__AVX512VBMI2__) && __AVX512VBMI2__ == 1
#define SIMDUTF_HAS_AVX512VBMI2 1
#endif
#endif
#ifndef SIMDUTF_HAS_AVX512VNNI
#if defined(__AVX512VNNI__) && __AVX512VNNI__ == 1
#define SIMDUTF_HAS_AVX512VNNI 1
#endif
#endif
#ifndef SIMDUTF_HAS_AVX512BITALG
#if defined(__AVX512BITALG__) && __AVX512BITALG__ == 1
#define SIMDUTF_HAS_AVX512BITALG 1
#endif
#endif
#ifndef SIMDUTF_HAS_AVX512VPOPCNTDQ
#if defined(__AVX512VPOPCNTDQ__) && __AVX512VPOPCNTDQ__ == 1
#define SIMDUTF_HAS_AVX512VPOPCNTDQ 1
#endif
#endif
#endif
#ifdef SIMDUTF_LOGGING
#include <cstdlib>
#include <iostream>
#define simdutf_log(msg) \
std::cout << "[" << __FUNCTION__ << "]: " << msg << std::endl \
<< "\t" << __FILE__ << ":" << __LINE__ << std::endl;
#define simdutf_log_assert(cond, msg) \
do { \
if (!(cond)) { \
std::cerr << "[" << __FUNCTION__ << "]: " << msg << std::endl \
<< "\t" << __FILE__ << ":" << __LINE__ << std::endl; \
std::abort(); \
} \
} while (0)
#else
#define simdutf_log(msg)
#define simdutf_log_assert(cond, msg)
#endif
#if SIMDUTF_CPLUSPLUS17
#define simdutf_unused [[maybe_unused]]
#endif
#if defined(SIMDUTF_REGULAR_VISUAL_STUDIO)
#define SIMDUTF_DEPRECATED __declspec(deprecated)
#define simdutf_really_inline __forceinline
#define simdutf_always_inline __forceinline
#define simdutf_never_inline __declspec(noinline)
#ifndef simdutf_unused
#define simdutf_unused
#endif #define simdutf_warn_unused
#ifndef simdutf_likely
#define simdutf_likely(x) x
#endif
#ifndef simdutf_unlikely
#define simdutf_unlikely(x) x
#endif
#define SIMDUTF_PUSH_DISABLE_WARNINGS __pragma(warning(push))
#define SIMDUTF_PUSH_DISABLE_ALL_WARNINGS __pragma(warning(push, 0))
#define SIMDUTF_DISABLE_VS_WARNING(WARNING_NUMBER) \
__pragma(warning(disable : WARNING_NUMBER))
#ifdef __has_include
#if __has_include(<CppCoreCheck\Warnings.h>)
#include <CppCoreCheck\Warnings.h>
#define SIMDUTF_DISABLE_UNDESIRED_WARNINGS \
SIMDUTF_DISABLE_VS_WARNING(ALL_CPPCORECHECK_WARNINGS)
#endif
#endif
#ifndef SIMDUTF_DISABLE_UNDESIRED_WARNINGS
#define SIMDUTF_DISABLE_UNDESIRED_WARNINGS
#endif
#define SIMDUTF_DISABLE_DEPRECATED_WARNING SIMDUTF_DISABLE_VS_WARNING(4996)
#define SIMDUTF_DISABLE_STRICT_OVERFLOW_WARNING
#define SIMDUTF_POP_DISABLE_WARNINGS __pragma(warning(pop))
#define SIMDUTF_DISABLE_UNUSED_WARNING
#else
#if defined(__OPTIMIZE__) || defined(NDEBUG)
#define simdutf_really_inline inline __attribute__((always_inline))
#else
#define simdutf_really_inline inline
#endif
#define simdutf_always_inline \
inline __attribute__((always_inline))
#define SIMDUTF_DEPRECATED __attribute__((deprecated))
#define simdutf_never_inline inline __attribute__((noinline))
#ifndef simdutf_unused
#define simdutf_unused __attribute__((unused))
#endif #define simdutf_warn_unused __attribute__((warn_unused_result))
#ifndef simdutf_likely
#define simdutf_likely(x) __builtin_expect(!!(x), 1)
#endif
#ifndef simdutf_unlikely
#define simdutf_unlikely(x) __builtin_expect(!!(x), 0)
#endif
#define SIMDUTF_PUSH_DISABLE_WARNINGS _Pragma("GCC diagnostic push")
#define SIMDUTF_PUSH_DISABLE_ALL_WARNINGS \
SIMDUTF_PUSH_DISABLE_WARNINGS \
SIMDUTF_DISABLE_GCC_WARNING(-Weffc++) \
SIMDUTF_DISABLE_GCC_WARNING(-Wall) \
SIMDUTF_DISABLE_GCC_WARNING(-Wconversion) \
SIMDUTF_DISABLE_GCC_WARNING(-Wextra) \
SIMDUTF_DISABLE_GCC_WARNING(-Wattributes) \
SIMDUTF_DISABLE_GCC_WARNING(-Wimplicit-fallthrough) \
SIMDUTF_DISABLE_GCC_WARNING(-Wnon-virtual-dtor) \
SIMDUTF_DISABLE_GCC_WARNING(-Wreturn-type) \
SIMDUTF_DISABLE_GCC_WARNING(-Wshadow) \
SIMDUTF_DISABLE_GCC_WARNING(-Wunused-parameter) \
SIMDUTF_DISABLE_GCC_WARNING(-Wunused-variable)
#define SIMDUTF_PRAGMA(P) _Pragma(#P)
#define SIMDUTF_DISABLE_GCC_WARNING(WARNING) \
SIMDUTF_PRAGMA(GCC diagnostic ignored #WARNING)
#if defined(SIMDUTF_CLANG_VISUAL_STUDIO)
#define SIMDUTF_DISABLE_UNDESIRED_WARNINGS \
SIMDUTF_DISABLE_GCC_WARNING(-Wmicrosoft-include)
#else
#define SIMDUTF_DISABLE_UNDESIRED_WARNINGS
#endif
#define SIMDUTF_DISABLE_DEPRECATED_WARNING \
SIMDUTF_DISABLE_GCC_WARNING(-Wdeprecated-declarations)
#define SIMDUTF_DISABLE_STRICT_OVERFLOW_WARNING \
SIMDUTF_DISABLE_GCC_WARNING(-Wstrict-overflow)
#define SIMDUTF_POP_DISABLE_WARNINGS _Pragma("GCC diagnostic pop")
#define SIMDUTF_DISABLE_UNUSED_WARNING \
SIMDUTF_PUSH_DISABLE_WARNINGS \
SIMDUTF_DISABLE_GCC_WARNING(-Wunused-function) \
SIMDUTF_DISABLE_GCC_WARNING(-Wunused-const-variable)
#endif
#if SIMDUTF_CPLUSPLUS23
#define simdutf_constexpr23 constexpr
#else
#define simdutf_constexpr23
#endif
#ifndef SIMDUTF_DLLIMPORTEXPORT
#if defined(SIMDUTF_VISUAL_STUDIO)
#if SIMDUTF_BUILDING_WINDOWS_DYNAMIC_LIBRARY
#define SIMDUTF_DLLIMPORTEXPORT __declspec(dllexport)
#elif SIMDUTF_USING_WINDOWS_DYNAMIC_LIBRARY
#define SIMDUTF_DLLIMPORTEXPORT __declspec(dllimport)
#else
#define SIMDUTF_DLLIMPORTEXPORT
#endif
#else
#define SIMDUTF_DLLIMPORTEXPORT
#endif #endif
#if SIMDUTF_MAYBE_UNUSED_AVAILABLE
#define simdutf_maybe_unused [[maybe_unused]]
#else
#define simdutf_maybe_unused
#endif
#endif
#ifndef SIMDUTF_ENCODING_TYPES_H
#define SIMDUTF_ENCODING_TYPES_H
#include <string_view>
#if !defined(SIMDUTF_NO_STD_TEXT_ENCODING) && \
defined(__cpp_lib_text_encoding) && __cpp_lib_text_encoding >= 202306L
#define SIMDUTF_HAS_STD_TEXT_ENCODING 1
#include <text_encoding>
#endif
namespace simdutf {
enum encoding_type {
UTF8 = 1, UTF16_LE = 2, UTF16_BE = 4, UTF32_LE = 8, UTF32_BE = 16, Latin1 = 32,
unspecified = 0
};
#ifndef SIMDUTF_IS_BIG_ENDIAN
#error "SIMDUTF_IS_BIG_ENDIAN needs to be defined."
#endif
enum endianness {
LITTLE = 0,
BIG = 1,
NATIVE =
#if SIMDUTF_IS_BIG_ENDIAN
BIG
#else
LITTLE
#endif
};
simdutf_warn_unused simdutf_really_inline constexpr bool
match_system(endianness e) {
return e == endianness::NATIVE;
}
simdutf_warn_unused std::string_view to_string(encoding_type bom);
namespace BOM {
simdutf_warn_unused encoding_type check_bom(const uint8_t *byte, size_t length);
simdutf_warn_unused encoding_type check_bom(const char *byte, size_t length);
simdutf_warn_unused size_t bom_byte_size(encoding_type bom);
}
#ifdef SIMDUTF_HAS_STD_TEXT_ENCODING
simdutf_warn_unused constexpr std::text_encoding
to_std_encoding(encoding_type enc) noexcept {
switch (enc) {
case UTF8:
return std::text_encoding(std::text_encoding::id::UTF8);
case UTF16_LE:
return std::text_encoding(std::text_encoding::id::UTF16LE);
case UTF16_BE:
return std::text_encoding(std::text_encoding::id::UTF16BE);
case UTF32_LE:
return std::text_encoding(std::text_encoding::id::UTF32LE);
case UTF32_BE:
return std::text_encoding(std::text_encoding::id::UTF32BE);
case Latin1:
return std::text_encoding(std::text_encoding::id::ISOLatin1);
case unspecified:
default:
return std::text_encoding(std::text_encoding::id::unknown);
}
}
simdutf_warn_unused constexpr encoding_type
from_std_encoding(const std::text_encoding &enc) noexcept {
switch (enc.mib()) {
case std::text_encoding::id::UTF8:
return UTF8;
case std::text_encoding::id::UTF16LE:
return UTF16_LE;
case std::text_encoding::id::UTF16BE:
return UTF16_BE;
case std::text_encoding::id::UTF32LE:
return UTF32_LE;
case std::text_encoding::id::UTF32BE:
return UTF32_BE;
case std::text_encoding::id::ISOLatin1:
return Latin1;
default:
return unspecified;
}
}
simdutf_warn_unused constexpr encoding_type native_utf16_encoding() noexcept {
#if SIMDUTF_IS_BIG_ENDIAN
return UTF16_BE;
#else
return UTF16_LE;
#endif
}
simdutf_warn_unused constexpr encoding_type native_utf32_encoding() noexcept {
#if SIMDUTF_IS_BIG_ENDIAN
return UTF32_BE;
#else
return UTF32_LE;
#endif
}
simdutf_warn_unused constexpr encoding_type
from_std_encoding_native(const std::text_encoding &enc) noexcept {
switch (enc.mib()) {
case std::text_encoding::id::UTF8:
return UTF8;
case std::text_encoding::id::UTF16:
return native_utf16_encoding();
case std::text_encoding::id::UTF16LE:
return UTF16_LE;
case std::text_encoding::id::UTF16BE:
return UTF16_BE;
case std::text_encoding::id::UTF32:
return native_utf32_encoding();
case std::text_encoding::id::UTF32LE:
return UTF32_LE;
case std::text_encoding::id::UTF32BE:
return UTF32_BE;
case std::text_encoding::id::ISOLatin1:
return Latin1;
default:
return unspecified;
}
}
#endif
} #endif
#ifndef SIMDUTF_ERROR_H
#define SIMDUTF_ERROR_H
#include <string_view>
namespace simdutf {
enum error_code {
SUCCESS = 0,
HEADER_BITS, TOO_SHORT, TOO_LONG, OVERLONG, TOO_LARGE, SURROGATE, INVALID_BASE64_CHARACTER, BASE64_INPUT_REMAINDER, BASE64_EXTRA_BITS, OUTPUT_BUFFER_TOO_SMALL, OTHER };
inline std::string_view error_to_string(error_code code) noexcept {
switch (code) {
case SUCCESS:
return "SUCCESS";
case HEADER_BITS:
return "HEADER_BITS";
case TOO_SHORT:
return "TOO_SHORT";
case TOO_LONG:
return "TOO_LONG";
case OVERLONG:
return "OVERLONG";
case TOO_LARGE:
return "TOO_LARGE";
case SURROGATE:
return "SURROGATE";
case INVALID_BASE64_CHARACTER:
return "INVALID_BASE64_CHARACTER";
case BASE64_INPUT_REMAINDER:
return "BASE64_INPUT_REMAINDER";
case BASE64_EXTRA_BITS:
return "BASE64_EXTRA_BITS";
case OUTPUT_BUFFER_TOO_SMALL:
return "OUTPUT_BUFFER_TOO_SMALL";
default:
return "OTHER";
}
}
struct result {
error_code error;
size_t count;
simdutf_really_inline simdutf_constexpr23 result() noexcept
: error{error_code::SUCCESS}, count{0} {}
simdutf_really_inline simdutf_constexpr23 result(error_code err,
size_t pos) noexcept
: error{err}, count{pos} {}
simdutf_really_inline simdutf_constexpr23 bool is_ok() const noexcept {
return error == error_code::SUCCESS;
}
simdutf_really_inline simdutf_constexpr23 bool is_err() const noexcept {
return error != error_code::SUCCESS;
}
};
struct full_result {
error_code error;
size_t input_count;
size_t output_count;
bool padding_error = false;
simdutf_really_inline simdutf_constexpr23 full_result() noexcept
: error{error_code::SUCCESS}, input_count{0}, output_count{0} {}
simdutf_really_inline simdutf_constexpr23 full_result(error_code err,
size_t pos_in,
size_t pos_out) noexcept
: error{err}, input_count{pos_in}, output_count{pos_out} {}
simdutf_really_inline simdutf_constexpr23 full_result(
error_code err, size_t pos_in, size_t pos_out, bool padding_err) noexcept
: error{err}, input_count{pos_in}, output_count{pos_out},
padding_error{padding_err} {}
simdutf_really_inline simdutf_constexpr23 operator result() const noexcept {
if (error == error_code::SUCCESS) {
return result{error, output_count};
} else {
return result{error, input_count};
}
}
};
} #endif
SIMDUTF_PUSH_DISABLE_WARNINGS
SIMDUTF_DISABLE_UNDESIRED_WARNINGS
#ifndef SIMDUTF_SIMDUTF_VERSION_H
#define SIMDUTF_SIMDUTF_VERSION_H
#define SIMDUTF_VERSION "9.0.0"
namespace simdutf {
enum {
SIMDUTF_VERSION_MAJOR = 9,
SIMDUTF_VERSION_MINOR = 0,
SIMDUTF_VERSION_REVISION = 0
};
}
#endif
#ifndef SIMDUTF_IMPLEMENTATION_H
#define SIMDUTF_IMPLEMENTATION_H
#if !defined(SIMDUTF_NO_THREADS)
#include <atomic>
#endif
#ifdef SIMDUTF_INTERNAL_TESTS
#include <vector>
#endif
#ifndef SIMDutf_INTERNAL_ISADETECTION_H
#define SIMDutf_INTERNAL_ISADETECTION_H
#include <cstdint>
#include <cstdlib>
#if defined(_MSC_VER)
#include <intrin.h>
#elif (defined(HAVE_GCC_GET_CPUID) && defined(USE_GCC_GET_CPUID)) || \
defined(__FILC__)
#include <cpuid.h>
#endif
#ifdef __FILC__
#include <stdfil.h>
#endif
#if SIMDUTF_IS_RISCV64 && defined(__linux__)
#include <unistd.h>
struct simdutf_riscv_hwprobe {
int64_t key;
uint64_t value;
};
#define simdutf_riscv_hwprobe(...) syscall(258, __VA_ARGS__)
#define SIMDUTF_RISCV_HWPROBE_KEY_IMA_EXT_0 4
#define SIMDUTF_RISCV_HWPROBE_IMA_V (1 << 2)
#define SIMDUTF_RISCV_HWPROBE_EXT_ZVBB (1 << 17)
#endif
#if defined(__loongarch__) && defined(__linux__)
#include <sys/auxv.h>
#endif
namespace simdutf {
namespace internal {
enum instruction_set {
DEFAULT = 0x0,
NEON = 0x1,
AVX2 = 0x4,
SSE42 = 0x8,
PCLMULQDQ = 0x10,
BMI1 = 0x20,
BMI2 = 0x40,
ALTIVEC = 0x80,
AVX512F = 0x100,
AVX512DQ = 0x200,
AVX512IFMA = 0x400,
AVX512PF = 0x800,
AVX512ER = 0x1000,
AVX512CD = 0x2000,
AVX512BW = 0x4000,
AVX512VL = 0x8000,
AVX512VBMI2 = 0x10000,
AVX512VPOPCNTDQ = 0x2000,
RVV = 0x4000,
ZVBB = 0x8000,
LSX = 0x40000,
LASX = 0x80000,
};
#if defined(__PPC64__)
static inline uint32_t detect_supported_architectures() {
return instruction_set::ALTIVEC;
}
#elif SIMDUTF_IS_RISCV64
static inline uint32_t detect_supported_architectures() {
uint32_t host_isa = instruction_set::DEFAULT;
#if SIMDUTF_IS_RVV
host_isa |= instruction_set::RVV;
#endif
#if SIMDUTF_IS_ZVBB
host_isa |= instruction_set::ZVBB;
#endif
#if defined(__linux__)
simdutf_riscv_hwprobe probes[] = {{SIMDUTF_RISCV_HWPROBE_KEY_IMA_EXT_0, 0}};
long ret = simdutf_riscv_hwprobe(&probes, sizeof probes / sizeof *probes, 0,
nullptr, 0);
if (ret == 0) {
uint64_t extensions = probes[0].value;
if (extensions & SIMDUTF_RISCV_HWPROBE_IMA_V)
host_isa |= instruction_set::RVV;
if (extensions & SIMDUTF_RISCV_HWPROBE_EXT_ZVBB)
host_isa |= instruction_set::ZVBB;
}
#endif
#if defined(RUN_IN_SPIKE_SIMULATOR)
host_isa |= instruction_set::RVV;
#endif
return host_isa;
}
#elif defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)
static inline uint32_t detect_supported_architectures() {
return instruction_set::NEON;
}
#elif defined(__x86_64__) || defined(_M_AMD64)
namespace {
namespace cpuid_bit {
constexpr uint32_t pclmulqdq = uint32_t(1)
<< 1; constexpr uint32_t sse42 = uint32_t(1)
<< 20; constexpr uint32_t osxsave =
(uint32_t(1) << 26) |
(uint32_t(1) << 27);
namespace ebx {
constexpr uint32_t bmi1 = uint32_t(1) << 3;
constexpr uint32_t avx2 = uint32_t(1) << 5;
constexpr uint32_t bmi2 = uint32_t(1) << 8;
constexpr uint32_t avx512f = uint32_t(1) << 16;
constexpr uint32_t avx512dq = uint32_t(1) << 17;
constexpr uint32_t avx512ifma = uint32_t(1) << 21;
constexpr uint32_t avx512cd = uint32_t(1) << 28;
constexpr uint32_t avx512bw = uint32_t(1) << 30;
constexpr uint32_t avx512vl = uint32_t(1) << 31;
}
namespace ecx {
constexpr uint32_t avx512vbmi = uint32_t(1) << 1;
constexpr uint32_t avx512vbmi2 = uint32_t(1) << 6;
constexpr uint32_t avx512vnni = uint32_t(1) << 11;
constexpr uint32_t avx512bitalg = uint32_t(1) << 12;
constexpr uint32_t avx512vpopcnt = uint32_t(1) << 14;
} namespace edx {
constexpr uint32_t avx512vp2intersect = uint32_t(1) << 8;
}
namespace xcr0_bit {
constexpr uint64_t avx256_saved = uint64_t(1) << 2; constexpr uint64_t avx512_saved =
uint64_t(7) << 5; } } }
static inline void cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx,
uint32_t *edx) {
#if defined(_MSC_VER)
int cpu_info[4];
__cpuidex(cpu_info, *eax, *ecx);
*eax = cpu_info[0];
*ebx = cpu_info[1];
*ecx = cpu_info[2];
*edx = cpu_info[3];
#elif (defined(HAVE_GCC_GET_CPUID) && defined(USE_GCC_GET_CPUID)) || \
defined(__FILC__)
uint32_t level = *eax;
__get_cpuid(level, eax, ebx, ecx, edx);
#else
uint32_t a = *eax, b, c = *ecx, d;
asm volatile("cpuid\n\t" : "+a"(a), "=b"(b), "+c"(c), "=d"(d));
*eax = a;
*ebx = b;
*ecx = c;
*edx = d;
#endif
}
static inline uint64_t xgetbv() {
#if defined(_MSC_VER)
return _xgetbv(0);
#elif defined(__FILC__)
return zxgetbv();
#else
uint32_t xcr0_lo, xcr0_hi;
asm volatile("xgetbv\n\t" : "=a"(xcr0_lo), "=d"(xcr0_hi) : "c"(0));
return xcr0_lo | ((uint64_t)xcr0_hi << 32);
#endif
}
static inline uint32_t detect_supported_architectures() {
uint32_t eax;
uint32_t ebx = 0;
uint32_t ecx = 0;
uint32_t edx = 0;
uint32_t host_isa = 0x0;
eax = 0x1;
cpuid(&eax, &ebx, &ecx, &edx);
if (ecx & cpuid_bit::sse42) {
host_isa |= instruction_set::SSE42;
}
if (ecx & cpuid_bit::pclmulqdq) {
host_isa |= instruction_set::PCLMULQDQ;
}
if ((ecx & cpuid_bit::osxsave) != cpuid_bit::osxsave) {
return host_isa;
}
uint64_t xcr0 = xgetbv();
if ((xcr0 & cpuid_bit::xcr0_bit::avx256_saved) == 0) {
return host_isa;
}
eax = 0x7;
ecx = 0x0; cpuid(&eax, &ebx, &ecx, &edx);
if (ebx & cpuid_bit::ebx::avx2) {
host_isa |= instruction_set::AVX2;
}
if (ebx & cpuid_bit::ebx::bmi1) {
host_isa |= instruction_set::BMI1;
}
if (ebx & cpuid_bit::ebx::bmi2) {
host_isa |= instruction_set::BMI2;
}
if (!((xcr0 & cpuid_bit::xcr0_bit::avx512_saved) ==
cpuid_bit::xcr0_bit::avx512_saved)) {
return host_isa;
}
if (ebx & cpuid_bit::ebx::avx512f) {
host_isa |= instruction_set::AVX512F;
}
if (ebx & cpuid_bit::ebx::avx512bw) {
host_isa |= instruction_set::AVX512BW;
}
if (ebx & cpuid_bit::ebx::avx512cd) {
host_isa |= instruction_set::AVX512CD;
}
if (ebx & cpuid_bit::ebx::avx512dq) {
host_isa |= instruction_set::AVX512DQ;
}
if (ebx & cpuid_bit::ebx::avx512vl) {
host_isa |= instruction_set::AVX512VL;
}
if (ecx & cpuid_bit::ecx::avx512vbmi2) {
host_isa |= instruction_set::AVX512VBMI2;
}
if (ecx & cpuid_bit::ecx::avx512vpopcnt) {
host_isa |= instruction_set::AVX512VPOPCNTDQ;
}
return host_isa;
}
#elif defined(__loongarch__)
static inline uint32_t detect_supported_architectures() {
uint32_t host_isa = instruction_set::DEFAULT;
#if defined(__linux__)
uint64_t hwcap = 0;
hwcap = getauxval(AT_HWCAP);
if (hwcap & HWCAP_LOONGARCH_LSX) {
host_isa |= instruction_set::LSX;
}
if (hwcap & HWCAP_LOONGARCH_LASX) {
host_isa |= instruction_set::LASX;
}
#endif
return host_isa;
}
#else
static inline uint32_t detect_supported_architectures() {
return instruction_set::DEFAULT;
}
#endif
} }
#endif
#include <string_view>
#if SIMDUTF_SPAN
#include <concepts>
#include <type_traits>
#include <span>
#include <tuple>
#include <utility>
#endif
#ifndef SIMDUTF_FEATURE_DETECT_ENCODING
#define SIMDUTF_FEATURE_DETECT_ENCODING 1
#endif
#ifndef SIMDUTF_FEATURE_ASCII
#define SIMDUTF_FEATURE_ASCII 1
#endif
#ifndef SIMDUTF_FEATURE_LATIN1
#define SIMDUTF_FEATURE_LATIN1 1
#endif
#ifndef SIMDUTF_FEATURE_UTF8
#define SIMDUTF_FEATURE_UTF8 1
#endif
#ifndef SIMDUTF_FEATURE_UTF16
#define SIMDUTF_FEATURE_UTF16 1
#endif
#ifndef SIMDUTF_FEATURE_UTF32
#define SIMDUTF_FEATURE_UTF32 1
#endif
#ifndef SIMDUTF_FEATURE_BASE64
#define SIMDUTF_FEATURE_BASE64 1
#endif
namespace simdutf {
namespace detail {
namespace {
constexpr std::size_t min(std::size_t a, std::size_t b) {
return a < b ? a : b;
}
template <typename T, typename U>
constexpr std::size_t min(const T &a, const U &b) = delete;
} } }
#if SIMDUTF_CPLUSPLUS23
#ifndef SIMDUTF_CONSTEXPR_PTR_H
#define SIMDUTF_CONSTEXPR_PTR_H
#include <cstddef>
namespace simdutf {
namespace detail {
template <typename to, typename from>
requires(sizeof(to) == sizeof(from))
struct constexpr_ptr {
const from *p;
constexpr explicit constexpr_ptr(const from *ptr) noexcept : p(ptr) {}
constexpr to operator*() const noexcept { return static_cast<to>(*p); }
constexpr constexpr_ptr &operator++() noexcept {
++p;
return *this;
}
constexpr constexpr_ptr operator++(int) noexcept {
auto old = *this;
++p;
return old;
}
constexpr constexpr_ptr &operator--() noexcept {
--p;
return *this;
}
constexpr constexpr_ptr operator--(int) noexcept {
auto old = *this;
--p;
return old;
}
constexpr constexpr_ptr &operator+=(std::ptrdiff_t n) noexcept {
p += n;
return *this;
}
constexpr constexpr_ptr &operator-=(std::ptrdiff_t n) noexcept {
p -= n;
return *this;
}
constexpr constexpr_ptr operator+(std::ptrdiff_t n) const noexcept {
return constexpr_ptr{p + n};
}
constexpr constexpr_ptr operator-(std::ptrdiff_t n) const noexcept {
return constexpr_ptr{p - n};
}
constexpr std::ptrdiff_t operator-(const constexpr_ptr &o) const noexcept {
return p - o.p;
}
constexpr to operator[](std::ptrdiff_t n) const noexcept {
return static_cast<to>(*(p + n));
}
constexpr operator const void *() const noexcept { return p; }
};
template <typename to, typename from>
constexpr constexpr_ptr<to, from> constexpr_cast_ptr(from *p) noexcept {
return constexpr_ptr<to, from>{p};
}
template <typename SrcType, typename TargetType>
struct constexpr_write_ptr_proxy {
constexpr explicit constexpr_write_ptr_proxy(TargetType *raw) : p(raw) {}
constexpr constexpr_write_ptr_proxy &operator=(SrcType v) {
*p = static_cast<TargetType>(v);
return *this;
}
TargetType *p;
};
template <typename SrcType, typename TargetType> struct constexpr_write_ptr {
constexpr explicit constexpr_write_ptr(TargetType *raw) : p(raw) {}
constexpr constexpr_write_ptr_proxy<SrcType, TargetType> operator*() const {
return constexpr_write_ptr_proxy<SrcType, TargetType>{p};
}
constexpr constexpr_write_ptr_proxy<SrcType, TargetType>
operator[](std::ptrdiff_t n) const {
return constexpr_write_ptr_proxy<SrcType, TargetType>{p + n};
}
constexpr constexpr_write_ptr &operator++() {
++p;
return *this;
}
constexpr constexpr_write_ptr operator++(int) {
constexpr_write_ptr old = *this;
++p;
return old;
}
constexpr std::ptrdiff_t operator-(const constexpr_write_ptr &other) const {
return p - other.p;
}
TargetType *p;
};
template <typename SrcType, typename TargetType>
constexpr auto constexpr_cast_writeptr(TargetType *raw) {
return constexpr_write_ptr<SrcType, TargetType>{raw};
}
} } #endif
#endif
#if SIMDUTF_SPAN
namespace simdutf {
namespace detail {
template <typename T>
concept byte_like = std::is_same_v<T, std::byte> || std::is_same_v<T, char> || std::is_same_v<T, signed char> || std::is_same_v<T, unsigned char> || std::is_same_v<T, char8_t>;
template <typename T>
concept is_byte_like = byte_like<std::remove_cvref_t<T>>;
template <typename T>
concept is_pointer = std::is_pointer_v<T>;
template <typename T>
concept input_span_of_byte_like = requires(const T &t) {
{ t.size() } noexcept -> std::convertible_to<std::size_t>;
{ t.data() } noexcept -> is_pointer;
{ *t.data() } noexcept -> is_byte_like;
};
template <typename T>
concept is_mutable = !std::is_const_v<std::remove_reference_t<T>>;
template <typename T>
concept output_span_of_byte_like = requires(T &t) {
{ t.size() } noexcept -> std::convertible_to<std::size_t>;
{ t.data() } noexcept -> is_pointer;
{ *t.data() } noexcept -> is_byte_like;
{ *t.data() } noexcept -> is_mutable;
};
template <class InputPtr>
concept indexes_into_byte_like = requires(InputPtr p) {
{ std::decay_t<decltype(p[0])>{} } -> simdutf::detail::byte_like;
};
template <class InputPtr>
concept indexes_into_utf16 = requires(InputPtr p) {
{ std::decay_t<decltype(p[0])>{} } -> std::same_as<char16_t>;
};
template <class InputPtr>
concept indexes_into_utf32 = requires(InputPtr p) {
{ std::decay_t<decltype(p[0])>{} } -> std::same_as<char32_t>;
};
template <class InputPtr>
concept index_assignable_from_char = requires(InputPtr p, char s) {
{ p[0] = s };
};
template <class InputPtr>
concept indexes_into_uint32 = requires(InputPtr p) {
{ std::decay_t<decltype(p[0])>{} } -> std::same_as<std::uint32_t>;
};
} } #endif
#ifndef SIMDUTF_SWAP_BYTES_H
#define SIMDUTF_SWAP_BYTES_H
namespace simdutf {
namespace scalar {
constexpr inline simdutf_warn_unused uint16_t
u16_swap_bytes(const uint16_t word) {
return uint16_t((word >> 8) | (word << 8));
}
constexpr inline simdutf_warn_unused uint32_t
u32_swap_bytes(const uint32_t word) {
return ((word >> 24) & 0xff) | ((word << 8) & 0xff0000) | ((word >> 8) & 0xff00) | ((word << 24) & 0xff000000); }
namespace utf32 {
template <endianness big_endian> constexpr uint32_t swap_if_needed(uint32_t c) {
return !match_system(big_endian) ? scalar::u32_swap_bytes(c) : c;
}
}
namespace utf16 {
template <endianness big_endian> constexpr uint16_t swap_if_needed(uint16_t c) {
return !match_system(big_endian) ? scalar::u16_swap_bytes(c) : c;
}
}
} }
#endif
#ifndef SIMDUTF_ASCII_H
#define SIMDUTF_ASCII_H
#include <cstring>
namespace simdutf {
namespace scalar {
namespace {
namespace ascii {
template <class InputPtr>
#if SIMDUTF_CPLUSPLUS20
requires simdutf::detail::indexes_into_byte_like<InputPtr>
#endif
simdutf_warn_unused simdutf_constexpr23 bool validate(InputPtr data,
size_t len) noexcept {
uint64_t pos = 0;
#if SIMDUTF_CPLUSPLUS23
if !consteval
#endif
{
for (; pos + 16 <= len; pos += 16) {
uint64_t v1;
std::memcpy(&v1, data + pos, sizeof(uint64_t));
uint64_t v2;
std::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
uint64_t v{v1 | v2};
if ((v & 0x8080808080808080) != 0) {
return false;
}
}
}
for (; pos < len; pos++) {
if (static_cast<std::uint8_t>(data[pos]) >= 0b10000000) {
return false;
}
}
return true;
}
template <class InputPtr>
#if SIMDUTF_CPLUSPLUS20
requires simdutf::detail::indexes_into_byte_like<InputPtr>
#endif
simdutf_warn_unused simdutf_constexpr23 result
validate_with_errors(InputPtr data, size_t len) noexcept {
size_t pos = 0;
#if SIMDUTF_CPLUSPLUS23
if !consteval
#endif
{
for (; pos + 16 <= len; pos += 16) {
uint64_t v1;
std::memcpy(&v1, data + pos, sizeof(uint64_t));
uint64_t v2;
std::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
uint64_t v{v1 | v2};
if ((v & 0x8080808080808080) != 0) {
for (; pos < len; pos++) {
if (static_cast<std::uint8_t>(data[pos]) >= 0b10000000) {
return result(error_code::TOO_LARGE, pos);
}
}
}
}
}
for (; pos < len; pos++) {
if (static_cast<std::uint8_t>(data[pos]) >= 0b10000000) {
return result(error_code::TOO_LARGE, pos);
}
}
return result(error_code::SUCCESS, pos);
}
} } } }
#endif
#ifndef SIMDUTF_ATOMIC_UTIL_H
#define SIMDUTF_ATOMIC_UTIL_H
#if SIMDUTF_ATOMIC_REF
#include <atomic>
#include <cstring>
namespace simdutf {
namespace scalar {
inline void memcpy_atomic_read(char *dst, const char *src, size_t len) {
static_assert(std::atomic_ref<char>::required_alignment == sizeof(char),
"std::atomic_ref requires the same alignment as char_type");
constexpr size_t alignment = sizeof(uint64_t);
auto bbb_memcpy_atomic_read = [](char *bytedst, const char *bytesrc,
size_t bytelen) noexcept {
char *mutable_src = const_cast<char *>(bytesrc);
for (size_t j = 0; j < bytelen; ++j) {
bytedst[j] =
std::atomic_ref<char>(mutable_src[j]).load(std::memory_order_relaxed);
}
};
size_t offset = reinterpret_cast<std::uintptr_t>(src) % alignment;
if (offset) {
size_t to_align = detail::min(len, alignment - offset);
bbb_memcpy_atomic_read(dst, src, to_align);
src += to_align;
dst += to_align;
len -= to_align;
}
while (len >= alignment) {
auto *src_aligned = reinterpret_cast<uint64_t *>(const_cast<char *>(src));
const auto dst_value =
std::atomic_ref<uint64_t>(*src_aligned).load(std::memory_order_relaxed);
std::memcpy(dst, &dst_value, sizeof(uint64_t));
src += alignment;
dst += alignment;
len -= alignment;
}
if (len) {
bbb_memcpy_atomic_read(dst, src, len);
}
}
inline void memcpy_atomic_write(char *dst, const char *src, size_t len) {
static_assert(std::atomic_ref<char>::required_alignment == sizeof(char),
"std::atomic_ref requires the same alignment as char");
constexpr size_t alignment = sizeof(uint64_t);
auto bbb_memcpy_atomic_write = [](char *bytedst, const char *bytesrc,
size_t bytelen) noexcept {
for (size_t j = 0; j < bytelen; ++j) {
std::atomic_ref<char>(bytedst[j])
.store(bytesrc[j], std::memory_order_relaxed);
}
};
size_t offset = reinterpret_cast<std::uintptr_t>(dst) % alignment;
if (offset) {
size_t to_align = detail::min(len, alignment - offset);
bbb_memcpy_atomic_write(dst, src, to_align);
dst += to_align;
src += to_align;
len -= to_align;
}
while (len >= alignment) {
auto *dst_aligned = reinterpret_cast<uint64_t *>(dst);
uint64_t src_val;
std::memcpy(&src_val, src, sizeof(uint64_t)); std::atomic_ref<uint64_t>(*dst_aligned)
.store(src_val, std::memory_order_relaxed);
dst += alignment;
src += alignment;
len -= alignment;
}
if (len) {
bbb_memcpy_atomic_write(dst, src, len);
}
}
} } #endif #endif
#ifndef SIMDUTF_LATIN1_H
#define SIMDUTF_LATIN1_H
namespace simdutf {
namespace scalar {
namespace {
namespace latin1 {
simdutf_really_inline size_t utf8_length_from_latin1(const char *buf,
size_t len) {
const uint8_t *c = reinterpret_cast<const uint8_t *>(buf);
size_t answer = 0;
for (size_t i = 0; i < len; i++) {
if ((c[i] >> 7)) {
answer++;
}
}
return answer + len;
}
} } } }
#endif
#ifndef SIMDUTF_LATIN1_TO_UTF16_H
#define SIMDUTF_LATIN1_TO_UTF16_H
namespace simdutf {
namespace scalar {
namespace {
namespace latin1_to_utf16 {
template <endianness big_endian, typename InputPtr>
#if SIMDUTF_CPLUSPLUS20
requires simdutf::detail::indexes_into_byte_like<InputPtr>
#endif
simdutf_constexpr23 size_t convert(InputPtr data, size_t len,
char16_t *utf16_output) {
size_t pos = 0;
char16_t *start{utf16_output};
while (pos < len) {
uint16_t word =
uint8_t(data[pos]); *utf16_output++ =
char16_t(match_system(big_endian) ? word : u16_swap_bytes(word));
pos++;
}
return utf16_output - start;
}
template <endianness big_endian>
inline result convert_with_errors(const char *buf, size_t len,
char16_t *utf16_output) {
const uint8_t *data = reinterpret_cast<const uint8_t *>(buf);
size_t pos = 0;
char16_t *start{utf16_output};
while (pos < len) {
uint16_t word =
uint16_t(data[pos]); *utf16_output++ =
char16_t(match_system(big_endian) ? word : u16_swap_bytes(word));
pos++;
}
return result(error_code::SUCCESS, utf16_output - start);
}
} } } }
#endif
#ifndef SIMDUTF_LATIN1_TO_UTF32_H
#define SIMDUTF_LATIN1_TO_UTF32_H
namespace simdutf {
namespace scalar {
namespace {
namespace latin1_to_utf32 {
template <typename InputPtr>
#if SIMDUTF_CPLUSPLUS20
requires simdutf::detail::indexes_into_byte_like<InputPtr>
#endif
simdutf_constexpr23 size_t convert(InputPtr data, size_t len,
char32_t *utf32_output) {
char32_t *start{utf32_output};
for (size_t i = 0; i < len; i++) {
*utf32_output++ = uint8_t(data[i]);
}
return utf32_output - start;
}
} } } }
#endif
#ifndef SIMDUTF_LATIN1_TO_UTF8_H
#define SIMDUTF_LATIN1_TO_UTF8_H
#include <cstring>
namespace simdutf {
namespace scalar {
namespace {
namespace latin1_to_utf8 {
template <typename InputPtr, typename OutputPtr>
#if SIMDUTF_CPLUSPLUS20
requires(simdutf::detail::indexes_into_byte_like<InputPtr> &&
simdutf::detail::index_assignable_from_char<OutputPtr>)
#endif
simdutf_constexpr23 size_t convert(InputPtr data, size_t len,
OutputPtr utf8_output) {
size_t pos = 0;
size_t utf8_pos = 0;
while (pos < len) {
#if SIMDUTF_CPLUSPLUS23
if !consteval
#endif
{
if (pos + 16 <= len) { uint64_t v1;
::memcpy(&v1, data + pos, sizeof(uint64_t));
uint64_t v2;
::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
uint64_t v{v1 |
v2}; if ((v & 0x8080808080808080) ==
0) { size_t final_pos = pos + 16;
while (pos < final_pos) {
utf8_output[utf8_pos++] = char(data[pos]);
pos++;
}
continue;
}
} }
unsigned char byte = data[pos];
if ((byte & 0x80) == 0) { utf8_output[utf8_pos++] = char(byte);
pos++;
} else {
utf8_output[utf8_pos++] = char((byte >> 6) | 0b11000000);
utf8_output[utf8_pos++] = char((byte & 0b111111) | 0b10000000);
pos++;
}
} return utf8_pos;
}
simdutf_really_inline size_t convert(const char *buf, size_t len,
char *utf8_output) {
return convert(reinterpret_cast<const unsigned char *>(buf), len,
utf8_output);
}
inline size_t convert_safe(const char *buf, size_t len, char *utf8_output,
size_t utf8_len) {
const unsigned char *data = reinterpret_cast<const unsigned char *>(buf);
size_t pos = 0;
size_t skip_pos = 0;
size_t utf8_pos = 0;
while (pos < len && utf8_pos < utf8_len) {
if (pos >= skip_pos && pos + 16 <= len &&
utf8_pos + 16 <= utf8_len) { uint64_t v1;
::memcpy(&v1, data + pos, sizeof(uint64_t));
uint64_t v2;
::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
uint64_t v{v1 |
v2}; if ((v & 0x8080808080808080) ==
0) { ::memcpy(utf8_output + utf8_pos, buf + pos, 16);
utf8_pos += 16;
pos += 16;
} else {
skip_pos = pos + 16;
}
} else {
const auto byte = data[pos];
if ((byte & 0x80) == 0) { utf8_output[utf8_pos++] = char(byte);
pos++;
} else if (utf8_pos + 2 <= utf8_len) {
utf8_output[utf8_pos++] = char((byte >> 6) | 0b11000000);
utf8_output[utf8_pos++] = char((byte & 0b111111) | 0b10000000);
pos++;
} else {
break;
}
}
}
return utf8_pos;
}
template <typename InputPtr, typename OutputPtr>
#if SIMDUTF_CPLUSPLUS20
requires(simdutf::detail::indexes_into_byte_like<InputPtr> &&
simdutf::detail::index_assignable_from_char<OutputPtr>)
#endif
simdutf_constexpr23 size_t convert_safe_constexpr(InputPtr data, size_t len,
OutputPtr utf8_output,
size_t utf8_len) {
size_t pos = 0;
size_t utf8_pos = 0;
while (pos < len && utf8_pos < utf8_len) {
const unsigned char byte = data[pos];
if ((byte & 0x80) == 0) { utf8_output[utf8_pos++] = char(byte);
pos++;
} else if (utf8_pos + 2 <= utf8_len) {
utf8_output[utf8_pos++] = char((byte >> 6) | 0b11000000);
utf8_output[utf8_pos++] = char((byte & 0b111111) | 0b10000000);
pos++;
} else {
break;
}
}
return utf8_pos;
}
template <typename InputPtr>
#if SIMDUTF_CPLUSPLUS20
requires simdutf::detail::indexes_into_byte_like<InputPtr>
#endif
simdutf_constexpr23 simdutf_warn_unused size_t
utf8_length_from_latin1(InputPtr input, size_t length) noexcept {
size_t answer = length;
size_t i = 0;
#if SIMDUTF_CPLUSPLUS23
if !consteval
#endif
{
auto pop = [](uint64_t v) {
return (size_t)(((v >> 7) & UINT64_C(0x0101010101010101)) *
UINT64_C(0x0101010101010101) >>
56);
};
for (; i + 32 <= length; i += 32) {
uint64_t v;
memcpy(&v, input + i, 8);
answer += pop(v);
memcpy(&v, input + i + 8, sizeof(v));
answer += pop(v);
memcpy(&v, input + i + 16, sizeof(v));
answer += pop(v);
memcpy(&v, input + i + 24, sizeof(v));
answer += pop(v);
}
for (; i + 8 <= length; i += 8) {
uint64_t v;
memcpy(&v, input + i, sizeof(v));
answer += pop(v);
}
} for (; i + 1 <= length; i += 1) {
answer += static_cast<uint8_t>(input[i]) >> 7;
}
return answer;
}
} } } }
#endif
#ifndef SIMDUTF_UTF16_H
#define SIMDUTF_UTF16_H
namespace simdutf {
namespace scalar {
namespace utf16 {
template <endianness big_endian>
simdutf_warn_unused simdutf_constexpr23 bool
validate_as_ascii(const char16_t *data, size_t len) noexcept {
for (size_t pos = 0; pos < len; pos++) {
char16_t word = scalar::utf16::swap_if_needed<big_endian>(data[pos]);
if (word >= 0x80) {
return false;
}
}
return true;
}
template <endianness big_endian>
inline simdutf_warn_unused simdutf_constexpr23 bool
validate(const char16_t *data, size_t len) noexcept {
uint64_t pos = 0;
while (pos < len) {
char16_t word = scalar::utf16::swap_if_needed<big_endian>(data[pos]);
if ((word & 0xF800) == 0xD800) {
if (pos + 1 >= len) {
return false;
}
char16_t diff = char16_t(word - 0xD800);
if (diff > 0x3FF) {
return false;
}
char16_t next_word = !match_system(big_endian)
? u16_swap_bytes(data[pos + 1])
: data[pos + 1];
char16_t diff2 = char16_t(next_word - 0xDC00);
if (diff2 > 0x3FF) {
return false;
}
pos += 2;
} else {
pos++;
}
}
return true;
}
template <endianness big_endian>
inline simdutf_warn_unused simdutf_constexpr23 result
validate_with_errors(const char16_t *data, size_t len) noexcept {
size_t pos = 0;
while (pos < len) {
char16_t word = scalar::utf16::swap_if_needed<big_endian>(data[pos]);
if ((word & 0xF800) == 0xD800) {
if (pos + 1 >= len) {
return result(error_code::SURROGATE, pos);
}
char16_t diff = char16_t(word - 0xD800);
if (diff > 0x3FF) {
return result(error_code::SURROGATE, pos);
}
char16_t next_word = !match_system(big_endian)
? u16_swap_bytes(data[pos + 1])
: data[pos + 1];
char16_t diff2 = uint16_t(next_word - 0xDC00);
if (diff2 > 0x3FF) {
return result(error_code::SURROGATE, pos);
}
pos += 2;
} else {
pos++;
}
}
return result(error_code::SUCCESS, pos);
}
template <endianness big_endian>
simdutf_constexpr23 size_t count_code_points(const char16_t *p, size_t len) {
size_t counter{0};
for (size_t i = 0; i < len; i++) {
char16_t word = scalar::utf16::swap_if_needed<big_endian>(p[i]);
counter += ((word & 0xFC00) != 0xDC00);
}
return counter;
}
template <endianness big_endian>
simdutf_constexpr23 size_t utf8_length_from_utf16(const char16_t *p,
size_t len) {
size_t counter{0};
for (size_t i = 0; i < len; i++) {
char16_t word = scalar::utf16::swap_if_needed<big_endian>(p[i]);
counter++; counter += static_cast<size_t>(
word >
0x7F); counter += static_cast<size_t>((word > 0x7FF && word <= 0xD7FF) ||
(word >= 0xE000)); }
return counter;
}
template <endianness big_endian>
simdutf_constexpr23 size_t utf32_length_from_utf16(const char16_t *p,
size_t len) {
size_t counter{0};
for (size_t i = 0; i < len; i++) {
char16_t word = scalar::utf16::swap_if_needed<big_endian>(p[i]);
counter += ((word & 0xFC00) != 0xDC00);
}
return counter;
}
simdutf_really_inline simdutf_constexpr23 void
change_endianness_utf16(const char16_t *input, size_t size, char16_t *output) {
for (size_t i = 0; i < size; i++) {
*output++ = char16_t(input[i] >> 8 | input[i] << 8);
}
}
template <endianness big_endian>
simdutf_warn_unused simdutf_constexpr23 size_t
trim_partial_utf16(const char16_t *input, size_t length) {
if (length == 0) {
return 0;
}
uint16_t last_word = uint16_t(input[length - 1]);
last_word = scalar::utf16::swap_if_needed<big_endian>(last_word);
length -= ((last_word & 0xFC00) == 0xD800);
return length;
}
template <endianness big_endian> constexpr bool is_high_surrogate(char16_t c) {
c = scalar::utf16::swap_if_needed<big_endian>(c);
return (0xd800 <= c && c <= 0xdbff);
}
template <endianness big_endian> constexpr bool is_low_surrogate(char16_t c) {
c = scalar::utf16::swap_if_needed<big_endian>(c);
return (0xdc00 <= c && c <= 0xdfff);
}
simdutf_unused simdutf_really_inline constexpr bool high_surrogate(char16_t c) {
return (0xd800 <= c && c <= 0xdbff);
}
template <endianness big_endian>
simdutf_constexpr23 result
utf8_length_from_utf16_with_replacement(const char16_t *p, size_t len) {
bool any_surrogates = false;
size_t counter{0};
for (size_t i = 0; i < len; i++) {
if (is_high_surrogate<big_endian>(p[i])) {
any_surrogates = true;
if (i + 1 < len && is_low_surrogate<big_endian>(p[i + 1])) {
counter += 4;
i++; } else {
counter += 3; }
continue;
} else if (is_low_surrogate<big_endian>(p[i])) {
any_surrogates = true;
counter += 3; continue;
}
char16_t word = !match_system(big_endian) ? u16_swap_bytes(p[i]) : p[i];
counter++; counter +=
static_cast<size_t>(word > 0x7F); counter += static_cast<size_t>(word > 0x7FF); }
return {any_surrogates ? error_code::SURROGATE : error_code::SUCCESS,
counter};
}
template <endianness big_endian> constexpr char16_t replacement() {
return !match_system(big_endian) ? scalar::u16_swap_bytes(0xfffd) : 0xfffd;
}
template <endianness big_endian>
simdutf_constexpr23 void to_well_formed_utf16(const char16_t *input, size_t len,
char16_t *output) {
const char16_t replacement = utf16::replacement<big_endian>();
bool high_surrogate_prev = false, high_surrogate, low_surrogate;
size_t i = 0;
for (; i < len; i++) {
char16_t c = input[i];
high_surrogate = is_high_surrogate<big_endian>(c);
low_surrogate = is_low_surrogate<big_endian>(c);
if (high_surrogate_prev && !low_surrogate) {
output[i - 1] = replacement;
}
if (!high_surrogate_prev && low_surrogate) {
output[i] = replacement;
} else {
output[i] = input[i];
}
high_surrogate_prev = high_surrogate;
}
if (high_surrogate_prev) {
output[i - 1] = replacement;
}
}
} } }
#endif
#ifndef SIMDUTF_UTF16_TO_LATIN1_H
#define SIMDUTF_UTF16_TO_LATIN1_H
#include <cstring>
namespace simdutf {
namespace scalar {
namespace {
namespace utf16_to_latin1 {
template <endianness big_endian, typename InputPtr, typename OutputPtr>
#if SIMDUTF_CPLUSPLUS20
requires(simdutf::detail::indexes_into_utf16<InputPtr> &&
simdutf::detail::index_assignable_from_char<OutputPtr>)
#endif
simdutf_constexpr23 size_t convert(InputPtr data, size_t len,
OutputPtr latin_output) {
if (len == 0) {
return 0;
}
size_t pos = 0;
const auto latin_output_start = latin_output;
uint16_t word = 0;
uint16_t too_large = 0;
while (pos < len) {
word = !match_system(big_endian) ? u16_swap_bytes(data[pos]) : data[pos];
too_large |= word;
*latin_output++ = char(word & 0xFF);
pos++;
}
if ((too_large & 0xFF00) != 0) {
return 0;
}
return latin_output - latin_output_start;
}
template <endianness big_endian, typename InputPtr, typename OutputPtr>
#if SIMDUTF_CPLUSPLUS20
requires(simdutf::detail::indexes_into_utf16<InputPtr> &&
simdutf::detail::index_assignable_from_char<OutputPtr>)
#endif
simdutf_constexpr23 result convert_with_errors(InputPtr data, size_t len,
OutputPtr latin_output) {
if (len == 0) {
return result(error_code::SUCCESS, 0);
}
size_t pos = 0;
auto start = latin_output;
uint16_t word;
while (pos < len) {
#if SIMDUTF_CPLUSPLUS23
if !consteval
#endif
{
if (pos + 16 <= len) { uint64_t v1, v2, v3, v4;
::memcpy(&v1, data + pos, sizeof(uint64_t));
::memcpy(&v2, data + pos + 4, sizeof(uint64_t));
::memcpy(&v3, data + pos + 8, sizeof(uint64_t));
::memcpy(&v4, data + pos + 12, sizeof(uint64_t));
if constexpr (!match_system(big_endian)) {
v1 = (v1 >> 8) | (v1 << (64 - 8));
}
if constexpr (!match_system(big_endian)) {
v2 = (v2 >> 8) | (v2 << (64 - 8));
}
if constexpr (!match_system(big_endian)) {
v3 = (v3 >> 8) | (v3 << (64 - 8));
}
if constexpr (!match_system(big_endian)) {
v4 = (v4 >> 8) | (v4 << (64 - 8));
}
if (((v1 | v2 | v3 | v4) & 0xFF00FF00FF00FF00) == 0) {
size_t final_pos = pos + 16;
while (pos < final_pos) {
*latin_output++ = !match_system(big_endian)
? char(u16_swap_bytes(data[pos]))
: char(data[pos]);
pos++;
}
continue;
}
}
}
word = !match_system(big_endian) ? u16_swap_bytes(data[pos]) : data[pos];
if ((word & 0xFF00) == 0) {
*latin_output++ = char(word & 0xFF);
pos++;
} else {
return result(error_code::TOO_LARGE, pos);
}
}
return result(error_code::SUCCESS, latin_output - start);
}
} } } }
#endif
#ifndef SIMDUTF_VALID_UTF16_TO_LATIN1_H
#define SIMDUTF_VALID_UTF16_TO_LATIN1_H
namespace simdutf {
namespace scalar {
namespace {
namespace utf16_to_latin1 {
template <endianness big_endian, class InputIterator, class OutputIterator>
simdutf_constexpr23 inline size_t
convert_valid_impl(InputIterator data, size_t len,
OutputIterator latin_output) {
static_assert(
std::is_same<typename std::decay<decltype(*data)>::type, uint16_t>::value,
"must decay to uint16_t");
size_t pos = 0;
const auto start = latin_output;
uint16_t word = 0;
while (pos < len) {
word = !match_system(big_endian) ? u16_swap_bytes(data[pos]) : data[pos];
*latin_output++ = char(word);
pos++;
}
return latin_output - start;
}
template <endianness big_endian>
simdutf_really_inline size_t convert_valid(const char16_t *buf, size_t len,
char *latin_output) {
return convert_valid_impl<big_endian>(reinterpret_cast<const uint16_t *>(buf),
len, latin_output);
}
} } } }
#endif
#ifndef SIMDUTF_UTF16_TO_UTF32_H
#define SIMDUTF_UTF16_TO_UTF32_H
namespace simdutf {
namespace scalar {
namespace {
namespace utf16_to_utf32 {
template <endianness big_endian>
simdutf_constexpr23 size_t convert(const char16_t *data, size_t len,
char32_t *utf32_output) {
size_t pos = 0;
char32_t *start{utf32_output};
while (pos < len) {
uint16_t word =
!match_system(big_endian) ? u16_swap_bytes(data[pos]) : data[pos];
if ((word & 0xF800) != 0xD800) {
*utf32_output++ = char32_t(word);
pos++;
} else {
uint16_t diff = uint16_t(word - 0xD800);
if (diff > 0x3FF) {
return 0;
}
if (pos + 1 >= len) {
return 0;
} uint16_t next_word = !match_system(big_endian)
? u16_swap_bytes(data[pos + 1])
: data[pos + 1];
uint16_t diff2 = uint16_t(next_word - 0xDC00);
if (diff2 > 0x3FF) {
return 0;
}
uint32_t value = (diff << 10) + diff2 + 0x10000;
*utf32_output++ = char32_t(value);
pos += 2;
}
}
return utf32_output - start;
}
template <endianness big_endian>
simdutf_constexpr23 result convert_with_errors(const char16_t *data, size_t len,
char32_t *utf32_output) {
size_t pos = 0;
char32_t *start{utf32_output};
while (pos < len) {
uint16_t word =
!match_system(big_endian) ? u16_swap_bytes(data[pos]) : data[pos];
if ((word & 0xF800) != 0xD800) {
*utf32_output++ = char32_t(word);
pos++;
} else {
uint16_t diff = uint16_t(word - 0xD800);
if (diff > 0x3FF) {
return result(error_code::SURROGATE, pos);
}
if (pos + 1 >= len) {
return result(error_code::SURROGATE, pos);
} uint16_t next_word = !match_system(big_endian)
? u16_swap_bytes(data[pos + 1])
: data[pos + 1];
uint16_t diff2 = uint16_t(next_word - 0xDC00);
if (diff2 > 0x3FF) {
return result(error_code::SURROGATE, pos);
}
uint32_t value = (diff << 10) + diff2 + 0x10000;
*utf32_output++ = char32_t(value);
pos += 2;
}
}
return result(error_code::SUCCESS, utf32_output - start);
}
} } } }
#endif
#ifndef SIMDUTF_VALID_UTF16_TO_UTF32_H
#define SIMDUTF_VALID_UTF16_TO_UTF32_H
namespace simdutf {
namespace scalar {
namespace {
namespace utf16_to_utf32 {
template <endianness big_endian>
simdutf_constexpr23 size_t convert_valid(const char16_t *data, size_t len,
char32_t *utf32_output) {
size_t pos = 0;
char32_t *start{utf32_output};
while (pos < len) {
uint16_t word =
!match_system(big_endian) ? u16_swap_bytes(data[pos]) : data[pos];
if ((word & 0xF800) != 0xD800) {
*utf32_output++ = char32_t(word);
pos++;
} else {
uint16_t diff = uint16_t(word - 0xD800);
if (pos + 1 >= len) {
return 0;
} uint16_t next_word = !match_system(big_endian)
? u16_swap_bytes(data[pos + 1])
: data[pos + 1];
uint16_t diff2 = uint16_t(next_word - 0xDC00);
uint32_t value = (diff << 10) + diff2 + 0x10000;
*utf32_output++ = char32_t(value);
pos += 2;
}
}
return utf32_output - start;
}
} } } }
#endif
#ifndef SIMDUTF_UTF16_TO_UTF8_H
#define SIMDUTF_UTF16_TO_UTF8_H
#include <cstring>
namespace simdutf {
namespace scalar {
namespace {
namespace utf16_to_utf8 {
template <endianness big_endian, typename InputPtr, typename OutputPtr>
#if SIMDUTF_CPLUSPLUS20
requires simdutf::detail::indexes_into_utf16<InputPtr>
#endif
simdutf_constexpr23 size_t convert(InputPtr data, size_t len,
OutputPtr utf8_output) {
size_t pos = 0;
const auto start = utf8_output;
while (pos < len) {
#if SIMDUTF_CPLUSPLUS23
if !consteval
#endif
{
if (pos + 4 <= len) { uint64_t v;
::memcpy(&v, data + pos, sizeof(uint64_t));
if constexpr (!match_system(big_endian)) {
v = (v >> 8) | (v << (64 - 8));
}
if ((v & 0xFF80FF80FF80FF80) == 0) {
size_t final_pos = pos + 4;
while (pos < final_pos) {
*utf8_output++ = !match_system(big_endian)
? char(u16_swap_bytes(data[pos]))
: char(data[pos]);
pos++;
}
continue;
}
}
}
uint16_t word =
!match_system(big_endian) ? u16_swap_bytes(data[pos]) : data[pos];
if ((word & 0xFF80) == 0) {
*utf8_output++ = char(word);
pos++;
} else if ((word & 0xF800) == 0) {
*utf8_output++ = char((word >> 6) | 0b11000000);
*utf8_output++ = char((word & 0b111111) | 0b10000000);
pos++;
} else if ((word & 0xF800) != 0xD800) {
*utf8_output++ = char((word >> 12) | 0b11100000);
*utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
*utf8_output++ = char((word & 0b111111) | 0b10000000);
pos++;
} else {
if (pos + 1 >= len) {
return 0;
}
uint16_t diff = uint16_t(word - 0xD800);
if (diff > 0x3FF) {
return 0;
}
uint16_t next_word = !match_system(big_endian)
? u16_swap_bytes(data[pos + 1])
: data[pos + 1];
uint16_t diff2 = uint16_t(next_word - 0xDC00);
if (diff2 > 0x3FF) {
return 0;
}
uint32_t value = (diff << 10) + diff2 + 0x10000;
*utf8_output++ = char((value >> 18) | 0b11110000);
*utf8_output++ = char(((value >> 12) & 0b111111) | 0b10000000);
*utf8_output++ = char(((value >> 6) & 0b111111) | 0b10000000);
*utf8_output++ = char((value & 0b111111) | 0b10000000);
pos += 2;
}
}
return utf8_output - start;
}
template <endianness big_endian, bool check_output = false, typename InputPtr,
typename OutputPtr>
#if SIMDUTF_CPLUSPLUS20
requires(simdutf::detail::indexes_into_utf16<InputPtr> &&
simdutf::detail::index_assignable_from_char<OutputPtr>)
#endif
simdutf_constexpr23 full_result convert_with_errors(InputPtr data, size_t len,
OutputPtr utf8_output,
size_t utf8_len = 0) {
if (check_output && utf8_len == 0) {
return full_result(error_code::OUTPUT_BUFFER_TOO_SMALL, 0, 0);
}
size_t pos = 0;
auto start = utf8_output;
auto end = utf8_output + utf8_len;
while (pos < len) {
#if SIMDUTF_CPLUSPLUS23
if !consteval
#endif
{
if (pos + 4 <= len) { uint64_t v;
::memcpy(&v, data + pos, sizeof(uint64_t));
if constexpr (!match_system(big_endian))
v = (v >> 8) | (v << (64 - 8));
if ((v & 0xFF80FF80FF80FF80) == 0) {
size_t final_pos = pos + 4;
while (pos < final_pos) {
if (check_output && size_t(end - utf8_output) < 1) {
return full_result(error_code::OUTPUT_BUFFER_TOO_SMALL, pos,
utf8_output - start);
}
*utf8_output++ = !match_system(big_endian)
? char(u16_swap_bytes(data[pos]))
: char(data[pos]);
pos++;
}
continue;
}
}
}
uint16_t word =
!match_system(big_endian) ? u16_swap_bytes(data[pos]) : data[pos];
if ((word & 0xFF80) == 0) {
if (check_output && size_t(end - utf8_output) < 1) {
return full_result(error_code::OUTPUT_BUFFER_TOO_SMALL, pos,
utf8_output - start);
}
*utf8_output++ = char(word);
pos++;
} else if ((word & 0xF800) == 0) {
if (check_output && size_t(end - utf8_output) < 2) {
return full_result(error_code::OUTPUT_BUFFER_TOO_SMALL, pos,
utf8_output - start);
}
*utf8_output++ = char((word >> 6) | 0b11000000);
*utf8_output++ = char((word & 0b111111) | 0b10000000);
pos++;
} else if ((word & 0xF800) != 0xD800) {
if (check_output && size_t(end - utf8_output) < 3) {
return full_result(error_code::OUTPUT_BUFFER_TOO_SMALL, pos,
utf8_output - start);
}
*utf8_output++ = char((word >> 12) | 0b11100000);
*utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
*utf8_output++ = char((word & 0b111111) | 0b10000000);
pos++;
} else {
if (check_output && size_t(end - utf8_output) < 4) {
return full_result(error_code::OUTPUT_BUFFER_TOO_SMALL, pos,
utf8_output - start);
}
if (pos + 1 >= len) {
return full_result(error_code::SURROGATE, pos, utf8_output - start);
}
uint16_t diff = uint16_t(word - 0xD800);
if (diff > 0x3FF) {
return full_result(error_code::SURROGATE, pos, utf8_output - start);
}
uint16_t next_word = !match_system(big_endian)
? u16_swap_bytes(data[pos + 1])
: data[pos + 1];
uint16_t diff2 = uint16_t(next_word - 0xDC00);
if (diff2 > 0x3FF) {
return full_result(error_code::SURROGATE, pos, utf8_output - start);
}
uint32_t value = (diff << 10) + diff2 + 0x10000;
*utf8_output++ = char((value >> 18) | 0b11110000);
*utf8_output++ = char(((value >> 12) & 0b111111) | 0b10000000);
*utf8_output++ = char(((value >> 6) & 0b111111) | 0b10000000);
*utf8_output++ = char((value & 0b111111) | 0b10000000);
pos += 2;
}
}
return full_result(error_code::SUCCESS, pos, utf8_output - start);
}
template <endianness big_endian>
inline result simple_convert_with_errors(const char16_t *buf, size_t len,
char *utf8_output) {
return convert_with_errors<big_endian, false>(buf, len, utf8_output, 0);
}
template <endianness big_endian>
simdutf_constexpr23 size_t convert_with_replacement(const char16_t *data,
size_t len,
char *utf8_output) {
size_t pos = 0;
char *start = utf8_output;
while (pos < len) {
#if SIMDUTF_CPLUSPLUS23
if !consteval
#endif
{
if (pos + 4 <= len) { uint64_t v;
::memcpy(&v, data + pos, sizeof(uint64_t));
if constexpr (!match_system(big_endian)) {
v = (v >> 8) | (v << (64 - 8));
}
if ((v & 0xFF80FF80FF80FF80) == 0) {
size_t final_pos = pos + 4;
while (pos < final_pos) {
*utf8_output++ = !match_system(big_endian)
? char(u16_swap_bytes(data[pos]))
: char(data[pos]);
pos++;
}
continue;
}
}
}
uint16_t word =
!match_system(big_endian) ? u16_swap_bytes(data[pos]) : data[pos];
if ((word & 0xFF80) == 0) {
*utf8_output++ = char(word);
pos++;
} else if ((word & 0xF800) == 0) {
*utf8_output++ = char((word >> 6) | 0b11000000);
*utf8_output++ = char((word & 0b111111) | 0b10000000);
pos++;
} else if ((word & 0xF800) != 0xD800) {
*utf8_output++ = char((word >> 12) | 0b11100000);
*utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
*utf8_output++ = char((word & 0b111111) | 0b10000000);
pos++;
} else {
uint16_t diff = uint16_t(word - 0xD800);
if (diff <= 0x3FF && pos + 1 < len) {
uint16_t next_word = !match_system(big_endian)
? u16_swap_bytes(data[pos + 1])
: data[pos + 1];
uint16_t diff2 = uint16_t(next_word - 0xDC00);
if (diff2 <= 0x3FF) {
uint32_t value = (diff << 10) + diff2 + 0x10000;
*utf8_output++ = char((value >> 18) | 0b11110000);
*utf8_output++ = char(((value >> 12) & 0b111111) | 0b10000000);
*utf8_output++ = char(((value >> 6) & 0b111111) | 0b10000000);
*utf8_output++ = char((value & 0b111111) | 0b10000000);
pos += 2;
continue;
}
}
*utf8_output++ = char(0xef);
*utf8_output++ = char(0xbf);
*utf8_output++ = char(0xbd);
pos++;
}
}
return utf8_output - start;
}
} } } }
#endif
#ifndef SIMDUTF_VALID_UTF16_TO_UTF8_H
#define SIMDUTF_VALID_UTF16_TO_UTF8_H
#include <cstring>
namespace simdutf {
namespace scalar {
namespace {
namespace utf16_to_utf8 {
template <endianness big_endian, typename InputPtr, typename OutputPtr>
#if SIMDUTF_CPLUSPLUS20
requires(simdutf::detail::indexes_into_utf16<InputPtr> &&
simdutf::detail::index_assignable_from_char<OutputPtr>)
#endif
simdutf_constexpr23 size_t convert_valid(InputPtr data, size_t len,
OutputPtr utf8_output) {
size_t pos = 0;
auto start = utf8_output;
while (pos < len) {
#if SIMDUTF_CPLUSPLUS23
if !consteval
#endif
{
if (pos + 4 <= len) { uint64_t v;
::memcpy(&v, data + pos, sizeof(uint64_t));
if constexpr (!match_system(big_endian)) {
v = (v >> 8) | (v << (64 - 8));
}
if ((v & 0xFF80FF80FF80FF80) == 0) {
size_t final_pos = pos + 4;
while (pos < final_pos) {
*utf8_output++ = !match_system(big_endian)
? char(u16_swap_bytes(data[pos]))
: char(data[pos]);
pos++;
}
continue;
}
}
}
uint16_t word =
!match_system(big_endian) ? u16_swap_bytes(data[pos]) : data[pos];
if ((word & 0xFF80) == 0) {
*utf8_output++ = char(word);
pos++;
} else if ((word & 0xF800) == 0) {
*utf8_output++ = char((word >> 6) | 0b11000000);
*utf8_output++ = char((word & 0b111111) | 0b10000000);
pos++;
} else if ((word & 0xF800) != 0xD800) {
*utf8_output++ = char((word >> 12) | 0b11100000);
*utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
*utf8_output++ = char((word & 0b111111) | 0b10000000);
pos++;
} else {
uint16_t diff = uint16_t(word - 0xD800);
if (pos + 1 >= len) {
return 0;
} uint16_t next_word = !match_system(big_endian)
? u16_swap_bytes(data[pos + 1])
: data[pos + 1];
uint16_t diff2 = uint16_t(next_word - 0xDC00);
uint32_t value = (diff << 10) + diff2 + 0x10000;
*utf8_output++ = char((value >> 18) | 0b11110000);
*utf8_output++ = char(((value >> 12) & 0b111111) | 0b10000000);
*utf8_output++ = char(((value >> 6) & 0b111111) | 0b10000000);
*utf8_output++ = char((value & 0b111111) | 0b10000000);
pos += 2;
}
}
return utf8_output - start;
}
} } } }
#endif
#ifndef SIMDUTF_UTF32_H
#define SIMDUTF_UTF32_H
namespace simdutf {
namespace scalar {
namespace utf32 {
template <typename InputPtr>
#if SIMDUTF_CPLUSPLUS20
requires simdutf::detail::indexes_into_uint32<InputPtr>
#endif
simdutf_warn_unused simdutf_constexpr23 bool validate(InputPtr data,
size_t len) noexcept {
uint64_t pos = 0;
for (; pos < len; pos++) {
uint32_t word = data[pos];
if (word > 0x10FFFF || (word >= 0xD800 && word <= 0xDFFF)) {
return false;
}
}
return true;
}
simdutf_warn_unused simdutf_really_inline bool validate(const char32_t *buf,
size_t len) noexcept {
return validate(reinterpret_cast<const uint32_t *>(buf), len);
}
template <typename InputPtr>
#if SIMDUTF_CPLUSPLUS20
requires simdutf::detail::indexes_into_uint32<InputPtr>
#endif
simdutf_warn_unused simdutf_constexpr23 result
validate_with_errors(InputPtr data, size_t len) noexcept {
size_t pos = 0;
for (; pos < len; pos++) {
uint32_t word = data[pos];
if (word > 0x10FFFF) {
return result(error_code::TOO_LARGE, pos);
}
if (word >= 0xD800 && word <= 0xDFFF) {
return result(error_code::SURROGATE, pos);
}
}
return result(error_code::SUCCESS, pos);
}
simdutf_warn_unused simdutf_really_inline result
validate_with_errors(const char32_t *buf, size_t len) noexcept {
return validate_with_errors(reinterpret_cast<const uint32_t *>(buf), len);
}
inline simdutf_constexpr23 size_t utf8_length_from_utf32(const char32_t *p,
size_t len) {
size_t counter{0};
for (size_t i = 0; i < len; i++) {
counter++; counter += static_cast<size_t>(p[i] > 0x7F); counter += static_cast<size_t>(p[i] > 0x7FF); counter += static_cast<size_t>(p[i] > 0xFFFF); }
return counter;
}
inline simdutf_warn_unused simdutf_constexpr23 size_t
utf16_length_from_utf32(const char32_t *p, size_t len) {
size_t counter{0};
for (size_t i = 0; i < len; i++) {
counter++; counter += static_cast<size_t>(p[i] > 0xFFFF); }
return counter;
}
} } }
#endif
#ifndef SIMDUTF_UTF32_TO_LATIN1_H
#define SIMDUTF_UTF32_TO_LATIN1_H
#include <cstring>
namespace simdutf {
namespace scalar {
namespace {
namespace utf32_to_latin1 {
inline simdutf_constexpr23 size_t convert(const char32_t *data, size_t len,
char *latin1_output) {
char *start = latin1_output;
uint32_t utf32_char;
size_t pos = 0;
uint32_t too_large = 0;
while (pos < len) {
utf32_char = (uint32_t)data[pos];
too_large |= utf32_char;
*latin1_output++ = (char)(utf32_char & 0xFF);
pos++;
}
if ((too_large & 0xFFFFFF00) != 0) {
return 0;
}
return latin1_output - start;
}
inline simdutf_constexpr23 result convert_with_errors(const char32_t *data,
size_t len,
char *latin1_output) {
char *start{latin1_output};
size_t pos = 0;
while (pos < len) {
#if SIMDUTF_CPLUSPLUS23
if !consteval
#endif
{
if (pos + 2 <= len) { uint64_t v;
::memcpy(&v, data + pos, sizeof(uint64_t));
if ((v & 0xFFFFFF00FFFFFF00) == 0) {
*latin1_output++ = char(data[pos]);
*latin1_output++ = char(data[pos + 1]);
pos += 2;
continue;
}
}
}
uint32_t utf32_char = data[pos];
if ((utf32_char & 0xFFFFFF00) ==
0) { *latin1_output++ = (char)(utf32_char & 0xFF);
pos++;
} else {
return result(error_code::TOO_LARGE, pos);
};
}
return result(error_code::SUCCESS, latin1_output - start);
}
} } } }
#endif
#ifndef SIMDUTF_VALID_UTF32_TO_LATIN1_H
#define SIMDUTF_VALID_UTF32_TO_LATIN1_H
#include <cstring>
namespace simdutf {
namespace scalar {
namespace {
namespace utf32_to_latin1 {
template <typename ReadPtr, typename WritePtr>
simdutf_constexpr23 size_t convert_valid(ReadPtr data, size_t len,
WritePtr latin1_output) {
static_assert(
std::is_same<typename std::decay<decltype(*data)>::type, uint32_t>::value,
"dereferencing the data pointer must result in a uint32_t");
auto start = latin1_output;
uint32_t utf32_char;
size_t pos = 0;
while (pos < len) {
utf32_char = data[pos];
#if SIMDUTF_CPLUSPLUS23
if !consteval {
#endif
if (pos + 2 <= len) {
uint64_t v;
std::memcpy(&v, data + pos, sizeof(uint64_t));
if ((v & 0xFFFFFF00FFFFFF00) == 0) {
*latin1_output++ = char(data[pos]);
*latin1_output++ = char(data[pos + 1]);
pos += 2;
continue;
} else {
return 0;
}
}
#if SIMDUTF_CPLUSPLUS23
} #endif
if ((utf32_char & 0xFFFFFF00) == 0) {
*latin1_output++ = char(utf32_char);
} else {
return 0;
}
pos++;
}
return latin1_output - start;
}
simdutf_really_inline size_t convert_valid(const char32_t *buf, size_t len,
char *latin1_output) {
return convert_valid(reinterpret_cast<const uint32_t *>(buf), len,
latin1_output);
}
} } } }
#endif
#ifndef SIMDUTF_UTF32_TO_UTF16_H
#define SIMDUTF_UTF32_TO_UTF16_H
namespace simdutf {
namespace scalar {
namespace {
namespace utf32_to_utf16 {
template <endianness big_endian>
simdutf_constexpr23 size_t convert(const char32_t *data, size_t len,
char16_t *utf16_output) {
size_t pos = 0;
char16_t *start{utf16_output};
while (pos < len) {
uint32_t word = data[pos];
if ((word & 0xFFFF0000) == 0) {
if (word >= 0xD800 && word <= 0xDFFF) {
return 0;
}
*utf16_output++ = !match_system(big_endian)
? char16_t(u16_swap_bytes(uint16_t(word)))
: char16_t(word);
} else {
if (word > 0x10FFFF) {
return 0;
}
word -= 0x10000;
uint16_t high_surrogate = uint16_t(0xD800 + (word >> 10));
uint16_t low_surrogate = uint16_t(0xDC00 + (word & 0x3FF));
if constexpr (!match_system(big_endian)) {
high_surrogate = u16_swap_bytes(high_surrogate);
low_surrogate = u16_swap_bytes(low_surrogate);
}
*utf16_output++ = char16_t(high_surrogate);
*utf16_output++ = char16_t(low_surrogate);
}
pos++;
}
return utf16_output - start;
}
template <endianness big_endian>
simdutf_constexpr23 result convert_with_errors(const char32_t *data, size_t len,
char16_t *utf16_output) {
size_t pos = 0;
char16_t *start{utf16_output};
while (pos < len) {
uint32_t word = data[pos];
if ((word & 0xFFFF0000) == 0) {
if (word >= 0xD800 && word <= 0xDFFF) {
return result(error_code::SURROGATE, pos);
}
*utf16_output++ = !match_system(big_endian)
? char16_t(u16_swap_bytes(uint16_t(word)))
: char16_t(word);
} else {
if (word > 0x10FFFF) {
return result(error_code::TOO_LARGE, pos);
}
word -= 0x10000;
uint16_t high_surrogate = uint16_t(0xD800 + (word >> 10));
uint16_t low_surrogate = uint16_t(0xDC00 + (word & 0x3FF));
if constexpr (!match_system(big_endian)) {
high_surrogate = u16_swap_bytes(high_surrogate);
low_surrogate = u16_swap_bytes(low_surrogate);
}
*utf16_output++ = char16_t(high_surrogate);
*utf16_output++ = char16_t(low_surrogate);
}
pos++;
}
return result(error_code::SUCCESS, utf16_output - start);
}
} } } }
#endif
#ifndef SIMDUTF_VALID_UTF32_TO_UTF16_H
#define SIMDUTF_VALID_UTF32_TO_UTF16_H
namespace simdutf {
namespace scalar {
namespace {
namespace utf32_to_utf16 {
template <endianness big_endian>
simdutf_constexpr23 size_t convert_valid(const char32_t *data, size_t len,
char16_t *utf16_output) {
size_t pos = 0;
char16_t *start{utf16_output};
while (pos < len) {
uint32_t word = data[pos];
if ((word & 0xFFFF0000) == 0) {
*utf16_output++ = !match_system(big_endian)
? char16_t(u16_swap_bytes(uint16_t(word)))
: char16_t(word);
pos++;
} else {
word -= 0x10000;
uint16_t high_surrogate = uint16_t(0xD800 + (word >> 10));
uint16_t low_surrogate = uint16_t(0xDC00 + (word & 0x3FF));
if constexpr (!match_system(big_endian)) {
high_surrogate = u16_swap_bytes(high_surrogate);
low_surrogate = u16_swap_bytes(low_surrogate);
}
*utf16_output++ = char16_t(high_surrogate);
*utf16_output++ = char16_t(low_surrogate);
pos++;
}
}
return utf16_output - start;
}
} } } }
#endif
#ifndef SIMDUTF_UTF32_TO_UTF8_H
#define SIMDUTF_UTF32_TO_UTF8_H
#include <cstring>
namespace simdutf {
namespace scalar {
namespace {
namespace utf32_to_utf8 {
template <typename InputPtr, typename OutputPtr>
#if SIMDUTF_CPLUSPLUS20
requires(simdutf::detail::indexes_into_utf32<InputPtr> &&
simdutf::detail::index_assignable_from_char<OutputPtr>)
#endif
simdutf_constexpr23 size_t convert(InputPtr data, size_t len,
OutputPtr utf8_output) {
size_t pos = 0;
auto start = utf8_output;
while (pos < len) {
#if SIMDUTF_CPLUSPLUS23
if !consteval
#endif
{ if (pos + 2 <= len) { uint64_t v;
::memcpy(&v, data + pos, sizeof(uint64_t));
if ((v & 0xFFFFFF80FFFFFF80) == 0) {
*utf8_output++ = char(data[pos]);
*utf8_output++ = char(data[pos + 1]);
pos += 2;
continue;
}
}
}
uint32_t word = data[pos];
if ((word & 0xFFFFFF80) == 0) {
*utf8_output++ = char(word);
pos++;
} else if ((word & 0xFFFFF800) == 0) {
*utf8_output++ = char((word >> 6) | 0b11000000);
*utf8_output++ = char((word & 0b111111) | 0b10000000);
pos++;
} else if ((word & 0xFFFF0000) == 0) {
if (word >= 0xD800 && word <= 0xDFFF) {
return 0;
}
*utf8_output++ = char((word >> 12) | 0b11100000);
*utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
*utf8_output++ = char((word & 0b111111) | 0b10000000);
pos++;
} else {
if (word > 0x10FFFF) {
return 0;
}
*utf8_output++ = char((word >> 18) | 0b11110000);
*utf8_output++ = char(((word >> 12) & 0b111111) | 0b10000000);
*utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
*utf8_output++ = char((word & 0b111111) | 0b10000000);
pos++;
}
}
return utf8_output - start;
}
template <typename InputPtr, typename OutputPtr>
#if SIMDUTF_CPLUSPLUS20
requires(simdutf::detail::indexes_into_utf32<InputPtr> &&
simdutf::detail::index_assignable_from_char<OutputPtr>)
#endif
simdutf_constexpr23 result convert_with_errors(InputPtr data, size_t len,
OutputPtr utf8_output) {
size_t pos = 0;
auto start = utf8_output;
while (pos < len) {
#if SIMDUTF_CPLUSPLUS23
if !consteval
#endif
{ if (pos + 2 <= len) { uint64_t v;
::memcpy(&v, data + pos, sizeof(uint64_t));
if ((v & 0xFFFFFF80FFFFFF80) == 0) {
*utf8_output++ = char(data[pos]);
*utf8_output++ = char(data[pos + 1]);
pos += 2;
continue;
}
}
}
uint32_t word = data[pos];
if ((word & 0xFFFFFF80) == 0) {
*utf8_output++ = char(word);
pos++;
} else if ((word & 0xFFFFF800) == 0) {
*utf8_output++ = char((word >> 6) | 0b11000000);
*utf8_output++ = char((word & 0b111111) | 0b10000000);
pos++;
} else if ((word & 0xFFFF0000) == 0) {
if (word >= 0xD800 && word <= 0xDFFF) {
return result(error_code::SURROGATE, pos);
}
*utf8_output++ = char((word >> 12) | 0b11100000);
*utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
*utf8_output++ = char((word & 0b111111) | 0b10000000);
pos++;
} else {
if (word > 0x10FFFF) {
return result(error_code::TOO_LARGE, pos);
}
*utf8_output++ = char((word >> 18) | 0b11110000);
*utf8_output++ = char(((word >> 12) & 0b111111) | 0b10000000);
*utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
*utf8_output++ = char((word & 0b111111) | 0b10000000);
pos++;
}
}
return result(error_code::SUCCESS, utf8_output - start);
}
} } } }
#endif
#ifndef SIMDUTF_VALID_UTF32_TO_UTF8_H
#define SIMDUTF_VALID_UTF32_TO_UTF8_H
#include <cstring>
namespace simdutf {
namespace scalar {
namespace {
namespace utf32_to_utf8 {
template <typename InputPtr, typename OutputPtr>
#if SIMDUTF_CPLUSPLUS20
requires(simdutf::detail::indexes_into_utf32<InputPtr> &&
simdutf::detail::index_assignable_from_char<OutputPtr>)
#endif
simdutf_constexpr23 size_t convert_valid(InputPtr data, size_t len,
OutputPtr utf8_output) {
size_t pos = 0;
auto start = utf8_output;
while (pos < len) {
#if SIMDUTF_CPLUSPLUS23
if !consteval
#endif
{ if (pos + 2 <= len) { uint64_t v;
::memcpy(&v, data + pos, sizeof(uint64_t));
if ((v & 0xFFFFFF80FFFFFF80) == 0) {
*utf8_output++ = char(data[pos]);
*utf8_output++ = char(data[pos + 1]);
pos += 2;
continue;
}
}
}
uint32_t word = data[pos];
if ((word & 0xFFFFFF80) == 0) {
*utf8_output++ = char(word);
pos++;
} else if ((word & 0xFFFFF800) == 0) {
*utf8_output++ = char((word >> 6) | 0b11000000);
*utf8_output++ = char((word & 0b111111) | 0b10000000);
pos++;
} else if ((word & 0xFFFF0000) == 0) {
*utf8_output++ = char((word >> 12) | 0b11100000);
*utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
*utf8_output++ = char((word & 0b111111) | 0b10000000);
pos++;
} else {
*utf8_output++ = char((word >> 18) | 0b11110000);
*utf8_output++ = char(((word >> 12) & 0b111111) | 0b10000000);
*utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
*utf8_output++ = char((word & 0b111111) | 0b10000000);
pos++;
}
}
return utf8_output - start;
}
} } } }
#endif
#ifndef SIMDUTF_UTF8_H
#define SIMDUTF_UTF8_H
#include <cstring>
namespace simdutf {
namespace scalar {
namespace {
namespace utf8 {
template <class BytePtr>
simdutf_constexpr23 simdutf_warn_unused bool validate(BytePtr data,
size_t len) noexcept {
static_assert(
std::is_same<typename std::decay<decltype(*data)>::type, uint8_t>::value,
"dereferencing the data pointer must result in a uint8_t");
uint64_t pos = 0;
uint32_t code_point = 0;
while (pos < len) {
uint64_t next_pos;
#if SIMDUTF_CPLUSPLUS23
if !consteval
#endif
{ next_pos = pos + 16;
if (next_pos <= len) { uint64_t v1{};
std::memcpy(&v1, data + pos, sizeof(uint64_t));
uint64_t v2{};
std::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
uint64_t v{v1 | v2};
if ((v & 0x8080808080808080) == 0) {
pos = next_pos;
continue;
}
}
}
unsigned char byte = data[pos];
while (byte < 0b10000000) {
if (++pos == len) {
return true;
}
byte = data[pos];
}
if ((byte & 0b11100000) == 0b11000000) {
next_pos = pos + 2;
if (next_pos > len) {
return false;
}
if ((data[pos + 1] & 0b11000000) != 0b10000000) {
return false;
}
code_point = (byte & 0b00011111) << 6 | (data[pos + 1] & 0b00111111);
if (code_point < 0x80) {
return false;
}
} else if ((byte & 0b11110000) == 0b11100000) {
next_pos = pos + 3;
if (next_pos > len) {
return false;
}
if ((data[pos + 1] & 0b11000000) != 0b10000000) {
return false;
}
if ((data[pos + 2] & 0b11000000) != 0b10000000) {
return false;
}
code_point = (byte & 0b00001111) << 12 |
(data[pos + 1] & 0b00111111) << 6 |
(data[pos + 2] & 0b00111111);
if ((code_point < 0x800) ||
(0xd7ff < code_point && code_point < 0xe000)) {
return false;
}
} else if ((byte & 0b11111000) == 0b11110000) { next_pos = pos + 4;
if (next_pos > len) {
return false;
}
if ((data[pos + 1] & 0b11000000) != 0b10000000) {
return false;
}
if ((data[pos + 2] & 0b11000000) != 0b10000000) {
return false;
}
if ((data[pos + 3] & 0b11000000) != 0b10000000) {
return false;
}
code_point =
(byte & 0b00000111) << 18 | (data[pos + 1] & 0b00111111) << 12 |
(data[pos + 2] & 0b00111111) << 6 | (data[pos + 3] & 0b00111111);
if (code_point <= 0xffff || 0x10ffff < code_point) {
return false;
}
} else {
return false;
}
pos = next_pos;
}
return true;
}
simdutf_really_inline simdutf_warn_unused bool validate(const char *buf,
size_t len) noexcept {
return validate(reinterpret_cast<const uint8_t *>(buf), len);
}
template <class BytePtr>
simdutf_constexpr23 simdutf_warn_unused result
validate_with_errors(BytePtr data, size_t len) noexcept {
static_assert(
std::is_same<typename std::decay<decltype(*data)>::type, uint8_t>::value,
"dereferencing the data pointer must result in a uint8_t");
size_t pos = 0;
uint32_t code_point = 0;
while (pos < len) {
size_t next_pos = pos + 16;
if (next_pos <=
len) { uint64_t v1;
std::memcpy(&v1, data + pos, sizeof(uint64_t));
uint64_t v2;
std::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
uint64_t v{v1 | v2};
if ((v & 0x8080808080808080) == 0) {
pos = next_pos;
continue;
}
}
unsigned char byte = data[pos];
while (byte < 0b10000000) {
if (++pos == len) {
return result(error_code::SUCCESS, len);
}
byte = data[pos];
}
if ((byte & 0b11100000) == 0b11000000) {
next_pos = pos + 2;
if (next_pos > len) {
return result(error_code::TOO_SHORT, pos);
}
if ((data[pos + 1] & 0b11000000) != 0b10000000) {
return result(error_code::TOO_SHORT, pos);
}
code_point = (byte & 0b00011111) << 6 | (data[pos + 1] & 0b00111111);
if (code_point < 0x80) {
return result(error_code::OVERLONG, pos);
}
} else if ((byte & 0b11110000) == 0b11100000) {
next_pos = pos + 3;
if (next_pos > len) {
return result(error_code::TOO_SHORT, pos);
}
if ((data[pos + 1] & 0b11000000) != 0b10000000) {
return result(error_code::TOO_SHORT, pos);
}
if ((data[pos + 2] & 0b11000000) != 0b10000000) {
return result(error_code::TOO_SHORT, pos);
}
code_point = (byte & 0b00001111) << 12 |
(data[pos + 1] & 0b00111111) << 6 |
(data[pos + 2] & 0b00111111);
if (code_point < 0x800) {
return result(error_code::OVERLONG, pos);
}
if (0xd7ff < code_point && code_point < 0xe000) {
return result(error_code::SURROGATE, pos);
}
} else if ((byte & 0b11111000) == 0b11110000) { next_pos = pos + 4;
if (next_pos > len) {
return result(error_code::TOO_SHORT, pos);
}
if ((data[pos + 1] & 0b11000000) != 0b10000000) {
return result(error_code::TOO_SHORT, pos);
}
if ((data[pos + 2] & 0b11000000) != 0b10000000) {
return result(error_code::TOO_SHORT, pos);
}
if ((data[pos + 3] & 0b11000000) != 0b10000000) {
return result(error_code::TOO_SHORT, pos);
}
code_point =
(byte & 0b00000111) << 18 | (data[pos + 1] & 0b00111111) << 12 |
(data[pos + 2] & 0b00111111) << 6 | (data[pos + 3] & 0b00111111);
if (code_point <= 0xffff) {
return result(error_code::OVERLONG, pos);
}
if (0x10ffff < code_point) {
return result(error_code::TOO_LARGE, pos);
}
} else {
if ((byte & 0b11000000) == 0b10000000) {
return result(error_code::TOO_LONG, pos);
} else {
return result(error_code::HEADER_BITS, pos);
}
}
pos = next_pos;
}
return result(error_code::SUCCESS, len);
}
simdutf_really_inline simdutf_warn_unused result
validate_with_errors(const char *buf, size_t len) noexcept {
return validate_with_errors(reinterpret_cast<const uint8_t *>(buf), len);
}
inline simdutf_warn_unused result rewind_and_validate_with_errors(
const char *start, const char *buf, size_t len) noexcept {
if ((*start & 0b11000000) == 0b10000000) {
return result(error_code::TOO_LONG, 0);
}
size_t extra_len{0};
for (int i = 0; i < 5; i++) {
unsigned char byte = *buf;
if ((byte & 0b11000000) != 0b10000000) {
break;
} else {
buf--;
extra_len++;
}
}
result res = validate_with_errors(buf, len + extra_len);
res.count -= extra_len; return res;
}
template <typename InputPtr>
#if SIMDUTF_CPLUSPLUS20
requires simdutf::detail::indexes_into_byte_like<InputPtr>
#endif
simdutf_constexpr23 size_t count_code_points(InputPtr data, size_t len) {
size_t counter{0};
for (size_t i = 0; i < len; i++) {
if (int8_t(data[i]) > -65) {
counter++;
}
}
return counter;
}
template <typename InputPtr>
#if SIMDUTF_CPLUSPLUS20
requires simdutf::detail::indexes_into_byte_like<InputPtr>
#endif
simdutf_constexpr23 size_t utf16_length_from_utf8(InputPtr data, size_t len) {
size_t counter{0};
for (size_t i = 0; i < len; i++) {
if (int8_t(data[i]) > -65) {
counter++;
}
if (uint8_t(data[i]) >= 240) {
counter++;
}
}
return counter;
}
template <typename InputPtr>
#if SIMDUTF_CPLUSPLUS20
requires simdutf::detail::indexes_into_byte_like<InputPtr>
#endif
simdutf_warn_unused simdutf_constexpr23 size_t
trim_partial_utf8(InputPtr input, size_t length) {
if (length < 3) {
switch (length) {
case 2:
if (uint8_t(input[length - 1]) >= 0xc0) {
return length - 1;
} if (uint8_t(input[length - 2]) >= 0xe0) {
return length - 2;
} return length;
case 1:
if (uint8_t(input[length - 1]) >= 0xc0) {
return length - 1;
} return length;
case 0:
return length;
}
}
if (uint8_t(input[length - 1]) >= 0xc0) {
return length - 1;
} if (uint8_t(input[length - 2]) >= 0xe0) {
return length - 2;
} if (uint8_t(input[length - 3]) >= 0xf0) {
return length - 3;
} return length;
}
} } } }
#endif
#ifndef SIMDUTF_UTF8_TO_LATIN1_H
#define SIMDUTF_UTF8_TO_LATIN1_H
#include <cstring>
namespace simdutf {
namespace scalar {
namespace {
namespace utf8_to_latin1 {
template <typename InputPtr, typename OutputPtr>
#if SIMDUTF_CPLUSPLUS20
requires(simdutf::detail::indexes_into_byte_like<InputPtr> &&
simdutf::detail::indexes_into_byte_like<OutputPtr>)
#endif
simdutf_constexpr23 size_t convert(InputPtr data, size_t len,
OutputPtr latin_output) {
size_t pos = 0;
auto start = latin_output;
while (pos < len) {
#if SIMDUTF_CPLUSPLUS23
if !consteval
#endif
{
if (pos + 16 <= len) { uint64_t v1;
::memcpy(&v1, data + pos, sizeof(uint64_t));
uint64_t v2;
::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
uint64_t v{v1 | v2}; if ((v & 0x8080808080808080) ==
0) { size_t final_pos = pos + 16;
while (pos < final_pos) {
*latin_output++ = char(data[pos]);
pos++;
}
continue;
}
}
}
uint8_t leading_byte = data[pos]; if (leading_byte < 0b10000000) {
*latin_output++ = char(leading_byte);
pos++;
} else if ((leading_byte & 0b11100000) ==
0b11000000) { if (pos + 1 >= len) {
return 0;
} if ((data[pos + 1] & 0b11000000) != 0b10000000) {
return 0;
} uint32_t code_point =
(leading_byte & 0b00011111) << 6 |
(data[pos + 1] &
0b00111111); if (code_point < 0x80 || 0xFF < code_point) {
return 0; }
*latin_output++ = char(code_point);
pos += 2;
} else {
return 0;
}
}
return latin_output - start;
}
template <typename InputPtr>
#if SIMDUTF_CPLUSPLUS20
requires simdutf::detail::indexes_into_byte_like<InputPtr>
#endif
simdutf_constexpr23 result convert_with_errors(InputPtr data, size_t len,
char *latin_output) {
size_t pos = 0;
char *start{latin_output};
while (pos < len) {
#if SIMDUTF_CPLUSPLUS23
if !consteval
#endif
{
if (pos + 16 <= len) { uint64_t v1;
::memcpy(&v1, data + pos, sizeof(uint64_t));
uint64_t v2;
::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
uint64_t v{v1 | v2}; if ((v & 0x8080808080808080) ==
0) { size_t final_pos = pos + 16;
while (pos < final_pos) {
*latin_output++ = char(data[pos]);
pos++;
}
continue;
}
}
}
uint8_t leading_byte = data[pos]; if (leading_byte < 0b10000000) {
*latin_output++ = char(leading_byte);
pos++;
} else if ((leading_byte & 0b11100000) ==
0b11000000) { if (pos + 1 >= len) {
return result(error_code::TOO_SHORT, pos);
} if ((data[pos + 1] & 0b11000000) != 0b10000000) {
return result(error_code::TOO_SHORT, pos);
} uint32_t code_point =
(leading_byte & 0b00011111) << 6 |
(data[pos + 1] &
0b00111111); if (code_point < 0x80) {
return result(error_code::OVERLONG, pos);
}
if (0xFF < code_point) {
return result(error_code::TOO_LARGE, pos);
} *latin_output++ = char(code_point);
pos += 2;
} else if ((leading_byte & 0b11110000) == 0b11100000) {
return result(error_code::TOO_LARGE, pos);
} else if ((leading_byte & 0b11111000) == 0b11110000) { return result(error_code::TOO_LARGE, pos);
} else {
if ((leading_byte & 0b11000000) == 0b10000000) {
return result(error_code::TOO_LONG, pos);
}
return result(error_code::HEADER_BITS, pos);
}
}
return result(error_code::SUCCESS, latin_output - start);
}
inline result rewind_and_convert_with_errors(size_t prior_bytes,
const char *buf, size_t len,
char *latin1_output) {
size_t extra_len{0};
size_t how_far_back = prior_bytes;
bool found_leading_bytes{false};
for (size_t i = 0; i <= how_far_back; i++) {
unsigned char byte = buf[-static_cast<std::ptrdiff_t>(i)];
found_leading_bytes = ((byte & 0b11000000) != 0b10000000);
if (found_leading_bytes) {
if (i > 0 && byte < 128) {
return result(error_code::TOO_LONG, 0 - i + 1);
}
buf -= i;
extra_len = i;
break;
}
}
if (!found_leading_bytes) {
return result(error_code::TOO_LONG, 0 - how_far_back);
}
result res = convert_with_errors(buf, len + extra_len, latin1_output);
if (res.error) {
res.count -= extra_len;
}
return res;
}
} } } }
#endif
#ifndef SIMDUTF_VALID_UTF8_TO_LATIN1_H
#define SIMDUTF_VALID_UTF8_TO_LATIN1_H
#include <cstring>
namespace simdutf {
namespace scalar {
namespace {
namespace utf8_to_latin1 {
template <typename InputPtr>
#if SIMDUTF_CPLUSPLUS20
requires simdutf::detail::indexes_into_byte_like<InputPtr>
#endif
simdutf_constexpr23 size_t convert_valid(InputPtr data, size_t len,
char *latin_output) {
size_t pos = 0;
char *start{latin_output};
while (pos < len) {
#if SIMDUTF_CPLUSPLUS23
if !consteval
#endif
{
if (pos + 16 <= len) { uint64_t v1;
::memcpy(&v1, data + pos, sizeof(uint64_t));
uint64_t v2;
::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
uint64_t v{v1 |
v2}; if ((v & 0x8080808080808080) ==
0) { size_t final_pos = pos + 16;
while (pos < final_pos) {
*latin_output++ = uint8_t(data[pos]);
pos++;
}
continue;
}
}
}
auto leading_byte = uint8_t(data[pos]); if (leading_byte < 0b10000000) {
*latin_output++ = char(leading_byte);
pos++;
} else if ((leading_byte & 0b11100000) ==
0b11000000) { if (pos + 1 >= len) {
break;
} if ((uint8_t(data[pos + 1]) & 0b11000000) != 0b10000000) {
return 0;
} uint32_t code_point =
(leading_byte & 0b00011111) << 6 |
(uint8_t(data[pos + 1]) &
0b00111111); *latin_output++ = char(code_point);
pos += 2;
} else {
return 0;
}
}
return latin_output - start;
}
} } } }
#endif
#ifndef SIMDUTF_UTF8_TO_UTF16_H
#define SIMDUTF_UTF8_TO_UTF16_H
#include <cstring>
namespace simdutf {
namespace scalar {
namespace {
namespace utf8_to_utf16 {
template <endianness big_endian, typename InputPtr>
#if SIMDUTF_CPLUSPLUS20
requires simdutf::detail::indexes_into_byte_like<InputPtr>
#endif
simdutf_constexpr23 size_t convert(InputPtr data, size_t len,
char16_t *utf16_output) {
size_t pos = 0;
char16_t *start{utf16_output};
while (pos < len) {
#if SIMDUTF_CPLUSPLUS23
if !consteval
#endif
{
if (pos + 16 <= len) { uint64_t v1;
::memcpy(&v1, data + pos, sizeof(uint64_t));
uint64_t v2;
::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
uint64_t v{v1 | v2};
if ((v & 0x8080808080808080) == 0) {
size_t final_pos = pos + 16;
while (pos < final_pos) {
*utf16_output++ = !match_system(big_endian)
? char16_t(u16_swap_bytes(data[pos]))
: char16_t(data[pos]);
pos++;
}
continue;
}
}
}
uint8_t leading_byte = data[pos]; if (leading_byte < 0b10000000) {
*utf16_output++ = !match_system(big_endian)
? char16_t(u16_swap_bytes(leading_byte))
: char16_t(leading_byte);
pos++;
} else if ((leading_byte & 0b11100000) == 0b11000000) {
if (pos + 1 >= len) {
return 0;
} if ((data[pos + 1] & 0b11000000) != 0b10000000) {
return 0;
}
uint32_t code_point =
(leading_byte & 0b00011111) << 6 | (data[pos + 1] & 0b00111111);
if (code_point < 0x80) {
return 0;
}
if constexpr (!match_system(big_endian)) {
code_point = uint32_t(u16_swap_bytes(uint16_t(code_point)));
}
*utf16_output++ = char16_t(code_point);
pos += 2;
} else if ((leading_byte & 0b11110000) == 0b11100000) {
if (pos + 2 >= len) {
return 0;
}
if ((data[pos + 1] & 0b11000000) != 0b10000000) {
return 0;
}
if ((data[pos + 2] & 0b11000000) != 0b10000000) {
return 0;
}
uint32_t code_point = (leading_byte & 0b00001111) << 12 |
(data[pos + 1] & 0b00111111) << 6 |
(data[pos + 2] & 0b00111111);
if (code_point < 0x800 || (0xd7ff < code_point && code_point < 0xe000)) {
return 0;
}
if constexpr (!match_system(big_endian)) {
code_point = uint32_t(u16_swap_bytes(uint16_t(code_point)));
}
*utf16_output++ = char16_t(code_point);
pos += 3;
} else if ((leading_byte & 0b11111000) == 0b11110000) { if (pos + 3 >= len) {
return 0;
} if ((data[pos + 1] & 0b11000000) != 0b10000000) {
return 0;
}
if ((data[pos + 2] & 0b11000000) != 0b10000000) {
return 0;
}
if ((data[pos + 3] & 0b11000000) != 0b10000000) {
return 0;
}
uint32_t code_point = (leading_byte & 0b00000111) << 18 |
(data[pos + 1] & 0b00111111) << 12 |
(data[pos + 2] & 0b00111111) << 6 |
(data[pos + 3] & 0b00111111);
if (code_point <= 0xffff || 0x10ffff < code_point) {
return 0;
}
code_point -= 0x10000;
uint16_t high_surrogate = uint16_t(0xD800 + (code_point >> 10));
uint16_t low_surrogate = uint16_t(0xDC00 + (code_point & 0x3FF));
if constexpr (!match_system(big_endian)) {
high_surrogate = u16_swap_bytes(high_surrogate);
low_surrogate = u16_swap_bytes(low_surrogate);
}
*utf16_output++ = char16_t(high_surrogate);
*utf16_output++ = char16_t(low_surrogate);
pos += 4;
} else {
return 0;
}
}
return utf16_output - start;
}
template <endianness big_endian, typename InputPtr>
#if SIMDUTF_CPLUSPLUS20
requires simdutf::detail::indexes_into_byte_like<InputPtr>
#endif
simdutf_constexpr23 result convert_with_errors(InputPtr data, size_t len,
char16_t *utf16_output) {
size_t pos = 0;
char16_t *start{utf16_output};
while (pos < len) {
#if SIMDUTF_CPLUSPLUS23
if !consteval
#endif
{
if (pos + 16 <= len) { uint64_t v1;
::memcpy(&v1, data + pos, sizeof(uint64_t));
uint64_t v2;
::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
uint64_t v{v1 | v2};
if ((v & 0x8080808080808080) == 0) {
size_t final_pos = pos + 16;
while (pos < final_pos) {
const char16_t byte = uint8_t(data[pos]);
*utf16_output++ =
!match_system(big_endian) ? u16_swap_bytes(byte) : byte;
pos++;
}
continue;
}
}
}
auto leading_byte = uint8_t(data[pos]); if (leading_byte < 0b10000000) {
*utf16_output++ = !match_system(big_endian)
? char16_t(u16_swap_bytes(leading_byte))
: char16_t(leading_byte);
pos++;
} else if ((leading_byte & 0b11100000) == 0b11000000) {
if (pos + 1 >= len) {
return result(error_code::TOO_SHORT, pos);
} if ((uint8_t(data[pos + 1]) & 0b11000000) != 0b10000000) {
return result(error_code::TOO_SHORT, pos);
}
uint32_t code_point = (leading_byte & 0b00011111) << 6 |
(uint8_t(data[pos + 1]) & 0b00111111);
if (code_point < 0x80) {
return result(error_code::OVERLONG, pos);
}
if constexpr (!match_system(big_endian)) {
code_point = uint32_t(u16_swap_bytes(uint16_t(code_point)));
}
*utf16_output++ = char16_t(code_point);
pos += 2;
} else if ((leading_byte & 0b11110000) == 0b11100000) {
if (pos + 2 >= len) {
return result(error_code::TOO_SHORT, pos);
}
if ((uint8_t(data[pos + 1]) & 0b11000000) != 0b10000000) {
return result(error_code::TOO_SHORT, pos);
}
if ((uint8_t(data[pos + 2]) & 0b11000000) != 0b10000000) {
return result(error_code::TOO_SHORT, pos);
}
uint32_t code_point = (leading_byte & 0b00001111) << 12 |
(uint8_t(data[pos + 1]) & 0b00111111) << 6 |
(uint8_t(data[pos + 2]) & 0b00111111);
if (code_point < 0x800) {
return result(error_code::OVERLONG, pos);
}
if (0xd7ff < code_point && code_point < 0xe000) {
return result(error_code::SURROGATE, pos);
}
if constexpr (!match_system(big_endian)) {
code_point = uint32_t(u16_swap_bytes(uint16_t(code_point)));
}
*utf16_output++ = char16_t(code_point);
pos += 3;
} else if ((leading_byte & 0b11111000) == 0b11110000) { if (pos + 3 >= len) {
return result(error_code::TOO_SHORT, pos);
} if ((uint8_t(data[pos + 1]) & 0b11000000) != 0b10000000) {
return result(error_code::TOO_SHORT, pos);
}
if ((uint8_t(data[pos + 2]) & 0b11000000) != 0b10000000) {
return result(error_code::TOO_SHORT, pos);
}
if ((uint8_t(data[pos + 3]) & 0b11000000) != 0b10000000) {
return result(error_code::TOO_SHORT, pos);
}
uint32_t code_point = (leading_byte & 0b00000111) << 18 |
(uint8_t(data[pos + 1]) & 0b00111111) << 12 |
(uint8_t(data[pos + 2]) & 0b00111111) << 6 |
(uint8_t(data[pos + 3]) & 0b00111111);
if (code_point <= 0xffff) {
return result(error_code::OVERLONG, pos);
}
if (0x10ffff < code_point) {
return result(error_code::TOO_LARGE, pos);
}
code_point -= 0x10000;
uint16_t high_surrogate = uint16_t(0xD800 + (code_point >> 10));
uint16_t low_surrogate = uint16_t(0xDC00 + (code_point & 0x3FF));
if constexpr (!match_system(big_endian)) {
high_surrogate = u16_swap_bytes(high_surrogate);
low_surrogate = u16_swap_bytes(low_surrogate);
}
*utf16_output++ = char16_t(high_surrogate);
*utf16_output++ = char16_t(low_surrogate);
pos += 4;
} else {
if ((leading_byte & 0b11000000) == 0b10000000) {
return result(error_code::TOO_LONG, pos);
} else {
return result(error_code::HEADER_BITS, pos);
}
}
}
return result(error_code::SUCCESS, utf16_output - start);
}
template <endianness endian>
inline result rewind_and_convert_with_errors(size_t prior_bytes,
const char *buf, size_t len,
char16_t *utf16_output) {
size_t extra_len{0};
size_t how_far_back = prior_bytes;
bool found_leading_bytes{false};
for (size_t i = 0; i <= how_far_back; i++) {
unsigned char byte = buf[-static_cast<std::ptrdiff_t>(i)];
found_leading_bytes = ((byte & 0b11000000) != 0b10000000);
if (found_leading_bytes) {
if (i > 0 && byte < 128) {
return result(error_code::TOO_LONG, 0 - i + 1);
}
buf -= i;
extra_len = i;
break;
}
}
if (!found_leading_bytes) {
return result(error_code::TOO_LONG, 0 - how_far_back);
}
result res = convert_with_errors<endian>(buf, len + extra_len, utf16_output);
if (res.error) {
res.count -= extra_len;
}
return res;
}
} } } }
#endif
#ifndef SIMDUTF_VALID_UTF8_TO_UTF16_H
#define SIMDUTF_VALID_UTF8_TO_UTF16_H
#include <cstring>
namespace simdutf {
namespace scalar {
namespace {
namespace utf8_to_utf16 {
template <endianness big_endian, typename InputPtr>
#if SIMDUTF_CPLUSPLUS20
requires simdutf::detail::indexes_into_byte_like<InputPtr>
#endif
simdutf_constexpr23 size_t convert_valid(InputPtr data, size_t len,
char16_t *utf16_output) {
size_t pos = 0;
char16_t *start{utf16_output};
while (pos < len) {
#if SIMDUTF_CPLUSPLUS23
if !consteval
#endif
{ if (pos + 8 <= len) { uint64_t v;
::memcpy(&v, data + pos, sizeof(uint64_t));
if ((v & 0x8080808080808080) == 0) {
size_t final_pos = pos + 8;
while (pos < final_pos) {
const char16_t byte = uint8_t(data[pos]);
*utf16_output++ =
!match_system(big_endian) ? u16_swap_bytes(byte) : byte;
pos++;
}
continue;
}
}
}
auto leading_byte = uint8_t(data[pos]); if (leading_byte < 0b10000000) {
*utf16_output++ = !match_system(big_endian)
? char16_t(u16_swap_bytes(leading_byte))
: char16_t(leading_byte);
pos++;
} else if ((leading_byte & 0b11100000) == 0b11000000) {
if (pos + 1 >= len) {
break;
} uint16_t code_point = uint16_t(((leading_byte & 0b00011111) << 6) |
(uint8_t(data[pos + 1]) & 0b00111111));
if constexpr (!match_system(big_endian)) {
code_point = u16_swap_bytes(uint16_t(code_point));
}
*utf16_output++ = char16_t(code_point);
pos += 2;
} else if ((leading_byte & 0b11110000) == 0b11100000) {
if (pos + 2 >= len) {
break;
} uint16_t code_point =
uint16_t(((leading_byte & 0b00001111) << 12) |
((uint8_t(data[pos + 1]) & 0b00111111) << 6) |
(uint8_t(data[pos + 2]) & 0b00111111));
if constexpr (!match_system(big_endian)) {
code_point = u16_swap_bytes(uint16_t(code_point));
}
*utf16_output++ = char16_t(code_point);
pos += 3;
} else if ((leading_byte & 0b11111000) == 0b11110000) { if (pos + 3 >= len) {
break;
} uint32_t code_point = ((leading_byte & 0b00000111) << 18) |
((uint8_t(data[pos + 1]) & 0b00111111) << 12) |
((uint8_t(data[pos + 2]) & 0b00111111) << 6) |
(uint8_t(data[pos + 3]) & 0b00111111);
code_point -= 0x10000;
uint16_t high_surrogate = uint16_t(0xD800 + (code_point >> 10));
uint16_t low_surrogate = uint16_t(0xDC00 + (code_point & 0x3FF));
if constexpr (!match_system(big_endian)) {
high_surrogate = u16_swap_bytes(high_surrogate);
low_surrogate = u16_swap_bytes(low_surrogate);
}
*utf16_output++ = char16_t(high_surrogate);
*utf16_output++ = char16_t(low_surrogate);
pos += 4;
} else {
return 0;
}
}
return utf16_output - start;
}
} } } }
#endif
#ifndef SIMDUTF_UTF8_TO_UTF32_H
#define SIMDUTF_UTF8_TO_UTF32_H
#include <cstring>
namespace simdutf {
namespace scalar {
namespace {
namespace utf8_to_utf32 {
template <typename InputPtr>
#if SIMDUTF_CPLUSPLUS20
requires simdutf::detail::indexes_into_byte_like<InputPtr>
#endif
simdutf_constexpr23 size_t convert(InputPtr data, size_t len,
char32_t *utf32_output) {
size_t pos = 0;
char32_t *start{utf32_output};
while (pos < len) {
#if SIMDUTF_CPLUSPLUS23
if !consteval
#endif
{
if (pos + 16 <= len) { uint64_t v1;
::memcpy(&v1, data + pos, sizeof(uint64_t));
uint64_t v2;
::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
uint64_t v{v1 | v2};
if ((v & 0x8080808080808080) == 0) {
size_t final_pos = pos + 16;
while (pos < final_pos) {
*utf32_output++ = uint8_t(data[pos]);
pos++;
}
continue;
}
}
}
auto leading_byte = uint8_t(data[pos]); if (leading_byte < 0b10000000) {
*utf32_output++ = char32_t(leading_byte);
pos++;
} else if ((leading_byte & 0b11100000) == 0b11000000) {
if (pos + 1 >= len) {
return 0;
} if ((data[pos + 1] & 0b11000000) != 0b10000000) {
return 0;
}
uint32_t code_point = (leading_byte & 0b00011111) << 6 |
(uint8_t(data[pos + 1]) & 0b00111111);
if (code_point < 0x80) {
return 0;
}
*utf32_output++ = char32_t(code_point);
pos += 2;
} else if ((leading_byte & 0b11110000) == 0b11100000) {
if (pos + 2 >= len) {
return 0;
}
if ((uint8_t(data[pos + 1]) & 0b11000000) != 0b10000000) {
return 0;
}
if ((uint8_t(data[pos + 2]) & 0b11000000) != 0b10000000) {
return 0;
}
uint32_t code_point = (leading_byte & 0b00001111) << 12 |
(uint8_t(data[pos + 1]) & 0b00111111) << 6 |
(uint8_t(data[pos + 2]) & 0b00111111);
if (code_point < 0x800 || (0xd7ff < code_point && code_point < 0xe000)) {
return 0;
}
*utf32_output++ = char32_t(code_point);
pos += 3;
} else if ((leading_byte & 0b11111000) == 0b11110000) { if (pos + 3 >= len) {
return 0;
} if ((uint8_t(data[pos + 1]) & 0b11000000) != 0b10000000) {
return 0;
}
if ((uint8_t(data[pos + 2]) & 0b11000000) != 0b10000000) {
return 0;
}
if ((uint8_t(data[pos + 3]) & 0b11000000) != 0b10000000) {
return 0;
}
uint32_t code_point = (leading_byte & 0b00000111) << 18 |
(uint8_t(data[pos + 1]) & 0b00111111) << 12 |
(uint8_t(data[pos + 2]) & 0b00111111) << 6 |
(uint8_t(data[pos + 3]) & 0b00111111);
if (code_point <= 0xffff || 0x10ffff < code_point) {
return 0;
}
*utf32_output++ = char32_t(code_point);
pos += 4;
} else {
return 0;
}
}
return utf32_output - start;
}
template <typename InputPtr>
#if SIMDUTF_CPLUSPLUS20
requires simdutf::detail::indexes_into_byte_like<InputPtr>
#endif
simdutf_constexpr23 result convert_with_errors(InputPtr data, size_t len,
char32_t *utf32_output) {
size_t pos = 0;
char32_t *start{utf32_output};
while (pos < len) {
#if SIMDUTF_CPLUSPLUS23
if !consteval
#endif
{
if (pos + 16 <= len) { uint64_t v1;
::memcpy(&v1, data + pos, sizeof(uint64_t));
uint64_t v2;
::memcpy(&v2, data + pos + sizeof(uint64_t), sizeof(uint64_t));
uint64_t v{v1 | v2};
if ((v & 0x8080808080808080) == 0) {
size_t final_pos = pos + 16;
while (pos < final_pos) {
*utf32_output++ = uint8_t(data[pos]);
pos++;
}
continue;
}
}
}
auto leading_byte = uint8_t(data[pos]); if (leading_byte < 0b10000000) {
*utf32_output++ = char32_t(leading_byte);
pos++;
} else if ((leading_byte & 0b11100000) == 0b11000000) {
if (pos + 1 >= len) {
return result(error_code::TOO_SHORT, pos);
} if ((uint8_t(data[pos + 1]) & 0b11000000) != 0b10000000) {
return result(error_code::TOO_SHORT, pos);
}
uint32_t code_point = (leading_byte & 0b00011111) << 6 |
(uint8_t(data[pos + 1]) & 0b00111111);
if (code_point < 0x80) {
return result(error_code::OVERLONG, pos);
}
*utf32_output++ = char32_t(code_point);
pos += 2;
} else if ((leading_byte & 0b11110000) == 0b11100000) {
if (pos + 2 >= len) {
return result(error_code::TOO_SHORT, pos);
}
if ((uint8_t(data[pos + 1]) & 0b11000000) != 0b10000000) {
return result(error_code::TOO_SHORT, pos);
}
if ((uint8_t(data[pos + 2]) & 0b11000000) != 0b10000000) {
return result(error_code::TOO_SHORT, pos);
}
uint32_t code_point = (leading_byte & 0b00001111) << 12 |
(uint8_t(data[pos + 1]) & 0b00111111) << 6 |
(uint8_t(data[pos + 2]) & 0b00111111);
if (code_point < 0x800) {
return result(error_code::OVERLONG, pos);
}
if (0xd7ff < code_point && code_point < 0xe000) {
return result(error_code::SURROGATE, pos);
}
*utf32_output++ = char32_t(code_point);
pos += 3;
} else if ((leading_byte & 0b11111000) == 0b11110000) { if (pos + 3 >= len) {
return result(error_code::TOO_SHORT, pos);
} if ((uint8_t(data[pos + 1]) & 0b11000000) != 0b10000000) {
return result(error_code::TOO_SHORT, pos);
}
if ((uint8_t(data[pos + 2]) & 0b11000000) != 0b10000000) {
return result(error_code::TOO_SHORT, pos);
}
if ((uint8_t(data[pos + 3]) & 0b11000000) != 0b10000000) {
return result(error_code::TOO_SHORT, pos);
}
uint32_t code_point = (leading_byte & 0b00000111) << 18 |
(uint8_t(data[pos + 1]) & 0b00111111) << 12 |
(uint8_t(data[pos + 2]) & 0b00111111) << 6 |
(uint8_t(data[pos + 3]) & 0b00111111);
if (code_point <= 0xffff) {
return result(error_code::OVERLONG, pos);
}
if (0x10ffff < code_point) {
return result(error_code::TOO_LARGE, pos);
}
*utf32_output++ = char32_t(code_point);
pos += 4;
} else {
if ((leading_byte & 0b11000000) == 0b10000000) {
return result(error_code::TOO_LONG, pos);
} else {
return result(error_code::HEADER_BITS, pos);
}
}
}
return result(error_code::SUCCESS, utf32_output - start);
}
inline result rewind_and_convert_with_errors(size_t prior_bytes,
const char *buf, size_t len,
char32_t *utf32_output) {
size_t extra_len{0};
size_t how_far_back = 3; if (how_far_back > prior_bytes) {
how_far_back = prior_bytes;
}
bool found_leading_bytes{false};
for (size_t i = 0; i <= how_far_back; i++) {
unsigned char byte = buf[-static_cast<std::ptrdiff_t>(i)];
found_leading_bytes = ((byte & 0b11000000) != 0b10000000);
if (found_leading_bytes) {
if (i > 0 && byte < 128) {
return result(error_code::TOO_LONG, 0 - i + 1);
}
buf -= i;
extra_len = i;
break;
}
}
if (!found_leading_bytes) {
return result(error_code::TOO_LONG, 0 - how_far_back);
}
result res = convert_with_errors(buf, len + extra_len, utf32_output);
if (res.error) {
res.count -= extra_len;
}
return res;
}
} } } }
#endif
#ifndef SIMDUTF_VALID_UTF8_TO_UTF32_H
#define SIMDUTF_VALID_UTF8_TO_UTF32_H
#include <cstring>
namespace simdutf {
namespace scalar {
namespace {
namespace utf8_to_utf32 {
template <typename InputPtr>
#if SIMDUTF_CPLUSPLUS20
requires simdutf::detail::indexes_into_byte_like<InputPtr>
#endif
simdutf_constexpr23 size_t convert_valid(InputPtr data, size_t len,
char32_t *utf32_output) {
size_t pos = 0;
char32_t *start{utf32_output};
while (pos < len) {
#if SIMDUTF_CPLUSPLUS23
if !consteval
#endif
{
if (pos + 8 <= len) { uint64_t v;
::memcpy(&v, data + pos, sizeof(uint64_t));
if ((v & 0x8080808080808080) == 0) {
size_t final_pos = pos + 8;
while (pos < final_pos) {
*utf32_output++ = uint8_t(data[pos]);
pos++;
}
continue;
}
}
}
auto leading_byte = uint8_t(data[pos]); if (leading_byte < 0b10000000) {
*utf32_output++ = char32_t(leading_byte);
pos++;
} else if ((leading_byte & 0b11100000) == 0b11000000) {
if (pos + 1 >= len) {
break;
} *utf32_output++ = char32_t(((leading_byte & 0b00011111) << 6) |
(uint8_t(data[pos + 1]) & 0b00111111));
pos += 2;
} else if ((leading_byte & 0b11110000) == 0b11100000) {
if (pos + 2 >= len) {
break;
} *utf32_output++ = char32_t(((leading_byte & 0b00001111) << 12) |
((uint8_t(data[pos + 1]) & 0b00111111) << 6) |
(uint8_t(data[pos + 2]) & 0b00111111));
pos += 3;
} else if ((leading_byte & 0b11111000) == 0b11110000) { if (pos + 3 >= len) {
break;
} uint32_t code_word = ((leading_byte & 0b00000111) << 18) |
((uint8_t(data[pos + 1]) & 0b00111111) << 12) |
((uint8_t(data[pos + 2]) & 0b00111111) << 6) |
(uint8_t(data[pos + 3]) & 0b00111111);
*utf32_output++ = char32_t(code_word);
pos += 4;
} else {
return 0;
}
}
return utf32_output - start;
}
} } } }
#endif
namespace simdutf {
constexpr size_t default_line_length =
76;
#if SIMDUTF_FEATURE_DETECT_ENCODING
simdutf_warn_unused simdutf::encoding_type
autodetect_encoding(const char *input, size_t length) noexcept;
simdutf_really_inline simdutf_warn_unused simdutf::encoding_type
autodetect_encoding(const uint8_t *input, size_t length) noexcept {
return autodetect_encoding(reinterpret_cast<const char *>(input), length);
}
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf::encoding_type
autodetect_encoding(
const detail::input_span_of_byte_like auto &input) noexcept {
return autodetect_encoding(reinterpret_cast<const char *>(input.data()),
input.size());
}
#endif
simdutf_warn_unused int detect_encodings(const char *input,
size_t length) noexcept;
simdutf_really_inline simdutf_warn_unused int
detect_encodings(const uint8_t *input, size_t length) noexcept {
return detect_encodings(reinterpret_cast<const char *>(input), length);
}
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused int
detect_encodings(const detail::input_span_of_byte_like auto &input) noexcept {
return detect_encodings(reinterpret_cast<const char *>(input.data()),
input.size());
}
#endif #endif
#if SIMDUTF_FEATURE_UTF8 || SIMDUTF_FEATURE_DETECT_ENCODING
simdutf_warn_unused bool validate_utf8(const char *buf, size_t len) noexcept;
#if SIMDUTF_SPAN
simdutf_constexpr23 simdutf_really_inline simdutf_warn_unused bool
validate_utf8(const detail::input_span_of_byte_like auto &input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf8::validate(
detail::constexpr_cast_ptr<uint8_t>(input.data()), input.size());
} else
#endif
{
return validate_utf8(reinterpret_cast<const char *>(input.data()),
input.size());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF8
simdutf_warn_unused result validate_utf8_with_errors(const char *buf,
size_t len) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_constexpr23 simdutf_warn_unused result
validate_utf8_with_errors(
const detail::input_span_of_byte_like auto &input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf8::validate_with_errors(
detail::constexpr_cast_ptr<uint8_t>(input.data()), input.size());
} else
#endif
{
return validate_utf8_with_errors(
reinterpret_cast<const char *>(input.data()), input.size());
}
}
#endif #endif
#if SIMDUTF_FEATURE_ASCII
simdutf_warn_unused bool validate_ascii(const char *buf, size_t len) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 bool
validate_ascii(const detail::input_span_of_byte_like auto &input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::ascii::validate(
detail::constexpr_cast_ptr<std::uint8_t>(input.data()), input.size());
} else
#endif
{
return validate_ascii(reinterpret_cast<const char *>(input.data()),
input.size());
}
}
#endif
simdutf_warn_unused result validate_ascii_with_errors(const char *buf,
size_t len) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
validate_ascii_with_errors(
const detail::input_span_of_byte_like auto &input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::ascii::validate_with_errors(
detail::constexpr_cast_ptr<std::uint8_t>(input.data()), input.size());
} else
#endif
{
return validate_ascii_with_errors(
reinterpret_cast<const char *>(input.data()), input.size());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_ASCII
simdutf_warn_unused bool validate_utf16_as_ascii(const char16_t *buf,
size_t len) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 bool
validate_utf16_as_ascii(std::span<const char16_t> input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::validate_as_ascii<endianness::NATIVE>(input.data(),
input.size());
} else
#endif
{
return validate_utf16_as_ascii(input.data(), input.size());
}
}
#endif
simdutf_warn_unused bool validate_utf16be_as_ascii(const char16_t *buf,
size_t len) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 bool
validate_utf16be_as_ascii(std::span<const char16_t> input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::validate_as_ascii<endianness::BIG>(input.data(),
input.size());
} else
#endif
{
return validate_utf16be_as_ascii(input.data(), input.size());
}
}
#endif
simdutf_warn_unused bool validate_utf16le_as_ascii(const char16_t *buf,
size_t len) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 bool
validate_utf16le_as_ascii(std::span<const char16_t> input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::validate_as_ascii<endianness::LITTLE>(input.data(),
input.size());
} else
#endif
{
return validate_utf16le_as_ascii(input.data(), input.size());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF16
simdutf_warn_unused bool validate_utf16(const char16_t *buf,
size_t len) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 bool
validate_utf16(std::span<const char16_t> input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::validate<endianness::NATIVE>(input.data(),
input.size());
} else
#endif
{
return validate_utf16(input.data(), input.size());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF16 || SIMDUTF_FEATURE_DETECT_ENCODING
simdutf_warn_unused bool validate_utf16le(const char16_t *buf,
size_t len) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_constexpr23 simdutf_warn_unused bool
validate_utf16le(std::span<const char16_t> input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::validate<endianness::LITTLE>(input.data(),
input.size());
} else
#endif
{
return validate_utf16le(input.data(), input.size());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF16
simdutf_warn_unused bool validate_utf16be(const char16_t *buf,
size_t len) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 bool
validate_utf16be(std::span<const char16_t> input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::validate<endianness::BIG>(input.data(), input.size());
} else
#endif
{
return validate_utf16be(input.data(), input.size());
}
}
#endif
simdutf_warn_unused result validate_utf16_with_errors(const char16_t *buf,
size_t len) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
validate_utf16_with_errors(std::span<const char16_t> input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::validate_with_errors<endianness::NATIVE>(
input.data(), input.size());
} else
#endif
{
return validate_utf16_with_errors(input.data(), input.size());
}
}
#endif
simdutf_warn_unused result validate_utf16le_with_errors(const char16_t *buf,
size_t len) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
validate_utf16le_with_errors(std::span<const char16_t> input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::validate_with_errors<endianness::LITTLE>(
input.data(), input.size());
} else
#endif
{
return validate_utf16le_with_errors(input.data(), input.size());
}
}
#endif
simdutf_warn_unused result validate_utf16be_with_errors(const char16_t *buf,
size_t len) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
validate_utf16be_with_errors(std::span<const char16_t> input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::validate_with_errors<endianness::BIG>(input.data(),
input.size());
} else
#endif
{
return validate_utf16be_with_errors(input.data(), input.size());
}
}
#endif
void to_well_formed_utf16le(const char16_t *input, size_t len,
char16_t *output) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_constexpr23 void
to_well_formed_utf16le(std::span<const char16_t> input,
std::span<char16_t> output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
scalar::utf16::to_well_formed_utf16<endianness::LITTLE>(
input.data(), input.size(), output.data());
} else
#endif
{
to_well_formed_utf16le(input.data(), input.size(), output.data());
}
}
#endif
void to_well_formed_utf16be(const char16_t *input, size_t len,
char16_t *output) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_constexpr23 void
to_well_formed_utf16be(std::span<const char16_t> input,
std::span<char16_t> output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
scalar::utf16::to_well_formed_utf16<endianness::BIG>(
input.data(), input.size(), output.data());
} else
#endif
{
to_well_formed_utf16be(input.data(), input.size(), output.data());
}
}
#endif
void to_well_formed_utf16(const char16_t *input, size_t len,
char16_t *output) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_constexpr23 void
to_well_formed_utf16(std::span<const char16_t> input,
std::span<char16_t> output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
scalar::utf16::to_well_formed_utf16<endianness::NATIVE>(
input.data(), input.size(), output.data());
} else
#endif
{
to_well_formed_utf16(input.data(), input.size(), output.data());
}
}
#endif
#endif
#if SIMDUTF_FEATURE_UTF32 || SIMDUTF_FEATURE_DETECT_ENCODING
simdutf_warn_unused bool validate_utf32(const char32_t *buf,
size_t len) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 bool
validate_utf32(std::span<const char32_t> input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf32::validate(
detail::constexpr_cast_ptr<std::uint32_t>(input.data()), input.size());
} else
#endif
{
return validate_utf32(input.data(), input.size());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF32
simdutf_warn_unused result validate_utf32_with_errors(const char32_t *buf,
size_t len) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
validate_utf32_with_errors(std::span<const char32_t> input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf32::validate_with_errors(
detail::constexpr_cast_ptr<std::uint32_t>(input.data()), input.size());
} else
#endif
{
return validate_utf32_with_errors(input.data(), input.size());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused size_t convert_latin1_to_utf8(const char *input,
size_t length,
char *utf8_output) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_latin1_to_utf8(
const detail::input_span_of_byte_like auto &latin1_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::latin1_to_utf8::convert(
detail::constexpr_cast_ptr<char>(latin1_input.data()),
latin1_input.size(),
detail::constexpr_cast_writeptr<char>(utf8_output.data()));
} else
#endif
{
return convert_latin1_to_utf8(
reinterpret_cast<const char *>(latin1_input.data()),
latin1_input.size(), reinterpret_cast<char *>(utf8_output.data()));
}
}
#endif
simdutf_warn_unused size_t
convert_latin1_to_utf8_safe(const char *input, size_t length, char *utf8_output,
size_t utf8_len) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_latin1_to_utf8_safe(
const detail::input_span_of_byte_like auto &input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::latin1_to_utf8::convert_safe_constexpr(
input.data(), input.size(), utf8_output.data(), utf8_output.size());
} else
#endif
{
return convert_latin1_to_utf8_safe(
reinterpret_cast<const char *>(input.data()), input.size(),
reinterpret_cast<char *>(utf8_output.data()), utf8_output.size());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused size_t convert_latin1_to_utf16le(
const char *input, size_t length, char16_t *utf16_output) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_latin1_to_utf16le(
const detail::input_span_of_byte_like auto &latin1_input,
std::span<char16_t> utf16_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::latin1_to_utf16::convert<endianness::LITTLE>(
latin1_input.data(), latin1_input.size(), utf16_output.data());
} else
#endif
{
return convert_latin1_to_utf16le(
reinterpret_cast<const char *>(latin1_input.data()),
latin1_input.size(), utf16_output.data());
}
}
#endif
simdutf_warn_unused size_t convert_latin1_to_utf16be(
const char *input, size_t length, char16_t *utf16_output) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_latin1_to_utf16be(const detail::input_span_of_byte_like auto &input,
std::span<char16_t> output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::latin1_to_utf16::convert<endianness::BIG>(
input.data(), input.size(), output.data());
} else
#endif
{
return convert_latin1_to_utf16be(
reinterpret_cast<const char *>(input.data()), input.size(),
output.data());
}
}
#endif
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
latin1_length_from_utf16(size_t length) noexcept {
return length;
}
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
utf16_length_from_latin1(size_t length) noexcept {
return length;
}
#endif
#if SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused size_t convert_latin1_to_utf32(
const char *input, size_t length, char32_t *utf32_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_latin1_to_utf32(
const detail::input_span_of_byte_like auto &latin1_input,
std::span<char32_t> utf32_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::latin1_to_utf32::convert(
latin1_input.data(), latin1_input.size(), utf32_output.data());
} else
#endif
{
return convert_latin1_to_utf32(
reinterpret_cast<const char *>(latin1_input.data()),
latin1_input.size(), utf32_output.data());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused size_t convert_utf8_to_latin1(const char *input,
size_t length,
char *latin1_output) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_utf8_to_latin1(
const detail::input_span_of_byte_like auto &input,
detail::output_span_of_byte_like auto &&output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf8_to_latin1::convert(input.data(), input.size(),
output.data());
} else
#endif
{
return convert_utf8_to_latin1(reinterpret_cast<const char *>(input.data()),
input.size(),
reinterpret_cast<char *>(output.data()));
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
simdutf_warn_unused size_t convert_utf8_to_utf16(
const char *input, size_t length, char16_t *utf16_output) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_utf8_to_utf16(const detail::input_span_of_byte_like auto &input,
std::span<char16_t> output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf8_to_utf16::convert<endianness::NATIVE>(
input.data(), input.size(), output.data());
} else
#endif
{
return convert_utf8_to_utf16(reinterpret_cast<const char *>(input.data()),
input.size(), output.data());
}
}
#endif
simdutf_warn_unused result utf8_length_from_utf16le_with_replacement(
const char16_t *input, size_t length) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_constexpr23 simdutf_warn_unused result
utf8_length_from_utf16le_with_replacement(
std::span<const char16_t> valid_utf16_input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::utf8_length_from_utf16_with_replacement<
endianness::LITTLE>(valid_utf16_input.data(), valid_utf16_input.size());
} else
#endif
{
return utf8_length_from_utf16le_with_replacement(valid_utf16_input.data(),
valid_utf16_input.size());
}
}
#endif
simdutf_warn_unused result utf8_length_from_utf16be_with_replacement(
const char16_t *input, size_t length) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
utf8_length_from_utf16be_with_replacement(
std::span<const char16_t> valid_utf16_input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::utf8_length_from_utf16_with_replacement<
endianness::BIG>(valid_utf16_input.data(), valid_utf16_input.size());
} else
#endif
{
return utf8_length_from_utf16be_with_replacement(valid_utf16_input.data(),
valid_utf16_input.size());
}
}
#endif
#endif
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused size_t convert_latin1_to_utf16(
const char *input, size_t length, char16_t *utf16_output) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_latin1_to_utf16(const detail::input_span_of_byte_like auto &input,
std::span<char16_t> output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::latin1_to_utf16::convert<endianness::NATIVE>(
input.data(), input.size(), output.data());
} else
#endif
{
return convert_latin1_to_utf16(reinterpret_cast<const char *>(input.data()),
input.size(), output.data());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
simdutf_warn_unused size_t convert_utf8_to_utf16le(
const char *input, size_t length, char16_t *utf16_output) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_utf8_to_utf16le(const detail::input_span_of_byte_like auto &utf8_input,
std::span<char16_t> utf16_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf8_to_utf16::convert<endianness::LITTLE>(
utf8_input.data(), utf8_input.size(), utf16_output.data());
} else
#endif
{
return convert_utf8_to_utf16le(
reinterpret_cast<const char *>(utf8_input.data()), utf8_input.size(),
utf16_output.data());
}
}
#endif
simdutf_warn_unused size_t convert_utf8_to_utf16be(
const char *input, size_t length, char16_t *utf16_output) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_utf8_to_utf16be(const detail::input_span_of_byte_like auto &utf8_input,
std::span<char16_t> utf16_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf8_to_utf16::convert<endianness::BIG>(
utf8_input.data(), utf8_input.size(), utf16_output.data());
} else
#endif
{
return convert_utf8_to_utf16be(
reinterpret_cast<const char *>(utf8_input.data()), utf8_input.size(),
utf16_output.data());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused result convert_utf8_to_latin1_with_errors(
const char *input, size_t length, char *latin1_output) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
convert_utf8_to_latin1_with_errors(
const detail::input_span_of_byte_like auto &utf8_input,
detail::output_span_of_byte_like auto &&latin1_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf8_to_latin1::convert_with_errors(
utf8_input.data(), utf8_input.size(), latin1_output.data());
} else
#endif
{
return convert_utf8_to_latin1_with_errors(
reinterpret_cast<const char *>(utf8_input.data()), utf8_input.size(),
reinterpret_cast<char *>(latin1_output.data()));
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
simdutf_warn_unused result convert_utf8_to_utf16_with_errors(
const char *input, size_t length, char16_t *utf16_output) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
convert_utf8_to_utf16_with_errors(
const detail::input_span_of_byte_like auto &utf8_input,
std::span<char16_t> utf16_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf8_to_utf16::convert_with_errors<endianness::NATIVE>(
utf8_input.data(), utf8_input.size(), utf16_output.data());
} else
#endif
{
return convert_utf8_to_utf16_with_errors(
reinterpret_cast<const char *>(utf8_input.data()), utf8_input.size(),
utf16_output.data());
}
}
#endif
simdutf_warn_unused result convert_utf8_to_utf16le_with_errors(
const char *input, size_t length, char16_t *utf16_output) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
convert_utf8_to_utf16le_with_errors(
const detail::input_span_of_byte_like auto &utf8_input,
std::span<char16_t> utf16_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf8_to_utf16::convert_with_errors<endianness::LITTLE>(
utf8_input.data(), utf8_input.size(), utf16_output.data());
} else
#endif
{
return convert_utf8_to_utf16le_with_errors(
reinterpret_cast<const char *>(utf8_input.data()), utf8_input.size(),
utf16_output.data());
}
}
#endif
simdutf_warn_unused result convert_utf8_to_utf16be_with_errors(
const char *input, size_t length, char16_t *utf16_output) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
convert_utf8_to_utf16be_with_errors(
const detail::input_span_of_byte_like auto &utf8_input,
std::span<char16_t> utf16_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf8_to_utf16::convert_with_errors<endianness::BIG>(
utf8_input.data(), utf8_input.size(), utf16_output.data());
} else
#endif
{
return convert_utf8_to_utf16be_with_errors(
reinterpret_cast<const char *>(utf8_input.data()), utf8_input.size(),
utf16_output.data());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
simdutf_warn_unused size_t convert_utf8_to_utf32(
const char *input, size_t length, char32_t *utf32_output) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_utf8_to_utf32(const detail::input_span_of_byte_like auto &utf8_input,
std::span<char32_t> utf32_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf8_to_utf32::convert(utf8_input.data(), utf8_input.size(),
utf32_output.data());
} else
#endif
{
return convert_utf8_to_utf32(
reinterpret_cast<const char *>(utf8_input.data()), utf8_input.size(),
utf32_output.data());
}
}
#endif
simdutf_warn_unused result convert_utf8_to_utf32_with_errors(
const char *input, size_t length, char32_t *utf32_output) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
convert_utf8_to_utf32_with_errors(
const detail::input_span_of_byte_like auto &utf8_input,
std::span<char32_t> utf32_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf8_to_utf32::convert_with_errors(
utf8_input.data(), utf8_input.size(), utf32_output.data());
} else
#endif
{
return convert_utf8_to_utf32_with_errors(
reinterpret_cast<const char *>(utf8_input.data()), utf8_input.size(),
utf32_output.data());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused size_t convert_valid_utf8_to_latin1(
const char *input, size_t length, char *latin1_output) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_valid_utf8_to_latin1(
const detail::input_span_of_byte_like auto &valid_utf8_input,
detail::output_span_of_byte_like auto &&latin1_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf8_to_latin1::convert_valid(
valid_utf8_input.data(), valid_utf8_input.size(), latin1_output.data());
} else
#endif
{
return convert_valid_utf8_to_latin1(
reinterpret_cast<const char *>(valid_utf8_input.data()),
valid_utf8_input.size(), latin1_output.data());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
simdutf_warn_unused size_t convert_valid_utf8_to_utf16(
const char *input, size_t length, char16_t *utf16_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_valid_utf8_to_utf16(
const detail::input_span_of_byte_like auto &valid_utf8_input,
std::span<char16_t> utf16_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf8_to_utf16::convert_valid<endianness::NATIVE>(
valid_utf8_input.data(), valid_utf8_input.size(), utf16_output.data());
} else
#endif
{
return convert_valid_utf8_to_utf16(
reinterpret_cast<const char *>(valid_utf8_input.data()),
valid_utf8_input.size(), utf16_output.data());
}
}
#endif
simdutf_warn_unused size_t convert_valid_utf8_to_utf16le(
const char *input, size_t length, char16_t *utf16_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_valid_utf8_to_utf16le(
const detail::input_span_of_byte_like auto &valid_utf8_input,
std::span<char16_t> utf16_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf8_to_utf16::convert_valid<endianness::LITTLE>(
valid_utf8_input.data(), valid_utf8_input.size(), utf16_output.data());
} else
#endif
{
return convert_valid_utf8_to_utf16le(
reinterpret_cast<const char *>(valid_utf8_input.data()),
valid_utf8_input.size(), utf16_output.data());
}
}
#endif
simdutf_warn_unused size_t convert_valid_utf8_to_utf16be(
const char *input, size_t length, char16_t *utf16_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_valid_utf8_to_utf16be(
const detail::input_span_of_byte_like auto &valid_utf8_input,
std::span<char16_t> utf16_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf8_to_utf16::convert_valid<endianness::BIG>(
valid_utf8_input.data(), valid_utf8_input.size(), utf16_output.data());
} else
#endif
{
return convert_valid_utf8_to_utf16be(
reinterpret_cast<const char *>(valid_utf8_input.data()),
valid_utf8_input.size(), utf16_output.data());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
simdutf_warn_unused size_t convert_valid_utf8_to_utf32(
const char *input, size_t length, char32_t *utf32_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_valid_utf8_to_utf32(
const detail::input_span_of_byte_like auto &valid_utf8_input,
std::span<char32_t> utf32_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf8_to_utf32::convert_valid(
valid_utf8_input.data(), valid_utf8_input.size(), utf32_output.data());
} else
#endif
{
return convert_valid_utf8_to_utf32(
reinterpret_cast<const char *>(valid_utf8_input.data()),
valid_utf8_input.size(), utf32_output.data());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused size_t utf8_length_from_latin1(const char *input,
size_t length) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
utf8_length_from_latin1(
const detail::input_span_of_byte_like auto &latin1_input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::latin1_to_utf8::utf8_length_from_latin1(latin1_input.data(),
latin1_input.size());
} else
#endif
{
return utf8_length_from_latin1(
reinterpret_cast<const char *>(latin1_input.data()),
latin1_input.size());
}
}
#endif
simdutf_warn_unused size_t latin1_length_from_utf8(const char *input,
size_t length) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
latin1_length_from_utf8(
const detail::input_span_of_byte_like auto &valid_utf8_input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf8::count_code_points(valid_utf8_input.data(),
valid_utf8_input.size());
} else
#endif
{
return latin1_length_from_utf8(
reinterpret_cast<const char *>(valid_utf8_input.data()),
valid_utf8_input.size());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
simdutf_warn_unused size_t utf16_length_from_utf8(const char *input,
size_t length) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
utf16_length_from_utf8(
const detail::input_span_of_byte_like auto &valid_utf8_input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf8::utf16_length_from_utf8(valid_utf8_input.data(),
valid_utf8_input.size());
} else
#endif
{
return utf16_length_from_utf8(
reinterpret_cast<const char *>(valid_utf8_input.data()),
valid_utf8_input.size());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
simdutf_warn_unused size_t utf32_length_from_utf8(const char *input,
size_t length) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
utf32_length_from_utf8(
const detail::input_span_of_byte_like auto &valid_utf8_input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf8::count_code_points(valid_utf8_input.data(),
valid_utf8_input.size());
} else
#endif
{
return utf32_length_from_utf8(
reinterpret_cast<const char *>(valid_utf8_input.data()),
valid_utf8_input.size());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
simdutf_warn_unused size_t convert_utf16_to_utf8(const char16_t *input,
size_t length,
char *utf8_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_utf16_to_utf8(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_utf8::convert<endianness::NATIVE>(
utf16_input.data(), utf16_input.size(), utf8_output.data());
} else
#endif
{
return convert_utf16_to_utf8(utf16_input.data(), utf16_input.size(),
reinterpret_cast<char *>(utf8_output.data()));
}
}
#endif
simdutf_warn_unused size_t convert_utf16_to_utf8_safe(const char16_t *input,
size_t length,
char *utf8_output,
size_t utf8_len) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_utf16_to_utf8_safe(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
const full_result r =
scalar::utf16_to_utf8::convert_with_errors<endianness::NATIVE, true>(
utf16_input.data(), utf16_input.size(), utf8_output.data(),
utf8_output.size());
if (r.error != error_code::SUCCESS &&
r.error != error_code::OUTPUT_BUFFER_TOO_SMALL) {
return 0;
}
return r.output_count;
} else
#endif
{
return convert_utf16_to_utf8_safe(
utf16_input.data(), utf16_input.size(),
reinterpret_cast<char *>(utf8_output.data()), utf8_output.size());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused size_t convert_utf16_to_latin1(
const char16_t *input, size_t length, char *latin1_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_utf16_to_latin1(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&latin1_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_latin1::convert<endianness::NATIVE>(
utf16_input.data(), utf16_input.size(), latin1_output.data());
} else
#endif
{
return convert_utf16_to_latin1(
utf16_input.data(), utf16_input.size(),
reinterpret_cast<char *>(latin1_output.data()));
}
}
#endif
simdutf_warn_unused size_t convert_utf16le_to_latin1(
const char16_t *input, size_t length, char *latin1_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_utf16le_to_latin1(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&latin1_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_latin1::convert<endianness::LITTLE>(
utf16_input.data(), utf16_input.size(), latin1_output.data());
} else
#endif
{
return convert_utf16le_to_latin1(
utf16_input.data(), utf16_input.size(),
reinterpret_cast<char *>(latin1_output.data()));
}
}
#endif
simdutf_warn_unused size_t convert_utf16be_to_latin1(
const char16_t *input, size_t length, char *latin1_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_utf16be_to_latin1(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&latin1_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_latin1::convert<endianness::BIG>(
utf16_input.data(), utf16_input.size(), latin1_output.data());
} else
#endif
{
return convert_utf16be_to_latin1(
utf16_input.data(), utf16_input.size(),
reinterpret_cast<char *>(latin1_output.data()));
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
simdutf_warn_unused size_t convert_utf16le_to_utf8(const char16_t *input,
size_t length,
char *utf8_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_utf16le_to_utf8(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_utf8::convert<endianness::LITTLE>(
utf16_input.data(), utf16_input.size(), utf8_output.data());
} else
#endif
{
return convert_utf16le_to_utf8(
utf16_input.data(), utf16_input.size(),
reinterpret_cast<char *>(utf8_output.data()));
}
}
#endif
simdutf_warn_unused size_t convert_utf16be_to_utf8(const char16_t *input,
size_t length,
char *utf8_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_utf16be_to_utf8(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_utf8::convert<endianness::BIG>(
utf16_input.data(), utf16_input.size(), utf8_output.data());
} else
#endif
{
return convert_utf16be_to_utf8(
utf16_input.data(), utf16_input.size(),
reinterpret_cast<char *>(utf8_output.data()));
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused result convert_utf16_to_latin1_with_errors(
const char16_t *input, size_t length, char *latin1_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
convert_utf16_to_latin1_with_errors(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&latin1_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_latin1::convert_with_errors<endianness::NATIVE>(
utf16_input.data(), utf16_input.size(), latin1_output.data());
} else
#endif
{
return convert_utf16_to_latin1_with_errors(
utf16_input.data(), utf16_input.size(),
reinterpret_cast<char *>(latin1_output.data()));
}
}
#endif
simdutf_warn_unused result convert_utf16le_to_latin1_with_errors(
const char16_t *input, size_t length, char *latin1_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
convert_utf16le_to_latin1_with_errors(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&latin1_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_latin1::convert_with_errors<endianness::LITTLE>(
utf16_input.data(), utf16_input.size(), latin1_output.data());
} else
#endif
{
return convert_utf16le_to_latin1_with_errors(
utf16_input.data(), utf16_input.size(),
reinterpret_cast<char *>(latin1_output.data()));
}
}
#endif
simdutf_warn_unused result convert_utf16be_to_latin1_with_errors(
const char16_t *input, size_t length, char *latin1_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
convert_utf16be_to_latin1_with_errors(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&latin1_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_latin1::convert_with_errors<endianness::BIG>(
utf16_input.data(), utf16_input.size(), latin1_output.data());
} else
#endif
{
return convert_utf16be_to_latin1_with_errors(
utf16_input.data(), utf16_input.size(),
reinterpret_cast<char *>(latin1_output.data()));
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
simdutf_warn_unused result convert_utf16_to_utf8_with_errors(
const char16_t *input, size_t length, char *utf8_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
convert_utf16_to_utf8_with_errors(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_utf8::convert_with_errors<endianness::NATIVE>(
utf16_input.data(), utf16_input.size(), utf8_output.data());
} else
#endif
{
return convert_utf16_to_utf8_with_errors(
utf16_input.data(), utf16_input.size(),
reinterpret_cast<char *>(utf8_output.data()));
}
}
#endif
simdutf_warn_unused result convert_utf16le_to_utf8_with_errors(
const char16_t *input, size_t length, char *utf8_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
convert_utf16le_to_utf8_with_errors(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_utf8::convert_with_errors<endianness::LITTLE>(
utf16_input.data(), utf16_input.size(), utf8_output.data());
} else
#endif
{
return convert_utf16le_to_utf8_with_errors(
utf16_input.data(), utf16_input.size(),
reinterpret_cast<char *>(utf8_output.data()));
}
}
#endif
simdutf_warn_unused result convert_utf16be_to_utf8_with_errors(
const char16_t *input, size_t length, char *utf8_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
convert_utf16be_to_utf8_with_errors(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_utf8::convert_with_errors<endianness::BIG>(
utf16_input.data(), utf16_input.size(), utf8_output.data());
} else
#endif
{
return convert_utf16be_to_utf8_with_errors(
utf16_input.data(), utf16_input.size(),
reinterpret_cast<char *>(utf8_output.data()));
}
}
#endif
simdutf_warn_unused size_t convert_utf16le_to_utf8_with_replacement(
const char16_t *input, size_t length, char *utf8_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_utf16le_to_utf8_with_replacement(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_utf8::convert_with_replacement<endianness::LITTLE>(
utf16_input.data(), utf16_input.size(), utf8_output.data());
} else
#endif
{
return convert_utf16le_to_utf8_with_replacement(
utf16_input.data(), utf16_input.size(),
reinterpret_cast<char *>(utf8_output.data()));
}
}
#endif
simdutf_warn_unused size_t convert_utf16be_to_utf8_with_replacement(
const char16_t *input, size_t length, char *utf8_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_utf16be_to_utf8_with_replacement(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_utf8::convert_with_replacement<endianness::BIG>(
utf16_input.data(), utf16_input.size(), utf8_output.data());
} else
#endif
{
return convert_utf16be_to_utf8_with_replacement(
utf16_input.data(), utf16_input.size(),
reinterpret_cast<char *>(utf8_output.data()));
}
}
#endif
simdutf_warn_unused size_t convert_utf16_to_utf8_with_replacement(
const char16_t *input, size_t length, char *utf8_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_utf16_to_utf8_with_replacement(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_utf8::convert_with_replacement<endianness::NATIVE>(
utf16_input.data(), utf16_input.size(), utf8_output.data());
} else
#endif
{
return convert_utf16_to_utf8_with_replacement(
utf16_input.data(), utf16_input.size(),
reinterpret_cast<char *>(utf8_output.data()));
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
simdutf_warn_unused size_t convert_valid_utf16_to_utf8(
const char16_t *input, size_t length, char *utf8_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_valid_utf16_to_utf8(
std::span<const char16_t> valid_utf16_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_utf8::convert_valid<endianness::NATIVE>(
valid_utf16_input.data(), valid_utf16_input.size(), utf8_output.data());
} else
#endif
{
return convert_valid_utf16_to_utf8(
valid_utf16_input.data(), valid_utf16_input.size(),
reinterpret_cast<char *>(utf8_output.data()));
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused size_t convert_valid_utf16_to_latin1(
const char16_t *input, size_t length, char *latin1_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_valid_utf16_to_latin1(
std::span<const char16_t> valid_utf16_input,
detail::output_span_of_byte_like auto &&latin1_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_latin1::convert_valid_impl<endianness::NATIVE>(
detail::constexpr_cast_ptr<uint16_t>(valid_utf16_input.data()),
valid_utf16_input.size(),
detail::constexpr_cast_writeptr<char>(latin1_output.data()));
} else
#endif
{
return convert_valid_utf16_to_latin1(
valid_utf16_input.data(), valid_utf16_input.size(),
reinterpret_cast<char *>(latin1_output.data()));
}
}
#endif
simdutf_warn_unused size_t convert_valid_utf16le_to_latin1(
const char16_t *input, size_t length, char *latin1_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_constexpr23 simdutf_warn_unused size_t
convert_valid_utf16le_to_latin1(
std::span<const char16_t> valid_utf16_input,
detail::output_span_of_byte_like auto &&latin1_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_latin1::convert_valid_impl<endianness::LITTLE>(
detail::constexpr_cast_ptr<uint16_t>(valid_utf16_input.data()),
valid_utf16_input.size(),
detail::constexpr_cast_writeptr<char>(latin1_output.data()));
} else
#endif
{
return convert_valid_utf16le_to_latin1(
valid_utf16_input.data(), valid_utf16_input.size(),
reinterpret_cast<char *>(latin1_output.data()));
}
}
#endif
simdutf_warn_unused size_t convert_valid_utf16be_to_latin1(
const char16_t *input, size_t length, char *latin1_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_constexpr23 simdutf_warn_unused size_t
convert_valid_utf16be_to_latin1(
std::span<const char16_t> valid_utf16_input,
detail::output_span_of_byte_like auto &&latin1_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_latin1::convert_valid_impl<endianness::BIG>(
detail::constexpr_cast_ptr<uint16_t>(valid_utf16_input.data()),
valid_utf16_input.size(),
detail::constexpr_cast_writeptr<char>(latin1_output.data()));
} else
#endif
{
return convert_valid_utf16be_to_latin1(
valid_utf16_input.data(), valid_utf16_input.size(),
reinterpret_cast<char *>(latin1_output.data()));
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
simdutf_warn_unused size_t convert_valid_utf16le_to_utf8(
const char16_t *input, size_t length, char *utf8_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_valid_utf16le_to_utf8(
std::span<const char16_t> valid_utf16_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_utf8::convert_valid<endianness::NATIVE>(
valid_utf16_input.data(), valid_utf16_input.size(), utf8_output.data());
} else
#endif
{
return convert_valid_utf16le_to_utf8(
valid_utf16_input.data(), valid_utf16_input.size(),
reinterpret_cast<char *>(utf8_output.data()));
}
}
#endif
simdutf_warn_unused size_t convert_valid_utf16be_to_utf8(
const char16_t *input, size_t length, char *utf8_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_valid_utf16be_to_utf8(
std::span<const char16_t> valid_utf16_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_utf8::convert_valid<endianness::BIG>(
valid_utf16_input.data(), valid_utf16_input.size(), utf8_output.data());
} else
#endif
{
return convert_valid_utf16be_to_utf8(
valid_utf16_input.data(), valid_utf16_input.size(),
reinterpret_cast<char *>(utf8_output.data()));
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
simdutf_warn_unused size_t convert_utf16_to_utf32(
const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_utf16_to_utf32(std::span<const char16_t> utf16_input,
std::span<char32_t> utf32_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_utf32::convert<endianness::NATIVE>(
utf16_input.data(), utf16_input.size(), utf32_output.data());
} else
#endif
{
return convert_utf16_to_utf32(utf16_input.data(), utf16_input.size(),
utf32_output.data());
}
}
#endif
simdutf_warn_unused size_t convert_utf16le_to_utf32(
const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_utf16le_to_utf32(std::span<const char16_t> utf16_input,
std::span<char32_t> utf32_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_utf32::convert<endianness::LITTLE>(
utf16_input.data(), utf16_input.size(), utf32_output.data());
} else
#endif
{
return convert_utf16le_to_utf32(utf16_input.data(), utf16_input.size(),
utf32_output.data());
}
}
#endif
simdutf_warn_unused size_t convert_utf16be_to_utf32(
const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_utf16be_to_utf32(std::span<const char16_t> utf16_input,
std::span<char32_t> utf32_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_utf32::convert<endianness::BIG>(
utf16_input.data(), utf16_input.size(), utf32_output.data());
} else
#endif
{
return convert_utf16be_to_utf32(utf16_input.data(), utf16_input.size(),
utf32_output.data());
}
}
#endif
simdutf_warn_unused result convert_utf16_to_utf32_with_errors(
const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
convert_utf16_to_utf32_with_errors(std::span<const char16_t> utf16_input,
std::span<char32_t> utf32_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_utf32::convert_with_errors<endianness::NATIVE>(
utf16_input.data(), utf16_input.size(), utf32_output.data());
} else
#endif
{
return convert_utf16_to_utf32_with_errors(
utf16_input.data(), utf16_input.size(), utf32_output.data());
}
}
#endif
simdutf_warn_unused result convert_utf16le_to_utf32_with_errors(
const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
convert_utf16le_to_utf32_with_errors(
std::span<const char16_t> utf16_input,
std::span<char32_t> utf32_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_utf32::convert_with_errors<endianness::LITTLE>(
utf16_input.data(), utf16_input.size(), utf32_output.data());
} else
#endif
{
return convert_utf16le_to_utf32_with_errors(
utf16_input.data(), utf16_input.size(), utf32_output.data());
}
}
#endif
simdutf_warn_unused result convert_utf16be_to_utf32_with_errors(
const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
convert_utf16be_to_utf32_with_errors(
std::span<const char16_t> utf16_input,
std::span<char32_t> utf32_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_utf32::convert_with_errors<endianness::BIG>(
utf16_input.data(), utf16_input.size(), utf32_output.data());
} else
#endif
{
return convert_utf16be_to_utf32_with_errors(
utf16_input.data(), utf16_input.size(), utf32_output.data());
}
}
#endif
simdutf_warn_unused size_t convert_valid_utf16_to_utf32(
const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_valid_utf16_to_utf32(std::span<const char16_t> valid_utf16_input,
std::span<char32_t> utf32_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_utf32::convert_valid<endianness::NATIVE>(
valid_utf16_input.data(), valid_utf16_input.size(),
utf32_output.data());
} else
#endif
{
return convert_valid_utf16_to_utf32(valid_utf16_input.data(),
valid_utf16_input.size(),
utf32_output.data());
}
}
#endif
simdutf_warn_unused size_t convert_valid_utf16le_to_utf32(
const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_valid_utf16le_to_utf32(std::span<const char16_t> valid_utf16_input,
std::span<char32_t> utf32_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_utf32::convert_valid<endianness::LITTLE>(
valid_utf16_input.data(), valid_utf16_input.size(),
utf32_output.data());
} else
#endif
{
return convert_valid_utf16le_to_utf32(valid_utf16_input.data(),
valid_utf16_input.size(),
utf32_output.data());
}
}
#endif
simdutf_warn_unused size_t convert_valid_utf16be_to_utf32(
const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_valid_utf16be_to_utf32(std::span<const char16_t> valid_utf16_input,
std::span<char32_t> utf32_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16_to_utf32::convert_valid<endianness::BIG>(
valid_utf16_input.data(), valid_utf16_input.size(),
utf32_output.data());
} else
#endif
{
return convert_valid_utf16be_to_utf32(valid_utf16_input.data(),
valid_utf16_input.size(),
utf32_output.data());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
simdutf_warn_unused size_t utf8_length_from_utf16(const char16_t *input,
size_t length) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
utf8_length_from_utf16(std::span<const char16_t> valid_utf16_input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::utf8_length_from_utf16<endianness::NATIVE>(
valid_utf16_input.data(), valid_utf16_input.size());
} else
#endif
{
return utf8_length_from_utf16(valid_utf16_input.data(),
valid_utf16_input.size());
}
}
#endif
simdutf_warn_unused result utf8_length_from_utf16_with_replacement(
const char16_t *input, size_t length) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
utf8_length_from_utf16_with_replacement(
std::span<const char16_t> valid_utf16_input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::utf8_length_from_utf16_with_replacement<
endianness::NATIVE>(valid_utf16_input.data(), valid_utf16_input.size());
} else
#endif
{
return utf8_length_from_utf16_with_replacement(valid_utf16_input.data(),
valid_utf16_input.size());
}
}
#endif
simdutf_warn_unused size_t utf8_length_from_utf16le(const char16_t *input,
size_t length) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_constexpr23 simdutf_warn_unused size_t
utf8_length_from_utf16le(std::span<const char16_t> valid_utf16_input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::utf8_length_from_utf16<endianness::LITTLE>(
valid_utf16_input.data(), valid_utf16_input.size());
} else
#endif
{
return utf8_length_from_utf16le(valid_utf16_input.data(),
valid_utf16_input.size());
}
}
#endif
simdutf_warn_unused size_t utf8_length_from_utf16be(const char16_t *input,
size_t length) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
utf8_length_from_utf16be(std::span<const char16_t> valid_utf16_input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::utf8_length_from_utf16<endianness::BIG>(
valid_utf16_input.data(), valid_utf16_input.size());
} else
#endif
{
return utf8_length_from_utf16be(valid_utf16_input.data(),
valid_utf16_input.size());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
simdutf_warn_unused size_t convert_utf32_to_utf8(const char32_t *input,
size_t length,
char *utf8_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_utf32_to_utf8(
std::span<const char32_t> utf32_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf32_to_utf8::convert(
utf32_input.data(), utf32_input.size(), utf8_output.data());
} else
#endif
{
return convert_utf32_to_utf8(utf32_input.data(), utf32_input.size(),
reinterpret_cast<char *>(utf8_output.data()));
}
}
#endif
simdutf_warn_unused result convert_utf32_to_utf8_with_errors(
const char32_t *input, size_t length, char *utf8_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
convert_utf32_to_utf8_with_errors(
std::span<const char32_t> utf32_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf32_to_utf8::convert_with_errors(
utf32_input.data(), utf32_input.size(), utf8_output.data());
} else
#endif
{
return convert_utf32_to_utf8_with_errors(
utf32_input.data(), utf32_input.size(),
reinterpret_cast<char *>(utf8_output.data()));
}
}
#endif
simdutf_warn_unused size_t convert_valid_utf32_to_utf8(
const char32_t *input, size_t length, char *utf8_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_valid_utf32_to_utf8(
std::span<const char32_t> valid_utf32_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf32_to_utf8::convert_valid(
valid_utf32_input.data(), valid_utf32_input.size(), utf8_output.data());
} else
#endif
{
return convert_valid_utf32_to_utf8(
valid_utf32_input.data(), valid_utf32_input.size(),
reinterpret_cast<char *>(utf8_output.data()));
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
simdutf_warn_unused size_t convert_utf32_to_utf16(
const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_utf32_to_utf16(std::span<const char32_t> utf32_input,
std::span<char16_t> utf16_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf32_to_utf16::convert<endianness::NATIVE>(
utf32_input.data(), utf32_input.size(), utf16_output.data());
} else
#endif
{
return convert_utf32_to_utf16(utf32_input.data(), utf32_input.size(),
utf16_output.data());
}
}
#endif
simdutf_warn_unused size_t convert_utf32_to_utf16le(
const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_utf32_to_utf16le(std::span<const char32_t> utf32_input,
std::span<char16_t> utf16_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf32_to_utf16::convert<endianness::LITTLE>(
utf32_input.data(), utf32_input.size(), utf16_output.data());
} else
#endif
{
return convert_utf32_to_utf16le(utf32_input.data(), utf32_input.size(),
utf16_output.data());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused size_t convert_utf32_to_latin1(
const char32_t *input, size_t length, char *latin1_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_utf32_to_latin1(
std::span<const char32_t> utf32_input,
detail::output_span_of_byte_like auto &&latin1_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf32_to_latin1::convert(
utf32_input.data(), utf32_input.size(), latin1_output.data());
} else
#endif
{
return convert_utf32_to_latin1(
utf32_input.data(), utf32_input.size(),
reinterpret_cast<char *>(latin1_output.data()));
}
}
#endif
simdutf_warn_unused result convert_utf32_to_latin1_with_errors(
const char32_t *input, size_t length, char *latin1_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
convert_utf32_to_latin1_with_errors(
std::span<const char32_t> utf32_input,
detail::output_span_of_byte_like auto &&latin1_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf32_to_latin1::convert_with_errors(
utf32_input.data(), utf32_input.size(), latin1_output.data());
} else
#endif
{
return convert_utf32_to_latin1_with_errors(
utf32_input.data(), utf32_input.size(),
reinterpret_cast<char *>(latin1_output.data()));
}
}
#endif
simdutf_warn_unused size_t convert_valid_utf32_to_latin1(
const char32_t *input, size_t length, char *latin1_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_constexpr23 simdutf_warn_unused size_t
convert_valid_utf32_to_latin1(
std::span<const char32_t> valid_utf32_input,
detail::output_span_of_byte_like auto &&latin1_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf32_to_latin1::convert_valid(
detail::constexpr_cast_ptr<uint32_t>(valid_utf32_input.data()),
valid_utf32_input.size(),
detail::constexpr_cast_writeptr<char>(latin1_output.data()));
}
#endif
{
return convert_valid_utf32_to_latin1(
valid_utf32_input.data(), valid_utf32_input.size(),
reinterpret_cast<char *>(latin1_output.data()));
}
}
#endif
simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 size_t
latin1_length_from_utf32(size_t length) noexcept {
return length;
}
simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 size_t
utf32_length_from_latin1(size_t length) noexcept {
return length;
}
#endif
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
simdutf_warn_unused size_t convert_utf32_to_utf16be(
const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_utf32_to_utf16be(std::span<const char32_t> utf32_input,
std::span<char16_t> utf16_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf32_to_utf16::convert<endianness::BIG>(
utf32_input.data(), utf32_input.size(), utf16_output.data());
} else
#endif
{
return convert_utf32_to_utf16be(utf32_input.data(), utf32_input.size(),
utf16_output.data());
}
}
#endif
simdutf_warn_unused result convert_utf32_to_utf16_with_errors(
const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
convert_utf32_to_utf16_with_errors(std::span<const char32_t> utf32_input,
std::span<char16_t> utf16_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf32_to_utf16::convert_with_errors<endianness::NATIVE>(
utf32_input.data(), utf32_input.size(), utf16_output.data());
} else
#endif
{
return convert_utf32_to_utf16_with_errors(
utf32_input.data(), utf32_input.size(), utf16_output.data());
}
}
#endif
simdutf_warn_unused result convert_utf32_to_utf16le_with_errors(
const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
convert_utf32_to_utf16le_with_errors(
std::span<const char32_t> utf32_input,
std::span<char16_t> utf16_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf32_to_utf16::convert_with_errors<endianness::LITTLE>(
utf32_input.data(), utf32_input.size(), utf16_output.data());
} else
#endif
{
return convert_utf32_to_utf16le_with_errors(
utf32_input.data(), utf32_input.size(), utf16_output.data());
}
}
#endif
simdutf_warn_unused result convert_utf32_to_utf16be_with_errors(
const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
convert_utf32_to_utf16be_with_errors(
std::span<const char32_t> utf32_input,
std::span<char16_t> utf16_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf32_to_utf16::convert_with_errors<endianness::BIG>(
utf32_input.data(), utf32_input.size(), utf16_output.data());
} else
#endif
{
return convert_utf32_to_utf16be_with_errors(
utf32_input.data(), utf32_input.size(), utf16_output.data());
}
}
#endif
simdutf_warn_unused size_t convert_valid_utf32_to_utf16(
const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_valid_utf32_to_utf16(std::span<const char32_t> valid_utf32_input,
std::span<char16_t> utf16_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf32_to_utf16::convert_valid<endianness::NATIVE>(
valid_utf32_input.data(), valid_utf32_input.size(),
utf16_output.data());
} else
#endif
{
return convert_valid_utf32_to_utf16(valid_utf32_input.data(),
valid_utf32_input.size(),
utf16_output.data());
}
}
#endif
simdutf_warn_unused size_t convert_valid_utf32_to_utf16le(
const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_valid_utf32_to_utf16le(std::span<const char32_t> valid_utf32_input,
std::span<char16_t> utf16_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf32_to_utf16::convert_valid<endianness::LITTLE>(
valid_utf32_input.data(), valid_utf32_input.size(),
utf16_output.data());
} else
#endif
{
return convert_valid_utf32_to_utf16le(valid_utf32_input.data(),
valid_utf32_input.size(),
utf16_output.data());
}
}
#endif
simdutf_warn_unused size_t convert_valid_utf32_to_utf16be(
const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
convert_valid_utf32_to_utf16be(std::span<const char32_t> valid_utf32_input,
std::span<char16_t> utf16_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf32_to_utf16::convert_valid<endianness::BIG>(
valid_utf32_input.data(), valid_utf32_input.size(),
utf16_output.data());
} else
#endif
{
return convert_valid_utf32_to_utf16be(valid_utf32_input.data(),
valid_utf32_input.size(),
utf16_output.data());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF16
void change_endianness_utf16(const char16_t *input, size_t length,
char16_t *output) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_constexpr23 void
change_endianness_utf16(std::span<const char16_t> utf16_input,
std::span<char16_t> utf16_output) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::change_endianness_utf16(
utf16_input.data(), utf16_input.size(), utf16_output.data());
} else
#endif
{
return change_endianness_utf16(utf16_input.data(), utf16_input.size(),
utf16_output.data());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
simdutf_warn_unused size_t utf8_length_from_utf32(const char32_t *input,
size_t length) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
utf8_length_from_utf32(std::span<const char32_t> valid_utf32_input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf32::utf8_length_from_utf32(valid_utf32_input.data(),
valid_utf32_input.size());
} else
#endif
{
return utf8_length_from_utf32(valid_utf32_input.data(),
valid_utf32_input.size());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
simdutf_warn_unused size_t utf16_length_from_utf32(const char32_t *input,
size_t length) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
utf16_length_from_utf32(std::span<const char32_t> valid_utf32_input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf32::utf16_length_from_utf32(valid_utf32_input.data(),
valid_utf32_input.size());
} else
#endif
{
return utf16_length_from_utf32(valid_utf32_input.data(),
valid_utf32_input.size());
}
}
#endif
simdutf_warn_unused size_t utf32_length_from_utf16(const char16_t *input,
size_t length) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
utf32_length_from_utf16(std::span<const char16_t> valid_utf16_input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::utf32_length_from_utf16<endianness::NATIVE>(
valid_utf16_input.data(), valid_utf16_input.size());
} else
#endif
{
return utf32_length_from_utf16(valid_utf16_input.data(),
valid_utf16_input.size());
}
}
#endif
simdutf_warn_unused size_t utf32_length_from_utf16le(const char16_t *input,
size_t length) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
utf32_length_from_utf16le(
std::span<const char16_t> valid_utf16_input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::utf32_length_from_utf16<endianness::LITTLE>(
valid_utf16_input.data(), valid_utf16_input.size());
} else
#endif
{
return utf32_length_from_utf16le(valid_utf16_input.data(),
valid_utf16_input.size());
}
}
#endif
simdutf_warn_unused size_t utf32_length_from_utf16be(const char16_t *input,
size_t length) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
utf32_length_from_utf16be(
std::span<const char16_t> valid_utf16_input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::utf32_length_from_utf16<endianness::BIG>(
valid_utf16_input.data(), valid_utf16_input.size());
} else
#endif
{
return utf32_length_from_utf16be(valid_utf16_input.data(),
valid_utf16_input.size());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF16
simdutf_warn_unused size_t count_utf16(const char16_t *input,
size_t length) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
count_utf16(std::span<const char16_t> valid_utf16_input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::count_code_points<endianness::NATIVE>(
valid_utf16_input.data(), valid_utf16_input.size());
} else
#endif
{
return count_utf16(valid_utf16_input.data(), valid_utf16_input.size());
}
}
#endif
simdutf_warn_unused size_t count_utf16le(const char16_t *input,
size_t length) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
count_utf16le(std::span<const char16_t> valid_utf16_input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::count_code_points<endianness::LITTLE>(
valid_utf16_input.data(), valid_utf16_input.size());
} else
#endif
{
return count_utf16le(valid_utf16_input.data(), valid_utf16_input.size());
}
}
#endif
simdutf_warn_unused size_t count_utf16be(const char16_t *input,
size_t length) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
count_utf16be(std::span<const char16_t> valid_utf16_input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::count_code_points<endianness::BIG>(
valid_utf16_input.data(), valid_utf16_input.size());
} else
#endif
{
return count_utf16be(valid_utf16_input.data(), valid_utf16_input.size());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF8
simdutf_warn_unused size_t count_utf8(const char *input,
size_t length) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t count_utf8(
const detail::input_span_of_byte_like auto &valid_utf8_input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf8::count_code_points(valid_utf8_input.data(),
valid_utf8_input.size());
} else
#endif
{
return count_utf8(reinterpret_cast<const char *>(valid_utf8_input.data()),
valid_utf8_input.size());
}
}
#endif
simdutf_warn_unused size_t trim_partial_utf8(const char *input, size_t length);
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
trim_partial_utf8(
const detail::input_span_of_byte_like auto &valid_utf8_input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf8::trim_partial_utf8(valid_utf8_input.data(),
valid_utf8_input.size());
} else
#endif
{
return trim_partial_utf8(
reinterpret_cast<const char *>(valid_utf8_input.data()),
valid_utf8_input.size());
}
}
#endif #endif
#if SIMDUTF_FEATURE_UTF16
simdutf_warn_unused size_t trim_partial_utf16be(const char16_t *input,
size_t length);
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
trim_partial_utf16be(std::span<const char16_t> valid_utf16_input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::trim_partial_utf16<endianness::BIG>(
valid_utf16_input.data(), valid_utf16_input.size());
} else
#endif
{
return trim_partial_utf16be(valid_utf16_input.data(),
valid_utf16_input.size());
}
}
#endif
simdutf_warn_unused size_t trim_partial_utf16le(const char16_t *input,
size_t length);
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
trim_partial_utf16le(std::span<const char16_t> valid_utf16_input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::trim_partial_utf16<endianness::LITTLE>(
valid_utf16_input.data(), valid_utf16_input.size());
} else
#endif
{
return trim_partial_utf16le(valid_utf16_input.data(),
valid_utf16_input.size());
}
}
#endif
simdutf_warn_unused size_t trim_partial_utf16(const char16_t *input,
size_t length);
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
trim_partial_utf16(std::span<const char16_t> valid_utf16_input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::utf16::trim_partial_utf16<endianness::NATIVE>(
valid_utf16_input.data(), valid_utf16_input.size());
} else
#endif
{
return trim_partial_utf16(valid_utf16_input.data(),
valid_utf16_input.size());
}
}
#endif #endif
#if SIMDUTF_FEATURE_BASE64 || SIMDUTF_FEATURE_UTF16 || \
SIMDUTF_FEATURE_DETECT_ENCODING
#ifndef SIMDUTF_NEED_TRAILING_ZEROES
#define SIMDUTF_NEED_TRAILING_ZEROES 1
#endif
#endif
#if SIMDUTF_FEATURE_BASE64
constexpr uint64_t base64_reverse_padding =
2;
enum base64_options : uint64_t {
base64_default = 0,
base64_url = 1,
base64_default_no_padding =
base64_default |
base64_reverse_padding,
base64_url_with_padding =
base64_url | base64_reverse_padding,
base64_default_accept_garbage =
4,
base64_url_accept_garbage =
5,
base64_default_or_url =
8,
base64_default_or_url_accept_garbage =
12,
};
enum last_chunk_handling_options : uint64_t {
loose = 0,
strict = 1,
stop_before_partial =
2,
only_full_chunks =
3
};
inline simdutf_constexpr23 bool
is_partial(last_chunk_handling_options options) {
return (options == stop_before_partial) || (options == only_full_chunks);
}
namespace detail {
simdutf_warn_unused const char *find(const char *start, const char *end,
char character) noexcept;
simdutf_warn_unused const char16_t *
find(const char16_t *start, const char16_t *end, char16_t character) noexcept;
}
simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 const char *
find(const char *start, const char *end, char character) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
for (; start != end; ++start)
if (*start == character)
return start;
return end;
} else
#endif
{
return detail::find(start, end, character);
}
}
simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 const char16_t *
find(const char16_t *start, const char16_t *end, char16_t character) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
for (; start != end; ++start)
if (*start == character)
return start;
return end;
} else
#endif
{
return detail::find(start, end, character);
}
}
}
#ifndef SIMDUTF_BASE64_TABLES_H
#define SIMDUTF_BASE64_TABLES_H
#include <cstdint>
namespace simdutf {
namespace {
namespace tables {
namespace base64 {
namespace base64_default {
constexpr char e0[256] = {
'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'D', 'D', 'D',
'D', 'E', 'E', 'E', 'E', 'F', 'F', 'F', 'F', 'G', 'G', 'G', 'G', 'H', 'H',
'H', 'H', 'I', 'I', 'I', 'I', 'J', 'J', 'J', 'J', 'K', 'K', 'K', 'K', 'L',
'L', 'L', 'L', 'M', 'M', 'M', 'M', 'N', 'N', 'N', 'N', 'O', 'O', 'O', 'O',
'P', 'P', 'P', 'P', 'Q', 'Q', 'Q', 'Q', 'R', 'R', 'R', 'R', 'S', 'S', 'S',
'S', 'T', 'T', 'T', 'T', 'U', 'U', 'U', 'U', 'V', 'V', 'V', 'V', 'W', 'W',
'W', 'W', 'X', 'X', 'X', 'X', 'Y', 'Y', 'Y', 'Y', 'Z', 'Z', 'Z', 'Z', 'a',
'a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'c', 'd', 'd', 'd', 'd',
'e', 'e', 'e', 'e', 'f', 'f', 'f', 'f', 'g', 'g', 'g', 'g', 'h', 'h', 'h',
'h', 'i', 'i', 'i', 'i', 'j', 'j', 'j', 'j', 'k', 'k', 'k', 'k', 'l', 'l',
'l', 'l', 'm', 'm', 'm', 'm', 'n', 'n', 'n', 'n', 'o', 'o', 'o', 'o', 'p',
'p', 'p', 'p', 'q', 'q', 'q', 'q', 'r', 'r', 'r', 'r', 's', 's', 's', 's',
't', 't', 't', 't', 'u', 'u', 'u', 'u', 'v', 'v', 'v', 'v', 'w', 'w', 'w',
'w', 'x', 'x', 'x', 'x', 'y', 'y', 'y', 'y', 'z', 'z', 'z', 'z', '0', '0',
'0', '0', '1', '1', '1', '1', '2', '2', '2', '2', '3', '3', '3', '3', '4',
'4', '4', '4', '5', '5', '5', '5', '6', '6', '6', '6', '7', '7', '7', '7',
'8', '8', '8', '8', '9', '9', '9', '9', '+', '+', '+', '+', '/', '/', '/',
'/'};
constexpr char e1[256] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', '+', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', 'A', 'B', 'C',
'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+',
'/'};
constexpr char e2[256] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', '+', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', 'A', 'B', 'C',
'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+',
'/'};
constexpr uint32_t d0[256] = {
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x000000f8, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x000000fc,
0x000000d0, 0x000000d4, 0x000000d8, 0x000000dc, 0x000000e0, 0x000000e4,
0x000000e8, 0x000000ec, 0x000000f0, 0x000000f4, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
0x00000004, 0x00000008, 0x0000000c, 0x00000010, 0x00000014, 0x00000018,
0x0000001c, 0x00000020, 0x00000024, 0x00000028, 0x0000002c, 0x00000030,
0x00000034, 0x00000038, 0x0000003c, 0x00000040, 0x00000044, 0x00000048,
0x0000004c, 0x00000050, 0x00000054, 0x00000058, 0x0000005c, 0x00000060,
0x00000064, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x00000068, 0x0000006c, 0x00000070, 0x00000074, 0x00000078,
0x0000007c, 0x00000080, 0x00000084, 0x00000088, 0x0000008c, 0x00000090,
0x00000094, 0x00000098, 0x0000009c, 0x000000a0, 0x000000a4, 0x000000a8,
0x000000ac, 0x000000b0, 0x000000b4, 0x000000b8, 0x000000bc, 0x000000c0,
0x000000c4, 0x000000c8, 0x000000cc, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff};
constexpr uint32_t d1[256] = {
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x0000e003, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x0000f003,
0x00004003, 0x00005003, 0x00006003, 0x00007003, 0x00008003, 0x00009003,
0x0000a003, 0x0000b003, 0x0000c003, 0x0000d003, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
0x00001000, 0x00002000, 0x00003000, 0x00004000, 0x00005000, 0x00006000,
0x00007000, 0x00008000, 0x00009000, 0x0000a000, 0x0000b000, 0x0000c000,
0x0000d000, 0x0000e000, 0x0000f000, 0x00000001, 0x00001001, 0x00002001,
0x00003001, 0x00004001, 0x00005001, 0x00006001, 0x00007001, 0x00008001,
0x00009001, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x0000a001, 0x0000b001, 0x0000c001, 0x0000d001, 0x0000e001,
0x0000f001, 0x00000002, 0x00001002, 0x00002002, 0x00003002, 0x00004002,
0x00005002, 0x00006002, 0x00007002, 0x00008002, 0x00009002, 0x0000a002,
0x0000b002, 0x0000c002, 0x0000d002, 0x0000e002, 0x0000f002, 0x00000003,
0x00001003, 0x00002003, 0x00003003, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff};
constexpr uint32_t d2[256] = {
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x00800f00, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00c00f00,
0x00000d00, 0x00400d00, 0x00800d00, 0x00c00d00, 0x00000e00, 0x00400e00,
0x00800e00, 0x00c00e00, 0x00000f00, 0x00400f00, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
0x00400000, 0x00800000, 0x00c00000, 0x00000100, 0x00400100, 0x00800100,
0x00c00100, 0x00000200, 0x00400200, 0x00800200, 0x00c00200, 0x00000300,
0x00400300, 0x00800300, 0x00c00300, 0x00000400, 0x00400400, 0x00800400,
0x00c00400, 0x00000500, 0x00400500, 0x00800500, 0x00c00500, 0x00000600,
0x00400600, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x00800600, 0x00c00600, 0x00000700, 0x00400700, 0x00800700,
0x00c00700, 0x00000800, 0x00400800, 0x00800800, 0x00c00800, 0x00000900,
0x00400900, 0x00800900, 0x00c00900, 0x00000a00, 0x00400a00, 0x00800a00,
0x00c00a00, 0x00000b00, 0x00400b00, 0x00800b00, 0x00c00b00, 0x00000c00,
0x00400c00, 0x00800c00, 0x00c00c00, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff};
constexpr uint32_t d3[256] = {
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x003e0000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x003f0000,
0x00340000, 0x00350000, 0x00360000, 0x00370000, 0x00380000, 0x00390000,
0x003a0000, 0x003b0000, 0x003c0000, 0x003d0000, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
0x00010000, 0x00020000, 0x00030000, 0x00040000, 0x00050000, 0x00060000,
0x00070000, 0x00080000, 0x00090000, 0x000a0000, 0x000b0000, 0x000c0000,
0x000d0000, 0x000e0000, 0x000f0000, 0x00100000, 0x00110000, 0x00120000,
0x00130000, 0x00140000, 0x00150000, 0x00160000, 0x00170000, 0x00180000,
0x00190000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x001a0000, 0x001b0000, 0x001c0000, 0x001d0000, 0x001e0000,
0x001f0000, 0x00200000, 0x00210000, 0x00220000, 0x00230000, 0x00240000,
0x00250000, 0x00260000, 0x00270000, 0x00280000, 0x00290000, 0x002a0000,
0x002b0000, 0x002c0000, 0x002d0000, 0x002e0000, 0x002f0000, 0x00300000,
0x00310000, 0x00320000, 0x00330000, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff};
}
namespace base64_url {
constexpr char e0[256] = {
'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'D', 'D', 'D',
'D', 'E', 'E', 'E', 'E', 'F', 'F', 'F', 'F', 'G', 'G', 'G', 'G', 'H', 'H',
'H', 'H', 'I', 'I', 'I', 'I', 'J', 'J', 'J', 'J', 'K', 'K', 'K', 'K', 'L',
'L', 'L', 'L', 'M', 'M', 'M', 'M', 'N', 'N', 'N', 'N', 'O', 'O', 'O', 'O',
'P', 'P', 'P', 'P', 'Q', 'Q', 'Q', 'Q', 'R', 'R', 'R', 'R', 'S', 'S', 'S',
'S', 'T', 'T', 'T', 'T', 'U', 'U', 'U', 'U', 'V', 'V', 'V', 'V', 'W', 'W',
'W', 'W', 'X', 'X', 'X', 'X', 'Y', 'Y', 'Y', 'Y', 'Z', 'Z', 'Z', 'Z', 'a',
'a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'c', 'd', 'd', 'd', 'd',
'e', 'e', 'e', 'e', 'f', 'f', 'f', 'f', 'g', 'g', 'g', 'g', 'h', 'h', 'h',
'h', 'i', 'i', 'i', 'i', 'j', 'j', 'j', 'j', 'k', 'k', 'k', 'k', 'l', 'l',
'l', 'l', 'm', 'm', 'm', 'm', 'n', 'n', 'n', 'n', 'o', 'o', 'o', 'o', 'p',
'p', 'p', 'p', 'q', 'q', 'q', 'q', 'r', 'r', 'r', 'r', 's', 's', 's', 's',
't', 't', 't', 't', 'u', 'u', 'u', 'u', 'v', 'v', 'v', 'v', 'w', 'w', 'w',
'w', 'x', 'x', 'x', 'x', 'y', 'y', 'y', 'y', 'z', 'z', 'z', 'z', '0', '0',
'0', '0', '1', '1', '1', '1', '2', '2', '2', '2', '3', '3', '3', '3', '4',
'4', '4', '4', '5', '5', '5', '5', '6', '6', '6', '6', '7', '7', '7', '7',
'8', '8', '8', '8', '9', '9', '9', '9', '-', '-', '-', '-', '_', '_', '_',
'_'};
constexpr char e1[256] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', '-', '_', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '-', '_', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_', 'A', 'B', 'C',
'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-',
'_'};
constexpr char e2[256] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', '-', '_', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '-', '_', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_', 'A', 'B', 'C',
'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-',
'_'};
constexpr uint32_t d0[256] = {
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x000000f8, 0x01ffffff, 0x01ffffff,
0x000000d0, 0x000000d4, 0x000000d8, 0x000000dc, 0x000000e0, 0x000000e4,
0x000000e8, 0x000000ec, 0x000000f0, 0x000000f4, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
0x00000004, 0x00000008, 0x0000000c, 0x00000010, 0x00000014, 0x00000018,
0x0000001c, 0x00000020, 0x00000024, 0x00000028, 0x0000002c, 0x00000030,
0x00000034, 0x00000038, 0x0000003c, 0x00000040, 0x00000044, 0x00000048,
0x0000004c, 0x00000050, 0x00000054, 0x00000058, 0x0000005c, 0x00000060,
0x00000064, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x000000fc,
0x01ffffff, 0x00000068, 0x0000006c, 0x00000070, 0x00000074, 0x00000078,
0x0000007c, 0x00000080, 0x00000084, 0x00000088, 0x0000008c, 0x00000090,
0x00000094, 0x00000098, 0x0000009c, 0x000000a0, 0x000000a4, 0x000000a8,
0x000000ac, 0x000000b0, 0x000000b4, 0x000000b8, 0x000000bc, 0x000000c0,
0x000000c4, 0x000000c8, 0x000000cc, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff};
constexpr uint32_t d1[256] = {
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x0000e003, 0x01ffffff, 0x01ffffff,
0x00004003, 0x00005003, 0x00006003, 0x00007003, 0x00008003, 0x00009003,
0x0000a003, 0x0000b003, 0x0000c003, 0x0000d003, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
0x00001000, 0x00002000, 0x00003000, 0x00004000, 0x00005000, 0x00006000,
0x00007000, 0x00008000, 0x00009000, 0x0000a000, 0x0000b000, 0x0000c000,
0x0000d000, 0x0000e000, 0x0000f000, 0x00000001, 0x00001001, 0x00002001,
0x00003001, 0x00004001, 0x00005001, 0x00006001, 0x00007001, 0x00008001,
0x00009001, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x0000f003,
0x01ffffff, 0x0000a001, 0x0000b001, 0x0000c001, 0x0000d001, 0x0000e001,
0x0000f001, 0x00000002, 0x00001002, 0x00002002, 0x00003002, 0x00004002,
0x00005002, 0x00006002, 0x00007002, 0x00008002, 0x00009002, 0x0000a002,
0x0000b002, 0x0000c002, 0x0000d002, 0x0000e002, 0x0000f002, 0x00000003,
0x00001003, 0x00002003, 0x00003003, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff};
constexpr uint32_t d2[256] = {
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00800f00, 0x01ffffff, 0x01ffffff,
0x00000d00, 0x00400d00, 0x00800d00, 0x00c00d00, 0x00000e00, 0x00400e00,
0x00800e00, 0x00c00e00, 0x00000f00, 0x00400f00, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
0x00400000, 0x00800000, 0x00c00000, 0x00000100, 0x00400100, 0x00800100,
0x00c00100, 0x00000200, 0x00400200, 0x00800200, 0x00c00200, 0x00000300,
0x00400300, 0x00800300, 0x00c00300, 0x00000400, 0x00400400, 0x00800400,
0x00c00400, 0x00000500, 0x00400500, 0x00800500, 0x00c00500, 0x00000600,
0x00400600, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00c00f00,
0x01ffffff, 0x00800600, 0x00c00600, 0x00000700, 0x00400700, 0x00800700,
0x00c00700, 0x00000800, 0x00400800, 0x00800800, 0x00c00800, 0x00000900,
0x00400900, 0x00800900, 0x00c00900, 0x00000a00, 0x00400a00, 0x00800a00,
0x00c00a00, 0x00000b00, 0x00400b00, 0x00800b00, 0x00c00b00, 0x00000c00,
0x00400c00, 0x00800c00, 0x00c00c00, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff};
constexpr uint32_t d3[256] = {
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x003e0000, 0x01ffffff, 0x01ffffff,
0x00340000, 0x00350000, 0x00360000, 0x00370000, 0x00380000, 0x00390000,
0x003a0000, 0x003b0000, 0x003c0000, 0x003d0000, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
0x00010000, 0x00020000, 0x00030000, 0x00040000, 0x00050000, 0x00060000,
0x00070000, 0x00080000, 0x00090000, 0x000a0000, 0x000b0000, 0x000c0000,
0x000d0000, 0x000e0000, 0x000f0000, 0x00100000, 0x00110000, 0x00120000,
0x00130000, 0x00140000, 0x00150000, 0x00160000, 0x00170000, 0x00180000,
0x00190000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x003f0000,
0x01ffffff, 0x001a0000, 0x001b0000, 0x001c0000, 0x001d0000, 0x001e0000,
0x001f0000, 0x00200000, 0x00210000, 0x00220000, 0x00230000, 0x00240000,
0x00250000, 0x00260000, 0x00270000, 0x00280000, 0x00290000, 0x002a0000,
0x002b0000, 0x002c0000, 0x002d0000, 0x002e0000, 0x002f0000, 0x00300000,
0x00310000, 0x00320000, 0x00330000, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff};
}
namespace base64_default_or_url {
constexpr uint32_t d0[256] = {
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x000000f8, 0x01ffffff, 0x000000f8, 0x01ffffff, 0x000000fc,
0x000000d0, 0x000000d4, 0x000000d8, 0x000000dc, 0x000000e0, 0x000000e4,
0x000000e8, 0x000000ec, 0x000000f0, 0x000000f4, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
0x00000004, 0x00000008, 0x0000000c, 0x00000010, 0x00000014, 0x00000018,
0x0000001c, 0x00000020, 0x00000024, 0x00000028, 0x0000002c, 0x00000030,
0x00000034, 0x00000038, 0x0000003c, 0x00000040, 0x00000044, 0x00000048,
0x0000004c, 0x00000050, 0x00000054, 0x00000058, 0x0000005c, 0x00000060,
0x00000064, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x000000fc,
0x01ffffff, 0x00000068, 0x0000006c, 0x00000070, 0x00000074, 0x00000078,
0x0000007c, 0x00000080, 0x00000084, 0x00000088, 0x0000008c, 0x00000090,
0x00000094, 0x00000098, 0x0000009c, 0x000000a0, 0x000000a4, 0x000000a8,
0x000000ac, 0x000000b0, 0x000000b4, 0x000000b8, 0x000000bc, 0x000000c0,
0x000000c4, 0x000000c8, 0x000000cc, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff};
constexpr uint32_t d1[256] = {
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x0000e003, 0x01ffffff, 0x0000e003, 0x01ffffff, 0x0000f003,
0x00004003, 0x00005003, 0x00006003, 0x00007003, 0x00008003, 0x00009003,
0x0000a003, 0x0000b003, 0x0000c003, 0x0000d003, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
0x00001000, 0x00002000, 0x00003000, 0x00004000, 0x00005000, 0x00006000,
0x00007000, 0x00008000, 0x00009000, 0x0000a000, 0x0000b000, 0x0000c000,
0x0000d000, 0x0000e000, 0x0000f000, 0x00000001, 0x00001001, 0x00002001,
0x00003001, 0x00004001, 0x00005001, 0x00006001, 0x00007001, 0x00008001,
0x00009001, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x0000f003,
0x01ffffff, 0x0000a001, 0x0000b001, 0x0000c001, 0x0000d001, 0x0000e001,
0x0000f001, 0x00000002, 0x00001002, 0x00002002, 0x00003002, 0x00004002,
0x00005002, 0x00006002, 0x00007002, 0x00008002, 0x00009002, 0x0000a002,
0x0000b002, 0x0000c002, 0x0000d002, 0x0000e002, 0x0000f002, 0x00000003,
0x00001003, 0x00002003, 0x00003003, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff};
constexpr uint32_t d2[256] = {
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x00800f00, 0x01ffffff, 0x00800f00, 0x01ffffff, 0x00c00f00,
0x00000d00, 0x00400d00, 0x00800d00, 0x00c00d00, 0x00000e00, 0x00400e00,
0x00800e00, 0x00c00e00, 0x00000f00, 0x00400f00, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
0x00400000, 0x00800000, 0x00c00000, 0x00000100, 0x00400100, 0x00800100,
0x00c00100, 0x00000200, 0x00400200, 0x00800200, 0x00c00200, 0x00000300,
0x00400300, 0x00800300, 0x00c00300, 0x00000400, 0x00400400, 0x00800400,
0x00c00400, 0x00000500, 0x00400500, 0x00800500, 0x00c00500, 0x00000600,
0x00400600, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00c00f00,
0x01ffffff, 0x00800600, 0x00c00600, 0x00000700, 0x00400700, 0x00800700,
0x00c00700, 0x00000800, 0x00400800, 0x00800800, 0x00c00800, 0x00000900,
0x00400900, 0x00800900, 0x00c00900, 0x00000a00, 0x00400a00, 0x00800a00,
0x00c00a00, 0x00000b00, 0x00400b00, 0x00800b00, 0x00c00b00, 0x00000c00,
0x00400c00, 0x00800c00, 0x00c00c00, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff};
constexpr uint32_t d3[256] = {
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x003e0000, 0x01ffffff, 0x003e0000, 0x01ffffff, 0x003f0000,
0x00340000, 0x00350000, 0x00360000, 0x00370000, 0x00380000, 0x00390000,
0x003a0000, 0x003b0000, 0x003c0000, 0x003d0000, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
0x00010000, 0x00020000, 0x00030000, 0x00040000, 0x00050000, 0x00060000,
0x00070000, 0x00080000, 0x00090000, 0x000a0000, 0x000b0000, 0x000c0000,
0x000d0000, 0x000e0000, 0x000f0000, 0x00100000, 0x00110000, 0x00120000,
0x00130000, 0x00140000, 0x00150000, 0x00160000, 0x00170000, 0x00180000,
0x00190000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x003f0000,
0x01ffffff, 0x001a0000, 0x001b0000, 0x001c0000, 0x001d0000, 0x001e0000,
0x001f0000, 0x00200000, 0x00210000, 0x00220000, 0x00230000, 0x00240000,
0x00250000, 0x00260000, 0x00270000, 0x00280000, 0x00290000, 0x002a0000,
0x002b0000, 0x002c0000, 0x002d0000, 0x002e0000, 0x002f0000, 0x00300000,
0x00310000, 0x00320000, 0x00330000, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff};
} constexpr uint64_t thintable_epi8[256] = {
0x0706050403020100, 0x0007060504030201, 0x0007060504030200,
0x0000070605040302, 0x0007060504030100, 0x0000070605040301,
0x0000070605040300, 0x0000000706050403, 0x0007060504020100,
0x0000070605040201, 0x0000070605040200, 0x0000000706050402,
0x0000070605040100, 0x0000000706050401, 0x0000000706050400,
0x0000000007060504, 0x0007060503020100, 0x0000070605030201,
0x0000070605030200, 0x0000000706050302, 0x0000070605030100,
0x0000000706050301, 0x0000000706050300, 0x0000000007060503,
0x0000070605020100, 0x0000000706050201, 0x0000000706050200,
0x0000000007060502, 0x0000000706050100, 0x0000000007060501,
0x0000000007060500, 0x0000000000070605, 0x0007060403020100,
0x0000070604030201, 0x0000070604030200, 0x0000000706040302,
0x0000070604030100, 0x0000000706040301, 0x0000000706040300,
0x0000000007060403, 0x0000070604020100, 0x0000000706040201,
0x0000000706040200, 0x0000000007060402, 0x0000000706040100,
0x0000000007060401, 0x0000000007060400, 0x0000000000070604,
0x0000070603020100, 0x0000000706030201, 0x0000000706030200,
0x0000000007060302, 0x0000000706030100, 0x0000000007060301,
0x0000000007060300, 0x0000000000070603, 0x0000000706020100,
0x0000000007060201, 0x0000000007060200, 0x0000000000070602,
0x0000000007060100, 0x0000000000070601, 0x0000000000070600,
0x0000000000000706, 0x0007050403020100, 0x0000070504030201,
0x0000070504030200, 0x0000000705040302, 0x0000070504030100,
0x0000000705040301, 0x0000000705040300, 0x0000000007050403,
0x0000070504020100, 0x0000000705040201, 0x0000000705040200,
0x0000000007050402, 0x0000000705040100, 0x0000000007050401,
0x0000000007050400, 0x0000000000070504, 0x0000070503020100,
0x0000000705030201, 0x0000000705030200, 0x0000000007050302,
0x0000000705030100, 0x0000000007050301, 0x0000000007050300,
0x0000000000070503, 0x0000000705020100, 0x0000000007050201,
0x0000000007050200, 0x0000000000070502, 0x0000000007050100,
0x0000000000070501, 0x0000000000070500, 0x0000000000000705,
0x0000070403020100, 0x0000000704030201, 0x0000000704030200,
0x0000000007040302, 0x0000000704030100, 0x0000000007040301,
0x0000000007040300, 0x0000000000070403, 0x0000000704020100,
0x0000000007040201, 0x0000000007040200, 0x0000000000070402,
0x0000000007040100, 0x0000000000070401, 0x0000000000070400,
0x0000000000000704, 0x0000000703020100, 0x0000000007030201,
0x0000000007030200, 0x0000000000070302, 0x0000000007030100,
0x0000000000070301, 0x0000000000070300, 0x0000000000000703,
0x0000000007020100, 0x0000000000070201, 0x0000000000070200,
0x0000000000000702, 0x0000000000070100, 0x0000000000000701,
0x0000000000000700, 0x0000000000000007, 0x0006050403020100,
0x0000060504030201, 0x0000060504030200, 0x0000000605040302,
0x0000060504030100, 0x0000000605040301, 0x0000000605040300,
0x0000000006050403, 0x0000060504020100, 0x0000000605040201,
0x0000000605040200, 0x0000000006050402, 0x0000000605040100,
0x0000000006050401, 0x0000000006050400, 0x0000000000060504,
0x0000060503020100, 0x0000000605030201, 0x0000000605030200,
0x0000000006050302, 0x0000000605030100, 0x0000000006050301,
0x0000000006050300, 0x0000000000060503, 0x0000000605020100,
0x0000000006050201, 0x0000000006050200, 0x0000000000060502,
0x0000000006050100, 0x0000000000060501, 0x0000000000060500,
0x0000000000000605, 0x0000060403020100, 0x0000000604030201,
0x0000000604030200, 0x0000000006040302, 0x0000000604030100,
0x0000000006040301, 0x0000000006040300, 0x0000000000060403,
0x0000000604020100, 0x0000000006040201, 0x0000000006040200,
0x0000000000060402, 0x0000000006040100, 0x0000000000060401,
0x0000000000060400, 0x0000000000000604, 0x0000000603020100,
0x0000000006030201, 0x0000000006030200, 0x0000000000060302,
0x0000000006030100, 0x0000000000060301, 0x0000000000060300,
0x0000000000000603, 0x0000000006020100, 0x0000000000060201,
0x0000000000060200, 0x0000000000000602, 0x0000000000060100,
0x0000000000000601, 0x0000000000000600, 0x0000000000000006,
0x0000050403020100, 0x0000000504030201, 0x0000000504030200,
0x0000000005040302, 0x0000000504030100, 0x0000000005040301,
0x0000000005040300, 0x0000000000050403, 0x0000000504020100,
0x0000000005040201, 0x0000000005040200, 0x0000000000050402,
0x0000000005040100, 0x0000000000050401, 0x0000000000050400,
0x0000000000000504, 0x0000000503020100, 0x0000000005030201,
0x0000000005030200, 0x0000000000050302, 0x0000000005030100,
0x0000000000050301, 0x0000000000050300, 0x0000000000000503,
0x0000000005020100, 0x0000000000050201, 0x0000000000050200,
0x0000000000000502, 0x0000000000050100, 0x0000000000000501,
0x0000000000000500, 0x0000000000000005, 0x0000000403020100,
0x0000000004030201, 0x0000000004030200, 0x0000000000040302,
0x0000000004030100, 0x0000000000040301, 0x0000000000040300,
0x0000000000000403, 0x0000000004020100, 0x0000000000040201,
0x0000000000040200, 0x0000000000000402, 0x0000000000040100,
0x0000000000000401, 0x0000000000000400, 0x0000000000000004,
0x0000000003020100, 0x0000000000030201, 0x0000000000030200,
0x0000000000000302, 0x0000000000030100, 0x0000000000000301,
0x0000000000000300, 0x0000000000000003, 0x0000000000020100,
0x0000000000000201, 0x0000000000000200, 0x0000000000000002,
0x0000000000000100, 0x0000000000000001, 0x0000000000000000,
0x0000000000000000,
};
constexpr uint8_t pshufb_combine_table[272] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08,
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, 0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, 0xff,
0x00, 0x01, 0x02, 0x03, 0x04, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x08, 0x09, 0x0a, 0x0b,
0x0c, 0x0d, 0x0e, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x08,
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x01, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0x09, 0x0a, 0x0b,
0x0c, 0x0d, 0x0e, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
constexpr unsigned char BitsSetTable256mul2[256] = {
0, 2, 2, 4, 2, 4, 4, 6, 2, 4, 4, 6, 4, 6, 6, 8, 2, 4, 4,
6, 4, 6, 6, 8, 4, 6, 6, 8, 6, 8, 8, 10, 2, 4, 4, 6, 4, 6,
6, 8, 4, 6, 6, 8, 6, 8, 8, 10, 4, 6, 6, 8, 6, 8, 8, 10, 6,
8, 8, 10, 8, 10, 10, 12, 2, 4, 4, 6, 4, 6, 6, 8, 4, 6, 6, 8,
6, 8, 8, 10, 4, 6, 6, 8, 6, 8, 8, 10, 6, 8, 8, 10, 8, 10, 10,
12, 4, 6, 6, 8, 6, 8, 8, 10, 6, 8, 8, 10, 8, 10, 10, 12, 6, 8,
8, 10, 8, 10, 10, 12, 8, 10, 10, 12, 10, 12, 12, 14, 2, 4, 4, 6, 4,
6, 6, 8, 4, 6, 6, 8, 6, 8, 8, 10, 4, 6, 6, 8, 6, 8, 8, 10,
6, 8, 8, 10, 8, 10, 10, 12, 4, 6, 6, 8, 6, 8, 8, 10, 6, 8, 8,
10, 8, 10, 10, 12, 6, 8, 8, 10, 8, 10, 10, 12, 8, 10, 10, 12, 10, 12,
12, 14, 4, 6, 6, 8, 6, 8, 8, 10, 6, 8, 8, 10, 8, 10, 10, 12, 6,
8, 8, 10, 8, 10, 10, 12, 8, 10, 10, 12, 10, 12, 12, 14, 6, 8, 8, 10,
8, 10, 10, 12, 8, 10, 10, 12, 10, 12, 12, 14, 8, 10, 10, 12, 10, 12, 12,
14, 10, 12, 12, 14, 12, 14, 14, 16};
constexpr uint8_t to_base64_value[] = {
255, 255, 255, 255, 255, 255, 255, 255, 255, 64, 64, 255, 64, 64, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 64, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255,
255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 255, 255, 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33,
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255};
constexpr uint8_t to_base64_url_value[] = {
255, 255, 255, 255, 255, 255, 255, 255, 255, 64, 64, 255, 64, 64, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 64, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
62, 255, 255, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 255, 255, 255, 255, 63, 255, 26, 27, 28, 29, 30, 31, 32, 33,
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255};
constexpr uint8_t to_base64_default_or_url_value[] = {
255, 255, 255, 255, 255, 255, 255, 255, 255, 64, 64, 255, 64, 64, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 64, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255,
62, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 255, 255, 255, 255, 63, 255, 26, 27, 28, 29, 30, 31, 32, 33,
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255};
static_assert(sizeof(to_base64_value) == 256,
"to_base64_value must have 256 elements");
static_assert(sizeof(to_base64_url_value) == 256,
"to_base64_url_value must have 256 elements");
static_assert(to_base64_value[uint8_t(' ')] == 64,
"space must be == 64 in to_base64_value");
static_assert(to_base64_url_value[uint8_t(' ')] == 64,
"space must be == 64 in to_base64_url_value");
static_assert(to_base64_value[uint8_t('\t')] == 64,
"tab must be == 64 in to_base64_value");
static_assert(to_base64_url_value[uint8_t('\t')] == 64,
"tab must be == 64 in to_base64_url_value");
static_assert(to_base64_value[uint8_t('\r')] == 64,
"cr must be == 64 in to_base64_value");
static_assert(to_base64_url_value[uint8_t('\r')] == 64,
"cr must be == 64 in to_base64_url_value");
static_assert(to_base64_value[uint8_t('\n')] == 64,
"lf must be == 64 in to_base64_value");
static_assert(to_base64_url_value[uint8_t('\n')] == 64,
"lf must be == 64 in to_base64_url_value");
static_assert(to_base64_value[uint8_t('\f')] == 64,
"ff must be == 64 in to_base64_value");
static_assert(to_base64_url_value[uint8_t('\f')] == 64,
"ff must be == 64 in to_base64_url_value");
static_assert(to_base64_value[uint8_t('+')] == 62,
"+ must be == 62 in to_base64_value");
static_assert(to_base64_url_value[uint8_t('-')] == 62,
"- must be == 62 in to_base64_url_value");
static_assert(to_base64_value[uint8_t('/')] == 63,
"/ must be == 63 in to_base64_value");
static_assert(to_base64_url_value[uint8_t('_')] == 63,
"_ must be == 63 in to_base64_url_value");
} } } }
#endif
#ifndef SIMDUTF_BASE64_H
#define SIMDUTF_BASE64_H
#include <cstddef>
#include <cstdint>
#include <cstring>
namespace simdutf {
namespace scalar {
namespace {
namespace base64 {
template <class char_type> bool is_ascii_white_space(char_type c) {
return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f';
}
template <class char_type> simdutf_constexpr23 bool is_eight_byte(char_type c) {
if constexpr (sizeof(char_type) == 1) {
return true;
}
return uint8_t(c) == c;
}
template <class char_type>
simdutf_constexpr23 bool is_ignorable(char_type c,
simdutf::base64_options options) {
const uint8_t *to_base64 =
(options & base64_default_or_url)
? tables::base64::to_base64_default_or_url_value
: ((options & base64_url) ? tables::base64::to_base64_url_value
: tables::base64::to_base64_value);
const bool ignore_garbage =
(options == base64_options::base64_url_accept_garbage) ||
(options == base64_options::base64_default_accept_garbage) ||
(options == base64_options::base64_default_or_url_accept_garbage);
uint8_t code = to_base64[uint8_t(c)];
if (is_eight_byte(c) && code <= 63) {
return false;
}
if (is_eight_byte(c) && code == 64) {
return true;
}
return ignore_garbage;
}
template <class char_type>
simdutf_constexpr23 bool is_base64(char_type c,
simdutf::base64_options options) {
const uint8_t *to_base64 =
(options & base64_default_or_url)
? tables::base64::to_base64_default_or_url_value
: ((options & base64_url) ? tables::base64::to_base64_url_value
: tables::base64::to_base64_value);
uint8_t code = to_base64[uint8_t(c)];
if (is_eight_byte(c) && code <= 63) {
return true;
}
return false;
}
template <class char_type>
simdutf_constexpr23 bool is_base64_or_padding(char_type c,
simdutf::base64_options options) {
const uint8_t *to_base64 =
(options & base64_default_or_url)
? tables::base64::to_base64_default_or_url_value
: ((options & base64_url) ? tables::base64::to_base64_url_value
: tables::base64::to_base64_value);
if (c == '=') {
return true;
}
uint8_t code = to_base64[uint8_t(c)];
if (is_eight_byte(c) && code <= 63) {
return true;
}
return false;
}
template <class char_type>
bool is_ignorable_or_padding(char_type c, simdutf::base64_options options) {
return is_ignorable(c, options) || c == '=';
}
struct reduced_input {
size_t equalsigns; size_t equallocation; size_t srclen; size_t full_input_length; };
template <class char_type>
simdutf_constexpr23 reduced_input find_end(const char_type *src, size_t srclen,
simdutf::base64_options options) {
const uint8_t *to_base64 =
(options & base64_default_or_url)
? tables::base64::to_base64_default_or_url_value
: ((options & base64_url) ? tables::base64::to_base64_url_value
: tables::base64::to_base64_value);
const bool ignore_garbage =
(options == base64_options::base64_url_accept_garbage) ||
(options == base64_options::base64_default_accept_garbage) ||
(options == base64_options::base64_default_or_url_accept_garbage);
size_t equalsigns = 0;
size_t full_input_length = srclen;
while (!ignore_garbage && srclen > 0 &&
scalar::base64::is_eight_byte(src[srclen - 1]) &&
to_base64[uint8_t(src[srclen - 1])] == 64) {
srclen--;
}
size_t equallocation =
srclen; if (ignore_garbage) {
auto it = simdutf::find(src, src + srclen, '=');
if (it != src + srclen) {
equallocation = it - src;
equalsigns = 1;
srclen = equallocation;
full_input_length = equallocation + 1;
}
return {equalsigns, equallocation, srclen, full_input_length};
}
if (!ignore_garbage && srclen > 0 && src[srclen - 1] == '=') {
equallocation = srclen - 1;
srclen--;
equalsigns = 1;
while (srclen > 0 && scalar::base64::is_eight_byte(src[srclen - 1]) &&
to_base64[uint8_t(src[srclen - 1])] == 64) {
srclen--;
}
if (srclen > 0 && src[srclen - 1] == '=') {
equallocation = srclen - 1;
srclen--;
equalsigns = 2;
}
}
return {equalsigns, equallocation, srclen, full_input_length};
}
template <bool check_capacity, class char_type>
simdutf_constexpr23 full_result base64_tail_decode_impl(
char *dst, size_t outlen, const char_type *src, size_t length,
size_t padding_characters, base64_options options, last_chunk_handling_options last_chunk_options) {
char *dstend = dst + outlen;
(void)dstend;
const uint8_t *to_base64 =
(options & base64_default_or_url)
? tables::base64::to_base64_default_or_url_value
: ((options & base64_url) ? tables::base64::to_base64_url_value
: tables::base64::to_base64_value);
const uint32_t *d0 =
(options & base64_default_or_url)
? tables::base64::base64_default_or_url::d0
: ((options & base64_url) ? tables::base64::base64_url::d0
: tables::base64::base64_default::d0);
const uint32_t *d1 =
(options & base64_default_or_url)
? tables::base64::base64_default_or_url::d1
: ((options & base64_url) ? tables::base64::base64_url::d1
: tables::base64::base64_default::d1);
const uint32_t *d2 =
(options & base64_default_or_url)
? tables::base64::base64_default_or_url::d2
: ((options & base64_url) ? tables::base64::base64_url::d2
: tables::base64::base64_default::d2);
const uint32_t *d3 =
(options & base64_default_or_url)
? tables::base64::base64_default_or_url::d3
: ((options & base64_url) ? tables::base64::base64_url::d3
: tables::base64::base64_default::d3);
const bool ignore_garbage =
(options == base64_options::base64_url_accept_garbage) ||
(options == base64_options::base64_default_accept_garbage) ||
(options == base64_options::base64_default_or_url_accept_garbage);
const char_type *srcend = src + length;
const char_type *srcinit = src;
const char *dstinit = dst;
uint32_t x;
size_t idx;
uint8_t buffer[4];
while (true) {
while (srcend - src >= 4 && is_eight_byte(src[0]) &&
is_eight_byte(src[1]) && is_eight_byte(src[2]) &&
is_eight_byte(src[3]) &&
(x = d0[uint8_t(src[0])] | d1[uint8_t(src[1])] |
d2[uint8_t(src[2])] | d3[uint8_t(src[3])]) < 0x01FFFFFF) {
if (check_capacity && dstend - dst < 3) {
return {OUTPUT_BUFFER_TOO_SMALL, size_t(src - srcinit),
size_t(dst - dstinit)};
}
*dst++ = static_cast<char>(x & 0xFF);
*dst++ = static_cast<char>((x >> 8) & 0xFF);
*dst++ = static_cast<char>((x >> 16) & 0xFF);
src += 4;
}
const char_type *srccur = src;
idx = 0;
#ifdef __clang__
if (ignore_garbage && src + 4 <= srcend) {
char_type c0 = src[0];
char_type c1 = src[1];
char_type c2 = src[2];
char_type c3 = src[3];
uint8_t code0 = to_base64[uint8_t(c0)];
uint8_t code1 = to_base64[uint8_t(c1)];
uint8_t code2 = to_base64[uint8_t(c2)];
uint8_t code3 = to_base64[uint8_t(c3)];
buffer[idx] = code0;
idx += (is_eight_byte(c0) && code0 <= 63);
buffer[idx] = code1;
idx += (is_eight_byte(c1) && code1 <= 63);
buffer[idx] = code2;
idx += (is_eight_byte(c2) && code2 <= 63);
buffer[idx] = code3;
idx += (is_eight_byte(c3) && code3 <= 63);
src += 4;
}
#endif
while ((idx < 4) && (src < srcend)) {
char_type c = *src;
uint8_t code = to_base64[uint8_t(c)];
buffer[idx] = uint8_t(code);
if (is_eight_byte(c) && code <= 63) {
idx++;
} else if (!ignore_garbage &&
(code > 64 || !scalar::base64::is_eight_byte(c))) {
return {INVALID_BASE64_CHARACTER, size_t(src - srcinit),
size_t(dst - dstinit)};
} else {
}
src++;
}
if (idx != 4) {
simdutf_log_assert(idx < 4, "idx should be less than 4");
if (!ignore_garbage && (idx + padding_characters > 4)) {
return {INVALID_BASE64_CHARACTER, size_t(src - srcinit),
size_t(dst - dstinit), true};
}
if (!ignore_garbage &&
last_chunk_options == last_chunk_handling_options::loose &&
(idx >= 2) && padding_characters > 0 &&
((idx + padding_characters) & 3) != 0) {
return {INVALID_BASE64_CHARACTER, size_t(src - srcinit),
size_t(dst - dstinit), true};
} else
if (!ignore_garbage &&
last_chunk_options == last_chunk_handling_options::strict &&
(idx >= 2) && ((idx + padding_characters) & 3) != 0) {
return {BASE64_INPUT_REMAINDER, size_t(src - srcinit),
size_t(dst - dstinit), true};
} else
if ((last_chunk_options ==
last_chunk_handling_options::stop_before_partial &&
(padding_characters + idx < 4) && (idx != 0) &&
(idx >= 2 || padding_characters == 0)) ||
(last_chunk_options ==
last_chunk_handling_options::only_full_chunks &&
(idx >= 2 || padding_characters == 0))) {
src = srccur;
return {SUCCESS, size_t(src - srcinit), size_t(dst - dstinit)};
} else {
if (idx == 2) {
uint32_t triple = (uint32_t(buffer[0]) << 3 * 6) +
(uint32_t(buffer[1]) << 2 * 6);
if (!ignore_garbage &&
(last_chunk_options == last_chunk_handling_options::strict) &&
(triple & 0xffff)) {
return {BASE64_EXTRA_BITS, size_t(src - srcinit),
size_t(dst - dstinit)};
}
if (check_capacity && dstend - dst < 1) {
return {OUTPUT_BUFFER_TOO_SMALL, size_t(srccur - srcinit),
size_t(dst - dstinit)};
}
*dst++ = static_cast<char>((triple >> 16) & 0xFF);
} else if (idx == 3) {
uint32_t triple = (uint32_t(buffer[0]) << 3 * 6) +
(uint32_t(buffer[1]) << 2 * 6) +
(uint32_t(buffer[2]) << 1 * 6);
if (!ignore_garbage &&
(last_chunk_options == last_chunk_handling_options::strict) &&
(triple & 0xff)) {
return {BASE64_EXTRA_BITS, size_t(src - srcinit),
size_t(dst - dstinit)};
}
if (check_capacity && dstend - dst < 2) {
return {OUTPUT_BUFFER_TOO_SMALL, size_t(srccur - srcinit),
size_t(dst - dstinit)};
}
*dst++ = static_cast<char>((triple >> 16) & 0xFF);
*dst++ = static_cast<char>((triple >> 8) & 0xFF);
} else if (!ignore_garbage && idx == 1 &&
(!is_partial(last_chunk_options) ||
(is_partial(last_chunk_options) &&
padding_characters > 0))) {
return {BASE64_INPUT_REMAINDER, size_t(src - srcinit),
size_t(dst - dstinit)};
} else if (!ignore_garbage && idx == 0 && padding_characters > 0) {
return {INVALID_BASE64_CHARACTER, size_t(src - srcinit),
size_t(dst - dstinit), true};
}
return {SUCCESS, size_t(src - srcinit), size_t(dst - dstinit)};
}
}
if (check_capacity && dstend - dst < 3) {
return {OUTPUT_BUFFER_TOO_SMALL, size_t(srccur - srcinit),
size_t(dst - dstinit)};
}
uint32_t triple =
(uint32_t(buffer[0]) << 3 * 6) + (uint32_t(buffer[1]) << 2 * 6) +
(uint32_t(buffer[2]) << 1 * 6) + (uint32_t(buffer[3]) << 0 * 6);
*dst++ = static_cast<char>((triple >> 16) & 0xFF);
*dst++ = static_cast<char>((triple >> 8) & 0xFF);
*dst++ = static_cast<char>(triple & 0xFF);
}
}
template <class char_type>
simdutf_constexpr23 full_result base64_tail_decode(
char *dst, const char_type *src, size_t length,
size_t padding_characters, base64_options options, last_chunk_handling_options last_chunk_options) {
return base64_tail_decode_impl<false>(dst, 0, src, length, padding_characters,
options, last_chunk_options);
}
template <class char_type>
simdutf_constexpr23 full_result base64_tail_decode_safe(
char *dst, size_t outlen, const char_type *src, size_t length,
size_t padding_characters, base64_options options, last_chunk_handling_options last_chunk_options) {
return base64_tail_decode_impl<true>(dst, outlen, src, length,
padding_characters, options,
last_chunk_options);
}
inline simdutf_constexpr23 full_result
patch_tail_result(full_result r, size_t previous_input, size_t previous_output,
size_t equallocation, size_t full_input_length,
last_chunk_handling_options last_chunk_options) {
r.input_count += previous_input;
r.output_count += previous_output;
if (r.padding_error) {
r.input_count = equallocation;
}
if (r.error == error_code::SUCCESS) {
if (!is_partial(last_chunk_options)) {
r.input_count = full_input_length;
} else if (r.output_count % 3 != 0) {
r.input_count = full_input_length;
}
}
return r;
}
template <bool use_lines = false>
simdutf_constexpr23 size_t tail_encode_base64_impl(
char *dst, const char *src, size_t srclen, base64_options options,
size_t line_length = simdutf::default_line_length, size_t line_offset = 0) {
if constexpr (use_lines) {
if (line_length < 4) {
line_length = 4;
}
simdutf_log_assert(line_offset <= line_length,
"line_offset should be less than line_length");
}
bool use_padding =
((options & base64_url) == 0) ^
((options & base64_reverse_padding) == base64_reverse_padding);
const char *e0 = (options & base64_url) ? tables::base64::base64_url::e0
: tables::base64::base64_default::e0;
const char *e1 = (options & base64_url) ? tables::base64::base64_url::e1
: tables::base64::base64_default::e1;
const char *e2 = (options & base64_url) ? tables::base64::base64_url::e2
: tables::base64::base64_default::e2;
char *out = dst;
size_t i = 0;
uint8_t t1, t2, t3;
for (; i + 2 < srclen; i += 3) {
t1 = uint8_t(src[i]);
t2 = uint8_t(src[i + 1]);
t3 = uint8_t(src[i + 2]);
if constexpr (use_lines) {
if (line_offset + 3 >= line_length) {
if (line_offset == line_length) {
*out++ = '\n';
*out++ = e0[t1];
*out++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
*out++ = e1[((t2 & 0x0F) << 2) | ((t3 >> 6) & 0x03)];
*out++ = e2[t3];
line_offset = 4;
} else if (line_offset + 1 == line_length) {
*out++ = e0[t1];
*out++ = '\n';
*out++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
*out++ = e1[((t2 & 0x0F) << 2) | ((t3 >> 6) & 0x03)];
*out++ = e2[t3];
line_offset = 3;
} else if (line_offset + 2 == line_length) {
*out++ = e0[t1];
*out++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
*out++ = '\n';
*out++ = e1[((t2 & 0x0F) << 2) | ((t3 >> 6) & 0x03)];
*out++ = e2[t3];
line_offset = 2;
} else if (line_offset + 3 == line_length) {
*out++ = e0[t1];
*out++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
*out++ = e1[((t2 & 0x0F) << 2) | ((t3 >> 6) & 0x03)];
*out++ = '\n';
*out++ = e2[t3];
line_offset = 1;
}
} else {
*out++ = e0[t1];
*out++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
*out++ = e1[((t2 & 0x0F) << 2) | ((t3 >> 6) & 0x03)];
*out++ = e2[t3];
line_offset += 4;
}
} else {
*out++ = e0[t1];
*out++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
*out++ = e1[((t2 & 0x0F) << 2) | ((t3 >> 6) & 0x03)];
*out++ = e2[t3];
}
}
switch (srclen - i) {
case 0:
break;
case 1:
t1 = uint8_t(src[i]);
if constexpr (use_lines) {
if (use_padding) {
if (line_offset + 3 >= line_length) {
if (line_offset == line_length) {
*out++ = '\n';
*out++ = e0[t1];
*out++ = e1[(t1 & 0x03) << 4];
*out++ = '=';
*out++ = '=';
} else if (line_offset + 1 == line_length) {
*out++ = e0[t1];
*out++ = '\n';
*out++ = e1[(t1 & 0x03) << 4];
*out++ = '=';
*out++ = '=';
} else if (line_offset + 2 == line_length) {
*out++ = e0[t1];
*out++ = e1[(t1 & 0x03) << 4];
*out++ = '\n';
*out++ = '=';
*out++ = '=';
} else if (line_offset + 3 == line_length) {
*out++ = e0[t1];
*out++ = e1[(t1 & 0x03) << 4];
*out++ = '=';
*out++ = '\n';
*out++ = '=';
}
} else {
*out++ = e0[t1];
*out++ = e1[(t1 & 0x03) << 4];
*out++ = '=';
*out++ = '=';
}
} else {
if (line_offset + 2 >= line_length) {
if (line_offset == line_length) {
*out++ = '\n';
*out++ = e0[uint8_t(src[i])];
*out++ = e1[(uint8_t(src[i]) & 0x03) << 4];
} else if (line_offset + 1 == line_length) {
*out++ = e0[uint8_t(src[i])];
*out++ = '\n';
*out++ = e1[(uint8_t(src[i]) & 0x03) << 4];
} else {
*out++ = e0[uint8_t(src[i])];
*out++ = e1[(uint8_t(src[i]) & 0x03) << 4];
}
} else {
*out++ = e0[uint8_t(src[i])];
*out++ = e1[(uint8_t(src[i]) & 0x03) << 4];
}
}
} else {
*out++ = e0[t1];
*out++ = e1[(t1 & 0x03) << 4];
if (use_padding) {
*out++ = '=';
*out++ = '=';
}
}
break;
default:
t1 = uint8_t(src[i]);
t2 = uint8_t(src[i + 1]);
if constexpr (use_lines) {
if (use_padding) {
if (line_offset + 3 >= line_length) {
if (line_offset == line_length) {
*out++ = '\n';
*out++ = e0[t1];
*out++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
*out++ = e2[(t2 & 0x0F) << 2];
*out++ = '=';
} else if (line_offset + 1 == line_length) {
*out++ = e0[t1];
*out++ = '\n';
*out++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
*out++ = e2[(t2 & 0x0F) << 2];
*out++ = '=';
} else if (line_offset + 2 == line_length) {
*out++ = e0[t1];
*out++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
*out++ = '\n';
*out++ = e2[(t2 & 0x0F) << 2];
*out++ = '=';
} else if (line_offset + 3 == line_length) {
*out++ = e0[t1];
*out++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
*out++ = e2[(t2 & 0x0F) << 2];
*out++ = '\n';
*out++ = '=';
}
} else {
*out++ = e0[t1];
*out++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
*out++ = e2[(t2 & 0x0F) << 2];
*out++ = '=';
}
} else {
if (line_offset + 3 >= line_length) {
if (line_offset == line_length) {
*out++ = '\n';
*out++ = e0[t1];
*out++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
*out++ = e2[(t2 & 0x0F) << 2];
} else if (line_offset + 1 == line_length) {
*out++ = e0[t1];
*out++ = '\n';
*out++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
*out++ = e2[(t2 & 0x0F) << 2];
} else if (line_offset + 2 == line_length) {
*out++ = e0[t1];
*out++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
*out++ = '\n';
*out++ = e2[(t2 & 0x0F) << 2];
} else {
*out++ = e0[t1];
*out++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
*out++ = e2[(t2 & 0x0F) << 2];
}
} else {
*out++ = e0[t1];
*out++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
*out++ = e2[(t2 & 0x0F) << 2];
}
}
} else {
*out++ = e0[t1];
*out++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
*out++ = e2[(t2 & 0x0F) << 2];
if (use_padding) {
*out++ = '=';
}
}
}
return (size_t)(out - dst);
}
simdutf_unused inline simdutf_constexpr23 size_t tail_encode_base64(
char *dst, const char *src, size_t srclen, base64_options options) {
return tail_encode_base64_impl(dst, src, srclen, options);
}
template <class InputPtr>
simdutf_warn_unused simdutf_constexpr23 size_t
maximal_binary_length_from_base64(InputPtr input, size_t length) noexcept {
size_t padding = 0;
if (length > 0) {
if (input[length - 1] == '=') {
padding++;
if (length > 1 && input[length - 2] == '=') {
padding++;
}
}
}
size_t actual_length = length - padding;
if (actual_length % 4 <= 1) {
return actual_length / 4 * 3;
}
return actual_length / 4 * 3 + (actual_length % 4) - 1;
}
template <class char_type>
simdutf_warn_unused simdutf_constexpr23 size_t
binary_length_from_base64(const char_type *input, size_t length) noexcept {
size_t count = 0;
for (size_t i = 0; i < length; i++) {
count += (input[i] > ' ');
}
size_t padding = 0;
size_t pos = length;
while (pos > 0 && padding < 2) {
char_type c = input[--pos];
if (c == '=') {
padding++;
} else if (c > ' ') {
break;
}
}
return ((count - padding) * 3) / 4;
}
template <typename char_type>
simdutf_warn_unused simdutf_constexpr23 full_result
base64_to_binary_details_impl(
const char_type *input, size_t length, char *output, base64_options options,
last_chunk_handling_options last_chunk_options) noexcept {
const bool ignore_garbage =
(options == base64_options::base64_url_accept_garbage) ||
(options == base64_options::base64_default_accept_garbage) ||
(options == base64_options::base64_default_or_url_accept_garbage);
auto ri = simdutf::scalar::base64::find_end(input, length, options);
size_t equallocation = ri.equallocation;
size_t equalsigns = ri.equalsigns;
length = ri.srclen;
size_t full_input_length = ri.full_input_length;
if (length == 0) {
if (!ignore_garbage && equalsigns > 0) {
return {INVALID_BASE64_CHARACTER, equallocation, 0, true};
}
return {SUCCESS, full_input_length, 0};
}
full_result r = scalar::base64::base64_tail_decode(
output, input, length, equalsigns, options, last_chunk_options);
r = scalar::base64::patch_tail_result(r, 0, 0, equallocation,
full_input_length, last_chunk_options);
if (!is_partial(last_chunk_options) && r.error == error_code::SUCCESS &&
equalsigns > 0 && !ignore_garbage) {
if ((r.output_count % 3 == 0) ||
((r.output_count % 3) + 1 + equalsigns != 4)) {
return {INVALID_BASE64_CHARACTER, equallocation, r.output_count, true};
}
}
if (is_partial(last_chunk_options) && r.error == error_code::SUCCESS &&
r.input_count < full_input_length) {
while (r.input_count < full_input_length &&
base64_ignorable(*(input + r.input_count), options)) {
r.input_count++;
}
if (r.input_count < full_input_length) {
while (r.input_count > 0 &&
base64_ignorable(*(input + r.input_count - 1), options)) {
r.input_count--;
}
}
}
return r;
}
template <typename char_type>
simdutf_constexpr23 simdutf_warn_unused full_result
base64_to_binary_details_safe_impl(
const char_type *input, size_t length, char *output, size_t outlen,
base64_options options,
last_chunk_handling_options last_chunk_options) noexcept {
const bool ignore_garbage =
(options == base64_options::base64_url_accept_garbage) ||
(options == base64_options::base64_default_accept_garbage) ||
(options == base64_options::base64_default_or_url_accept_garbage);
auto ri = simdutf::scalar::base64::find_end(input, length, options);
size_t equallocation = ri.equallocation;
size_t equalsigns = ri.equalsigns;
length = ri.srclen;
size_t full_input_length = ri.full_input_length;
if (length == 0) {
if (!ignore_garbage && equalsigns > 0) {
return {INVALID_BASE64_CHARACTER, equallocation, 0};
}
return {SUCCESS, full_input_length, 0};
}
full_result r = scalar::base64::base64_tail_decode_safe(
output, outlen, input, length, equalsigns, options, last_chunk_options);
r = scalar::base64::patch_tail_result(r, 0, 0, equallocation,
full_input_length, last_chunk_options);
if (!is_partial(last_chunk_options) && r.error == error_code::SUCCESS &&
equalsigns > 0 && !ignore_garbage) {
if ((r.output_count % 3 == 0) ||
((r.output_count % 3) + 1 + equalsigns != 4)) {
return {INVALID_BASE64_CHARACTER, equallocation, r.output_count};
}
}
if (is_partial(last_chunk_options) && r.error == error_code::SUCCESS &&
r.input_count < full_input_length) {
while (r.input_count < full_input_length &&
base64_ignorable(*(input + r.input_count), options)) {
r.input_count++;
}
if (r.input_count < full_input_length) {
while (r.input_count > 0 &&
base64_ignorable(*(input + r.input_count - 1), options)) {
r.input_count--;
}
}
}
return r;
}
simdutf_warn_unused simdutf_constexpr23 size_t
base64_length_from_binary(size_t length, base64_options options) noexcept {
bool use_padding =
((options & base64_url) == 0) ^
((options & base64_reverse_padding) == base64_reverse_padding);
if (!use_padding) {
return length / 3 * 4 + ((length % 3) ? (length % 3) + 1 : 0);
}
return (length + 2) / 3 *
4; }
simdutf_warn_unused simdutf_constexpr23 size_t
base64_length_from_binary_with_lines(size_t length, base64_options options,
size_t line_length) noexcept {
if (length == 0) {
return 0;
}
size_t base64_length =
scalar::base64::base64_length_from_binary(length, options);
if (line_length < 4) {
line_length = 4;
}
size_t lines =
(base64_length + line_length - 1) / line_length; return base64_length + lines - 1;
}
template <typename char_type>
simdutf_warn_unused size_t prefix_length(size_t count,
simdutf::base64_options options,
const char_type *input,
size_t length) noexcept {
size_t i = 0;
while (i < length && is_ignorable(input[i], options)) {
i++;
}
if (count == 0) {
return i; }
for (; i < length; i++) {
if (is_ignorable(input[i], options)) {
continue;
}
count--;
if (count == 0) {
return i + 1;
}
}
simdutf_log_assert(false, "You never get here");
return -1; }
} } } }
#endif
namespace simdutf {
inline std::string_view to_string(base64_options options) {
switch (options) {
case base64_default:
return "base64_default";
case base64_url:
return "base64_url";
case base64_reverse_padding:
return "base64_reverse_padding";
case base64_url_with_padding:
return "base64_url_with_padding";
case base64_default_accept_garbage:
return "base64_default_accept_garbage";
case base64_url_accept_garbage:
return "base64_url_accept_garbage";
case base64_default_or_url:
return "base64_default_or_url";
case base64_default_or_url_accept_garbage:
return "base64_default_or_url_accept_garbage";
}
return "<unknown>";
}
inline std::string_view to_string(last_chunk_handling_options options) {
switch (options) {
case loose:
return "loose";
case strict:
return "strict";
case stop_before_partial:
return "stop_before_partial";
case only_full_chunks:
return "only_full_chunks";
}
return "<unknown>";
}
simdutf_warn_unused size_t
maximal_binary_length_from_base64(const char *input, size_t length) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
maximal_binary_length_from_base64(
const detail::input_span_of_byte_like auto &input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::base64::maximal_binary_length_from_base64(
detail::constexpr_cast_ptr<uint8_t>(input.data()), input.size());
} else
#endif
{
return maximal_binary_length_from_base64(
reinterpret_cast<const char *>(input.data()), input.size());
}
}
#endif
simdutf_warn_unused size_t maximal_binary_length_from_base64(
const char16_t *input, size_t length) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
maximal_binary_length_from_base64(std::span<const char16_t> input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::base64::maximal_binary_length_from_base64(input.data(),
input.size());
} else
#endif
{
return maximal_binary_length_from_base64(input.data(), input.size());
}
}
#endif
simdutf_warn_unused size_t binary_length_from_base64(const char *input,
size_t length) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
binary_length_from_base64(
const detail::input_span_of_byte_like auto &input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::base64::binary_length_from_base64(input.data(),
input.size());
} else
#endif
{
return binary_length_from_base64(
reinterpret_cast<const char *>(input.data()), input.size());
}
}
#endif
simdutf_warn_unused size_t binary_length_from_base64(const char16_t *input,
size_t length) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
binary_length_from_base64(std::span<const char16_t> input) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::base64::binary_length_from_base64(input.data(),
input.size());
} else
#endif
{
return binary_length_from_base64(input.data(), input.size());
}
}
#endif
simdutf_warn_unused result base64_to_binary(
const char *input, size_t length, char *output,
base64_options options = base64_default,
last_chunk_handling_options last_chunk_options = loose) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
base64_to_binary(
const detail::input_span_of_byte_like auto &input,
detail::output_span_of_byte_like auto &&binary_output,
base64_options options = base64_default,
last_chunk_handling_options last_chunk_options = loose) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::base64::base64_to_binary_details_impl(
input.data(), input.size(), binary_output.data(), options,
last_chunk_options);
} else
#endif
{
return base64_to_binary(reinterpret_cast<const char *>(input.data()),
input.size(),
reinterpret_cast<char *>(binary_output.data()),
options, last_chunk_options);
}
}
#endif
inline simdutf_warn_unused simdutf_constexpr23 size_t base64_length_from_binary(
size_t length, base64_options options = base64_default) noexcept {
return scalar::base64::base64_length_from_binary(length, options);
}
inline simdutf_warn_unused simdutf_constexpr23 size_t
base64_length_from_binary_with_lines(
size_t length, base64_options options = base64_default,
size_t line_length = default_line_length) noexcept {
return scalar::base64::base64_length_from_binary_with_lines(length, options,
line_length);
}
size_t binary_to_base64(const char *input, size_t length, char *output,
base64_options options = base64_default) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
binary_to_base64(const detail::input_span_of_byte_like auto &input,
detail::output_span_of_byte_like auto &&binary_output,
base64_options options = base64_default) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::base64::tail_encode_base64(
binary_output.data(), input.data(), input.size(), options);
} else
#endif
{
return binary_to_base64(
reinterpret_cast<const char *>(input.data()), input.size(),
reinterpret_cast<char *>(binary_output.data()), options);
}
}
#endif
size_t
binary_to_base64_with_lines(const char *input, size_t length, char *output,
size_t line_length = simdutf::default_line_length,
base64_options options = base64_default) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
binary_to_base64_with_lines(
const detail::input_span_of_byte_like auto &input,
detail::output_span_of_byte_like auto &&binary_output,
size_t line_length = simdutf::default_line_length,
base64_options options = base64_default) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::base64::tail_encode_base64_impl<true>(
binary_output.data(), input.data(), input.size(), options, line_length);
} else
#endif
{
return binary_to_base64_with_lines(
reinterpret_cast<const char *>(input.data()), input.size(),
reinterpret_cast<char *>(binary_output.data()), line_length, options);
}
}
#endif
#if SIMDUTF_ATOMIC_REF
size_t
atomic_binary_to_base64(const char *input, size_t length, char *output,
base64_options options = base64_default) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused size_t
atomic_binary_to_base64(const detail::input_span_of_byte_like auto &input,
detail::output_span_of_byte_like auto &&binary_output,
base64_options options = base64_default) noexcept {
return atomic_binary_to_base64(
reinterpret_cast<const char *>(input.data()), input.size(),
reinterpret_cast<char *>(binary_output.data()), options);
}
#endif #endif
simdutf_warn_unused result
base64_to_binary(const char16_t *input, size_t length, char *output,
base64_options options = base64_default,
last_chunk_handling_options last_chunk_options =
last_chunk_handling_options::loose) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
base64_to_binary(
std::span<const char16_t> input,
detail::output_span_of_byte_like auto &&binary_output,
base64_options options = base64_default,
last_chunk_handling_options last_chunk_options = loose) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::base64::base64_to_binary_details_impl(
input.data(), input.size(), binary_output.data(), options,
last_chunk_options);
} else
#endif
{
return base64_to_binary(input.data(), input.size(),
reinterpret_cast<char *>(binary_output.data()),
options, last_chunk_options);
}
}
#endif
simdutf_warn_unused full_result
base64_to_binary_details(const char *input, size_t length, char *output,
base64_options options = base64_default,
last_chunk_handling_options last_chunk_options =
last_chunk_handling_options::loose) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 full_result
base64_to_binary_details(
const detail::input_span_of_byte_like auto &input,
detail::output_span_of_byte_like auto &&binary_output,
base64_options options = base64_default,
last_chunk_handling_options last_chunk_options = loose) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::base64::base64_to_binary_details_impl(
input.data(), input.size(), binary_output.data(), options,
last_chunk_options);
} else
#endif
{
return base64_to_binary_details(
reinterpret_cast<const char *>(input.data()), input.size(),
reinterpret_cast<char *>(binary_output.data()), options,
last_chunk_options);
}
}
#endif
simdutf_warn_unused full_result
base64_to_binary_details(const char16_t *input, size_t length, char *output,
base64_options options = base64_default,
last_chunk_handling_options last_chunk_options =
last_chunk_handling_options::loose) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 full_result
base64_to_binary_details(
std::span<const char16_t> input,
detail::output_span_of_byte_like auto &&binary_output,
base64_options options = base64_default,
last_chunk_handling_options last_chunk_options = loose) noexcept {
#if SIMDUTF_CPLUSPLUS23
if consteval {
return scalar::base64::base64_to_binary_details_impl(
input.data(), input.size(), binary_output.data(), options,
last_chunk_options);
} else
#endif
{
return base64_to_binary_details(
input.data(), input.size(),
reinterpret_cast<char *>(binary_output.data()), options,
last_chunk_options);
}
}
#endif
simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 bool
base64_ignorable(char input, base64_options options = base64_default) noexcept {
return scalar::base64::is_ignorable(input, options);
}
simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 bool
base64_ignorable(char16_t input,
base64_options options = base64_default) noexcept {
return scalar::base64::is_ignorable(input, options);
}
simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 bool
base64_valid(char input, base64_options options = base64_default) noexcept {
return scalar::base64::is_base64(input, options);
}
simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 bool
base64_valid(char16_t input, base64_options options = base64_default) noexcept {
return scalar::base64::is_base64(input, options);
}
simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 bool
base64_valid_or_padding(char input,
base64_options options = base64_default) noexcept {
return scalar::base64::is_base64_or_padding(input, options);
}
simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 bool
base64_valid_or_padding(char16_t input,
base64_options options = base64_default) noexcept {
return scalar::base64::is_base64_or_padding(input, options);
}
simdutf_warn_unused result
base64_to_binary_safe(const char *input, size_t length, char *output,
size_t &outlen, base64_options options = base64_default,
last_chunk_handling_options last_chunk_options =
last_chunk_handling_options::loose,
bool decode_up_to_bad_char = false) noexcept;
simdutf_warn_unused result
base64_to_binary_safe(const char16_t *input, size_t length, char *output,
size_t &outlen, base64_options options = base64_default,
last_chunk_handling_options last_chunk_options =
last_chunk_handling_options::loose,
bool decode_up_to_bad_char = false) noexcept;
#if SIMDUTF_ATOMIC_REF
simdutf_warn_unused result atomic_base64_to_binary_safe(
const char *input, size_t length, char *output, size_t &outlen,
base64_options options = base64_default,
last_chunk_handling_options last_chunk_options =
last_chunk_handling_options::loose,
bool decode_up_to_bad_char = false) noexcept;
simdutf_warn_unused result atomic_base64_to_binary_safe(
const char16_t *input, size_t length, char *output, size_t &outlen,
base64_options options = base64_default,
last_chunk_handling_options last_chunk_options = loose,
bool decode_up_to_bad_char = false) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused std::tuple<result, std::size_t>
atomic_base64_to_binary_safe(
const detail::input_span_of_byte_like auto &binary_input,
detail::output_span_of_byte_like auto &&output,
base64_options options = base64_default,
last_chunk_handling_options last_chunk_options =
last_chunk_handling_options::loose,
bool decode_up_to_bad_char = false) noexcept {
size_t outlen = output.size();
auto ret = atomic_base64_to_binary_safe(
reinterpret_cast<const char *>(binary_input.data()), binary_input.size(),
reinterpret_cast<char *>(output.data()), outlen, options,
last_chunk_options, decode_up_to_bad_char);
return {ret, outlen};
}
simdutf_warn_unused std::tuple<result, std::size_t>
atomic_base64_to_binary_safe(
std::span<const char16_t> base64_input,
detail::output_span_of_byte_like auto &&binary_output,
base64_options options = base64_default,
last_chunk_handling_options last_chunk_options = loose,
bool decode_up_to_bad_char = false) noexcept {
size_t outlen = binary_output.size();
auto ret = atomic_base64_to_binary_safe(
base64_input.data(), base64_input.size(),
reinterpret_cast<char *>(binary_output.data()), outlen, options,
last_chunk_options, decode_up_to_bad_char);
return {ret, outlen};
}
#endif #endif
#endif
class implementation {
public:
virtual std::string_view name() const noexcept { return _name; }
virtual std::string_view description() const noexcept { return _description; }
bool supported_by_runtime_system() const;
#if SIMDUTF_FEATURE_DETECT_ENCODING
virtual encoding_type autodetect_encoding(const char *input,
size_t length) const noexcept;
virtual int detect_encodings(const char *input,
size_t length) const noexcept = 0;
#endif
virtual uint32_t required_instruction_sets() const {
return _required_instruction_sets;
}
#if SIMDUTF_FEATURE_UTF8 || SIMDUTF_FEATURE_DETECT_ENCODING
simdutf_warn_unused virtual bool validate_utf8(const char *buf,
size_t len) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF8
simdutf_warn_unused virtual result
validate_utf8_with_errors(const char *buf, size_t len) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_ASCII
simdutf_warn_unused virtual bool
validate_ascii(const char *buf, size_t len) const noexcept = 0;
simdutf_warn_unused virtual result
validate_ascii_with_errors(const char *buf, size_t len) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_ASCII
simdutf_warn_unused virtual bool
validate_utf16be_as_ascii(const char16_t *buf, size_t len) const noexcept = 0;
simdutf_warn_unused virtual bool
validate_utf16le_as_ascii(const char16_t *buf, size_t len) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF16 || SIMDUTF_FEATURE_DETECT_ENCODING
simdutf_warn_unused virtual bool
validate_utf16le(const char16_t *buf, size_t len) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF16
simdutf_warn_unused virtual bool
validate_utf16be(const char16_t *buf, size_t len) const noexcept = 0;
simdutf_warn_unused virtual result
validate_utf16le_with_errors(const char16_t *buf,
size_t len) const noexcept = 0;
simdutf_warn_unused virtual result
validate_utf16be_with_errors(const char16_t *buf,
size_t len) const noexcept = 0;
virtual void to_well_formed_utf16le(const char16_t *input, size_t len,
char16_t *output) const noexcept = 0;
virtual void to_well_formed_utf16be(const char16_t *input, size_t len,
char16_t *output) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF32 || SIMDUTF_FEATURE_DETECT_ENCODING
simdutf_warn_unused virtual bool
validate_utf32(const char32_t *buf, size_t len) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF32
simdutf_warn_unused virtual result
validate_utf32_with_errors(const char32_t *buf,
size_t len) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused virtual size_t
convert_latin1_to_utf8(const char *input, size_t length,
char *utf8_output) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused virtual size_t
convert_latin1_to_utf16le(const char *input, size_t length,
char16_t *utf16_output) const noexcept = 0;
simdutf_warn_unused virtual size_t
convert_latin1_to_utf16be(const char *input, size_t length,
char16_t *utf16_output) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused virtual size_t
convert_latin1_to_utf32(const char *input, size_t length,
char32_t *utf32_buffer) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused virtual size_t
convert_utf8_to_latin1(const char *input, size_t length,
char *latin1_output) const noexcept = 0;
simdutf_warn_unused virtual result
convert_utf8_to_latin1_with_errors(const char *input, size_t length,
char *latin1_output) const noexcept = 0;
simdutf_warn_unused virtual size_t
convert_valid_utf8_to_latin1(const char *input, size_t length,
char *latin1_output) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
simdutf_warn_unused virtual size_t
convert_utf8_to_utf16le(const char *input, size_t length,
char16_t *utf16_output) const noexcept = 0;
simdutf_warn_unused virtual size_t
convert_utf8_to_utf16be(const char *input, size_t length,
char16_t *utf16_output) const noexcept = 0;
simdutf_warn_unused virtual result convert_utf8_to_utf16le_with_errors(
const char *input, size_t length,
char16_t *utf16_output) const noexcept = 0;
simdutf_warn_unused virtual result convert_utf8_to_utf16be_with_errors(
const char *input, size_t length,
char16_t *utf16_output) const noexcept = 0;
virtual simdutf_warn_unused result utf8_length_from_utf16le_with_replacement(
const char16_t *input, size_t length) const noexcept = 0;
virtual simdutf_warn_unused result utf8_length_from_utf16be_with_replacement(
const char16_t *input, size_t length) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
simdutf_warn_unused virtual size_t
convert_utf8_to_utf32(const char *input, size_t length,
char32_t *utf32_output) const noexcept = 0;
simdutf_warn_unused virtual result
convert_utf8_to_utf32_with_errors(const char *input, size_t length,
char32_t *utf32_output) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
simdutf_warn_unused virtual size_t
convert_valid_utf8_to_utf16le(const char *input, size_t length,
char16_t *utf16_buffer) const noexcept = 0;
simdutf_warn_unused virtual size_t
convert_valid_utf8_to_utf16be(const char *input, size_t length,
char16_t *utf16_buffer) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
simdutf_warn_unused virtual size_t
convert_valid_utf8_to_utf32(const char *input, size_t length,
char32_t *utf32_buffer) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
simdutf_warn_unused virtual size_t
utf16_length_from_utf8(const char *input, size_t length) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
simdutf_warn_unused virtual size_t
utf32_length_from_utf8(const char *input, size_t length) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused virtual size_t
convert_utf16le_to_latin1(const char16_t *input, size_t length,
char *latin1_buffer) const noexcept = 0;
simdutf_warn_unused virtual size_t
convert_utf16be_to_latin1(const char16_t *input, size_t length,
char *latin1_buffer) const noexcept = 0;
simdutf_warn_unused virtual result
convert_utf16le_to_latin1_with_errors(const char16_t *input, size_t length,
char *latin1_buffer) const noexcept = 0;
simdutf_warn_unused virtual result
convert_utf16be_to_latin1_with_errors(const char16_t *input, size_t length,
char *latin1_buffer) const noexcept = 0;
simdutf_warn_unused virtual size_t
convert_valid_utf16le_to_latin1(const char16_t *input, size_t length,
char *latin1_buffer) const noexcept = 0;
simdutf_warn_unused virtual size_t
convert_valid_utf16be_to_latin1(const char16_t *input, size_t length,
char *latin1_buffer) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
simdutf_warn_unused virtual size_t
convert_utf16le_to_utf8(const char16_t *input, size_t length,
char *utf8_buffer) const noexcept = 0;
simdutf_warn_unused virtual size_t
convert_utf16be_to_utf8(const char16_t *input, size_t length,
char *utf8_buffer) const noexcept = 0;
simdutf_warn_unused virtual result
convert_utf16le_to_utf8_with_errors(const char16_t *input, size_t length,
char *utf8_buffer) const noexcept = 0;
simdutf_warn_unused virtual result
convert_utf16be_to_utf8_with_errors(const char16_t *input, size_t length,
char *utf8_buffer) const noexcept = 0;
simdutf_warn_unused virtual size_t convert_utf16le_to_utf8_with_replacement(
const char16_t *input, size_t length,
char *utf8_buffer) const noexcept = 0;
simdutf_warn_unused virtual size_t convert_utf16be_to_utf8_with_replacement(
const char16_t *input, size_t length,
char *utf8_buffer) const noexcept = 0;
simdutf_warn_unused virtual size_t
convert_valid_utf16le_to_utf8(const char16_t *input, size_t length,
char *utf8_buffer) const noexcept = 0;
simdutf_warn_unused virtual size_t
convert_valid_utf16be_to_utf8(const char16_t *input, size_t length,
char *utf8_buffer) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
simdutf_warn_unused virtual size_t
convert_utf16le_to_utf32(const char16_t *input, size_t length,
char32_t *utf32_buffer) const noexcept = 0;
simdutf_warn_unused virtual size_t
convert_utf16be_to_utf32(const char16_t *input, size_t length,
char32_t *utf32_buffer) const noexcept = 0;
simdutf_warn_unused virtual result convert_utf16le_to_utf32_with_errors(
const char16_t *input, size_t length,
char32_t *utf32_buffer) const noexcept = 0;
simdutf_warn_unused virtual result convert_utf16be_to_utf32_with_errors(
const char16_t *input, size_t length,
char32_t *utf32_buffer) const noexcept = 0;
simdutf_warn_unused virtual size_t
convert_valid_utf16le_to_utf32(const char16_t *input, size_t length,
char32_t *utf32_buffer) const noexcept = 0;
simdutf_warn_unused virtual size_t
convert_valid_utf16be_to_utf32(const char16_t *input, size_t length,
char32_t *utf32_buffer) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
simdutf_warn_unused virtual size_t
utf8_length_from_utf16le(const char16_t *input,
size_t length) const noexcept = 0;
simdutf_warn_unused virtual size_t
utf8_length_from_utf16be(const char16_t *input,
size_t length) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused virtual size_t
convert_utf32_to_latin1(const char32_t *input, size_t length,
char *latin1_buffer) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused virtual result
convert_utf32_to_latin1_with_errors(const char32_t *input, size_t length,
char *latin1_buffer) const noexcept = 0;
simdutf_warn_unused virtual size_t
convert_valid_utf32_to_latin1(const char32_t *input, size_t length,
char *latin1_buffer) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
simdutf_warn_unused virtual size_t
convert_utf32_to_utf8(const char32_t *input, size_t length,
char *utf8_buffer) const noexcept = 0;
simdutf_warn_unused virtual result
convert_utf32_to_utf8_with_errors(const char32_t *input, size_t length,
char *utf8_buffer) const noexcept = 0;
simdutf_warn_unused virtual size_t
convert_valid_utf32_to_utf8(const char32_t *input, size_t length,
char *utf8_buffer) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused virtual size_t
utf16_length_from_latin1(size_t length) const noexcept {
return length;
}
#endif
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
simdutf_warn_unused virtual size_t
convert_utf32_to_utf16le(const char32_t *input, size_t length,
char16_t *utf16_buffer) const noexcept = 0;
simdutf_warn_unused virtual size_t
convert_utf32_to_utf16be(const char32_t *input, size_t length,
char16_t *utf16_buffer) const noexcept = 0;
simdutf_warn_unused virtual result convert_utf32_to_utf16le_with_errors(
const char32_t *input, size_t length,
char16_t *utf16_buffer) const noexcept = 0;
simdutf_warn_unused virtual result convert_utf32_to_utf16be_with_errors(
const char32_t *input, size_t length,
char16_t *utf16_buffer) const noexcept = 0;
simdutf_warn_unused virtual size_t
convert_valid_utf32_to_utf16le(const char32_t *input, size_t length,
char16_t *utf16_buffer) const noexcept = 0;
simdutf_warn_unused virtual size_t
convert_valid_utf32_to_utf16be(const char32_t *input, size_t length,
char16_t *utf16_buffer) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF16
virtual void change_endianness_utf16(const char16_t *input, size_t length,
char16_t *output) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused virtual size_t
utf8_length_from_latin1(const char *input, size_t length) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
simdutf_warn_unused virtual size_t
utf8_length_from_utf32(const char32_t *input,
size_t length) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused virtual size_t
latin1_length_from_utf32(size_t length) const noexcept {
return length;
}
#endif
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused virtual size_t
latin1_length_from_utf8(const char *input, size_t length) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused virtual size_t
latin1_length_from_utf16(size_t length) const noexcept {
return length;
}
#endif
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
simdutf_warn_unused virtual size_t
utf16_length_from_utf32(const char32_t *input,
size_t length) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused virtual size_t
utf32_length_from_latin1(size_t length) const noexcept {
return length;
}
#endif
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
simdutf_warn_unused virtual size_t
utf32_length_from_utf16le(const char16_t *input,
size_t length) const noexcept = 0;
simdutf_warn_unused virtual size_t
utf32_length_from_utf16be(const char16_t *input,
size_t length) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF16
simdutf_warn_unused virtual size_t
count_utf16le(const char16_t *input, size_t length) const noexcept = 0;
simdutf_warn_unused virtual size_t
count_utf16be(const char16_t *input, size_t length) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_UTF8
simdutf_warn_unused virtual size_t
count_utf8(const char *input, size_t length) const noexcept = 0;
#endif
#if SIMDUTF_FEATURE_BASE64
simdutf_warn_unused size_t maximal_binary_length_from_base64(
const char *input, size_t length) const noexcept;
simdutf_warn_unused size_t maximal_binary_length_from_base64(
const char16_t *input, size_t length) const noexcept;
simdutf_warn_unused virtual size_t
binary_length_from_base64(const char *input, size_t length) const noexcept;
simdutf_warn_unused virtual size_t
binary_length_from_base64(const char16_t *input,
size_t length) const noexcept;
simdutf_warn_unused virtual result
base64_to_binary(const char *input, size_t length, char *output,
base64_options options = base64_default,
last_chunk_handling_options last_chunk_options =
last_chunk_handling_options::loose) const noexcept = 0;
simdutf_warn_unused virtual full_result base64_to_binary_details(
const char *input, size_t length, char *output,
base64_options options = base64_default,
last_chunk_handling_options last_chunk_options =
last_chunk_handling_options::loose) const noexcept = 0;
simdutf_warn_unused virtual result
base64_to_binary(const char16_t *input, size_t length, char *output,
base64_options options = base64_default,
last_chunk_handling_options last_chunk_options =
last_chunk_handling_options::loose) const noexcept = 0;
simdutf_warn_unused virtual full_result base64_to_binary_details(
const char16_t *input, size_t length, char *output,
base64_options options = base64_default,
last_chunk_handling_options last_chunk_options =
last_chunk_handling_options::loose) const noexcept = 0;
simdutf_warn_unused size_t base64_length_from_binary(
size_t length, base64_options options = base64_default) const noexcept;
virtual size_t
binary_to_base64(const char *input, size_t length, char *output,
base64_options options = base64_default) const noexcept = 0;
virtual size_t binary_to_base64_with_lines(
const char *input, size_t length, char *output,
size_t line_length = simdutf::default_line_length,
base64_options options = base64_default) const noexcept = 0;
virtual const char *find(const char *start, const char *end,
char character) const noexcept = 0;
virtual const char16_t *find(const char16_t *start, const char16_t *end,
char16_t character) const noexcept = 0;
#endif
#ifdef SIMDUTF_INTERNAL_TESTS
struct TestProcedure {
std::string_view name;
void (*procedure)(const implementation &);
};
virtual std::vector<TestProcedure> internal_tests() const;
#endif
protected:
simdutf_really_inline implementation(const char *name,
const char *description,
uint32_t required_instruction_sets)
: _name(name), _description(description),
_required_instruction_sets(required_instruction_sets) {}
protected:
~implementation() = default;
private:
const char *_name;
const char *_description;
const uint32_t _required_instruction_sets;
};
namespace internal {
class available_implementation_list {
public:
simdutf_really_inline available_implementation_list() {}
size_t size() const noexcept;
const implementation *const *begin() const noexcept;
const implementation *const *end() const noexcept;
const implementation *operator[](std::string_view name) const noexcept {
for (const implementation *impl : *this) {
if (impl->name() == name) {
return impl;
}
}
return nullptr;
}
const implementation *detect_best_supported() const noexcept;
};
template <typename T> class atomic_ptr {
public:
atomic_ptr(T *_ptr) : ptr{_ptr} {}
#if defined(SIMDUTF_NO_THREADS)
operator const T *() const { return ptr; }
const T &operator*() const { return *ptr; }
const T *operator->() const { return ptr; }
operator T *() { return ptr; }
T &operator*() { return *ptr; }
T *operator->() { return ptr; }
atomic_ptr &operator=(T *_ptr) {
ptr = _ptr;
return *this;
}
#else
operator const T *() const { return ptr.load(); }
const T &operator*() const { return *ptr; }
const T *operator->() const { return ptr.load(); }
operator T *() { return ptr.load(); }
T &operator*() { return *ptr; }
T *operator->() { return ptr.load(); }
atomic_ptr &operator=(T *_ptr) {
ptr = _ptr;
return *this;
}
#endif
private:
#if defined(SIMDUTF_NO_THREADS)
T *ptr;
#else
std::atomic<T *> ptr;
#endif
};
class detect_best_supported_implementation_on_first_use;
}
extern SIMDUTF_DLLIMPORTEXPORT const internal::available_implementation_list &
get_available_implementations();
extern SIMDUTF_DLLIMPORTEXPORT internal::atomic_ptr<const implementation> &
get_active_implementation();
}
#if SIMDUTF_FEATURE_BASE64
#ifndef SIMDUTF_BASE64_IMPLEMENTATION_H
#define SIMDUTF_BASE64_IMPLEMENTATION_H
#include <type_traits>
namespace simdutf {
template <typename chartype>
simdutf_warn_unused simdutf_constexpr23 result slow_base64_to_binary_safe_impl(
const chartype *input, size_t length, char *output, size_t &outlen,
base64_options options,
last_chunk_handling_options last_chunk_options) noexcept {
const bool ignore_garbage = (options & base64_default_accept_garbage) != 0;
auto ri = simdutf::scalar::base64::find_end(input, length, options);
size_t equallocation = ri.equallocation;
size_t equalsigns = ri.equalsigns;
length = ri.srclen;
size_t full_input_length = ri.full_input_length;
(void)full_input_length;
if (length == 0) {
outlen = 0;
if (!ignore_garbage && equalsigns > 0) {
return {INVALID_BASE64_CHARACTER, equallocation};
}
return {SUCCESS, 0};
}
full_result r = scalar::base64::base64_tail_decode_safe(
output, outlen, input, length, equalsigns, options, last_chunk_options);
r = scalar::base64::patch_tail_result(r, 0, 0, equallocation,
full_input_length, last_chunk_options);
outlen = r.output_count;
if (!is_partial(last_chunk_options) && r.error == error_code::SUCCESS &&
equalsigns > 0) {
if ((outlen % 3 == 0) || ((outlen % 3) + 1 + equalsigns != 4)) {
r.error = error_code::INVALID_BASE64_CHARACTER;
}
}
return {r.error, r.input_count}; }
template <typename chartype>
simdutf_warn_unused simdutf_constexpr23 result base64_to_binary_safe_impl(
const chartype *input, size_t length, char *output, size_t &outlen,
base64_options options,
last_chunk_handling_options last_chunk_handling_options,
bool decode_up_to_bad_char) noexcept {
static_assert(std::is_same<chartype, char>::value ||
std::is_same<chartype, char16_t>::value,
"Only char and char16_t are supported.");
size_t remaining_input_length = length;
size_t remaining_output_length = outlen;
size_t input_position = 0;
size_t output_position = 0;
size_t safe_input = detail::min(
remaining_input_length,
base64_length_from_binary(remaining_output_length / 3 * 3, options));
bool done_with_partial = (safe_input == remaining_input_length);
simdutf::full_result r;
#if SIMDUTF_CPLUSPLUS23
if consteval {
r = scalar::base64::base64_to_binary_details_impl(
input + input_position, safe_input, output + output_position, options,
done_with_partial
? last_chunk_handling_options
: simdutf::last_chunk_handling_options::only_full_chunks);
} else
#endif
{
r = get_active_implementation()->base64_to_binary_details(
input + input_position, safe_input, output + output_position, options,
done_with_partial
? last_chunk_handling_options
: simdutf::last_chunk_handling_options::only_full_chunks);
}
simdutf_log_assert(r.input_count <= safe_input,
"You should not read more than safe_input");
simdutf_log_assert(r.output_count <= remaining_output_length,
"You should not write more than remaining_output_length");
input_position += r.input_count;
output_position += r.output_count;
remaining_input_length -= r.input_count;
remaining_output_length -= r.output_count;
if (r.error != simdutf::error_code::SUCCESS) {
if (decode_up_to_bad_char &&
r.error == error_code::INVALID_BASE64_CHARACTER) {
return slow_base64_to_binary_safe_impl(
input, length, output, outlen, options, last_chunk_handling_options);
}
outlen = output_position;
return {r.error, input_position};
}
if (done_with_partial) {
outlen = output_position;
return {simdutf::error_code::SUCCESS, input_position};
}
r = simdutf::scalar::base64::base64_to_binary_details_safe_impl(
input + input_position, remaining_input_length, output + output_position,
remaining_output_length, options, last_chunk_handling_options);
input_position += r.input_count;
output_position += r.output_count;
remaining_input_length -= r.input_count;
remaining_output_length -= r.output_count;
if (r.error != simdutf::error_code::SUCCESS) {
if (decode_up_to_bad_char &&
r.error == error_code::INVALID_BASE64_CHARACTER) {
return slow_base64_to_binary_safe_impl(
input, length, output, outlen, options, last_chunk_handling_options);
}
outlen = output_position;
return {r.error, input_position};
}
if (input_position < length) {
while (input_position > 0 &&
base64_ignorable(input[input_position - 1], options)) {
input_position--;
}
}
outlen = output_position;
return {simdutf::error_code::SUCCESS, input_position};
}
} #endif
namespace simdutf {
#if SIMDUTF_SPAN
simdutf_really_inline
simdutf_constexpr23 simdutf_warn_unused std::tuple<result, std::size_t>
base64_to_binary_safe(
const detail::input_span_of_byte_like auto &input,
detail::output_span_of_byte_like auto &&binary_output,
base64_options options = base64_default,
last_chunk_handling_options last_chunk_options = loose,
bool decode_up_to_bad_char = false) noexcept {
size_t outlen = binary_output.size();
#if SIMDUTF_CPLUSPLUS23
if consteval {
using CInput = std::decay_t<decltype(*input.data())>;
static_assert(std::is_same_v<CInput, char>,
"sorry, the constexpr implementation is for now limited to "
"input of type char");
using COutput = std::decay_t<decltype(*binary_output.data())>;
static_assert(std::is_same_v<COutput, char>,
"sorry, the constexpr implementation is for now limited to "
"output of type char");
auto r = base64_to_binary_safe_impl(
input.data(), input.size(), binary_output.data(), outlen, options,
last_chunk_options, decode_up_to_bad_char);
return {r, outlen};
} else
#endif
{
auto r = base64_to_binary_safe_impl<char>(
reinterpret_cast<const char *>(input.data()), input.size(),
reinterpret_cast<char *>(binary_output.data()), outlen, options,
last_chunk_options, decode_up_to_bad_char);
return {r, outlen};
}
}
#if SIMDUTF_SPAN
simdutf_really_inline
simdutf_warn_unused simdutf_constexpr23 std::tuple<result, std::size_t>
base64_to_binary_safe(
std::span<const char16_t> input,
detail::output_span_of_byte_like auto &&binary_output,
base64_options options = base64_default,
last_chunk_handling_options last_chunk_options = loose,
bool decode_up_to_bad_char = false) noexcept {
size_t outlen = binary_output.size();
#if SIMDUTF_CPLUSPLUS23
if consteval {
auto r = base64_to_binary_safe_impl(
input.data(), input.size(), binary_output.data(), outlen, options,
last_chunk_options, decode_up_to_bad_char);
return {r, outlen};
} else
#endif
{
auto r = base64_to_binary_safe(
input.data(), input.size(),
reinterpret_cast<char *>(binary_output.data()), outlen, options,
last_chunk_options, decode_up_to_bad_char);
return {r, outlen};
}
}
#endif
#endif }
#endif
#if SIMDUTF_CPLUSPLUS23 && SIMDUTF_FEATURE_BASE64
namespace simdutf {
namespace literals {
namespace detail {
template <std::size_t N> struct base64_literal_helper {
std::array<char, N - 1> storage{};
static constexpr std::size_t size() noexcept { return N - 1; }
consteval base64_literal_helper(const char (&str)[N]) {
for (std::size_t i = 0; i < size(); i++) {
storage[i] = str[i];
}
}
};
template <std::size_t InputLen> struct base64_decode_result {
static constexpr std::size_t max_out = (InputLen + 3) / 4 * 3;
std::array<char, max_out> buffer{};
std::size_t output_count{};
};
template <std::size_t InputLen>
consteval auto base64_decode_literal(const char *str) {
base64_decode_result<InputLen> result{};
auto r = scalar::base64::base64_to_binary_details_impl(
str, InputLen, result.buffer.data(), base64_default, loose);
if (r.error != error_code::SUCCESS) {
#if __cpp_lib_unreachable >= 202202L
std::unreachable(); #else
throw "invalid base64 input in _base64 literal";
#endif
}
result.output_count = r.output_count;
return result;
}
template <base64_literal_helper a> consteval auto base64_make_array() {
constexpr auto decoded = base64_decode_literal<a.size()>(a.storage.data());
std::array<char, decoded.output_count> ret{};
for (std::size_t i = 0; i < decoded.output_count; i++) {
ret[i] = decoded.buffer[i];
}
return ret;
}
}
template <detail::base64_literal_helper a> consteval auto operator""_base64() {
return detail::base64_make_array<a>();
}
} }
#endif
#endif
SIMDUTF_POP_DISABLE_WARNINGS
#endif