1 /*
2 * (C) 1999 Lars Knoll (knoll@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
String(const UChar * str,unsigned len)51 String::String(const UChar* str, unsigned len)
52 {
53 if (!str)
54 return;
55 m_impl = StringImpl::create(str, len);
56 }
57
String(const UChar * str)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
String(const char * str)70 String::String(const char* str)
71 {
72 if (!str)
73 return;
74 m_impl = StringImpl::create(str);
75 }
76
String(const char * str,unsigned length)77 String::String(const char* str, unsigned length)
78 {
79 if (!str)
80 return;
81 m_impl = StringImpl::create(str, length);
82 }
83
append(const String & str)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
append(char c)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
append(UChar c)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
operator +(const String & a,const String & b)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
operator +(const String & s,const char * cs)151 String operator+(const String& s, const char* cs)
152 {
153 return s + String(cs);
154 }
155
operator +(const char * cs,const String & s)156 String operator+(const char* cs, const String& s)
157 {
158 return String(cs) + s;
159 }
160
insert(const String & str,unsigned pos)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
append(const UChar * charactersToAppend,unsigned lengthToAppend)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
insert(const UChar * charactersToInsert,unsigned lengthToInsert,unsigned position)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
operator [](unsigned i) const216 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
characterStartingAt(unsigned i) const223 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
length() const230 unsigned String::length() const
231 {
232 if (!m_impl)
233 return 0;
234 return m_impl->length();
235 }
236
truncate(unsigned position)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
remove(unsigned position,int lengthToRemove)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
substring(unsigned pos,unsigned len) const264 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
lower() const271 String String::lower() const
272 {
273 if (!m_impl)
274 return String();
275 return m_impl->lower();
276 }
277
upper() const278 String String::upper() const
279 {
280 if (!m_impl)
281 return String();
282 return m_impl->upper();
283 }
284
stripWhiteSpace() const285 String String::stripWhiteSpace() const
286 {
287 if (!m_impl)
288 return String();
289 return m_impl->stripWhiteSpace();
290 }
291
simplifyWhiteSpace() const292 String String::simplifyWhiteSpace() const
293 {
294 if (!m_impl)
295 return String();
296 return m_impl->simplifyWhiteSpace();
297 }
298
removeCharacters(CharacterMatchFunctionPtr findMatch) const299 String String::removeCharacters(CharacterMatchFunctionPtr findMatch) const
300 {
301 if (!m_impl)
302 return String();
303 return m_impl->removeCharacters(findMatch);
304 }
305
foldCase() const306 String String::foldCase() const
307 {
308 if (!m_impl)
309 return String();
310 return m_impl->foldCase();
311 }
312
percentage(int & result) const313 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
characters() const325 const UChar* String::characters() const
326 {
327 if (!m_impl)
328 return 0;
329 return m_impl->characters();
330 }
331
charactersWithNullTermination()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
format(const char * format,...)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
number(short n)417 String String::number(short n)
418 {
419 return String::format("%hd", n);
420 }
421
number(unsigned short n)422 String String::number(unsigned short n)
423 {
424 return String::format("%hu", n);
425 }
426
number(int n)427 String String::number(int n)
428 {
429 return String::format("%d", n);
430 }
431
number(unsigned n)432 String String::number(unsigned n)
433 {
434 return String::format("%u", n);
435 }
436
number(long n)437 String String::number(long n)
438 {
439 return String::format("%ld", n);
440 }
441
number(unsigned long n)442 String String::number(unsigned long n)
443 {
444 return String::format("%lu", n);
445 }
446
number(long long n)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
number(unsigned long long n)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
number(double n)465 String String::number(double n)
466 {
467 return String::format("%.6lg", n);
468 }
469
toIntStrict(bool * ok,int base) const470 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
toUIntStrict(bool * ok,int base) const480 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
toInt64Strict(bool * ok,int base) const490 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
toUInt64Strict(bool * ok,int base) const500 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
toIntPtrStrict(bool * ok,int base) const510 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
toInt(bool * ok) const521 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
toUInt(bool * ok) const531 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
toInt64(bool * ok) const541 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
toUInt64(bool * ok) const551 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
toIntPtr(bool * ok) const561 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
toDouble(bool * ok) const571 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
toFloat(bool * ok) const581 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
threadsafeCopy() const591 String String::threadsafeCopy() const
592 {
593 if (!m_impl)
594 return String();
595 return m_impl->threadsafeCopy();
596 }
597
crossThreadString() const598 String String::crossThreadString() const
599 {
600 if (!m_impl)
601 return String();
602 return m_impl->crossThreadString();
603 }
604
isEmpty() const605 bool String::isEmpty() const
606 {
607 return !m_impl || !m_impl->length();
608 }
609
split(const String & separator,bool allowEmptyEntries,Vector<String> & result) const610 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
split(const String & separator,Vector<String> & result) const625 void String::split(const String& separator, Vector<String>& result) const
626 {
627 return split(separator, false, result);
628 }
629
split(UChar separator,bool allowEmptyEntries,Vector<String> & result) const630 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
split(UChar separator,Vector<String> & result) const645 void String::split(UChar separator, Vector<String>& result) const
646 {
647 return split(String(&separator, 1), false, result);
648 }
649
650 #ifndef NDEBUG
ascii() const651 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
latin1() const666 CString String::latin1() const
667 {
668 return Latin1Encoding().encode(characters(), length(), QuestionMarksForUnencodables);
669 }
670
utf8() const671 CString String::utf8() const
672 {
673 return UTF8Encoding().encode(characters(), length(), QuestionMarksForUnencodables);
674 }
675
fromUTF8(const char * string,size_t size)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
fromUTF8(const char * string)683 String String::fromUTF8(const char* string)
684 {
685 if (!string)
686 return String();
687 return UTF8Encoding().decode(string, strlen(string));
688 }
689
fromUTF8WithLatin1Fallback(const char * string,size_t size)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)
String(const Identifier & str)700 String::String(const Identifier& str)
701 {
702 if (str.isNull())
703 return;
704 m_impl = StringImpl::create(str.ustring());
705 }
706
String(const UString & str)707 String::String(const UString& str)
708 {
709 if (str.isNull())
710 return;
711 m_impl = StringImpl::create(str);
712 }
713
operator UString() const714 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
isCharacterAllowedInBase(UChar c,int base)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>
toIntegralType(const UChar * data,size_t length,bool * ok,int base)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
lengthOfCharactersAsInteger(const UChar * data,size_t length)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
charactersToIntStrict(const UChar * data,size_t length,bool * ok,int base)838 int charactersToIntStrict(const UChar* data, size_t length, bool* ok, int base)
839 {
840 return toIntegralType<int>(data, length, ok, base);
841 }
842
charactersToUIntStrict(const UChar * data,size_t length,bool * ok,int base)843 unsigned charactersToUIntStrict(const UChar* data, size_t length, bool* ok, int base)
844 {
845 return toIntegralType<unsigned>(data, length, ok, base);
846 }
847
charactersToInt64Strict(const UChar * data,size_t length,bool * ok,int base)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
charactersToUInt64Strict(const UChar * data,size_t length,bool * ok,int base)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
charactersToIntPtrStrict(const UChar * data,size_t length,bool * ok,int base)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
charactersToInt(const UChar * data,size_t length,bool * ok)863 int charactersToInt(const UChar* data, size_t length, bool* ok)
864 {
865 return toIntegralType<int>(data, lengthOfCharactersAsInteger(data, length), ok, 10);
866 }
867
charactersToUInt(const UChar * data,size_t length,bool * ok)868 unsigned charactersToUInt(const UChar* data, size_t length, bool* ok)
869 {
870 return toIntegralType<unsigned>(data, lengthOfCharactersAsInteger(data, length), ok, 10);
871 }
872
charactersToInt64(const UChar * data,size_t length,bool * ok)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
charactersToUInt64(const UChar * data,size_t length,bool * ok)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
charactersToIntPtr(const UChar * data,size_t length,bool * ok)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
charactersToDouble(const UChar * data,size_t length,bool * ok)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
charactersToFloat(const UChar * data,size_t length,bool * ok)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
utf8Buffer(const String & string)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
numGraphemeClusters() const930 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
numCharactersInGraphemeClusters(unsigned numGraphemeClusters) const942 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
string(const char * s)961 WebCore::String* string(const char* s)
962 {
963 return new WebCore::String(s);
964 }
965 #endif
966