| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2009, 2010, 2012, 2013 Apple Inc. All rights reserved. | 2 * Copyright (C) 2009, 2010, 2012, 2013 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2012 Google Inc. All rights reserved. | 3 * Copyright (C) 2012 Google Inc. All rights reserved. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 #ifndef StringBuilder_h | 27 #ifndef StringBuilder_h |
| 28 #define StringBuilder_h | 28 #define StringBuilder_h |
| 29 | 29 |
| 30 #include "wtf/WTFExport.h" | 30 #include "wtf/WTFExport.h" |
| 31 #include "wtf/text/AtomicString.h" | 31 #include "wtf/text/AtomicString.h" |
| 32 #include "wtf/text/WTFString.h" | 32 #include "wtf/text/WTFString.h" |
| 33 | 33 |
| 34 namespace WTF { | 34 namespace WTF { |
| 35 | 35 |
| 36 class WTF_EXPORT StringBuilder { | 36 class WTF_EXPORT StringBuilder { |
| 37 // Disallow copying since it's expensive and we don't want code to do it by
accident. | 37 // Disallow copying since it's expensive and we don't want code to do it by ac
cident. |
| 38 WTF_MAKE_NONCOPYABLE(StringBuilder); | 38 WTF_MAKE_NONCOPYABLE(StringBuilder); |
| 39 | 39 |
| 40 public: | 40 public: |
| 41 StringBuilder() | 41 StringBuilder() : m_bufferCharacters8(0), m_length(0), m_is8Bit(true) {} |
| 42 : m_bufferCharacters8(0) | 42 |
| 43 , m_length(0) | 43 void append(const UChar*, unsigned); |
| 44 , m_is8Bit(true) | 44 void append(const LChar*, unsigned); |
| 45 { | 45 |
| 46 } | 46 ALWAYS_INLINE void append(const char* characters, unsigned length) { |
| 47 | 47 append(reinterpret_cast<const LChar*>(characters), length); |
| 48 void append(const UChar*, unsigned); | 48 } |
| 49 void append(const LChar*, unsigned); | 49 |
| 50 | 50 void append(const String& string) { |
| 51 ALWAYS_INLINE void append(const char* characters, unsigned length) { append(
reinterpret_cast<const LChar*>(characters), length); } | 51 if (!string.length()) |
| 52 | 52 return; |
| 53 void append(const String& string) | 53 |
| 54 { | 54 // If we're appending to an empty string, and there is not a buffer (reserve
Capacity has not been called) |
| 55 if (!string.length()) | 55 // then just retain the string. |
| 56 return; | 56 if (!m_length && !m_buffer) { |
| 57 | 57 m_string = string; |
| 58 // If we're appending to an empty string, and there is not a buffer (res
erveCapacity has not been called) | 58 m_length = string.length(); |
| 59 // then just retain the string. | 59 m_is8Bit = m_string.is8Bit(); |
| 60 if (!m_length && !m_buffer) { | 60 return; |
| 61 m_string = string; | 61 } |
| 62 m_length = string.length(); | 62 |
| 63 m_is8Bit = m_string.is8Bit(); | 63 if (string.is8Bit()) |
| 64 return; | 64 append(string.characters8(), string.length()); |
| 65 } | 65 else |
| 66 | 66 append(string.characters16(), string.length()); |
| 67 if (string.is8Bit()) | 67 } |
| 68 append(string.characters8(), string.length()); | 68 |
| 69 else | 69 void append(const StringBuilder& other) { |
| 70 append(string.characters16(), string.length()); | 70 if (!other.m_length) |
| 71 } | 71 return; |
| 72 | 72 |
| 73 void append(const StringBuilder& other) | 73 // If we're appending to an empty string, and there is not a buffer (reserve
Capacity has not been called) |
| 74 { | 74 // then just retain the string. |
| 75 if (!other.m_length) | 75 if (!m_length && !m_buffer && !other.m_string.isNull()) { |
| 76 return; | 76 m_string = other.m_string; |
| 77 | 77 m_length = other.m_length; |
| 78 // If we're appending to an empty string, and there is not a buffer (res
erveCapacity has not been called) | 78 return; |
| 79 // then just retain the string. | 79 } |
| 80 if (!m_length && !m_buffer && !other.m_string.isNull()) { | 80 |
| 81 m_string = other.m_string; | 81 if (other.is8Bit()) |
| 82 m_length = other.m_length; | 82 append(other.characters8(), other.m_length); |
| 83 return; | 83 else |
| 84 } | 84 append(other.characters16(), other.m_length); |
| 85 | 85 } |
| 86 if (other.is8Bit()) | 86 |
| 87 append(other.characters8(), other.m_length); | 87 void append(const String& string, unsigned offset, unsigned length) { |
| 88 else | 88 if (!string.length()) |
| 89 append(other.characters16(), other.m_length); | 89 return; |
| 90 } | 90 |
| 91 | 91 unsigned extent = offset + length; |
| 92 void append(const String& string, unsigned offset, unsigned length) | 92 if (extent < offset || extent > string.length()) |
| 93 { | 93 return; |
| 94 if (!string.length()) | 94 |
| 95 return; | 95 if (string.is8Bit()) |
| 96 | 96 append(string.characters8() + offset, length); |
| 97 unsigned extent = offset + length; | 97 else |
| 98 if (extent < offset || extent > string.length()) | 98 append(string.characters16() + offset, length); |
| 99 return; | 99 } |
| 100 | 100 |
| 101 if (string.is8Bit()) | 101 void append(const StringView& string) { |
| 102 append(string.characters8() + offset, length); | 102 if (!string.length()) |
| 103 else | 103 return; |
| 104 append(string.characters16() + offset, length); | 104 |
| 105 } | 105 if (string.is8Bit()) |
| 106 | 106 append(string.characters8(), string.length()); |
| 107 void append(const StringView& string) | 107 else |
| 108 { | 108 append(string.characters16(), string.length()); |
| 109 if (!string.length()) | 109 } |
| 110 return; | 110 |
| 111 | 111 void append(const char* characters) { |
| 112 if (string.is8Bit()) | 112 if (characters) |
| 113 append(string.characters8(), string.length()); | 113 append(characters, strlen(characters)); |
| 114 else | 114 } |
| 115 append(string.characters16(), string.length()); | 115 |
| 116 } | 116 void append(UChar c) { |
| 117 | 117 if (m_buffer && m_length < m_buffer->length() && m_string.isNull()) { |
| 118 void append(const char* characters) | 118 if (!m_is8Bit) { |
| 119 { | 119 m_bufferCharacters16[m_length++] = c; |
| 120 if (characters) | 120 return; |
| 121 append(characters, strlen(characters)); | 121 } |
| 122 } | 122 |
| 123 | 123 if (!(c & ~0xff)) { |
| 124 void append(UChar c) | 124 m_bufferCharacters8[m_length++] = static_cast<LChar>(c); |
| 125 { | 125 return; |
| 126 if (m_buffer && m_length < m_buffer->length() && m_string.isNull()) { | 126 } |
| 127 if (!m_is8Bit) { | 127 } |
| 128 m_bufferCharacters16[m_length++] = c; | 128 append(&c, 1); |
| 129 return; | 129 } |
| 130 } | 130 |
| 131 | 131 void append(LChar c) { |
| 132 if (!(c & ~0xff)) { | 132 if (m_buffer && m_length < m_buffer->length() && m_string.isNull()) { |
| 133 m_bufferCharacters8[m_length++] = static_cast<LChar>(c); | 133 if (m_is8Bit) |
| 134 return; | 134 m_bufferCharacters8[m_length++] = c; |
| 135 } | 135 else |
| 136 } | 136 m_bufferCharacters16[m_length++] = c; |
| 137 append(&c, 1); | 137 } else { |
| 138 } | 138 append(&c, 1); |
| 139 | 139 } |
| 140 void append(LChar c) | 140 } |
| 141 { | 141 |
| 142 if (m_buffer && m_length < m_buffer->length() && m_string.isNull()) { | 142 void append(char c) { append(static_cast<LChar>(c)); } |
| 143 if (m_is8Bit) | 143 |
| 144 m_bufferCharacters8[m_length++] = c; | 144 void append(UChar32 c) { |
| 145 else | 145 if (U_IS_BMP(c)) { |
| 146 m_bufferCharacters16[m_length++] = c; | 146 append(static_cast<UChar>(c)); |
| 147 } else { | 147 return; |
| 148 append(&c, 1); | 148 } |
| 149 } | 149 append(U16_LEAD(c)); |
| 150 } | 150 append(U16_TRAIL(c)); |
| 151 | 151 } |
| 152 void append(char c) | 152 |
| 153 { | 153 template <unsigned charactersCount> |
| 154 append(static_cast<LChar>(c)); | 154 ALWAYS_INLINE void appendLiteral(const char (&characters)[charactersCount]) { |
| 155 } | 155 append(characters, charactersCount - 1); |
| 156 | 156 } |
| 157 void append(UChar32 c) | 157 |
| 158 { | 158 void appendNumber(int); |
| 159 if (U_IS_BMP(c)) { | 159 void appendNumber(unsigned); |
| 160 append(static_cast<UChar>(c)); | 160 void appendNumber(long); |
| 161 return; | 161 void appendNumber(unsigned long); |
| 162 } | 162 void appendNumber(long long); |
| 163 append(U16_LEAD(c)); | 163 void appendNumber(unsigned long long); |
| 164 append(U16_TRAIL(c)); | 164 void appendNumber(double, |
| 165 } | 165 unsigned precision = 6, |
| 166 | 166 TrailingZerosTruncatingPolicy = TruncateTrailingZeros); |
| 167 template<unsigned charactersCount> | 167 |
| 168 ALWAYS_INLINE void appendLiteral(const char (&characters)[charactersCount])
{ append(characters, charactersCount - 1); } | 168 String toString() { |
| 169 | 169 shrinkToFit(); |
| 170 void appendNumber(int); | 170 if (m_string.isNull()) |
| 171 void appendNumber(unsigned); | 171 reifyString(); |
| 172 void appendNumber(long); | 172 return m_string; |
| 173 void appendNumber(unsigned long); | 173 } |
| 174 void appendNumber(long long); | 174 |
| 175 void appendNumber(unsigned long long); | 175 String substring(unsigned position, unsigned length) const { |
| 176 void appendNumber(double, unsigned precision = 6, TrailingZerosTruncatingPol
icy = TruncateTrailingZeros); | 176 if (!m_length) |
| 177 | 177 return emptyString(); |
| 178 String toString() | 178 if (!m_string.isNull()) |
| 179 { | 179 return m_string.substring(position, length); |
| 180 shrinkToFit(); | 180 return reifySubstring(position, length); |
| 181 if (m_string.isNull()) | 181 } |
| 182 reifyString(); | 182 |
| 183 return m_string; | 183 AtomicString toAtomicString() const { |
| 184 } | 184 if (!m_length) |
| 185 | 185 return emptyAtom; |
| 186 String substring(unsigned position, unsigned length) const | 186 |
| 187 { | 187 // If the buffer is sufficiently over-allocated, make a new AtomicString fro
m a copy so its buffer is not so large. |
| 188 if (!m_length) | 188 if (canShrink()) { |
| 189 return emptyString(); | 189 if (is8Bit()) |
| 190 if (!m_string.isNull()) | 190 return AtomicString(characters8(), length()); |
| 191 return m_string.substring(position, length); | 191 return AtomicString(characters16(), length()); |
| 192 return reifySubstring(position, length); | 192 } |
| 193 } | 193 |
| 194 | 194 if (!m_string.isNull()) |
| 195 AtomicString toAtomicString() const | 195 return AtomicString(m_string); |
| 196 { | 196 |
| 197 if (!m_length) | 197 ASSERT(m_buffer); |
| 198 return emptyAtom; | 198 return AtomicString(m_buffer.get(), 0, m_length); |
| 199 | 199 } |
| 200 // If the buffer is sufficiently over-allocated, make a new AtomicString
from a copy so its buffer is not so large. | 200 |
| 201 if (canShrink()) { | 201 unsigned length() const { return m_length; } |
| 202 if (is8Bit()) | 202 |
| 203 return AtomicString(characters8(), length()); | 203 bool isEmpty() const { return !m_length; } |
| 204 return AtomicString(characters16(), length()); | 204 |
| 205 } | 205 void reserveCapacity(unsigned newCapacity); |
| 206 | 206 |
| 207 if (!m_string.isNull()) | 207 unsigned capacity() const { return m_buffer ? m_buffer->length() : m_length; } |
| 208 return AtomicString(m_string); | 208 |
| 209 | 209 void resize(unsigned newSize); |
| 210 ASSERT(m_buffer); | 210 |
| 211 return AtomicString(m_buffer.get(), 0, m_length); | 211 bool canShrink() const; |
| 212 } | 212 |
| 213 | 213 void shrinkToFit(); |
| 214 unsigned length() const | 214 |
| 215 { | 215 UChar operator[](unsigned i) const { |
| 216 return m_length; | 216 ASSERT_WITH_SECURITY_IMPLICATION(i < m_length); |
| 217 } | 217 if (m_is8Bit) |
| 218 | 218 return characters8()[i]; |
| 219 bool isEmpty() const { return !m_length; } | 219 return characters16()[i]; |
| 220 | 220 } |
| 221 void reserveCapacity(unsigned newCapacity); | 221 |
| 222 | 222 const LChar* characters8() const { |
| 223 unsigned capacity() const | 223 ASSERT(m_is8Bit); |
| 224 { | 224 if (!m_length) |
| 225 return m_buffer ? m_buffer->length() : m_length; | 225 return 0; |
| 226 } | 226 if (!m_string.isNull()) |
| 227 | 227 return m_string.characters8(); |
| 228 void resize(unsigned newSize); | 228 ASSERT(m_buffer); |
| 229 | 229 return m_buffer->characters8(); |
| 230 bool canShrink() const; | 230 } |
| 231 | 231 |
| 232 void shrinkToFit(); | 232 const UChar* characters16() const { |
| 233 | 233 ASSERT(!m_is8Bit); |
| 234 UChar operator[](unsigned i) const | 234 if (!m_length) |
| 235 { | 235 return 0; |
| 236 ASSERT_WITH_SECURITY_IMPLICATION(i < m_length); | 236 if (!m_string.isNull()) |
| 237 if (m_is8Bit) | 237 return m_string.characters16(); |
| 238 return characters8()[i]; | 238 ASSERT(m_buffer); |
| 239 return characters16()[i]; | 239 return m_buffer->characters16(); |
| 240 } | 240 } |
| 241 | 241 |
| 242 const LChar* characters8() const | 242 bool is8Bit() const { return m_is8Bit; } |
| 243 { | 243 |
| 244 ASSERT(m_is8Bit); | 244 void clear() { |
| 245 if (!m_length) | 245 m_length = 0; |
| 246 return 0; | 246 m_string = String(); |
| 247 if (!m_string.isNull()) | 247 m_buffer = nullptr; |
| 248 return m_string.characters8(); | 248 m_bufferCharacters8 = 0; |
| 249 ASSERT(m_buffer); | 249 m_is8Bit = true; |
| 250 return m_buffer->characters8(); | 250 } |
| 251 } | 251 |
| 252 | 252 void swap(StringBuilder& stringBuilder) { |
| 253 const UChar* characters16() const | 253 std::swap(m_length, stringBuilder.m_length); |
| 254 { | 254 m_string.swap(stringBuilder.m_string); |
| 255 ASSERT(!m_is8Bit); | 255 m_buffer.swap(stringBuilder.m_buffer); |
| 256 if (!m_length) | 256 std::swap(m_is8Bit, stringBuilder.m_is8Bit); |
| 257 return 0; | 257 std::swap(m_bufferCharacters8, stringBuilder.m_bufferCharacters8); |
| 258 if (!m_string.isNull()) | 258 } |
| 259 return m_string.characters16(); | 259 |
| 260 ASSERT(m_buffer); | 260 private: |
| 261 return m_buffer->characters16(); | 261 void allocateBuffer(const LChar* currentCharacters, unsigned requiredLength); |
| 262 } | 262 void allocateBuffer(const UChar* currentCharacters, unsigned requiredLength); |
| 263 | 263 void allocateBufferUpConvert(const LChar* currentCharacters, |
| 264 bool is8Bit() const { return m_is8Bit; } | 264 unsigned requiredLength); |
| 265 | 265 template <typename CharType> |
| 266 void clear() | 266 void reallocateBuffer(unsigned requiredLength); |
| 267 { | 267 template <typename CharType> |
| 268 m_length = 0; | 268 ALWAYS_INLINE CharType* appendUninitialized(unsigned length); |
| 269 m_string = String(); | 269 template <typename CharType> |
| 270 m_buffer = nullptr; | 270 CharType* appendUninitializedSlow(unsigned length); |
| 271 m_bufferCharacters8 = 0; | 271 template <typename CharType> |
| 272 m_is8Bit = true; | 272 ALWAYS_INLINE CharType* getBufferCharacters(); |
| 273 } | 273 void reifyString(); |
| 274 | 274 String reifySubstring(unsigned position, unsigned length) const; |
| 275 void swap(StringBuilder& stringBuilder) | 275 |
| 276 { | 276 String m_string; // Pointers first: crbug.com/232031 |
| 277 std::swap(m_length, stringBuilder.m_length); | 277 RefPtr<StringImpl> m_buffer; |
| 278 m_string.swap(stringBuilder.m_string); | 278 union { |
| 279 m_buffer.swap(stringBuilder.m_buffer); | 279 LChar* m_bufferCharacters8; |
| 280 std::swap(m_is8Bit, stringBuilder.m_is8Bit); | 280 UChar* m_bufferCharacters16; |
| 281 std::swap(m_bufferCharacters8, stringBuilder.m_bufferCharacters8); | 281 }; |
| 282 } | 282 unsigned m_length; |
| 283 | 283 bool m_is8Bit; |
| 284 private: | |
| 285 void allocateBuffer(const LChar* currentCharacters, unsigned requiredLength)
; | |
| 286 void allocateBuffer(const UChar* currentCharacters, unsigned requiredLength)
; | |
| 287 void allocateBufferUpConvert(const LChar* currentCharacters, unsigned requir
edLength); | |
| 288 template <typename CharType> | |
| 289 void reallocateBuffer(unsigned requiredLength); | |
| 290 template <typename CharType> | |
| 291 ALWAYS_INLINE CharType* appendUninitialized(unsigned length); | |
| 292 template <typename CharType> | |
| 293 CharType* appendUninitializedSlow(unsigned length); | |
| 294 template <typename CharType> | |
| 295 ALWAYS_INLINE CharType * getBufferCharacters(); | |
| 296 void reifyString(); | |
| 297 String reifySubstring(unsigned position, unsigned length) const; | |
| 298 | |
| 299 String m_string; // Pointers first: crbug.com/232031 | |
| 300 RefPtr<StringImpl> m_buffer; | |
| 301 union { | |
| 302 LChar* m_bufferCharacters8; | |
| 303 UChar* m_bufferCharacters16; | |
| 304 }; | |
| 305 unsigned m_length; | |
| 306 bool m_is8Bit; | |
| 307 }; | 284 }; |
| 308 | 285 |
| 309 template <> | 286 template <> |
| 310 ALWAYS_INLINE LChar* StringBuilder::getBufferCharacters<LChar>() | 287 ALWAYS_INLINE LChar* StringBuilder::getBufferCharacters<LChar>() { |
| 311 { | 288 ASSERT(m_is8Bit); |
| 312 ASSERT(m_is8Bit); | 289 return m_bufferCharacters8; |
| 313 return m_bufferCharacters8; | |
| 314 } | 290 } |
| 315 | 291 |
| 316 template <> | 292 template <> |
| 317 ALWAYS_INLINE UChar* StringBuilder::getBufferCharacters<UChar>() | 293 ALWAYS_INLINE UChar* StringBuilder::getBufferCharacters<UChar>() { |
| 318 { | 294 ASSERT(!m_is8Bit); |
| 319 ASSERT(!m_is8Bit); | 295 return m_bufferCharacters16; |
| 320 return m_bufferCharacters16; | |
| 321 } | 296 } |
| 322 | 297 |
| 323 template <typename CharType> | 298 template <typename CharType> |
| 324 bool equal(const StringBuilder& s, const CharType* buffer, unsigned length) | 299 bool equal(const StringBuilder& s, const CharType* buffer, unsigned length) { |
| 325 { | 300 if (s.length() != length) |
| 326 if (s.length() != length) | 301 return false; |
| 327 return false; | 302 |
| 328 | 303 if (s.is8Bit()) |
| 329 if (s.is8Bit()) | 304 return equal(s.characters8(), buffer, length); |
| 330 return equal(s.characters8(), buffer, length); | 305 |
| 331 | 306 return equal(s.characters16(), buffer, length); |
| 332 return equal(s.characters16(), buffer, length); | 307 } |
| 333 } | 308 |
| 334 | 309 template <typename CharType> |
| 335 template<typename CharType> | 310 bool equalIgnoringCase(const StringBuilder& s, |
| 336 bool equalIgnoringCase(const StringBuilder& s, const CharType* buffer, unsigned
length) | 311 const CharType* buffer, |
| 337 { | 312 unsigned length) { |
| 338 if (s.length() != length) | 313 if (s.length() != length) |
| 339 return false; | 314 return false; |
| 340 | 315 |
| 341 if (s.is8Bit()) | 316 if (s.is8Bit()) |
| 342 return equalIgnoringCase(s.characters8(), buffer, length); | 317 return equalIgnoringCase(s.characters8(), buffer, length); |
| 343 | 318 |
| 344 return equalIgnoringCase(s.characters16(), buffer, length); | 319 return equalIgnoringCase(s.characters16(), buffer, length); |
| 345 } | 320 } |
| 346 | 321 |
| 347 inline bool equalIgnoringCase(const StringBuilder& s, const char* string) | 322 inline bool equalIgnoringCase(const StringBuilder& s, const char* string) { |
| 348 { | 323 return equalIgnoringCase(s, reinterpret_cast<const LChar*>(string), |
| 349 return equalIgnoringCase(s, reinterpret_cast<const LChar*>(string), strlen(s
tring)); | 324 strlen(string)); |
| 350 } | 325 } |
| 351 | 326 |
| 352 template <typename StringType> | 327 template <typename StringType> |
| 353 bool equal(const StringBuilder& a, const StringType& b) | 328 bool equal(const StringBuilder& a, const StringType& b) { |
| 354 { | 329 if (a.length() != b.length()) |
| 355 if (a.length() != b.length()) | 330 return false; |
| 356 return false; | 331 |
| 357 | 332 if (!a.length()) |
| 358 if (!a.length()) | 333 return true; |
| 359 return true; | 334 |
| 360 | 335 if (a.is8Bit()) { |
| 361 if (a.is8Bit()) { | |
| 362 if (b.is8Bit()) | |
| 363 return equal(a.characters8(), b.characters8(), a.length()); | |
| 364 return equal(a.characters8(), b.characters16(), a.length()); | |
| 365 } | |
| 366 | |
| 367 if (b.is8Bit()) | 336 if (b.is8Bit()) |
| 368 return equal(a.characters16(), b.characters8(), a.length()); | 337 return equal(a.characters8(), b.characters8(), a.length()); |
| 369 return equal(a.characters16(), b.characters16(), a.length()); | 338 return equal(a.characters8(), b.characters16(), a.length()); |
| 339 } |
| 340 |
| 341 if (b.is8Bit()) |
| 342 return equal(a.characters16(), b.characters8(), a.length()); |
| 343 return equal(a.characters16(), b.characters16(), a.length()); |
| 370 } | 344 } |
| 371 | 345 |
| 372 template <typename StringType> | 346 template <typename StringType> |
| 373 bool equalIgnoringCase(const StringBuilder& a, const StringType& b) | 347 bool equalIgnoringCase(const StringBuilder& a, const StringType& b) { |
| 374 { | 348 if (a.length() != b.length()) |
| 375 if (a.length() != b.length()) | 349 return false; |
| 376 return false; | 350 |
| 377 | 351 if (!a.length()) |
| 378 if (!a.length()) | 352 return true; |
| 379 return true; | 353 |
| 380 | 354 if (a.is8Bit()) { |
| 381 if (a.is8Bit()) { | |
| 382 if (b.is8Bit()) | |
| 383 return equalIgnoringCase(a.characters8(), b.characters8(), a.length(
)); | |
| 384 return equalIgnoringCase(a.characters8(), b.characters16(), a.length()); | |
| 385 } | |
| 386 | |
| 387 if (b.is8Bit()) | 355 if (b.is8Bit()) |
| 388 return equalIgnoringCase(a.characters16(), b.characters8(), a.length()); | 356 return equalIgnoringCase(a.characters8(), b.characters8(), a.length()); |
| 389 return equalIgnoringCase(a.characters16(), b.characters16(), a.length()); | 357 return equalIgnoringCase(a.characters8(), b.characters16(), a.length()); |
| 390 } | 358 } |
| 391 | 359 |
| 392 inline bool operator==(const StringBuilder& a, const StringBuilder& b) { return
equal(a, b); } | 360 if (b.is8Bit()) |
| 393 inline bool operator!=(const StringBuilder& a, const StringBuilder& b) { return
!equal(a, b); } | 361 return equalIgnoringCase(a.characters16(), b.characters8(), a.length()); |
| 394 inline bool operator==(const StringBuilder& a, const String& b) { return equal(a
, b); } | 362 return equalIgnoringCase(a.characters16(), b.characters16(), a.length()); |
| 395 inline bool operator!=(const StringBuilder& a, const String& b) { return !equal(
a, b); } | 363 } |
| 396 inline bool operator==(const String& a, const StringBuilder& b) { return equal(b
, a); } | 364 |
| 397 inline bool operator!=(const String& a, const StringBuilder& b) { return !equal(
b, a); } | 365 inline bool operator==(const StringBuilder& a, const StringBuilder& b) { |
| 398 | 366 return equal(a, b); |
| 399 } // namespace WTF | 367 } |
| 368 inline bool operator!=(const StringBuilder& a, const StringBuilder& b) { |
| 369 return !equal(a, b); |
| 370 } |
| 371 inline bool operator==(const StringBuilder& a, const String& b) { |
| 372 return equal(a, b); |
| 373 } |
| 374 inline bool operator!=(const StringBuilder& a, const String& b) { |
| 375 return !equal(a, b); |
| 376 } |
| 377 inline bool operator==(const String& a, const StringBuilder& b) { |
| 378 return equal(b, a); |
| 379 } |
| 380 inline bool operator!=(const String& a, const StringBuilder& b) { |
| 381 return !equal(b, a); |
| 382 } |
| 383 |
| 384 } // namespace WTF |
| 400 | 385 |
| 401 using WTF::StringBuilder; | 386 using WTF::StringBuilder; |
| 402 | 387 |
| 403 #endif // StringBuilder_h | 388 #endif // StringBuilder_h |
| OLD | NEW |