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