11 const auto*
p = (
const unsigned char*)data.data();
12 const unsigned char*
const end =
p + data.size();
15 int code_point_length = std::countl_one(*
p);
17 switch (code_point_length)
19 case 0:
p++;
continue;
24 default:
return false;
30 if (end < code_point_length +
p)
36 switch (code_point_length)
39 if (std::countl_one(
p[3]) != 1)
45 if (std::countl_one(
p[2]) != 1)
51 if (std::countl_one(
p[1]) != 1)
60 switch (code_point_length)
64 if (*
p == 0xC0 || *
p == 0xC1)
72 if (
p[0] == 0xED &&
p[1] >= 0xA0)
77 if (
p[0] == 0xE0 &&
p[1] < 0xA0)
86 if (*
p > 0xF4 || (
p[0] == 0xF4 &&
p[1] >= 0x90))
91 if (
p[0] == 0xF0 &&
p[1] < 0x90)
99 p += code_point_length;
127 if (caseSensitivity == Qt::CaseSensitive)
138 const QChar* currA = a.unicode();
139 const QChar* currB = b.unicode();
143 return std::strong_ordering::equal;
146 while (!currA->isNull() && !currB->isNull())
148 const QChar* begSeqA = currA;
149 const QChar* begSeqB = currB;
151 if (currA->unicode() == QChar::ObjectReplacementCharacter)
152 return std::strong_ordering::greater;
153 if (currB->unicode() == QChar::ObjectReplacementCharacter)
154 return std::strong_ordering::less;
156 if (currA->unicode() == QChar::ReplacementCharacter)
157 return std::strong_ordering::greater;
158 if (currB->unicode() == QChar::ReplacementCharacter)
159 return std::strong_ordering::less;
162 while (!currA->isNull() && !currA->isDigit() && !currA->isPunct() &&
168 while (!currB->isNull() && !currB->isDigit() && !currB->isPunct() &&
175 const QString& subA(a.mid(begSeqA - a.unicode(), currA - begSeqA));
176 const QString& subB(b.mid(begSeqB - b.unicode(), currB - begSeqB));
177 int cmp = QString::localeAwareCompare(subA, subB);
179 return cmp < 0 ? std::strong_ordering::less : std::strong_ordering::greater;
181 if (currA->isNull() || currB->isNull())
185 while ((currA->isPunct() || currA->isSpace()) &&
186 (currB->isPunct() || currB->isSpace()))
188 auto cmp2 = (currA->unicode() <=> currB->unicode());
193 if (currA->isNull() || currB->isNull())
200 if ((*currA == QLatin1Char(
'0')) || (*currB == QLatin1Char(
'0')))
206 if (!currA->isDigit() && !currB->isDigit())
208 if (!currA->isDigit())
209 return std::strong_ordering::greater;
210 if (!currB->isDigit())
211 return std::strong_ordering::less;
212 auto cmp2 = (currA->unicode() <=> currB->unicode());
228 bool isFirstRun =
true;
229 std::strong_ordering weight = std::strong_ordering::equal;
233 if (!currA->isDigit() && !currB->isDigit())
239 if (!currA->isDigit())
242 return currA->unicode() <=> currB->unicode();
243 return std::strong_ordering::less;
245 if (!currB->isDigit())
248 return currA->unicode() <=> currB->unicode();
249 return std::strong_ordering::greater;
252 weight = (currA->unicode() <=> currB->unicode());
260 if (currA->isNull() && currB->isNull())
262 if (caseSensitivity == Qt::CaseSensitive)
263 return std::strong_ordering::equal;
264 return std::strong_ordering::equivalent;
267 return currA->isNull() ? std::strong_ordering::less : std::strong_ordering::greater;
286 return QObject::tr(
"%1 TB").arg(sizeTB, 0,
'f', (sizeTB>10)?0:precision);
291 return QObject::tr(
"%1 GB").arg(sizeGB, 0,
'f', (sizeGB>10)?0:precision);
296 return QObject::tr(
"%1 MB").arg(sizeMB, 0,
'f', (sizeMB>10)?0:precision);
299 return QObject::tr(
"%1 KB").arg(sizeKB);
306 return QString(
"%1 B").arg(sizeB);
MBASE_PUBLIC bool isValidUTF8(const QByteArray &data)
MBASE_PUBLIC std::strong_ordering naturalCompare(const QString &_a, const QString &_b, Qt::CaseSensitivity caseSensitivity=Qt::CaseSensitive)
This method chops the input a and b into pieces of digits and non-digits (a1.05 becomes a | 1 | .
MBASE_PUBLIC QString formatBytes(int64_t sizeB, int prec=1)
MBASE_PUBLIC QString formatKBytes(int64_t sizeKB, int prec=1)
static constexpr int64_t kOneTerabyte
static constexpr int64_t kOneGigabyte
static constexpr int64_t kOneMegabyte