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_ {
66 static constexpr char32_t UNI_MAX_BMP = (char32_t)0x0000FFFF;
67 static constexpr char32_t UNI_MAX_UTF16 = (char32_t)0x0010FFFF;
68 static constexpr char32_t UNI_MAX_LEGAL_UTF32 = (char32_t)0x0010FFFF;
70 enum ConversionResult {
81 return UTFConvert::ConversionStatusFlag::ok;
83 return UTFConvert::ConversionStatusFlag::sourceExhausted;
86 return UTFConvert::ConversionStatusFlag::sourceIllegal;
88 return UTFConvert::ConversionStatusFlag::sourceIllegal;
91 return UTFConvert::ConversionStatusFlag::sourceIllegal;
95 constexpr int halfShift = 10;
97 constexpr char32_t halfBase = 0x0010000UL;
98 constexpr char32_t halfMask = 0x3FFUL;
105 constexpr char32_t offsetsFromUTF8[6] = {0x00000000UL, 0x00003080UL, 0x000E2080UL, 0x03C82080UL, 0xFA082080UL, 0x82082080UL};
114 constexpr char8_t firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC};
123 constexpr char trailingBytesForUTF8[256] = {
124 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,
125 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,
126 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,
127 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,
128 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,
129 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};
141 bool isLegalUTF8_ (
const char8_t* source,
int length)
144 const char8_t* srcptr = source + length;
150 if ((a = (*--srcptr)) < 0x80 || a > 0xBF)
153 if ((a = (*--srcptr)) < 0x80 || a > 0xBF)
156 if ((a = (*--srcptr)) > 0xBF)
159 switch ((
unsigned char)*source) {
183 if (*source >= 0x80 && *source < 0xC2)
191 inline ConversionResult ConvertUTF8toUTF16_ (
const char8_t** sourceStart,
const char8_t* sourceEnd,
char16_t** targetStart,
192 char16_t* targetEnd, optional<char32_t> missingCharacterReplacement)
194 ConversionResult result = conversionOK;
195 const char8_t* source = *sourceStart;
196 char16_t* target = *targetStart;
197 auto addMissing = [&] () {
201 *target++ = p.second;
204 *target++ =
static_cast<char16_t> (*missingCharacterReplacement);
207 while (source < sourceEnd) {
209 unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
210 if (source + extraBytesToRead >= sourceEnd) {
211 result = sourceExhausted;
214 if (!isLegalUTF8_ (source, extraBytesToRead + 1)) {
215 if (missingCharacterReplacement) {
219 result = sourceIllegal;
226 switch (extraBytesToRead) {
245 ch -= offsetsFromUTF8[extraBytesToRead];
247 if (target >= targetEnd) [[unlikely]] {
248 source -= (extraBytesToRead + 1);
249 result = targetExhausted;
252 if (ch <= UNI_MAX_BMP) {
254 if (ch >= Character::kUNICODESurrogate_High_Start && ch <= Character::kUNICODESurrogate_Low_End) {
255 if (missingCharacterReplacement) {
259 source -= (extraBytesToRead + 1);
260 result = sourceIllegal;
265 *target++ = (char16_t)ch;
268 else if (ch > UNI_MAX_UTF16) {
269 if (missingCharacterReplacement) {
273 result = sourceIllegal;
274 source -= (extraBytesToRead + 1);
280 if (target + 1 >= targetEnd) {
281 source -= (extraBytesToRead + 1);
282 result = targetExhausted;
286 *target++ = (char16_t)((ch >> halfShift) + Character::kUNICODESurrogate_High_Start);
287 *target++ = (char16_t)((ch & halfMask) + Character::kUNICODESurrogate_Low_Start);
290 *sourceStart = source;
291 *targetStart = target;
294 inline ConversionResult ConvertUTF16toUTF8_ (
const char16_t** sourceStart,
const char16_t* sourceEnd,
char8_t** targetStart,
295 char8_t* targetEnd, optional<char32_t> missingCharacterReplacement)
297 ConversionResult result = conversionOK;
298 const char16_t* source = *sourceStart;
299 char8_t* target = *targetStart;
300 while (source < sourceEnd) {
302 unsigned short bytesToWrite = 0;
303 constexpr char32_t byteMask = 0xBF;
304 constexpr char32_t byteMark = 0x80;
305 const char16_t* oldSource = source;
308 if (ch >= Character::kUNICODESurrogate_High_Start && ch <= Character::kUNICODESurrogate_High_End) [[unlikely]] {
310 if (source < sourceEnd) [[likely]] {
311 char32_t ch2 = *source;
313 if (ch2 >= Character::kUNICODESurrogate_Low_Start && ch2 <= Character::kUNICODESurrogate_Low_End) {
314 ch = ((ch - Character::kUNICODESurrogate_High_Start) << halfShift) + (ch2 - Character::kUNICODESurrogate_Low_Start) + halfBase;
317 else if (missingCharacterReplacement == nullopt) {
319 result = sourceIllegal;
325 result = sourceExhausted;
329 else if (missingCharacterReplacement == nullopt) {
331 if (ch >= Character::kUNICODESurrogate_Low_Start && ch <= Character::kUNICODESurrogate_Low_End) {
333 result = sourceIllegal;
338 if (ch < (
char32_t)0x80) {
341 else if (ch < (
char32_t)0x800) {
344 else if (ch < (
char32_t)0x10000) {
347 else if (ch < (
char32_t)0x110000) {
352 Assert (missingCharacterReplacement.has_value ());
353 ch = *missingCharacterReplacement;
356 target += bytesToWrite;
357 if (target > targetEnd) {
359 target -= bytesToWrite;
360 result = targetExhausted;
363 switch (bytesToWrite) {
365 *--target = (char8_t)((ch | byteMark) & byteMask);
368 *--target = (char8_t)((ch | byteMark) & byteMask);
371 *--target = (char8_t)((ch | byteMark) & byteMask);
374 *--target = (char8_t)(ch | firstByteMark[bytesToWrite]);
376 target += bytesToWrite;
378 *sourceStart = source;
379 *targetStart = target;
382 DISABLE_COMPILER_MSC_WARNING_START (4701)
383 DISABLE_COMPILER_GCC_WARNING_START ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"");
384 inline ConversionResult ConvertUTF16toUTF32_ (const
char16_t** sourceStart, const
char16_t* sourceEnd,
char32_t** targetStart,
385 char32_t* targetEnd, optional<
char32_t> missingCharacterReplacement)
387 ConversionResult result = conversionOK;
388 const char16_t* source = *sourceStart;
389 char32_t* target = *targetStart;
391 while (source < sourceEnd) {
392 const char16_t* oldSource = source;
395 if (ch >= Character::kUNICODESurrogate_High_Start && ch <= Character::kUNICODESurrogate_High_End) [[unlikely]] {
397 if (source < sourceEnd) {
400 if (ch2 >= Character::kUNICODESurrogate_Low_Start && ch2 <= Character::kUNICODESurrogate_Low_End) {
401 ch = ((ch - Character::kUNICODESurrogate_High_Start) << halfShift) + (ch2 - Character::kUNICODESurrogate_Low_Start) + halfBase;
404 else if (missingCharacterReplacement == nullopt) {
406 result = sourceIllegal;
412 result = sourceExhausted;
416 else if (missingCharacterReplacement == nullopt) {
418 if (ch >= Character::kUNICODESurrogate_Low_Start && ch <= Character::kUNICODESurrogate_Low_End) {
420 result = sourceIllegal;
424 if (target >= targetEnd) {
426 result = targetExhausted;
431 *sourceStart = source;
432 *targetStart = target;
433 if (result == sourceIllegal) {
434 using namespace Characters::Literals;
435 DbgTrace (
"ConvertUTF16toUTF32 illegal seq 0x{:x},0x{:x}"_f,
static_cast<int> (ch),
static_cast<int> (ch2));
439 DISABLE_COMPILER_MSC_WARNING_END (4701)
440 DISABLE_COMPILER_GCC_WARNING_END ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"");
441 inline ConversionResult ConvertUTF32toUTF16_ (const
char32_t** sourceStart, const
char32_t* sourceEnd,
char16_t** targetStart,
442 char16_t* targetEnd, optional<
char32_t> missingCharacterReplacement)
444 ConversionResult result = conversionOK;
445 const char32_t* source = *sourceStart;
446 char16_t* target = *targetStart;
447 auto addMissing = [&] () {
451 *target++ = p.second;
454 *target++ =
static_cast<char16_t> (*missingCharacterReplacement);
457 while (source < sourceEnd) {
459 if (target >= targetEnd) {
460 result = targetExhausted;
464 if (ch <= UNI_MAX_BMP) [[likely]] {
466 if (ch >= Character::kUNICODESurrogate_High_Start && ch <= Character::kUNICODESurrogate_Low_End) [[unlikely]] {
467 if (missingCharacterReplacement == nullopt) {
469 result = sourceIllegal;
477 *target++ = (char16_t)ch;
480 else if (ch > UNI_MAX_LEGAL_UTF32) {
481 if (missingCharacterReplacement) {
485 result = sourceIllegal;
490 if (target + 1 >= targetEnd) {
492 result = targetExhausted;
496 *target++ = (char16_t)((ch >> halfShift) + Character::kUNICODESurrogate_High_Start);
497 *target++ = (char16_t)((ch & halfMask) + Character::kUNICODESurrogate_Low_Start);
500 *sourceStart = source;
501 *targetStart = target;
504 inline ConversionResult ConvertUTF8toUTF32_ (
const char8_t** sourceStart,
const char8_t* sourceEnd,
char32_t** targetStart,
505 char32_t* targetEnd, optional<char32_t> missingCharacterReplacement)
507 ConversionResult result = conversionOK;
508 const char8_t* source = *sourceStart;
509 char32_t* target = *targetStart;
510 while (source < sourceEnd) {
512 unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
513 if (source + extraBytesToRead >= sourceEnd) [[unlikely]] {
514 result = sourceExhausted;
517 if (!isLegalUTF8_ (source, extraBytesToRead + 1)) {
518 if (missingCharacterReplacement) {
522 result = sourceIllegal;
529 switch (extraBytesToRead) {
548 ch -= offsetsFromUTF8[extraBytesToRead];
550 if (target >= targetEnd) [[unlikely]] {
551 source -= (extraBytesToRead + 1);
552 result = targetExhausted;
555 if (ch <= UNI_MAX_LEGAL_UTF32) [[likely]] {
560 if (ch >= Character::kUNICODESurrogate_High_Start && ch <= Character::kUNICODESurrogate_Low_End) {
561 if (missingCharacterReplacement) {
562 *target++ = *missingCharacterReplacement;
565 source -= (extraBytesToRead + 1);
566 result = sourceIllegal;
575 if (missingCharacterReplacement) {
576 *target++ = *missingCharacterReplacement;
579 result = sourceIllegal;
584 *sourceStart = source;
585 *targetStart = target;
588 inline ConversionResult ConvertUTF32toUTF8_ (
const char32_t** sourceStart,
const char32_t* sourceEnd,
char8_t** targetStart,
589 char8_t* targetEnd, optional<char32_t> missingCharacterReplacement)
591 ConversionResult result = conversionOK;
592 const char32_t* source = *sourceStart;
593 char8_t* target = *targetStart;
594 while (source < sourceEnd) {
596 unsigned short bytesToWrite = 0;
597 const char32_t byteMask = 0xBF;
598 const char32_t byteMark = 0x80;
600 if (missingCharacterReplacement == nullopt) {
602 if (ch >= Character::kUNICODESurrogate_High_Start && ch <= Character::kUNICODESurrogate_Low_End) [[unlikely]] {
604 result = sourceIllegal;
612 if (ch < (
char32_t)0x80) {
615 else if (ch < (
char32_t)0x800) {
618 else if (ch < (
char32_t)0x10000) {
621 else if (ch <= UNI_MAX_LEGAL_UTF32) {
625 if (missingCharacterReplacement) {
626 ch = *missingCharacterReplacement;
630 result = sourceIllegal;
635 target += bytesToWrite;
636 if (target > targetEnd) {
638 target -= bytesToWrite;
639 result = targetExhausted;
642 switch (bytesToWrite) {
644 *--target = (char8_t)((ch | byteMark) & byteMask);
647 *--target = (char8_t)((ch | byteMark) & byteMask);
650 *--target = (char8_t)((ch | byteMark) & byteMask);
653 *--target = (char8_t)(ch | firstByteMark[bytesToWrite]);
655 target += bytesToWrite;
657 *sourceStart = source;
658 *targetStart = target;
666 namespace UTFConvert_codecvtSupport_ {
670 case codecvt_base::ok:
671 return UTFConvert::ConversionStatusFlag::ok;
672 case codecvt_base::error:
673 return UTFConvert::ConversionStatusFlag::sourceIllegal;
674 case codecvt_base::partial:
675 return UTFConvert::ConversionStatusFlag::sourceExhausted;
676 case codecvt_base::noconv:
677 return UTFConvert::ConversionStatusFlag::sourceIllegal;
680 return UTFConvert::ConversionStatusFlag::sourceIllegal;
684 char16_t** targetStart,
char16_t* targetEnd)
686 DISABLE_COMPILER_MSC_WARNING_START (4996)
687 static const deletable_facet_<codecvt<
char16_t,
char8_t, mbstate_t>> cvt;
688 mbstate_t ignoredMBState{};
689 const char8_t* sourceCursor = *sourceStart;
690 char16_t* outCursor = *targetStart;
691 codecvt_base::result rr = cvt.in (ignoredMBState, *sourceStart, sourceEnd, sourceCursor, *targetStart, targetEnd, outCursor);
692 *sourceStart =
reinterpret_cast<const char8_t*
> (sourceCursor);
693 *targetStart = outCursor;
694 return cvt_stdcodecvt_results_ (rr);
695 DISABLE_COMPILER_MSC_WARNING_END (4996)
698 char8_t** targetStart,
char8_t* targetEnd)
700 DISABLE_COMPILER_MSC_WARNING_START (4996)
701 static const deletable_facet_<codecvt<
char16_t,
char8_t, mbstate_t>> cvt;
702 mbstate_t ignoredMBState{};
703 const char16_t* sourceCursor = *sourceStart;
704 char8_t* outCursor = *targetStart;
705 codecvt_base::result rr = cvt.out (ignoredMBState, *sourceStart, sourceEnd, sourceCursor, *targetStart, targetEnd, outCursor);
706 *sourceStart =
reinterpret_cast<const char16_t*
> (sourceCursor);
707 *targetStart =
reinterpret_cast<char8_t*
> (outCursor);
708 return cvt_stdcodecvt_results_ (rr);
709 DISABLE_COMPILER_MSC_WARNING_END (4996)
712 char32_t** targetStart,
char32_t* targetEnd)
714 DISABLE_COMPILER_MSC_WARNING_START (4996)
715 static const deletable_facet_<codecvt<
char32_t,
char8_t, mbstate_t>> cvt;
716 mbstate_t ignoredState{};
718 const char8_t* sourceCursor = *sourceStart;
719 char32_t* outCursor = *targetStart;
720 codecvt_base::result rr = cvt.in (ignoredState, *sourceStart, sourceEnd, sourceCursor, *targetStart, targetEnd, outCursor);
721 *sourceStart =
reinterpret_cast<const char8_t*
> (sourceCursor);
722 *targetStart = outCursor;
723 return cvt_stdcodecvt_results_ (rr);
724 DISABLE_COMPILER_MSC_WARNING_END (4996)
727 char8_t** targetStart,
char8_t* targetEnd)
729 DISABLE_COMPILER_MSC_WARNING_START (4996)
730 static const deletable_facet_<codecvt<
char32_t,
char8_t, mbstate_t>> cvt;
731 mbstate_t ignoredState{};
732 const char32_t* sourceCursor = *sourceStart;
733 char8_t* outCursor = *targetStart;
734 codecvt_base::result rr = cvt.out (ignoredState, *sourceStart, sourceEnd, sourceCursor, *targetStart, targetEnd, outCursor);
735 *sourceStart =
reinterpret_cast<const char32_t*
> (sourceCursor);
736 *targetStart =
reinterpret_cast<char8_t*
> (outCursor);
737 return cvt_stdcodecvt_results_ (rr);
738 DISABLE_COMPILER_MSC_WARNING_END (4996)
749 using ConversionResultWithStatus = Characters::UTFConvert::ConversionResultWithStatus;
752 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>
753 inline auto ConvertQuietly_StroikaPortable_helper_ (optional<Character> invalidCharacterReplacement, span<const IN_T> source,
754 span<OUT_T> target, FUN2DO_REAL_WORK&& realWork) -> ConversionResultWithStatus
756 using namespace UTFConvert_libutfxx_;
757 const IN_T* sourceStart = source.data ();
758 const IN_T* sourceEnd = sourceStart + source.size ();
759 OUT_T* targetStart = target.data ();
760 OUT_T* targetEnd = targetStart + target.size ();
763 realWork (&sourceStart, sourceEnd, &targetStart, targetEnd,
764 invalidCharacterReplacement.has_value () ? invalidCharacterReplacement->As<
char32_t> () : optional<char32_t>{});
765 return ConversionResultWithStatus{
766 {
static_cast<size_t> (sourceStart - source.data ()),
static_cast<size_t> (targetStart - target.data ())}, cvt_ (r)};
769auto UTFConvert::ConvertQuietly_StroikaPortable_ (optional<Character> invalidCharacterReplacement, span<const char8_t> source, span<char16_t> target)
770 -> ConversionResultWithStatus
772#if qCompilerAndStdLib_arm_ubsan_callDirectFunInsteadOfThruLamdba_Buggy
773 if (Debug::kBuiltWithUndefinedBehaviorSanitizer) {
774 return ConvertQuietly_StroikaPortable_helper_ (invalidCharacterReplacement, source, target,
775 [] (
const char8_t** sourceStart,
const char8_t* sourceEnd,
char16_t** targetStart,
776 char16_t* targetEnd, optional<char32_t> missingCharacterReplacement) {
777 return UTFConvert_libutfxx_::ConvertUTF8toUTF16_ (
778 sourceStart, sourceEnd, targetStart, targetEnd, missingCharacterReplacement);
782 return ConvertQuietly_StroikaPortable_helper_ (invalidCharacterReplacement, source, target, UTFConvert_libutfxx_::ConvertUTF8toUTF16_);
784auto UTFConvert::ConvertQuietly_StroikaPortable_ (optional<Character> invalidCharacterReplacement, span<const char8_t> source, span<char32_t> target)
785 -> ConversionResultWithStatus
787#if qCompilerAndStdLib_arm_ubsan_callDirectFunInsteadOfThruLamdba_Buggy
788 if (Debug::kBuiltWithUndefinedBehaviorSanitizer) {
789 return ConvertQuietly_StroikaPortable_helper_ (invalidCharacterReplacement, source, target,
790 [] (
const char8_t** sourceStart,
const char8_t* sourceEnd,
char32_t** targetStart,
791 char32_t* targetEnd, optional<char32_t> missingCharacterReplacement) {
792 return UTFConvert_libutfxx_::ConvertUTF8toUTF32_ (
793 sourceStart, sourceEnd, targetStart, targetEnd, missingCharacterReplacement);
797 return ConvertQuietly_StroikaPortable_helper_ (invalidCharacterReplacement, source, target, UTFConvert_libutfxx_::ConvertUTF8toUTF32_);
799auto UTFConvert::ConvertQuietly_StroikaPortable_ (optional<Character> invalidCharacterReplacement, span<const char16_t> source,
800 span<char32_t> target) -> ConversionResultWithStatus
802#if qCompilerAndStdLib_arm_ubsan_callDirectFunInsteadOfThruLamdba_Buggy
803 if (Debug::kBuiltWithUndefinedBehaviorSanitizer) {
804 return ConvertQuietly_StroikaPortable_helper_ (invalidCharacterReplacement, source, target,
805 [] (
const char16_t** sourceStart,
const char16_t* sourceEnd,
char32_t** targetStart,
806 char32_t* targetEnd, optional<char32_t> missingCharacterReplacement) {
807 return UTFConvert_libutfxx_::ConvertUTF16toUTF32_ (
808 sourceStart, sourceEnd, targetStart, targetEnd, missingCharacterReplacement);
812 return ConvertQuietly_StroikaPortable_helper_ (invalidCharacterReplacement, source, target, UTFConvert_libutfxx_::ConvertUTF16toUTF32_);
814auto UTFConvert::ConvertQuietly_StroikaPortable_ (optional<Character> invalidCharacterReplacement, span<const char32_t> source,
815 span<char16_t> target) -> ConversionResultWithStatus
817#if qCompilerAndStdLib_arm_ubsan_callDirectFunInsteadOfThruLamdba_Buggy
818 if (Debug::kBuiltWithUndefinedBehaviorSanitizer) {
819 return ConvertQuietly_StroikaPortable_helper_ (invalidCharacterReplacement, source, target,
820 [] (
const char32_t** sourceStart,
const char32_t* sourceEnd,
char16_t** targetStart,
821 char16_t* targetEnd, optional<char32_t> missingCharacterReplacement) {
822 return UTFConvert_libutfxx_::ConvertUTF32toUTF16_ (
823 sourceStart, sourceEnd, targetStart, targetEnd, missingCharacterReplacement);
827 return ConvertQuietly_StroikaPortable_helper_ (invalidCharacterReplacement, source, target, UTFConvert_libutfxx_::ConvertUTF32toUTF16_);
829auto UTFConvert::ConvertQuietly_StroikaPortable_ (optional<Character> invalidCharacterReplacement, span<const char32_t> source, span<char8_t> target)
830 -> ConversionResultWithStatus
832#if qCompilerAndStdLib_arm_ubsan_callDirectFunInsteadOfThruLamdba_Buggy
833 if (Debug::kBuiltWithUndefinedBehaviorSanitizer) {
834 return ConvertQuietly_StroikaPortable_helper_ (invalidCharacterReplacement, source, target,
835 [] (
const char32_t** sourceStart,
const char32_t* sourceEnd,
char8_t** targetStart,
836 char8_t* targetEnd, optional<char32_t> missingCharacterReplacement) {
837 return UTFConvert_libutfxx_::ConvertUTF32toUTF8_ (
838 sourceStart, sourceEnd, targetStart, targetEnd, missingCharacterReplacement);
842 return ConvertQuietly_StroikaPortable_helper_ (invalidCharacterReplacement, source, target, UTFConvert_libutfxx_::ConvertUTF32toUTF8_);
844auto UTFConvert::ConvertQuietly_StroikaPortable_ (optional<Character> invalidCharacterReplacement, span<const char16_t> source, span<char8_t> target)
845 -> ConversionResultWithStatus
847#if qCompilerAndStdLib_arm_ubsan_callDirectFunInsteadOfThruLamdba_Buggy
848 if (Debug::kBuiltWithUndefinedBehaviorSanitizer) {
849 return ConvertQuietly_StroikaPortable_helper_ (invalidCharacterReplacement, source, target,
850 [] (
const char16_t** sourceStart,
const char16_t* sourceEnd,
char8_t** targetStart,
851 char8_t* targetEnd, optional<char32_t> missingCharacterReplacement) {
852 return UTFConvert_libutfxx_::ConvertUTF16toUTF8_ (
853 sourceStart, sourceEnd, targetStart, targetEnd, missingCharacterReplacement);
857 return ConvertQuietly_StroikaPortable_helper_ (invalidCharacterReplacement, source, target, UTFConvert_libutfxx_::ConvertUTF16toUTF8_);
861 template <
typename IN_T,
typename OUT_T,
typename FUN2DO_REAL_WORK>
862 inline auto ConvertQuietly_codeCvt_helper_ (span<const IN_T> source,
const span<OUT_T> target, FUN2DO_REAL_WORK&& realWork) -> ConversionResultWithStatus
864 using namespace UTFConvert_codecvtSupport_;
865 const IN_T* sourceStart =
reinterpret_cast<const IN_T*
> (source.data ());
866 const IN_T* sourceEnd = sourceStart + source.size ();
867 OUT_T* targetStart =
reinterpret_cast<OUT_T*
> (target.data ());
868 OUT_T* targetEnd = targetStart + target.size ();
869 ConversionStatusFlag r = realWork (&sourceStart, sourceEnd, &targetStart, targetEnd);
870 if (r == ConversionStatusFlag::ok) {
871 return ConversionResultWithStatus{{
static_cast<size_t> (sourceStart -
reinterpret_cast<const IN_T*
> (source.data ())),
872 static_cast<size_t> (targetStart -
reinterpret_cast<const OUT_T*
> (target.data ()))},
873 ConversionStatusFlag::ok};
876 return ConversionResultWithStatus{{0, 0}, r};
880auto UTFConvert::ConvertQuietly_codeCvt_ (span<const char8_t> source, span<char16_t> target) -> ConversionResultWithStatus
882 return ConvertQuietly_codeCvt_helper_ (source, target, UTFConvert_codecvtSupport_::ConvertUTF8toUTF16_codecvt_);
884auto UTFConvert::ConvertQuietly_codeCvt_ (span<const char16_t> source, span<char8_t> target) -> ConversionResultWithStatus
886 return ConvertQuietly_codeCvt_helper_ (source, target, UTFConvert_codecvtSupport_::ConvertUTF16toUTF8_codecvt_);
888auto UTFConvert::ConvertQuietly_codeCvt_ (span<const char8_t> source, span<char32_t> target) -> ConversionResultWithStatus
890 return ConvertQuietly_codeCvt_helper_ (source, target, UTFConvert_codecvtSupport_::ConvertUTF8toUTF32_codecvt_);
892auto UTFConvert::ConvertQuietly_codeCvt_ (span<const char32_t> source, span<char8_t> target) -> ConversionResultWithStatus
894 return ConvertQuietly_codeCvt_helper_ (source, target, UTFConvert_codecvtSupport_::ConvertUTF32toUTF8_codecvt_);
897void 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...