| 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() |
| 42 : m_bufferCharacters8(0) | 42 : m_bufferCharacters8(0), m_length(0), m_is8Bit(true) { |
| 43 , m_length(0) | 43 } |
| 44 , m_is8Bit(true) | 44 |
| 45 { | 45 void append(const UChar*, unsigned); |
| 46 } | 46 void append(const LChar*, unsigned); |
| 47 | 47 |
| 48 void append(const UChar*, unsigned); | 48 ALWAYS_INLINE void append(const char* characters, unsigned length) { append(re
interpret_cast<const LChar*>(characters), length); } |
| 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) { |
| 143 if (m_is8Bit) | 143 append(static_cast<LChar>(c)); |
| 144 m_bufferCharacters8[m_length++] = c; | 144 } |
| 145 else | 145 |
| 146 m_bufferCharacters16[m_length++] = c; | 146 void append(UChar32 c) { |
| 147 } else { | 147 if (U_IS_BMP(c)) { |
| 148 append(&c, 1); | 148 append(static_cast<UChar>(c)); |
| 149 } | 149 return; |
| 150 } | 150 } |
| 151 | 151 append(U16_LEAD(c)); |
| 152 void append(char c) | 152 append(U16_TRAIL(c)); |
| 153 { | 153 } |
| 154 append(static_cast<LChar>(c)); | 154 |
| 155 } | 155 template <unsigned charactersCount> |
| 156 | 156 ALWAYS_INLINE void appendLiteral(const char(&characters)[charactersCount]) { a
ppend(characters, charactersCount - 1); } |
| 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, unsigned precision = 6, TrailingZerosTruncatingPolic
y = TruncateTrailingZeros); |
| 165 } | 165 |
| 166 | 166 String toString() { |
| 167 template<unsigned charactersCount> | 167 shrinkToFit(); |
| 168 ALWAYS_INLINE void appendLiteral(const char (&characters)[charactersCount])
{ append(characters, charactersCount - 1); } | 168 if (m_string.isNull()) |
| 169 | 169 reifyString(); |
| 170 void appendNumber(int); | 170 return m_string; |
| 171 void appendNumber(unsigned); | 171 } |
| 172 void appendNumber(long); | 172 |
| 173 void appendNumber(unsigned long); | 173 String substring(unsigned position, unsigned length) const { |
| 174 void appendNumber(long long); | 174 if (!m_length) |
| 175 void appendNumber(unsigned long long); | 175 return emptyString(); |
| 176 void appendNumber(double, unsigned precision = 6, TrailingZerosTruncatingPol
icy = TruncateTrailingZeros); | 176 if (!m_string.isNull()) |
| 177 | 177 return m_string.substring(position, length); |
| 178 String toString() | 178 return reifySubstring(position, length); |
| 179 { | 179 } |
| 180 shrinkToFit(); | 180 |
| 181 if (m_string.isNull()) | 181 AtomicString toAtomicString() const { |
| 182 reifyString(); | 182 if (!m_length) |
| 183 return m_string; | 183 return emptyAtom; |
| 184 } | 184 |
| 185 | 185 // If the buffer is sufficiently over-allocated, make a new AtomicString fro
m a copy so its buffer is not so large. |
| 186 String substring(unsigned position, unsigned length) const | 186 if (canShrink()) { |
| 187 { | 187 if (is8Bit()) |
| 188 if (!m_length) | 188 return AtomicString(characters8(), length()); |
| 189 return emptyString(); | 189 return AtomicString(characters16(), length()); |
| 190 if (!m_string.isNull()) | 190 } |
| 191 return m_string.substring(position, length); | 191 |
| 192 return reifySubstring(position, length); | 192 if (!m_string.isNull()) |
| 193 } | 193 return AtomicString(m_string); |
| 194 | 194 |
| 195 AtomicString toAtomicString() const | 195 ASSERT(m_buffer); |
| 196 { | 196 return AtomicString(m_buffer.get(), 0, m_length); |
| 197 if (!m_length) | 197 } |
| 198 return emptyAtom; | 198 |
| 199 | 199 unsigned length() const { |
| 200 // If the buffer is sufficiently over-allocated, make a new AtomicString
from a copy so its buffer is not so large. | 200 return m_length; |
| 201 if (canShrink()) { | 201 } |
| 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 { |
| 208 return AtomicString(m_string); | 208 return m_buffer ? m_buffer->length() : m_length; |
| 209 | 209 } |
| 210 ASSERT(m_buffer); | 210 |
| 211 return AtomicString(m_buffer.get(), 0, m_length); | 211 void resize(unsigned newSize); |
| 212 } | 212 |
| 213 | 213 bool canShrink() const; |
| 214 unsigned length() const | 214 |
| 215 { | 215 void shrinkToFit(); |
| 216 return m_length; | 216 |
| 217 } | 217 UChar operator[](unsigned i) const { |
| 218 | 218 ASSERT_WITH_SECURITY_IMPLICATION(i < m_length); |
| 219 bool isEmpty() const { return !m_length; } | 219 if (m_is8Bit) |
| 220 | 220 return characters8()[i]; |
| 221 void reserveCapacity(unsigned newCapacity); | 221 return characters16()[i]; |
| 222 | 222 } |
| 223 unsigned capacity() const | 223 |
| 224 { | 224 const LChar* characters8() const { |
| 225 return m_buffer ? m_buffer->length() : m_length; | 225 ASSERT(m_is8Bit); |
| 226 } | 226 if (!m_length) |
| 227 | 227 return 0; |
| 228 void resize(unsigned newSize); | 228 if (!m_string.isNull()) |
| 229 | 229 return m_string.characters8(); |
| 230 bool canShrink() const; | 230 ASSERT(m_buffer); |
| 231 | 231 return m_buffer->characters8(); |
| 232 void shrinkToFit(); | 232 } |
| 233 | 233 |
| 234 UChar operator[](unsigned i) const | 234 const UChar* characters16() const { |
| 235 { | 235 ASSERT(!m_is8Bit); |
| 236 ASSERT_WITH_SECURITY_IMPLICATION(i < m_length); | 236 if (!m_length) |
| 237 if (m_is8Bit) | 237 return 0; |
| 238 return characters8()[i]; | 238 if (!m_string.isNull()) |
| 239 return characters16()[i]; | 239 return m_string.characters16(); |
| 240 } | 240 ASSERT(m_buffer); |
| 241 | 241 return m_buffer->characters16(); |
| 242 const LChar* characters8() const | 242 } |
| 243 { | 243 |
| 244 ASSERT(m_is8Bit); | 244 bool is8Bit() const { return m_is8Bit; } |
| 245 if (!m_length) | 245 |
| 246 return 0; | 246 void clear() { |
| 247 if (!m_string.isNull()) | 247 m_length = 0; |
| 248 return m_string.characters8(); | 248 m_string = String(); |
| 249 ASSERT(m_buffer); | 249 m_buffer = nullptr; |
| 250 return m_buffer->characters8(); | 250 m_bufferCharacters8 = 0; |
| 251 } | 251 m_is8Bit = true; |
| 252 | 252 } |
| 253 const UChar* characters16() const | 253 |
| 254 { | 254 void swap(StringBuilder& stringBuilder) { |
| 255 ASSERT(!m_is8Bit); | 255 std::swap(m_length, stringBuilder.m_length); |
| 256 if (!m_length) | 256 m_string.swap(stringBuilder.m_string); |
| 257 return 0; | 257 m_buffer.swap(stringBuilder.m_buffer); |
| 258 if (!m_string.isNull()) | 258 std::swap(m_is8Bit, stringBuilder.m_is8Bit); |
| 259 return m_string.characters16(); | 259 std::swap(m_bufferCharacters8, stringBuilder.m_bufferCharacters8); |
| 260 ASSERT(m_buffer); | 260 } |
| 261 return m_buffer->characters16(); | 261 |
| 262 } | 262 private: |
| 263 | 263 void allocateBuffer(const LChar* currentCharacters, unsigned requiredLength); |
| 264 bool is8Bit() const { return m_is8Bit; } | 264 void allocateBuffer(const UChar* currentCharacters, unsigned requiredLength); |
| 265 | 265 void allocateBufferUpConvert(const LChar* currentCharacters, unsigned required
Length); |
| 266 void clear() | 266 template <typename CharType> |
| 267 { | 267 void reallocateBuffer(unsigned requiredLength); |
| 268 m_length = 0; | 268 template <typename CharType> |
| 269 m_string = String(); | 269 ALWAYS_INLINE CharType* appendUninitialized(unsigned length); |
| 270 m_buffer = nullptr; | 270 template <typename CharType> |
| 271 m_bufferCharacters8 = 0; | 271 CharType* appendUninitializedSlow(unsigned length); |
| 272 m_is8Bit = true; | 272 template <typename CharType> |
| 273 } | 273 ALWAYS_INLINE CharType* getBufferCharacters(); |
| 274 | 274 void reifyString(); |
| 275 void swap(StringBuilder& stringBuilder) | 275 String reifySubstring(unsigned position, unsigned length) const; |
| 276 { | 276 |
| 277 std::swap(m_length, stringBuilder.m_length); | 277 String m_string; // Pointers first: crbug.com/232031 |
| 278 m_string.swap(stringBuilder.m_string); | 278 RefPtr<StringImpl> m_buffer; |
| 279 m_buffer.swap(stringBuilder.m_buffer); | 279 union { |
| 280 std::swap(m_is8Bit, stringBuilder.m_is8Bit); | 280 LChar* m_bufferCharacters8; |
| 281 std::swap(m_bufferCharacters8, stringBuilder.m_bufferCharacters8); | 281 UChar* m_bufferCharacters16; |
| 282 } | 282 }; |
| 283 | 283 unsigned m_length; |
| 284 private: | 284 bool m_is8Bit; |
| 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 }; | 285 }; |
| 308 | 286 |
| 309 template <> | 287 template <> |
| 310 ALWAYS_INLINE LChar* StringBuilder::getBufferCharacters<LChar>() | 288 ALWAYS_INLINE LChar* StringBuilder::getBufferCharacters<LChar>() { |
| 311 { | 289 ASSERT(m_is8Bit); |
| 312 ASSERT(m_is8Bit); | 290 return m_bufferCharacters8; |
| 313 return m_bufferCharacters8; | |
| 314 } | 291 } |
| 315 | 292 |
| 316 template <> | 293 template <> |
| 317 ALWAYS_INLINE UChar* StringBuilder::getBufferCharacters<UChar>() | 294 ALWAYS_INLINE UChar* StringBuilder::getBufferCharacters<UChar>() { |
| 318 { | 295 ASSERT(!m_is8Bit); |
| 319 ASSERT(!m_is8Bit); | 296 return m_bufferCharacters16; |
| 320 return m_bufferCharacters16; | |
| 321 } | 297 } |
| 322 | 298 |
| 323 template <typename CharType> | 299 template <typename CharType> |
| 324 bool equal(const StringBuilder& s, const CharType* buffer, unsigned length) | 300 bool equal(const StringBuilder& s, const CharType* buffer, unsigned length) { |
| 325 { | 301 if (s.length() != length) |
| 326 if (s.length() != length) | 302 return false; |
| 327 return false; | 303 |
| 328 | 304 if (s.is8Bit()) |
| 329 if (s.is8Bit()) | 305 return equal(s.characters8(), buffer, length); |
| 330 return equal(s.characters8(), buffer, length); | 306 |
| 331 | 307 return equal(s.characters16(), buffer, length); |
| 332 return equal(s.characters16(), buffer, length); | 308 } |
| 333 } | 309 |
| 334 | 310 template <typename CharType> |
| 335 template<typename CharType> | 311 bool equalIgnoringCase(const StringBuilder& s, const CharType* buffer, unsigned
length) { |
| 336 bool equalIgnoringCase(const StringBuilder& s, const CharType* buffer, unsigned
length) | 312 if (s.length() != length) |
| 337 { | 313 return false; |
| 338 if (s.length() != length) | 314 |
| 339 return false; | 315 if (s.is8Bit()) |
| 340 | 316 return equalIgnoringCase(s.characters8(), buffer, length); |
| 341 if (s.is8Bit()) | 317 |
| 342 return equalIgnoringCase(s.characters8(), buffer, length); | 318 return equalIgnoringCase(s.characters16(), buffer, length); |
| 343 | 319 } |
| 344 return equalIgnoringCase(s.characters16(), buffer, length); | 320 |
| 345 } | 321 inline bool equalIgnoringCase(const StringBuilder& s, const char* string) { |
| 346 | 322 return equalIgnoringCase(s, reinterpret_cast<const LChar*>(string), strlen(str
ing)); |
| 347 inline bool equalIgnoringCase(const StringBuilder& s, const char* string) | |
| 348 { | |
| 349 return equalIgnoringCase(s, reinterpret_cast<const LChar*>(string), strlen(s
tring)); | |
| 350 } | 323 } |
| 351 | 324 |
| 352 template <typename StringType> | 325 template <typename StringType> |
| 353 bool equal(const StringBuilder& a, const StringType& b) | 326 bool equal(const StringBuilder& a, const StringType& b) { |
| 354 { | 327 if (a.length() != b.length()) |
| 355 if (a.length() != b.length()) | 328 return false; |
| 356 return false; | 329 |
| 357 | 330 if (!a.length()) |
| 358 if (!a.length()) | 331 return true; |
| 359 return true; | 332 |
| 360 | 333 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()) | 334 if (b.is8Bit()) |
| 368 return equal(a.characters16(), b.characters8(), a.length()); | 335 return equal(a.characters8(), b.characters8(), a.length()); |
| 369 return equal(a.characters16(), b.characters16(), a.length()); | 336 return equal(a.characters8(), b.characters16(), a.length()); |
| 337 } |
| 338 |
| 339 if (b.is8Bit()) |
| 340 return equal(a.characters16(), b.characters8(), a.length()); |
| 341 return equal(a.characters16(), b.characters16(), a.length()); |
| 370 } | 342 } |
| 371 | 343 |
| 372 template <typename StringType> | 344 template <typename StringType> |
| 373 bool equalIgnoringCase(const StringBuilder& a, const StringType& b) | 345 bool equalIgnoringCase(const StringBuilder& a, const StringType& b) { |
| 374 { | 346 if (a.length() != b.length()) |
| 375 if (a.length() != b.length()) | 347 return false; |
| 376 return false; | 348 |
| 377 | 349 if (!a.length()) |
| 378 if (!a.length()) | 350 return true; |
| 379 return true; | 351 |
| 380 | 352 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()) | 353 if (b.is8Bit()) |
| 388 return equalIgnoringCase(a.characters16(), b.characters8(), a.length()); | 354 return equalIgnoringCase(a.characters8(), b.characters8(), a.length()); |
| 389 return equalIgnoringCase(a.characters16(), b.characters16(), a.length()); | 355 return equalIgnoringCase(a.characters8(), b.characters16(), a.length()); |
| 390 } | 356 } |
| 391 | 357 |
| 392 inline bool operator==(const StringBuilder& a, const StringBuilder& b) { return
equal(a, b); } | 358 if (b.is8Bit()) |
| 393 inline bool operator!=(const StringBuilder& a, const StringBuilder& b) { return
!equal(a, b); } | 359 return equalIgnoringCase(a.characters16(), b.characters8(), a.length()); |
| 394 inline bool operator==(const StringBuilder& a, const String& b) { return equal(a
, b); } | 360 return equalIgnoringCase(a.characters16(), b.characters16(), a.length()); |
| 395 inline bool operator!=(const StringBuilder& a, const String& b) { return !equal(
a, b); } | 361 } |
| 396 inline bool operator==(const String& a, const StringBuilder& b) { return equal(b
, a); } | 362 |
| 397 inline bool operator!=(const String& a, const StringBuilder& b) { return !equal(
b, a); } | 363 inline bool operator==(const StringBuilder& a, const StringBuilder& b) { |
| 398 | 364 return equal(a, b); |
| 399 } // namespace WTF | 365 } |
| 366 inline bool operator!=(const StringBuilder& a, const StringBuilder& b) { |
| 367 return !equal(a, b); |
| 368 } |
| 369 inline bool operator==(const StringBuilder& a, const String& b) { |
| 370 return equal(a, b); |
| 371 } |
| 372 inline bool operator!=(const StringBuilder& a, const String& b) { |
| 373 return !equal(a, b); |
| 374 } |
| 375 inline bool operator==(const String& a, const StringBuilder& b) { |
| 376 return equal(b, a); |
| 377 } |
| 378 inline bool operator!=(const String& a, const StringBuilder& b) { |
| 379 return !equal(b, a); |
| 380 } |
| 381 |
| 382 } // namespace WTF |
| 400 | 383 |
| 401 using WTF::StringBuilder; | 384 using WTF::StringBuilder; |
| 402 | 385 |
| 403 #endif // StringBuilder_h | 386 #endif // StringBuilder_h |
| OLD | NEW |