unsigned calculateStringHashAndLengthFromUTF8(const char* data, const char* dataEnd, unsigned& dataLength, unsigned& utf16Length) { if (!data) return 0; StringHasher stringHasher; dataLength = 0; utf16Length = 0; while (data < dataEnd || (!dataEnd && *data)) { if (isASCII(*data)) { stringHasher.addCharacter(*data++); dataLength++; utf16Length++; continue; } int utf8SequenceLength = inlineUTF8SequenceLengthNonASCII(*data); dataLength += utf8SequenceLength; if (!dataEnd) { for (int i = 1; i < utf8SequenceLength; ++i) { if (!data[i]) return 0; } } else if (dataEnd - data < utf8SequenceLength) return 0; if (!isLegalUTF8(reinterpret_cast<const unsigned char*>(data), utf8SequenceLength)) return 0; UChar32 character = readUTF8Sequence(data, utf8SequenceLength); ASSERT(!isASCII(character)); if (U_IS_BMP(character)) { // UTF-16 surrogate values are illegal in UTF-32 if (U_IS_SURROGATE(character)) return 0; stringHasher.addCharacter(static_cast<UChar>(character)); // normal case utf16Length++; } else if (U_IS_SUPPLEMENTARY(character)) { stringHasher.addCharacters(static_cast<UChar>(U16_LEAD(character)), static_cast<UChar>(U16_TRAIL(character))); utf16Length += 2; } else return 0; } return stringHasher.hash(); }
unsigned FontDescription::styleHashWithoutFamilyList() const { unsigned hash = 0; StringHasher stringHasher; const FontFeatureSettings* settings = featureSettings(); if (settings) { unsigned numFeatures = settings->size(); for (unsigned i = 0; i < numFeatures; ++i) { const AtomicString& tag = settings->at(i).tag(); for (unsigned j = 0; j < tag.length(); j++) stringHasher.addCharacter(tag[j]); addToHash(hash, settings->at(i).value()); } } const FontVariationSettings* varSettings = variationSettings(); if (varSettings) { unsigned numFeatures = varSettings->size(); for (unsigned i = 0; i < numFeatures; ++i) { const AtomicString& tag = varSettings->at(i).tag(); for (unsigned j = 0; j < tag.length(); j++) stringHasher.addCharacter(tag[j]); addToHash(hash, varSettings->at(i).value()); } } if (m_locale) { const AtomicString& locale = m_locale->localeString(); for (unsigned i = 0; i < locale.length(); i++) stringHasher.addCharacter(locale[i]); } addToHash(hash, stringHasher.hash()); addFloatToHash(hash, m_specifiedSize); addFloatToHash(hash, m_computedSize); addFloatToHash(hash, m_adjustedSize); addFloatToHash(hash, m_sizeAdjust); addFloatToHash(hash, m_letterSpacing); addFloatToHash(hash, m_wordSpacing); addToHash(hash, m_fieldsAsUnsigned.parts[0]); addToHash(hash, m_fieldsAsUnsigned.parts[1]); return hash; }
unsigned MappedAttributeHash::hash(const MappedAttributeKey& key) { COMPILE_ASSERT(sizeof(key.name) == 4 || sizeof(key.name) == 8, key_name_size); COMPILE_ASSERT(sizeof(key.value) == 4 || sizeof(key.value) == 8, key_value_size); StringHasher hasher; const UChar* data; data = reinterpret_cast<const UChar*>(&key.name); hasher.addCharacters(data[0], data[1]); if (sizeof(key.name) == 8) hasher.addCharacters(data[2], data[3]); data = reinterpret_cast<const UChar*>(&key.value); hasher.addCharacters(data[0], data[1]); if (sizeof(key.value) == 8) hasher.addCharacters(data[2], data[3]); return hasher.hash(); }
TEST(StringHasherTest, StringHasher_addCharacter) { StringHasher hasher; // Hashing a single character. hasher = StringHasher(); hasher.addCharacter(0); EXPECT_EQ(singleNullCharacterHash, hasher.hash()); EXPECT_EQ(singleNullCharacterHash & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); // Hashing five characters, checking the intermediate state after each is added. hasher = StringHasher(); hasher.addCharacter(testAUChars[0]); EXPECT_EQ(testAHash1, hasher.hash()); EXPECT_EQ(testAHash1 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharacter(testAUChars[1]); EXPECT_EQ(testAHash2, hasher.hash()); EXPECT_EQ(testAHash2 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharacter(testAUChars[2]); EXPECT_EQ(testAHash3, hasher.hash()); EXPECT_EQ(testAHash3 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharacter(testAUChars[3]); EXPECT_EQ(testAHash4, hasher.hash()); EXPECT_EQ(testAHash4 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharacter(testAUChars[4]); EXPECT_EQ(testAHash5, hasher.hash()); EXPECT_EQ(testAHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); // Hashing a second set of five characters, including non-Latin-1 characters. hasher = StringHasher(); hasher.addCharacter(testBUChars[0]); EXPECT_EQ(testBHash1, hasher.hash()); EXPECT_EQ(testBHash1 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharacter(testBUChars[1]); EXPECT_EQ(testBHash2, hasher.hash()); EXPECT_EQ(testBHash2 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharacter(testBUChars[2]); EXPECT_EQ(testBHash3, hasher.hash()); EXPECT_EQ(testBHash3 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharacter(testBUChars[3]); EXPECT_EQ(testBHash4, hasher.hash()); EXPECT_EQ(testBHash4 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharacter(testBUChars[4]); EXPECT_EQ(testBHash5, hasher.hash()); EXPECT_EQ(testBHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); }
TEST(StringHasherTest, StringHasher_addCharactersAssumingAligned) { StringHasher hasher; // Hashing zero characters. hasher = StringHasher(); hasher.addCharactersAssumingAligned(static_cast<LChar*>(0), 0); EXPECT_EQ(emptyStringHash, hasher.hash()); EXPECT_EQ(emptyStringHash & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharactersAssumingAligned(nullLChars, 0); EXPECT_EQ(emptyStringHash, hasher.hash()); EXPECT_EQ(emptyStringHash & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharactersAssumingAligned(static_cast<UChar*>(0), 0); EXPECT_EQ(emptyStringHash, hasher.hash()); EXPECT_EQ(emptyStringHash & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharactersAssumingAligned(nullUChars, 0); EXPECT_EQ(emptyStringHash, hasher.hash()); EXPECT_EQ(emptyStringHash & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); // Hashing one character. hasher = StringHasher(); hasher.addCharactersAssumingAligned(nullLChars, 1); EXPECT_EQ(singleNullCharacterHash, hasher.hash()); EXPECT_EQ(singleNullCharacterHash & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharactersAssumingAligned(nullUChars, 1); EXPECT_EQ(singleNullCharacterHash, hasher.hash()); EXPECT_EQ(singleNullCharacterHash & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); // Hashing five characters, all at once. hasher = StringHasher(); hasher.addCharactersAssumingAligned(testALChars, 5); EXPECT_EQ(testAHash5, hasher.hash()); EXPECT_EQ(testAHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharactersAssumingAligned(testAUChars, 5); EXPECT_EQ(testAHash5, hasher.hash()); EXPECT_EQ(testAHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharactersAssumingAligned(testBUChars, 5); EXPECT_EQ(testBHash5, hasher.hash()); EXPECT_EQ(testBHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); // Hashing five characters, in groups of two, then the last one. hasher = StringHasher(); hasher.addCharactersAssumingAligned(testALChars, 2); EXPECT_EQ(testAHash2, hasher.hash()); EXPECT_EQ(testAHash2 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharactersAssumingAligned(testALChars + 2, 2); EXPECT_EQ(testAHash4, hasher.hash()); EXPECT_EQ(testAHash4 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharactersAssumingAligned(testALChars + 4, 1); EXPECT_EQ(testAHash5, hasher.hash()); EXPECT_EQ(testAHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharactersAssumingAligned(testALChars, 2); hasher.addCharactersAssumingAligned(testALChars + 2, 2); hasher.addCharactersAssumingAligned(testALChars + 4, 1); EXPECT_EQ(testAHash5, hasher.hash()); EXPECT_EQ(testAHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharactersAssumingAligned(testAUChars, 2); EXPECT_EQ(testAHash2, hasher.hash()); EXPECT_EQ(testAHash2 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharactersAssumingAligned(testAUChars + 2, 2); EXPECT_EQ(testAHash4, hasher.hash()); EXPECT_EQ(testAHash4 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharactersAssumingAligned(testAUChars + 4, 1); EXPECT_EQ(testAHash5, hasher.hash()); EXPECT_EQ(testAHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharactersAssumingAligned(testAUChars, 2); hasher.addCharactersAssumingAligned(testAUChars + 2, 2); hasher.addCharactersAssumingAligned(testAUChars + 4, 1); EXPECT_EQ(testAHash5, hasher.hash()); EXPECT_EQ(testAHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharactersAssumingAligned(testBUChars, 2); EXPECT_EQ(testBHash2, hasher.hash()); EXPECT_EQ(testBHash2 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharactersAssumingAligned(testBUChars + 2, 2); EXPECT_EQ(testBHash4, hasher.hash()); EXPECT_EQ(testBHash4 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharactersAssumingAligned(testBUChars + 4, 1); EXPECT_EQ(testBHash5, hasher.hash()); EXPECT_EQ(testBHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharactersAssumingAligned(testBUChars, 2); hasher.addCharactersAssumingAligned(testBUChars + 2, 2); hasher.addCharactersAssumingAligned(testBUChars + 4, 1); EXPECT_EQ(testBHash5, hasher.hash()); EXPECT_EQ(testBHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); // Hashing five characters, first two characters one at a time, // then two more, then the last one. hasher = StringHasher(); hasher.addCharacter(testBUChars[0]); EXPECT_EQ(testBHash1, hasher.hash()); EXPECT_EQ(testBHash1 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharacter(testBUChars[1]); EXPECT_EQ(testBHash2, hasher.hash()); EXPECT_EQ(testBHash2 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharactersAssumingAligned(testBUChars[2], testBUChars[3]); EXPECT_EQ(testBHash4, hasher.hash()); EXPECT_EQ(testBHash4 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharactersAssumingAligned(testBUChars + 4, 1); EXPECT_EQ(testBHash5, hasher.hash()); EXPECT_EQ(testBHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); }
TEST(StringHasherTest, StringHasher_addCharacters) { StringHasher hasher; // Hashing zero characters. hasher = StringHasher(); hasher.addCharacters(static_cast<LChar*>(0), 0); EXPECT_EQ(emptyStringHash, hasher.hash()); EXPECT_EQ(emptyStringHash & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharacters(nullLChars, 0); EXPECT_EQ(emptyStringHash, hasher.hash()); EXPECT_EQ(emptyStringHash & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharacters(static_cast<UChar*>(0), 0); EXPECT_EQ(emptyStringHash, hasher.hash()); EXPECT_EQ(emptyStringHash & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharacters(nullUChars, 0); EXPECT_EQ(emptyStringHash, hasher.hash()); EXPECT_EQ(emptyStringHash & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); // Hashing one character. hasher = StringHasher(); hasher.addCharacters(nullLChars, 1); EXPECT_EQ(singleNullCharacterHash, hasher.hash()); EXPECT_EQ(singleNullCharacterHash & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharacters(nullUChars, 1); EXPECT_EQ(singleNullCharacterHash, hasher.hash()); EXPECT_EQ(singleNullCharacterHash & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); // Hashing five characters, all at once. hasher = StringHasher(); hasher.addCharacters(testALChars, 5); EXPECT_EQ(testAHash5, hasher.hash()); EXPECT_EQ(testAHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharacters(testAUChars, 5); EXPECT_EQ(testAHash5, hasher.hash()); EXPECT_EQ(testAHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharacters(testBUChars, 5); EXPECT_EQ(testBHash5, hasher.hash()); EXPECT_EQ(testBHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); // Hashing five characters, in groups of two, then the last one. hasher = StringHasher(); hasher.addCharacters(testALChars, 2); EXPECT_EQ(testAHash2, hasher.hash()); EXPECT_EQ(testAHash2 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharacters(testALChars + 2, 2); EXPECT_EQ(testAHash4, hasher.hash()); EXPECT_EQ(testAHash4 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharacters(testALChars + 4, 1); EXPECT_EQ(testAHash5, hasher.hash()); EXPECT_EQ(testAHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharacters(testALChars, 2); hasher.addCharacters(testALChars + 2, 2); hasher.addCharacters(testALChars + 4, 1); EXPECT_EQ(testAHash5, hasher.hash()); EXPECT_EQ(testAHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharacters(testAUChars, 2); EXPECT_EQ(testAHash2, hasher.hash()); EXPECT_EQ(testAHash2 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharacters(testAUChars + 2, 2); EXPECT_EQ(testAHash4, hasher.hash()); EXPECT_EQ(testAHash4 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharacters(testAUChars + 4, 1); EXPECT_EQ(testAHash5, hasher.hash()); EXPECT_EQ(testAHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharacters(testAUChars, 2); hasher.addCharacters(testAUChars + 2, 2); hasher.addCharacters(testAUChars + 4, 1); EXPECT_EQ(testAHash5, hasher.hash()); EXPECT_EQ(testAHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharacters(testBUChars, 2); EXPECT_EQ(testBHash2, hasher.hash()); EXPECT_EQ(testBHash2 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharacters(testBUChars + 2, 2); EXPECT_EQ(testBHash4, hasher.hash()); EXPECT_EQ(testBHash4 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharacters(testBUChars + 4, 1); EXPECT_EQ(testBHash5, hasher.hash()); EXPECT_EQ(testBHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharacters(testBUChars, 2); hasher.addCharacters(testBUChars + 2, 2); hasher.addCharacters(testBUChars + 4, 1); EXPECT_EQ(testBHash5, hasher.hash()); EXPECT_EQ(testBHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); // Hashing five characters, the first three, then the last two. hasher = StringHasher(); hasher.addCharacters(testALChars, 3); EXPECT_EQ(testAHash3, hasher.hash()); EXPECT_EQ(testAHash3 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharacters(testALChars + 3, 2); EXPECT_EQ(testAHash5, hasher.hash()); EXPECT_EQ(testAHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharacters(testALChars, 3); EXPECT_EQ(testAHash3, hasher.hash()); EXPECT_EQ(testAHash3 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharacters(testALChars + 3, 2); EXPECT_EQ(testAHash5, hasher.hash()); EXPECT_EQ(testAHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharacters(testAUChars, 3); EXPECT_EQ(testAHash3, hasher.hash()); EXPECT_EQ(testAHash3 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharacters(testAUChars + 3, 2); EXPECT_EQ(testAHash5, hasher.hash()); EXPECT_EQ(testAHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharacters(testAUChars, 3); EXPECT_EQ(testAHash3, hasher.hash()); EXPECT_EQ(testAHash3 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharacters(testAUChars + 3, 2); EXPECT_EQ(testAHash5, hasher.hash()); EXPECT_EQ(testAHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharacters(testBUChars, 3); EXPECT_EQ(testBHash3, hasher.hash()); EXPECT_EQ(testBHash3 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher.addCharacters(testBUChars + 3, 2); EXPECT_EQ(testBHash5, hasher.hash()); EXPECT_EQ(testBHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); hasher = StringHasher(); hasher.addCharacters(testBUChars, 3); hasher.addCharacters(testBUChars + 3, 2); EXPECT_EQ(testBHash5, hasher.hash()); EXPECT_EQ(testBHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked()); }