uint32_t miniVarTop; if((settings.options & CollationSettings::ALTERNATE_MASK) == 0) { // No mini primaries are variable, set a variableTop just below the // lowest long mini primary.
miniVarTop = MIN_LONG - 1;
} else {
int32_t headerLength = *table & 0xff;
int32_t i = 1 + settings.getMaxVariable(); if(i >= headerLength) { return -1; // variableTop >= digits, should not occur
}
miniVarTop = table[i];
}
UBool digitsAreReordered = false; if(settings.hasReordering()) {
uint32_t prevStart = 0;
uint32_t beforeDigitStart = 0;
uint32_t digitStart = 0;
uint32_t afterDigitStart = 0; for(int32_t group = UCOL_REORDER_CODE_FIRST;
group < UCOL_REORDER_CODE_FIRST + CollationData::MAX_NUM_SPECIAL_REORDER_CODES;
++group) {
uint32_t start = data->getFirstPrimaryForGroup(group);
start = settings.reorder(start); if(group == UCOL_REORDER_CODE_DIGIT) {
beforeDigitStart = prevStart;
digitStart = start;
} elseif(start != 0) { if(start < prevStart) { // The permutation affects the groups up to Latin. return -1;
} // In the future, there might be a special group between digits & Latin. if(digitStart != 0 && afterDigitStart == 0 && prevStart == beforeDigitStart) {
afterDigitStart = start;
}
prevStart = start;
}
}
uint32_t latinStart = data->getFirstPrimaryForGroup(USCRIPT_LATIN);
latinStart = settings.reorder(latinStart); if(latinStart < prevStart) { return -1;
} if(afterDigitStart == 0) {
afterDigitStart = latinStart;
} if(!(beforeDigitStart < digitStart && digitStart < afterDigitStart)) {
digitsAreReordered = true;
}
}
table += (table[0] & 0xff); // skip the header for(UChar32 c = 0; c < LATIN_LIMIT; ++c) {
uint32_t p = table[c]; if(p >= MIN_SHORT) {
p &= SHORT_PRIMARY_MASK;
} elseif(p > miniVarTop) {
p &= LONG_PRIMARY_MASK;
} else {
p = 0;
}
primaries[c] = static_cast<uint16_t>(p);
} if(digitsAreReordered || (settings.options & CollationSettings::NUMERIC) != 0) { // Bail out for digits. for(UChar32 c = 0x30; c <= 0x39; ++c) { primaries[c] = 0; }
}
// Shift the miniVarTop above other options. return (static_cast<int32_t>(miniVarTop) << 16) | settings.options;
}
int32_t
CollationFastLatin::compareUTF16(const uint16_t *table, const uint16_t *primaries, int32_t options, const char16_t *left, int32_t leftLength, const char16_t *right, int32_t rightLength) { // This is a modified copy of CollationCompare::compareUpToQuaternary(), // optimized for common Latin text. // Keep them in sync! // Keep compareUTF16() and compareUTF8() in sync very closely!
U_ASSERT((table[0] >> 8) == VERSION);
table += (table[0] & 0xff); // skip the header
uint32_t variableTop = static_cast<uint32_t>(options) >> 16; // see getOptions()
options &= 0xffff; // needed for CollationSettings::getStrength() to work
// Check for supported characters, fetch mini CEs, and compare primaries.
int32_t leftIndex = 0, rightIndex = 0; /** * Single mini CE or a pair. * The current mini CE is in the lower 16 bits, the next one is in the upper 16 bits. * If there is only one, then it is in the lower bits, and the upper bits are 0.
*/
uint32_t leftPair = 0, rightPair = 0; for(;;) { // We fetch CEs until we get a non-ignorable primary or reach the end. while(leftPair == 0) { if(leftIndex == leftLength) {
leftPair = EOS; break;
}
UChar32 c = left[leftIndex++]; if(c <= LATIN_MAX) {
leftPair = primaries[c]; if(leftPair != 0) { break; } if(c <= 0x39 && c >= 0x30 && (options & CollationSettings::NUMERIC) != 0) { return BAIL_OUT_RESULT;
}
leftPair = table[c];
} elseif(PUNCT_START <= c && c < PUNCT_LIMIT) {
leftPair = table[c - PUNCT_START + LATIN_LIMIT];
} else {
leftPair = lookup(table, c);
} if(leftPair >= MIN_SHORT) {
leftPair &= SHORT_PRIMARY_MASK; break;
} elseif(leftPair > variableTop) {
leftPair &= LONG_PRIMARY_MASK; break;
} else {
leftPair = nextPair(table, c, leftPair, left, nullptr, leftIndex, leftLength); if(leftPair == BAIL_OUT) { return BAIL_OUT_RESULT; }
leftPair = getPrimaries(variableTop, leftPair);
}
}
if(leftPair == rightPair) { if(leftPair == EOS) { break; }
leftPair = rightPair = 0; continue;
}
uint32_t leftPrimary = leftPair & 0xffff;
uint32_t rightPrimary = rightPair & 0xffff; if(leftPrimary != rightPrimary) { // Return the primary difference. return (leftPrimary < rightPrimary) ? UCOL_LESS : UCOL_GREATER;
} if(leftPair == EOS) { break; }
leftPair >>= 16;
rightPair >>= 16;
} // In the following, we need to re-fetch each character because we did not buffer the CEs, // but we know that the string is well-formed and // only contains supported characters and mappings.
// We might skip the secondary level but continue with the case level // which is turned on separately. if(CollationSettings::getStrength(options) >= UCOL_SECONDARY) {
leftIndex = rightIndex = 0;
leftPair = rightPair = 0; for(;;) { while(leftPair == 0) { if(leftIndex == leftLength) {
leftPair = EOS; break;
}
UChar32 c = left[leftIndex++]; if(c <= LATIN_MAX) {
leftPair = table[c];
} elseif(PUNCT_START <= c && c < PUNCT_LIMIT) {
leftPair = table[c - PUNCT_START + LATIN_LIMIT];
} else {
leftPair = lookup(table, c);
} if(leftPair >= MIN_SHORT) {
leftPair = getSecondariesFromOneShortCE(leftPair); break;
} elseif(leftPair > variableTop) {
leftPair = COMMON_SEC_PLUS_OFFSET; break;
} else {
leftPair = nextPair(table, c, leftPair, left, nullptr, leftIndex, leftLength);
leftPair = getSecondaries(variableTop, leftPair);
}
}
// Remove the case bits from the tertiary weight when caseLevel is on or caseFirst is off.
UBool withCaseBits = CollationSettings::isTertiaryWithCaseBits(options);
int32_t
CollationFastLatin::compareUTF8(const uint16_t *table, const uint16_t *primaries, int32_t options, const uint8_t *left, int32_t leftLength, const uint8_t *right, int32_t rightLength) { // Keep compareUTF16() and compareUTF8() in sync very closely!
U_ASSERT((table[0] >> 8) == VERSION);
table += (table[0] & 0xff); // skip the header
uint32_t variableTop = static_cast<uint32_t>(options) >> 16; // see RuleBasedCollator::getFastLatinOptions()
options &= 0xffff; // needed for CollationSettings::getStrength() to work
// Check for supported characters, fetch mini CEs, and compare primaries.
int32_t leftIndex = 0, rightIndex = 0; /** * Single mini CE or a pair. * The current mini CE is in the lower 16 bits, the next one is in the upper 16 bits. * If there is only one, then it is in the lower bits, and the upper bits are 0.
*/
uint32_t leftPair = 0, rightPair = 0; // Note: There is no need to assemble the code point. // We only need to look up the table entry for the character, // and nextPair() looks for whether c==0. for(;;) { // We fetch CEs until we get a non-ignorable primary or reach the end. while(leftPair == 0) { if(leftIndex == leftLength) {
leftPair = EOS; break;
}
UChar32 c = left[leftIndex++];
uint8_t t; if(c <= 0x7f) {
leftPair = primaries[c]; if(leftPair != 0) { break; } if(c <= 0x39 && c >= 0x30 && (options & CollationSettings::NUMERIC) != 0) { return BAIL_OUT_RESULT;
}
leftPair = table[c];
} elseif(c <= LATIN_MAX_UTF8_LEAD && 0xc2 <= c && leftIndex != leftLength &&
0x80 <= (t = left[leftIndex]) && t <= 0xbf) {
++leftIndex;
c = ((c - 0xc2) << 6) + t;
leftPair = primaries[c]; if(leftPair != 0) { break; }
leftPair = table[c];
} else {
leftPair = lookupUTF8(table, c, left, leftIndex, leftLength);
} if(leftPair >= MIN_SHORT) {
leftPair &= SHORT_PRIMARY_MASK; break;
} elseif(leftPair > variableTop) {
leftPair &= LONG_PRIMARY_MASK; break;
} else {
leftPair = nextPair(table, c, leftPair, nullptr, left, leftIndex, leftLength); if(leftPair == BAIL_OUT) { return BAIL_OUT_RESULT; }
leftPair = getPrimaries(variableTop, leftPair);
}
}
if(leftPair == rightPair) { if(leftPair == EOS) { break; }
leftPair = rightPair = 0; continue;
}
uint32_t leftPrimary = leftPair & 0xffff;
uint32_t rightPrimary = rightPair & 0xffff; if(leftPrimary != rightPrimary) { // Return the primary difference. return (leftPrimary < rightPrimary) ? UCOL_LESS : UCOL_GREATER;
} if(leftPair == EOS) { break; }
leftPair >>= 16;
rightPair >>= 16;
} // In the following, we need to re-fetch each character because we did not buffer the CEs, // but we know that the string is well-formed and // only contains supported characters and mappings.
// Remove the case bits from the tertiary weight when caseLevel is on or caseFirst is off.
UBool withCaseBits = CollationSettings::isTertiaryWithCaseBits(options);
uint32_t
CollationFastLatin::getCases(uint32_t variableTop, UBool strengthIsPrimary, uint32_t pair) { // Primary+caseLevel: Ignore case level weights of primary ignorables. // Otherwise: Ignore case level weights of secondary ignorables. // For details see the comments in the CollationCompare class. // Tertiary CEs (secondary ignorables) are not supported in fast Latin. if(pair <= 0xffff) { // one mini CE if(pair >= MIN_SHORT) { // A high secondary weight means we really have two CEs, // a primary CE and a secondary CE.
uint32_t ce = pair;
pair &= CASE_MASK; // explicit weight of primary CE if(!strengthIsPrimary && (ce & SECONDARY_MASK) >= MIN_SEC_HIGH) {
pair |= LOWER_CASE << 16; // implied weight of secondary CE
}
} elseif(pair > variableTop) {
pair = LOWER_CASE;
} elseif(pair >= MIN_LONG) {
pair = 0; // variable
} // else special mini CE
} else { // two mini CEs, same primary groups, neither expands like above
uint32_t ce = pair & 0xffff; if(ce >= MIN_SHORT) { if(strengthIsPrimary && (pair & (SHORT_PRIMARY_MASK << 16)) == 0) {
pair &= CASE_MASK;
} else {
pair &= TWO_CASES_MASK;
}
} elseif(ce > variableTop) {
pair = TWO_LOWER_CASES;
} else {
U_ASSERT(ce >= MIN_LONG);
pair = 0; // variable
}
} return pair;
}
uint32_t
CollationFastLatin::getTertiaries(uint32_t variableTop, UBool withCaseBits, uint32_t pair) { if(pair <= 0xffff) { // one mini CE if(pair >= MIN_SHORT) { // A high secondary weight means we really have two CEs, // a primary CE and a secondary CE.
uint32_t ce = pair; if(withCaseBits) {
pair = (pair & CASE_AND_TERTIARY_MASK) + TER_OFFSET; if((ce & SECONDARY_MASK) >= MIN_SEC_HIGH) {
pair |= (LOWER_CASE | COMMON_TER_PLUS_OFFSET) << 16;
}
} else {
pair = (pair & TERTIARY_MASK) + TER_OFFSET; if((ce & SECONDARY_MASK) >= MIN_SEC_HIGH) {
pair |= COMMON_TER_PLUS_OFFSET << 16;
}
}
} elseif(pair > variableTop) {
pair = (pair & TERTIARY_MASK) + TER_OFFSET; if(withCaseBits) {
pair |= LOWER_CASE;
}
} elseif(pair >= MIN_LONG) {
pair = 0; // variable
} // else special mini CE
} else { // two mini CEs, same primary groups, neither expands like above
uint32_t ce = pair & 0xffff; if(ce >= MIN_SHORT) { if(withCaseBits) {
pair &= TWO_CASES_MASK | TWO_TERTIARIES_MASK;
} else {
pair &= TWO_TERTIARIES_MASK;
}
pair += TWO_TER_OFFSETS;
} elseif(ce > variableTop) {
pair = (pair & TWO_TERTIARIES_MASK) + TWO_TER_OFFSETS; if(withCaseBits) {
pair |= TWO_LOWER_CASES;
}
} else {
U_ASSERT(ce >= MIN_LONG);
pair = 0; // variable
}
} return pair;
}
uint32_t
CollationFastLatin::getQuaternaries(uint32_t variableTop, uint32_t pair) { // Return the primary weight of a variable CE, // or the maximum primary weight for a non-variable, not-completely-ignorable CE. if(pair <= 0xffff) { // one mini CE if(pair >= MIN_SHORT) { // A high secondary weight means we really have two CEs, // a primary CE and a secondary CE. if((pair & SECONDARY_MASK) >= MIN_SEC_HIGH) {
pair = TWO_SHORT_PRIMARIES_MASK;
} else {
pair = SHORT_PRIMARY_MASK;
}
} elseif(pair > variableTop) {
pair = SHORT_PRIMARY_MASK;
} elseif(pair >= MIN_LONG) {
pair &= LONG_PRIMARY_MASK; // variable
} // else special mini CE
} else { // two mini CEs, same primary groups, neither expands like above
uint32_t ce = pair & 0xffff; if(ce > variableTop) {
pair = TWO_SHORT_PRIMARIES_MASK;
} else {
U_ASSERT(ce >= MIN_LONG);
pair &= TWO_LONG_PRIMARIES_MASK; // variable
}
} return pair;
}
U_NAMESPACE_END
#endif// !UCONFIG_NO_COLLATION
Messung V0.5
¤ Dauer der Verarbeitung: 0.19 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.