38 #include "operations.h"
39 #include "identifier.h"
44 extern const double NaN;
45 extern const double Inf;
50 CString::CString(
const char *c)
53 data =
new char[length+1];
54 memcpy(data, c, length + 1);
57 CString::CString(
const char *c,
int len)
60 data =
new char[len+1];
65 CString::CString(
const CString &b)
68 data =
new char[length+1];
69 memcpy(data, b.data, length + 1);
79 char *n =
new char[length + t.length + 1];
81 memcpy(n, data, length);
83 memcpy(n+length, t.data, t.length);
93 CString &CString::operator=(
const char *c)
97 data =
new char[length+1];
98 memcpy(data, c, length + 1);
111 data =
new char[length + 1];
112 memcpy(data, str.data, length + 1);
123 return len == c2.size() && (len == 0 || memcmp(c1.c_str(), c2.c_str(), len) == 0);
127 UString::Rep UString::Rep::null = { 0, 0, 0, 1, 1 };
128 UString::Rep UString::Rep::empty = { 0, 0, 0, 1, 1 };
130 static const int normalStatBufferSize = 4096;
131 static char *statBuffer = 0;
132 static int statBufferSize = 0;
141 return static_cast<unsigned char>( ( ( uc >=
'A' ) && ( uc <=
'Z' ) ) ? ( (
int)uc +
'a' -
'A' ) : uc );
150 return static_cast<unsigned char>( ( ( uc >=
'a' ) && ( uc <=
'z' ) ) ? ( (
int)uc +
'A' -
'a' ) : uc );
156 if (offset < str->rep->len)
157 *(str->rep->dat + offset) = c;
162 UChar& UCharReference::ref()
const
164 if (offset < str->rep->len)
165 return *(str->rep->dat + offset);
171 static inline UChar* allocateChars(
int s)
174 return reinterpret_cast<UChar*
>(
new short[s]);
177 UString::Rep *UString::Rep::create(
UChar *d,
int l)
188 void UString::Rep::destroy()
190 if (capacity == capacityForIdentifier)
191 Identifier::remove(
this);
198 const unsigned PHI = 0x9e3779b9U;
203 unsigned UString::Rep::computeHash(
const UChar *s,
int length)
205 int prefixLength = length < 8 ? length : 8;
206 int suffixPosition = length < 16 ? 8 : length - 8;
213 for (
int i = 0; i < prefixLength; i++) {
218 for (
int i = suffixPosition; i < length; i++){
237 unsigned UString::Rep::computeHash(
const char *s)
239 int length = strlen(s);
240 int prefixLength = length < 8 ? length : 8;
241 int suffixPosition = length < 16 ? 8 : length - 8;
248 for (
int i = 0; i < prefixLength; i++) {
249 h += (
unsigned char)s[i];
253 for (
int i = suffixPosition; i < length; i++) {
254 h += (
unsigned char)s[i];
271 null.rep = &Rep::null;
277 UChar *d = allocateChars(1);
279 rep = Rep::create(d, 1);
288 int length = strlen(c);
294 for (
int i = 0; i < length; i++)
295 d[i].uc = (
unsigned char)c[i];
296 rep = Rep::create(d, length);
305 UChar *d = allocateChars(length);
306 memcpy(d, c, length *
sizeof(
UChar));
307 rep = Rep::create(d, length);
318 d = allocateChars(length);
319 memcpy(d, c, length *
sizeof(
UChar));
322 rep = Rep::create(d, length);
327 int aSize = a.
size();
328 int bSize = b.
size();
329 int length = aSize + bSize;
334 UChar *d = allocateChars(length);
335 memcpy(d, a.
data(), aSize *
sizeof(
UChar));
336 memcpy(d + aSize, b.
data(), bSize *
sizeof(
UChar));
337 rep = Rep::create(d, length);
342 return from((
long)i);
348 UChar *end = buf + 20;
355 *--p = (
unsigned short)((u % 10) +
'0');
366 UChar *end = buf + 20;
372 bool negative =
false;
378 *--p = (
unsigned short)((l % 10) +
'0');
395 char *result = kjs_dtoa(d, 0, 0, &decimalPoint, &sign, NULL);
396 int length = strlen(result);
403 if (decimalPoint <= 0 && decimalPoint > -6) {
406 for (
int j = decimalPoint; j < 0; j++) {
409 strcpy(buf + i, result);
410 }
else if (decimalPoint <= 21 && decimalPoint > 0) {
411 if (length <= decimalPoint) {
412 strcpy(buf + i, result);
414 for (
int j = 0; j < decimalPoint - length; j++) {
419 strncpy(buf + i, result, decimalPoint);
422 strcpy(buf + i, result + decimalPoint);
424 }
else if (result[0] <
'0' || result[0] >
'9') {
425 strcpy(buf + i, result);
427 buf[i++] = result[0];
430 strcpy(buf + i, result + 1);
435 buf[i++] = (decimalPoint >= 0) ?
'+' :
'-';
438 int exponential = decimalPoint - 1;
439 if (exponential < 0) {
440 exponential = exponential * -1;
442 if (exponential >= 100) {
443 buf[i++] =
'0' + exponential / 100;
445 if (exponential >= 10) {
446 buf[i++] =
'0' + (exponential % 100) / 10;
448 buf[i++] =
'0' + exponential % 10;
452 kjs_freedtoa(result);
461 int newLen = l + tLen;
462 if (rep->rc == 1 && newLen <= rep->capacity) {
463 memcpy(rep->dat+l, t.
data(), tLen *
sizeof(
UChar));
469 int newCapacity = (newLen * 3 + 1) / 2;
470 UChar *n = allocateChars(newCapacity);
472 memcpy(n+l, t.
data(), tLen *
sizeof(
UChar));
474 rep = Rep::create(n, newLen);
475 rep->capacity = newCapacity;
490 int neededSize = length + 1;
491 if (neededSize < normalStatBufferSize) {
492 neededSize = normalStatBufferSize;
494 if (neededSize != statBufferSize) {
495 delete [] statBuffer;
496 statBuffer =
new char [neededSize];
497 statBufferSize = neededSize;
501 char *q = statBuffer;
502 const UChar *limit = p + length;
514 void UString::globalClear()
516 delete [] statBuffer;
524 int l = c ? strlen(c) : 0;
526 if (rep->rc == 1 && l <= rep->capacity) {
531 d = allocateChars(l);
532 rep = Rep::create(d, l);
534 for (
int i = 0; i < l; i++)
535 d[i].uc = (
unsigned char)c[i];
576 static int skipInfString(
const char *start)
578 const char *c = start;
579 if (*c ==
'+' || *c ==
'-')
581 if (!strncmp(c,
"Infinity",8))
584 while (*c >=
'0' && *c <=
'9')
586 const char *
const at_dot = c;
589 while (*c >=
'0' && *c <=
'9')
593 if (c - at_dot == 1 && *at_dot ==
'.')
600 if (*c ==
'+' || *c ==
'-')
602 while (*c >=
'0' && *c <=
'9')
607 double UString::toDouble(
bool tolerateTrailingJunk,
bool tolerateEmptyString)
const
617 const char *c =
ascii();
625 return tolerateEmptyString ? 0.0 : NaN;
631 else if (*c ==
'+') {
637 if (*c ==
'0' && (*(c+1) ==
'x' || *(c+1) ==
'X')) {
641 if (*c >=
'0' && *c <=
'9')
642 d = d * 16.0 + *c -
'0';
643 else if ((*c >=
'A' && *c <=
'F') || (*c >=
'a' && *c <=
'f'))
644 d = d * 16.0 + (*c & 0xdf) -
'A' + 10.0;
651 d = kjs_strtod(c, &end);
652 if ((d != 0.0 || end != c) && d != HUGE_VAL && d != -HUGE_VAL) {
657 int count = skipInfString(c);
669 if (!tolerateTrailingJunk && *c !=
'\0')
675 double UString::toDouble(
bool tolerateTrailingJunk)
const
677 return toDouble(tolerateTrailingJunk,
true);
680 double UString::toDouble()
const
682 return toDouble(
false,
true);
687 double d =
toDouble(
false, tolerateEmptyString);
690 if (isNaN(d) || d !=
static_cast<unsigned long>(d)) {
698 return static_cast<unsigned long>(d);
709 for (
int i = 0; i <
size(); i++)
717 for (
int i = 0; i <
size(); i++)
722 unsigned int UString::toUInt32(
bool *ok)
const
724 double d = toDouble();
727 if (isNaN(d) || d !=
static_cast<unsigned>(d)) {
735 return static_cast<unsigned>(d);
738 unsigned int UString::toStrictUInt32(
bool *ok)
const
747 const UChar *p = rep->dat;
748 unsigned short c = p->
unicode();
761 if (c < '0' || c >
'9')
763 const unsigned d = c -
'0';
766 if (i > 0xFFFFFFFFU / 10)
771 const unsigned max = 0xFFFFFFFFU - d;
784 c = (++p)->unicode();
792 unsigned i = toStrictUInt32(ok);
793 if (i >= 0xFFFFFFFFU && ok)
809 long fsizeminusone = (fsz - 1) *
sizeof(
UChar);
811 unsigned short fchar = fdata->uc;
813 for (
const UChar *c =
data() + pos; c <= end; c++)
814 if (c->uc == fchar && !memcmp(c + 1, fdata, fsizeminusone))
825 for (
const UChar *c =
data() + pos; c < end; c++)
844 long fsizeminusone = (fsz - 1) *
sizeof(
UChar);
847 if (*c == *fdata && !memcmp(c + 1, fdata + 1, fsizeminusone))
858 if (pos + 1 >=
size())
872 else if (pos >= (
int)
size())
876 if (pos + len >= (
int)
size())
879 UChar *tmp = allocateChars(len);
880 memcpy(tmp,
data()+pos, len *
sizeof(
UChar));
887 void UString::attach(Rep *r)
893 void UString::detach()
897 UChar *n = allocateChars(l);
900 rep = Rep::create(n, l);
904 void UString::release()
911 if (s1.rep->len != s2.rep->len)
918 "KJS warning: comparison between empty and null string\n");
921 return (memcmp(s1.rep->dat, s2.rep->dat,
922 s1.rep->len *
sizeof(
UChar)) == 0);
925 bool KJS::operator==(
const UString& s1,
const char *s2)
933 while (u != uend && *s2) {
934 if (u->uc != (
unsigned char)*s2)
940 return u == uend && *s2 == 0;
945 const int l1 = s1.
size();
946 const int l2 = s2.
size();
947 const int lmin = l1 < l2 ? l1 : l2;
951 while (l < lmin && *c1 == *c2) {
957 return (c1->uc < c2->uc);
964 const int l1 = s1.
size();
965 const int l2 = s2.
size();
966 const int lmin = l1 < l2 ? l1 : l2;
970 while (l < lmin && *c1 == *c2) {
976 return (c1->uc > c2->uc) ? 1 : -1;
981 return (l1 < l2) ? 1 : -1;
8 bit char based string class
Dynamic reference to a string character.
UCharReference & operator=(UChar c)
Set the referenced character to c.
unsigned long toULong(bool *ok, bool tolerateEmptyString) const
Attempts an conversion to an unsigned long integer.
unsigned toArrayIndex(bool *ok=0) const
Attempts an conversion to an array index.
bool is8Bit() const
Use this if you want to make sure that this string is a plain ASCII string.
UString toLower() const
Returns this string converted to lower case characters.
double toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const
Attempts an conversion to a number.
int find(const UString &f, int pos=0) const
int rfind(const UString &f, int pos) const
UString()
Constructs a null string.
UString & operator=(const char *c)
Assignment operator.
char * ascii() const
Convert the Unicode string to plain ASCII chars chopping of any higher bytes.
const UChar * data() const
static UString null
Static instance of a null string.
UString substr(int pos=0, int len=-1) const
UString toUpper() const
Returns this string converted to upper case characters.
UChar operator[](int pos) const
Const character at specified position.
UString & append(const UString &)
Append another string.
static UString from(int i)
Constructs a string from an int.
static UChar null
A static instance of UChar(0).
unsigned short unicode() const