kjs Library API Documentation

ustring.cpp

00001 // -*- c-basic-offset: 2 -*- 00002 /* 00003 * This file is part of the KDE libraries 00004 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) 00005 * Copyright (C) 2003 Apple Computer, Inc. 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Library General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Library General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Library General Public License 00018 * along with this library; see the file COPYING.LIB. If not, write to 00019 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00020 * Boston, MA 02111-1307, USA. 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 // ### properly support unicode tolower 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 /* TODO: lengthen string ? */ 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 // return an uninitialized UChar array of size s 00166 static inline UChar* allocateChars(int s) 00167 { 00168 // work around default UChar constructor code 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 // Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's 00192 // or anything like that. 00193 const unsigned PHI = 0x9e3779b9U; 00194 00195 // This hash algorithm comes from: 00196 // http://burtleburtle.net/bob/hash/hashfaq.html 00197 // http://burtleburtle.net/bob/hash/doobs.html 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 // This hash algorithm comes from: 00230 // http://burtleburtle.net/bob/hash/hashfaq.html 00231 // http://burtleburtle.net/bob/hash/doobs.html 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 = 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 // decimalPoint can't be more than 3 digits decimal given the 00432 // nature of float representation 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 // Never make the buffer smaller than normalStatBufferSize. 00483 // Thus we almost never need to reallocate. 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 = 0L; 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 = 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 /* TODO: boundary check */ 00568 return UCharReference(this, pos); 00569 } 00570 00571 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 if (*c == '.') 00582 c++; 00583 while (*c >= '0' && *c <= '9') 00584 c++; 00585 00586 if (*c != 'e') 00587 return c-start; 00588 00589 c++; 00590 if (*c == '+' || *c == '-') 00591 c++; 00592 while (*c >= '0' && *c <= '9') 00593 c++; 00594 return c-start; 00595 } 00596 00597 double UString::toDouble( bool tolerateTrailingJunk, bool tolerateEmptyString ) const 00598 { 00599 double d; 00600 double sign = 1; 00601 00602 // FIXME: If tolerateTrailingJunk is true, then we want to tolerate non-8-bit junk 00603 // after the number, so is8Bit is too strict a check. 00604 if (!is8Bit()) 00605 return NaN; 00606 00607 const char *c = ascii(); 00608 00609 // skip leading white space 00610 while (isspace(*c)) 00611 c++; 00612 00613 // empty string ? 00614 if (*c == '\0') 00615 return tolerateEmptyString ? 0.0 : NaN; 00616 00617 if (*c == '-') { 00618 sign = -1; 00619 c++; 00620 } 00621 else if (*c == '+') { 00622 sign = 1; 00623 c++; 00624 } 00625 00626 // hex number ? 00627 if (*c == '0' && (*(c+1) == 'x' || *(c+1) == 'X')) { 00628 c++; 00629 d = 0.0; 00630 while (*(++c)) { 00631 if (*c >= '0' && *c <= '9') 00632 d = d * 16.0 + *c - '0'; 00633 else if ((*c >= 'A' && *c <= 'F') || (*c >= 'a' && *c <= 'f')) 00634 d = d * 16.0 + (*c & 0xdf) - 'A' + 10.0; 00635 else 00636 break; 00637 } 00638 } else { 00639 // regular number ? 00640 char *end; 00641 d = kjs_strtod(c, &end); 00642 if ((d != 0.0 || end != c) && d != HUGE_VAL && d != -HUGE_VAL) { 00643 c = end; 00644 } else { 00645 // infinity ? 00646 00647 int count = skipInfString(c); 00648 if (count == 0) 00649 return NaN; 00650 d = Inf; 00651 c += count; 00652 } 00653 } 00654 00655 // allow trailing white space 00656 while (isspace(*c)) 00657 c++; 00658 // don't allow anything after - unless tolerant=true 00659 if (!tolerateTrailingJunk && *c != '\0') 00660 return NaN; 00661 00662 return d*sign; 00663 } 00664 00665 double UString::toDouble(bool tolerateTrailingJunk) const 00666 { 00667 return toDouble(tolerateTrailingJunk, true); 00668 } 00669 00670 double UString::toDouble() const 00671 { 00672 return toDouble(false, true); 00673 } 00674 00675 unsigned long UString::toULong(bool *ok, bool tolerateEmptyString) const 00676 { 00677 double d = toDouble(false, tolerateEmptyString); 00678 bool b = true; 00679 00680 if (isNaN(d) || d != static_cast<unsigned long>(d)) { 00681 b = false; 00682 d = 0; 00683 } 00684 00685 if (ok) 00686 *ok = b; 00687 00688 return static_cast<unsigned long>(d); 00689 } 00690 00691 unsigned long UString::toULong(bool *ok) const 00692 { 00693 return toULong(ok, true); 00694 } 00695 00696 UString UString::toLower() const 00697 { 00698 UString u = *this; 00699 for (int i = 0; i < size(); i++) 00700 u[i] = u[i].toLower(); 00701 return u; 00702 } 00703 00704 UString UString::toUpper() const 00705 { 00706 UString u = *this; 00707 for (int i = 0; i < size(); i++) 00708 u[i] = u[i].toUpper(); 00709 return u; 00710 } 00711 00712 unsigned int UString::toStrictUInt32(bool *ok) const 00713 { 00714 if (ok) 00715 *ok = false; 00716 00717 // Empty string is not OK. 00718 int len = rep->len; 00719 if (len == 0) 00720 return 0; 00721 const UChar *p = rep->dat; 00722 unsigned short c = p->unicode(); 00723 00724 // If the first digit is 0, only 0 itself is OK. 00725 if (c == '0') { 00726 if (len == 1 && ok) 00727 *ok = true; 00728 return 0; 00729 } 00730 00731 // Convert to UInt32, checking for overflow. 00732 unsigned int i = 0; 00733 while (1) { 00734 // Process character, turning it into a digit. 00735 if (c < '0' || c > '9') 00736 return 0; 00737 const unsigned d = c - '0'; 00738 00739 // Multiply by 10, checking for overflow out of 32 bits. 00740 if (i > 0xFFFFFFFFU / 10) 00741 return 0; 00742 i *= 10; 00743 00744 // Add in the digit, checking for overflow out of 32 bits. 00745 const unsigned max = 0xFFFFFFFFU - d; 00746 if (i > max) 00747 return 0; 00748 i += d; 00749 00750 // Handle end of string. 00751 if (--len == 0) { 00752 if (ok) 00753 *ok = true; 00754 return i; 00755 } 00756 00757 // Get next character. 00758 c = (++p)->unicode(); 00759 } 00760 } 00761 00762 // Rule from ECMA 15.2 about what an array index is. 00763 // Must exactly match string form of an unsigned integer, and be less than 2^32 - 1. 00764 unsigned UString::toArrayIndex(bool *ok) const 00765 { 00766 unsigned i = toStrictUInt32(ok); 00767 if (i >= 0xFFFFFFFFU && ok) 00768 *ok = false; 00769 return i; 00770 } 00771 00772 int UString::find(const UString &f, int pos) const 00773 { 00774 int sz = size(); 00775 int fsz = f.size(); 00776 if (sz < fsz) 00777 return -1; 00778 if (pos < 0) 00779 pos = 0; 00780 if (fsz == 0) 00781 return pos; 00782 const UChar *end = data() + sz - fsz; 00783 long fsizeminusone = (fsz - 1) * sizeof(UChar); 00784 const UChar *fdata = f.data(); 00785 for (const UChar *c = data() + pos; c <= end; c++) 00786 if (*c == *fdata && !memcmp(c + 1, fdata + 1, fsizeminusone)) 00787 return (c-data()); 00788 00789 return -1; 00790 } 00791 00792 int UString::find(UChar ch, int pos) const 00793 { 00794 if (pos < 0) 00795 pos = 0; 00796 const UChar *end = data() + size(); 00797 for (const UChar *c = data() + pos; c < end; c++) 00798 if (*c == ch) 00799 return (c-data()); 00800 00801 return -1; 00802 } 00803 00804 int UString::rfind(const UString &f, int pos) const 00805 { 00806 int sz = size(); 00807 int fsz = f.size(); 00808 if (sz < fsz) 00809 return -1; 00810 if (pos < 0) 00811 pos = 0; 00812 if (pos > sz - fsz) 00813 pos = sz - fsz; 00814 if (fsz == 0) 00815 return pos; 00816 long fsizeminusone = (fsz - 1) * sizeof(UChar); 00817 const UChar *fdata = f.data(); 00818 for (const UChar *c = data() + pos; c >= data(); c--) { 00819 if (*c == *fdata && !memcmp(c + 1, fdata + 1, fsizeminusone)) 00820 return (c-data()); 00821 } 00822 00823 return -1; 00824 } 00825 00826 int UString::rfind(UChar ch, int pos) const 00827 { 00828 if (isEmpty()) 00829 return -1; 00830 if (pos + 1 >= size()) 00831 pos = size() - 1; 00832 for (const UChar *c = data() + pos; c >= data(); c--) { 00833 if (*c == ch) 00834 return (c-data()); 00835 } 00836 00837 return -1; 00838 } 00839 00840 UString UString::substr(int pos, int len) const 00841 { 00842 if (pos < 0) 00843 pos = 0; 00844 else if (pos >= (int) size()) 00845 pos = size(); 00846 if (len < 0) 00847 len = size(); 00848 if (pos + len >= (int) size()) 00849 len = size() - pos; 00850 00851 UChar *tmp = allocateChars(len); 00852 memcpy(tmp, data()+pos, len * sizeof(UChar)); 00853 UString result(tmp, len); 00854 delete [] tmp; 00855 00856 return result; 00857 } 00858 00859 void UString::attach(Rep *r) 00860 { 00861 rep = r; 00862 rep->ref(); 00863 } 00864 00865 void UString::detach() 00866 { 00867 if (rep->rc > 1) { 00868 int l = size(); 00869 UChar *n = allocateChars(l); 00870 memcpy(n, data(), l * sizeof(UChar)); 00871 release(); 00872 rep = Rep::create(n, l); 00873 } 00874 } 00875 00876 void UString::release() 00877 { 00878 rep->deref(); 00879 } 00880 00881 bool KJS::operator==(const UString& s1, const UString& s2) 00882 { 00883 if (s1.rep->len != s2.rep->len) 00884 return false; 00885 00886 return (memcmp(s1.rep->dat, s2.rep->dat, 00887 s1.rep->len * sizeof(UChar)) == 0); 00888 } 00889 00890 bool KJS::operator==(const UString& s1, const char *s2) 00891 { 00892 if (s2 == 0) { 00893 return s1.isEmpty(); 00894 } 00895 00896 const UChar *u = s1.data(); 00897 const UChar *uend = u + s1.size(); 00898 while (u != uend && *s2) { 00899 if (u->uc != (unsigned char)*s2) 00900 return false; 00901 s2++; 00902 u++; 00903 } 00904 00905 return u == uend && *s2 == 0; 00906 } 00907 00908 bool KJS::operator<(const UString& s1, const UString& s2) 00909 { 00910 const int l1 = s1.size(); 00911 const int l2 = s2.size(); 00912 const int lmin = l1 < l2 ? l1 : l2; 00913 const UChar *c1 = s1.data(); 00914 const UChar *c2 = s2.data(); 00915 int l = 0; 00916 while (l < lmin && *c1 == *c2) { 00917 c1++; 00918 c2++; 00919 l++; 00920 } 00921 if (l < lmin) 00922 return (c1->uc < c2->uc); 00923 00924 return (l1 < l2); 00925 } 00926 00927 int KJS::compare(const UString& s1, const UString& s2) 00928 { 00929 const int l1 = s1.size(); 00930 const int l2 = s2.size(); 00931 const int lmin = l1 < l2 ? l1 : l2; 00932 const UChar *c1 = s1.data(); 00933 const UChar *c2 = s2.data(); 00934 int l = 0; 00935 while (l < lmin && *c1 == *c2) { 00936 c1++; 00937 c2++; 00938 l++; 00939 } 00940 if (l < lmin) 00941 return (c1->uc > c2->uc) ? 1 : -1; 00942 00943 if (l1 == l2) { 00944 return 0; 00945 } 00946 return (l1 < l2) ? 1 : -1; 00947 }
KDE Logo
This file is part of the documentation for kjs Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Mar 16 17:22:14 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003