source: webkit/trunk/JavaScriptCore/runtime/UString.cpp@ 56560

Last change on this file since 56560 was 56560, checked in by [email protected], 15 years ago

Bug 36611 - Cleanup JSC::CString
Rename CString::c_str() -> CString::data(), CString::size() -> CString::length(),
remove UString::getCString() (all uses are wrong, should use UString::UTF8String()).

Reviewed by Geoff Garen.

JavaScriptCore:

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::printUnaryOp):
(JSC::CodeBlock::printBinaryOp):
(JSC::CodeBlock::printConditionalJump):
(JSC::CodeBlock::printGetByIdOp):
(JSC::CodeBlock::printPutByIdOp):
(JSC::printGlobalResolveInfo):
(JSC::printStructureStubInfo):
(JSC::CodeBlock::printStructure):
(JSC::CodeBlock::printStructures):
(JSC::CodeBlock::dump):

  • jsc.cpp:

(functionPrint):
(functionDebug):
(runInteractive):
(fillBufferWithContentsOfFile):

  • profiler/CallIdentifier.h:

(JSC::CallIdentifier::c_str):

  • profiler/Profile.cpp:

(JSC::Profile::debugPrintDataSampleStyle):

  • profiler/ProfileNode.cpp:

(JSC::ProfileNode::debugPrintData):
(JSC::ProfileNode::debugPrintDataSampleStyle):

  • runtime/DateConversion.cpp:

(JSC::parseDate):

  • runtime/JSGlobalObjectFunctions.cpp:

(JSC::encode):
(JSC::globalFuncJSCPrint):

  • runtime/UString.cpp:

(JSC::operator==):
(JSC::UString::toDouble):

  • runtime/UString.h:

(JSC::CString::length):
(JSC::CString::data):

WebCore:

  • bridge/NP_jsobject.cpp:

(_NPN_Enumerate):

  • bridge/c/c_utility.cpp:

(JSC::Bindings::convertValueToNPVariant):

  • bridge/jni/jsc/JNIBridgeJSC.cpp:

(JavaField::valueFromInstance):
(JavaField::setValueToInstance):

  • bridge/jni/jsc/JavaInstanceJSC.cpp:

(JavaInstance::invokeMethod):

  • bridge/jni/jsc/JavaStringJSC.h:

(JSC::Bindings::JavaStringImpl::UTF8String):

  • Property svn:eol-style set to native
