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