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