7#if QT_CONFIG(regularexpression)
11#include <private/qstringconverter_p.h>
12#include <private/qtools_p.h>
14#include "private/qsimd_p.h"
30#include <private/qcore_mac_p.h>
33#include <private/qfunctions_p.h>
54# if !defined(QT_BOOTSTRAPPED) && (defined(QT_NO_CAST_FROM_ASCII) || defined(QT_NO_CAST_TO_ASCII))
56# error "This file cannot be compiled with QT_NO_CAST_{TO,FROM}_ASCII, " \
57 "otherwise some QString functions will not get exported."
66 if (sl_minus_1 < sizeof(std::size_t) * CHAR_BIT) \
67 hashHaystack -= std::size_t(a) << sl_minus_1; \
75const char16_t QString::_empty = 0;
81enum StringComparisonMode {
82 CompareStringsForEquality,
83 CompareStringsForOrdering
86template <
typename Po
inter>
87char32_t foldCaseHelper(Pointer
ch, Pointer
start) =
delete;
92 return foldCase(
reinterpret_cast<const char16_t*
>(
ch),
93 reinterpret_cast<const char16_t*
>(
start));
97char32_t foldCaseHelper<const char*>(
const char*
ch,
const char*)
103char16_t valueTypeToUtf16(T
t) =
delete;
106char16_t valueTypeToUtf16<QChar>(
QChar t)
112char16_t valueTypeToUtf16<char>(
char t)
114 return char16_t{
uchar(
t)};
118static inline bool foldAndCompare(
const T
a,
const T
b)
131template <
typename Haystack>
132static inline qsizetype qLastIndexOf(Haystack haystack,
QChar needle,
135 if (haystack.size() == 0)
138 from += haystack.size();
139 else if (std::size_t(from) > std::size_t(haystack.size()))
140 from = haystack.size() - 1;
142 char16_t c = needle.unicode();
143 const auto b = haystack.data();
147 if (valueTypeToUtf16(*
n) ==
c)
161template<
typename Haystack,
typename Needle>
167 return qLastIndexOf(haystack0, needle0.front(), from, cs);
172 if (from == l && sl == 0)
175 if (std::size_t(from) > std::size_t(l) || delta < 0)
180 auto sv = [sl](
const typename Haystack::value_type *
v) {
return Haystack(
v, sl); };
182 auto haystack = haystack0.data();
183 const auto needle = needle0.data();
184 const auto *
end = haystack;
186 const std::size_t sl_minus_1 = sl ? sl - 1 : 0;
187 const auto *
n = needle + sl_minus_1;
188 const auto *
h = haystack + sl_minus_1;
189 std::size_t hashNeedle = 0, hashHaystack = 0;
192 for (
qsizetype idx = 0; idx < sl; ++idx) {
193 hashNeedle = (hashNeedle << 1) + valueTypeToUtf16(*(
n - idx));
194 hashHaystack = (hashHaystack << 1) + valueTypeToUtf16(*(
h - idx));
196 hashHaystack -= valueTypeToUtf16(*haystack);
198 while (haystack >=
end) {
199 hashHaystack += valueTypeToUtf16(*haystack);
200 if (hashHaystack == hashNeedle
202 return haystack -
end;
204 REHASH(valueTypeToUtf16(haystack[sl]));
207 for (
qsizetype idx = 0; idx < sl; ++idx) {
208 hashNeedle = (hashNeedle << 1) + foldCaseHelper(
n - idx, needle);
209 hashHaystack = (hashHaystack << 1) + foldCaseHelper(
h - idx,
end);
211 hashHaystack -= foldCaseHelper(haystack,
end);
213 while (haystack >=
end) {
214 hashHaystack += foldCaseHelper(haystack,
end);
215 if (hashHaystack == hashNeedle
217 return haystack -
end;
219 REHASH(foldCaseHelper(haystack + sl,
end));
225template <
typename Haystack,
typename Needle>
228 if (haystack.isNull())
229 return needle.isNull();
230 const auto haystackLen = haystack.size();
231 const auto needleLen = needle.size();
232 if (haystackLen == 0)
233 return needleLen == 0;
234 if (needleLen > haystackLen)
240template <
typename Haystack,
typename Needle>
243 if (haystack.isNull())
244 return needle.isNull();
245 const auto haystackLen = haystack.size();
246 const auto needleLen = needle.size();
247 if (haystackLen == 0)
248 return needleLen == 0;
249 if (haystackLen < needleLen)
258 const auto strData =
view.data();
261 if (strData && strSize > 0) {
268 auto dst = std::next(
d.data(),
d.size);
269 if constexpr (std::is_same_v<T, QUtf8StringView>) {
271 }
else if constexpr (std::is_same_v<T, QLatin1StringView>) {
276 "Can only operate on UTF-8 and Latin-1");
279 }
else if (
d.isNull() && !
view.isNull()) {
284template <u
int MaxCount>
struct UnrollTailLoop
286 template <
typename RetType,
typename Functor1,
typename Functor2,
typename Number>
287 static inline RetType
exec(Number
count, RetType returnIfExited, Functor1 loopCheck, Functor2 returnIfFailed, Number
i = 0)
298 return returnIfExited;
300 bool check = loopCheck(
i);
302 return returnIfFailed(
i);
304 return UnrollTailLoop<MaxCount - 1>::exec(
count - 1, returnIfExited, loopCheck, returnIfFailed,
i + 1);
307 template <
typename Functor,
typename Number>
314 exec(
count, 0, [=](Number
i) ->
bool {
code(
i);
return false; }, [](Number) {
return 0; });
317template <>
template <
typename RetType,
typename Functor1,
typename Functor2,
typename Number>
318inline RetType UnrollTailLoop<0>::exec(Number, RetType returnIfExited, Functor1, Functor2, Number)
320 return returnIfExited;
354#if defined(__mips_dsp)
356extern "C" void qt_fromlatin1_mips_asm_unroll4 (
char16_t*,
const char*,
uint);
357extern "C" void qt_fromlatin1_mips_asm_unroll8 (
char16_t*,
const char*,
uint);
358extern "C" void qt_toLatin1_mips_dsp_asm(
uchar *
dst,
const char16_t *
src,
int length);
361#if defined(__SSE2__) && defined(Q_CC_GNU)
364# define ATTRIBUTE_NO_SANITIZE __attribute__((__no_sanitize_address__))
366# define ATTRIBUTE_NO_SANITIZE
371static constexpr bool UseAvx2 = UseSse4_1 &&
377 const __m128i *dataptr =
static_cast<const __m128i *
>(
ptr);
378 if constexpr (UseSse4_1) {
381 __m128i
data = _mm_loadl_epi64(dataptr);
382 return _mm_cvtepu8_epi16(
data);
386 __m128i
data = _mm_loadl_epi64(dataptr);
387 return _mm_unpacklo_epi8(
data, _mm_setzero_si128());
391static qsizetype qustrlen_sse2(
const char16_t *
str)
noexcept
396 const char16_t *
ptr =
str - (misalignment / 2);
400 const __m128i zeroes = _mm_setzero_si128();
401 __m128i
data = _mm_load_si128(
reinterpret_cast<const __m128i *
>(
ptr));
402 __m128i comparison = _mm_cmpeq_epi16(
data, zeroes);
403 uint mask = _mm_movemask_epi8(comparison);
406 mask >>= misalignment;
413 constexpr qsizetype Step =
sizeof(__m128i) /
sizeof(
char16_t);
419 data = _mm_load_si128(
reinterpret_cast<const __m128i *
>(
str +
size));
421 comparison = _mm_cmpeq_epi16(
data, zeroes);
422 mask = _mm_movemask_epi8(comparison);
433static bool simdTestMask(
const char *&
ptr,
const char *
end,
quint32 maskval)
442 if constexpr (UseSse4_1) {
445 auto updatePtrSimd = [&](__m128i
data) ->
bool {
446 __m128i masked = _mm_and_si128(
mask,
data);
447 __m128i comparison = _mm_cmpeq_epi16(masked, _mm_setzero_si128());
452 if constexpr (UseAvx2) {
454 const __m256i mask256 = _mm256_broadcastd_epi32(_mm_cvtsi32_si128(maskval));
456 __m256i
data = _mm256_loadu_si256(
reinterpret_cast<const __m256i *
>(
ptr));
457 if (!_mm256_testz_si256(mask256,
data)) {
459 __m256i masked256 = _mm256_and_si256(mask256,
data);
460 __m256i comparison256 = _mm256_cmpeq_epi16(masked256, _mm256_setzero_si256());
461 return updatePtr(_mm256_movemask_epi8(comparison256));
466 mask = _mm256_castsi256_si128(mask256);
470 mask = _mm_set1_epi32(maskval);
472 __m128i data1 = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(
ptr));
473 __m128i data2 = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(
ptr + 16));
474 if (!_mm_testz_si128(
mask, data1))
475 return updatePtrSimd(data1);
478 if (!_mm_testz_si128(
mask, data2))
479 return updatePtrSimd(data2);
486 __m128i data1 = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(
ptr));
487 if (!_mm_testz_si128(
mask, data1))
488 return updatePtrSimd(data1);
494 __m128i data1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(
ptr));
495 if (!_mm_testz_si128(
mask, data1))
496 return updatePtrSimd(data1);
505 const __m128i
mask = _mm_set1_epi32(maskval);
507 __m128i
data = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(
ptr));
508 __m128i masked = _mm_and_si128(
mask,
data);
509 __m128i comparison = _mm_cmpeq_epi16(masked, _mm_setzero_si128());
518 __m128i
data = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(
ptr));
519 __m128i masked = _mm_and_si128(
mask,
data);
520 __m128i comparison = _mm_cmpeq_epi16(masked, _mm_setzero_si128());
530template <StringComparisonMode Mode,
typename Char> [[maybe_unused]]
531static int ucstrncmp_sse2(
const char16_t *
a,
const Char *
b,
size_t l)
533 static_assert(std::is_unsigned_v<Char>);
537 static const auto codeUnitAt = [](
const auto *
n,
qptrdiff idx) ->
int {
538 constexpr int Stride = 2;
545 auto ptr =
reinterpret_cast<const uchar *
>(
n);
546 ptr += idx / (Stride /
sizeof(*n));
547 return *
reinterpret_cast<decltype(
n)
>(
ptr);
550 if (
Mode == CompareStringsForEquality)
556 static const auto load8Chars = [](
const auto *
ptr) {
557 if (
sizeof(*
ptr) == 2)
558 return _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(
ptr));
559 __m128i chunk = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(
ptr));
560 return _mm_unpacklo_epi8(chunk, _mm_setzero_si128());
562 static const auto load4Chars = [](
const auto *
ptr) {
563 if (
sizeof(*
ptr) == 2)
564 return _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(
ptr));
565 __m128i chunk = _mm_cvtsi32_si128(qFromUnaligned<quint32>(
ptr));
566 return _mm_unpacklo_epi8(chunk, _mm_setzero_si128());
571 if constexpr (UseAvx2) {
572 __m256i a_data = _mm256_loadu_si256(
reinterpret_cast<const __m256i *
>(
a +
offset));
574 if (
sizeof(
Char) == 1) {
576 __m128i chunk = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(
b +
offset));
577 b_data = _mm256_cvtepu8_epi16(chunk);
579 b_data = _mm256_loadu_si256(
reinterpret_cast<const __m256i *
>(
b +
offset));
581 __m256i
result = _mm256_cmpeq_epi16(a_data, b_data);
582 return _mm256_movemask_epi8(
result);
585 __m128i a_data1 = load8Chars(
a +
offset);
586 __m128i a_data2 = load8Chars(
a +
offset + 8);
587 __m128i b_data1, b_data2;
588 if (
sizeof(
Char) == 1) {
590 __m128i b_data = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(
b +
offset));
591 b_data1 = _mm_unpacklo_epi8(b_data, _mm_setzero_si128());
592 b_data2 = _mm_unpackhi_epi8(b_data, _mm_setzero_si128());
594 b_data1 = load8Chars(
b +
offset);
595 b_data2 = load8Chars(
b +
offset + 8);
597 __m128i result1 = _mm_cmpeq_epi16(a_data1, b_data1);
598 __m128i result2 = _mm_cmpeq_epi16(a_data2, b_data2);
599 return _mm_movemask_epi8(result1) | _mm_movemask_epi8(result2) << 16;
602 if (l >=
sizeof(__m256i) /
sizeof(
char16_t)) {
604 for ( ; l >=
offset +
sizeof(__m256i) /
sizeof(
char16_t);
offset +=
sizeof(__m256i) /
sizeof(
char16_t)) {
612 offset = l -
sizeof(__m256i) /
sizeof(
char16_t);
617 __m128i a_data1, b_data1;
618 __m128i a_data2, b_data2;
622 a_data1 = load8Chars(
a);
623 b_data1 = load8Chars(
b);
624 a_data2 = load8Chars(
a + l -
width);
625 b_data2 = load8Chars(
b + l -
width);
629 a_data1 = load4Chars(
a);
630 b_data1 = load4Chars(
b);
631 a_data2 = load4Chars(
a + l -
width);
632 b_data2 = load4Chars(
b + l -
width);
635 __m128i
result = _mm_cmpeq_epi16(a_data1, b_data1);
638 return difference(
mask, 0);
640 result = _mm_cmpeq_epi16(a_data2, b_data2);
648 const auto lambda = [=](
size_t i) ->
int {
651 return UnrollTailLoop<3>::exec(l, 0, lambda, lambda);
660#if defined(__SSE2__) && !(defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer))
661 return qustrlen_sse2(
str);
664 if (
sizeof(
wchar_t) ==
sizeof(
char16_t))
665 return wcslen(
reinterpret_cast<const wchar_t *
>(
str));
697 if constexpr (UseAvx2) {
699 __m256i mch256 = _mm256_set1_epi32(
c | (
c << 16));
701 __m256i
data = _mm256_loadu_si256(
reinterpret_cast<const __m256i *
>(
n));
702 __m256i
result = _mm256_cmpeq_epi16(
data, mch256);
710 mch = _mm256_castsi256_si128(mch256);
712 mch = _mm_set1_epi32(
c | (
c << 16));
715 auto hasMatch = [mch, &
n](__m128i
data,
ushort validityMask) {
718 if ((
mask & validityMask) == 0)
727 __m128i
data = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(
n));
728 if (hasMatch(
data, 0xffff))
737# if !defined(__OPTIMIZE_SIZE__)
740 __m128i
data = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(
n));
741 if (hasMatch(
data, 0xff))
747 return UnrollTailLoop<3>::exec(e -
n, e,
751#elif defined(__ARM_NEON__)
752 const uint16x8_t vmask = { 1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7 };
753 const uint16x8_t ch_vec = vdupq_n_u16(
c);
755 uint16x8_t
data = vld1q_u16(
reinterpret_cast<const uint16_t *
>(
n));
756 uint mask = vaddvq_u16(vandq_u16(vceqq_u16(
data, ch_vec), vmask));
764 return std::find(
n, e,
c);
780 auto it = std::find_if(
n, e, [
c](
auto ch) {
return foldAndCompare(
ch,
QChar(
c)); });
781 return reinterpret_cast<const char16_t *
>(
it);
791 if constexpr (UseAvx2) {
793 __m256i
data = _mm256_loadu_si256(
reinterpret_cast<const __m256i *
>(
ptr));
806 __m128i
data = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(
ptr));
819 __m128i
data = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(
ptr));
832 if (
data &= 0x80808080U) {
852 const char *
ptr =
s.begin();
853 const char *
end =
s.end();
861 const char *ptr8 =
reinterpret_cast<const char *
>(
ptr);
862 const char *end8 =
reinterpret_cast<const char *
>(
end);
863 bool ok = simdTestMask(ptr8, end8, 0xff80ff80);
864 ptr =
reinterpret_cast<const char16_t *
>(ptr8);
879 const char16_t *
ptr =
s.utf16();
880 const char16_t *
end =
ptr +
s.size();
887 const char16_t *
ptr =
s.utf16();
888 const char16_t *
end =
ptr +
s.size();
891 const char *ptr8 =
reinterpret_cast<const char *
>(
ptr);
892 const char *end8 =
reinterpret_cast<const char *
>(
end);
893 if (!simdTestMask(ptr8, end8, 0xff00ff00))
895 ptr =
reinterpret_cast<const char16_t *
>(ptr8);
907 constexpr char32_t InvalidCodePoint = UINT_MAX;
910 while (
i.hasNext()) {
911 const char32_t c =
i.next(InvalidCodePoint);
912 if (
c == InvalidCodePoint)
929 const __m128i nullMask = _mm_setzero_si128();
931 const __m128i chunk = _mm_loadu_si128((
const __m128i*)(
str +
offset));
932 if constexpr (UseAvx2) {
934 const __m256i extended = _mm256_cvtepu8_epi16(chunk);
937 _mm256_storeu_si256((__m256i*)(
dst +
offset), extended);
940 const __m128i firstHalf = _mm_unpacklo_epi8(chunk, nullMask);
941 _mm_storeu_si128((__m128i*)(
dst +
offset), firstHalf);
944 const __m128i secondHalf = _mm_unpackhi_epi8 (chunk, nullMask);
945 _mm_storeu_si128((__m128i*)(
dst +
offset + 8), secondHalf);
950 if (
size >=
sizeof(__m128i)) {
952 for ( ;
str +
offset +
sizeof(__m128i) <= e;
offset +=
sizeof(__m128i))
955 processOneChunk(
size -
sizeof(__m128i));
959# if !defined(__OPTIMIZE_SIZE__)
963 const __m128i unpacked1 = mm_load8_zero_extend(
str);
964 const __m128i unpacked2 = mm_load8_zero_extend(
str +
size - 8);
965 _mm_storeu_si128(
reinterpret_cast<__m128i *
>(
dst), unpacked1);
966 _mm_storeu_si128(
reinterpret_cast<__m128i *
>(
dst +
size - 8), unpacked2);
968 const __m128i chunk1 = _mm_cvtsi32_si128(qFromUnaligned<quint32>(
str));
969 const __m128i chunk2 = _mm_cvtsi32_si128(qFromUnaligned<quint32>(
str +
size - 4));
970 const __m128i unpacked1 = _mm_unpacklo_epi8(chunk1, nullMask);
971 const __m128i unpacked2 = _mm_unpacklo_epi8(chunk2, nullMask);
972 _mm_storel_epi64(
reinterpret_cast<__m128i *
>(
dst), unpacked1);
973 _mm_storel_epi64(
reinterpret_cast<__m128i *
>(
dst +
size - 4), unpacked2);
982#if defined(__mips_dsp)
983 static_assert(
sizeof(
qsizetype) ==
sizeof(
int),
984 "oops, the assembler implementation needs to be called in a loop");
986 qt_fromlatin1_mips_asm_unroll8(
dst,
str,
size);
988 qt_fromlatin1_mips_asm_unroll4(
dst,
str,
size);
998 QVarLengthArray<char16_t> arr(
len);
1003template <
bool Checked>
1006#if defined(__SSE2__)
1007 auto questionMark256 = []() {
1008 if constexpr (UseAvx2)
1009 return _mm256_broadcastw_epi16(_mm_cvtsi32_si128(
'?'));
1013 auto outOfRange256 = []() {
1014 if constexpr (UseAvx2)
1015 return _mm256_broadcastw_epi16(_mm_cvtsi32_si128(0x100));
1019 __m128i questionMark, outOfRange;
1020 if constexpr (UseAvx2) {
1021 questionMark = _mm256_castsi256_si128(questionMark256);
1022 outOfRange = _mm256_castsi256_si128(outOfRange256);
1024 questionMark = _mm_set1_epi16(
'?');
1025 outOfRange = _mm_set1_epi16(0x100);
1028 auto mergeQuestionMarks = [=](__m128i chunk) {
1033 if constexpr (UseSse4_1) {
1035 chunk = _mm_min_epu16(chunk, outOfRange);
1036 const __m128i offLimitMask = _mm_cmpeq_epi16(chunk, outOfRange);
1037 chunk = _mm_blendv_epi8(chunk, questionMark, offLimitMask);
1041 const __m128i signedBitOffset = _mm_set1_epi16(
short(0x8000));
1042 const __m128i thresholdMask = _mm_set1_epi16(
short(0xff + 0x8000));
1044 const __m128i signedChunk = _mm_add_epi16(chunk, signedBitOffset);
1045 const __m128i offLimitMask = _mm_cmpgt_epi16(signedChunk, thresholdMask);
1049 const __m128i offLimitQuestionMark = _mm_and_si128(offLimitMask, questionMark);
1053 const __m128i correctBytes = _mm_andnot_si128(offLimitMask, chunk);
1056 chunk = _mm_or_si128(correctBytes, offLimitQuestionMark);
1064 __m128i chunk1, chunk2;
1065 if constexpr (UseAvx2) {
1066 __m256i chunk = _mm256_loadu_si256(
reinterpret_cast<const __m256i *
>(
src +
offset));
1069 chunk = _mm256_min_epu16(chunk, outOfRange256);
1070 const __m256i offLimitMask = _mm256_cmpeq_epi16(chunk, outOfRange256);
1071 chunk = _mm256_blendv_epi8(chunk, questionMark256, offLimitMask);
1074 chunk2 = _mm256_extracti128_si256(chunk, 1);
1075 chunk1 = _mm256_castsi256_si128(chunk);
1077 chunk1 = _mm_loadu_si128((
const __m128i*)(
src +
offset));
1078 chunk1 = mergeQuestionMarks(chunk1);
1080 chunk2 = _mm_loadu_si128((
const __m128i*)(
src +
offset + 8));
1081 chunk2 = mergeQuestionMarks(chunk2);
1085 return _mm_packus_epi16(chunk1, chunk2);
1088 if (
size_t(
length) >=
sizeof(__m128i)) {
1092 _mm_storeu_si128(
reinterpret_cast<__m128i *
>(
dst +
offset), loadChunkAt(
offset));
1095 __m128i last1 = loadChunkAt(
offset);
1096 __m128i last2 = loadChunkAt(
length -
sizeof(__m128i));
1097 _mm_storeu_si128(
reinterpret_cast<__m128i *
>(
dst +
offset), last1);
1098 _mm_storeu_si128(
reinterpret_cast<__m128i *
>(
dst +
length -
sizeof(__m128i)), last2);
1102# if !defined(__OPTIMIZE_SIZE__)
1107 __m128i chunk1 = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(
src));
1108 __m128i chunk2 = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(
src +
length - 8));
1109 chunk1 = mergeQuestionMarks(chunk1);
1110 chunk2 = mergeQuestionMarks(chunk2);
1113 const __m128i result1 = _mm_packus_epi16(chunk1, chunk1);
1114 const __m128i result2 = _mm_packus_epi16(chunk2, chunk2);
1115 _mm_storel_epi64(
reinterpret_cast<__m128i *
>(
dst), result1);
1116 _mm_storel_epi64(
reinterpret_cast<__m128i *
>(
dst +
length - 8), result2);
1118 __m128i chunk1 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(
src));
1119 __m128i chunk2 = _mm_loadl_epi64(
reinterpret_cast<const __m128i *
>(
src +
length - 4));
1120 chunk1 = mergeQuestionMarks(chunk1);
1121 chunk2 = mergeQuestionMarks(chunk2);
1124 const __m128i result1 = _mm_packus_epi16(chunk1, chunk1);
1125 const __m128i result2 = _mm_packus_epi16(chunk2, chunk2);
1142#elif defined(__ARM_NEON__)
1149 const uint16x8_t questionMark = vdupq_n_u16(
'?');
1150 const uint16x8_t thresholdMask = vdupq_n_u16(0xff);
1152 uint16x8_t chunk = vld1q_u16((uint16_t *)
src);
1156 const uint16x8_t offLimitMask = vcgtq_u16(chunk, thresholdMask);
1157 const uint16x8_t offLimitQuestionMark = vandq_u16(offLimitMask, questionMark);
1158 const uint16x8_t correctBytes = vbicq_u16(chunk, offLimitMask);
1159 chunk = vorrq_u16(correctBytes, offLimitQuestionMark);
1161 const uint8x8_t
result = vmovn_u16(chunk);
1168#if defined(__mips_dsp)
1169 static_assert(
sizeof(
qsizetype) ==
sizeof(
int),
1170 "oops, the assembler implementation needs to be called in a loop");
1203 for (
i = 0;
i < l; ++
i) {
1225 for (
i = 0;
i < l; ++
i) {
1241 auto src1 =
reinterpret_cast<const uchar *
>(utf8);
1242 auto end1 =
reinterpret_cast<const uchar *
>(utf8end);
1245 while (src1 < end1 && src2.hasNext()) {
1252 uc1 = QChar::ReplacementCharacter;
1254 uc1 = QChar::toCaseFolded(uc1);
1257 char32_t uc2 = QChar::toCaseFolded(src2.next());
1258 int diff = uc1 - uc2;
1264 return (end1 > src1) - int(src2.hasNext());
1267#if defined(__mips_dsp)
1269extern "C" int qt_ucstrncmp_mips_dsp_asm(
const char16_t *
a,
1275template <StringComparisonMode Mode>
1282#ifndef __OPTIMIZE_SIZE__
1283# if defined(__mips_dsp)
1284 static_assert(
sizeof(
uint) ==
sizeof(
size_t));
1286 return qt_ucstrncmp_mips_dsp_asm(
a,
b, l);
1288# elif defined(__SSE2__)
1289 return ucstrncmp_sse2<Mode>(
a,
b, l);
1290# elif defined(__ARM_NEON__)
1292 const char16_t *
end =
a + l;
1293 const uint16x8_t
mask = { 1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7 };
1294 while (
end -
a > 7) {
1295 uint16x8_t da = vld1q_u16(
reinterpret_cast<const uint16_t *
>(
a));
1296 uint16x8_t
db = vld1q_u16(
reinterpret_cast<const uint16_t *
>(
b));
1298 uint8_t
r = ~(uint8_t)vaddvq_u16(vandq_u16(vceqq_u16(da,
db),
mask));
1301 if (
Mode == CompareStringsForEquality)
1304 return a[idx] -
b[idx];
1311 const auto lambda = [=](
size_t i) ->
int {
1314 return UnrollTailLoop<7>::exec(l, 0, lambda, lambda);
1319 return memcmp(
a,
b, l *
sizeof(
char16_t));
1321 for (
size_t i = 0;
i < l; ++
i) {
1322 if (
int diff =
a[
i] -
b[
i])
1328template <StringComparisonMode Mode>
1332 const char16_t *uc =
a;
1333 const char16_t *e = uc + l;
1335#if defined(__SSE2__) && !defined(__OPTIMIZE_SIZE__)
1336 return ucstrncmp_sse2<Mode>(uc,
c, l);
1340 int diff = *uc - *
c;
1350template <
typename Char2>
1351static bool ucstreq(
const char16_t *
a,
size_t alen,
const Char2 *
b)
1353 if constexpr (std::is_same_v<
decltype(
a),
decltype(
b)>) {
1357 return ucstrncmp<CompareStringsForEquality>(
a,
b, alen) == 0;
1361template <
typename Char2>
1362static int ucstrcmp(
const char16_t *
a,
size_t alen,
const Char2 *
b,
size_t blen)
1364 if constexpr (std::is_same_v<
decltype(
a),
decltype(
b)>) {
1365 if (
a ==
b && alen == blen)
1368 const size_t l =
qMin(alen, blen);
1369 int cmp = ucstrncmp<CompareStringsForOrdering>(
a,
b, l);
1370 return cmp ? cmp :
qt_lencmp(alen, blen);
1378 Q_ASSERT(lSize >= 0 && rSize >= 0);
1380 return rSize ? -1 : 0;
1395 Q_ASSERT(lhs.size() == rhs.size());
1396 return ucstreq(lhs.utf16(), lhs.size(), rhs.utf16());
1401 Q_ASSERT(lhs.size() == rhs.size());
1402 return ucstreq(lhs.utf16(), lhs.size(), rhs.latin1());
1412 Q_ASSERT(lhs.size() == rhs.size());
1413 return (!lhs.size() || memcmp(lhs.data(), rhs.data(), lhs.size()) == 0);
1438#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED) || defined(QT_STATIC)
1439 Q_ASSERT(lhs.size() == rhs.size());
1442 if (lhs.size() != rhs.size())
1445 return (!lhs.size() || memcmp(lhs.data(), rhs.data(), lhs.size()) == 0);
1450 if (lhs.size() != rhs.size() && lhs.isUtf8() == rhs.isUtf8())
1452 return lhs.visit([rhs](
auto lhs) {
1453 return rhs.visit([lhs](
auto rhs) {
1477 return ucstrcmp(lhs.utf16(), lhs.size(), rhs.utf16(), rhs.size());
1478 return ucstricmp(lhs.size(), lhs.utf16(), rhs.size(), rhs.utf16());
1500 return ucstrcmp(lhs.utf16(), lhs.size(), rhs.latin1(), rhs.size());
1501 return ucstricmp(lhs.size(), lhs.utf16(), rhs.size(), rhs.latin1());
1512 return -compareStrings(rhs, lhs, cs);
1523 return -compareStrings(rhs, lhs, cs);
1547 return latin1nicmp(lhs.data(), lhs.size(), rhs.data(), rhs.size());
1548 const auto l = std::min(lhs.size(), rhs.size());
1549 int r = memcmp(lhs.data(), rhs.data(), l);
1574 return ucstricmp8(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
1585 return -compareStrings(rhs, lhs, cs);
1601 return lhs.visit([rhs, cs](
auto lhs) {
1602 return rhs.visit([lhs, cs](
auto rhs) {
1610#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
1611static bool supportUnicodeDigitValuesInArg()
1613 static const bool result = []() {
1614 static const char supportUnicodeDigitValuesEnvVar[]
1615 =
"QT_USE_UNICODE_DIGIT_VALUES_IN_STRING_ARG";
1620#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
1633#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
1634 if (supportUnicodeDigitValuesInArg())
1635 return ch.digitValue();
1637 if (
ch >= u
'0' &&
ch <= u
'9')
1638 return int(
ch.unicode() - u
'0');
1642#if QT_CONFIG(regularexpression)
2385Returns a copy of the \a str string. The given string is assumed to be
2386encoded in \1, and is converted to QString using the \2 function.
2501 d = DataPointer::fromRawData(&_empty, 0);
2505 memcpy(
d.data(), unicode,
size *
sizeof(
QChar));
2506 d.data()[
size] =
'\0';
2520 d = DataPointer::fromRawData(&_empty, 0);
2524 d.data()[
size] =
'\0';
2525 char16_t *
b =
d.data();
2526 char16_t *e =
d.data() +
size;
2527 const char16_t value =
ch.unicode();
2541 d = DataPointer::fromRawData(&_empty, 0);
2545 d.data()[
size] =
'\0';
2563 d.data()[0] =
ch.unicode();
2634 return newSize > capacityAtEnd;
2676 if (
d->allocatedCapacity())
2677 d.data()[
size] = u
'\0';
2696 std::fill_n(
d.data() + oldSize, difference, fillChar.unicode());
2788 d = DataPointer::fromRawData(&_empty, 0);
2794 const bool cannotUseReallocate =
d.freeSpaceAtBegin() > 0;
2796 if (
d->needsDetach() || cannotUseReallocate) {
2797 DataPointer dd(alloc,
qMin(alloc,
d.size),
option);
2800 ::memcpy(dd.data(),
d.data(), dd.size *
sizeof(
QChar));
2801 dd.data()[dd.size] = 0;
2813 if (
d->needsDetach()) {
2816 dd->copyAppend(
d.data(),
d.data() +
d.size);
2817 dd.data()[dd.size] = 0;
2860 if (isDetached() &&
other.size() <= capacityAtEnd) {
2862 d.data()[
other.size()] = 0;
2865 *
this = fromLatin1(
other.latin1(),
other.size());
2903 return assign(1,
ch);
2969template <
typename T>
2975 difference =
i - str_d.size;
2977 const qsizetype insert_size = toInsert.size();
2978 const qsizetype newSize = str_d.size + difference + insert_size;
2984 const auto insert_start = difference == 0 ? std::next(cbegin,
i) : cend;
2988 other.data_ptr().detachAndGrow(side, newSize,
nullptr,
nullptr);
2991 other.append(toInsert);
2997 str_d.detachAndGrow(side, difference + insert_size,
nullptr,
nullptr);
3001 auto begin = str_d.begin();
3002 auto old_end = std::next(
begin, oldSize);
3003 std::fill_n(old_end, difference, u
' ');
3004 auto insert_start = std::next(
begin,
i);
3005 if (difference == 0)
3006 std::move_backward(insert_start, old_end, str_d.end());
3008 using Char = std::remove_cv_t<typename T::value_type>;
3009 if constexpr(std::is_same_v<Char, QChar>)
3010 std::copy_n(
reinterpret_cast<const char16_t *
>(toInsert.data()), insert_size, insert_start);
3011 else if constexpr (std::is_same_v<Char, char16_t>)
3012 std::copy_n(toInsert.data(), insert_size, insert_start);
3013 else if constexpr (std::is_same_v<Char, char>)
3027 const char *
s =
str.latin1();
3028 if (
i < 0 || !
s || !(*
s))
3050 auto insert_size =
s.
size();
3051 if (
i < 0 || insert_size <= 0)
3056 difference =
i -
d.size;
3058 const qsizetype newSize =
d.size + difference + insert_size;
3061 const auto cbegin = this->cbegin();
3062 const auto insert_start = difference == 0 ? std::next(cbegin,
i) : cend();
3064 other.reserve(newSize);
3085 QVarLengthArray<char16_t>
buffer(insert_size);
3107 if (
i < 0 ||
size <= 0)
3189 static_assert(
sizeof(
QChar) ==
sizeof(
char16_t),
"Unexpected difference in sizes");
3191 const char16_t *char16String =
reinterpret_cast<const char16_t *
>(
str);
3192 d->growAppend(char16String, char16String +
len);
3193 d.
data()[
d.size] = u
'\0';
3205 append_helper(*
this,
str);
3217 append_helper(*
this,
str);
3255 d->copyAppend(1,
ch.unicode());
3408 if (
s.size() <=
capacity() && isDetached()) {
3409 const auto offset =
d.freeSpaceAtBegin();
3413 s.visit([
this](
auto input) {
3417 *
this =
s.toString();
3422#ifndef QT_BOOTSTRAPPED
3426 const auto requiredCapacity =
len * 2;
3427 if (requiredCapacity <=
capacity() && isDetached()) {
3428 const auto offset =
d.freeSpaceAtBegin();
3431 auto begin =
reinterpret_cast<QChar *
>(
d.begin());
3436 d.data()[
d.size] = u
'\0';
3471 if (
size_t(
pos) >=
size_t(
size()) ||
len <= 0)
3476 if (!
d->isShared()) {
3478 d.data()[
d.size] = u
'\0';
3486 auto toRemove_start =
d.begin() +
pos;
3487 copy.d->copyRanges({{
begin, toRemove_start},
3488 {toRemove_start +
len,
d.end()}});
3497 const auto needleSize = needle.size();
3510 auto copyFunc = [&](
auto &
dst) {
3513 i =
s.indexOf(needle, std::distance(
begin,
src), cs);
3516 src = hit + needleSize;
3521 if (!dptr->needsDetach()) {
3527 auto copy_begin =
copy.begin();
3530 copy.resize(std::distance(copy_begin,
dst));
3634 ch = isCase ?
ch :
ch.toCaseFolded();
3636 return ch == (isCase ?
x :
x.toCaseFolded());
3641 auto first_match =
begin + idx;
3643 if (!
d->isShared()) {
3644 auto it = std::remove_if(first_match,
end,
match);
3645 d->erase(
it, std::distance(
it,
end));
3646 d.data()[
d.size] = u
'\0';
3653 auto it = std::copy(
begin, first_match,
dst);
3654 it = std::remove_copy_if(first_match + 1,
end,
it,
match);
3656 copy.d.data()[
copy.d.size] = u
'\0';
3657 *
this = std::move(
copy);
3696 const char16_t *after_b = after.utf16();
3699 auto src_start = str_d.
begin();
3703 auto dst = copy_d.begin();
3705 auto hit = str_d.begin() +
index;
3706 dst = std::copy(src_start, hit,
dst);
3707 dst = std::copy_n(after_b, alen,
dst);
3708 src_start = hit + blen;
3710 dst = std::copy(src_start, str_d.end(),
dst);
3719 const char16_t *after_b = after.utf16();
3720 const char16_t *after_e = after.utf16() + after.size();
3725 }
else if (blen > alen) {
3729 to = std::copy_n(after_b, alen, to);
3730 char16_t *movestart = hit + blen;
3733 to = std::move(movestart, hit, to);
3734 to = std::copy_n(after_b, alen, to);
3735 movestart = hit + blen;
3742 const qsizetype newSize = oldSize + adjust;
3746 char16_t *moveend =
begin + oldSize;
3751 char16_t *movestart = hit + blen;
3752 to = std::move_backward(movestart, moveend, to);
3753 to = std::copy_backward(after_b, after_e, to);
3763 const qsizetype newSize = oldSize + adjust;
3795 return replace(
pos,
len, after.constData(), after.size());
3807 if (
size_t(
pos) >
size_t(this->
size()))
3809 if (len > this->
size() - pos)
3826 return replace(
pos,
len, &after, 1);
3848 return replace(before.
constData(), before.
size(), after.constData(), after.size(), cs);
3872 if (alen == 0 && blen == 0)
3874 if (alen == 1 && blen == 1)
3875 return replace(*before, *after, cs);
3881 QVarLengthArray<size_t>
indices;
3905 if (after.size() == 0)
3908 if (after.size() == 1)
3909 return replace(
ch, after.front(), cs);
3916 QVarLengthArray<size_t>
indices;
3918 const char16_t *
begin =
d.begin();
3919 const char16_t *
end =
d.end();
3921 const char16_t *hit =
nullptr;
3928 if (QChar::toCaseFolded(
d.data()[
i]) == cc)
3951 const char16_t achar = after.unicode();
3952 char16_t bchar = before.unicode();
3954 auto matchesCIS = [](
char16_t beforeChar) {
3955 return [beforeChar](
char16_t ch) {
return foldAndCompare(
ch, beforeChar); };
3958 auto hit =
d.begin() + idx;
3959 if (!
d.needsDetach()) {
3962 std::replace(hit,
d.end(), bchar, achar);
3965 std::replace_if(hit,
d.end(), matchesCIS(bchar), achar);
3969 auto dest = std::copy(
d.begin(), hit,
other.d.begin());
3973 std::replace_copy(hit,
d.end(), dest, bchar, achar);
3976 std::replace_copy_if(hit,
d.end(), dest, matchesCIS(bchar), achar);
4000 if (blen == 1 && alen == 1)
4001 return replace(before.
front(), after.front(), cs);
4005 return replace((
const QChar *)
b.data(), blen, (
const QChar *)
a.data(), alen, cs);
4023 if (blen == 1 && after.size() == 1)
4024 return replace(before.
front(), after.front(), cs);
4027 return replace((
const QChar *)
b.data(), blen, after.constData(), after.d.size, cs);
4044 if (before.
size() == 1 && alen == 1)
4045 return replace(before.
front(), after.front(), cs);
4066 return replace(
c, after.front(), cs);
4069 return replace(&
c, 1, (
const QChar *)
a.data(), alen, cs);
4670#if QT_CONFIG(regularexpression)
4671struct QStringCapture
4699 if (!re.isValid()) {
4711 qsizetype numCaptures = re.captureCount();
4715 QVarLengthArray<QStringCapture> backReferences;
4717 const QChar *ac = after.unicode();
4720 if (ac[
i] == u
'\\') {
4721 int no = ac[
i + 1].digitValue();
4722 if (no > 0 && no <= numCaptures) {
4723 QStringCapture backReference;
4724 backReference.pos =
i;
4725 backReference.len = 2;
4728 int secondDigit = ac[
i + 2].digitValue();
4729 if (secondDigit != -1 && ((no * 10) + secondDigit) <= numCaptures) {
4730 no = (no * 10) + secondDigit;
4731 ++backReference.len;
4735 backReference.no = no;
4736 backReferences.append(backReference);
4747 QVarLengthArray<QStringView> chunks;
4753 len =
match.capturedStart() - lastEnd;
4755 chunks << copyView.mid(lastEnd,
len);
4761 for (
const QStringCapture &backReference :
std::as_const(backReferences)) {
4763 len = backReference.pos - lastEnd;
4765 chunks << afterView.mid(lastEnd,
len);
4770 len =
match.capturedLength(backReference.no);
4772 chunks << copyView.mid(
match.capturedStart(backReference.no),
len);
4776 lastEnd = backReference.pos + backReference.len;
4780 len = afterView.size() - lastEnd;
4782 chunks << afterView.mid(lastEnd,
len);
4786 lastEnd =
match.capturedEnd();
4790 if (copyView.size() > lastEnd) {
4791 chunks << copyView.mid(lastEnd);
4792 newLength += copyView.size() - lastEnd;
4801 memcpy(uc +
i, chunk.constData(),
len *
sizeof(
QChar));
4895#if QT_CONFIG(regularexpression)
4988 return QtPrivate::contains(
QStringView(*
this),
this, re, rmatch);
5015#if QT_DEPRECATED_SINCE(6, 4)
5092 const qsizetype sectionsSize = sections.size();
5093 if (!(
flags & SectionSkipEmpty)) {
5095 start += sectionsSize;
5097 end += sectionsSize;
5100 for (
qsizetype k = 0; k < sectionsSize; ++k) {
5101 if (sections.at(k).isEmpty())
5105 start += sectionsSize - skip;
5107 end += sectionsSize - skip;
5109 if (
start >= sectionsSize || end < 0 || start >
end)
5116 const bool empty = section.
isEmpty();
5126 if (!empty || !(
flags & SectionSkipEmpty))
5129 if ((
flags & SectionIncludeLeadingSep) && first_i > 0)
5131 if ((
flags & SectionIncludeTrailingSep) && last_i < sectionsSize - 1)
5136#if QT_CONFIG(regularexpression)
5137class qt_section_chunk {
5139 qt_section_chunk() {}
5147 QString::SectionFlags
flags)
5149 const qsizetype sectionsSize = sections.size();
5153 start += sectionsSize;
5155 end += sectionsSize;
5158 for (
qsizetype k = 0; k < sectionsSize; ++k) {
5159 const qt_section_chunk §ion = sections[k];
5160 if (section.length == section.string.size())
5164 start += sectionsSize - skip;
5166 end += sectionsSize - skip;
5168 if (
start >= sectionsSize || end < 0 || start >
end)
5175 const qt_section_chunk §ion = sections[
i];
5176 const bool empty = (section.length == section.string.size());
5183 ret += section.string;
5185 ret += section.string.mid(section.length);
5192 const qt_section_chunk §ion = sections[first_i];
5193 ret.prepend(section.string.left(section.length));
5197 && last_i < sectionsSize - 1) {
5198 const qt_section_chunk §ion = sections[last_i + 1];
5199 ret += section.string.left(section.length);
5221 if (!re.isValid()) {
5226 const QChar *uc = unicode();
5231 if (
flags & SectionCaseInsensitiveSeps)
5234 QVarLengthArray<qt_section_chunk> sections;
5239 m =
match.capturedStart();
5240 sections.append(qt_section_chunk(last_len,
QStringView{ *
this }.
sliced(last_m,
m - last_m)));
5242 last_len =
match.capturedLength();
5244 sections.append(qt_section_chunk(last_len,
QStringView{ *
this }.
sliced(last_m,
n - last_m)));
5305 switch (QContainerImplHelper::mid(
size(), &
p, &l)) {
5306 case QContainerImplHelper::Null:
5308 case QContainerImplHelper::Empty:
5309 return QString(DataPointer::fromRawData(&_empty, 0));
5310 case QContainerImplHelper::Full:
5312 case QContainerImplHelper::Subset:
5313 return sliced(
p, l);
5315 Q_UNREACHABLE_RETURN(
QString());
5323 switch (QContainerImplHelper::mid(
size(), &
p, &l)) {
5324 case QContainerImplHelper::Null:
5326 case QContainerImplHelper::Empty:
5329 case QContainerImplHelper::Full:
5330 return std::move(*
this);
5331 case QContainerImplHelper::Subset:
5332 return std::move(*this).sliced(
p, l);
5334 Q_UNREACHABLE_RETURN(
QString());
5384 return QString(DataPointer::fromRawData(&_empty, 0));
5385 DataPointer
d = std::move(
str.d).sliced(
pos,
n);
5549 while (
it.hasNext()) {
5550 const char32_t uc =
it.next();
5622 return string.visit([] (
auto string) {
return string.toString(); });
5653 string.utf16(),
string.size());
5659 if (!
s.isDetached())
5669 char16_t *sdata =
s.d->data();
5675 auto ba_d = std::move(
s.d).reinterpreted<
char>();
5678 Q_ASSERT(ba_d.d->allocatedCapacity() >= ba_d.size);
5691 return std::next(
out,
len);
5737 if (
string.isNull())
5830 QList<uint>
v(
string.
size());
5833 while (
it.hasNext())
5835 v.resize(
a -
v.constData());
5876 }
else if (
ba.
size() == 0) {
5877 d = DataPointer::fromRawData(&_empty, 0);
5882 char16_t *
dst =
d.data();
5954 return QString(DataPointer::fromRawData(&_empty, 0));
6023 return QString(DataPointer::fromRawData(&_empty, 0));
6027#ifndef QT_BOOTSTRAPPED
6083 while (unicode[
size] != 0)
6103 if (unicode &&
size)
6104 memcpy(
d.data(), unicode,
size *
sizeof(
QChar));
6151 template <
typename StringView>
6152 StringView qt_trimmed(StringView
s)
noexcept
6176 return qt_trimmed(
s);
6181 return qt_trimmed(
s);
6362 std::fill(
d.data(),
d.data() +
d.size,
ch.unicode());
6886#if !defined(CSTR_LESS_THAN)
6887#define CSTR_LESS_THAN 1
6889#define CSTR_GREATER_THAN 3
6909 return localeAwareCompare_helper(constData(),
size(),
other.constData(),
other.size());
6916int QString::localeAwareCompare_helper(
const QChar *data1,
qsizetype length1,
6925 if (length1 == 0 || length2 == 0)
6934# if defined(Q_OS_WIN)
6945# elif defined (Q_OS_DARWIN)
6950 const CFStringRef thisString =
6951 CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault,
6952 reinterpret_cast<const UniChar *
>(lhs.
constData()), lhs.
length(), kCFAllocatorNull);
6953 const CFStringRef otherString =
6954 CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault,
6955 reinterpret_cast<const UniChar *
>(rhs.
constData()), rhs.
length(), kCFAllocatorNull);
6957 const int result = CFStringCompare(thisString, otherString, kCFCompareLocalized);
6958 CFRelease(thisString);
6959 CFRelease(otherString);
6961# elif defined(Q_OS_UNIX)
6965# error "This case shouldn't happen"
6997 if (!
d->isMutable()) {
7001 return reinterpret_cast<const ushort *
>(
d.data());
7072 memcpy(
static_cast<void *
>(uc),
static_cast<const void *
>(
d.data()),
sizeof(
QChar)*
len);
7121template <
typename T>
7127 QChar *pp =
s.begin() +
it.index();
7132 if (folded.chars[0] == *pp && folded.size() == 2) {
7136 *pp++ = folded.chars[1];
7142 s.replace(outpos, 1,
reinterpret_cast<const QChar *
>(folded.data()), folded.size());
7143 pp =
const_cast<QChar *
>(
s.constBegin()) + outpos + folded.size();
7146 if constexpr (!std::is_const<T>::value)
7150 *pp++ = folded.chars[0];
7152 }
while (
it.hasNext());
7157template <
typename T>
7164 while (e !=
p && e[-1].isHighSurrogate())
7168 while (
it.hasNext()) {
7169 const char32_t uc =
it.next();
7170 if (
qGetProp(uc)->cases[which].diff) {
7175 return std::move(
str);
7266 va_start(ap, cformat);
7267 const QString s = vasprintf(cformat, ap);
7275 qs.resize(oldSize +
len);
7277 qs.resize(newEnd - qs.constData());
7294 default:
return flags;
7303 const char *
const stop =
c +
size;
7333 case 'L':
return lm_L;
7334 case 'j':
return lm_j;
7336 case 'Z':
return lm_z;
7337 case 't':
return lm_t;
7359 if (!cformat || !*cformat) {
7361 return fromLatin1(
"");
7367 const char *
c = cformat;
7368 const char *formatEnd = cformat +
qstrlen(cformat);
7372 while (*
c !=
'\0' && *
c !=
'%')
7380 const char *escape_start =
c;
7404 }
else if (*
c ==
'*') {
7405 width = va_arg(ap,
int);
7423 }
else if (*
c ==
'*') {
7449 switch (length_mod) {
7450 case lm_none:
i = va_arg(ap,
int);
break;
7451 case lm_hh:
i = va_arg(ap,
int);
break;
7452 case lm_h:
i = va_arg(ap,
int);
break;
7453 case lm_l:
i = va_arg(ap,
long int);
break;
7455 case lm_j:
i = va_arg(ap,
long int);
break;
7460 default:
i = 0;
break;
7471 switch (length_mod) {
7473 case lm_hh: u = va_arg(ap,
uint);
break;
7474 case lm_h: u = va_arg(ap,
uint);
break;
7475 case lm_l: u = va_arg(ap,
ulong);
break;
7477 case lm_t: u = va_arg(ap,
size_t);
break;
7478 case lm_z: u = va_arg(ap,
size_t);
break;
7479 default: u = 0;
break;
7508 if (length_mod ==
lm_L)
7509 d = va_arg(ap,
long double);
7511 d = va_arg(ap,
double);
7529 if (length_mod ==
lm_l)
7530 subst = QChar::fromUcs2(va_arg(ap,
int));
7537 if (length_mod ==
lm_l) {
7544 subst.setUtf16(buff,
ch - buff);
7548 const char *buff = va_arg(ap,
const char*);
7555 void *
arg = va_arg(ap,
void*);
7563 switch (length_mod) {
7565 signed char *
n = va_arg(ap,
signed char*);
7570 short int *
n = va_arg(ap,
short int*);
7575 long int *
n = va_arg(ap,
long int*);
7585 int *
n = va_arg(ap,
int*);
7594 for (
const char *cc = escape_start; cc !=
c; ++cc)
7637template <
typename Int>
7640#if defined(QT_CHECK_RANGE)
7641 if (
base != 0 && (base < 2 || base > 36)) {
7642 qWarning(
"QString::toIntegral: Invalid base (%d)",
base);
7647 QVarLengthArray<uchar> latin1(
string.
size());
7648 qt_to_latin1(latin1.data(),
string.utf16(),
string.size());
7649 QSimpleParsedNumber<Int>
r;
7650 if constexpr (std::is_signed_v<Int>)
7661 return toIntegral<qlonglong>(
string,
ok,
base);
7695 return toIntegral<qulonglong>(
string,
ok,
base);
7912 QVarLengthArray<uchar> latin1(
string.
size());
7913 qt_to_latin1(latin1.data(),
string.utf16(),
string.size());
7914 auto r =
qt_asciiToDouble(
reinterpret_cast<const char *
>(latin1.data()),
string.size());
8102#if defined(QT_CHECK_RANGE)
8103 if (base < 2 || base > 36) {
8108 bool negative =
n < 0;
8121#if defined(QT_CHECK_RANGE)
8122 if (base < 2 || base > 36) {
8157#if defined(QT_CHECK_RANGE)
8167template<
class ResultList,
class StringSource>
8172 typename StringSource::size_type
start = 0;
8173 typename StringSource::size_type
end;
8174 typename StringSource::size_type extra = 0;
8179 extra = (
sep.size() == 0 ? 1 : 0);
8220 return splitString<QStringList>(*
this,
sep, behavior, cs);
8229 return splitString<QStringList>(*
this,
QStringView(&
sep, 1), behavior, cs);
8251 return splitString<QList<QStringView>>(
QStringView(*
this),
sep, behavior, cs);
8259#if QT_CONFIG(regularexpression)
8261template<
class ResultList,
typename String,
typename MatchingFunction>
8263 MatchingFunction matchingFunction,
8264 Qt::SplitBehavior behavior)
8267 if (!re.isValid()) {
8319#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
8320 const auto matchingFunction = qOverload<const QString &, qsizetype, QRegularExpression::MatchType, QRegularExpression::MatchOptions>(&
QRegularExpression::globalMatch);
8324 return splitString<QStringList>(*
this,
8389 result.reserve(resultSize);
8390 if (
result.capacity() != resultSize)
8396 char16_t *
end =
result.d.data() + sizeSoFar;
8398 const qsizetype halfResultSize = resultSize >> 1;
8399 while (sizeSoFar <= halfResultSize) {
8404 memcpy(
end,
result.d.data(), (resultSize - sizeSoFar) *
sizeof(
QChar));
8405 result.d.data()[resultSize] =
'\0';
8406 result.d.size = resultSize;
8414 auto start =
reinterpret_cast<const char16_t *
>(
data->constData());
8415 const char16_t *
p =
start + from;
8422 if (version == QChar::Unicode_Unassigned) {
8423 version = QChar::currentUnicodeVersion();
8428 if (
n.version > version) {
8430 if (QChar::requiresSurrogates(
n.ucs4)) {
8431 char16_t ucs4High = QChar::highSurrogate(
n.ucs4);
8432 char16_t ucs4Low = QChar::lowSurrogate(
n.ucs4);
8433 char16_t oldHigh = QChar::highSurrogate(
n.old_mapping);
8434 char16_t oldLow = QChar::lowSurrogate(
n.old_mapping);
8435 while (
pos <
s.size() - 1) {
8436 if (
s.at(
pos).unicode() == ucs4High &&
s.at(
pos + 1).unicode() == ucs4Low) {
8445 while (
pos <
s.size()) {
8446 if (
s.at(
pos).unicode() ==
n.ucs4) {
8482#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
8488 if (!supportUnicodeDigitValuesInArg())
8491 const auto isNonAsciiDigit = [](
QChar c) {
8492 return c.unicode() < u
'0' ||
c.unicode() > u
'9';
8495 if (std::any_of(
s.begin(),
s.end(), isNonAsciiDigit)) {
8496 const auto accumulateDigit = [](
int partial,
QChar digit) {
8497 return partial * 10 + digit.digitValue();
8499 const int parsedNumber = std::accumulate(
s.begin(),
s.end(), 0, accumulateDigit);
8501 qWarning(
"QString::arg(): the replacement \"%%%ls\" contains non-ASCII digits;\n"
8502 " it is currently being interpreted as the %d-th substitution.\n"
8503 " This is deprecated; support for non-ASCII digits will be dropped\n"
8504 " in a future version of Qt.",
8522 const QChar *uc_begin =
s.begin();
8523 const QChar *uc_end =
s.end();
8530 d.locale_occurrences = 0;
8532 const QChar *
c = uc_begin;
8533 while (
c != uc_end) {
8534 while (
c != uc_end &&
c->unicode() !=
'%')
8539 const QChar *escape_start =
c;
8543 bool locale_arg =
false;
8544 if (
c->unicode() ==
'L') {
8556#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
8557 const QChar *escapeBegin =
c;
8558 const QChar *escapeEnd = escapeBegin + 1;
8565 if (next_escape != -1) {
8568#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
8574#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0) && !defined(QT_BOOTSTRAPPED)
8575 checkArgEscape(
QStringView(escapeBegin, escapeEnd));
8585 d.locale_occurrences = 0;
8590 ++
d.locale_occurrences;
8591 d.escape_len +=
c - escape_start;
8602 s.size() -
d.escape_len
8603 + (
d.occurrences -
d.locale_occurrences) *
qMax(abs_field_width,
arg.size())
8604 +
d.locale_occurrences *
qMax(abs_field_width, larg.size());
8608 QChar *
const result_end = rc + result_len;
8612 const QChar *
const uc_end =
s.end();
8613 while (
c != uc_end) {
8619 const QChar *text_start =
c;
8620 while (
c->unicode() !=
'%')
8623 const QChar *escape_start =
c++;
8624 const bool localize =
c->unicode() ==
'L';
8629 if (
escape != -1 &&
c + 1 != uc_end) {
8638 memcpy(rc, text_start, (
c - text_start) *
sizeof(
QChar));
8639 rc +=
c - text_start;
8643 memcpy(rc, text_start, (escape_start - text_start) *
sizeof(
QChar));
8644 rc += escape_start - text_start;
8647 const qsizetype pad_chars = abs_field_width - use.size();
8650 if (field_width > 0) {
8651 rc = std::fill_n(rc, pad_chars, fillChar);
8655 memcpy(rc, use.data(), use.size() *
sizeof(
QChar));
8658 if (field_width < 0) {
8659 rc = std::fill_n(rc, pad_chars, fillChar);
8662 if (++repl_cnt ==
d.occurrences) {
8663 memcpy(rc,
c, (uc_end -
c) *
sizeof(
QChar));
8780 return arg(
QStringView(utf16.data(), utf16.size()), fieldWidth, fillChar);
8874 if (
d.occurrences == 0) {
8875 qWarning() <<
"QString::arg: Argument missing:" << *
this <<
',' <<
a;
8881 if (fillChar == u
'0')
8885 if (
d.occurrences >
d.locale_occurrences) {
8887 Q_ASSERT(fillChar != u
'0' || fieldWidth <=
arg.size());
8891 if (
d.locale_occurrences > 0) {
8895 localeArg = locale.d->m_data->longLongToString(
a, -1,
base, fieldWidth,
flags);
8896 Q_ASSERT(fillChar != u
'0' || fieldWidth <= localeArg.size());
8920 if (
d.occurrences == 0) {
8921 qWarning() <<
"QString::arg: Argument missing:" << *
this <<
',' <<
a;
8927 if (fillChar == u
'0')
8931 if (
d.occurrences >
d.locale_occurrences) {
8933 Q_ASSERT(fillChar != u
'0' || fieldWidth <=
arg.size());
8937 if (
d.locale_occurrences > 0) {
8941 localeArg = locale.d->m_data->unsLongLongToString(
a, -1,
base, fieldWidth,
flags);
8942 Q_ASSERT(fillChar != u
'0' || fieldWidth <= localeArg.size());
9018 if (
d.occurrences == 0) {
9025 if (fillChar == u
'0')
9043#if defined(QT_CHECK_RANGE)
9050 if (
d.occurrences >
d.locale_occurrences) {
9054 || fieldWidth <=
arg.size());
9058 if (
d.locale_occurrences > 0) {
9061 const QLocale::NumberOptions numberOptions = locale.numberOptions();
9070 || fieldWidth <= localeArg.size());
9079template <
typename Char>
9084 if (
i <
len && uc[
i] == u
'L')
9094 if (
uint(digit) < 10U) {
9162enum { ExpectedParts = 32 };
9164typedef QVarLengthArray<Part, ExpectedParts> ParseResult;
9165typedef QVarLengthArray<int, ExpectedParts/2> ArgIndexToPlaceholderMap;
9167template <
typename StringView>
9168static ParseResult parseMultiArgFormatString(StringView
s)
9172 const auto uc =
s.data();
9173 const auto len =
s.size();
9174 const auto end =
len - 1;
9179 if (uc[
i] == u
'%') {
9183 if (last != percent)
9184 result.push_back(Part{
s.sliced(last, percent - last)});
9194 result.push_back(Part{
s.sliced(last,
len - last)});
9199static ArgIndexToPlaceholderMap makeArgIndexToPlaceholderMap(
const ParseResult &parts)
9201 ArgIndexToPlaceholderMap
result;
9203 for (
const Part &part : parts) {
9204 if (part.number >= 0)
9205 result.push_back(part.number);
9215static qsizetype resolveStringRefsAndReturnTotalSize(ParseResult &parts,
const ArgIndexToPlaceholderMap &argIndexToPlaceholderMap,
const QtPrivate::ArgBase *
args[])
9219 for (Part &part : parts) {
9220 if (part.number != -1) {
9221 const auto it = std::find(argIndexToPlaceholderMap.begin(), argIndexToPlaceholderMap.end(), part.number);
9222 if (
it != argIndexToPlaceholderMap.
end()) {
9237 totalSize += part.size;
9247template <
typename StringView>
9251 ParseResult parts = parseMultiArgFormatString(
pattern);
9254 ArgIndexToPlaceholderMap argIndexToPlaceholderMap = makeArgIndexToPlaceholderMap(parts);
9256 if (
static_cast<size_t>(argIndexToPlaceholderMap.size()) > numArgs)
9257 argIndexToPlaceholderMap.resize(
qsizetype(numArgs));
9258 else if (
Q_UNLIKELY(
static_cast<size_t>(argIndexToPlaceholderMap.size()) < numArgs))
9259 qWarning(
"QString::arg: %d argument(s) missing in %ls",
9263 const qsizetype totalSize = resolveStringRefsAndReturnTotalSize(parts, argIndexToPlaceholderMap,
args);
9269 for (
const Part &part : parts) {
9274 reinterpret_cast<const char*
>(part.data), part.size);
9282 memcpy(
out, part.data, part.size *
sizeof(
QChar));
9413 const auto start = std::distance(cbegin(),
first);
9414 const auto len = std::distance(
first, last);
9484 return QString(DataPointer::fromRawData(
const_cast<char16_t *
>(
reinterpret_cast<const char16_t *
>(unicode)),
size));
9503 if (!unicode || !
size) {
9506 *
this = fromRawData(unicode,
size);
9548#if !defined(QT_NO_DATASTREAM)
9560 if (
out.version() == 1) {
9565 out.writeBytes(
reinterpret_cast<const char *
>(
str.
unicode()),
9570 out.writeBytes(
reinterpret_cast<const char *
>(
buffer.data()),
9574 QDataStream::writeQSizeType(
out, -1);
9591 if (
in.version() == 1) {
9600 in.setStatus(QDataStream::SizeLimitExceeded);
9605 }
else if (bytes > 0) {
9608 in.setStatus(QDataStream::ReadCorruptData);
9616 while (allocated <
len) {
9619 if (
in.readRawData(
reinterpret_cast<char *
>(
str.
data()) + allocated * 2,
9622 in.setStatus(QDataStream::ReadPastEnd);
9630 char16_t *
data =
reinterpret_cast<char16_t *
>(
str.
data());
9667 int isolateLevel = 0;
9670 const char32_t c =
i.next();
9672 switch (QChar::direction(
c)) {
9717 if (haystack.size() > 500 && needle.size() > 5) {
9719 while ((
i =
matcher.indexIn(haystack,
i + 1)) != -1)
9731 return std::count(haystack.cbegin(), haystack.cend(), needle);
9734 return std::count_if(haystack.cbegin(), haystack.cend(),
9735 [needle](
const QChar c) { return foldAndCompare(c, needle); });
9744 while ((
i =
matcher.indexIn(haystack,
i + 1)) != -1)
9752 if (haystack.size() < needle.size())
9761 QVarLengthArray<uchar>
s(needle.size());
9766 while ((
i =
matcher.indexIn(haystack,
i + 1)) != -1)
9774 if (haystack.size() < needle.size())
9784 if (needle.unicode() > 0xff)
9788 return std::count(haystack.cbegin(), haystack.cend(), needle.toLatin1());
9790 return std::count_if(haystack.cbegin(), haystack.cend(),
9817 return qt_starts_with_impl(haystack, needle, cs);
9822 return qt_starts_with_impl(haystack, needle, cs);
9827 return qt_starts_with_impl(haystack, needle, cs);
9832 return qt_starts_with_impl(haystack, needle, cs);
9857 return qt_ends_with_impl(haystack, needle, cs);
9862 return qt_ends_with_impl(haystack, needle, cs);
9867 return qt_ends_with_impl(haystack, needle, cs);
9872 return qt_ends_with_impl(haystack, needle, cs);
9880 return findString(haystack0, from, needle0[0], cs);
9883 if (std::size_t(sl + from) > std::size_t(l))
9895 if (l > 500 && sl > 5)
9898 auto sv = [sl](
const char16_t *
v) {
return QStringView(
v, sl); };
9905 const char16_t *needle = needle0.utf16();
9906 const char16_t *haystack = haystack0.utf16() + from;
9907 const char16_t *
end = haystack0.utf16() + (l - sl);
9908 const std::size_t sl_minus_1 = sl - 1;
9909 std::size_t hashNeedle = 0, hashHaystack = 0;
9913 for (idx = 0; idx < sl; ++idx) {
9914 hashNeedle = ((hashNeedle<<1) + needle[idx]);
9915 hashHaystack = ((hashHaystack<<1) + haystack[idx]);
9917 hashHaystack -= haystack[sl_minus_1];
9919 while (haystack <=
end) {
9920 hashHaystack += haystack[sl_minus_1];
9921 if (hashHaystack == hashNeedle
9923 return haystack - haystack0.utf16();
9929 const char16_t *haystack_start = haystack0.utf16();
9930 for (idx = 0; idx < sl; ++idx) {
9931 hashNeedle = (hashNeedle<<1) +
foldCase(needle + idx, needle);
9932 hashHaystack = (hashHaystack<<1) +
foldCase(haystack + idx, haystack_start);
9934 hashHaystack -=
foldCase(haystack + sl_minus_1, haystack_start);
9936 while (haystack <=
end) {
9937 hashHaystack +=
foldCase(haystack + sl_minus_1, haystack_start);
9938 if (hashHaystack == hashNeedle
9940 return haystack - haystack0.utf16();
9951 if (haystack.size() < needle.size())
9960 if (haystack.size() < needle.size())
9966 if (needle.size() == 1) {
9967 const char n = needle.front().toLatin1();
9971 QVarLengthArray<char>
s(needle.size());
9979 from += haystack.size();
9982 qsizetype adjustedSize = haystack.size() - from;
9983 if (adjustedSize < needle.size())
9985 if (needle.size() == 0)
9990 if (needle.size() == 1) {
9991 Q_ASSERT(haystack.data() !=
nullptr);
9992 if (
auto it = memchr(haystack.data() + from, needle.front().toLatin1(), adjustedSize))
9993 return static_cast<const char *
>(
it) - haystack.data();
9998 return matcher.indexIn(haystack, from);
10015 if (needle.size() <= threshold) {
10016 const auto begin = haystack.begin();
10017 const auto end = haystack.end() - needle.size() + 1;
10019 const qsizetype nlen1 = needle.size() - 1;
10021 it = std::find_if(
it + 1,
end, ciMatch)) {
10024 return std::distance(
begin,
it);
10030 return matcher.indexIn(haystack, from);
10035 return qLastIndexOf(haystack,
QChar(needle), from, cs);
10040 return qLastIndexOf(haystack, from, needle, cs);
10045 return qLastIndexOf(haystack, from, needle, cs);
10050 return qLastIndexOf(haystack, from, needle, cs);
10055 return qLastIndexOf(haystack, from, needle, cs);
10058#if QT_CONFIG(regularexpression)
10061 if (!re.isValid()) {
10067 ? re.match(*stringHaystack, from)
10068 : re.matchView(viewHaystack, from);
10069 if (
match.hasMatch()) {
10072 *rmatch = std::move(
match);
10081 return indexOf(haystack,
nullptr, re, from, rmatch);
10086 if (!re.isValid()) {
10091 qsizetype endpos = (from < 0) ? (viewHaystack.size() + from + 1) : (from + 1);
10093 ? re.globalMatch(*stringHaystack)
10094 : re.globalMatchView(viewHaystack);
10099 if (
start < endpos) {
10102 *rmatch = std::move(
match);
10113 return lastIndexOf(haystack,
nullptr, re, from, rmatch);
10118 if (!re.isValid()) {
10123 ? re.match(*stringHaystack)
10124 : re.matchView(viewHaystack);
10126 if (hasMatch && rmatch)
10127 *rmatch = std::move(
m);
10133 return contains(haystack,
nullptr, re, rmatch);
10138 if (!re.isValid()) {
10147 if (!
match.hasMatch())
10176 const auto pos = std::u16string_view(*this).find_first_of(u
"<>&\"");
10177 if (
pos == std::u16string_view::npos)
10186 else if (
ch == u
'>')
10188 else if (
ch == u
'&')
10189 rich +=
"&"_L1;
10190 else if (
ch == u
'"')
10191 rich +=
"""_L1;
10243#if QT_DEPRECATED_SINCE(6, 8)
static Q_CORE_EXPORT int compare(QAnyStringView lhs, QAnyStringView rhs, Qt::CaseSensitivity cs=Qt::CaseSensitive) noexcept
Compares the string view lhs with the string view rhs and returns a negative integer if lhs is less t...
static Q_CORE_EXPORT bool equal(QAnyStringView lhs, QAnyStringView rhs) noexcept
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
bool isNull() const noexcept
Returns true if this byte array is null; otherwise returns false.
static int defaultCompare(QStringView s1, QStringView s2)
\inmodule QtCore\reentrant
constexpr QLatin1Char front() const
int compare(QStringView other, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
constexpr qsizetype size() const noexcept
void append(parameter_type t)
@ IncludeTrailingZeroesAfterDot
@ OmitLeadingZeroInExponent
\inmodule QtCore \reentrant
\inmodule QtCore \reentrant
bool hasMatch() const
Returns true if the regular expression matched against the subject string, or false otherwise.
\inmodule QtCore \reentrant
QRegularExpressionMatchIterator globalMatchView(QStringView subjectView, qsizetype offset=0, MatchType matchType=NormalMatch, MatchOptions matchOptions=NoMatchOption) const
QRegularExpressionMatchIterator globalMatch(const QString &subject, qsizetype offset=0, MatchType matchType=NormalMatch, MatchOptions matchOptions=NoMatchOption) const
Attempts to perform a global match of the regular expression against the given subject string,...
const_iterator constBegin() const noexcept
Q_CORE_EXPORT double toDouble(bool *ok=nullptr) const
Returns the string view converted to a double value.
Q_CORE_EXPORT float toFloat(bool *ok=nullptr) const
Returns the string view converted to a float value.
constexpr bool isEmpty() const noexcept
Returns whether this string view is empty - that is, whether {size() == 0}.
constexpr QStringView first(qsizetype n) const noexcept
Q_CORE_EXPORT QList< QStringView > split(QStringView sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the view into substring views wherever sep occurs, and returns the list of those string views.
constexpr QStringView sliced(qsizetype pos) const noexcept
\macro QT_RESTRICTED_CAST_FROM_ASCII
iterator begin()
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first character in the string.
QByteArray toLatin1() const &
QString repeated(qsizetype times) const
double toDouble(bool *ok=nullptr) const
Returns the string converted to a double value.
void resizeForOverwrite(qsizetype size)
qsizetype indexOf(QLatin1StringView s, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
QString & fill(QChar c, qsizetype size=-1)
Sets every character in the string to character ch.
QString & replace(qsizetype i, qsizetype len, QChar after)
QString rightJustified(qsizetype width, QChar fill=u' ', bool trunc=false) const
Returns a string of size() width that contains the fill character followed by the string.
void chop(qsizetype n)
Removes n characters from the end of the string.
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
const ushort * utf16() const
Returns the QString as a '\0\'-terminated array of unsigned shorts.
QStringList split(const QString &sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the string into substrings wherever sep occurs, and returns the list of those strings.
void truncate(qsizetype pos)
Truncates the string at the given position index.
QString mid(qsizetype position, qsizetype n=-1) const &
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QString fromUtf16(const char16_t *, qsizetype size=-1)
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
static QString fromUcs4(const char32_t *, qsizetype size=-1)
void clear()
Clears the contents of the string and makes it null.
const QChar * constData() const
Returns a pointer to the data stored in the QString.
const_iterator cbegin() const
QString & operator=(QChar c)
bool isNull() const
Returns true if this string is null; otherwise returns false.
QString & setUnicode(const QChar *unicode, qsizetype size)
Resizes the string to size characters and copies unicode into the string.
QList< uint > toUcs4() const
qsizetype size() const noexcept
Returns the number of characters in this string.
const_iterator cend() const
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool isLower() const
Returns true if the string is lowercase, that is, it's identical to its toLower() folding.
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
@ SectionIncludeLeadingSep
@ SectionIncludeTrailingSep
void swap(QString &other) noexcept
QString section(QChar sep, qsizetype start, qsizetype end=-1, SectionFlags flags=SectionDefault) const
This function returns a section of the string.
static QString fromRawData(const QChar *, qsizetype size)
Constructs a QString that uses the first size Unicode characters in the array unicode.
constexpr QString() noexcept
Constructs a null string.
qsizetype capacity() const
Returns the maximum number of characters that can be stored in the string without forcing a reallocat...
iterator end()
Returns an \l{STL-style iterators}{STL-style iterator} pointing just after the last character in the ...
QString leftJustified(qsizetype width, QChar fill=u' ', bool trunc=false) const
Returns a string of size width that contains this string padded by the fill character.
QString & assign(QAnyStringView s)
bool isUpper() const
Returns true if the string is uppercase, that is, it's identical to its toUpper() folding.
float toFloat(bool *ok=nullptr) const
Returns the string converted to a float value.
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
int compare(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
QString & insert(qsizetype i, QChar c)
friend qsizetype erase(QString &s, const T &t)
QByteArray toLocal8Bit() const &
QChar * data()
Returns a pointer to the data stored in the QString.
qsizetype count(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
static QString vasprintf(const char *format, va_list ap) Q_ATTRIBUTE_FORMAT_PRINTF(1
bool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString & append(QChar c)
int localeAwareCompare(const QString &s) const
bool isRightToLeft() const
Returns true if the string is read right to left.
QString & setNum(short, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString & setRawData(const QChar *unicode, qsizetype size)
QString & remove(qsizetype i, qsizetype len)
Removes n characters from the string, starting at the given position index, and returns a reference t...
const_iterator constBegin() const
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first character in the st...
static QString static QString asprintf(const char *format,...) Q_ATTRIBUTE_FORMAT_PRINTF(1
QString toHtmlEscaped() const
NormalizationForm
This enum describes the various normalized forms of Unicode text.
const QChar * unicode() const
Returns a Unicode representation of the string.
QString normalized(NormalizationForm mode, QChar::UnicodeVersion version=QChar::Unicode_Unassigned) const
Returns the string in the given Unicode normalization mode, according to the given version of the Uni...
qsizetype length() const noexcept
Returns the number of characters in this string.
void resize(qsizetype size)
Sets the size of the string to size characters.
\inmodule QtCore \title Classes and helpers for defining comparison operators \keyword qtcompare
list append(new Employee("Blackpool", "Stephen"))
cache insert(employee->id(), employee)
QSet< QString >::iterator it
typename C::iterator iterator
Combined button and popup list for selecting options.
static QString convertCase(T &str, QUnicodeTables::Case which)
static Q_NEVER_INLINE QString detachAndConvertCase(T &str, QStringIterator it, QUnicodeTables::Case which)
static Q_DECL_CONST_FUNCTION const Properties * qGetProp(char32_t ucs4) noexcept
static constexpr NormalizationCorrection uc_normalization_corrections[]
@ NormalizationCorrectionsVersionMax
constexpr bool isAsciiDigit(char32_t c) noexcept
constexpr bool isAsciiUpper(char32_t c) noexcept
constexpr int qt_lencmp(qsizetype lhs, qsizetype rhs) noexcept
constexpr char toAsciiLower(char ch) noexcept
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype lastIndexOf(QByteArrayView haystack, qsizetype from, char needle) noexcept
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool endsWith(QByteArrayView haystack, QByteArrayView needle) noexcept
Q_CORE_EXPORT QString convertToQString(QAnyStringView s)
static constexpr bool q_points_into_range(const T *p, const T *b, const T *e, Cmp less={}) noexcept
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isLower(QStringView s) noexcept
Q_CORE_EXPORT QList< uint > convertToUcs4(QStringView str)
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isValidUtf16(QStringView s) noexcept
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QByteArrayView trimmed(QByteArrayView s) noexcept
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QByteArrayView haystack, QByteArrayView needle) noexcept
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype count(QByteArrayView haystack, QByteArrayView needle) noexcept
Q_CORE_EXPORT QByteArray convertToLocal8Bit(QStringView str)
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool equalStrings(QStringView lhs, QStringView rhs) noexcept
qsizetype findString(QStringView str, qsizetype from, QChar needle, Qt::CaseSensitivity cs=Qt::CaseSensitive) noexcept
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isRightToLeft(QStringView string) noexcept
Q_CORE_EXPORT QByteArray convertToLatin1(QStringView str)
Q_CORE_EXPORT QString argToQString(QStringView pattern, size_t n, const ArgBase **args)
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype qustrnlen(const char16_t *str, qsizetype maxlen) noexcept
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int compareStrings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs=Qt::CaseSensitive) noexcept
qsizetype indexOf(const QList< V > &list, const U &u, qsizetype from) noexcept
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isAscii(QLatin1StringView s) noexcept
Q_CORE_EXPORT QByteArray convertToUtf8(QStringView str)
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype qustrlen(const char16_t *str) noexcept
constexpr bool isLatin1(QLatin1StringView s) noexcept
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION const char16_t * qustrcasechr(QStringView str, char16_t ch) noexcept
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool isUpper(QStringView s) noexcept
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION const char16_t * qustrchr(QStringView str, char16_t ch) noexcept
constexpr Qt::strong_ordering compareThreeWay(LeftInt lhs, RightInt rhs) noexcept
constexpr Initialization Uninitialized
QT_POPCOUNT_RELAXED_CONSTEXPR uint qCountLeadingZeroBits(quint32 v) noexcept
constexpr uint qCountTrailingZeroBits(quint32 v) noexcept
static jboolean copy(JNIEnv *, jobject)
size_t qstrlen(const char *str)
size_t qstrnlen(const char *str, size_t maxlen)
void qt_to_latin1_unchecked(uchar *dst, const char16_t *uc, qsizetype len)
static void canonicalOrderHelper(QString *str, QChar::UnicodeVersion version, qsizetype from)
static auto fullConvertCase(char32_t uc, QUnicodeTables::Case which) noexcept
static void decomposeHelper(QString *str, bool canonical, QChar::UnicodeVersion version, qsizetype from)
static void composeHelper(QString *str, QChar::UnicodeVersion version, qsizetype from)
static bool normalizationQuickCheckHelper(QString *str, QString::NormalizationForm mode, qsizetype from, qsizetype *lastStable)
static char32_t foldCase(const char16_t *ch, const char16_t *start)
#define Q_DECL_COLD_FUNCTION
AudioChannelLayoutTag tag
bool comparesEqual(const QDir &lhs, const QDir &rhs)
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
QT_BEGIN_NAMESPACE Q_ALWAYS_INLINE void qToUnaligned(const T src, void *dest)
static ControlElement< T > * ptr(QWidget *widget)
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qMax(const T &a, const T &b)
constexpr T qAbs(const T &t)
static Q_DECL_CONST_FUNCTION bool qt_is_finite(double d)
static bool contains(const QJsonArray &haystack, unsigned needle)
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s1
GLenum GLuint GLenum GLsizei length
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLint GLsizei GLsizei GLenum format
GLsizei GLenum const void * indices
GLfloat GLfloat GLfloat GLfloat h
GLsizei GLsizei GLchar * source
GLenum GLenum GLenum input
GLenum GLint GLint * precision
GLsizei const GLchar *const * string
[0]
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
static void split(QT_FT_Vector *b)
Q_DECL_COLD_FUNCTION void qtWarnAboutInvalidRegularExpression(const QString &pattern, const char *where)
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
static constexpr QChar sep
static const uint64_t qCompilerCpuFeatures
QSpan(It, EndOrSize) -> QSpan< std::remove_reference_t< q20::iter_reference_t< It > > >
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
static QString argToQStringImpl(StringView pattern, size_t numArgs, const QtPrivate::ArgBase **args)
static bool isAscii_helper(const char16_t *&ptr, const char16_t *end)
static Int toIntegral(QStringView string, bool *ok, int base)
void qt_to_latin1(uchar *dst, const char16_t *src, qsizetype length)
static void append_utf8(QString &qs, const char *cs, qsizetype len)
#define ATTRIBUTE_NO_SANITIZE
bool qt_is_ascii(const char *&ptr, const char *end) noexcept
static void replace_in_place(QString &str, QSpan< size_t > indices, qsizetype blen, QStringView after)
static bool checkCase(QStringView s, QUnicodeTables::Case c) noexcept
static void replace_helper(QString &str, QSpan< size_t > indices, qsizetype blen, QStringView after)
static int ucstrcmp(const char16_t *a, size_t alen, const Char2 *b, size_t blen)
static void removeStringImpl(QString &s, const T &needle, Qt::CaseSensitivity cs)
Q_ALWAYS_INLINE QString to_string(QLatin1StringView s) noexcept
static bool needsReallocate(const QString &str, qsizetype newSize)
static int qArgDigitValue(QChar ch) noexcept
static void replace_with_copy(QString &str, QSpan< size_t > indices, qsizetype blen, QStringView after)
static int ucstrncmp(const char16_t *a, const char16_t *b, size_t l)
static QByteArray qt_convert_to_latin1(QStringView string)
static bool ucstreq(const char16_t *a, size_t alen, const Char2 *b)
static QList< uint > qt_convert_to_ucs4(QStringView string)
qsizetype qFindStringBoyerMoore(QStringView haystack, qsizetype from, QStringView needle, Qt::CaseSensitivity cs)
static QByteArray qt_convert_to_local_8bit(QStringView string)
static LengthMod parse_length_modifier(const char *&c) noexcept
static ArgEscapeData findArgEscapes(QStringView s)
static QByteArray qt_convert_to_utf8(QStringView str)
static void qt_to_latin1_internal(uchar *dst, const char16_t *src, qsizetype length)
static void insert_helper(QString &str, qsizetype i, const T &toInsert)
static int latin1nicmp(const char *lhsChar, qsizetype lSize, const char *rhsChar, qsizetype rSize)
static QString replaceArgEscapes(QStringView s, const ArgEscapeData &d, qsizetype field_width, QStringView arg, QStringView larg, QChar fillChar)
static QVarLengthArray< char16_t > qt_from_latin1_to_qvla(QLatin1StringView str)
static Q_NEVER_INLINE int ucstricmp8(const char *utf8, const char *utf8end, const QChar *utf16, const QChar *utf16end)
void qt_string_normalize(QString *data, QString::NormalizationForm mode, QChar::UnicodeVersion version, qsizetype from)
static uint parse_flag_characters(const char *&c) noexcept
static Q_NEVER_INLINE int ucstricmp(qsizetype alen, const char16_t *a, qsizetype blen, const char16_t *b)
#define CSTR_GREATER_THAN
static char16_t to_unicode(const QChar c)
Q_CORE_EXPORT void qt_from_latin1(char16_t *dst, const char *str, size_t size) noexcept
static int getEscape(const Char *uc, qsizetype *pos, qsizetype len)
static bool can_consume(const char *&c, char ch) noexcept
static int parse_field_width(const char *&c, qsizetype size)
#define qUtf16Printable(string)
static char * toLocal8Bit(char *out, QStringView in, QStringConverter::State *state)
QBasicUtf8StringView< false > QUtf8StringView
QStringView qToStringViewIgnoringNull(const QStringLike &s) noexcept
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
#define Q_DECLARE_TYPEINFO(TYPE, FLAGS)
unsigned long long quint64
Qt::weak_ordering compareThreeWay(const QUrl &lhs, const QUrl &rhs)
static QString escape(const QString &input)
static double toDouble(Value v)
QVarLengthArray(InputIterator, InputIterator) -> QVarLengthArray< ValueType >
QT_BEGIN_NAMESPACE typedef uchar * output
Q_CHECK_PTR(a=new int[80])
settings remove("monkey")
QTextStream out(stdout)
[7]
static const auto matcher
[0]
qsizetype locale_occurrences
static void appendLatin1To(QLatin1StringView in, QChar *out) noexcept
void detachAndGrow(QArrayData::GrowthPosition where, qsizetype n, const T **data, QArrayDataPointer *old)
qsizetype freeSpaceAtBegin() const noexcept
bool needsDetach() const noexcept
bool isMutable() const noexcept
\inmodule QtCore \reentrant
constexpr char16_t unicode() const noexcept
Converts a Latin-1 character to an 16-bit-encoded Unicode representation of the character.
static char16_t * convertToUnicode(char16_t *dst, QLatin1StringView in) noexcept
static char * convertFromUnicode(char *out, QStringView in, QStringConverter::State *state) noexcept
static float convertDoubleToFloat(double d, bool *ok)
static const QLocaleData * c()
static QSimpleParsedNumber< quint64 > bytearrayToUnsLongLong(QByteArrayView num, int base)
static Q_CORE_EXPORT QSimpleParsedNumber< qint64 > bytearrayToLongLong(QByteArrayView num, int base)
static TrimPositions trimmed_helper_positions(const StringType &str)
static StringType trimmed_helper(StringType &str)
static StringType simplified_helper(StringType &str)
static QChar * convertToUnicode(QChar *out, QByteArrayView, QStringConverter::State *state, DataEndianness endian)
static Q_CORE_EXPORT QByteArray convertFromUnicode(QStringView in)
static int compareUtf8(QByteArrayView utf8, QStringView utf16, Qt::CaseSensitivity cs=Qt::CaseSensitive) noexcept
static QChar * convertToUnicode(QChar *buffer, QByteArrayView in) noexcept
static auto matcher(char ch)
static int difference(char lhs, char rhs)