4#include "Stroika/Foundation/StroikaPreComp.h"
8#include "Stroika/Foundation/Execution/Exceptions.h"
17 template <
typename FACET>
18 struct deletable_facet_ : FACET {
19 template <
typename... Args>
20 deletable_facet_ (Args&&... args)
21 : FACET{forward<Args> (args)...}
64 namespace UTFConvert_libutfxx_ {
68#if defined(__clang_major__) and (20 < __clang_major__)
69 DISABLE_COMPILER_CLANG_WARNING_START (
"clang diagnostic ignored \"-Wcharacter-conversion\"")
73 static constexpr char32_t UNI_MAX_BMP = (char32_t)0x0000FFFF;
74 static constexpr char32_t UNI_MAX_UTF16 = (char32_t)0x0010FFFF;
75 static constexpr char32_t UNI_MAX_LEGAL_UTF32 = (char32_t)0x0010FFFF;
77 enum ConversionResult {
88 return UTFConvert::ConversionStatusFlag::ok;
90 return UTFConvert::ConversionStatusFlag::sourceExhausted;
93 return UTFConvert::ConversionStatusFlag::sourceIllegal;
95 return UTFConvert::ConversionStatusFlag::sourceIllegal;
98 return UTFConvert::ConversionStatusFlag::sourceIllegal;
102 constexpr int halfShift = 10;
104 constexpr char32_t halfBase = 0x0010000UL;
105 constexpr char32_t halfMask = 0x3FFUL;
112 constexpr char32_t offsetsFromUTF8[6] = {0x00000000UL, 0x00003080UL, 0x000E2080UL, 0x03C82080UL, 0xFA082080UL, 0x82082080UL};
121 constexpr char8_t firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC};
130 constexpr char trailingBytesForUTF8[256] = {
131 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
132 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
133 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
134 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
135 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
136 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5};
148 bool isLegalUTF8_ (
const char8_t* source,
int length)
151 const char8_t* srcptr = source + length;
157 if ((a = (*--srcptr)) < 0x80 || a > 0xBF)
160 if ((a = (*--srcptr)) < 0x80 || a > 0xBF)
163 if ((a = (*--srcptr)) > 0xBF)
166 switch ((
unsigned char)*source) {
190 if (*source >= 0x80 && *source < 0xC2)
198 inline ConversionResult ConvertUTF8toUTF16_ (
const char8_t** sourceStart,
const char8_t* sourceEnd,
char16_t** targetStart,
199 char16_t* targetEnd, optional<char32_t> missingCharacterReplacement)
201 ConversionResult result = conversionOK;
202 const char8_t* source = *sourceStart;
203 char16_t* target = *targetStart;
204 auto addMissing = [&] () {
208 *target++ = p.second;
211 *target++ =
static_cast<char16_t> (*missingCharacterReplacement);
214 while (source < sourceEnd) {
216 unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
217 if (source + extraBytesToRead >= sourceEnd) {
218 result = sourceExhausted;
221 if (!isLegalUTF8_ (source, extraBytesToRead + 1)) {
222 if (missingCharacterReplacement) {
226 result = sourceIllegal;
233 switch (extraBytesToRead) {
252 ch -= offsetsFromUTF8[extraBytesToRead];
254 if (target >= targetEnd) [[unlikely]] {
255 source -= (extraBytesToRead + 1);
256 result = targetExhausted;
259 if (ch <= UNI_MAX_BMP) {
261 if (ch >= Character::kUNICODESurrogate_High_Start && ch <= Character::kUNICODESurrogate_Low_End) {
262 if (missingCharacterReplacement) {
266 source -= (extraBytesToRead + 1);
267 result = sourceIllegal;
272 *target++ = (char16_t)ch;
275 else if (ch > UNI_MAX_UTF16) {
276 if (missingCharacterReplacement) {
280 result = sourceIllegal;
281 source -= (extraBytesToRead + 1);
287 if (target + 1 >= targetEnd) {
288 source -= (extraBytesToRead + 1);
289 result = targetExhausted;
293 *target++ = (char16_t)((ch >> halfShift) + Character::kUNICODESurrogate_High_Start);
294 *target++ = (char16_t)((ch & halfMask) + Character::kUNICODESurrogate_Low_Start);
297 *sourceStart = source;
298 *targetStart = target;
301 inline ConversionResult ConvertUTF16toUTF8_ (
const char16_t** sourceStart,
const char16_t* sourceEnd,
char8_t** targetStart,
302 char8_t* targetEnd, optional<char32_t> missingCharacterReplacement)
304 ConversionResult result = conversionOK;
305 const char16_t* source = *sourceStart;
306 char8_t* target = *targetStart;
307 while (source < sourceEnd) {
309 unsigned short bytesToWrite = 0;
310 constexpr char32_t byteMask = 0xBF;
311 constexpr char32_t byteMark = 0x80;
312 const char16_t* oldSource = source;
315 if (ch >= Character::kUNICODESurrogate_High_Start && ch <= Character::kUNICODESurrogate_High_End) [[unlikely]] {
317 if (source < sourceEnd) [[likely]] {
318 char32_t ch2 = *source;
320 if (ch2 >= Character::kUNICODESurrogate_Low_Start && ch2 <= Character::kUNICODESurrogate_Low_End) {
321 ch = ((ch - Character::kUNICODESurrogate_High_Start) << halfShift) + (ch2 - Character::kUNICODESurrogate_Low_Start) + halfBase;
324 else if (missingCharacterReplacement == nullopt) {
326 result = sourceIllegal;
332 result = sourceExhausted;
336 else if (missingCharacterReplacement == nullopt) {
338 if (ch >= Character::kUNICODESurrogate_Low_Start && ch <= Character::kUNICODESurrogate_Low_End) {
340 result = sourceIllegal;
345 if (ch < (
char32_t)0x80) {
348 else if (ch < (
char32_t)0x800) {
351 else if (ch < (
char32_t)0x10000) {
354 else if (ch < (
char32_t)0x110000) {
359 Assert (missingCharacterReplacement.has_value ());
360 ch = *missingCharacterReplacement;
363 target += bytesToWrite;
364 if (target > targetEnd) {
366 target -= bytesToWrite;
367 result = targetExhausted;
370 switch (bytesToWrite) {
372 *--target = (char8_t)((ch | byteMark) & byteMask);
375 *--target = (char8_t)((ch | byteMark) & byteMask);
378 *--target = (char8_t)((ch | byteMark) & byteMask);
381 *--target = (char8_t)(ch | firstByteMark[bytesToWrite]);
383 target += bytesToWrite;
385 *sourceStart = source;
386 *targetStart = target;
389 DISABLE_COMPILER_MSC_WARNING_START (4701)
390 DISABLE_COMPILER_GCC_WARNING_START ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"");
391 inline ConversionResult ConvertUTF16toUTF32_ (const
char16_t** sourceStart, const
char16_t* sourceEnd,
char32_t** targetStart,
392 char32_t* targetEnd, optional<
char32_t> missingCharacterReplacement)
394 ConversionResult result = conversionOK;
395 const char16_t* source = *sourceStart;
396 char32_t* target = *targetStart;
398 while (source < sourceEnd) {
399 const char16_t* oldSource = source;
402 if (ch >= Character::kUNICODESurrogate_High_Start && ch <= Character::kUNICODESurrogate_High_End) [[unlikely]] {
404 if (source < sourceEnd) {
407 if (ch2 >= Character::kUNICODESurrogate_Low_Start && ch2 <= Character::kUNICODESurrogate_Low_End) {
408 ch = ((ch - Character::kUNICODESurrogate_High_Start) << halfShift) + (ch2 - Character::kUNICODESurrogate_Low_Start) + halfBase;
411 else if (missingCharacterReplacement == nullopt) {
413 result = sourceIllegal;
419 result = sourceExhausted;
423 else if (missingCharacterReplacement == nullopt) {
425 if (ch >= Character::kUNICODESurrogate_Low_Start && ch <= Character::kUNICODESurrogate_Low_End) {
427 result = sourceIllegal;
431 if (target >= targetEnd) {
433 result = targetExhausted;
438 *sourceStart = source;
439 *targetStart = target;
440 if (result == sourceIllegal) {
441 using namespace Characters::Literals;
442 DbgTrace (
"ConvertUTF16toUTF32 illegal seq 0x{:x},0x{:x}"_f,
static_cast<int> (ch),
static_cast<int> (ch2));
446 DISABLE_COMPILER_MSC_WARNING_END (4701)
447 DISABLE_COMPILER_GCC_WARNING_END ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"");
448 inline ConversionResult ConvertUTF32toUTF16_ (const
char32_t** sourceStart, const
char32_t* sourceEnd,
char16_t** targetStart,
449 char16_t* targetEnd, optional<
char32_t> missingCharacterReplacement)
451 ConversionResult result = conversionOK;
452 const char32_t* source = *sourceStart;
453 char16_t* target = *targetStart;
454 auto addMissing = [&] () {
458 *target++ = p.second;
461 *target++ =
static_cast<char16_t> (*missingCharacterReplacement);
464 while (source < sourceEnd) {
466 if (target >= targetEnd) {
467 result = targetExhausted;
471 if (ch <= UNI_MAX_BMP) [[likely]] {
473 if (ch >= Character::kUNICODESurrogate_High_Start && ch <= Character::kUNICODESurrogate_Low_End) [[unlikely]] {
474 if (missingCharacterReplacement == nullopt) {
476 result = sourceIllegal;
484 *target++ = (char16_t)ch;
487 else if (ch > UNI_MAX_LEGAL_UTF32) {
488 if (missingCharacterReplacement) {
492 result = sourceIllegal;
497 if (target + 1 >= targetEnd) {
499 result = targetExhausted;
503 *target++ = (char16_t)((ch >> halfShift) + Character::kUNICODESurrogate_High_Start);
504 *target++ = (char16_t)((ch & halfMask) + Character::kUNICODESurrogate_Low_Start);
507 *sourceStart = source;
508 *targetStart = target;
511 inline ConversionResult ConvertUTF8toUTF32_ (
const char8_t** sourceStart,
const char8_t* sourceEnd,
char32_t** targetStart,
512 char32_t* targetEnd, optional<char32_t> missingCharacterReplacement)
514 ConversionResult result = conversionOK;
515 const char8_t* source = *sourceStart;
516 char32_t* target = *targetStart;
517 while (source < sourceEnd) {
519 unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
520 if (source + extraBytesToRead >= sourceEnd) [[unlikely]] {
521 result = sourceExhausted;
524 if (!isLegalUTF8_ (source, extraBytesToRead + 1)) {
525 if (missingCharacterReplacement) {
529 result = sourceIllegal;
536 switch (extraBytesToRead) {
555 ch -= offsetsFromUTF8[extraBytesToRead];
557 if (target >= targetEnd) [[unlikely]] {
558 source -= (extraBytesToRead + 1);
559 result = targetExhausted;
562 if (ch <= UNI_MAX_LEGAL_UTF32) [[likely]] {
567 if (ch >= Character::kUNICODESurrogate_High_Start && ch <= Character::kUNICODESurrogate_Low_End) {
568 if (missingCharacterReplacement) {
569 *target++ = *missingCharacterReplacement;
572 source -= (extraBytesToRead + 1);
573 result = sourceIllegal;
582 if (missingCharacterReplacement) {
583 *target++ = *missingCharacterReplacement;
586 result = sourceIllegal;
591 *sourceStart = source;
592 *targetStart = target;
595 inline ConversionResult ConvertUTF32toUTF8_ (
const char32_t** sourceStart,
const char32_t* sourceEnd,
char8_t** targetStart,
596 char8_t* targetEnd, optional<char32_t> missingCharacterReplacement)
598 ConversionResult result = conversionOK;
599 const char32_t* source = *sourceStart;
600 char8_t* target = *targetStart;
601 while (source < sourceEnd) {
603 unsigned short bytesToWrite = 0;
604 const char32_t byteMask = 0xBF;
605 const char32_t byteMark = 0x80;
607 if (missingCharacterReplacement == nullopt) {
609 if (ch >= Character::kUNICODESurrogate_High_Start && ch <= Character::kUNICODESurrogate_Low_End) [[unlikely]] {
611 result = sourceIllegal;
619 if (ch < (
char32_t)0x80) {
622 else if (ch < (
char32_t)0x800) {
625 else if (ch < (
char32_t)0x10000) {
628 else if (ch <= UNI_MAX_LEGAL_UTF32) {
632 if (missingCharacterReplacement) {
633 ch = *missingCharacterReplacement;
637 result = sourceIllegal;
642 target += bytesToWrite;
643 if (target > targetEnd) {
645 target -= bytesToWrite;
646 result = targetExhausted;
649 switch (bytesToWrite) {
651 *--target = (char8_t)((ch | byteMark) & byteMask);
654 *--target = (char8_t)((ch | byteMark) & byteMask);
657 *--target = (char8_t)((ch | byteMark) & byteMask);
660 *--target = (char8_t)(ch | firstByteMark[bytesToWrite]);
662 target += bytesToWrite;
664 *sourceStart = source;
665 *targetStart = target;
669#if defined(__clang_major__) and (20 < __clang_major__)
670 DISABLE_COMPILER_CLANG_WARNING_END (
"clang diagnostic ignored \"-Wcharacter-conversion\"")
676 namespace UTFConvert_codecvtSupport_ {
680 case codecvt_base::ok:
681 return UTFConvert::ConversionStatusFlag::ok;
682 case codecvt_base::error:
683 return UTFConvert::ConversionStatusFlag::sourceIllegal;
684 case codecvt_base::partial:
685 return UTFConvert::ConversionStatusFlag::sourceExhausted;
686 case codecvt_base::noconv:
687 return UTFConvert::ConversionStatusFlag::sourceIllegal;
690 return UTFConvert::ConversionStatusFlag::sourceIllegal;
694 char16_t** targetStart,
char16_t* targetEnd)
696 DISABLE_COMPILER_MSC_WARNING_START (4996)
697 static const deletable_facet_<codecvt<
char16_t,
char8_t, mbstate_t>> cvt;
698 mbstate_t ignoredMBState{};
699 const char8_t* sourceCursor = *sourceStart;
700 char16_t* outCursor = *targetStart;
701 codecvt_base::result rr = cvt.in (ignoredMBState, *sourceStart, sourceEnd, sourceCursor, *targetStart, targetEnd, outCursor);
702 *sourceStart =
reinterpret_cast<const char8_t*
> (sourceCursor);
703 *targetStart = outCursor;
704 return cvt_stdcodecvt_results_ (rr);
705 DISABLE_COMPILER_MSC_WARNING_END (4996)
708 char8_t** targetStart,
char8_t* targetEnd)
710 DISABLE_COMPILER_MSC_WARNING_START (4996)
711 static const deletable_facet_<codecvt<
char16_t,
char8_t, mbstate_t>> cvt;
712 mbstate_t ignoredMBState{};
713 const char16_t* sourceCursor = *sourceStart;
714 char8_t* outCursor = *targetStart;
715 codecvt_base::result rr = cvt.out (ignoredMBState, *sourceStart, sourceEnd, sourceCursor, *targetStart, targetEnd, outCursor);
716 *sourceStart =
reinterpret_cast<const char16_t*
> (sourceCursor);
717 *targetStart =
reinterpret_cast<char8_t*
> (outCursor);
718 return cvt_stdcodecvt_results_ (rr);
719 DISABLE_COMPILER_MSC_WARNING_END (4996)
722 char32_t** targetStart,
char32_t* targetEnd)
724 DISABLE_COMPILER_MSC_WARNING_START (4996)
725 static const deletable_facet_<codecvt<
char32_t,
char8_t, mbstate_t>> cvt;
726 mbstate_t ignoredState{};
728 const char8_t* sourceCursor = *sourceStart;
729 char32_t* outCursor = *targetStart;
730 codecvt_base::result rr = cvt.in (ignoredState, *sourceStart, sourceEnd, sourceCursor, *targetStart, targetEnd, outCursor);
731 *sourceStart =
reinterpret_cast<const char8_t*
> (sourceCursor);
732 *targetStart = outCursor;
733 return cvt_stdcodecvt_results_ (rr);
734 DISABLE_COMPILER_MSC_WARNING_END (4996)
737 char8_t** targetStart,
char8_t* targetEnd)
739 DISABLE_COMPILER_MSC_WARNING_START (4996)
740 static const deletable_facet_<codecvt<
char32_t,
char8_t, mbstate_t>> cvt;
741 mbstate_t ignoredState{};
742 const char32_t* sourceCursor = *sourceStart;
743 char8_t* outCursor = *targetStart;
744 codecvt_base::result rr = cvt.out (ignoredState, *sourceStart, sourceEnd, sourceCursor, *targetStart, targetEnd, outCursor);
745 *sourceStart =
reinterpret_cast<const char32_t*
> (sourceCursor);
746 *targetStart =
reinterpret_cast<char8_t*
> (outCursor);
747 return cvt_stdcodecvt_results_ (rr);
748 DISABLE_COMPILER_MSC_WARNING_END (4996)
759 using ConversionResultWithStatus = Characters::UTFConvert::ConversionResultWithStatus;
762 template <
typename IN_T,
typename OUT_T, regular_invocable<const IN_T**, const IN_T*, OUT_T**, OUT_T*, optional<
char32_t>> FUN2DO_REAL_WORK>
763 inline auto ConvertQuietly_StroikaPortable_helper_ (optional<Character> invalidCharacterReplacement, span<const IN_T> source,
764 span<OUT_T> target, FUN2DO_REAL_WORK&& realWork) -> ConversionResultWithStatus
766 using namespace UTFConvert_libutfxx_;
767 const IN_T* sourceStart = source.data ();
768 const IN_T* sourceEnd = sourceStart + source.size ();
769 OUT_T* targetStart = target.data ();
770 OUT_T* targetEnd = targetStart + target.size ();
773 realWork (&sourceStart, sourceEnd, &targetStart, targetEnd,
774 invalidCharacterReplacement.has_value () ? invalidCharacterReplacement->As<
char32_t> () : optional<char32_t>{});
775 return ConversionResultWithStatus{
776 {
static_cast<size_t> (sourceStart - source.data ()),
static_cast<size_t> (targetStart - target.data ())}, cvt_ (r)};
779auto UTFConvert::ConvertQuietly_StroikaPortable_ (optional<Character> invalidCharacterReplacement, span<const char8_t> source, span<char16_t> target)
780 -> ConversionResultWithStatus
782#if qCompilerAndStdLib_arm_ubsan_callDirectFunInsteadOfThruLamdba_Buggy
783 if (Debug::kBuiltWithUndefinedBehaviorSanitizer) {
784 return ConvertQuietly_StroikaPortable_helper_ (invalidCharacterReplacement, source, target,
785 [] (
const char8_t** sourceStart,
const char8_t* sourceEnd,
char16_t** targetStart,
786 char16_t* targetEnd, optional<char32_t> missingCharacterReplacement) {
787 return UTFConvert_libutfxx_::ConvertUTF8toUTF16_ (
788 sourceStart, sourceEnd, targetStart, targetEnd, missingCharacterReplacement);
792 return ConvertQuietly_StroikaPortable_helper_ (invalidCharacterReplacement, source, target, UTFConvert_libutfxx_::ConvertUTF8toUTF16_);
794auto UTFConvert::ConvertQuietly_StroikaPortable_ (optional<Character> invalidCharacterReplacement, span<const char8_t> source, span<char32_t> target)
795 -> ConversionResultWithStatus
797#if qCompilerAndStdLib_arm_ubsan_callDirectFunInsteadOfThruLamdba_Buggy
798 if (Debug::kBuiltWithUndefinedBehaviorSanitizer) {
799 return ConvertQuietly_StroikaPortable_helper_ (invalidCharacterReplacement, source, target,
800 [] (
const char8_t** sourceStart,
const char8_t* sourceEnd,
char32_t** targetStart,
801 char32_t* targetEnd, optional<char32_t> missingCharacterReplacement) {
802 return UTFConvert_libutfxx_::ConvertUTF8toUTF32_ (
803 sourceStart, sourceEnd, targetStart, targetEnd, missingCharacterReplacement);
807 return ConvertQuietly_StroikaPortable_helper_ (invalidCharacterReplacement, source, target, UTFConvert_libutfxx_::ConvertUTF8toUTF32_);
809auto UTFConvert::ConvertQuietly_StroikaPortable_ (optional<Character> invalidCharacterReplacement, span<const char16_t> source,
810 span<char32_t> target) -> ConversionResultWithStatus
812#if qCompilerAndStdLib_arm_ubsan_callDirectFunInsteadOfThruLamdba_Buggy
813 if (Debug::kBuiltWithUndefinedBehaviorSanitizer) {
814 return ConvertQuietly_StroikaPortable_helper_ (invalidCharacterReplacement, source, target,
815 [] (
const char16_t** sourceStart,
const char16_t* sourceEnd,
char32_t** targetStart,
816 char32_t* targetEnd, optional<char32_t> missingCharacterReplacement) {
817 return UTFConvert_libutfxx_::ConvertUTF16toUTF32_ (
818 sourceStart, sourceEnd, targetStart, targetEnd, missingCharacterReplacement);
822 return ConvertQuietly_StroikaPortable_helper_ (invalidCharacterReplacement, source, target, UTFConvert_libutfxx_::ConvertUTF16toUTF32_);
824auto UTFConvert::ConvertQuietly_StroikaPortable_ (optional<Character> invalidCharacterReplacement, span<const char32_t> source,
825 span<char16_t> target) -> ConversionResultWithStatus
827#if qCompilerAndStdLib_arm_ubsan_callDirectFunInsteadOfThruLamdba_Buggy
828 if (Debug::kBuiltWithUndefinedBehaviorSanitizer) {
829 return ConvertQuietly_StroikaPortable_helper_ (invalidCharacterReplacement, source, target,
830 [] (
const char32_t** sourceStart,
const char32_t* sourceEnd,
char16_t** targetStart,
831 char16_t* targetEnd, optional<char32_t> missingCharacterReplacement) {
832 return UTFConvert_libutfxx_::ConvertUTF32toUTF16_ (
833 sourceStart, sourceEnd, targetStart, targetEnd, missingCharacterReplacement);
837 return ConvertQuietly_StroikaPortable_helper_ (invalidCharacterReplacement, source, target, UTFConvert_libutfxx_::ConvertUTF32toUTF16_);
839auto UTFConvert::ConvertQuietly_StroikaPortable_ (optional<Character> invalidCharacterReplacement, span<const char32_t> source, span<char8_t> target)
840 -> ConversionResultWithStatus
842#if qCompilerAndStdLib_arm_ubsan_callDirectFunInsteadOfThruLamdba_Buggy
843 if (Debug::kBuiltWithUndefinedBehaviorSanitizer) {
844 return ConvertQuietly_StroikaPortable_helper_ (invalidCharacterReplacement, source, target,
845 [] (
const char32_t** sourceStart,
const char32_t* sourceEnd,
char8_t** targetStart,
846 char8_t* targetEnd, optional<char32_t> missingCharacterReplacement) {
847 return UTFConvert_libutfxx_::ConvertUTF32toUTF8_ (
848 sourceStart, sourceEnd, targetStart, targetEnd, missingCharacterReplacement);
852 return ConvertQuietly_StroikaPortable_helper_ (invalidCharacterReplacement, source, target, UTFConvert_libutfxx_::ConvertUTF32toUTF8_);
854auto UTFConvert::ConvertQuietly_StroikaPortable_ (optional<Character> invalidCharacterReplacement, span<const char16_t> source, span<char8_t> target)
855 -> ConversionResultWithStatus
857#if qCompilerAndStdLib_arm_ubsan_callDirectFunInsteadOfThruLamdba_Buggy
858 if (Debug::kBuiltWithUndefinedBehaviorSanitizer) {
859 return ConvertQuietly_StroikaPortable_helper_ (invalidCharacterReplacement, source, target,
860 [] (
const char16_t** sourceStart,
const char16_t* sourceEnd,
char8_t** targetStart,
861 char8_t* targetEnd, optional<char32_t> missingCharacterReplacement) {
862 return UTFConvert_libutfxx_::ConvertUTF16toUTF8_ (
863 sourceStart, sourceEnd, targetStart, targetEnd, missingCharacterReplacement);
867 return ConvertQuietly_StroikaPortable_helper_ (invalidCharacterReplacement, source, target, UTFConvert_libutfxx_::ConvertUTF16toUTF8_);
871 template <
typename IN_T,
typename OUT_T,
typename FUN2DO_REAL_WORK>
872 inline auto ConvertQuietly_codeCvt_helper_ (span<const IN_T> source,
const span<OUT_T> target, FUN2DO_REAL_WORK&& realWork) -> ConversionResultWithStatus
874 using namespace UTFConvert_codecvtSupport_;
875 const IN_T* sourceStart =
reinterpret_cast<const IN_T*
> (source.data ());
876 const IN_T* sourceEnd = sourceStart + source.size ();
877 OUT_T* targetStart =
reinterpret_cast<OUT_T*
> (target.data ());
878 OUT_T* targetEnd = targetStart + target.size ();
879 ConversionStatusFlag r = realWork (&sourceStart, sourceEnd, &targetStart, targetEnd);
880 if (r == ConversionStatusFlag::ok) {
881 return ConversionResultWithStatus{{
static_cast<size_t> (sourceStart -
reinterpret_cast<const IN_T*
> (source.data ())),
882 static_cast<size_t> (targetStart -
reinterpret_cast<const OUT_T*
> (target.data ()))},
883 ConversionStatusFlag::ok};
886 return ConversionResultWithStatus{{0, 0}, r};
890auto UTFConvert::ConvertQuietly_codeCvt_ (span<const char8_t> source, span<char16_t> target) -> ConversionResultWithStatus
892 return ConvertQuietly_codeCvt_helper_ (source, target, UTFConvert_codecvtSupport_::ConvertUTF8toUTF16_codecvt_);
894auto UTFConvert::ConvertQuietly_codeCvt_ (span<const char16_t> source, span<char8_t> target) -> ConversionResultWithStatus
896 return ConvertQuietly_codeCvt_helper_ (source, target, UTFConvert_codecvtSupport_::ConvertUTF16toUTF8_codecvt_);
898auto UTFConvert::ConvertQuietly_codeCvt_ (span<const char8_t> source, span<char32_t> target) -> ConversionResultWithStatus
900 return ConvertQuietly_codeCvt_helper_ (source, target, UTFConvert_codecvtSupport_::ConvertUTF8toUTF32_codecvt_);
902auto UTFConvert::ConvertQuietly_codeCvt_ (span<const char32_t> source, span<char8_t> target) -> ConversionResultWithStatus
904 return ConvertQuietly_codeCvt_helper_ (source, target, UTFConvert_codecvtSupport_::ConvertUTF32toUTF8_codecvt_);
907void UTFConvert::Throw (ConversionStatusFlag cr,
size_t errorAtSourceOffset)
#define AssertNotImplemented()
#define RequireNotReached()
#define AssertNotReached()
An error occurred encoding or decoding a character
constexpr bool IsSurrogatePair() const
constexpr pair< char16_t, char16_t > GetSurrogatePair() const
ConversionStatusFlag
used for ConvertQuietly
void Throw(T &&e2Throw)
identical to builtin C++ 'throw' except that it does helpful, type dependent DbgTrace() messages firs...