| OLD | NEW |
| 1 /* | 1 /* |
| 2 * (C) 1999 Lars Knoll (knoll@kde.org) | 2 * (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010, 2012 Apple Inc. All rights
reserved. | 3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010, 2012 Apple Inc. All rights
reserved. |
| 4 * Copyright (C) 2007-2009 Torch Mobile, Inc. | 4 * Copyright (C) 2007-2009 Torch Mobile, Inc. |
| 5 * | 5 * |
| 6 * This library is free software; you can redistribute it and/or | 6 * This library is free software; you can redistribute it and/or |
| 7 * modify it under the terms of the GNU Library General Public | 7 * modify it under the terms of the GNU Library General Public |
| 8 * License as published by the Free Software Foundation; either | 8 * License as published by the Free Software Foundation; either |
| 9 * version 2 of the License, or (at your option) any later version. | 9 * version 2 of the License, or (at your option) any later version. |
| 10 * | 10 * |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 #include "wtf/MathExtras.h" | 29 #include "wtf/MathExtras.h" |
| 30 #include "wtf/StringExtras.h" | 30 #include "wtf/StringExtras.h" |
| 31 #include "wtf/Vector.h" | 31 #include "wtf/Vector.h" |
| 32 #include "wtf/dtoa.h" | 32 #include "wtf/dtoa.h" |
| 33 #include "wtf/text/CString.h" | 33 #include "wtf/text/CString.h" |
| 34 #include "wtf/text/CharacterNames.h" | 34 #include "wtf/text/CharacterNames.h" |
| 35 #include "wtf/text/UTF8.h" | 35 #include "wtf/text/UTF8.h" |
| 36 #include "wtf/text/Unicode.h" | 36 #include "wtf/text/Unicode.h" |
| 37 #include <stdarg.h> | 37 #include <stdarg.h> |
| 38 | 38 |
| 39 using namespace std; | |
| 40 | |
| 41 namespace WTF { | 39 namespace WTF { |
| 42 | 40 |
| 43 using namespace Unicode; | 41 using namespace Unicode; |
| 44 using namespace std; | |
| 45 | 42 |
| 46 // Construct a string with UTF-16 data. | 43 // Construct a string with UTF-16 data. |
| 47 String::String(const UChar* characters, unsigned length) | 44 String::String(const UChar* characters, unsigned length) |
| 48 : m_impl(characters ? StringImpl::create(characters, length) : nullptr) | 45 : m_impl(characters ? StringImpl::create(characters, length) : nullptr) |
| 49 { | 46 { |
| 50 } | 47 } |
| 51 | 48 |
| 52 // Construct a string with UTF-16 data, from a null-terminated source. | 49 // Construct a string with UTF-16 data, from a null-terminated source. |
| 53 String::String(const UChar* str) | 50 String::String(const UChar* str) |
| 54 { | 51 { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 81 | 78 |
| 82 void String::append(const String& string) | 79 void String::append(const String& string) |
| 83 { | 80 { |
| 84 if (string.isEmpty()) | 81 if (string.isEmpty()) |
| 85 return; | 82 return; |
| 86 if (!m_impl) { | 83 if (!m_impl) { |
| 87 m_impl = string.m_impl; | 84 m_impl = string.m_impl; |
| 88 return; | 85 return; |
| 89 } | 86 } |
| 90 | 87 |
| 91 // FIXME: This is extremely inefficient. So much so that we might want to ta
ke this | 88 // FIXME: This is extremely inefficient. So much so that we might want to |
| 92 // out of String's API. We can make it better by optimizing the case where e
xactly | 89 // take this out of String's API. We can make it better by optimizing the |
| 93 // one String is pointing at this StringImpl, but even then it's going to re
quire a | 90 // case where exactly one String is pointing at this StringImpl, but even |
| 94 // call into the allocator every single time. | 91 // then it's going to require a call into the allocator every single time. |
| 95 | 92 |
| 96 if (m_impl->is8Bit() && string.m_impl->is8Bit()) { | 93 if (m_impl->is8Bit() && string.m_impl->is8Bit()) { |
| 97 LChar* data; | 94 LChar* data; |
| 98 RELEASE_ASSERT(string.length() <= numeric_limits<unsigned>::max() - m_im
pl->length()); | 95 RELEASE_ASSERT(string.length() <= std::numeric_limits<unsigned>::max() -
m_impl->length()); |
| 99 RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(m_impl->len
gth() + string.length(), data); | 96 RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(m_impl->len
gth() + string.length(), data); |
| 100 memcpy(data, m_impl->characters8(), m_impl->length() * sizeof(LChar)); | 97 memcpy(data, m_impl->characters8(), m_impl->length() * sizeof(LChar)); |
| 101 memcpy(data + m_impl->length(), string.characters8(), string.length() *
sizeof(LChar)); | 98 memcpy(data + m_impl->length(), string.characters8(), string.length() *
sizeof(LChar)); |
| 102 m_impl = newImpl.release(); | 99 m_impl = newImpl.release(); |
| 103 return; | 100 return; |
| 104 } | 101 } |
| 105 | 102 |
| 106 UChar* data; | 103 UChar* data; |
| 107 RELEASE_ASSERT(string.length() <= numeric_limits<unsigned>::max() - m_impl->
length()); | 104 RELEASE_ASSERT(string.length() <= std::numeric_limits<unsigned>::max() - m_i
mpl->length()); |
| 108 RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(m_impl->length(
) + string.length(), data); | 105 RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(m_impl->length(
) + string.length(), data); |
| 109 | 106 |
| 110 if (m_impl->is8Bit()) | 107 if (m_impl->is8Bit()) |
| 111 StringImpl::copyChars(data, m_impl->characters8(), m_impl->length()); | 108 StringImpl::copyChars(data, m_impl->characters8(), m_impl->length()); |
| 112 else | 109 else |
| 113 StringImpl::copyChars(data, m_impl->characters16(), m_impl->length()); | 110 StringImpl::copyChars(data, m_impl->characters16(), m_impl->length()); |
| 114 | 111 |
| 115 if (string.impl()->is8Bit()) | 112 if (string.impl()->is8Bit()) |
| 116 StringImpl::copyChars(data + m_impl->length(), string.impl()->characters
8(), string.impl()->length()); | 113 StringImpl::copyChars(data + m_impl->length(), string.impl()->characters
8(), string.impl()->length()); |
| 117 else | 114 else |
| 118 StringImpl::copyChars(data + m_impl->length(), string.impl()->characters
16(), string.impl()->length()); | 115 StringImpl::copyChars(data + m_impl->length(), string.impl()->characters
16(), string.impl()->length()); |
| 119 | 116 |
| 120 m_impl = newImpl.release(); | 117 m_impl = newImpl.release(); |
| 121 } | 118 } |
| 122 | 119 |
| 123 template <typename CharacterType> | 120 template <typename CharacterType> |
| 124 inline void String::appendInternal(CharacterType c) | 121 inline void String::appendInternal(CharacterType c) |
| 125 { | 122 { |
| 126 // FIXME: This is extremely inefficient. So much so that we might want to ta
ke this | 123 // FIXME: This is extremely inefficient. So much so that we might want to |
| 127 // out of String's API. We can make it better by optimizing the case where e
xactly | 124 // take this out of String's API. We can make it better by optimizing the |
| 128 // one String is pointing at this StringImpl, but even then it's going to re
quire a | 125 // case where exactly one String is pointing at this StringImpl, but even |
| 129 // call into the allocator every single time. | 126 // then it's going to require a call into the allocator every single time. |
| 130 if (!m_impl) { | 127 if (!m_impl) { |
| 131 m_impl = StringImpl::create(&c, 1); | 128 m_impl = StringImpl::create(&c, 1); |
| 132 return; | 129 return; |
| 133 } | 130 } |
| 134 | 131 |
| 135 UChar* data; // FIXME: We should be able to create an 8 bit string via this
code path. | 132 // FIXME: We should be able to create an 8 bit string via this code path. |
| 136 RELEASE_ASSERT(m_impl->length() < numeric_limits<unsigned>::max()); | 133 UChar* data; |
| 134 RELEASE_ASSERT(m_impl->length() < std::numeric_limits<unsigned>::max()); |
| 137 RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(m_impl->length(
) + 1, data); | 135 RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(m_impl->length(
) + 1, data); |
| 138 if (m_impl->is8Bit()) | 136 if (m_impl->is8Bit()) |
| 139 StringImpl::copyChars(data, m_impl->characters8(), m_impl->length()); | 137 StringImpl::copyChars(data, m_impl->characters8(), m_impl->length()); |
| 140 else | 138 else |
| 141 StringImpl::copyChars(data, m_impl->characters16(), m_impl->length()); | 139 StringImpl::copyChars(data, m_impl->characters16(), m_impl->length()); |
| 142 data[m_impl->length()] = c; | 140 data[m_impl->length()] = c; |
| 143 m_impl = newImpl.release(); | 141 m_impl = newImpl.release(); |
| 144 } | 142 } |
| 145 | 143 |
| 146 void String::append(LChar c) | 144 void String::append(LChar c) |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 } | 182 } |
| 185 | 183 |
| 186 if (!lengthToAppend) | 184 if (!lengthToAppend) |
| 187 return; | 185 return; |
| 188 | 186 |
| 189 ASSERT(charactersToAppend); | 187 ASSERT(charactersToAppend); |
| 190 | 188 |
| 191 unsigned strLength = m_impl->length(); | 189 unsigned strLength = m_impl->length(); |
| 192 | 190 |
| 193 if (m_impl->is8Bit()) { | 191 if (m_impl->is8Bit()) { |
| 194 RELEASE_ASSERT(lengthToAppend <= numeric_limits<unsigned>::max() - strLe
ngth); | 192 RELEASE_ASSERT(lengthToAppend <= std::numeric_limits<unsigned>::max() -
strLength); |
| 195 LChar* data; | 193 LChar* data; |
| 196 RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(strLength +
lengthToAppend, data); | 194 RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(strLength +
lengthToAppend, data); |
| 197 StringImpl::copyChars(data, m_impl->characters8(), strLength); | 195 StringImpl::copyChars(data, m_impl->characters8(), strLength); |
| 198 StringImpl::copyChars(data + strLength, charactersToAppend, lengthToAppe
nd); | 196 StringImpl::copyChars(data + strLength, charactersToAppend, lengthToAppe
nd); |
| 199 m_impl = newImpl.release(); | 197 m_impl = newImpl.release(); |
| 200 return; | 198 return; |
| 201 } | 199 } |
| 202 | 200 |
| 203 RELEASE_ASSERT(lengthToAppend <= numeric_limits<unsigned>::max() - strLength
); | 201 RELEASE_ASSERT(lengthToAppend <= std::numeric_limits<unsigned>::max() - strL
ength); |
| 204 UChar* data; | 202 UChar* data; |
| 205 RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(length() + leng
thToAppend, data); | 203 RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(length() + leng
thToAppend, data); |
| 206 StringImpl::copyChars(data, m_impl->characters16(), strLength); | 204 StringImpl::copyChars(data, m_impl->characters16(), strLength); |
| 207 StringImpl::copyChars(data + strLength, charactersToAppend, lengthToAppend); | 205 StringImpl::copyChars(data + strLength, charactersToAppend, lengthToAppend); |
| 208 m_impl = newImpl.release(); | 206 m_impl = newImpl.release(); |
| 209 } | 207 } |
| 210 | 208 |
| 211 void String::append(const UChar* charactersToAppend, unsigned lengthToAppend) | 209 void String::append(const UChar* charactersToAppend, unsigned lengthToAppend) |
| 212 { | 210 { |
| 213 if (!m_impl) { | 211 if (!m_impl) { |
| 214 if (!charactersToAppend) | 212 if (!charactersToAppend) |
| 215 return; | 213 return; |
| 216 m_impl = StringImpl::create(charactersToAppend, lengthToAppend); | 214 m_impl = StringImpl::create(charactersToAppend, lengthToAppend); |
| 217 return; | 215 return; |
| 218 } | 216 } |
| 219 | 217 |
| 220 if (!lengthToAppend) | 218 if (!lengthToAppend) |
| 221 return; | 219 return; |
| 222 | 220 |
| 223 unsigned strLength = m_impl->length(); | 221 unsigned strLength = m_impl->length(); |
| 224 | 222 |
| 225 ASSERT(charactersToAppend); | 223 ASSERT(charactersToAppend); |
| 226 RELEASE_ASSERT(lengthToAppend <= numeric_limits<unsigned>::max() - strLength
); | 224 RELEASE_ASSERT(lengthToAppend <= std::numeric_limits<unsigned>::max() - strL
ength); |
| 227 UChar* data; | 225 UChar* data; |
| 228 RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(strLength + len
gthToAppend, data); | 226 RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(strLength + len
gthToAppend, data); |
| 229 if (m_impl->is8Bit()) | 227 if (m_impl->is8Bit()) |
| 230 StringImpl::copyChars(data, characters8(), strLength); | 228 StringImpl::copyChars(data, characters8(), strLength); |
| 231 else | 229 else |
| 232 StringImpl::copyChars(data, characters16(), strLength); | 230 StringImpl::copyChars(data, characters16(), strLength); |
| 233 StringImpl::copyChars(data + strLength, charactersToAppend, lengthToAppend); | 231 StringImpl::copyChars(data + strLength, charactersToAppend, lengthToAppend); |
| 234 m_impl = newImpl.release(); | 232 m_impl = newImpl.release(); |
| 235 } | 233 } |
| 236 | 234 |
| 237 template<typename CharType> | 235 template<typename CharType> |
| 238 PassRefPtr<StringImpl> insertInternal(PassRefPtr<StringImpl> impl, const CharTyp
e* charactersToInsert, unsigned lengthToInsert, unsigned position) | 236 PassRefPtr<StringImpl> insertInternal(PassRefPtr<StringImpl> impl, const CharTyp
e* charactersToInsert, unsigned lengthToInsert, unsigned position) |
| 239 { | 237 { |
| 240 if (!lengthToInsert) | 238 if (!lengthToInsert) |
| 241 return impl; | 239 return impl; |
| 242 | 240 |
| 243 ASSERT(charactersToInsert); | 241 ASSERT(charactersToInsert); |
| 244 UChar* data; // FIXME: We should be able to create an 8 bit string here. | 242 UChar* data; // FIXME: We should be able to create an 8 bit string here. |
| 245 RELEASE_ASSERT(lengthToInsert <= numeric_limits<unsigned>::max() - impl->len
gth()); | 243 RELEASE_ASSERT(lengthToInsert <= std::numeric_limits<unsigned>::max() - impl
->length()); |
| 246 RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(impl->length()
+ lengthToInsert, data); | 244 RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(impl->length()
+ lengthToInsert, data); |
| 247 | 245 |
| 248 if (impl->is8Bit()) | 246 if (impl->is8Bit()) |
| 249 StringImpl::copyChars(data, impl->characters8(), position); | 247 StringImpl::copyChars(data, impl->characters8(), position); |
| 250 else | 248 else |
| 251 StringImpl::copyChars(data, impl->characters16(), position); | 249 StringImpl::copyChars(data, impl->characters16(), position); |
| 252 | 250 |
| 253 StringImpl::copyChars(data + position, charactersToInsert, lengthToInsert); | 251 StringImpl::copyChars(data + position, charactersToInsert, lengthToInsert); |
| 254 | 252 |
| 255 if (impl->is8Bit()) | 253 if (impl->is8Bit()) |
| (...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 766 // Allocate a buffer big enough to hold all the characters | 764 // Allocate a buffer big enough to hold all the characters |
| 767 // (an individual UTF-16 UChar can only expand to 3 UTF-8 bytes). | 765 // (an individual UTF-16 UChar can only expand to 3 UTF-8 bytes). |
| 768 // Optimization ideas, if we find this function is hot: | 766 // Optimization ideas, if we find this function is hot: |
| 769 // * We could speculatively create a CStringBuffer to contain 'length' | 767 // * We could speculatively create a CStringBuffer to contain 'length' |
| 770 // characters, and resize if necessary (i.e. if the buffer contains | 768 // characters, and resize if necessary (i.e. if the buffer contains |
| 771 // non-ascii characters). (Alternatively, scan the buffer first for | 769 // non-ascii characters). (Alternatively, scan the buffer first for |
| 772 // ascii characters, so we know this will be sufficient). | 770 // ascii characters, so we know this will be sufficient). |
| 773 // * We could allocate a CStringBuffer with an appropriate size to | 771 // * We could allocate a CStringBuffer with an appropriate size to |
| 774 // have a good chance of being able to write the string into the | 772 // have a good chance of being able to write the string into the |
| 775 // buffer without reallocing (say, 1.5 x length). | 773 // buffer without reallocing (say, 1.5 x length). |
| 776 if (length > numeric_limits<unsigned>::max() / 3) | 774 if (length > std::numeric_limits<unsigned>::max() / 3) |
| 777 return CString(); | 775 return CString(); |
| 778 Vector<char, 1024> bufferVector(length * 3); | 776 Vector<char, 1024> bufferVector(length * 3); |
| 779 | 777 |
| 780 char* buffer = bufferVector.data(); | 778 char* buffer = bufferVector.data(); |
| 781 | 779 |
| 782 if (is8Bit()) { | 780 if (is8Bit()) { |
| 783 const LChar* characters = this->characters8(); | 781 const LChar* characters = this->characters8(); |
| 784 | 782 |
| 785 ConversionResult result = convertLatin1ToUTF8(&characters, characters +
length, &buffer, buffer + bufferVector.size()); | 783 ConversionResult result = convertLatin1ToUTF8(&characters, characters +
length, &buffer, buffer + bufferVector.size()); |
| 786 ASSERT_UNUSED(result, result != targetExhausted); // (length * 3) should
be sufficient for any conversion | 784 ASSERT_UNUSED(result, result != targetExhausted); // (length * 3) should
be sufficient for any conversion |
| 787 } else { | 785 } else { |
| 788 const UChar* characters = this->characters16(); | 786 const UChar* characters = this->characters16(); |
| 789 | 787 |
| 790 if (mode == StrictUTF8ConversionReplacingUnpairedSurrogatesWithFFFD) { | 788 if (mode == StrictUTF8ConversionReplacingUnpairedSurrogatesWithFFFD) { |
| 791 const UChar* charactersEnd = characters + length; | 789 const UChar* charactersEnd = characters + length; |
| 792 char* bufferEnd = buffer + bufferVector.size(); | 790 char* bufferEnd = buffer + bufferVector.size(); |
| 793 while (characters < charactersEnd) { | 791 while (characters < charactersEnd) { |
| 794 // Use strict conversion to detect unpaired surrogates. | 792 // Use strict conversion to detect unpaired surrogates. |
| 795 ConversionResult result = convertUTF16ToUTF8(&characters, charac
tersEnd, &buffer, bufferEnd, true); | 793 ConversionResult result = convertUTF16ToUTF8(&characters, charac
tersEnd, &buffer, bufferEnd, true); |
| 796 ASSERT(result != targetExhausted); | 794 ASSERT(result != targetExhausted); |
| 797 // Conversion fails when there is an unpaired surrogate. | 795 // Conversion fails when there is an unpaired surrogate. Put |
| 798 // Put replacement character (U+FFFD) instead of the unpaired su
rrogate. | 796 // replacement character (U+FFFD) instead of the unpaired |
| 797 // surrogate. |
| 799 if (result != conversionOK) { | 798 if (result != conversionOK) { |
| 800 ASSERT((0xD800 <= *characters && *characters <= 0xDFFF)); | 799 ASSERT((0xD800 <= *characters && *characters <= 0xDFFF)); |
| 801 // There should be room left, since one UChar hasn't been co
nverted. | 800 // There should be room left, since one UChar hasn't been |
| 801 // converted. |
| 802 ASSERT((buffer + 3) <= bufferEnd); | 802 ASSERT((buffer + 3) <= bufferEnd); |
| 803 putUTF8Triple(buffer, replacementCharacter); | 803 putUTF8Triple(buffer, replacementCharacter); |
| 804 ++characters; | 804 ++characters; |
| 805 } | 805 } |
| 806 } | 806 } |
| 807 } else { | 807 } else { |
| 808 bool strict = mode == StrictUTF8Conversion; | 808 bool strict = mode == StrictUTF8Conversion; |
| 809 ConversionResult result = convertUTF16ToUTF8(&characters, characters
+ length, &buffer, buffer + bufferVector.size(), strict); | 809 ConversionResult result = convertUTF16ToUTF8(&characters, characters
+ length, &buffer, buffer + bufferVector.size(), strict); |
| 810 ASSERT(result != targetExhausted); // (length * 3) should be suffici
ent for any conversion | 810 ASSERT(result != targetExhausted); // (length * 3) should be suffici
ent for any conversion |
| 811 | 811 |
| 812 // Only produced from strict conversion. | 812 // Only produced from strict conversion. |
| 813 if (result == sourceIllegal) { | 813 if (result == sourceIllegal) { |
| 814 ASSERT(strict); | 814 ASSERT(strict); |
| 815 return CString(); | 815 return CString(); |
| 816 } | 816 } |
| 817 | 817 |
| 818 // Check for an unconverted high surrogate. | 818 // Check for an unconverted high surrogate. |
| 819 if (result == sourceExhausted) { | 819 if (result == sourceExhausted) { |
| 820 if (strict) | 820 if (strict) |
| 821 return CString(); | 821 return CString(); |
| 822 // This should be one unpaired high surrogate. Treat it the same | 822 // This should be one unpaired high surrogate. Treat it the same |
| 823 // was as an unpaired high surrogate would have been handled in | 823 // was as an unpaired high surrogate would have been handled in |
| 824 // the middle of a string with non-strict conversion - which is | 824 // the middle of a string with non-strict conversion - which is |
| 825 // to say, simply encode it to UTF-8. | 825 // to say, simply encode it to UTF-8. |
| 826 ASSERT((characters + 1) == (this->characters16() + length)); | 826 ASSERT((characters + 1) == (this->characters16() + length)); |
| 827 ASSERT((*characters >= 0xD800) && (*characters <= 0xDBFF)); | 827 ASSERT((*characters >= 0xD800) && (*characters <= 0xDBFF)); |
| 828 // There should be room left, since one UChar hasn't been conver
ted. | 828 // There should be room left, since one UChar hasn't been |
| 829 // converted. |
| 829 ASSERT((buffer + 3) <= (buffer + bufferVector.size())); | 830 ASSERT((buffer + 3) <= (buffer + bufferVector.size())); |
| 830 putUTF8Triple(buffer, *characters); | 831 putUTF8Triple(buffer, *characters); |
| 831 } | 832 } |
| 832 } | 833 } |
| 833 } | 834 } |
| 834 | 835 |
| 835 return CString(bufferVector.data(), buffer - bufferVector.data()); | 836 return CString(bufferVector.data(), buffer - bufferVector.data()); |
| 836 } | 837 } |
| 837 | 838 |
| 838 String String::make8BitFrom16BitSource(const UChar* source, size_t length) | 839 String String::make8BitFrom16BitSource(const UChar* source, size_t length) |
| (...skipping 17 matching lines...) Expand all Loading... |
| 856 UChar* destination; | 857 UChar* destination; |
| 857 String result = String::createUninitialized(length, destination); | 858 String result = String::createUninitialized(length, destination); |
| 858 | 859 |
| 859 StringImpl::copyChars(destination, source, length); | 860 StringImpl::copyChars(destination, source, length); |
| 860 | 861 |
| 861 return result; | 862 return result; |
| 862 } | 863 } |
| 863 | 864 |
| 864 String String::fromUTF8(const LChar* stringStart, size_t length) | 865 String String::fromUTF8(const LChar* stringStart, size_t length) |
| 865 { | 866 { |
| 866 RELEASE_ASSERT(length <= numeric_limits<unsigned>::max()); | 867 RELEASE_ASSERT(length <= std::numeric_limits<unsigned>::max()); |
| 867 | 868 |
| 868 if (!stringStart) | 869 if (!stringStart) |
| 869 return String(); | 870 return String(); |
| 870 | 871 |
| 871 if (!length) | 872 if (!length) |
| 872 return emptyString(); | 873 return emptyString(); |
| 873 | 874 |
| 874 if (charactersAreAllASCII(stringStart, length)) | 875 if (charactersAreAllASCII(stringStart, length)) |
| 875 return StringImpl::create(stringStart, length); | 876 return StringImpl::create(stringStart, length); |
| 876 | 877 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 920 base = 36; | 921 base = 36; |
| 921 return (c >= 'a' && c < 'a' + base - 10) | 922 return (c >= 'a' && c < 'a' + base - 10) |
| 922 || (c >= 'A' && c < 'A' + base - 10); | 923 || (c >= 'A' && c < 'A' + base - 10); |
| 923 } | 924 } |
| 924 return false; | 925 return false; |
| 925 } | 926 } |
| 926 | 927 |
| 927 template <typename IntegralType, typename CharType> | 928 template <typename IntegralType, typename CharType> |
| 928 static inline IntegralType toIntegralType(const CharType* data, size_t length, b
ool* ok, int base) | 929 static inline IntegralType toIntegralType(const CharType* data, size_t length, b
ool* ok, int base) |
| 929 { | 930 { |
| 930 static const IntegralType integralMax = numeric_limits<IntegralType>::max(); | 931 static const IntegralType integralMax = std::numeric_limits<IntegralType>::m
ax(); |
| 931 static const bool isSigned = numeric_limits<IntegralType>::is_signed; | 932 static const bool isSigned = std::numeric_limits<IntegralType>::is_signed; |
| 932 const IntegralType maxMultiplier = integralMax / base; | 933 const IntegralType maxMultiplier = integralMax / base; |
| 933 | 934 |
| 934 IntegralType value = 0; | 935 IntegralType value = 0; |
| 935 bool isOk = false; | 936 bool isOk = false; |
| 936 bool isNegative = false; | 937 bool isNegative = false; |
| 937 | 938 |
| 938 if (!data) | 939 if (!data) |
| 939 goto bye; | 940 goto bye; |
| 940 | 941 |
| 941 // skip leading whitespace | 942 // skip leading whitespace |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1133 } | 1134 } |
| 1134 | 1135 |
| 1135 double charactersToDouble(const UChar* data, size_t length, bool* ok) | 1136 double charactersToDouble(const UChar* data, size_t length, bool* ok) |
| 1136 { | 1137 { |
| 1137 size_t parsedLength; | 1138 size_t parsedLength; |
| 1138 return toDoubleType<UChar, DisallowTrailingJunk>(data, length, ok, parsedLen
gth); | 1139 return toDoubleType<UChar, DisallowTrailingJunk>(data, length, ok, parsedLen
gth); |
| 1139 } | 1140 } |
| 1140 | 1141 |
| 1141 float charactersToFloat(const LChar* data, size_t length, bool* ok) | 1142 float charactersToFloat(const LChar* data, size_t length, bool* ok) |
| 1142 { | 1143 { |
| 1143 // FIXME: This will return ok even when the string fits into a double but no
t a float. | 1144 // FIXME: This will return ok even when the string fits into a double but |
| 1145 // not a float. |
| 1144 size_t parsedLength; | 1146 size_t parsedLength; |
| 1145 return static_cast<float>(toDoubleType<LChar, DisallowTrailingJunk>(data, le
ngth, ok, parsedLength)); | 1147 return static_cast<float>(toDoubleType<LChar, DisallowTrailingJunk>(data, le
ngth, ok, parsedLength)); |
| 1146 } | 1148 } |
| 1147 | 1149 |
| 1148 float charactersToFloat(const UChar* data, size_t length, bool* ok) | 1150 float charactersToFloat(const UChar* data, size_t length, bool* ok) |
| 1149 { | 1151 { |
| 1150 // FIXME: This will return ok even when the string fits into a double but no
t a float. | 1152 // FIXME: This will return ok even when the string fits into a double but |
| 1153 // not a float. |
| 1151 size_t parsedLength; | 1154 size_t parsedLength; |
| 1152 return static_cast<float>(toDoubleType<UChar, DisallowTrailingJunk>(data, le
ngth, ok, parsedLength)); | 1155 return static_cast<float>(toDoubleType<UChar, DisallowTrailingJunk>(data, le
ngth, ok, parsedLength)); |
| 1153 } | 1156 } |
| 1154 | 1157 |
| 1155 float charactersToFloat(const LChar* data, size_t length, size_t& parsedLength) | 1158 float charactersToFloat(const LChar* data, size_t length, size_t& parsedLength) |
| 1156 { | 1159 { |
| 1157 // FIXME: This will return ok even when the string fits into a double but no
t a float. | 1160 // FIXME: This will return ok even when the string fits into a double but |
| 1161 // not a float. |
| 1158 return static_cast<float>(toDoubleType<LChar, AllowTrailingJunk>(data, lengt
h, 0, parsedLength)); | 1162 return static_cast<float>(toDoubleType<LChar, AllowTrailingJunk>(data, lengt
h, 0, parsedLength)); |
| 1159 } | 1163 } |
| 1160 | 1164 |
| 1161 float charactersToFloat(const UChar* data, size_t length, size_t& parsedLength) | 1165 float charactersToFloat(const UChar* data, size_t length, size_t& parsedLength) |
| 1162 { | 1166 { |
| 1163 // FIXME: This will return ok even when the string fits into a double but no
t a float. | 1167 // FIXME: This will return ok even when the string fits into a double but |
| 1168 // not a float. |
| 1164 return static_cast<float>(toDoubleType<UChar, AllowTrailingJunk>(data, lengt
h, 0, parsedLength)); | 1169 return static_cast<float>(toDoubleType<UChar, AllowTrailingJunk>(data, lengt
h, 0, parsedLength)); |
| 1165 } | 1170 } |
| 1166 | 1171 |
| 1167 const String& emptyString() | 1172 const String& emptyString() |
| 1168 { | 1173 { |
| 1169 DEFINE_STATIC_LOCAL(String, emptyString, (StringImpl::empty())); | 1174 DEFINE_STATIC_LOCAL(String, emptyString, (StringImpl::empty())); |
| 1170 return emptyString; | 1175 return emptyString; |
| 1171 } | 1176 } |
| 1172 | 1177 |
| 1173 const String& emptyString16Bit() | 1178 const String& emptyString16Bit() |
| 1174 { | 1179 { |
| 1175 DEFINE_STATIC_LOCAL(String, emptyString, (StringImpl::empty16Bit())); | 1180 DEFINE_STATIC_LOCAL(String, emptyString, (StringImpl::empty16Bit())); |
| 1176 return emptyString; | 1181 return emptyString; |
| 1177 } | 1182 } |
| 1178 | 1183 |
| 1179 } // namespace WTF | 1184 } // namespace WTF |
| 1180 | 1185 |
| 1181 #ifndef NDEBUG | 1186 #ifndef NDEBUG |
| 1182 // For use in the debugger | 1187 // For use in the debugger |
| 1183 String* string(const char*); | 1188 String* string(const char*); |
| 1184 Vector<char> asciiDebug(StringImpl* impl); | 1189 Vector<char> asciiDebug(StringImpl*); |
| 1185 Vector<char> asciiDebug(String& string); | 1190 Vector<char> asciiDebug(String&); |
| 1186 | 1191 |
| 1187 void String::show() const | 1192 void String::show() const |
| 1188 { | 1193 { |
| 1189 dataLogF("%s\n", asciiDebug(impl()).data()); | 1194 dataLogF("%s\n", asciiDebug(impl()).data()); |
| 1190 } | 1195 } |
| 1191 | 1196 |
| 1192 String* string(const char* s) | 1197 String* string(const char* s) |
| 1193 { | 1198 { |
| 1194 // leaks memory! | 1199 // leaks memory! |
| 1195 return new String(s); | 1200 return new String(s); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1216 buffer.append('\0'); | 1221 buffer.append('\0'); |
| 1217 return buffer; | 1222 return buffer; |
| 1218 } | 1223 } |
| 1219 | 1224 |
| 1220 Vector<char> asciiDebug(String& string) | 1225 Vector<char> asciiDebug(String& string) |
| 1221 { | 1226 { |
| 1222 return asciiDebug(string.impl()); | 1227 return asciiDebug(string.impl()); |
| 1223 } | 1228 } |
| 1224 | 1229 |
| 1225 #endif | 1230 #endif |
| OLD | NEW |