[2/2] Implement Unicode Normalization Form Quick Check (NF QC)
Use QuickCheck data from DerivedNormalizationProps.txt to check if the input text is already in the desired Normalization Form. \sa http://www.unicode.org/reports/tr15/#Detecting_Normalization_Forms Using NF QC makes a significant boost to most operations that rely on normalized input data, i.e. file path conversions on Mac, where "native" form is a decomposed Unicode string. Change-Id: I292a9da479c6beed730528fc7000c45bf1befc34 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>bb10
parent
252bad7c58
commit
2e0a4b13ad
|
|
@ -1884,4 +1884,65 @@ static void canonicalOrderHelper(QString *str, QChar::UnicodeVersion version, in
|
|||
}
|
||||
}
|
||||
|
||||
// returns true if the text is in a desired Normalization Form already; false otherwise.
|
||||
// sets lastStable to the position of the last stable code point
|
||||
static bool normalizationQuickCheckHelper(QString *str, QString::NormalizationForm mode, int from, int *lastStable)
|
||||
{
|
||||
Q_STATIC_ASSERT(QString::NormalizationForm_D == 0);
|
||||
Q_STATIC_ASSERT(QString::NormalizationForm_C == 1);
|
||||
Q_STATIC_ASSERT(QString::NormalizationForm_KD == 2);
|
||||
Q_STATIC_ASSERT(QString::NormalizationForm_KC == 3);
|
||||
|
||||
enum { NFQC_YES = 0, NFQC_NO = 1, NFQC_MAYBE = 3 };
|
||||
|
||||
const ushort *string = reinterpret_cast<const ushort *>(str->constData());
|
||||
int length = str->length();
|
||||
|
||||
// this avoids one out of bounds check in the loop
|
||||
while (length > from && QChar::isHighSurrogate(string[length - 1]))
|
||||
--length;
|
||||
|
||||
uchar lastCombining = 0;
|
||||
for (int i = from; i < length; ++i) {
|
||||
int pos = i;
|
||||
uint uc = string[i];
|
||||
if (uc < 0x80) {
|
||||
// ASCII characters are stable code points
|
||||
lastCombining = 0;
|
||||
*lastStable = pos;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (QChar::isHighSurrogate(uc)) {
|
||||
ushort low = string[i + 1];
|
||||
if (!QChar::isLowSurrogate(low)) {
|
||||
// treat surrogate like stable code point
|
||||
lastCombining = 0;
|
||||
*lastStable = pos;
|
||||
continue;
|
||||
}
|
||||
++i;
|
||||
uc = QChar::surrogateToUcs4(uc, low);
|
||||
}
|
||||
|
||||
const QUnicodeTables::Properties *p = qGetProp(uc);
|
||||
|
||||
if (p->combiningClass < lastCombining && p->combiningClass > 0)
|
||||
return false;
|
||||
|
||||
const uchar check = (p->nfQuickCheck >> (mode << 1)) & 0x03;
|
||||
if (check != NFQC_YES)
|
||||
return false; // ### can we quick check NFQC_MAYBE ?
|
||||
|
||||
lastCombining = p->combiningClass;
|
||||
if (lastCombining == 0)
|
||||
*lastStable = pos;
|
||||
}
|
||||
|
||||
if (length != str->length()) // low surrogate parts at the end of text
|
||||
*lastStable = str->length() - 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -6637,6 +6637,8 @@ void qt_string_normalize(QString *data, QString::NormalizationForm mode, QChar::
|
|||
for (int i = from; i < len; ++i) {
|
||||
if (p[i].unicode() >= 0x80) {
|
||||
simple = false;
|
||||
if (i > from)
|
||||
from = i - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -6679,6 +6681,10 @@ void qt_string_normalize(QString *data, QString::NormalizationForm mode, QChar::
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (normalizationQuickCheckHelper(data, mode, from, &from))
|
||||
return;
|
||||
|
||||
decomposeHelper(data, mode < QString::NormalizationForm_KD, version, from);
|
||||
|
||||
canonicalOrderHelper(data, version, from);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -79,8 +79,9 @@ struct Properties {
|
|||
ushort titleCaseSpecial : 1;
|
||||
ushort caseFoldSpecial : 1;
|
||||
ushort unicodeVersion : 4;
|
||||
ushort graphemeBreakClass : 8; /* 4 used */
|
||||
ushort wordBreakClass : 8; /* 4 used */
|
||||
ushort nfQuickCheck : 8;
|
||||
ushort graphemeBreakClass : 4; /* 4 used */
|
||||
ushort wordBreakClass : 4; /* 4 used */
|
||||
ushort sentenceBreakClass : 8; /* 4 used */
|
||||
ushort lineBreakClass : 8; /* 6 used */
|
||||
ushort script : 8; /* 7 used */
|
||||
|
|
|
|||
Loading…
Reference in New Issue