| 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 10 matching lines...) Expand all Loading... |
| 21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| 22 * Boston, MA 02110-1301, USA. | 22 * Boston, MA 02110-1301, USA. |
| 23 * | 23 * |
| 24 */ | 24 */ |
| 25 | 25 |
| 26 #include "wtf/text/StringImpl.h" | 26 #include "wtf/text/StringImpl.h" |
| 27 | 27 |
| 28 #include "wtf/DynamicAnnotations.h" | 28 #include "wtf/DynamicAnnotations.h" |
| 29 #include "wtf/LeakAnnotations.h" | 29 #include "wtf/LeakAnnotations.h" |
| 30 #include "wtf/PtrUtil.h" | 30 #include "wtf/PtrUtil.h" |
| 31 #include "wtf/StaticConstructors.h" |
| 31 #include "wtf/StdLibExtras.h" | 32 #include "wtf/StdLibExtras.h" |
| 32 #include "wtf/allocator/Partitions.h" | 33 #include "wtf/allocator/Partitions.h" |
| 33 #include "wtf/text/AtomicString.h" | 34 #include "wtf/text/AtomicString.h" |
| 34 #include "wtf/text/AtomicStringTable.h" | 35 #include "wtf/text/AtomicStringTable.h" |
| 35 #include "wtf/text/CString.h" | 36 #include "wtf/text/CString.h" |
| 36 #include "wtf/text/CharacterNames.h" | 37 #include "wtf/text/CharacterNames.h" |
| 37 #include "wtf/text/StringBuffer.h" | 38 #include "wtf/text/StringBuffer.h" |
| 38 #include "wtf/text/StringHash.h" | 39 #include "wtf/text/StringHash.h" |
| 39 #include "wtf/text/StringToNumber.h" | 40 #include "wtf/text/StringToNumber.h" |
| 40 #include <algorithm> | 41 #include <algorithm> |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 337 std::string StringImpl::asciiForDebugging() const { | 338 std::string StringImpl::asciiForDebugging() const { |
| 338 CString ascii = String(isolatedCopy()->substring(0, 128)).ascii(); | 339 CString ascii = String(isolatedCopy()->substring(0, 128)).ascii(); |
| 339 return std::string(ascii.data(), ascii.length()); | 340 return std::string(ascii.data(), ascii.length()); |
| 340 } | 341 } |
| 341 #endif | 342 #endif |
| 342 | 343 |
| 343 PassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, | 344 PassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, |
| 344 LChar*& data) { | 345 LChar*& data) { |
| 345 if (!length) { | 346 if (!length) { |
| 346 data = 0; | 347 data = 0; |
| 347 return empty(); | 348 return empty; |
| 348 } | 349 } |
| 349 | 350 |
| 350 // Allocate a single buffer large enough to contain the StringImpl | 351 // Allocate a single buffer large enough to contain the StringImpl |
| 351 // struct as well as the data which it contains. This removes one | 352 // struct as well as the data which it contains. This removes one |
| 352 // heap allocation from this call. | 353 // heap allocation from this call. |
| 353 StringImpl* string = static_cast<StringImpl*>(Partitions::bufferMalloc( | 354 StringImpl* string = static_cast<StringImpl*>(Partitions::bufferMalloc( |
| 354 allocationSize<LChar>(length), "WTF::StringImpl")); | 355 allocationSize<LChar>(length), "WTF::StringImpl")); |
| 355 | 356 |
| 356 data = reinterpret_cast<LChar*>(string + 1); | 357 data = reinterpret_cast<LChar*>(string + 1); |
| 357 return adoptRef(new (string) StringImpl(length, Force8BitConstructor)); | 358 return adoptRef(new (string) StringImpl(length, Force8BitConstructor)); |
| 358 } | 359 } |
| 359 | 360 |
| 360 PassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, | 361 PassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, |
| 361 UChar*& data) { | 362 UChar*& data) { |
| 362 if (!length) { | 363 if (!length) { |
| 363 data = 0; | 364 data = 0; |
| 364 return empty(); | 365 return empty; |
| 365 } | 366 } |
| 366 | 367 |
| 367 // Allocate a single buffer large enough to contain the StringImpl | 368 // Allocate a single buffer large enough to contain the StringImpl |
| 368 // struct as well as the data which it contains. This removes one | 369 // struct as well as the data which it contains. This removes one |
| 369 // heap allocation from this call. | 370 // heap allocation from this call. |
| 370 StringImpl* string = static_cast<StringImpl*>(Partitions::bufferMalloc( | 371 StringImpl* string = static_cast<StringImpl*>(Partitions::bufferMalloc( |
| 371 allocationSize<UChar>(length), "WTF::StringImpl")); | 372 allocationSize<UChar>(length), "WTF::StringImpl")); |
| 372 | 373 |
| 373 data = reinterpret_cast<UChar*>(string + 1); | 374 data = reinterpret_cast<UChar*>(string + 1); |
| 374 return adoptRef(new (string) StringImpl(length)); | 375 return adoptRef(new (string) StringImpl(length)); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 390 void StringImpl::freezeStaticStrings() { | 391 void StringImpl::freezeStaticStrings() { |
| 391 DCHECK(isMainThread()); | 392 DCHECK(isMainThread()); |
| 392 | 393 |
| 393 #if DCHECK_IS_ON() | 394 #if DCHECK_IS_ON() |
| 394 s_allowCreationOfStaticStrings = false; | 395 s_allowCreationOfStaticStrings = false; |
| 395 #endif | 396 #endif |
| 396 } | 397 } |
| 397 | 398 |
| 398 unsigned StringImpl::m_highestStaticStringLength = 0; | 399 unsigned StringImpl::m_highestStaticStringLength = 0; |
| 399 | 400 |
| 401 DEFINE_GLOBAL(StringImpl, globalEmpty); |
| 402 DEFINE_GLOBAL(StringImpl, globalEmpty16Bit); |
| 403 // Callers need the global empty strings to be non-const. |
| 404 StringImpl* StringImpl::empty = const_cast<StringImpl*>(&globalEmpty); |
| 405 StringImpl* StringImpl::empty16Bit = const_cast<StringImpl*>(&globalEmpty16Bit); |
| 406 void StringImpl::initStatics() { |
| 407 new ((void*)empty) StringImpl(ConstructEmptyString); |
| 408 new ((void*)empty16Bit) StringImpl(ConstructEmptyString16Bit); |
| 409 WTF_ANNOTATE_BENIGN_RACE(StringImpl::empty, |
| 410 "Benign race on the reference counter of a static " |
| 411 "string created by StringImpl::empty"); |
| 412 WTF_ANNOTATE_BENIGN_RACE(StringImpl::empty16Bit, |
| 413 "Benign race on the reference counter of a static " |
| 414 "string created by StringImpl::empty16Bit"); |
| 415 } |
| 416 |
| 400 StringImpl* StringImpl::createStatic(const char* string, | 417 StringImpl* StringImpl::createStatic(const char* string, |
| 401 unsigned length, | 418 unsigned length, |
| 402 unsigned hash) { | 419 unsigned hash) { |
| 403 #if DCHECK_IS_ON() | 420 #if DCHECK_IS_ON() |
| 404 DCHECK(s_allowCreationOfStaticStrings); | 421 DCHECK(s_allowCreationOfStaticStrings); |
| 405 #endif | 422 #endif |
| 406 DCHECK(string); | 423 DCHECK(string); |
| 407 DCHECK(length); | 424 DCHECK(length); |
| 408 | 425 |
| 409 StaticStringsTable::const_iterator it = staticStrings().find(hash); | 426 StaticStringsTable::const_iterator it = staticStrings().find(hash); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 444 void StringImpl::reserveStaticStringsCapacityForSize(unsigned size) { | 461 void StringImpl::reserveStaticStringsCapacityForSize(unsigned size) { |
| 445 #if DCHECK_IS_ON() | 462 #if DCHECK_IS_ON() |
| 446 DCHECK(s_allowCreationOfStaticStrings); | 463 DCHECK(s_allowCreationOfStaticStrings); |
| 447 #endif | 464 #endif |
| 448 staticStrings().reserveCapacityForSize(size); | 465 staticStrings().reserveCapacityForSize(size); |
| 449 } | 466 } |
| 450 | 467 |
| 451 PassRefPtr<StringImpl> StringImpl::create(const UChar* characters, | 468 PassRefPtr<StringImpl> StringImpl::create(const UChar* characters, |
| 452 unsigned length) { | 469 unsigned length) { |
| 453 if (!characters || !length) | 470 if (!characters || !length) |
| 454 return empty(); | 471 return empty; |
| 455 | 472 |
| 456 UChar* data; | 473 UChar* data; |
| 457 RefPtr<StringImpl> string = createUninitialized(length, data); | 474 RefPtr<StringImpl> string = createUninitialized(length, data); |
| 458 memcpy(data, characters, length * sizeof(UChar)); | 475 memcpy(data, characters, length * sizeof(UChar)); |
| 459 return string.release(); | 476 return string.release(); |
| 460 } | 477 } |
| 461 | 478 |
| 462 PassRefPtr<StringImpl> StringImpl::create(const LChar* characters, | 479 PassRefPtr<StringImpl> StringImpl::create(const LChar* characters, |
| 463 unsigned length) { | 480 unsigned length) { |
| 464 if (!characters || !length) | 481 if (!characters || !length) |
| 465 return empty(); | 482 return empty; |
| 466 | 483 |
| 467 LChar* data; | 484 LChar* data; |
| 468 RefPtr<StringImpl> string = createUninitialized(length, data); | 485 RefPtr<StringImpl> string = createUninitialized(length, data); |
| 469 memcpy(data, characters, length * sizeof(LChar)); | 486 memcpy(data, characters, length * sizeof(LChar)); |
| 470 return string.release(); | 487 return string.release(); |
| 471 } | 488 } |
| 472 | 489 |
| 473 PassRefPtr<StringImpl> StringImpl::create8BitIfPossible(const UChar* characters, | 490 PassRefPtr<StringImpl> StringImpl::create8BitIfPossible(const UChar* characters, |
| 474 unsigned length) { | 491 unsigned length) { |
| 475 if (!characters || !length) | 492 if (!characters || !length) |
| 476 return empty(); | 493 return empty; |
| 477 | 494 |
| 478 LChar* data; | 495 LChar* data; |
| 479 RefPtr<StringImpl> string = createUninitialized(length, data); | 496 RefPtr<StringImpl> string = createUninitialized(length, data); |
| 480 | 497 |
| 481 for (size_t i = 0; i < length; ++i) { | 498 for (size_t i = 0; i < length; ++i) { |
| 482 if (characters[i] & 0xff00) | 499 if (characters[i] & 0xff00) |
| 483 return create(characters, length); | 500 return create(characters, length); |
| 484 data[i] = static_cast<LChar>(characters[i]); | 501 data[i] = static_cast<LChar>(characters[i]); |
| 485 } | 502 } |
| 486 | 503 |
| 487 return string.release(); | 504 return string.release(); |
| 488 } | 505 } |
| 489 | 506 |
| 490 PassRefPtr<StringImpl> StringImpl::create(const LChar* string) { | 507 PassRefPtr<StringImpl> StringImpl::create(const LChar* string) { |
| 491 if (!string) | 508 if (!string) |
| 492 return empty(); | 509 return empty; |
| 493 size_t length = strlen(reinterpret_cast<const char*>(string)); | 510 size_t length = strlen(reinterpret_cast<const char*>(string)); |
| 494 RELEASE_ASSERT(length <= numeric_limits<unsigned>::max()); | 511 RELEASE_ASSERT(length <= numeric_limits<unsigned>::max()); |
| 495 return create(string, length); | 512 return create(string, length); |
| 496 } | 513 } |
| 497 | 514 |
| 498 bool StringImpl::containsOnlyWhitespace() { | 515 bool StringImpl::containsOnlyWhitespace() { |
| 499 // FIXME: The definition of whitespace here includes a number of characters | 516 // FIXME: The definition of whitespace here includes a number of characters |
| 500 // that are not whitespace from the point of view of LayoutText; I wonder if | 517 // that are not whitespace from the point of view of LayoutText; I wonder if |
| 501 // that's a problem in practice. | 518 // that's a problem in practice. |
| 502 if (is8Bit()) { | 519 if (is8Bit()) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 513 UChar c = characters16()[i]; | 530 UChar c = characters16()[i]; |
| 514 if (!isASCIISpace(c)) | 531 if (!isASCIISpace(c)) |
| 515 return false; | 532 return false; |
| 516 } | 533 } |
| 517 return true; | 534 return true; |
| 518 } | 535 } |
| 519 | 536 |
| 520 PassRefPtr<StringImpl> StringImpl::substring(unsigned start, | 537 PassRefPtr<StringImpl> StringImpl::substring(unsigned start, |
| 521 unsigned length) const { | 538 unsigned length) const { |
| 522 if (start >= m_length) | 539 if (start >= m_length) |
| 523 return empty(); | 540 return empty; |
| 524 unsigned maxLength = m_length - start; | 541 unsigned maxLength = m_length - start; |
| 525 if (length >= maxLength) { | 542 if (length >= maxLength) { |
| 526 // PassRefPtr has trouble dealing with const arguments. It should be updated | 543 // PassRefPtr has trouble dealing with const arguments. It should be updated |
| 527 // so this const_cast is not necessary. | 544 // so this const_cast is not necessary. |
| 528 if (!start) | 545 if (!start) |
| 529 return const_cast<StringImpl*>(this); | 546 return const_cast<StringImpl*>(this); |
| 530 length = maxLength; | 547 length = maxLength; |
| 531 } | 548 } |
| 532 if (is8Bit()) | 549 if (is8Bit()) |
| 533 return create(characters8() + start, length); | 550 return create(characters8() + start, length); |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 952 return this; | 969 return this; |
| 953 if (is8Bit()) | 970 if (is8Bit()) |
| 954 return create(characters8(), length); | 971 return create(characters8(), length); |
| 955 return create(characters16(), length); | 972 return create(characters16(), length); |
| 956 } | 973 } |
| 957 | 974 |
| 958 template <class UCharPredicate> | 975 template <class UCharPredicate> |
| 959 inline PassRefPtr<StringImpl> StringImpl::stripMatchedCharacters( | 976 inline PassRefPtr<StringImpl> StringImpl::stripMatchedCharacters( |
| 960 UCharPredicate predicate) { | 977 UCharPredicate predicate) { |
| 961 if (!m_length) | 978 if (!m_length) |
| 962 return empty(); | 979 return empty; |
| 963 | 980 |
| 964 unsigned start = 0; | 981 unsigned start = 0; |
| 965 unsigned end = m_length - 1; | 982 unsigned end = m_length - 1; |
| 966 | 983 |
| 967 // skip white space from start | 984 // skip white space from start |
| 968 while (start <= end && | 985 while (start <= end && |
| 969 predicate(is8Bit() ? characters8()[start] : characters16()[start])) | 986 predicate(is8Bit() ? characters8()[start] : characters16()[start])) |
| 970 ++start; | 987 ++start; |
| 971 | 988 |
| 972 // only white space | 989 // only white space |
| 973 if (start > end) | 990 if (start > end) |
| 974 return empty(); | 991 return empty; |
| 975 | 992 |
| 976 // skip white space from end | 993 // skip white space from end |
| 977 while (end && predicate(is8Bit() ? characters8()[end] : characters16()[end])) | 994 while (end && predicate(is8Bit() ? characters8()[end] : characters16()[end])) |
| 978 --end; | 995 --end; |
| 979 | 996 |
| 980 if (!start && end == m_length - 1) | 997 if (!start && end == m_length - 1) |
| 981 return this; | 998 return this; |
| 982 if (is8Bit()) | 999 if (is8Bit()) |
| 983 return create(characters8() + start, end + 1 - start); | 1000 return create(characters8() + start, end + 1 - start); |
| 984 return create(characters16() + start, end + 1 - start); | 1001 return create(characters16() + start, end + 1 - start); |
| (...skipping 1211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2196 } else if (localeIdMatchesLang(localeIdentifier, "lt")) { | 2213 } else if (localeIdMatchesLang(localeIdentifier, "lt")) { |
| 2197 // TODO(rob.buis) implement upper-casing rules for lt | 2214 // TODO(rob.buis) implement upper-casing rules for lt |
| 2198 // like in StringImpl::upper(locale). | 2215 // like in StringImpl::upper(locale). |
| 2199 } | 2216 } |
| 2200 } | 2217 } |
| 2201 | 2218 |
| 2202 return toUpper(c); | 2219 return toUpper(c); |
| 2203 } | 2220 } |
| 2204 | 2221 |
| 2205 } // namespace WTF | 2222 } // namespace WTF |
| OLD | NEW |