Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Side by Side Diff: third_party/WebKit/Source/wtf/text/StringImpl.cpp

Issue 2146163003: Use StringView for startsWith and endsWith. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller ( mueller@kde.org ) 4 * (C) 2001 Dirk Mueller ( mueller@kde.org )
5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All r ights reserved. 5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All r ights reserved.
6 * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net) 6 * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
7 * 7 *
8 * This library is free software; you can redistribute it and/or 8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public 9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either 10 * License as published by the Free Software Foundation; either
(...skipping 689 matching lines...) Expand 10 before | Expand all | Expand 10 after
700 int32_t realLength = Unicode::toUpper(data16, length, source16, m_length, &e rror); 700 int32_t realLength = Unicode::toUpper(data16, length, source16, m_length, &e rror);
701 if (!error && realLength == length) 701 if (!error && realLength == length)
702 return newImpl; 702 return newImpl;
703 newImpl = createUninitialized(realLength, data16); 703 newImpl = createUninitialized(realLength, data16);
704 Unicode::toUpper(data16, realLength, source16, m_length, &error); 704 Unicode::toUpper(data16, realLength, source16, m_length, &error);
705 if (error) 705 if (error)
706 return this; 706 return this;
707 return newImpl.release(); 707 return newImpl.release();
708 } 708 }
709 709
710 static inline bool localeIdMatchesLang(const AtomicString& localeId, const char* lang) 710 static inline bool localeIdMatchesLang(const AtomicString& localeId, const Strin gView& lang)
711 { 711 {
712 size_t langLength = strlen(lang); 712 RELEASE_ASSERT(lang.length() >= 2 && lang.length() <= 3);
713 RELEASE_ASSERT(langLength >= 2 && langLength <= 3); 713 if (!localeId.impl() || !localeId.impl()->startsWithIgnoringCase(lang))
714 if (!localeId.impl() || !localeId.impl()->startsWithIgnoringCase(lang, langL ength))
715 return false; 714 return false;
716 if (localeId.impl()->length() == langLength) 715 if (localeId.impl()->length() == lang.length())
717 return true; 716 return true;
718 const UChar maybeDelimiter = (*localeId.impl())[langLength]; 717 const UChar maybeDelimiter = (*localeId.impl())[lang.length()];
719 return maybeDelimiter == '-' || maybeDelimiter == '_' || maybeDelimiter == ' @'; 718 return maybeDelimiter == '-' || maybeDelimiter == '_' || maybeDelimiter == ' @';
720 } 719 }
721 720
722 typedef int32_t (*icuCaseConverter)(UChar*, int32_t, const UChar*, int32_t, cons t char*, UErrorCode*); 721 typedef int32_t (*icuCaseConverter)(UChar*, int32_t, const UChar*, int32_t, cons t char*, UErrorCode*);
723 722
724 static PassRefPtr<StringImpl> caseConvert(const UChar* source16, size_t length, icuCaseConverter converter, const char* locale, StringImpl* originalString) 723 static PassRefPtr<StringImpl> caseConvert(const UChar* source16, size_t length, icuCaseConverter converter, const char* locale, StringImpl* originalString)
725 { 724 {
726 UChar* data16; 725 UChar* data16;
727 size_t targetLength = length; 726 size_t targetLength = length;
728 RefPtr<StringImpl> output = StringImpl::createUninitialized(length, data16); 727 RefPtr<StringImpl> output = StringImpl::createUninitialized(length, data16);
(...skipping 762 matching lines...) Expand 10 before | Expand all | Expand 10 after
1491 return reverseFindInner(characters8(), matchString->characters8(), i ndex, ourLength, matchLength); 1490 return reverseFindInner(characters8(), matchString->characters8(), i ndex, ourLength, matchLength);
1492 return reverseFindInner(characters8(), matchString->characters16(), inde x, ourLength, matchLength); 1491 return reverseFindInner(characters8(), matchString->characters16(), inde x, ourLength, matchLength);
1493 } 1492 }
1494 1493
1495 if (matchString->is8Bit()) 1494 if (matchString->is8Bit())
1496 return reverseFindInner(characters16(), matchString->characters8(), inde x, ourLength, matchLength); 1495 return reverseFindInner(characters16(), matchString->characters8(), inde x, ourLength, matchLength);
1497 1496
1498 return reverseFindInner(characters16(), matchString->characters16(), index, ourLength, matchLength); 1497 return reverseFindInner(characters16(), matchString->characters16(), index, ourLength, matchLength);
1499 } 1498 }
1500 1499
1501 ALWAYS_INLINE static bool equalSubstring(const StringImpl* stringImpl, unsigned startOffset, const LChar* matchString, unsigned matchLength)
1502 {
1503 ASSERT(stringImpl);
1504 ASSERT(matchLength <= stringImpl->length());
1505 ASSERT(startOffset + matchLength <= stringImpl->length());
1506
1507 if (stringImpl->is8Bit())
1508 return equal(stringImpl->characters8() + startOffset, matchString, match Length);
1509 return equal(stringImpl->characters16() + startOffset, matchString, matchLen gth);
1510 }
1511
1512 bool StringImpl::startsWith(UChar character) const 1500 bool StringImpl::startsWith(UChar character) const
1513 { 1501 {
1514 return m_length && (*this)[0] == character; 1502 return m_length && (*this)[0] == character;
1515 } 1503 }
1516 1504
1517 bool StringImpl::startsWith(const char* prefixString, unsigned prefixLength) con st 1505 bool StringImpl::startsWith(const StringView& prefix) const
1518 { 1506 {
1519 ASSERT(prefixLength); 1507 if (prefix.length() > length())
1520 if (prefixLength > length())
1521 return false; 1508 return false;
1522 return equalSubstring(this, 0, reinterpret_cast<const LChar*>(prefixString), prefixLength); 1509 if (is8Bit()) {
1510 if (prefix.is8Bit())
1511 return equal(characters8(), prefix.characters8(), prefix.length());
1512 return equal(characters8(), prefix.characters16(), prefix.length());
1513 }
1514 if (prefix.is8Bit())
1515 return equal(characters16(), prefix.characters8(), prefix.length());
1516 return equal(characters16(), prefix.characters16(), prefix.length());
1523 } 1517 }
1524 1518
1525 ALWAYS_INLINE static bool equalSubstring(const StringImpl* stringImpl, unsigned startOffset, const StringImpl* matchString) 1519 bool StringImpl::startsWithIgnoringCase(const StringView& prefix) const
1526 { 1520 {
1527 ASSERT(stringImpl); 1521 if (prefix.length() > length())
1528 ASSERT(matchString); 1522 return false;
1529 ASSERT(matchString->length() <= stringImpl->length()); 1523 if (is8Bit()) {
1530 ASSERT(startOffset + matchString->length() <= stringImpl->length()); 1524 if (prefix.is8Bit())
1531 1525 return equalIgnoringCase(characters8(), prefix.characters8(), prefix .length());
1532 unsigned matchLength = matchString->length(); 1526 return equalIgnoringCase(characters8(), prefix.characters16(), prefix.le ngth());
1533 if (matchString->is8Bit()) 1527 }
1534 return equalSubstring(stringImpl, startOffset, matchString->characters8( ), matchLength); 1528 if (prefix.is8Bit())
1535 if (stringImpl->is8Bit()) 1529 return equalIgnoringCase(characters16(), prefix.characters8(), prefix.le ngth());
1536 return equal(stringImpl->characters8() + startOffset, matchString->chara cters16(), matchLength); 1530 return equalIgnoringCase(characters16(), prefix.characters16(), prefix.lengt h());
1537 return equal(stringImpl->characters16() + startOffset, matchString->characte rs16(), matchLength);
1538 } 1531 }
1539 1532
1540 bool StringImpl::startsWith(const StringImpl* prefix) const 1533 bool StringImpl::startsWithIgnoringASCIICase(const StringView& prefix) const
1541 { 1534 {
1542 ASSERT(prefix); 1535 if (prefix.length() > length())
1543 if (prefix->length() > length())
1544 return false; 1536 return false;
1545 return equalSubstring(this, 0, prefix); 1537 if (is8Bit()) {
1546 } 1538 if (prefix.is8Bit())
1547 1539 return equalIgnoringASCIICase(characters8(), prefix.characters8(), p refix.length());
1548 ALWAYS_INLINE static bool equalSubstringIgnoringCase(const StringImpl* stringImp l, unsigned startOffset, const LChar* matchString, unsigned matchLength) 1540 return equalIgnoringASCIICase(characters8(), prefix.characters16(), pref ix.length());
1549 { 1541 }
1550 ASSERT(stringImpl); 1542 if (prefix.is8Bit())
1551 ASSERT(matchLength <= stringImpl->length()); 1543 return equalIgnoringASCIICase(characters16(), prefix.characters8(), pref ix.length());
1552 ASSERT(startOffset + matchLength <= stringImpl->length()); 1544 return equalIgnoringASCIICase(characters16(), prefix.characters16(), prefix. length());
1553
1554 if (stringImpl->is8Bit())
1555 return equalIgnoringCase(stringImpl->characters8() + startOffset, matchS tring, matchLength);
1556 return equalIgnoringCase(stringImpl->characters16() + startOffset, matchStri ng, matchLength);
1557 }
1558
1559 bool StringImpl::startsWithIgnoringCase(const char* prefixString, unsigned prefi xLength) const
1560 {
1561 ASSERT(prefixLength);
1562 if (prefixLength > length())
1563 return false;
1564 return equalSubstringIgnoringCase(this, 0, reinterpret_cast<const LChar*>(pr efixString), prefixLength);
1565 }
1566
1567 ALWAYS_INLINE static bool equalSubstringIgnoringCase(const StringImpl* stringImp l, unsigned startOffset, const StringImpl* matchString)
1568 {
1569 ASSERT(stringImpl);
1570 ASSERT(matchString);
1571 ASSERT(matchString->length() <= stringImpl->length());
1572 ASSERT(startOffset + matchString->length() <= stringImpl->length());
1573
1574 unsigned matchLength = matchString->length();
1575 if (matchString->is8Bit())
1576 return equalSubstringIgnoringCase(stringImpl, startOffset, matchString-> characters8(), matchLength);
1577 if (stringImpl->is8Bit())
1578 return equalIgnoringCase(stringImpl->characters8() + startOffset, matchS tring->characters16(), matchLength);
1579 return equalIgnoringCase(stringImpl->characters16() + startOffset, matchStri ng->characters16(), matchLength);
1580 }
1581
1582 bool StringImpl::startsWithIgnoringCase(const StringImpl* prefix) const
1583 {
1584 ASSERT(prefix);
1585 if (prefix->length() > length())
1586 return false;
1587 return equalSubstringIgnoringCase(this, 0, prefix);
1588 }
1589
1590 ALWAYS_INLINE static bool equalSubstringIgnoringASCIICase(const StringImpl* stri ngImpl, unsigned startOffset, const LChar* matchString, unsigned matchLength)
1591 {
1592 ASSERT(stringImpl);
1593 ASSERT(matchLength <= stringImpl->length());
1594 ASSERT(startOffset + matchLength <= stringImpl->length());
1595
1596 if (stringImpl->is8Bit())
1597 return equalIgnoringASCIICase(stringImpl->characters8() + startOffset, m atchString, matchLength);
1598 return equalIgnoringASCIICase(stringImpl->characters16() + startOffset, matc hString, matchLength);
1599 }
1600
1601 bool StringImpl::startsWithIgnoringASCIICase(const char* prefixString, unsigned prefixLength) const
1602 {
1603 ASSERT(prefixLength);
1604 if (prefixLength > length())
1605 return false;
1606 return equalSubstringIgnoringASCIICase(this, 0, reinterpret_cast<const LChar *>(prefixString), prefixLength);
1607 }
1608
1609 ALWAYS_INLINE static bool equalSubstringIgnoringASCIICase(const StringImpl* stri ngImpl, unsigned startOffset, const StringImpl* matchString)
1610 {
1611 ASSERT(stringImpl);
1612 ASSERT(matchString);
1613 ASSERT(matchString->length() <= stringImpl->length());
1614 ASSERT(startOffset + matchString->length() <= stringImpl->length());
1615
1616 unsigned matchLength = matchString->length();
1617 if (matchString->is8Bit())
1618 return equalSubstringIgnoringASCIICase(stringImpl, startOffset, matchStr ing->characters8(), matchLength);
1619 if (stringImpl->is8Bit())
1620 return equalIgnoringASCIICase(stringImpl->characters8() + startOffset, m atchString->characters16(), matchLength);
1621 return equalIgnoringASCIICase(stringImpl->characters16() + startOffset, matc hString->characters16(), matchLength);
1622 }
1623
1624 bool StringImpl::startsWithIgnoringASCIICase(const StringImpl* prefix) const
1625 {
1626 ASSERT(prefix);
1627 if (prefix->length() > length())
1628 return false;
1629 return equalSubstringIgnoringASCIICase(this, 0, prefix);
1630 } 1545 }
1631 1546
1632 bool StringImpl::endsWith(UChar character) const 1547 bool StringImpl::endsWith(UChar character) const
1633 { 1548 {
1634 return m_length && (*this)[m_length - 1] == character; 1549 return m_length && (*this)[m_length - 1] == character;
1635 } 1550 }
1636 1551
1637 bool StringImpl::endsWith(const char* suffixString, unsigned suffixLength) const 1552 bool StringImpl::endsWith(const StringView& suffix) const
1638 { 1553 {
1639 ASSERT(suffixLength); 1554 if (suffix.length() > length())
1640 if (suffixLength > length())
1641 return false; 1555 return false;
1642 return equalSubstring(this, length() - suffixLength, reinterpret_cast<const LChar*>(suffixString), suffixLength); 1556 unsigned startOffset = length() - suffix.length();
1557 if (is8Bit()) {
1558 if (suffix.is8Bit())
1559 return equal(characters8() + startOffset, suffix.characters8(), suff ix.length());
1560 return equal(characters8() + startOffset, suffix.characters16(), suffix. length());
1561 }
1562 if (suffix.is8Bit())
1563 return equal(characters16() + startOffset, suffix.characters8(), suffix. length());
1564 return equal(characters16() + startOffset, suffix.characters16(), suffix.len gth());
1643 } 1565 }
1644 1566
1645 bool StringImpl::endsWith(const StringImpl* suffix) const 1567 bool StringImpl::endsWithIgnoringCase(const StringView& suffix) const
1646 { 1568 {
1647 ASSERT(suffix); 1569 if (suffix.length() > length())
1648 unsigned suffixLength = suffix->length();
1649 if (suffixLength > length())
1650 return false; 1570 return false;
1651 return equalSubstring(this, length() - suffixLength, suffix); 1571 unsigned startOffset = length() - suffix.length();
1572 if (is8Bit()) {
1573 if (suffix.is8Bit())
1574 return equalIgnoringCase(characters8() + startOffset, suffix.charact ers8(), suffix.length());
1575 return equalIgnoringCase(characters8() + startOffset, suffix.characters1 6(), suffix.length());
1576 }
1577 if (suffix.is8Bit())
1578 return equalIgnoringCase(characters16() + startOffset, suffix.characters 8(), suffix.length());
1579 return equalIgnoringCase(characters16() + startOffset, suffix.characters16() , suffix.length());
1652 } 1580 }
1653 1581
1654 bool StringImpl::endsWithIgnoringCase(const char* suffixString, unsigned suffixL ength) const 1582 bool StringImpl::endsWithIgnoringASCIICase(const StringView& suffix) const
1655 { 1583 {
1656 ASSERT(suffixLength); 1584 if (suffix.length() > length())
1657 if (suffixLength > length())
1658 return false; 1585 return false;
1659 return equalSubstringIgnoringCase(this, length() - suffixLength, reinterpret _cast<const LChar*>(suffixString), suffixLength); 1586 unsigned startOffset = length() - suffix.length();
1660 } 1587 if (is8Bit()) {
1661 1588 if (suffix.is8Bit())
1662 bool StringImpl::endsWithIgnoringCase(const StringImpl* suffix) const 1589 return equalIgnoringASCIICase(characters8() + startOffset, suffix.ch aracters8(), suffix.length());
1663 { 1590 return equalIgnoringASCIICase(characters8() + startOffset, suffix.charac ters16(), suffix.length());
1664 ASSERT(suffix); 1591 }
1665 unsigned suffixLength = suffix->length(); 1592 if (suffix.is8Bit())
1666 if (suffixLength > length()) 1593 return equalIgnoringASCIICase(characters16() + startOffset, suffix.chara cters8(), suffix.length());
1667 return false; 1594 return equalIgnoringASCIICase(characters16() + startOffset, suffix.character s16(), suffix.length());
1668 return equalSubstringIgnoringCase(this, length() - suffixLength, suffix);
1669 }
1670
1671 bool StringImpl::endsWithIgnoringASCIICase(const char* suffixString, unsigned su ffixLength) const
1672 {
1673 ASSERT(suffixLength);
1674 if (suffixLength > length())
1675 return false;
1676 return equalSubstringIgnoringASCIICase(this, length() - suffixLength, reinte rpret_cast<const LChar*>(suffixString), suffixLength);
1677 }
1678
1679 bool StringImpl::endsWithIgnoringASCIICase(const StringImpl* suffix) const
1680 {
1681 ASSERT(suffix);
1682 unsigned suffixLength = suffix->length();
1683 if (suffixLength > length())
1684 return false;
1685 return equalSubstringIgnoringASCIICase(this, length() - suffixLength, suffix );
1686 } 1595 }
1687 1596
1688 PassRefPtr<StringImpl> StringImpl::replace(UChar oldC, UChar newC) 1597 PassRefPtr<StringImpl> StringImpl::replace(UChar oldC, UChar newC)
1689 { 1598 {
1690 if (oldC == newC) 1599 if (oldC == newC)
1691 return this; 1600 return this;
1692 1601
1693 if (find(oldC) == kNotFound) 1602 if (find(oldC) == kNotFound)
1694 return this; 1603 return this;
1695 1604
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after
2250 2159
2251 bool equalIgnoringNullity(StringImpl* a, StringImpl* b) 2160 bool equalIgnoringNullity(StringImpl* a, StringImpl* b)
2252 { 2161 {
2253 if (!a && b && !b->length()) 2162 if (!a && b && !b->length())
2254 return true; 2163 return true;
2255 if (!b && a && !a->length()) 2164 if (!b && a && !a->length())
2256 return true; 2165 return true;
2257 return equal(a, b); 2166 return equal(a, b);
2258 } 2167 }
2259 2168
2260 bool equalIgnoringASCIICase(const StringImpl* a, const StringImpl* b)
2261 {
2262 if (!a || !b)
2263 return !a == !b;
2264 unsigned length = b->length();
2265 if (a->length() != length)
2266 return false;
2267 if (a->is8Bit()) {
2268 if (b->is8Bit())
2269 return equalIgnoringASCIICase(a->characters8(), b->characters8(), le ngth);
2270 return equalIgnoringASCIICase(a->characters8(), b->characters16(), lengt h);
2271 }
2272 if (b->is8Bit())
2273 return equalIgnoringASCIICase(a->characters16(), b->characters8(), lengt h);
2274 return equalIgnoringASCIICase(a->characters16(), b->characters16(), length);
2275 }
2276
2277 bool equalIgnoringASCIICase(const StringImpl* a, const LChar* b, unsigned length )
2278 {
2279 if (!a || !b)
2280 return !a == !b;
2281 if (length != a->length())
2282 return false;
2283 return equalSubstringIgnoringASCIICase(a, 0, b, length);
2284 }
2285
2286 template<typename CharacterType1, typename CharacterType2> 2169 template<typename CharacterType1, typename CharacterType2>
2287 int codePointCompareIgnoringASCIICase(unsigned l1, unsigned l2, const CharacterT ype1* c1, const CharacterType2* c2) 2170 int codePointCompareIgnoringASCIICase(unsigned l1, unsigned l2, const CharacterT ype1* c1, const CharacterType2* c2)
2288 { 2171 {
2289 const unsigned lmin = l1 < l2 ? l1 : l2; 2172 const unsigned lmin = l1 < l2 ? l1 : l2;
2290 unsigned pos = 0; 2173 unsigned pos = 0;
2291 while (pos < lmin && toASCIILower(*c1) == toASCIILower(*c2)) { 2174 while (pos < lmin && toASCIILower(*c1) == toASCIILower(*c2)) {
2292 ++c1; 2175 ++c1;
2293 ++c2; 2176 ++c2;
2294 ++pos; 2177 ++pos;
2295 } 2178 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
2338 } else if (localeIdMatchesLang(localeIdentifier, "lt")) { 2221 } else if (localeIdMatchesLang(localeIdentifier, "lt")) {
2339 // TODO(rob.buis) implement upper-casing rules for lt 2222 // TODO(rob.buis) implement upper-casing rules for lt
2340 // like in StringImpl::upper(locale). 2223 // like in StringImpl::upper(locale).
2341 } 2224 }
2342 } 2225 }
2343 2226
2344 return toUpper(c); 2227 return toUpper(c);
2345 } 2228 }
2346 2229
2347 } // namespace WTF 2230 } // namespace WTF
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698