#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_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_CPLUSPLUS11
#error simdutf requires a compiler compliant with the C++11 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 <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
#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)
#ifdef SIMDUTF_IS_X86_64
#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 <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 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)
#define simdutf_unused
#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))
#define simdutf_unused __attribute__((unused))
#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
#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>
namespace simdutf {
enum encoding_type {
UTF8 = 1, UTF16_LE = 2, UTF16_BE = 4, UTF32_LE = 8, UTF32_BE = 16, Latin1 = 32,
unspecified = 0
};
enum endianness { LITTLE = 0, BIG = 1 };
constexpr bool match_system(endianness e) {
#ifndef SIMDUTF_IS_BIG_ENDIAN
#error "SIMDUTF_IS_BIG_ENDIAN needs to be defined."
#endif
#if SIMDUTF_IS_BIG_ENDIAN
return e == endianness::BIG;
#else
return e == endianness::LITTLE;
#endif
}
std::string to_string(encoding_type bom);
namespace BOM {
encoding_type check_bom(const uint8_t *byte, size_t length);
encoding_type check_bom(const char *byte, size_t length);
size_t bom_byte_size(encoding_type bom);
} } #endif
#ifndef SIMDUTF_ERROR_H
#define SIMDUTF_ERROR_H
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 };
#if SIMDUTF_CPLUSPLUS17
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";
}
}
#endif
struct result {
error_code error;
size_t count;
simdutf_really_inline result() noexcept
: error{error_code::SUCCESS}, count{0} {}
simdutf_really_inline result(error_code err, size_t pos) noexcept
: error{err}, count{pos} {}
simdutf_really_inline bool is_ok() const noexcept {
return error == error_code::SUCCESS;
}
simdutf_really_inline 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 full_result() noexcept
: error{error_code::SUCCESS}, input_count{0}, output_count{0} {}
simdutf_really_inline 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 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 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 "7.7.0"
namespace simdutf {
enum {
SIMDUTF_VERSION_MAJOR = 7,
SIMDUTF_VERSION_MINOR = 7,
SIMDUTF_VERSION_REVISION = 0
};
}
#endif
#ifndef SIMDUTF_IMPLEMENTATION_H
#define SIMDUTF_IMPLEMENTATION_H
#if !defined(SIMDUTF_NO_THREADS)
#include <atomic>
#endif
#include <string>
#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)
#include <cpuid.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)
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);
#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
#if SIMDUTF_SPAN
#include <concepts>
#include <type_traits>
#include <span>
#include <tuple>
#endif
#if SIMDUTF_CPLUSPLUS17
#include <string_view>
#endif
#define SIMDUTF_FEATURE_DETECT_ENCODING 1
#define SIMDUTF_FEATURE_ASCII 1
#define SIMDUTF_FEATURE_LATIN1 1
#define SIMDUTF_FEATURE_UTF8 1
#define SIMDUTF_FEATURE_UTF16 1
#define SIMDUTF_FEATURE_UTF32 1
#define SIMDUTF_FEATURE_BASE64 1
namespace simdutf {
constexpr size_t default_line_length =
76;
#if SIMDUTF_SPAN
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>;
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;
};
} #endif
#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_really_inline simdutf_warn_unused bool
validate_utf8(const detail::input_span_of_byte_like auto &input) noexcept {
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_warn_unused result validate_utf8_with_errors(
const detail::input_span_of_byte_like auto &input) noexcept {
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 bool
validate_ascii(const detail::input_span_of_byte_like auto &input) noexcept {
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 result validate_ascii_with_errors(
const detail::input_span_of_byte_like auto &input) noexcept {
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 bool
validate_utf16_as_ascii(std::span<const char16_t> input) noexcept {
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 bool
validate_utf16be_as_ascii(std::span<const char16_t> input) noexcept {
return validate_utf16be_as_ascii(input.data(), input.size());
}
#endif #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 bool
validate_utf16le_as_ascii(std::span<const char16_t> input) noexcept {
return validate_utf16le_as_ascii(input.data(), input.size());
}
#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 bool
validate_utf16(std::span<const char16_t> input) noexcept {
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_warn_unused bool
validate_utf16le(std::span<const char16_t> input) noexcept {
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 bool
validate_utf16be(std::span<const char16_t> input) noexcept {
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 result
validate_utf16_with_errors(std::span<const char16_t> input) noexcept {
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 result
validate_utf16le_with_errors(std::span<const char16_t> input) noexcept {
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 result
validate_utf16be_with_errors(std::span<const char16_t> input) noexcept {
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 void
to_well_formed_utf16le(std::span<const char16_t> input,
std::span<char16_t> output) noexcept {
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 void
to_well_formed_utf16be(std::span<const char16_t> input,
std::span<char16_t> output) noexcept {
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 void
to_well_formed_utf16(std::span<const char16_t> input,
std::span<char16_t> output) noexcept {
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 bool
validate_utf32(std::span<const char32_t> input) noexcept {
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 result
validate_utf32_with_errors(std::span<const char32_t> input) noexcept {
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 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 {
return convert_latin1_to_utf8(
reinterpret_cast<const char *>(latin1_input.data()), latin1_input.size(),
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 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 {
return convert_latin1_to_utf8_safe(
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 size_t convert_latin1_to_utf16le(
const detail::input_span_of_byte_like auto &latin1_input,
std::span<char16_t> utf16_output) noexcept {
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 size_t
convert_latin1_to_utf16be(const detail::input_span_of_byte_like auto &input,
std::span<char16_t> output) noexcept {
return convert_latin1_to_utf16be(reinterpret_cast<const char *>(input.data()),
input.size(), output.data());
}
#endif
simdutf_warn_unused size_t latin1_length_from_utf16(size_t length) noexcept;
simdutf_warn_unused size_t utf16_length_from_latin1(size_t length) noexcept;
#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 size_t convert_latin1_to_utf32(
const detail::input_span_of_byte_like auto &latin1_input,
std::span<char32_t> utf32_output) noexcept {
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 size_t convert_utf8_to_latin1(
const detail::input_span_of_byte_like auto &input,
detail::output_span_of_byte_like auto &&output) noexcept {
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 size_t
convert_utf8_to_utf16(const detail::input_span_of_byte_like auto &input,
std::span<char16_t> output) noexcept {
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_warn_unused result
utf8_length_from_utf16le_with_replacement(
std::span<const char16_t> valid_utf16_input) noexcept {
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 result
utf8_length_from_utf16be_with_replacement(
std::span<const char16_t> valid_utf16_input) noexcept {
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 size_t
convert_latin1_to_utf16(const detail::input_span_of_byte_like auto &input,
std::span<char16_t> output) noexcept {
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 size_t
convert_utf8_to_utf16le(const detail::input_span_of_byte_like auto &utf8_input,
std::span<char16_t> utf16_output) noexcept {
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 size_t
convert_utf8_to_utf16be(const detail::input_span_of_byte_like auto &utf8_input,
std::span<char16_t> utf16_output) noexcept {
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 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 {
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 result
convert_utf8_to_utf16_with_errors(
const detail::input_span_of_byte_like auto &utf8_input,
std::span<char16_t> utf16_output) noexcept {
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 result
convert_utf8_to_utf16le_with_errors(
const detail::input_span_of_byte_like auto &utf8_input,
std::span<char16_t> utf16_output) noexcept {
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 result
convert_utf8_to_utf16be_with_errors(
const detail::input_span_of_byte_like auto &utf8_input,
std::span<char16_t> utf16_output) noexcept {
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 size_t
convert_utf8_to_utf32(const detail::input_span_of_byte_like auto &utf8_input,
std::span<char32_t> utf32_output) noexcept {
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 result
convert_utf8_to_utf32_with_errors(
const detail::input_span_of_byte_like auto &utf8_input,
std::span<char32_t> utf32_output) noexcept {
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 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 {
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 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 {
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 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 {
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 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 {
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 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 {
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 size_t utf8_length_from_latin1(
const detail::input_span_of_byte_like auto &latin1_input) noexcept {
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 size_t latin1_length_from_utf8(
const detail::input_span_of_byte_like auto &valid_utf8_input) noexcept {
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 size_t utf16_length_from_utf8(
const detail::input_span_of_byte_like auto &valid_utf8_input) noexcept {
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 size_t utf32_length_from_utf8(
const detail::input_span_of_byte_like auto &valid_utf8_input) noexcept {
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 size_t convert_utf16_to_utf8(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
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 size_t convert_utf16_to_utf8_safe(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
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 size_t convert_utf16_to_latin1(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&latin1_output) noexcept {
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 size_t convert_utf16le_to_latin1(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&latin1_output) noexcept {
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 size_t convert_utf16be_to_latin1(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&latin1_output) noexcept {
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 size_t convert_utf16le_to_utf8(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
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 size_t convert_utf16be_to_utf8(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
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 result
convert_utf16_to_latin1_with_errors(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&latin1_output) noexcept {
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 result
convert_utf16le_to_latin1_with_errors(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&latin1_output) noexcept {
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 result
convert_utf16be_to_latin1_with_errors(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&latin1_output) noexcept {
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 result
convert_utf16_to_utf8_with_errors(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
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 result
convert_utf16le_to_utf8_with_errors(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
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 result
convert_utf16be_to_utf8_with_errors(
std::span<const char16_t> utf16_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
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_valid_utf16_to_utf8(
const char16_t *input, size_t length, char *utf8_buffer) noexcept;
#if SIMDUTF_SPAN
simdutf_really_inline simdutf_warn_unused 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 {
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 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 {
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_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 {
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_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 {
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 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 {
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 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 {
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 size_t
convert_utf16_to_utf32(std::span<const char16_t> utf16_input,
std::span<char32_t> utf32_output) noexcept {
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 size_t
convert_utf16le_to_utf32(std::span<const char16_t> utf16_input,
std::span<char32_t> utf32_output) noexcept {
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 size_t
convert_utf16be_to_utf32(std::span<const char16_t> utf16_input,
std::span<char32_t> utf32_output) noexcept {
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 result
convert_utf16_to_utf32_with_errors(std::span<const char16_t> utf16_input,
std::span<char32_t> utf32_output) noexcept {
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 result
convert_utf16le_to_utf32_with_errors(
std::span<const char16_t> utf16_input,
std::span<char32_t> utf32_output) noexcept {
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 result
convert_utf16be_to_utf32_with_errors(
std::span<const char16_t> utf16_input,
std::span<char32_t> utf32_output) noexcept {
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 size_t
convert_valid_utf16_to_utf32(std::span<const char16_t> valid_utf16_input,
std::span<char32_t> utf32_output) noexcept {
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 size_t
convert_valid_utf16le_to_utf32(std::span<const char16_t> valid_utf16_input,
std::span<char32_t> utf32_output) noexcept {
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 size_t
convert_valid_utf16be_to_utf32(std::span<const char16_t> valid_utf16_input,
std::span<char32_t> utf32_output) noexcept {
return convert_valid_utf16be_to_utf32(
valid_utf16_input.data(), valid_utf16_input.size(), utf32_output.data());
}
#endif #endif
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
simdutf_warn_unused size_t latin1_length_from_utf16(size_t length) noexcept;
#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 size_t
utf8_length_from_utf16(std::span<const char16_t> valid_utf16_input) noexcept {
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 result
utf8_length_from_utf16_with_replacement(
std::span<const char16_t> valid_utf16_input) noexcept {
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_warn_unused size_t
utf8_length_from_utf16le(std::span<const char16_t> valid_utf16_input) noexcept {
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 size_t
utf8_length_from_utf16be(std::span<const char16_t> valid_utf16_input) noexcept {
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 size_t convert_utf32_to_utf8(
std::span<const char32_t> utf32_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
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 result
convert_utf32_to_utf8_with_errors(
std::span<const char32_t> utf32_input,
detail::output_span_of_byte_like auto &&utf8_output) noexcept {
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 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 {
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 size_t
convert_utf32_to_utf16(std::span<const char32_t> utf32_input,
std::span<char16_t> utf16_output) noexcept {
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 size_t
convert_utf32_to_utf16le(std::span<const char32_t> utf32_input,
std::span<char16_t> utf16_output) noexcept {
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 size_t convert_utf32_to_latin1(
std::span<const char32_t> utf32_input,
detail::output_span_of_byte_like auto &&latin1_output) noexcept {
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 result
convert_utf32_to_latin1_with_errors(
std::span<const char32_t> utf32_input,
detail::output_span_of_byte_like auto &&latin1_output) noexcept {
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_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 {
return convert_valid_utf32_to_latin1(
valid_utf32_input.data(), valid_utf32_input.size(),
reinterpret_cast<char *>(latin1_output.data()));
}
#endif
simdutf_warn_unused size_t latin1_length_from_utf32(size_t length) noexcept;
simdutf_warn_unused size_t utf32_length_from_latin1(size_t length) noexcept;
#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 size_t
convert_utf32_to_utf16be(std::span<const char32_t> utf32_input,
std::span<char16_t> utf16_output) noexcept {
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 result
convert_utf32_to_utf16_with_errors(std::span<const char32_t> utf32_input,
std::span<char16_t> utf16_output) noexcept {
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 result
convert_utf32_to_utf16le_with_errors(
std::span<const char32_t> utf32_input,
std::span<char16_t> utf16_output) noexcept {
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 result
convert_utf32_to_utf16be_with_errors(
std::span<const char32_t> utf32_input,
std::span<char16_t> utf16_output) noexcept {
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 size_t
convert_valid_utf32_to_utf16(std::span<const char32_t> valid_utf32_input,
std::span<char16_t> utf16_output) noexcept {
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 size_t
convert_valid_utf32_to_utf16le(std::span<const char32_t> valid_utf32_input,
std::span<char16_t> utf16_output) noexcept {
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 size_t
convert_valid_utf32_to_utf16be(std::span<const char32_t> valid_utf32_input,
std::span<char16_t> utf16_output) noexcept {
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 void
change_endianness_utf16(std::span<const char16_t> utf16_input,
std::span<char16_t> utf16_output) noexcept {
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 size_t
utf8_length_from_utf32(std::span<const char32_t> valid_utf32_input) noexcept {
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 size_t
utf16_length_from_utf32(std::span<const char32_t> valid_utf32_input) noexcept {
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 size_t
utf32_length_from_utf16(std::span<const char16_t> valid_utf16_input) noexcept {
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 size_t utf32_length_from_utf16le(
std::span<const char16_t> valid_utf16_input) noexcept {
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 size_t utf32_length_from_utf16be(
std::span<const char16_t> valid_utf16_input) noexcept {
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 size_t
count_utf16(std::span<const char16_t> valid_utf16_input) noexcept {
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 size_t
count_utf16le(std::span<const char16_t> valid_utf16_input) noexcept {
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 size_t
count_utf16be(std::span<const char16_t> valid_utf16_input) noexcept {
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 size_t count_utf8(
const detail::input_span_of_byte_like auto &valid_utf8_input) noexcept {
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 size_t trim_partial_utf8(
const detail::input_span_of_byte_like auto &valid_utf8_input) noexcept {
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 size_t
trim_partial_utf16be(std::span<const char16_t> valid_utf16_input) noexcept {
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 size_t
trim_partial_utf16le(std::span<const char16_t> valid_utf16_input) noexcept {
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 size_t
trim_partial_utf16(std::span<const char16_t> valid_utf16_input) noexcept {
return trim_partial_utf16(valid_utf16_input.data(), valid_utf16_input.size());
}
#endif #endif
#if SIMDUTF_FEATURE_BASE64
#ifndef SIMDUTF_NEED_TRAILING_ZEROES
#define SIMDUTF_NEED_TRAILING_ZEROES 1
#endif
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,
};
#if SIMDUTF_CPLUSPLUS17
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>";
}
#endif
enum last_chunk_handling_options : uint64_t {
loose = 0,
strict = 1,
stop_before_partial =
2,
only_full_chunks =
3
};
inline bool is_partial(last_chunk_handling_options options) {
return (options == stop_before_partial) || (options == only_full_chunks);
}
#if SIMDUTF_CPLUSPLUS17
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>";
}
#endif
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 size_t
maximal_binary_length_from_base64(
const detail::input_span_of_byte_like auto &input) noexcept {
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 size_t
maximal_binary_length_from_base64(std::span<const char16_t> input) noexcept {
return maximal_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 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 {
return base64_to_binary(reinterpret_cast<const char *>(input.data()),
input.size(),
reinterpret_cast<char *>(binary_output.data()),
options, last_chunk_options);
}
#endif
simdutf_warn_unused size_t base64_length_from_binary(
size_t length, base64_options options = base64_default) noexcept;
simdutf_warn_unused size_t base64_length_from_binary_with_lines(
size_t length, base64_options options = base64_default,
size_t line_length = default_line_length) noexcept;
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 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 {
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 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 {
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 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 {
return base64_to_binary(input.data(), input.size(),
reinterpret_cast<char *>(binary_output.data()),
options, last_chunk_options);
}
#endif
simdutf_warn_unused bool
base64_ignorable(char input, base64_options options = base64_default) noexcept;
simdutf_warn_unused bool
base64_ignorable(char16_t input,
base64_options options = base64_default) noexcept;
simdutf_warn_unused bool
base64_valid(char input, base64_options options = base64_default) noexcept;
simdutf_warn_unused bool
base64_valid(char16_t input, base64_options options = base64_default) noexcept;
simdutf_warn_unused bool
base64_valid_or_padding(char input,
base64_options options = base64_default) noexcept;
simdutf_warn_unused bool
base64_valid_or_padding(char16_t input,
base64_options options = base64_default) noexcept;
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;
#if SIMDUTF_SPAN
simdutf_really_inline 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();
auto r = base64_to_binary_safe(
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};
}
#endif
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_SPAN
simdutf_really_inline simdutf_warn_unused 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();
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
#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
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;
#endif
class implementation {
public:
virtual std::string name() const { return std::string(_name); }
virtual std::string description() const { return std::string(_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_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 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 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[](const std::string &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();
}
#endif
SIMDUTF_POP_DISABLE_WARNINGS
#endif