00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027
00028 #include <stdlib.h>
00029 #include <stdio.h>
00030 #include <ctype.h>
00031 #ifdef HAVE_STRING_H
00032 #include <string.h>
00033 #endif
00034 #ifdef HAVE_STRINGS_H
00035 #include <strings.h>
00036 #endif
00037
00038 #include "ustring.h"
00039 #include "operations.h"
00040 #include "identifier.h"
00041 #include <math.h>
00042 #include "dtoa.h"
00043
00044 namespace KJS {
00045 extern const double NaN;
00046 extern const double Inf;
00047 }
00048
00049 using namespace KJS;
00050
00051 CString::CString(const char *c)
00052 {
00053 length = strlen(c);
00054 data = new char[length+1];
00055 memcpy(data, c, length + 1);
00056 }
00057
00058 CString::CString(const char *c, int len)
00059 {
00060 length = len;
00061 data = new char[len+1];
00062 memcpy(data, c, len);
00063 data[len] = 0;
00064 }
00065
00066 CString::CString(const CString &b)
00067 {
00068 length = b.length;
00069 data = new char[length+1];
00070 memcpy(data, b.data, length + 1);
00071 }
00072
00073 CString::~CString()
00074 {
00075 delete [] data;
00076 }
00077
00078 CString &CString::append(const CString &t)
00079 {
00080 char *n = new char[length + t.length + 1];
00081 if (length)
00082 memcpy(n, data, length);
00083 if (t.length)
00084 memcpy(n+length, t.data, t.length);
00085 length += t.length;
00086 n[length] = 0;
00087
00088 delete [] data;
00089 data = n;
00090
00091 return *this;
00092 }
00093
00094 CString &CString::operator=(const char *c)
00095 {
00096 delete [] data;
00097 length = strlen(c);
00098 data = new char[length+1];
00099 memcpy(data, c, length + 1);
00100
00101 return *this;
00102 }
00103
00104 CString &CString::operator=(const CString &str)
00105 {
00106 if (this == &str)
00107 return *this;
00108
00109 delete [] data;
00110 length = str.length;
00111 if (str.data) {
00112 data = new char[length + 1];
00113 memcpy(data, str.data, length + 1);
00114 }
00115 else
00116 data = 0;
00117
00118 return *this;
00119 }
00120
00121 bool KJS::operator==(const KJS::CString& c1, const KJS::CString& c2)
00122 {
00123 int len = c1.size();
00124 return len == c2.size() && (len == 0 || memcmp(c1.c_str(), c2.c_str(), len) == 0);
00125 }
00126
00127 UChar UChar::null((char)0);
00128 UString::Rep UString::Rep::null = { 0, 0, 0, 1, 1 };
00129 UString::Rep UString::Rep::empty = { 0, 0, 0, 1, 1 };
00130 UString UString::null;
00131 static const int normalStatBufferSize = 4096;
00132 static char *statBuffer = 0;
00133 static int statBufferSize = 0;
00134
00135 UChar UChar::toLower() const
00136 {
00137
00138 if (uc >= 256)
00139 return *this;
00140
00141
00142 return static_cast<unsigned char>( ( ( uc >= 'A' ) && ( uc <= 'Z' ) ) ? ( (int)uc + 'a' - 'A' ) : uc );
00143 }
00144
00145 UChar UChar::toUpper() const
00146 {
00147 if (uc >= 256)
00148 return *this;
00149
00150
00151 return static_cast<unsigned char>( ( ( uc >= 'a' ) && ( uc <= 'z' ) ) ? ( (int)uc + 'A' - 'a' ) : uc );
00152 }
00153
00154 UCharReference& UCharReference::operator=(UChar c)
00155 {
00156 str->detach();
00157 if (offset < str->rep->len)
00158 *(str->rep->dat + offset) = c;
00159
00160 return *this;
00161 }
00162
00163 UChar& UCharReference::ref() const
00164 {
00165 if (offset < str->rep->len)
00166 return *(str->rep->dat + offset);
00167 else
00168 return UChar::null;
00169 }
00170
00171
00172 static inline UChar* allocateChars(int s)
00173 {
00174
00175 return reinterpret_cast<UChar*>(new short[s]);
00176 }
00177
00178 UString::Rep *UString::Rep::create(UChar *d, int l)
00179 {
00180 Rep *r = new Rep;
00181 r->dat = d;
00182 r->len = l;
00183 r->capacity = l;
00184 r->rc = 1;
00185 r->_hash = 0;
00186 return r;
00187 }
00188
00189 void UString::Rep::destroy()
00190 {
00191 if (capacity == capacityForIdentifier)
00192 Identifier::remove(this);
00193 delete [] dat;
00194 delete this;
00195 }
00196
00197
00198
00199 const unsigned PHI = 0x9e3779b9U;
00200
00201
00202
00203
00204 unsigned UString::Rep::computeHash(const UChar *s, int length)
00205 {
00206 int prefixLength = length < 8 ? length : 8;
00207 int suffixPosition = length < 16 ? 8 : length - 8;
00208
00209 unsigned h = PHI;
00210 h += length;
00211 h += (h << 10);
00212 h ^= (h << 6);
00213
00214 for (int i = 0; i < prefixLength; i++) {
00215 h += s[i].uc;
00216 h += (h << 10);
00217 h ^= (h << 6);
00218 }
00219 for (int i = suffixPosition; i < length; i++){
00220 h += s[i].uc;
00221 h += (h << 10);
00222 h ^= (h << 6);
00223 }
00224
00225 h += (h << 3);
00226 h ^= (h >> 11);
00227 h += (h << 15);
00228
00229 if (h == 0)
00230 h = 0x80000000;
00231
00232 return h;
00233 }
00234
00235
00236
00237
00238 unsigned UString::Rep::computeHash(const char *s)
00239 {
00240 int length = strlen(s);
00241 int prefixLength = length < 8 ? length : 8;
00242 int suffixPosition = length < 16 ? 8 : length - 8;
00243
00244 unsigned h = PHI;
00245 h += length;
00246 h += (h << 10);
00247 h ^= (h << 6);
00248
00249 for (int i = 0; i < prefixLength; i++) {
00250 h += (unsigned char)s[i];
00251 h += (h << 10);
00252 h ^= (h << 6);
00253 }
00254 for (int i = suffixPosition; i < length; i++) {
00255 h += (unsigned char)s[i];
00256 h += (h << 10);
00257 h ^= (h << 6);
00258 }
00259
00260 h += (h << 3);
00261 h ^= (h >> 11);
00262 h += (h << 15);
00263
00264 if (h == 0)
00265 h = 0x80000000;
00266
00267 return h;
00268 }
00269
00270 UString::UString()
00271 {
00272 null.rep = &Rep::null;
00273 attach(&Rep::null);
00274 }
00275
00276 UString::UString(char c)
00277 {
00278 UChar *d = allocateChars(1);
00279 d[0] = c;
00280 rep = Rep::create(d, 1);
00281 }
00282
00283 UString::UString(const char *c)
00284 {
00285 if (!c) {
00286 attach(&Rep::null);
00287 return;
00288 }
00289 int length = strlen(c);
00290 if (length == 0) {
00291 attach(&Rep::empty);
00292 return;
00293 }
00294 UChar *d = new UChar[length];
00295 for (int i = 0; i < length; i++)
00296 d[i].uc = (unsigned char)c[i];
00297 rep = Rep::create(d, length);
00298 }
00299
00300 UString::UString(const UChar *c, int length)
00301 {
00302 if (length == 0) {
00303 attach(&Rep::empty);
00304 return;
00305 }
00306 UChar *d = allocateChars(length);
00307 memcpy(d, c, length * sizeof(UChar));
00308 rep = Rep::create(d, length);
00309 }
00310
00311 UString::UString(UChar *c, int length, bool copy)
00312 {
00313 if (length == 0) {
00314 attach(&Rep::empty);
00315 return;
00316 }
00317 UChar *d;
00318 if (copy) {
00319 d = allocateChars(length);
00320 memcpy(d, c, length * sizeof(UChar));
00321 } else
00322 d = c;
00323 rep = Rep::create(d, length);
00324 }
00325
00326 UString::UString(const UString &a, const UString &b)
00327 {
00328 int aSize = a.size();
00329 int bSize = b.size();
00330 int length = aSize + bSize;
00331 if (length == 0) {
00332 attach(&Rep::empty);
00333 return;
00334 }
00335 UChar *d = allocateChars(length);
00336 memcpy(d, a.data(), aSize * sizeof(UChar));
00337 memcpy(d + aSize, b.data(), bSize * sizeof(UChar));
00338 rep = Rep::create(d, length);
00339 }
00340
00341 UString UString::from(int i)
00342 {
00343 return from((long)i);
00344 }
00345
00346 UString UString::from(unsigned int u)
00347 {
00348 UChar buf[20];
00349 UChar *end = buf + 20;
00350 UChar *p = end;
00351
00352 if (u == 0) {
00353 *--p = '0';
00354 } else {
00355 while (u) {
00356 *--p = (unsigned short)((u % 10) + '0');
00357 u /= 10;
00358 }
00359 }
00360
00361 return UString(p, end - p);
00362 }
00363
00364 UString UString::from(long l)
00365 {
00366 UChar buf[20];
00367 UChar *end = buf + 20;
00368 UChar *p = end;
00369
00370 if (l == 0) {
00371 *--p = '0';
00372 } else {
00373 bool negative = false;
00374 if (l < 0) {
00375 negative = true;
00376 l = -l;
00377 }
00378 while (l) {
00379 *--p = (unsigned short)((l % 10) + '0');
00380 l /= 10;
00381 }
00382 if (negative) {
00383 *--p = '-';
00384 }
00385 }
00386
00387 return UString(p, end - p);
00388 }
00389
00390 UString UString::from(double d)
00391 {
00392 char buf[80];
00393 int decimalPoint;
00394 int sign;
00395
00396 char *result = kjs_dtoa(d, 0, 0, &decimalPoint, &sign, NULL);
00397 int length = strlen(result);
00398
00399 int i = 0;
00400 if (sign) {
00401 buf[i++] = '-';
00402 }
00403
00404 if (decimalPoint <= 0 && decimalPoint > -6) {
00405 buf[i++] = '0';
00406 buf[i++] = '.';
00407 for (int j = decimalPoint; j < 0; j++) {
00408 buf[i++] = '0';
00409 }
00410 strcpy(buf + i, result);
00411 } else if (decimalPoint <= 21 && decimalPoint > 0) {
00412 if (length <= decimalPoint) {
00413 strcpy(buf + i, result);
00414 i += length;
00415 for (int j = 0; j < decimalPoint - length; j++) {
00416 buf[i++] = '0';
00417 }
00418 buf[i] = '\0';
00419 } else {
00420 strncpy(buf + i, result, decimalPoint);
00421 i += decimalPoint;
00422 buf[i++] = '.';
00423 strcpy(buf + i, result + decimalPoint);
00424 }
00425 } else if (result[0] < '0' || result[0] > '9') {
00426 strcpy(buf + i, result);
00427 } else {
00428 buf[i++] = result[0];
00429 if (length > 1) {
00430 buf[i++] = '.';
00431 strcpy(buf + i, result + 1);
00432 i += length - 1;
00433 }
00434
00435 buf[i++] = 'e';
00436 buf[i++] = (decimalPoint >= 0) ? '+' : '-';
00437
00438
00439 int exponential = decimalPoint - 1;
00440 if (exponential < 0) {
00441 exponential = exponential * -1;
00442 }
00443 if (exponential >= 100) {
00444 buf[i++] = '0' + exponential / 100;
00445 }
00446 if (exponential >= 10) {
00447 buf[i++] = '0' + (exponential % 100) / 10;
00448 }
00449 buf[i++] = '0' + exponential % 10;
00450 buf[i++] = '\0';
00451 }
00452
00453 kjs_freedtoa(result);
00454
00455 return UString(buf);
00456 }
00457
00458 UString &UString::append(const UString &t)
00459 {
00460 int l = size();
00461 int tLen = t.size();
00462 int newLen = l + tLen;
00463 if (rep->rc == 1 && newLen <= rep->capacity) {
00464 memcpy(rep->dat+l, t.data(), tLen * sizeof(UChar));
00465 rep->len = newLen;
00466 rep->_hash = 0;
00467 return *this;
00468 }
00469
00470 int newCapacity = (newLen * 3 + 1) / 2;
00471 UChar *n = allocateChars(newCapacity);
00472 memcpy(n, data(), l * sizeof(UChar));
00473 memcpy(n+l, t.data(), tLen * sizeof(UChar));
00474 release();
00475 rep = Rep::create(n, newLen);
00476 rep->capacity = newCapacity;
00477
00478 return *this;
00479 }
00480
00481 CString UString::cstring() const
00482 {
00483 return ascii();
00484 }
00485
00486 char *UString::ascii() const
00487 {
00488
00489
00490 int length = size();
00491 int neededSize = length + 1;
00492 if (neededSize < normalStatBufferSize) {
00493 neededSize = normalStatBufferSize;
00494 }
00495 if (neededSize != statBufferSize) {
00496 delete [] statBuffer;
00497 statBuffer = new char [neededSize];
00498 statBufferSize = neededSize;
00499 }
00500
00501 const UChar *p = data();
00502 char *q = statBuffer;
00503 const UChar *limit = p + length;
00504 while (p != limit) {
00505 *q = p->uc;
00506 ++p;
00507 ++q;
00508 }
00509 *q = '\0';
00510
00511 return statBuffer;
00512 }
00513
00514 #ifdef KJS_DEBUG_MEM
00515 void UString::globalClear()
00516 {
00517 delete [] statBuffer;
00518 statBuffer = 0;
00519 statBufferSize = 0;
00520 }
00521 #endif
00522
00523 UString &UString::operator=(const char *c)
00524 {
00525 int l = c ? strlen(c) : 0;
00526 UChar *d;
00527 if (rep->rc == 1 && l <= rep->capacity) {
00528 d = rep->dat;
00529 rep->_hash = 0;
00530 } else {
00531 release();
00532 d = allocateChars(l);
00533 rep = Rep::create(d, l);
00534 }
00535 for (int i = 0; i < l; i++)
00536 d[i].uc = (unsigned char)c[i];
00537
00538 return *this;
00539 }
00540
00541 UString &UString::operator=(const UString &str)
00542 {
00543 str.rep->ref();
00544 release();
00545 rep = str.rep;
00546
00547 return *this;
00548 }
00549
00550 bool UString::is8Bit() const
00551 {
00552 const UChar *u = data();
00553 const UChar *limit = u + size();
00554 while (u < limit) {
00555 if (u->uc > 0xFF)
00556 return false;
00557 ++u;
00558 }
00559
00560 return true;
00561 }
00562
00563 UChar UString::operator[](int pos) const
00564 {
00565 if (pos >= size())
00566 return UChar::null;
00567
00568 return ((UChar *)data())[pos];
00569 }
00570
00571 UCharReference UString::operator[](int pos)
00572 {
00573
00574 return UCharReference(this, pos);
00575 }
00576
00577 static int skipInfString(const char *start)
00578 {
00579 const char *c = start;
00580 if (*c == '+' || *c == '-')
00581 c++;
00582 if (!strncmp(c,"Infinity",8))
00583 return c+8-start;
00584
00585 while (*c >= '0' && *c <= '9')
00586 c++;
00587 const char * const at_dot = c;
00588 if (*c == '.')
00589 c++;
00590 while (*c >= '0' && *c <= '9')
00591 c++;
00592
00593
00594 if (c - at_dot == 1 && *at_dot == '.')
00595 return at_dot-start;
00596
00597 if (*c != 'e')
00598 return c-start;
00599
00600 c++;
00601 if (*c == '+' || *c == '-')
00602 c++;
00603 while (*c >= '0' && *c <= '9')
00604 c++;
00605 return c-start;
00606 }
00607
00608 double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const
00609 {
00610 double d;
00611 double sign = 1;
00612
00613
00614
00615 if (!is8Bit())
00616 return NaN;
00617
00618 const char *c = ascii();
00619
00620
00621 while (isspace(*c))
00622 c++;
00623
00624
00625 if (*c == '\0')
00626 return tolerateEmptyString ? 0.0 : NaN;
00627
00628 if (*c == '-') {
00629 sign = -1;
00630 c++;
00631 }
00632 else if (*c == '+') {
00633 sign = 1;
00634 c++;
00635 }
00636
00637
00638 if (*c == '0' && (*(c+1) == 'x' || *(c+1) == 'X')) {
00639 c++;
00640 d = 0.0;
00641 while (*(++c)) {
00642 if (*c >= '0' && *c <= '9')
00643 d = d * 16.0 + *c - '0';
00644 else if ((*c >= 'A' && *c <= 'F') || (*c >= 'a' && *c <= 'f'))
00645 d = d * 16.0 + (*c & 0xdf) - 'A' + 10.0;
00646 else
00647 break;
00648 }
00649 } else {
00650
00651 char *end;
00652 d = kjs_strtod(c, &end);
00653 if ((d != 0.0 || end != c) && d != HUGE_VAL && d != -HUGE_VAL) {
00654 c = end;
00655 } else {
00656
00657
00658 int count = skipInfString(c);
00659 if (count == 0)
00660 return NaN;
00661 d = Inf;
00662 c += count;
00663 }
00664 }
00665
00666
00667 while (isspace(*c))
00668 c++;
00669
00670 if (!tolerateTrailingJunk && *c != '\0')
00671 return NaN;
00672
00673 return d*sign;
00674 }
00675
00676 double UString::toDouble(bool tolerateTrailingJunk) const
00677 {
00678 return toDouble(tolerateTrailingJunk, true);
00679 }
00680
00681 double UString::toDouble() const
00682 {
00683 return toDouble(false, true);
00684 }
00685
00686 unsigned long UString::toULong(bool *ok, bool tolerateEmptyString) const
00687 {
00688 double d = toDouble(false, tolerateEmptyString);
00689 bool b = true;
00690
00691 if (isNaN(d) || d != static_cast<unsigned long>(d)) {
00692 b = false;
00693 d = 0;
00694 }
00695
00696 if (ok)
00697 *ok = b;
00698
00699 return static_cast<unsigned long>(d);
00700 }
00701
00702 unsigned long UString::toULong(bool *ok) const
00703 {
00704 return toULong(ok, true);
00705 }
00706
00707 UString UString::toLower() const
00708 {
00709 UString u = *this;
00710 for (int i = 0; i < size(); i++)
00711 u[i] = u[i].toLower();
00712 return u;
00713 }
00714
00715 UString UString::toUpper() const
00716 {
00717 UString u = *this;
00718 for (int i = 0; i < size(); i++)
00719 u[i] = u[i].toUpper();
00720 return u;
00721 }
00722
00723 unsigned int UString::toUInt32(bool *ok) const
00724 {
00725 double d = toDouble();
00726 bool b = true;
00727
00728 if (isNaN(d) || d != static_cast<unsigned>(d)) {
00729 b = false;
00730 d = 0;
00731 }
00732
00733 if (ok)
00734 *ok = b;
00735
00736 return static_cast<unsigned>(d);
00737 }
00738
00739 unsigned int UString::toStrictUInt32(bool *ok) const
00740 {
00741 if (ok)
00742 *ok = false;
00743
00744
00745 int len = rep->len;
00746 if (len == 0)
00747 return 0;
00748 const UChar *p = rep->dat;
00749 unsigned short c = p->unicode();
00750
00751
00752 if (c == '0') {
00753 if (len == 1 && ok)
00754 *ok = true;
00755 return 0;
00756 }
00757
00758
00759 unsigned int i = 0;
00760 while (1) {
00761
00762 if (c < '0' || c > '9')
00763 return 0;
00764 const unsigned d = c - '0';
00765
00766
00767 if (i > 0xFFFFFFFFU / 10)
00768 return 0;
00769 i *= 10;
00770
00771
00772 const unsigned max = 0xFFFFFFFFU - d;
00773 if (i > max)
00774 return 0;
00775 i += d;
00776
00777
00778 if (--len == 0) {
00779 if (ok)
00780 *ok = true;
00781 return i;
00782 }
00783
00784
00785 c = (++p)->unicode();
00786 }
00787 }
00788
00789
00790
00791 unsigned UString::toArrayIndex(bool *ok) const
00792 {
00793 unsigned i = toStrictUInt32(ok);
00794 if (i >= 0xFFFFFFFFU && ok)
00795 *ok = false;
00796 return i;
00797 }
00798
00799 int UString::find(const UString &f, int pos) const
00800 {
00801 int sz = size();
00802 int fsz = f.size();
00803 if (sz < fsz)
00804 return -1;
00805 if (pos < 0)
00806 pos = 0;
00807 if (fsz == 0)
00808 return pos;
00809 const UChar *end = data() + sz - fsz;
00810 long fsizeminusone = (fsz - 1) * sizeof(UChar);
00811 const UChar *fdata = f.data();
00812 unsigned short fchar = fdata->uc;
00813 ++fdata;
00814 for (const UChar *c = data() + pos; c <= end; c++)
00815 if (c->uc == fchar && !memcmp(c + 1, fdata, fsizeminusone))
00816 return (c-data());
00817
00818 return -1;
00819 }
00820
00821 int UString::find(UChar ch, int pos) const
00822 {
00823 if (pos < 0)
00824 pos = 0;
00825 const UChar *end = data() + size();
00826 for (const UChar *c = data() + pos; c < end; c++)
00827 if (*c == ch)
00828 return (c-data());
00829
00830 return -1;
00831 }
00832
00833 int UString::rfind(const UString &f, int pos) const
00834 {
00835 int sz = size();
00836 int fsz = f.size();
00837 if (sz < fsz)
00838 return -1;
00839 if (pos < 0)
00840 pos = 0;
00841 if (pos > sz - fsz)
00842 pos = sz - fsz;
00843 if (fsz == 0)
00844 return pos;
00845 long fsizeminusone = (fsz - 1) * sizeof(UChar);
00846 const UChar *fdata = f.data();
00847 for (const UChar *c = data() + pos; c >= data(); c--) {
00848 if (*c == *fdata && !memcmp(c + 1, fdata + 1, fsizeminusone))
00849 return (c-data());
00850 }
00851
00852 return -1;
00853 }
00854
00855 int UString::rfind(UChar ch, int pos) const
00856 {
00857 if (isEmpty())
00858 return -1;
00859 if (pos + 1 >= size())
00860 pos = size() - 1;
00861 for (const UChar *c = data() + pos; c >= data(); c--) {
00862 if (*c == ch)
00863 return (c-data());
00864 }
00865
00866 return -1;
00867 }
00868
00869 UString UString::substr(int pos, int len) const
00870 {
00871 if (pos < 0)
00872 pos = 0;
00873 else if (pos >= (int) size())
00874 pos = size();
00875 if (len < 0)
00876 len = size();
00877 if (pos + len >= (int) size())
00878 len = size() - pos;
00879
00880 UChar *tmp = allocateChars(len);
00881 memcpy(tmp, data()+pos, len * sizeof(UChar));
00882 UString result(tmp, len);
00883 delete [] tmp;
00884
00885 return result;
00886 }
00887
00888 void UString::attach(Rep *r)
00889 {
00890 rep = r;
00891 rep->ref();
00892 }
00893
00894 void UString::detach()
00895 {
00896 if (rep->rc > 1) {
00897 int l = size();
00898 UChar *n = allocateChars(l);
00899 memcpy(n, data(), l * sizeof(UChar));
00900 release();
00901 rep = Rep::create(n, l);
00902 }
00903 }
00904
00905 void UString::release()
00906 {
00907 rep->deref();
00908 }
00909
00910 bool KJS::operator==(const UString& s1, const UString& s2)
00911 {
00912 if (s1.rep->len != s2.rep->len)
00913 return false;
00914
00915 #ifndef NDEBUG
00916 if ((s1.isNull() && s2.isEmpty() && !s2.isNull()) ||
00917 (s2.isNull() && s1.isEmpty() && !s1.isNull()))
00918 fprintf(stderr,
00919 "KJS warning: comparison between empty and null string\n");
00920 #endif
00921
00922 return (memcmp(s1.rep->dat, s2.rep->dat,
00923 s1.rep->len * sizeof(UChar)) == 0);
00924 }
00925
00926 bool KJS::operator==(const UString& s1, const char *s2)
00927 {
00928 if (s2 == 0) {
00929 return s1.isEmpty();
00930 }
00931
00932 const UChar *u = s1.data();
00933 const UChar *uend = u + s1.size();
00934 while (u != uend && *s2) {
00935 if (u->uc != (unsigned char)*s2)
00936 return false;
00937 s2++;
00938 u++;
00939 }
00940
00941 return u == uend && *s2 == 0;
00942 }
00943
00944 bool KJS::operator<(const UString& s1, const UString& s2)
00945 {
00946 const int l1 = s1.size();
00947 const int l2 = s2.size();
00948 const int lmin = l1 < l2 ? l1 : l2;
00949 const UChar *c1 = s1.data();
00950 const UChar *c2 = s2.data();
00951 int l = 0;
00952 while (l < lmin && *c1 == *c2) {
00953 c1++;
00954 c2++;
00955 l++;
00956 }
00957 if (l < lmin)
00958 return (c1->uc < c2->uc);
00959
00960 return (l1 < l2);
00961 }
00962
00963 int KJS::compare(const UString& s1, const UString& s2)
00964 {
00965 const int l1 = s1.size();
00966 const int l2 = s2.size();
00967 const int lmin = l1 < l2 ? l1 : l2;
00968 const UChar *c1 = s1.data();
00969 const UChar *c2 = s2.data();
00970 int l = 0;
00971 while (l < lmin && *c1 == *c2) {
00972 c1++;
00973 c2++;
00974 l++;
00975 }
00976 if (l < lmin)
00977 return (c1->uc > c2->uc) ? 1 : -1;
00978
00979 if (l1 == l2) {
00980 return 0;
00981 }
00982 return (l1 < l2) ? 1 : -1;
00983 }