OLD | NEW |
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 | 5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All |
6 * rights reserved. | 6 * rights reserved. |
7 * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net) | 7 * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net) |
8 * | 8 * |
9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
10 * modify it under the terms of the GNU Library General Public | 10 * modify it under the terms of the GNU Library General Public |
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 | 426 |
427 StaticStringsTable::const_iterator it = StaticStrings().Find(hash); | 427 StaticStringsTable::const_iterator it = StaticStrings().Find(hash); |
428 if (it != StaticStrings().end()) { | 428 if (it != StaticStrings().end()) { |
429 DCHECK(!memcmp(string, it->value + 1, length * sizeof(LChar))); | 429 DCHECK(!memcmp(string, it->value + 1, length * sizeof(LChar))); |
430 return it->value; | 430 return it->value; |
431 } | 431 } |
432 | 432 |
433 // Allocate a single buffer large enough to contain the StringImpl | 433 // Allocate a single buffer large enough to contain the StringImpl |
434 // struct as well as the data which it contains. This removes one | 434 // struct as well as the data which it contains. This removes one |
435 // heap allocation from this call. | 435 // heap allocation from this call. |
436 RELEASE_ASSERT(length <= | 436 CHECK_LE(length, |
437 ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / | 437 ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / |
438 sizeof(LChar))); | 438 sizeof(LChar))); |
439 size_t size = sizeof(StringImpl) + length * sizeof(LChar); | 439 size_t size = sizeof(StringImpl) + length * sizeof(LChar); |
440 | 440 |
441 WTF_INTERNAL_LEAK_SANITIZER_DISABLED_SCOPE; | 441 WTF_INTERNAL_LEAK_SANITIZER_DISABLED_SCOPE; |
442 StringImpl* impl = static_cast<StringImpl*>( | 442 StringImpl* impl = static_cast<StringImpl*>( |
443 Partitions::BufferMalloc(size, "WTF::StringImpl")); | 443 Partitions::BufferMalloc(size, "WTF::StringImpl")); |
444 | 444 |
445 LChar* data = reinterpret_cast<LChar*>(impl + 1); | 445 LChar* data = reinterpret_cast<LChar*>(impl + 1); |
446 impl = new (impl) StringImpl(length, hash, kStaticString); | 446 impl = new (impl) StringImpl(length, hash, kStaticString); |
447 memcpy(data, string, length * sizeof(LChar)); | 447 memcpy(data, string, length * sizeof(LChar)); |
448 #if DCHECK_IS_ON() | 448 #if DCHECK_IS_ON() |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 data[i] = static_cast<LChar>(characters[i]); | 503 data[i] = static_cast<LChar>(characters[i]); |
504 } | 504 } |
505 | 505 |
506 return string.Release(); | 506 return string.Release(); |
507 } | 507 } |
508 | 508 |
509 PassRefPtr<StringImpl> StringImpl::Create(const LChar* string) { | 509 PassRefPtr<StringImpl> StringImpl::Create(const LChar* string) { |
510 if (!string) | 510 if (!string) |
511 return empty_; | 511 return empty_; |
512 size_t length = strlen(reinterpret_cast<const char*>(string)); | 512 size_t length = strlen(reinterpret_cast<const char*>(string)); |
513 RELEASE_ASSERT(length <= numeric_limits<unsigned>::max()); | 513 CHECK_LE(length, numeric_limits<unsigned>::max()); |
514 return Create(string, length); | 514 return Create(string, length); |
515 } | 515 } |
516 | 516 |
517 bool StringImpl::ContainsOnlyWhitespace() { | 517 bool StringImpl::ContainsOnlyWhitespace() { |
518 // FIXME: The definition of whitespace here includes a number of characters | 518 // FIXME: The definition of whitespace here includes a number of characters |
519 // that are not whitespace from the point of view of LayoutText; I wonder if | 519 // that are not whitespace from the point of view of LayoutText; I wonder if |
520 // that's a problem in practice. | 520 // that's a problem in practice. |
521 if (Is8Bit()) { | 521 if (Is8Bit()) { |
522 for (unsigned i = 0; i < length_; ++i) { | 522 for (unsigned i = 0; i < length_; ++i) { |
523 UChar c = Characters8()[i]; | 523 UChar c = Characters8()[i]; |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
612 const UChar* end = Characters16() + length_; | 612 const UChar* end = Characters16() + length_; |
613 for (const UChar* chp = Characters16(); chp != end; ++chp) { | 613 for (const UChar* chp = Characters16(); chp != end; ++chp) { |
614 if (IsASCIIUpper(*chp)) | 614 if (IsASCIIUpper(*chp)) |
615 no_upper = false; | 615 no_upper = false; |
616 ored |= *chp; | 616 ored |= *chp; |
617 } | 617 } |
618 // Nothing to do if the string is all ASCII with no uppercase. | 618 // Nothing to do if the string is all ASCII with no uppercase. |
619 if (no_upper && !(ored & ~0x7F)) | 619 if (no_upper && !(ored & ~0x7F)) |
620 return this; | 620 return this; |
621 | 621 |
622 RELEASE_ASSERT(length_ <= | 622 CHECK_LE(length_, static_cast<unsigned>(numeric_limits<unsigned>::max())); |
623 static_cast<unsigned>(numeric_limits<unsigned>::max())); | |
624 unsigned length = length_; | 623 unsigned length = length_; |
625 | 624 |
626 UChar* data16; | 625 UChar* data16; |
627 RefPtr<StringImpl> new_impl = CreateUninitialized(length_, data16); | 626 RefPtr<StringImpl> new_impl = CreateUninitialized(length_, data16); |
628 | 627 |
629 for (unsigned i = 0; i < length; ++i) { | 628 for (unsigned i = 0; i < length; ++i) { |
630 UChar c = Characters16()[i]; | 629 UChar c = Characters16()[i]; |
631 data16[i] = IsASCIIUpper(c) ? ToASCIILower(c) : c; | 630 data16[i] = IsASCIIUpper(c) ? ToASCIILower(c) : c; |
632 } | 631 } |
633 return new_impl.Release(); | 632 return new_impl.Release(); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
671 const UChar* end = Characters16() + length_; | 670 const UChar* end = Characters16() + length_; |
672 for (const UChar* chp = Characters16(); chp != end; ++chp) { | 671 for (const UChar* chp = Characters16(); chp != end; ++chp) { |
673 if (UNLIKELY(IsASCIIUpper(*chp))) | 672 if (UNLIKELY(IsASCIIUpper(*chp))) |
674 no_upper = false; | 673 no_upper = false; |
675 ored |= *chp; | 674 ored |= *chp; |
676 } | 675 } |
677 // Nothing to do if the string is all ASCII with no uppercase. | 676 // Nothing to do if the string is all ASCII with no uppercase. |
678 if (no_upper && !(ored & ~0x7F)) | 677 if (no_upper && !(ored & ~0x7F)) |
679 return this; | 678 return this; |
680 | 679 |
681 RELEASE_ASSERT(length_ <= | 680 CHECK_LE(length_, static_cast<unsigned>(numeric_limits<int32_t>::max())); |
682 static_cast<unsigned>(numeric_limits<int32_t>::max())); | |
683 int32_t length = length_; | 681 int32_t length = length_; |
684 | 682 |
685 if (!(ored & ~0x7F)) { | 683 if (!(ored & ~0x7F)) { |
686 UChar* data16; | 684 UChar* data16; |
687 RefPtr<StringImpl> new_impl = CreateUninitialized(length_, data16); | 685 RefPtr<StringImpl> new_impl = CreateUninitialized(length_, data16); |
688 | 686 |
689 for (int32_t i = 0; i < length; ++i) { | 687 for (int32_t i = 0; i < length; ++i) { |
690 UChar c = Characters16()[i]; | 688 UChar c = Characters16()[i]; |
691 data16[i] = ToASCIILower(c); | 689 data16[i] = ToASCIILower(c); |
692 } | 690 } |
(...skipping 15 matching lines...) Expand all Loading... |
708 if (error) | 706 if (error) |
709 return this; | 707 return this; |
710 return new_impl.Release(); | 708 return new_impl.Release(); |
711 } | 709 } |
712 | 710 |
713 PassRefPtr<StringImpl> StringImpl::UpperUnicode() { | 711 PassRefPtr<StringImpl> StringImpl::UpperUnicode() { |
714 // This function could be optimized for no-op cases the way LowerUnicode() is, | 712 // This function could be optimized for no-op cases the way LowerUnicode() is, |
715 // but in empirical testing, few actual calls to UpperUnicode() are no-ops, so | 713 // but in empirical testing, few actual calls to UpperUnicode() are no-ops, so |
716 // it wouldn't be worth the extra time for pre-scanning. | 714 // it wouldn't be worth the extra time for pre-scanning. |
717 | 715 |
718 RELEASE_ASSERT(length_ <= | 716 CHECK_LE(length_, static_cast<unsigned>(numeric_limits<int32_t>::max())); |
719 static_cast<unsigned>(numeric_limits<int32_t>::max())); | |
720 int32_t length = length_; | 717 int32_t length = length_; |
721 | 718 |
722 if (Is8Bit()) { | 719 if (Is8Bit()) { |
723 LChar* data8; | 720 LChar* data8; |
724 RefPtr<StringImpl> new_impl = CreateUninitialized(length_, data8); | 721 RefPtr<StringImpl> new_impl = CreateUninitialized(length_, data8); |
725 | 722 |
726 // Do a faster loop for the case where all the characters are ASCII. | 723 // Do a faster loop for the case where all the characters are ASCII. |
727 LChar ored = 0; | 724 LChar ored = 0; |
728 for (int i = 0; i < length; ++i) { | 725 for (int i = 0; i < length; ++i) { |
729 LChar c = Characters8()[i]; | 726 LChar c = Characters8()[i]; |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
823 | 820 |
824 for (unsigned i = 0; i < length_; ++i) { | 821 for (unsigned i = 0; i < length_; ++i) { |
825 UChar c = Characters16()[i]; | 822 UChar c = Characters16()[i]; |
826 data16[i] = IsASCIILower(c) ? ToASCIIUpper(c) : c; | 823 data16[i] = IsASCIILower(c) ? ToASCIIUpper(c) : c; |
827 } | 824 } |
828 return new_impl.Release(); | 825 return new_impl.Release(); |
829 } | 826 } |
830 | 827 |
831 static inline bool LocaleIdMatchesLang(const AtomicString& locale_id, | 828 static inline bool LocaleIdMatchesLang(const AtomicString& locale_id, |
832 const StringView& lang) { | 829 const StringView& lang) { |
833 RELEASE_ASSERT(lang.length() >= 2 && lang.length() <= 3); | 830 CHECK_GE(lang.length(), 2u); |
| 831 CHECK_LE(lang.length(), 3u); |
834 if (!locale_id.Impl() || !locale_id.Impl()->StartsWithIgnoringCase(lang)) | 832 if (!locale_id.Impl() || !locale_id.Impl()->StartsWithIgnoringCase(lang)) |
835 return false; | 833 return false; |
836 if (locale_id.Impl()->length() == lang.length()) | 834 if (locale_id.Impl()->length() == lang.length()) |
837 return true; | 835 return true; |
838 const UChar maybe_delimiter = (*locale_id.Impl())[lang.length()]; | 836 const UChar maybe_delimiter = (*locale_id.Impl())[lang.length()]; |
839 return maybe_delimiter == '-' || maybe_delimiter == '_' || | 837 return maybe_delimiter == '-' || maybe_delimiter == '_' || |
840 maybe_delimiter == '@'; | 838 maybe_delimiter == '@'; |
841 } | 839 } |
842 | 840 |
843 typedef int32_t (*icuCaseConverter)(UChar*, | 841 typedef int32_t (*icuCaseConverter)(UChar*, |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
934 return new_impl.Release(); | 932 return new_impl.Release(); |
935 } | 933 } |
936 UChar* data; | 934 UChar* data; |
937 RefPtr<StringImpl> new_impl = CreateUninitialized(length_, data); | 935 RefPtr<StringImpl> new_impl = CreateUninitialized(length_, data); |
938 for (unsigned i = 0; i < length_; ++i) | 936 for (unsigned i = 0; i < length_; ++i) |
939 data[i] = character; | 937 data[i] = character; |
940 return new_impl.Release(); | 938 return new_impl.Release(); |
941 } | 939 } |
942 | 940 |
943 PassRefPtr<StringImpl> StringImpl::FoldCase() { | 941 PassRefPtr<StringImpl> StringImpl::FoldCase() { |
944 RELEASE_ASSERT(length_ <= | 942 CHECK_LE(length_, static_cast<unsigned>(numeric_limits<int32_t>::max())); |
945 static_cast<unsigned>(numeric_limits<int32_t>::max())); | |
946 int32_t length = length_; | 943 int32_t length = length_; |
947 | 944 |
948 if (Is8Bit()) { | 945 if (Is8Bit()) { |
949 // Do a faster loop for the case where all the characters are ASCII. | 946 // Do a faster loop for the case where all the characters are ASCII. |
950 LChar* data; | 947 LChar* data; |
951 RefPtr<StringImpl> new_impl = CreateUninitialized(length_, data); | 948 RefPtr<StringImpl> new_impl = CreateUninitialized(length_, data); |
952 LChar ored = 0; | 949 LChar ored = 0; |
953 | 950 |
954 for (int32_t i = 0; i < length; ++i) { | 951 for (int32_t i = 0; i < length; ++i) { |
955 LChar c = Characters8()[i]; | 952 LChar c = Characters8()[i]; |
(...skipping 798 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1754 // behavior. | 1751 // behavior. |
1755 PassRefPtr<StringImpl> StringImpl::Replace(unsigned position, | 1752 PassRefPtr<StringImpl> StringImpl::Replace(unsigned position, |
1756 unsigned length_to_replace, | 1753 unsigned length_to_replace, |
1757 const StringView& string) { | 1754 const StringView& string) { |
1758 position = min(position, length()); | 1755 position = min(position, length()); |
1759 length_to_replace = min(length_to_replace, length() - position); | 1756 length_to_replace = min(length_to_replace, length() - position); |
1760 unsigned length_to_insert = string.length(); | 1757 unsigned length_to_insert = string.length(); |
1761 if (!length_to_replace && !length_to_insert) | 1758 if (!length_to_replace && !length_to_insert) |
1762 return this; | 1759 return this; |
1763 | 1760 |
1764 RELEASE_ASSERT((length() - length_to_replace) < | 1761 CHECK_LT((length() - length_to_replace), |
1765 (numeric_limits<unsigned>::max() - length_to_insert)); | 1762 (numeric_limits<unsigned>::max() - length_to_insert)); |
1766 | 1763 |
1767 if (Is8Bit() && (string.IsNull() || string.Is8Bit())) { | 1764 if (Is8Bit() && (string.IsNull() || string.Is8Bit())) { |
1768 LChar* data; | 1765 LChar* data; |
1769 RefPtr<StringImpl> new_impl = CreateUninitialized( | 1766 RefPtr<StringImpl> new_impl = CreateUninitialized( |
1770 length() - length_to_replace + length_to_insert, data); | 1767 length() - length_to_replace + length_to_insert, data); |
1771 memcpy(data, Characters8(), position * sizeof(LChar)); | 1768 memcpy(data, Characters8(), position * sizeof(LChar)); |
1772 if (!string.IsNull()) | 1769 if (!string.IsNull()) |
1773 memcpy(data + position, string.Characters8(), | 1770 memcpy(data + position, string.Characters8(), |
1774 length_to_insert * sizeof(LChar)); | 1771 length_to_insert * sizeof(LChar)); |
1775 memcpy(data + position + length_to_insert, | 1772 memcpy(data + position + length_to_insert, |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1825 // Count the matches. | 1822 // Count the matches. |
1826 while ((src_segment_start = Find(pattern, src_segment_start)) != kNotFound) { | 1823 while ((src_segment_start = Find(pattern, src_segment_start)) != kNotFound) { |
1827 ++match_count; | 1824 ++match_count; |
1828 ++src_segment_start; | 1825 ++src_segment_start; |
1829 } | 1826 } |
1830 | 1827 |
1831 // If we have 0 matches then we don't have to do any more work. | 1828 // If we have 0 matches then we don't have to do any more work. |
1832 if (!match_count) | 1829 if (!match_count) |
1833 return this; | 1830 return this; |
1834 | 1831 |
1835 RELEASE_ASSERT(!rep_str_length || | 1832 CHECK(!rep_str_length || |
1836 match_count <= | 1833 match_count <= numeric_limits<unsigned>::max() / rep_str_length); |
1837 numeric_limits<unsigned>::max() / rep_str_length); | |
1838 | 1834 |
1839 unsigned replace_size = match_count * rep_str_length; | 1835 unsigned replace_size = match_count * rep_str_length; |
1840 unsigned new_size = length_ - match_count; | 1836 unsigned new_size = length_ - match_count; |
1841 RELEASE_ASSERT(new_size < (numeric_limits<unsigned>::max() - replace_size)); | 1837 CHECK_LT(new_size, (numeric_limits<unsigned>::max() - replace_size)); |
1842 | 1838 |
1843 new_size += replace_size; | 1839 new_size += replace_size; |
1844 | 1840 |
1845 // Construct the new data. | 1841 // Construct the new data. |
1846 size_t src_segment_end; | 1842 size_t src_segment_end; |
1847 unsigned src_segment_length; | 1843 unsigned src_segment_length; |
1848 src_segment_start = 0; | 1844 src_segment_start = 0; |
1849 unsigned dst_offset = 0; | 1845 unsigned dst_offset = 0; |
1850 | 1846 |
1851 if (Is8Bit()) { | 1847 if (Is8Bit()) { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1907 // Count the matches. | 1903 // Count the matches. |
1908 while ((src_segment_start = Find(pattern, src_segment_start)) != kNotFound) { | 1904 while ((src_segment_start = Find(pattern, src_segment_start)) != kNotFound) { |
1909 ++match_count; | 1905 ++match_count; |
1910 ++src_segment_start; | 1906 ++src_segment_start; |
1911 } | 1907 } |
1912 | 1908 |
1913 // If we have 0 matches then we don't have to do any more work. | 1909 // If we have 0 matches then we don't have to do any more work. |
1914 if (!match_count) | 1910 if (!match_count) |
1915 return this; | 1911 return this; |
1916 | 1912 |
1917 RELEASE_ASSERT(!rep_str_length || | 1913 CHECK(!rep_str_length || |
1918 match_count <= | 1914 match_count <= numeric_limits<unsigned>::max() / rep_str_length); |
1919 numeric_limits<unsigned>::max() / rep_str_length); | |
1920 | 1915 |
1921 unsigned replace_size = match_count * rep_str_length; | 1916 unsigned replace_size = match_count * rep_str_length; |
1922 unsigned new_size = length_ - match_count; | 1917 unsigned new_size = length_ - match_count; |
1923 RELEASE_ASSERT(new_size < (numeric_limits<unsigned>::max() - replace_size)); | 1918 CHECK_LT(new_size, (numeric_limits<unsigned>::max() - replace_size)); |
1924 | 1919 |
1925 new_size += replace_size; | 1920 new_size += replace_size; |
1926 | 1921 |
1927 // Construct the new data. | 1922 // Construct the new data. |
1928 size_t src_segment_end; | 1923 size_t src_segment_end; |
1929 unsigned src_segment_length; | 1924 unsigned src_segment_length; |
1930 src_segment_start = 0; | 1925 src_segment_start = 0; |
1931 unsigned dst_offset = 0; | 1926 unsigned dst_offset = 0; |
1932 | 1927 |
1933 if (Is8Bit()) { | 1928 if (Is8Bit()) { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1996 while ((src_segment_start = Find(pattern, src_segment_start)) != kNotFound) { | 1991 while ((src_segment_start = Find(pattern, src_segment_start)) != kNotFound) { |
1997 ++match_count; | 1992 ++match_count; |
1998 src_segment_start += pattern_length; | 1993 src_segment_start += pattern_length; |
1999 } | 1994 } |
2000 | 1995 |
2001 // If we have 0 matches, we don't have to do any more work | 1996 // If we have 0 matches, we don't have to do any more work |
2002 if (!match_count) | 1997 if (!match_count) |
2003 return this; | 1998 return this; |
2004 | 1999 |
2005 unsigned new_size = length_ - match_count * pattern_length; | 2000 unsigned new_size = length_ - match_count * pattern_length; |
2006 RELEASE_ASSERT(!rep_str_length || | 2001 CHECK(!rep_str_length || |
2007 match_count <= | 2002 match_count <= numeric_limits<unsigned>::max() / rep_str_length); |
2008 numeric_limits<unsigned>::max() / rep_str_length); | |
2009 | 2003 |
2010 RELEASE_ASSERT(new_size <= (numeric_limits<unsigned>::max() - | 2004 CHECK_LE(new_size, |
2011 match_count * rep_str_length)); | 2005 (numeric_limits<unsigned>::max() - match_count * rep_str_length)); |
2012 | 2006 |
2013 new_size += match_count * rep_str_length; | 2007 new_size += match_count * rep_str_length; |
2014 | 2008 |
2015 // Construct the new data | 2009 // Construct the new data |
2016 size_t src_segment_end; | 2010 size_t src_segment_end; |
2017 unsigned src_segment_length; | 2011 unsigned src_segment_length; |
2018 src_segment_start = 0; | 2012 src_segment_start = 0; |
2019 unsigned dst_offset = 0; | 2013 unsigned dst_offset = 0; |
2020 bool src_is8_bit = Is8Bit(); | 2014 bool src_is8_bit = Is8Bit(); |
2021 bool replacement_is8_bit = replacement.Is8Bit(); | 2015 bool replacement_is8_bit = replacement.Is8Bit(); |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2256 } else if (LocaleIdMatchesLang(locale_identifier, "lt")) { | 2250 } else if (LocaleIdMatchesLang(locale_identifier, "lt")) { |
2257 // TODO(rob.buis) implement upper-casing rules for lt | 2251 // TODO(rob.buis) implement upper-casing rules for lt |
2258 // like in StringImpl::upper(locale). | 2252 // like in StringImpl::upper(locale). |
2259 } | 2253 } |
2260 } | 2254 } |
2261 | 2255 |
2262 return ToUpper(c); | 2256 return ToUpper(c); |
2263 } | 2257 } |
2264 | 2258 |
2265 } // namespace WTF | 2259 } // namespace WTF |
OLD | NEW |