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

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

JavaScriptCore: Bug 37906 - Remove JSC::UStringImpl; unify with StringImpl.

Reviewed by Oliver Hunt, Darin Adler.

JSC::UStringImpl and WebCore::StringImpl (soon to be renamed to
WTF::StringImpl) are almost identical. Remove duplication of code by unifying
the two, move missing features from UStringImpl into StringImpl & delete the
class UStringImpl.

  • API/JSClassRef.cpp:
  • API/JSContextRef.cpp:
  • GNUmakefile.am:
  • JavaScriptCore.exp:
  • JavaScriptCore.pro:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bytecode/EvalCodeCache.h:
  • bytecode/JumpTable.cpp:
  • profiler/ProfileNode.cpp:
  • runtime/Identifier.cpp:

(JSC::Identifier::add):

  • runtime/Identifier.h:

(JSC::Identifier::equal):

  • runtime/UString.cpp:
  • runtime/UString.h:

(WTF::):

  • runtime/UStringImpl.cpp: Removed.
  • runtime/UStringImpl.h:
  • wtf/text/StringHash.h:

(WebCore::StringHash::equal):
(WebCore::CaseFoldingHash::equal):

  • wtf/text/StringImpl.cpp:

(WebCore::StringImpl::~StringImpl):
(WebCore::StringImpl::empty):
(WebCore::StringImpl::sharedBuffer):
(WebCore::equal):

  • wtf/text/StringImpl.h:

(WebCore::StringImpl::StringImpl):
(WebCore::StringImpl::create):
(WebCore::StringImpl::tryCreateUninitialized):
(WebCore::StringImpl::cost):
(WebCore::StringImpl::isIdentifier):
(WebCore::StringImpl::setIsIdentifier):
(WebCore::StringImpl::computeHash):
(WebCore::StringImpl::copyChars):
(WebCore::StringImpl::):

JavaScriptGlue: Bug 37906 - Remove JSC::UStringImpl; unify with StringImpl.
Add forwarding header.

Reviewed by Oliver Hunt, Darin Adler.

  • ForwardingHeaders/wtf/ASCIICType.h: Added.
  • ForwardingHeaders/wtf/text/StringImpl.h: Added.

WebCore: Bug 37906 - Remove JSC::UStringImpl; unify with StringImpl.
Add include for StringHash.h.

Reviewed by Oliver Hunt, Darin Adler.

  • WebCore.xcodeproj/project.pbxproj:
  • bridge/c/c_class.cpp:
  • Property svn:eol-style set to native
