1 /* 2 * (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. 4 * Copyright (C) 2007-2009 Torch Mobile, Inc. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Library General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Library General Public License for more details. 15 * 16 * You should have received a copy of the GNU Library General Public License 17 * along with this library; see the file COPYING.LIB. If not, write to 18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA. 20 */ 21 22 #include "config.h" 23 #include "PlatformString.h" 24 25 #include "CString.h" 26 #include "FloatConversion.h" 27 #include "StringBuffer.h" 28 #include "TextBreakIterator.h" 29 #include "TextEncoding.h" 30 #include <wtf/dtoa.h> 31 #include <limits> 32 #include <stdarg.h> 33 #include <wtf/ASCIICType.h> 34 #include <wtf/StringExtras.h> 35 #include <wtf/Vector.h> 36 #include <wtf/unicode/Unicode.h> 37 #include <wtf/unicode/UTF8.h> 38 39 #if USE(JSC) 40 #include <runtime/Identifier.h> 41 42 using JSC::Identifier; 43 using JSC::UString; 44 #endif 45 46 using namespace WTF; 47 using namespace WTF::Unicode; 48 49 namespace WebCore { 50 51 String::String(const UChar* str, unsigned len) 52 { 53 if (!str) 54 return; 55 m_impl = StringImpl::create(str, len); 56 } 57 58 String::String(const UChar* str) 59 { 60 if (!str) 61 return; 62 63 int len = 0; 64 while (str[len] != UChar(0)) 65 len++; 66 67 m_impl = StringImpl::create(str, len); 68 } 69 70 String::String(const char* str) 71 { 72 if (!str) 73 return; 74 m_impl = StringImpl::create(str); 75 } 76 77 String::String(const char* str, unsigned length) 78 { 79 if (!str) 80 return; 81 m_impl = StringImpl::create(str, length); 82 } 83 84 void String::append(const String& str) 85 { 86 if (str.isEmpty()) 87 return; 88 89 // FIXME: This is extremely inefficient. So much so that we might want to take this 90 // out of String's API. We can make it better by optimizing the case where exactly 91 // one String is pointing at this StringImpl, but even then it's going to require a 92 // call to fastMalloc every single time. 93 if (str.m_impl) { 94 if (m_impl) { 95 UChar* data; 96 RefPtr<StringImpl> newImpl = 97 StringImpl::createUninitialized(m_impl->length() + str.length(), data); 98 memcpy(data, m_impl->characters(), m_impl->length() * sizeof(UChar)); 99 memcpy(data + m_impl->length(), str.characters(), str.length() * sizeof(UChar)); 100 m_impl = newImpl.release(); 101 } else 102 m_impl = str.m_impl; 103 } 104 } 105 106 void String::append(char c) 107 { 108 // FIXME: This is extremely inefficient. So much so that we might want to take this 109 // out of String's API. We can make it better by optimizing the case where exactly 110 // one String is pointing at this StringImpl, but even then it's going to require a 111 // call to fastMalloc every single time. 112 if (m_impl) { 113 UChar* data; 114 RefPtr<StringImpl> newImpl = 115 StringImpl::createUninitialized(m_impl->length() + 1, data); 116 memcpy(data, m_impl->characters(), m_impl->length() * sizeof(UChar)); 117 data[m_impl->length()] = c; 118 m_impl = newImpl.release(); 119 } else 120 m_impl = StringImpl::create(&c, 1); 121 } 122 123 void String::append(UChar c) 124 { 125 // FIXME: This is extremely inefficient. So much so that we might want to take this 126 // out of String's API. We can make it better by optimizing the case where exactly 127 // one String is pointing at this StringImpl, but even then it's going to require a 128 // call to fastMalloc every single time. 129 if (m_impl) { 130 UChar* data; 131 RefPtr<StringImpl> newImpl = 132 StringImpl::createUninitialized(m_impl->length() + 1, data); 133 memcpy(data, m_impl->characters(), m_impl->length() * sizeof(UChar)); 134 data[m_impl->length()] = c; 135 m_impl = newImpl.release(); 136 } else 137 m_impl = StringImpl::create(&c, 1); 138 } 139 140 String operator+(const String& a, const String& b) 141 { 142 if (a.isEmpty()) 143 return b; 144 if (b.isEmpty()) 145 return a; 146 String c = a; 147 c += b; 148 return c; 149 } 150 151 String operator+(const String& s, const char* cs) 152 { 153 return s + String(cs); 154 } 155 156 String operator+(const char* cs, const String& s) 157 { 158 return String(cs) + s; 159 } 160 161 void String::insert(const String& str, unsigned pos) 162 { 163 if (str.isEmpty()) { 164 if (str.isNull()) 165 return; 166 if (isNull()) 167 m_impl = str.impl(); 168 return; 169 } 170 insert(str.characters(), str.length(), pos); 171 } 172 173 void String::append(const UChar* charactersToAppend, unsigned lengthToAppend) 174 { 175 if (!m_impl) { 176 if (!charactersToAppend) 177 return; 178 m_impl = StringImpl::create(charactersToAppend, lengthToAppend); 179 return; 180 } 181 182 if (!lengthToAppend) 183 return; 184 185 ASSERT(charactersToAppend); 186 UChar* data; 187 RefPtr<StringImpl> newImpl = 188 StringImpl::createUninitialized(length() + lengthToAppend, data); 189 memcpy(data, characters(), length() * sizeof(UChar)); 190 memcpy(data + length(), charactersToAppend, lengthToAppend * sizeof(UChar)); 191 m_impl = newImpl.release(); 192 } 193 194 void String::insert(const UChar* charactersToInsert, unsigned lengthToInsert, unsigned position) 195 { 196 if (position >= length()) { 197 append(charactersToInsert, lengthToInsert); 198 return; 199 } 200 201 ASSERT(m_impl); 202 203 if (!lengthToInsert) 204 return; 205 206 ASSERT(charactersToInsert); 207 UChar* data; 208 RefPtr<StringImpl> newImpl = 209 StringImpl::createUninitialized(length() + lengthToInsert, data); 210 memcpy(data, characters(), position * sizeof(UChar)); 211 memcpy(data + position, charactersToInsert, lengthToInsert * sizeof(UChar)); 212 memcpy(data + position + lengthToInsert, characters() + position, (length() - position) * sizeof(UChar)); 213 m_impl = newImpl.release(); 214 } 215 216 UChar String::operator[](unsigned i) const 217 { 218 if (!m_impl || i >= m_impl->length()) 219 return 0; 220 return m_impl->characters()[i]; 221 } 222 223 UChar32 String::characterStartingAt(unsigned i) const 224 { 225 if (!m_impl || i >= m_impl->length()) 226 return 0; 227 return m_impl->characterStartingAt(i); 228 } 229 230 unsigned String::length() const 231 { 232 if (!m_impl) 233 return 0; 234 return m_impl->length(); 235 } 236 237 void String::truncate(unsigned position) 238 { 239 if (position >= length()) 240 return; 241 UChar* data; 242 RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(position, data); 243 memcpy(data, characters(), position * sizeof(UChar)); 244 m_impl = newImpl.release(); 245 } 246 247 void String::remove(unsigned position, int lengthToRemove) 248 { 249 if (lengthToRemove <= 0) 250 return; 251 if (position >= length()) 252 return; 253 if (static_cast<unsigned>(lengthToRemove) > length() - position) 254 lengthToRemove = length() - position; 255 UChar* data; 256 RefPtr<StringImpl> newImpl = 257 StringImpl::createUninitialized(length() - lengthToRemove, data); 258 memcpy(data, characters(), position * sizeof(UChar)); 259 memcpy(data + position, characters() + position + lengthToRemove, 260 (length() - lengthToRemove - position) * sizeof(UChar)); 261 m_impl = newImpl.release(); 262 } 263 264 String String::substring(unsigned pos, unsigned len) const 265 { 266 if (!m_impl) 267 return String(); 268 return m_impl->substring(pos, len); 269 } 270 271 String String::lower() const 272 { 273 if (!m_impl) 274 return String(); 275 return m_impl->lower(); 276 } 277 278 String String::upper() const 279 { 280 if (!m_impl) 281 return String(); 282 return m_impl->upper(); 283 } 284 285 String String::stripWhiteSpace() const 286 { 287 if (!m_impl) 288 return String(); 289 return m_impl->stripWhiteSpace(); 290 } 291 292 String String::simplifyWhiteSpace() const 293 { 294 if (!m_impl) 295 return String(); 296 return m_impl->simplifyWhiteSpace(); 297 } 298 299 String String::removeCharacters(CharacterMatchFunctionPtr findMatch) const 300 { 301 if (!m_impl) 302 return String(); 303 return m_impl->removeCharacters(findMatch); 304 } 305 306 String String::foldCase() const 307 { 308 if (!m_impl) 309 return String(); 310 return m_impl->foldCase(); 311 } 312 313 bool String::percentage(int& result) const 314 { 315 if (!m_impl || !m_impl->length()) 316 return false; 317 318 if ((*m_impl)[m_impl->length() - 1] != '%') 319 return false; 320 321 result = charactersToIntStrict(m_impl->characters(), m_impl->length() - 1); 322 return true; 323 } 324 325 const UChar* String::characters() const 326 { 327 if (!m_impl) 328 return 0; 329 return m_impl->characters(); 330 } 331 332 const UChar* String::charactersWithNullTermination() 333 { 334 if (!m_impl) 335 return 0; 336 if (m_impl->hasTerminatingNullCharacter()) 337 return m_impl->characters(); 338 m_impl = StringImpl::createWithTerminatingNullCharacter(*m_impl); 339 return m_impl->characters(); 340 } 341 342 String String::format(const char *format, ...) 343 { 344 #if PLATFORM(QT) 345 // Use QString::vsprintf to avoid the locale dependent formatting of vsnprintf. 346 // https://bugs.webkit.org/show_bug.cgi?id=18994 347 va_list args; 348 va_start(args, format); 349 350 QString buffer; 351 buffer.vsprintf(format, args); 352 353 va_end(args); 354 355 return buffer; 356 357 #elif OS(WINCE) 358 va_list args; 359 va_start(args, format); 360 361 Vector<char, 256> buffer; 362 363 int bufferSize = 256; 364 buffer.resize(bufferSize); 365 for (;;) { 366 int written = vsnprintf(buffer.data(), bufferSize, format, args); 367 va_end(args); 368 369 if (written == 0) 370 return String(""); 371 if (written > 0) 372 return StringImpl::create(buffer.data(), written); 373 374 bufferSize <<= 1; 375 buffer.resize(bufferSize); 376 va_start(args, format); 377 } 378 379 #else 380 va_list args; 381 va_start(args, format); 382 383 Vector<char, 256> buffer; 384 385 // Do the format once to get the length. 386 #if COMPILER(MSVC) 387 int result = _vscprintf(format, args); 388 #else 389 char ch; 390 int result = vsnprintf(&ch, 1, format, args); 391 // We need to call va_end() and then va_start() again here, as the 392 // contents of args is undefined after the call to vsnprintf 393 // according to http://man.cx/snprintf(3) 394 // 395 // Not calling va_end/va_start here happens to work on lots of 396 // systems, but fails e.g. on 64bit Linux. 397 va_end(args); 398 va_start(args, format); 399 #endif 400 401 if (result == 0) 402 return String(""); 403 if (result < 0) 404 return String(); 405 unsigned len = result; 406 buffer.grow(len + 1); 407 408 // Now do the formatting again, guaranteed to fit. 409 vsnprintf(buffer.data(), buffer.size(), format, args); 410 411 va_end(args); 412 413 return StringImpl::create(buffer.data(), len); 414 #endif 415 } 416 417 String String::number(short n) 418 { 419 return String::format("%hd", n); 420 } 421 422 String String::number(unsigned short n) 423 { 424 return String::format("%hu", n); 425 } 426 427 String String::number(int n) 428 { 429 return String::format("%d", n); 430 } 431 432 String String::number(unsigned n) 433 { 434 return String::format("%u", n); 435 } 436 437 String String::number(long n) 438 { 439 return String::format("%ld", n); 440 } 441 442 String String::number(unsigned long n) 443 { 444 return String::format("%lu", n); 445 } 446 447 String String::number(long long n) 448 { 449 #if OS(WINDOWS) && !PLATFORM(QT) 450 return String::format("%I64i", n); 451 #else 452 return String::format("%lli", n); 453 #endif 454 } 455 456 String String::number(unsigned long long n) 457 { 458 #if OS(WINDOWS) && !PLATFORM(QT) 459 return String::format("%I64u", n); 460 #else 461 return String::format("%llu", n); 462 #endif 463 } 464 465 String String::number(double n) 466 { 467 return String::format("%.6lg", n); 468 } 469 470 int String::toIntStrict(bool* ok, int base) const 471 { 472 if (!m_impl) { 473 if (ok) 474 *ok = false; 475 return 0; 476 } 477 return m_impl->toIntStrict(ok, base); 478 } 479 480 unsigned String::toUIntStrict(bool* ok, int base) const 481 { 482 if (!m_impl) { 483 if (ok) 484 *ok = false; 485 return 0; 486 } 487 return m_impl->toUIntStrict(ok, base); 488 } 489 490 int64_t String::toInt64Strict(bool* ok, int base) const 491 { 492 if (!m_impl) { 493 if (ok) 494 *ok = false; 495 return 0; 496 } 497 return m_impl->toInt64Strict(ok, base); 498 } 499 500 uint64_t String::toUInt64Strict(bool* ok, int base) const 501 { 502 if (!m_impl) { 503 if (ok) 504 *ok = false; 505 return 0; 506 } 507 return m_impl->toUInt64Strict(ok, base); 508 } 509 510 intptr_t String::toIntPtrStrict(bool* ok, int base) const 511 { 512 if (!m_impl) { 513 if (ok) 514 *ok = false; 515 return 0; 516 } 517 return m_impl->toIntPtrStrict(ok, base); 518 } 519 520 521 int String::toInt(bool* ok) const 522 { 523 if (!m_impl) { 524 if (ok) 525 *ok = false; 526 return 0; 527 } 528 return m_impl->toInt(ok); 529 } 530 531 unsigned String::toUInt(bool* ok) const 532 { 533 if (!m_impl) { 534 if (ok) 535 *ok = false; 536 return 0; 537 } 538 return m_impl->toUInt(ok); 539 } 540 541 int64_t String::toInt64(bool* ok) const 542 { 543 if (!m_impl) { 544 if (ok) 545 *ok = false; 546 return 0; 547 } 548 return m_impl->toInt64(ok); 549 } 550 551 uint64_t String::toUInt64(bool* ok) const 552 { 553 if (!m_impl) { 554 if (ok) 555 *ok = false; 556 return 0; 557 } 558 return m_impl->toUInt64(ok); 559 } 560 561 intptr_t String::toIntPtr(bool* ok) const 562 { 563 if (!m_impl) { 564 if (ok) 565 *ok = false; 566 return 0; 567 } 568 return m_impl->toIntPtr(ok); 569 } 570 571 double String::toDouble(bool* ok) const 572 { 573 if (!m_impl) { 574 if (ok) 575 *ok = false; 576 return 0.0; 577 } 578 return m_impl->toDouble(ok); 579 } 580 581 float String::toFloat(bool* ok) const 582 { 583 if (!m_impl) { 584 if (ok) 585 *ok = false; 586 return 0.0f; 587 } 588 return m_impl->toFloat(ok); 589 } 590 591 String String::threadsafeCopy() const 592 { 593 if (!m_impl) 594 return String(); 595 return m_impl->threadsafeCopy(); 596 } 597 598 String String::crossThreadString() const 599 { 600 if (!m_impl) 601 return String(); 602 return m_impl->crossThreadString(); 603 } 604 605 bool String::isEmpty() const 606 { 607 return !m_impl || !m_impl->length(); 608 } 609 610 void String::split(const String& separator, bool allowEmptyEntries, Vector<String>& result) const 611 { 612 result.clear(); 613 614 int startPos = 0; 615 int endPos; 616 while ((endPos = find(separator, startPos)) != -1) { 617 if (allowEmptyEntries || startPos != endPos) 618 result.append(substring(startPos, endPos - startPos)); 619 startPos = endPos + separator.length(); 620 } 621 if (allowEmptyEntries || startPos != static_cast<int>(length())) 622 result.append(substring(startPos)); 623 } 624 625 void String::split(const String& separator, Vector<String>& result) const 626 { 627 return split(separator, false, result); 628 } 629 630 void String::split(UChar separator, bool allowEmptyEntries, Vector<String>& result) const 631 { 632 result.clear(); 633 634 int startPos = 0; 635 int endPos; 636 while ((endPos = find(separator, startPos)) != -1) { 637 if (allowEmptyEntries || startPos != endPos) 638 result.append(substring(startPos, endPos - startPos)); 639 startPos = endPos + 1; 640 } 641 if (allowEmptyEntries || startPos != static_cast<int>(length())) 642 result.append(substring(startPos)); 643 } 644 645 void String::split(UChar separator, Vector<String>& result) const 646 { 647 return split(String(&separator, 1), false, result); 648 } 649 650 #ifndef NDEBUG 651 Vector<char> String::ascii() const 652 { 653 if (m_impl) 654 return m_impl->ascii(); 655 656 const char* nullMsg = "(null impl)"; 657 Vector<char, 2048> buffer; 658 for (int i = 0; nullMsg[i]; ++i) 659 buffer.append(nullMsg[i]); 660 661 buffer.append('\0'); 662 return buffer; 663 } 664 #endif 665 666 CString String::latin1() const 667 { 668 return Latin1Encoding().encode(characters(), length(), QuestionMarksForUnencodables); 669 } 670 671 CString String::utf8() const 672 { 673 return UTF8Encoding().encode(characters(), length(), QuestionMarksForUnencodables); 674 } 675 676 String String::fromUTF8(const char* string, size_t size) 677 { 678 if (!string) 679 return String(); 680 return UTF8Encoding().decode(string, size); 681 } 682 683 String String::fromUTF8(const char* string) 684 { 685 if (!string) 686 return String(); 687 return UTF8Encoding().decode(string, strlen(string)); 688 } 689 690 String String::fromUTF8WithLatin1Fallback(const char* string, size_t size) 691 { 692 String result = fromUTF8(string, size); 693 if (!result) 694 result = String(string, size); 695 696 return result; 697 } 698 699 #if USE(JSC) 700 String::String(const Identifier& str) 701 { 702 if (str.isNull()) 703 return; 704 m_impl = StringImpl::create(str.ustring()); 705 } 706 707 String::String(const UString& str) 708 { 709 if (str.isNull()) 710 return; 711 m_impl = StringImpl::create(str); 712 } 713 714 String::operator UString() const 715 { 716 if (!m_impl) 717 return UString(); 718 return m_impl->ustring(); 719 } 720 #endif 721 722 // String Operations 723 724 static bool isCharacterAllowedInBase(UChar c, int base) 725 { 726 if (c > 0x7F) 727 return false; 728 if (isASCIIDigit(c)) 729 return c - '0' < base; 730 if (isASCIIAlpha(c)) { 731 if (base > 36) 732 base = 36; 733 return (c >= 'a' && c < 'a' + base - 10) 734 || (c >= 'A' && c < 'A' + base - 10); 735 } 736 return false; 737 } 738 739 template <typename IntegralType> 740 static inline IntegralType toIntegralType(const UChar* data, size_t length, bool* ok, int base) 741 { 742 static const IntegralType integralMax = std::numeric_limits<IntegralType>::max(); 743 static const bool isSigned = std::numeric_limits<IntegralType>::is_signed; 744 const IntegralType maxMultiplier = integralMax / base; 745 746 IntegralType value = 0; 747 bool isOk = false; 748 bool isNegative = false; 749 750 if (!data) 751 goto bye; 752 753 // skip leading whitespace 754 while (length && isSpaceOrNewline(*data)) { 755 length--; 756 data++; 757 } 758 759 if (isSigned && length && *data == '-') { 760 length--; 761 data++; 762 isNegative = true; 763 } else if (length && *data == '+') { 764 length--; 765 data++; 766 } 767 768 if (!length || !isCharacterAllowedInBase(*data, base)) 769 goto bye; 770 771 while (length && isCharacterAllowedInBase(*data, base)) { 772 length--; 773 IntegralType digitValue; 774 UChar c = *data; 775 if (isASCIIDigit(c)) 776 digitValue = c - '0'; 777 else if (c >= 'a') 778 digitValue = c - 'a' + 10; 779 else 780 digitValue = c - 'A' + 10; 781 782 if (value > maxMultiplier || (value == maxMultiplier && digitValue > (integralMax % base) + isNegative)) 783 goto bye; 784 785 value = base * value + digitValue; 786 data++; 787 } 788 789 #if COMPILER(MSVC) 790 #pragma warning(push, 0) 791 #pragma warning(disable:4146) 792 #endif 793 794 if (isNegative) 795 value = -value; 796 797 #if COMPILER(MSVC) 798 #pragma warning(pop) 799 #endif 800 801 // skip trailing space 802 while (length && isSpaceOrNewline(*data)) { 803 length--; 804 data++; 805 } 806 807 if (!length) 808 isOk = true; 809 bye: 810 if (ok) 811 *ok = isOk; 812 return isOk ? value : 0; 813 } 814 815 static unsigned lengthOfCharactersAsInteger(const UChar* data, size_t length) 816 { 817 size_t i = 0; 818 819 // Allow leading spaces. 820 for (; i != length; ++i) { 821 if (!isSpaceOrNewline(data[i])) 822 break; 823 } 824 825 // Allow sign. 826 if (i != length && (data[i] == '+' || data[i] == '-')) 827 ++i; 828 829 // Allow digits. 830 for (; i != length; ++i) { 831 if (!isASCIIDigit(data[i])) 832 break; 833 } 834 835 return i; 836 } 837 838 int charactersToIntStrict(const UChar* data, size_t length, bool* ok, int base) 839 { 840 return toIntegralType<int>(data, length, ok, base); 841 } 842 843 unsigned charactersToUIntStrict(const UChar* data, size_t length, bool* ok, int base) 844 { 845 return toIntegralType<unsigned>(data, length, ok, base); 846 } 847 848 int64_t charactersToInt64Strict(const UChar* data, size_t length, bool* ok, int base) 849 { 850 return toIntegralType<int64_t>(data, length, ok, base); 851 } 852 853 uint64_t charactersToUInt64Strict(const UChar* data, size_t length, bool* ok, int base) 854 { 855 return toIntegralType<uint64_t>(data, length, ok, base); 856 } 857 858 intptr_t charactersToIntPtrStrict(const UChar* data, size_t length, bool* ok, int base) 859 { 860 return toIntegralType<intptr_t>(data, length, ok, base); 861 } 862 863 int charactersToInt(const UChar* data, size_t length, bool* ok) 864 { 865 return toIntegralType<int>(data, lengthOfCharactersAsInteger(data, length), ok, 10); 866 } 867 868 unsigned charactersToUInt(const UChar* data, size_t length, bool* ok) 869 { 870 return toIntegralType<unsigned>(data, lengthOfCharactersAsInteger(data, length), ok, 10); 871 } 872 873 int64_t charactersToInt64(const UChar* data, size_t length, bool* ok) 874 { 875 return toIntegralType<int64_t>(data, lengthOfCharactersAsInteger(data, length), ok, 10); 876 } 877 878 uint64_t charactersToUInt64(const UChar* data, size_t length, bool* ok) 879 { 880 return toIntegralType<uint64_t>(data, lengthOfCharactersAsInteger(data, length), ok, 10); 881 } 882 883 intptr_t charactersToIntPtr(const UChar* data, size_t length, bool* ok) 884 { 885 return toIntegralType<intptr_t>(data, lengthOfCharactersAsInteger(data, length), ok, 10); 886 } 887 888 double charactersToDouble(const UChar* data, size_t length, bool* ok) 889 { 890 if (!length) { 891 if (ok) 892 *ok = false; 893 return 0.0; 894 } 895 896 Vector<char, 256> bytes(length + 1); 897 for (unsigned i = 0; i < length; ++i) 898 bytes[i] = data[i] < 0x7F ? data[i] : '?'; 899 bytes[length] = '\0'; 900 char* end; 901 double val = WTF::strtod(bytes.data(), &end); 902 if (ok) 903 *ok = (end == 0 || *end == '\0'); 904 return val; 905 } 906 907 float charactersToFloat(const UChar* data, size_t length, bool* ok) 908 { 909 // FIXME: This will return ok even when the string fits into a double but not a float. 910 return narrowPrecisionToFloat(charactersToDouble(data, length, ok)); 911 } 912 913 PassRefPtr<SharedBuffer> utf8Buffer(const String& string) 914 { 915 // Allocate a buffer big enough to hold all the characters. 916 const int length = string.length(); 917 Vector<char> buffer(length * 3); 918 919 // Convert to runs of 8-bit characters. 920 char* p = buffer.data(); 921 const UChar* d = string.characters(); 922 ConversionResult result = convertUTF16ToUTF8(&d, d + length, &p, p + buffer.size(), true); 923 if (result != conversionOK) 924 return 0; 925 926 buffer.shrink(p - buffer.data()); 927 return SharedBuffer::adoptVector(buffer); 928 } 929 930 unsigned String::numGraphemeClusters() const 931 { 932 TextBreakIterator* it = characterBreakIterator(characters(), length()); 933 if (!it) 934 return length(); 935 936 unsigned num = 0; 937 while (textBreakNext(it) != TextBreakDone) 938 ++num; 939 return num; 940 } 941 942 unsigned String::numCharactersInGraphemeClusters(unsigned numGraphemeClusters) const 943 { 944 TextBreakIterator* it = characterBreakIterator(characters(), length()); 945 if (!it) 946 return min(length(), numGraphemeClusters); 947 948 for (unsigned i = 0; i < numGraphemeClusters; ++i) { 949 if (textBreakNext(it) == TextBreakDone) 950 return length(); 951 } 952 return textBreakCurrent(it); 953 } 954 955 } // namespace WebCore 956 957 #ifndef NDEBUG 958 // For use in the debugger - leaks memory 959 WebCore::String* string(const char*); 960 961 WebCore::String* string(const char* s) 962 { 963 return new WebCore::String(s); 964 } 965 #endif 966