• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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