File size: 16.4 KB
Line 
1/*
2 * Copyright (C) 1999-2000 Harri Porten ([email protected])
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
4 * Copyright (C) 2007 Cameron Zwarich ([email protected])
5 * Copyright (C) 2009 Google Inc. All rights reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 *
22 */
23
24#include "config.h"
25#include "UString.h"
26
27#include "JSGlobalObjectFunctions.h"
28#include "Collector.h"
29#include "dtoa.h"
30#include "Identifier.h"
31#include "Operations.h"
32#include <ctype.h>
33#include <limits.h>
34#include <limits>
35#include <math.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <wtf/ASCIICType.h>
40#include <wtf/Assertions.h>
41#include <wtf/MathExtras.h>
42#include <wtf/StringExtras.h>
43#include <wtf/Vector.h>
44#include <wtf/unicode/UTF8.h>
45#include <wtf/StringExtras.h>
46
47#if HAVE(STRINGS_H)
48#include <strings.h>
49#endif
50
51using namespace WTF;
52using namespace WTF::Unicode;
53using namespace std;
54
55namespace JSC {
56
57extern const double NaN;
58extern const double Inf;
59
60CString::CString(const char* c)
61 : m_length(strlen(c))
62 , m_data(new char[m_length + 1])
63{
64 memcpy(m_data, c, m_length + 1);
65}
66
67CString::CString(const char* c, size_t length)
68 : m_length(length)
69 , m_data(new char[length + 1])
70{
71 memcpy(m_data, c, m_length);
72 m_data[m_length] = 0;
73}
74
75CString::CString(const CString& b)
76{
77 m_length = b.m_length;
78 if (b.m_data) {
79 m_data = new char[m_length + 1];
80 memcpy(m_data, b.m_data, m_length + 1);
81 } else
82 m_data = 0;
83}
84
85CString::~CString()
86{
87 delete [] m_data;
88}
89
90CString CString::adopt(char* c, size_t length)
91{
92 CString s;
93 s.m_data = c;
94 s.m_length = length;
95 return s;
96}
97
98CString& CString::append(const CString& t)
99{
100 char* n;
101 n = new char[m_length + t.m_length + 1];
102 if (m_length)
103 memcpy(n, m_data, m_length);
104 if (t.m_length)
105 memcpy(n + m_length, t.m_data, t.m_length);
106 m_length += t.m_length;
107 n[m_length] = 0;
108
109 delete [] m_data;
110 m_data = n;
111
112 return *this;
113}
114
115CString& CString::operator=(const char* c)
116{
117 if (m_data)
118 delete [] m_data;
119 m_length = strlen(c);
120 m_data = new char[m_length + 1];
121 memcpy(m_data, c, m_length + 1);
122
123 return *this;
124}
125
126CString& CString::operator=(const CString& str)
127{
128 if (this == &str)
129 return *this;
130
131 if (m_data)
132 delete [] m_data;
133 m_length = str.m_length;
134 if (str.m_data) {
135 m_data = new char[m_length + 1];
136 memcpy(m_data, str.m_data, m_length + 1);
137 } else
138 m_data = 0;
139
140 return *this;
141}
142
143bool operator==(const CString& c1, const CString& c2)
144{
145 size_t len = c1.length();
146 return len == c2.length() && (len == 0 || memcmp(c1.data(), c2.data(), len) == 0);
147}
148
149// The null string is immutable, except for refCount.
150UString::Rep* UString::s_nullRep;
151UString* UString::s_nullUString;
152
153void initializeUString()
154{
155 // UStringImpl::empty() does not construct its static string in a threadsafe fashion,
156 // so ensure it has been initialized from here.
157 UStringImpl::empty();
158
159 UString::s_nullRep = new UStringImpl(0, 0, UStringImpl::ConstructStaticString);
160 UString::s_nullUString = new UString;
161}
162
163UString::UString(const char* c)
164 : m_rep(Rep::create(c))
165{
166}
167
168UString::UString(const char* c, unsigned length)
169 : m_rep(Rep::create(c, length))
170{
171}
172
173UString::UString(const UChar* c, unsigned length)
174 : m_rep(Rep::create(c, length))
175{
176}
177
178UString UString::from(int i)
179{
180 UChar buf[1 + sizeof(i) * 3];
181 UChar* end = buf + sizeof(buf) / sizeof(UChar);
182 UChar* p = end;
183
184 if (i == 0)
185 *--p = '0';
186 else if (i == INT_MIN) {
187 char minBuf[1 + sizeof(i) * 3];
188 sprintf(minBuf, "%d", INT_MIN);
189 return UString(minBuf);
190 } else {
191 bool negative = false;
192 if (i < 0) {
193 negative = true;
194 i = -i;
195 }
196 while (i) {
197 *--p = static_cast<unsigned short>((i % 10) + '0');
198 i /= 10;
199 }
200 if (negative)
201 *--p = '-';
202 }
203
204 return UString(p, static_cast<unsigned>(end - p));
205}
206
207UString UString::from(long long i)
208{
209 UChar buf[1 + sizeof(i) * 3];
210 UChar* end = buf + sizeof(buf) / sizeof(UChar);
211 UChar* p = end;
212
213 if (i == 0)
214 *--p = '0';
215 else if (i == std::numeric_limits<long long>::min()) {
216 char minBuf[1 + sizeof(i) * 3];
217#if OS(WINDOWS)
218 snprintf(minBuf, sizeof(minBuf) - 1, "%I64d", std::numeric_limits<long long>::min());
219#else
220 snprintf(minBuf, sizeof(minBuf) - 1, "%lld", std::numeric_limits<long long>::min());
221#endif
222 return UString(minBuf);
223 } else {
224 bool negative = false;
225 if (i < 0) {
226 negative = true;
227 i = -i;
228 }
229 while (i) {
230 *--p = static_cast<unsigned short>((i % 10) + '0');
231 i /= 10;
232 }
233 if (negative)
234 *--p = '-';
235 }
236
237 return UString(p, static_cast<unsigned>(end - p));
238}
239
240UString UString::from(unsigned u)
241{
242 UChar buf[sizeof(u) * 3];
243 UChar* end = buf + sizeof(buf) / sizeof(UChar);
244 UChar* p = end;
245
246 if (u == 0)
247 *--p = '0';
248 else {
249 while (u) {
250 *--p = static_cast<unsigned short>((u % 10) + '0');
251 u /= 10;
252 }
253 }
254
255 return UString(p, static_cast<unsigned>(end - p));
256}
257
258UString UString::from(long l)
259{
260 UChar buf[1 + sizeof(l) * 3];
261 UChar* end = buf + sizeof(buf) / sizeof(UChar);
262 UChar* p = end;
263
264 if (l == 0)
265 *--p = '0';
266 else if (l == LONG_MIN) {
267 char minBuf[1 + sizeof(l) * 3];
268 sprintf(minBuf, "%ld", LONG_MIN);
269 return UString(minBuf);
270 } else {
271 bool negative = false;
272 if (l < 0) {
273 negative = true;
274 l = -l;
275 }
276 while (l) {
277 *--p = static_cast<unsigned short>((l % 10) + '0');
278 l /= 10;
279 }
280 if (negative)
281 *--p = '-';
282 }
283
284 return UString(p, end - p);
285}
286
287UString UString::from(double d)
288{
289 DtoaBuffer buffer;
290 unsigned length;
291 doubleToStringInJavaScriptFormat(d, buffer, &length);
292 return UString(buffer, length);
293}
294
295char* UString::ascii() const
296{
297 static char* asciiBuffer = 0;
298
299 unsigned length = size();
300 unsigned neededSize = length + 1;
301 delete[] asciiBuffer;
302 asciiBuffer = new char[neededSize];
303
304 const UChar* p = data();
305 char* q = asciiBuffer;
306 const UChar* limit = p + length;
307 while (p != limit) {
308 *q = static_cast<char>(p[0]);
309 ++p;
310 ++q;
311 }
312 *q = '\0';
313
314 return asciiBuffer;
315}
316
317bool UString::is8Bit() const
318{
319 const UChar* u = data();
320 const UChar* limit = u + size();
321 while (u < limit) {
322 if (u[0] > 0xFF)
323 return false;
324 ++u;
325 }
326
327 return true;
328}
329
330UChar UString::operator[](unsigned pos) const
331{
332 if (pos >= size())
333 return '\0';
334 return data()[pos];
335}
336
337double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const
338{
339 if (size() == 1) {
340 UChar c = data()[0];
341 if (isASCIIDigit(c))
342 return c - '0';
343 if (isASCIISpace(c) && tolerateEmptyString)
344 return 0;
345 return NaN;
346 }
347
348 CString s = UTF8String();
349 const char* c = s.data();
350
351 // skip leading white space
352 while (isASCIISpace(*c))
353 c++;
354
355 // empty string ?
356 if (*c == '\0')
357 return tolerateEmptyString ? 0.0 : NaN;
358
359 double d;
360
361 // hex number ?
362 if (*c == '0' && (*(c + 1) == 'x' || *(c + 1) == 'X')) {
363 const char* firstDigitPosition = c + 2;
364 c++;
365 d = 0.0;
366 while (*(++c)) {
367 if (*c >= '0' && *c <= '9')
368 d = d * 16.0 + *c - '0';
369 else if ((*c >= 'A' && *c <= 'F') || (*c >= 'a' && *c <= 'f'))
370 d = d * 16.0 + (*c & 0xdf) - 'A' + 10.0;
371 else
372 break;
373 }
374
375 if (d >= mantissaOverflowLowerBound)
376 d = parseIntOverflow(firstDigitPosition, c - firstDigitPosition, 16);
377 } else {
378 // regular number ?
379 char* end;
380 d = WTF::strtod(c, &end);
381 if ((d != 0.0 || end != c) && d != Inf && d != -Inf) {
382 c = end;
383 } else {
384 double sign = 1.0;
385
386 if (*c == '+')
387 c++;
388 else if (*c == '-') {
389 sign = -1.0;
390 c++;
391 }
392
393 // We used strtod() to do the conversion. However, strtod() handles
394 // infinite values slightly differently than JavaScript in that it
395 // converts the string "inf" with any capitalization to infinity,
396 // whereas the ECMA spec requires that it be converted to NaN.
397
398 if (c[0] == 'I' && c[1] == 'n' && c[2] == 'f' && c[3] == 'i' && c[4] == 'n' && c[5] == 'i' && c[6] == 't' && c[7] == 'y') {
399 d = sign * Inf;
400 c += 8;
401 } else if ((d == Inf || d == -Inf) && *c != 'I' && *c != 'i')
402 c = end;
403 else
404 return NaN;
405 }
406 }
407
408 // allow trailing white space
409 while (isASCIISpace(*c))
410 c++;
411 // don't allow anything after - unless tolerant=true
412 if (!tolerateTrailingJunk && *c != '\0')
413 d = NaN;
414
415 return d;
416}
417
418double UString::toDouble(bool tolerateTrailingJunk) const
419{
420 return toDouble(tolerateTrailingJunk, true);
421}
422
423double UString::toDouble() const
424{
425 return toDouble(false, true);
426}
427
428uint32_t UString::toUInt32(bool* ok) const
429{
430 double d = toDouble();
431 bool b = true;
432
433 if (d != static_cast<uint32_t>(d)) {
434 b = false;
435 d = 0;
436 }
437
438 if (ok)
439 *ok = b;
440
441 return static_cast<uint32_t>(d);
442}
443
444uint32_t UString::toUInt32(bool* ok, bool tolerateEmptyString) const
445{
446 double d = toDouble(false, tolerateEmptyString);
447 bool b = true;
448
449 if (d != static_cast<uint32_t>(d)) {
450 b = false;
451 d = 0;
452 }
453
454 if (ok)
455 *ok = b;
456
457 return static_cast<uint32_t>(d);
458}
459
460uint32_t UString::toStrictUInt32(bool* ok) const
461{
462 if (ok)
463 *ok = false;
464
465 // Empty string is not OK.
466 unsigned len = m_rep->length();
467 if (len == 0)
468 return 0;
469 const UChar* p = m_rep->characters();
470 unsigned short c = p[0];
471
472 // If the first digit is 0, only 0 itself is OK.
473 if (c == '0') {
474 if (len == 1 && ok)
475 *ok = true;
476 return 0;
477 }
478
479 // Convert to UInt32, checking for overflow.
480 uint32_t i = 0;
481 while (1) {
482 // Process character, turning it into a digit.
483 if (c < '0' || c > '9')
484 return 0;
485 const unsigned d = c - '0';
486
487 // Multiply by 10, checking for overflow out of 32 bits.
488 if (i > 0xFFFFFFFFU / 10)
489 return 0;
490 i *= 10;
491
492 // Add in the digit, checking for overflow out of 32 bits.
493 const unsigned max = 0xFFFFFFFFU - d;
494 if (i > max)
495 return 0;
496 i += d;
497
498 // Handle end of string.
499 if (--len == 0) {
500 if (ok)
501 *ok = true;
502 return i;
503 }
504
505 // Get next character.
506 c = *(++p);
507 }
508}
509
510unsigned UString::find(const UString& f, unsigned pos) const
511{
512 unsigned fsz = f.size();
513
514 if (fsz == 1) {
515 UChar ch = f[0];
516 const UChar* end = data() + size();
517 for (const UChar* c = data() + pos; c < end; c++) {
518 if (*c == ch)
519 return static_cast<unsigned>(c - data());
520 }
521 return NotFound;
522 }
523
524 unsigned sz = size();
525 if (sz < fsz)
526 return NotFound;
527 if (fsz == 0)
528 return pos;
529 const UChar* end = data() + sz - fsz;
530 unsigned fsizeminusone = (fsz - 1) * sizeof(UChar);
531 const UChar* fdata = f.data();
532 unsigned short fchar = fdata[0];
533 ++fdata;
534 for (const UChar* c = data() + pos; c <= end; c++) {
535 if (c[0] == fchar && !memcmp(c + 1, fdata, fsizeminusone))
536 return static_cast<unsigned>(c - data());
537 }
538
539 return NotFound;
540}
541
542unsigned UString::find(UChar ch, unsigned pos) const
543{
544 const UChar* end = data() + size();
545 for (const UChar* c = data() + pos; c < end; c++) {
546 if (*c == ch)
547 return static_cast<unsigned>(c - data());
548 }
549
550 return NotFound;
551}
552
553unsigned UString::rfind(const UString& f, unsigned pos) const
554{
555 unsigned sz = size();
556 unsigned fsz = f.size();
557 if (sz < fsz)
558 return NotFound;
559 if (pos > sz - fsz)
560 pos = sz - fsz;
561 if (fsz == 0)
562 return pos;
563 unsigned fsizeminusone = (fsz - 1) * sizeof(UChar);
564 const UChar* fdata = f.data();
565 for (const UChar* c = data() + pos; c >= data(); c--) {
566 if (*c == *fdata && !memcmp(c + 1, fdata + 1, fsizeminusone))
567 return static_cast<unsigned>(c - data());
568 }
569
570 return NotFound;
571}
572
573unsigned UString::rfind(UChar ch, unsigned pos) const
574{
575 if (isEmpty())
576 return NotFound;
577 if (pos + 1 >= size())
578 pos = size() - 1;
579 for (const UChar* c = data() + pos; c >= data(); c--) {
580 if (*c == ch)
581 return static_cast<unsigned>(c - data());
582 }
583
584 return NotFound;
585}
586
587UString UString::substr(unsigned pos, unsigned len) const
588{
589 unsigned s = size();
590
591 if (pos >= s)
592 pos = s;
593 unsigned limit = s - pos;
594 if (len > limit)
595 len = limit;
596
597 if (pos == 0 && len == s)
598 return *this;
599
600 return UString(Rep::create(m_rep, pos, len));
601}
602
603bool operator==(const UString& s1, const char *s2)
604{
605 if (s2 == 0)
606 return s1.isEmpty();
607
608 const UChar* u = s1.data();
609 const UChar* uend = u + s1.size();
610 while (u != uend && *s2) {
611 if (u[0] != (unsigned char)*s2)
612 return false;
613 s2++;
614 u++;
615 }
616
617 return u == uend && *s2 == 0;
618}
619
620bool operator<(const UString& s1, const UString& s2)
621{
622 const unsigned l1 = s1.size();
623 const unsigned l2 = s2.size();
624 const unsigned lmin = l1 < l2 ? l1 : l2;
625 const UChar* c1 = s1.data();
626 const UChar* c2 = s2.data();
627 unsigned l = 0;
628 while (l < lmin && *c1 == *c2) {
629 c1++;
630 c2++;
631 l++;
632 }
633 if (l < lmin)
634 return (c1[0] < c2[0]);
635
636 return (l1 < l2);
637}
638
639bool operator>(const UString& s1, const UString& s2)
640{
641 const unsigned l1 = s1.size();
642 const unsigned l2 = s2.size();
643 const unsigned lmin = l1 < l2 ? l1 : l2;
644 const UChar* c1 = s1.data();
645 const UChar* c2 = s2.data();
646 unsigned l = 0;
647 while (l < lmin && *c1 == *c2) {
648 c1++;
649 c2++;
650 l++;
651 }
652 if (l < lmin)
653 return (c1[0] > c2[0]);
654
655 return (l1 > l2);
656}
657
658int compare(const UString& s1, const UString& s2)
659{
660 const unsigned l1 = s1.size();
661 const unsigned l2 = s2.size();
662 const unsigned lmin = l1 < l2 ? l1 : l2;
663 const UChar* c1 = s1.data();
664 const UChar* c2 = s2.data();
665 unsigned l = 0;
666 while (l < lmin && *c1 == *c2) {
667 c1++;
668 c2++;
669 l++;
670 }
671
672 if (l < lmin)
673 return (c1[0] > c2[0]) ? 1 : -1;
674
675 if (l1 == l2)
676 return 0;
677
678 return (l1 > l2) ? 1 : -1;
679}
680
681bool equal(const UString::Rep* r, const UString::Rep* b)
682{
683 unsigned length = r->length();
684 if (length != b->length())
685 return false;
686 const UChar* d = r->characters();
687 const UChar* s = b->characters();
688 for (unsigned i = 0; i != length; ++i) {
689 if (d[i] != s[i])
690 return false;
691 }
692 return true;
693}
694
695CString UString::UTF8String(bool strict) const
696{
697 // Allocate a buffer big enough to hold all the characters.
698 const unsigned length = size();
699 Vector<char, 1024> buffer(length * 3);
700
701 // Convert to runs of 8-bit characters.
702 char* p = buffer.data();
703 const UChar* d = reinterpret_cast<const UChar*>(&data()[0]);
704 ConversionResult result = convertUTF16ToUTF8(&d, d + length, &p, p + buffer.size(), strict);
705 if (result != conversionOK)
706 return CString();
707
708 return CString(buffer.data(), p - buffer.data());
709}
710
711} // namespace JSC
Note: See TracBrowser for help on using the repository browser.