File size: 14.2 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
60// The null string is immutable, except for refCount.
61UString* UString::s_nullUString;
62
63void initializeUString()
64{
65 // UStringImpl::empty() does not construct its static string in a threadsafe fashion,
66 // so ensure it has been initialized from here.
67 UStringImpl::empty();
68
69 UString::s_nullUString = new UString;
70}
71
72UString::UString(const char* c)
73 : m_rep(Rep::create(c))
74{
75}
76
77UString::UString(const char* c, unsigned length)
78 : m_rep(Rep::create(c, length))
79{
80}
81
82UString::UString(const UChar* c, unsigned length)
83 : m_rep(Rep::create(c, length))
84{
85}
86
87UString UString::from(int i)
88{
89 UChar buf[1 + sizeof(i) * 3];
90 UChar* end = buf + sizeof(buf) / sizeof(UChar);
91 UChar* p = end;
92
93 if (i == 0)
94 *--p = '0';
95 else if (i == INT_MIN) {
96 char minBuf[1 + sizeof(i) * 3];
97 sprintf(minBuf, "%d", INT_MIN);
98 return UString(minBuf);
99 } else {
100 bool negative = false;
101 if (i < 0) {
102 negative = true;
103 i = -i;
104 }
105 while (i) {
106 *--p = static_cast<unsigned short>((i % 10) + '0');
107 i /= 10;
108 }
109 if (negative)
110 *--p = '-';
111 }
112
113 return UString(p, static_cast<unsigned>(end - p));
114}
115
116UString UString::from(long long i)
117{
118 UChar buf[1 + sizeof(i) * 3];
119 UChar* end = buf + sizeof(buf) / sizeof(UChar);
120 UChar* p = end;
121
122 if (i == 0)
123 *--p = '0';
124 else if (i == std::numeric_limits<long long>::min()) {
125 char minBuf[1 + sizeof(i) * 3];
126#if OS(WINDOWS)
127 snprintf(minBuf, sizeof(minBuf) - 1, "%I64d", std::numeric_limits<long long>::min());
128#else
129 snprintf(minBuf, sizeof(minBuf) - 1, "%lld", std::numeric_limits<long long>::min());
130#endif
131 return UString(minBuf);
132 } else {
133 bool negative = false;
134 if (i < 0) {
135 negative = true;
136 i = -i;
137 }
138 while (i) {
139 *--p = static_cast<unsigned short>((i % 10) + '0');
140 i /= 10;
141 }
142 if (negative)
143 *--p = '-';
144 }
145
146 return UString(p, static_cast<unsigned>(end - p));
147}
148
149UString UString::from(unsigned u)
150{
151 UChar buf[sizeof(u) * 3];
152 UChar* end = buf + sizeof(buf) / sizeof(UChar);
153 UChar* p = end;
154
155 if (u == 0)
156 *--p = '0';
157 else {
158 while (u) {
159 *--p = static_cast<unsigned short>((u % 10) + '0');
160 u /= 10;
161 }
162 }
163
164 return UString(p, static_cast<unsigned>(end - p));
165}
166
167UString UString::from(long l)
168{
169 UChar buf[1 + sizeof(l) * 3];
170 UChar* end = buf + sizeof(buf) / sizeof(UChar);
171 UChar* p = end;
172
173 if (l == 0)
174 *--p = '0';
175 else if (l == LONG_MIN) {
176 char minBuf[1 + sizeof(l) * 3];
177 sprintf(minBuf, "%ld", LONG_MIN);
178 return UString(minBuf);
179 } else {
180 bool negative = false;
181 if (l < 0) {
182 negative = true;
183 l = -l;
184 }
185 while (l) {
186 *--p = static_cast<unsigned short>((l % 10) + '0');
187 l /= 10;
188 }
189 if (negative)
190 *--p = '-';
191 }
192
193 return UString(p, end - p);
194}
195
196UString UString::from(double d)
197{
198 DtoaBuffer buffer;
199 unsigned length;
200 doubleToStringInJavaScriptFormat(d, buffer, &length);
201 return UString(buffer, length);
202}
203
204char* UString::ascii() const
205{
206 static char* asciiBuffer = 0;
207
208 unsigned length = size();
209 unsigned neededSize = length + 1;
210 delete[] asciiBuffer;
211 asciiBuffer = new char[neededSize];
212
213 const UChar* p = data();
214 char* q = asciiBuffer;
215 const UChar* limit = p + length;
216 while (p != limit) {
217 *q = static_cast<char>(p[0]);
218 ++p;
219 ++q;
220 }
221 *q = '\0';
222
223 return asciiBuffer;
224}
225
226bool UString::is8Bit() const
227{
228 const UChar* u = data();
229 const UChar* limit = u + size();
230 while (u < limit) {
231 if (u[0] > 0xFF)
232 return false;
233 ++u;
234 }
235
236 return true;
237}
238
239UChar UString::operator[](unsigned pos) const
240{
241 if (pos >= size())
242 return '\0';
243 return data()[pos];
244}
245
246double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const
247{
248 if (size() == 1) {
249 UChar c = data()[0];
250 if (isASCIIDigit(c))
251 return c - '0';
252 if (isASCIISpace(c) && tolerateEmptyString)
253 return 0;
254 return NaN;
255 }
256
257 CString s = UTF8String();
258 const char* c = s.data();
259
260 // skip leading white space
261 while (isASCIISpace(*c))
262 c++;
263
264 // empty string ?
265 if (*c == '\0')
266 return tolerateEmptyString ? 0.0 : NaN;
267
268 double d;
269
270 // hex number ?
271 if (*c == '0' && (*(c + 1) == 'x' || *(c + 1) == 'X')) {
272 const char* firstDigitPosition = c + 2;
273 c++;
274 d = 0.0;
275 while (*(++c)) {
276 if (*c >= '0' && *c <= '9')
277 d = d * 16.0 + *c - '0';
278 else if ((*c >= 'A' && *c <= 'F') || (*c >= 'a' && *c <= 'f'))
279 d = d * 16.0 + (*c & 0xdf) - 'A' + 10.0;
280 else
281 break;
282 }
283
284 if (d >= mantissaOverflowLowerBound)
285 d = parseIntOverflow(firstDigitPosition, c - firstDigitPosition, 16);
286 } else {
287 // regular number ?
288 char* end;
289 d = WTF::strtod(c, &end);
290 if ((d != 0.0 || end != c) && d != Inf && d != -Inf) {
291 c = end;
292 } else {
293 double sign = 1.0;
294
295 if (*c == '+')
296 c++;
297 else if (*c == '-') {
298 sign = -1.0;
299 c++;
300 }
301
302 // We used strtod() to do the conversion. However, strtod() handles
303 // infinite values slightly differently than JavaScript in that it
304 // converts the string "inf" with any capitalization to infinity,
305 // whereas the ECMA spec requires that it be converted to NaN.
306
307 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') {
308 d = sign * Inf;
309 c += 8;
310 } else if ((d == Inf || d == -Inf) && *c != 'I' && *c != 'i')
311 c = end;
312 else
313 return NaN;
314 }
315 }
316
317 // allow trailing white space
318 while (isASCIISpace(*c))
319 c++;
320 // don't allow anything after - unless tolerant=true
321 if (!tolerateTrailingJunk && *c != '\0')
322 d = NaN;
323
324 return d;
325}
326
327double UString::toDouble(bool tolerateTrailingJunk) const
328{
329 return toDouble(tolerateTrailingJunk, true);
330}
331
332double UString::toDouble() const
333{
334 return toDouble(false, true);
335}
336
337uint32_t UString::toUInt32(bool* ok) const
338{
339 double d = toDouble();
340 bool b = true;
341
342 if (d != static_cast<uint32_t>(d)) {
343 b = false;
344 d = 0;
345 }
346
347 if (ok)
348 *ok = b;
349
350 return static_cast<uint32_t>(d);
351}
352
353uint32_t UString::toUInt32(bool* ok, bool tolerateEmptyString) const
354{
355 double d = toDouble(false, tolerateEmptyString);
356 bool b = true;
357
358 if (d != static_cast<uint32_t>(d)) {
359 b = false;
360 d = 0;
361 }
362
363 if (ok)
364 *ok = b;
365
366 return static_cast<uint32_t>(d);
367}
368
369uint32_t UString::toStrictUInt32(bool* ok) const
370{
371 if (ok)
372 *ok = false;
373
374 // Empty string is not OK.
375 unsigned len = m_rep->length();
376 if (len == 0)
377 return 0;
378 const UChar* p = m_rep->characters();
379 unsigned short c = p[0];
380
381 // If the first digit is 0, only 0 itself is OK.
382 if (c == '0') {
383 if (len == 1 && ok)
384 *ok = true;
385 return 0;
386 }
387
388 // Convert to UInt32, checking for overflow.
389 uint32_t i = 0;
390 while (1) {
391 // Process character, turning it into a digit.
392 if (c < '0' || c > '9')
393 return 0;
394 const unsigned d = c - '0';
395
396 // Multiply by 10, checking for overflow out of 32 bits.
397 if (i > 0xFFFFFFFFU / 10)
398 return 0;
399 i *= 10;
400
401 // Add in the digit, checking for overflow out of 32 bits.
402 const unsigned max = 0xFFFFFFFFU - d;
403 if (i > max)
404 return 0;
405 i += d;
406
407 // Handle end of string.
408 if (--len == 0) {
409 if (ok)
410 *ok = true;
411 return i;
412 }
413
414 // Get next character.
415 c = *(++p);
416 }
417}
418
419unsigned UString::find(const UString& f, unsigned pos) const
420{
421 unsigned fsz = f.size();
422
423 if (fsz == 1) {
424 UChar ch = f[0];
425 const UChar* end = data() + size();
426 for (const UChar* c = data() + pos; c < end; c++) {
427 if (*c == ch)
428 return static_cast<unsigned>(c - data());
429 }
430 return NotFound;
431 }
432
433 unsigned sz = size();
434 if (sz < fsz)
435 return NotFound;
436 if (fsz == 0)
437 return pos;
438 const UChar* end = data() + sz - fsz;
439 unsigned fsizeminusone = (fsz - 1) * sizeof(UChar);
440 const UChar* fdata = f.data();
441 unsigned short fchar = fdata[0];
442 ++fdata;
443 for (const UChar* c = data() + pos; c <= end; c++) {
444 if (c[0] == fchar && !memcmp(c + 1, fdata, fsizeminusone))
445 return static_cast<unsigned>(c - data());
446 }
447
448 return NotFound;
449}
450
451unsigned UString::find(UChar ch, unsigned pos) const
452{
453 const UChar* end = data() + size();
454 for (const UChar* c = data() + pos; c < end; c++) {
455 if (*c == ch)
456 return static_cast<unsigned>(c - data());
457 }
458
459 return NotFound;
460}
461
462unsigned UString::rfind(const UString& f, unsigned pos) const
463{
464 unsigned sz = size();
465 unsigned fsz = f.size();
466 if (sz < fsz)
467 return NotFound;
468 if (pos > sz - fsz)
469 pos = sz - fsz;
470 if (fsz == 0)
471 return pos;
472 unsigned fsizeminusone = (fsz - 1) * sizeof(UChar);
473 const UChar* fdata = f.data();
474 for (const UChar* c = data() + pos; c >= data(); c--) {
475 if (*c == *fdata && !memcmp(c + 1, fdata + 1, fsizeminusone))
476 return static_cast<unsigned>(c - data());
477 }
478
479 return NotFound;
480}
481
482unsigned UString::rfind(UChar ch, unsigned pos) const
483{
484 if (isEmpty())
485 return NotFound;
486 if (pos + 1 >= size())
487 pos = size() - 1;
488 for (const UChar* c = data() + pos; c >= data(); c--) {
489 if (*c == ch)
490 return static_cast<unsigned>(c - data());
491 }
492
493 return NotFound;
494}
495
496UString UString::substr(unsigned pos, unsigned len) const
497{
498 unsigned s = size();
499
500 if (pos >= s)
501 pos = s;
502 unsigned limit = s - pos;
503 if (len > limit)
504 len = limit;
505
506 if (pos == 0 && len == s)
507 return *this;
508
509 return UString(Rep::create(m_rep, pos, len));
510}
511
512bool operator==(const UString& s1, const char *s2)
513{
514 if (s2 == 0)
515 return s1.isEmpty();
516
517 const UChar* u = s1.data();
518 const UChar* uend = u + s1.size();
519 while (u != uend && *s2) {
520 if (u[0] != (unsigned char)*s2)
521 return false;
522 s2++;
523 u++;
524 }
525
526 return u == uend && *s2 == 0;
527}
528
529bool operator<(const UString& s1, const UString& s2)
530{
531 const unsigned l1 = s1.size();
532 const unsigned l2 = s2.size();
533 const unsigned lmin = l1 < l2 ? l1 : l2;
534 const UChar* c1 = s1.data();
535 const UChar* c2 = s2.data();
536 unsigned l = 0;
537 while (l < lmin && *c1 == *c2) {
538 c1++;
539 c2++;
540 l++;
541 }
542 if (l < lmin)
543 return (c1[0] < c2[0]);
544
545 return (l1 < l2);
546}
547
548bool operator>(const UString& s1, const UString& s2)
549{
550 const unsigned l1 = s1.size();
551 const unsigned l2 = s2.size();
552 const unsigned lmin = l1 < l2 ? l1 : l2;
553 const UChar* c1 = s1.data();
554 const UChar* c2 = s2.data();
555 unsigned l = 0;
556 while (l < lmin && *c1 == *c2) {
557 c1++;
558 c2++;
559 l++;
560 }
561 if (l < lmin)
562 return (c1[0] > c2[0]);
563
564 return (l1 > l2);
565}
566
567int compare(const UString& s1, const UString& s2)
568{
569 const unsigned l1 = s1.size();
570 const unsigned l2 = s2.size();
571 const unsigned lmin = l1 < l2 ? l1 : l2;
572 const UChar* c1 = s1.data();
573 const UChar* c2 = s2.data();
574 unsigned l = 0;
575 while (l < lmin && *c1 == *c2) {
576 c1++;
577 c2++;
578 l++;
579 }
580
581 if (l < lmin)
582 return (c1[0] > c2[0]) ? 1 : -1;
583
584 if (l1 == l2)
585 return 0;
586
587 return (l1 > l2) ? 1 : -1;
588}
589
590CString UString::UTF8String(bool strict) const
591{
592 // Allocate a buffer big enough to hold all the characters.
593 const unsigned length = size();
594 Vector<char, 1024> buffer(length * 3);
595
596 // Convert to runs of 8-bit characters.
597 char* p = buffer.data();
598 const UChar* d = reinterpret_cast<const UChar*>(&data()[0]);
599 ConversionResult result = convertUTF16ToUTF8(&d, d + length, &p, p + buffer.size(), strict);
600 if (result != conversionOK)
601 return CString();
602
603 return CString(buffer.data(), p - buffer.data());
604}
605
606} // namespace JSC
Note: See TracBrowser for help on using the repository browser.