Changeset 179532 in webkit


Ignore:
Timestamp:
Feb 2, 2015 6:22:07 PM (9 years ago)
Author:
commit-queue@webkit.org
Message:

Optimize matchesLangPseudoClass() of :lang()
https://bugs.webkit.org/show_bug.cgi?id=140873

Patch by Dhi Aurrahman <diorahman@rockybars.com> on 2015-02-02
Reviewed by Darin Adler.

Source/WebCore:

Avoid unnecessary memory allocation.

No new tests, no behavior changed.

  • css/SelectorCheckerTestFunctions.h:

(WebCore::equalIgnoringASCIICase):
(WebCore::containslanguageSubtagMatchingRange):
(WebCore::matchesLangPseudoClass):

Source/WTF:

Add some basic equality comparison operators.

  • wtf/text/StringView.h:

(WTF::operator==):
(WTF::operator!=):
(WTF::equal):
(WTF::equalIgnoringASCIICase):

Location:
trunk/Source
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/ChangeLog

    r179500 r179532  
     12015-02-02  Dhi Aurrahman  <diorahman@rockybars.com>
     2
     3        Optimize matchesLangPseudoClass() of :lang()
     4        https://bugs.webkit.org/show_bug.cgi?id=140873
     5
     6        Reviewed by Darin Adler.
     7
     8        Add some basic equality comparison operators.
     9
     10        * wtf/text/StringView.h:
     11        (WTF::operator==):
     12        (WTF::operator!=):
     13        (WTF::equal):
     14        (WTF::equalIgnoringASCIICase):
     15
    1162015-02-02  Geoffrey Garen  <ggaren@apple.com>
    217
  • trunk/Source/WTF/wtf/text/StringView.h

    r176964 r179532  
    140140template<typename CharacterType, size_t inlineCapacity> void append(Vector<CharacterType, inlineCapacity>&, StringView);
    141141
     142bool equal(StringView, StringView);
     143bool equal(StringView, const LChar*);
     144bool equal(StringView, const char*);
     145bool equalIgnoringASCIICase(StringView, StringView);
     146
     147inline bool operator==(StringView a, StringView b) { return equal(a, b); }
     148inline bool operator==(StringView a, const LChar* b) { return equal(a, b); }
     149inline bool operator==(StringView a, const char* b) { return equal(a, b); }
     150inline bool operator==(const LChar* a, StringView b) { return equal(b, a); }
     151inline bool operator==(const char* a, StringView b) { return equal(b, a); }
     152
     153inline bool operator!=(StringView a, StringView b) { return !equal(a, b); }
     154inline bool operator!=(StringView a, const LChar* b) { return !equal(a, b); }
     155inline bool operator!=(StringView a, const char* b) { return !equal(a, b); }
     156inline bool operator!=(const LChar* a, StringView b) { return !equal(b, a); }
     157inline bool operator!=(const char* a, StringView b) { return !equal(b, a); }
     158
    142159}
    143160
     
    450467}
    451468
     469inline bool equal(StringView a, StringView b)
     470{
     471    unsigned aLength = a.length();
     472    unsigned bLength = b.length();
     473    if (aLength != bLength)
     474        return false;
     475
     476    if (a.is8Bit()) {
     477        if (b.is8Bit())
     478            return equal(a.characters8(), b.characters8(), aLength);
     479
     480        return equal(a.characters8(), b.characters16(), aLength);
     481    }
     482
     483    if (b.is8Bit())
     484        return equal(a.characters16(), b.characters8(), aLength);
     485
     486    return equal(a.characters16(), b.characters16(), aLength);
     487}
     488
     489inline bool equal(StringView a, const LChar* b)
     490{
     491    if (!b)
     492        return !a.isEmpty();
     493    if (a.isEmpty())
     494        return !b;
     495    unsigned aLength = a.length();
     496    if (a.is8Bit())
     497        return equal(a.characters8(), b, aLength);
     498    return equal(a.characters16(), b, aLength);
     499}
     500
     501inline bool equal(StringView a, const char* b)
     502{
     503    return equal(a, reinterpret_cast<const LChar*>(b));
     504}
     505
     506inline bool equalIgnoringASCIICase(StringView a, StringView b)
     507{
     508    unsigned aLength = a.length();
     509    if (aLength != b.length())
     510        return false;
     511    for (size_t i = 0; i < aLength; ++i) {
     512        if (toASCIILower(a[i]) != toASCIILower(b[i]))
     513            return false;
     514    }
     515    return true;
     516}
     517
    452518class StringView::CodePoints {
    453519public:
     
    620686
    621687using WTF::append;
     688using WTF::equal;
    622689using WTF::StringView;
    623690
  • trunk/Source/WebCore/ChangeLog

    r179530 r179532  
     12015-02-02  Dhi Aurrahman  <diorahman@rockybars.com>
     2
     3        Optimize matchesLangPseudoClass() of :lang()
     4        https://bugs.webkit.org/show_bug.cgi?id=140873
     5
     6        Reviewed by Darin Adler.
     7
     8        Avoid unnecessary memory allocation.
     9
     10        No new tests, no behavior changed.
     11
     12        * css/SelectorCheckerTestFunctions.h:
     13        (WebCore::equalIgnoringASCIICase):
     14        (WebCore::containslanguageSubtagMatchingRange):
     15        (WebCore::matchesLangPseudoClass):
     16
    1172015-02-02  Roger Fong  <roger_fong@apple.com>
    218
  • trunk/Source/WebCore/css/SelectorCheckerTestFunctions.h

    r178675 r179532  
    122122
    123123#if ENABLE(CSS_SELECTORS_LEVEL4)
    124 inline bool equalIgnoringASCIICase(const String& a, const String& b)
     124ALWAYS_INLINE bool equalIgnoringASCIICase(const String& a, const String& b)
    125125{
    126126    if (a.length() != b.length())
     
    133133}
    134134
    135 inline bool containslanguageSubtagMatchingRange(const Vector<String>& languageSubtags, const String& range, size_t& position)
    136 {
    137     for (size_t languageSubtagIndex = position; languageSubtagIndex < languageSubtags.size(); ++languageSubtagIndex) {
    138         const String& currentLanguageSubtag = languageSubtags[languageSubtagIndex];
    139         if (currentLanguageSubtag.length() == 1 && range != "*")
     135ALWAYS_INLINE bool containslanguageSubtagMatchingRange(StringView language, StringView range, unsigned languageLength, unsigned& position)
     136{
     137    unsigned languageSubtagsStartIndex = position;
     138    unsigned languageSubtagsEndIndex = languageLength;
     139    bool isAsteriskRange = range == "*";
     140    do {
     141        if (languageSubtagsStartIndex > 0)
     142            languageSubtagsStartIndex += 1;
     143       
     144        languageSubtagsEndIndex = std::min<unsigned>(language.find('-', languageSubtagsStartIndex), languageLength);
     145
     146        if (languageSubtagsStartIndex > languageSubtagsEndIndex)
    140147            return false;
    141         if (equalIgnoringASCIICase(range, currentLanguageSubtag) || range == "*") {
    142             position = languageSubtagIndex + 1;
    143             return true;
     148
     149        StringView languageSubtag = language.substring(languageSubtagsStartIndex, languageSubtagsEndIndex - languageSubtagsStartIndex);
     150        bool isEqual = equalIgnoringASCIICase(range, languageSubtag);
     151        if (!isAsteriskRange) {
     152            if ((!isEqual && !languageSubtagsStartIndex) || (languageSubtag.length() == 1 && languageSubtagsStartIndex > 0))
     153                return false;
    144154        }
    145     }
    146     return false;
    147 }
    148 
    149 inline bool matchesLangPseudoClass(const Element* element, const Vector<LanguageArgument>& argumentList)
     155        languageSubtagsStartIndex = languageSubtagsEndIndex;
     156        if (isEqual || isAsteriskRange) {
     157            position = languageSubtagsStartIndex;
     158            return true;
     159        }
     160
     161    } while (languageSubtagsStartIndex < languageLength);
     162    return false;
     163}
     164
     165ALWAYS_INLINE bool matchesLangPseudoClass(const Element* element, const Vector<LanguageArgument>& argumentList)
    150166{
    151167    ASSERT(element);
     
    164180    // Implement basic and extended filterings of given language tags
    165181    // as specified in www.ietf.org/rfc/rfc4647.txt.
    166     Vector<String> rangeSubtags;
    167     Vector<String> languageSubtags;
    168 
    169     language.string().split('-', true, languageSubtags);
    170 
     182    StringView languageStringView = language.string();
     183    unsigned languageLength = language.length();
    171184    for (const LanguageArgument& argument : argumentList) {
    172185        const AtomicString& range = argument.languageRange;
    173186        if (range.isEmpty())
    174187            continue;
    175 
    176188        if (range == "*")
    177189            return true;
    178 
    179         if (equalIgnoringASCIICase(language, range) && !language.contains('-'))
    180             return true;
    181 
    182         range.string().split('-', true, rangeSubtags);
    183 
    184         if (rangeSubtags.size() > languageSubtags.size())
     190    }
     191
     192    for (const LanguageArgument& argument : argumentList) {
     193        const AtomicString& range = argument.languageRange;
     194        if (range.isEmpty())
    185195            continue;
    186196
    187         const String& firstRangeSubtag = rangeSubtags.first();
    188         if (!equalIgnoringASCIICase(firstRangeSubtag, languageSubtags.first()) && firstRangeSubtag != "*")
    189             continue;
    190 
    191         size_t lastMatchedLanguageSubtagIndex = 1;
     197        if (range == "*")
     198            return true;
     199
     200        StringView rangeStringView = range.string();
     201        if (equalIgnoringASCIICase(languageStringView, rangeStringView) && !languageStringView.contains('-'))
     202            return true;
     203       
     204        unsigned rangeLength = rangeStringView.length();
     205        unsigned rangeSubtagsStartIndex = 0;
     206        unsigned rangeSubtagsEndIndex = rangeLength;
     207        unsigned lastMatchedLanguageSubtagIndex = 0;
     208
    192209        bool matchedRange = true;
    193         for (size_t rangeSubtagIndex = 1; rangeSubtagIndex < rangeSubtags.size(); ++rangeSubtagIndex) {
    194             if (!containslanguageSubtagMatchingRange(languageSubtags, rangeSubtags[rangeSubtagIndex], lastMatchedLanguageSubtagIndex)) {
     210        do {
     211            if (rangeSubtagsStartIndex > 0)
     212                rangeSubtagsStartIndex += 1;
     213            if (rangeSubtagsStartIndex > languageLength)
     214                return false;
     215            rangeSubtagsEndIndex = std::min<unsigned>(rangeStringView.find('-', rangeSubtagsStartIndex), rangeLength);
     216            StringView rangeSubtag = rangeStringView.substring(rangeSubtagsStartIndex, rangeSubtagsEndIndex - rangeSubtagsStartIndex);
     217            if (!containslanguageSubtagMatchingRange(languageStringView, rangeSubtag, languageLength, lastMatchedLanguageSubtagIndex)) {
    195218                matchedRange = false;
    196219                break;
    197220            }
    198         }
     221            rangeSubtagsStartIndex = rangeSubtagsEndIndex;
     222        } while (rangeSubtagsStartIndex < rangeLength);
    199223        if (matchedRange)
    200224            return true;
Note: See TracChangeset for help on using the changeset viewer.