39 #include "operations.h"
40 #include "identifier.h"
45 extern const double NaN;
46 extern const double Inf;
51 CString::CString(
const char *c)
54 data =
new char[length+1];
55 memcpy(data, c, length + 1);
58 CString::CString(
const char *c,
int len)
61 data =
new char[len+1];
66 CString::CString(
const CString &b)
69 data =
new char[length+1];
70 memcpy(data, b.data, length + 1);
80 char *n =
new char[length + t.length + 1];
82 memcpy(n, data, length);
84 memcpy(n+length, t.data, t.length);
94 CString &CString::operator=(
const char *c)
98 data =
new char[length+1];
99 memcpy(data, c, length + 1);
112 data =
new char[length + 1];
113 memcpy(data, str.data, length + 1);
124 return len == c2.size() && (len == 0 || memcmp(c1.c_str(), c2.c_str(), len) == 0);
128 UString::Rep UString::Rep::null = { 0, 0, 0, 1, 1 };
129 UString::Rep UString::Rep::empty = { 0, 0, 0, 1, 1 };
131 static const int normalStatBufferSize = 4096;
132 static char *statBuffer = 0;
133 static int statBufferSize = 0;
142 return static_cast<unsigned char>( ( ( uc >=
'A' ) && ( uc <=
'Z' ) ) ? ( (
int)uc +
'a' -
'A' ) : uc );
151 return static_cast<unsigned char>( ( ( uc >=
'a' ) && ( uc <=
'z' ) ) ? ( (
int)uc +
'A' -
'a' ) : uc );
157 if (offset < str->rep->len)
158 *(str->rep->dat + offset) = c;
163 UChar& UCharReference::ref()
const
165 if (offset < str->rep->len)
166 return *(str->rep->dat + offset);
172 static inline UChar* allocateChars(
int s)
175 return reinterpret_cast<UChar*
>(
new short[s]);
178 UString::Rep *UString::Rep::create(
UChar *d,
int l)
189 void UString::Rep::destroy()
191 if (capacity == capacityForIdentifier)
192 Identifier::remove(
this);
199 const unsigned PHI = 0x9e3779b9U;
204 unsigned UString::Rep::computeHash(
const UChar *s,
int length)
206 int prefixLength = length < 8 ? length : 8;
207 int suffixPosition = length < 16 ? 8 : length - 8;
214 for (
int i = 0; i < prefixLength; i++) {
219 for (
int i = suffixPosition; i < length; i++){
238 unsigned UString::Rep::computeHash(
const char *s)
240 int length = strlen(s);
241 int prefixLength = length < 8 ? length : 8;
242 int suffixPosition = length < 16 ? 8 : length - 8;
249 for (
int i = 0; i < prefixLength; i++) {
250 h += (
unsigned char)s[i];
254 for (
int i = suffixPosition; i < length; i++) {
255 h += (
unsigned char)s[i];
278 UChar *d = allocateChars(1);
280 rep = Rep::create(d, 1);
289 int length = strlen(c);
295 for (
int i = 0; i < length; i++)
296 d[i].uc = (
unsigned char)c[i];
297 rep = Rep::create(d, length);
306 UChar *d = allocateChars(length);
307 memcpy(d, c, length *
sizeof(
UChar));
308 rep = Rep::create(d, length);
319 d = allocateChars(length);
320 memcpy(d, c, length *
sizeof(
UChar));
323 rep = Rep::create(d, length);
328 int aSize = a.
size();
329 int bSize = b.
size();
330 int length = aSize + bSize;
335 UChar *d = allocateChars(length);
336 memcpy(d, a.
data(), aSize *
sizeof(
UChar));
337 memcpy(d + aSize, b.
data(), bSize *
sizeof(
UChar));
338 rep = Rep::create(d, length);
343 return from((
long)i);
349 UChar *end = buf + 20;
356 *--p = (
unsigned short)((u % 10) +
'0');
367 UChar *end = buf + 20;
373 bool negative =
false;
379 *--p = (
unsigned short)((l % 10) +
'0');
396 char *result = kjs_dtoa(d, 0, 0, &decimalPoint, &sign, NULL);
397 int length = strlen(result);
404 if (decimalPoint <= 0 && decimalPoint > -6) {
407 for (
int j = decimalPoint; j < 0; j++) {
410 strcpy(buf + i, result);
411 }
else if (decimalPoint <= 21 && decimalPoint > 0) {
412 if (length <= decimalPoint) {
413 strcpy(buf + i, result);
415 for (
int j = 0; j < decimalPoint - length; j++) {
420 strncpy(buf + i, result, decimalPoint);
423 strcpy(buf + i, result + decimalPoint);
425 }
else if (result[0] <
'0' || result[0] >
'9') {
426 strcpy(buf + i, result);
428 buf[i++] = result[0];
431 strcpy(buf + i, result + 1);
436 buf[i++] = (decimalPoint >= 0) ?
'+' :
'-';
439 int exponential = decimalPoint - 1;
440 if (exponential < 0) {
441 exponential = exponential * -1;
443 if (exponential >= 100) {
444 buf[i++] =
'0' + exponential / 100;
446 if (exponential >= 10) {
447 buf[i++] =
'0' + (exponential % 100) / 10;
449 buf[i++] =
'0' + exponential % 10;
453 kjs_freedtoa(result);
462 int newLen = l + tLen;
463 if (rep->rc == 1 && newLen <= rep->capacity) {
464 memcpy(rep->dat+l, t.
data(), tLen *
sizeof(
UChar));
470 int newCapacity = (newLen * 3 + 1) / 2;
471 UChar *n = allocateChars(newCapacity);
473 memcpy(n+l, t.
data(), tLen *
sizeof(
UChar));
475 rep = Rep::create(n, newLen);
476 rep->capacity = newCapacity;
491 int neededSize = length + 1;
492 if (neededSize < normalStatBufferSize) {
493 neededSize = normalStatBufferSize;
495 if (neededSize != statBufferSize) {
496 delete [] statBuffer;
497 statBuffer =
new char [neededSize];
498 statBufferSize = neededSize;
502 char *q = statBuffer;
503 const UChar *limit = p + length;
515 void UString::globalClear()
517 delete [] statBuffer;
525 int l = c ? strlen(c) : 0;
527 if (rep->rc == 1 && l <= rep->capacity) {
532 d = allocateChars(l);
533 rep = Rep::create(d, l);
535 for (
int i = 0; i < l; i++)
536 d[i].uc = (
unsigned char)c[i];
577 static int skipInfString(
const char *start)
579 const char *c = start;
580 if (*c ==
'+' || *c ==
'-')
582 if (!strncmp(c,
"Infinity",8))
585 while (*c >=
'0' && *c <=
'9')
587 const char *
const at_dot = c;
590 while (*c >=
'0' && *c <=
'9')
594 if (c - at_dot == 1 && *at_dot ==
'.')
601 if (*c ==
'+' || *c ==
'-')
603 while (*c >=
'0' && *c <=
'9')
608 double UString::toDouble(
bool tolerateTrailingJunk,
bool tolerateEmptyString)
const
618 const char *c =
ascii();
626 return tolerateEmptyString ? 0.0 : NaN;
632 else if (*c ==
'+') {
638 if (*c ==
'0' && (*(c+1) ==
'x' || *(c+1) ==
'X')) {
642 if (*c >=
'0' && *c <=
'9')
643 d = d * 16.0 + *c -
'0';
644 else if ((*c >=
'A' && *c <=
'F') || (*c >=
'a' && *c <=
'f'))
645 d = d * 16.0 + (*c & 0xdf) -
'A' + 10.0;
652 d = kjs_strtod(c, &end);
653 if ((d != 0.0 || end != c) && d != HUGE_VAL && d != -HUGE_VAL) {
658 int count = skipInfString(c);
670 if (!tolerateTrailingJunk && *c !=
'\0')
676 double UString::toDouble(
bool tolerateTrailingJunk)
const
678 return toDouble(tolerateTrailingJunk,
true);
681 double UString::toDouble()
const
683 return toDouble(
false,
true);
688 double d =
toDouble(
false, tolerateEmptyString);
691 if (isNaN(d) || d != static_cast<unsigned long>(d)) {
699 return static_cast<unsigned long>(d);
710 for (
int i = 0; i <
size(); i++)
718 for (
int i = 0; i <
size(); i++)
723 unsigned int UString::toUInt32(
bool *ok)
const
725 double d = toDouble();
728 if (isNaN(d) || d != static_cast<unsigned>(d)) {
736 return static_cast<unsigned>(d);
739 unsigned int UString::toStrictUInt32(
bool *ok)
const
748 const UChar *p = rep->dat;
749 unsigned short c = p->
unicode();
762 if (c < '0' || c >
'9')
764 const unsigned d = c -
'0';
767 if (i > 0xFFFFFFFFU / 10)
772 const unsigned max = 0xFFFFFFFFU - d;
785 c = (++p)->unicode();
793 unsigned i = toStrictUInt32(ok);
794 if (i >= 0xFFFFFFFFU && ok)
810 long fsizeminusone = (fsz - 1) *
sizeof(
UChar);
812 unsigned short fchar = fdata->uc;
814 for (
const UChar *c =
data() + pos; c <= end; c++)
815 if (c->uc == fchar && !memcmp(c + 1, fdata, fsizeminusone))
826 for (
const UChar *c =
data() + pos; c < end; c++)
845 long fsizeminusone = (fsz - 1) *
sizeof(
UChar);
848 if (*c == *fdata && !memcmp(c + 1, fdata + 1, fsizeminusone))
859 if (pos + 1 >=
size())
873 else if (pos >= (
int)
size())
877 if (pos + len >= (
int)
size())
880 UChar *tmp = allocateChars(len);
881 memcpy(tmp,
data()+pos, len *
sizeof(
UChar));
888 void UString::attach(Rep *r)
894 void UString::detach()
898 UChar *n = allocateChars(l);
901 rep = Rep::create(n, l);
905 void UString::release()
912 if (s1.rep->len != s2.rep->len)
919 "KJS warning: comparison between empty and null string\n");
922 return (memcmp(s1.rep->dat, s2.rep->dat,
923 s1.rep->len *
sizeof(
UChar)) == 0);
926 bool KJS::operator==(
const UString& s1,
const char *s2)
934 while (u != uend && *s2) {
935 if (u->uc != (
unsigned char)*s2)
941 return u == uend && *s2 == 0;
946 const int l1 = s1.
size();
947 const int l2 = s2.
size();
948 const int lmin = l1 < l2 ? l1 : l2;
952 while (l < lmin && *c1 == *c2) {
958 return (c1->uc < c2->uc);
965 const int l1 = s1.
size();
966 const int l2 = s2.
size();
967 const int lmin = l1 < l2 ? l1 : l2;
971 while (l < lmin && *c1 == *c2) {
977 return (c1->uc > c2->uc) ? 1 : -1;
982 return (l1 < l2) ? 1 : -1;