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 = 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 = 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 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   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::toUInt32(bool *ok) const
00713 {
00714   double d = toDouble();
00715   bool b = true;
00716 
00717   if (isNaN(d) || d != static_cast<unsigned>(d)) {
00718     b = false;
00719     d = 0;
00720   }
00721 
00722   if (ok)
00723     *ok = b;
00724 
00725   return static_cast<unsigned>(d);
00726 }
00727 
00728 unsigned int UString::toStrictUInt32(bool *ok) const
00729 {
00730   if (ok)
00731     *ok = false;
00732 
00733   // Empty string is not OK.
00734   int len = rep->len;
00735   if (len == 0)
00736     return 0;
00737   const UChar *p = rep->dat;
00738   unsigned short c = p->unicode();
00739 
00740   // If the first digit is 0, only 0 itself is OK.
00741   if (c == '0') {
00742     if (len == 1 && ok)
00743       *ok = true;
00744     return 0;
00745   }
00746 
00747   // Convert to UInt32, checking for overflow.
00748   unsigned int i = 0;
00749   while (1) {
00750     // Process character, turning it into a digit.
00751     if (c < '0' || c > '9')
00752       return 0;
00753     const unsigned d = c - '0';
00754 
00755     // Multiply by 10, checking for overflow out of 32 bits.
00756     if (i > 0xFFFFFFFFU / 10)
00757       return 0;
00758     i *= 10;
00759 
00760     // Add in the digit, checking for overflow out of 32 bits.
00761     const unsigned max = 0xFFFFFFFFU - d;
00762     if (i > max)
00763         return 0;
00764     i += d;
00765 
00766     // Handle end of string.
00767     if (--len == 0) {
00768       if (ok)
00769         *ok = true;
00770       return i;
00771     }
00772 
00773     // Get next character.
00774     c = (++p)->unicode();
00775   }
00776 }
00777 
00778 // Rule from ECMA 15.2 about what an array index is.
00779 // Must exactly match string form of an unsigned integer, and be less than 2^32 - 1.
00780 unsigned UString::toArrayIndex(bool *ok) const
00781 {
00782   unsigned i = toStrictUInt32(ok);
00783   if (i >= 0xFFFFFFFFU && ok)
00784     *ok = false;
00785   return i;
00786 }
00787 
00788 int UString::find(const UString &f, int pos) const
00789 {
00790   int sz = size();
00791   int fsz = f.size();
00792   if (sz < fsz)
00793     return -1;
00794   if (pos < 0)
00795     pos = 0;
00796   if (fsz == 0)
00797     return pos;
00798   const UChar *end = data() + sz - fsz;
00799   long fsizeminusone = (fsz - 1) * sizeof(UChar);
00800   const UChar *fdata = f.data();
00801   for (const UChar *c = data() + pos; c <= end; c++)
00802     if (*c == *fdata && !memcmp(c + 1, fdata + 1, fsizeminusone))
00803       return (c-data());
00804 
00805   return -1;
00806 }
00807 
00808 int UString::find(UChar ch, int pos) const
00809 {
00810   if (pos < 0)
00811     pos = 0;
00812   const UChar *end = data() + size();
00813   for (const UChar *c = data() + pos; c < end; c++)
00814     if (*c == ch)
00815       return (c-data());
00816 
00817   return -1;
00818 }
00819 
00820 int UString::rfind(const UString &f, int pos) const
00821 {
00822   int sz = size();
00823   int fsz = f.size();
00824   if (sz < fsz)
00825     return -1;
00826   if (pos < 0)
00827     pos = 0;
00828   if (pos > sz - fsz)
00829     pos = sz - fsz;
00830   if (fsz == 0)
00831     return pos;
00832   long fsizeminusone = (fsz - 1) * sizeof(UChar);
00833   const UChar *fdata = f.data();
00834   for (const UChar *c = data() + pos; c >= data(); c--) {
00835     if (*c == *fdata && !memcmp(c + 1, fdata + 1, fsizeminusone))
00836       return (c-data());
00837   }
00838 
00839   return -1;
00840 }
00841 
00842 int UString::rfind(UChar ch, int pos) const
00843 {
00844   if (isEmpty())
00845     return -1;
00846   if (pos + 1 >= size())
00847     pos = size() - 1;
00848   for (const UChar *c = data() + pos; c >= data(); c--) {
00849     if (*c == ch)
00850       return (c-data());
00851   }
00852 
00853   return -1;
00854 }
00855 
00856 UString UString::substr(int pos, int len) const
00857 {
00858   if (pos < 0)
00859     pos = 0;
00860   else if (pos >= (int) size())
00861     pos = size();
00862   if (len < 0)
00863     len = size();
00864   if (pos + len >= (int) size())
00865     len = size() - pos;
00866 
00867   UChar *tmp = allocateChars(len);
00868   memcpy(tmp, data()+pos, len * sizeof(UChar));
00869   UString result(tmp, len);
00870   delete [] tmp;
00871 
00872   return result;
00873 }
00874 
00875 void UString::attach(Rep *r)
00876 {
00877   rep = r;
00878   rep->ref();
00879 }
00880 
00881 void UString::detach()
00882 {
00883   if (rep->rc > 1) {
00884     int l = size();
00885     UChar *n = allocateChars(l);
00886     memcpy(n, data(), l * sizeof(UChar));
00887     release();
00888     rep = Rep::create(n, l);
00889   }
00890 }
00891 
00892 void UString::release()
00893 {
00894   rep->deref();
00895 }
00896 
00897 bool KJS::operator==(const UString& s1, const UString& s2)
00898 {
00899   if (s1.rep->len != s2.rep->len)
00900     return false;
00901 
00902   return (memcmp(s1.rep->dat, s2.rep->dat,
00903          s1.rep->len * sizeof(UChar)) == 0);
00904 }
00905 
00906 bool KJS::operator==(const UString& s1, const char *s2)
00907 {
00908   if (s2 == 0) {
00909     return s1.isEmpty();
00910   }
00911 
00912   const UChar *u = s1.data();
00913   const UChar *uend = u + s1.size();
00914   while (u != uend && *s2) {
00915     if (u->uc != (unsigned char)*s2)
00916       return false;
00917     s2++;
00918     u++;
00919   }
00920 
00921   return u == uend && *s2 == 0;
00922 }
00923 
00924 bool KJS::operator<(const UString& s1, const UString& s2)
00925 {
00926   const int l1 = s1.size();
00927   const int l2 = s2.size();
00928   const int lmin = l1 < l2 ? l1 : l2;
00929   const UChar *c1 = s1.data();
00930   const UChar *c2 = s2.data();
00931   int l = 0;
00932   while (l < lmin && *c1 == *c2) {
00933     c1++;
00934     c2++;
00935     l++;
00936   }
00937   if (l < lmin)
00938     return (c1->uc < c2->uc);
00939 
00940   return (l1 < l2);
00941 }
00942 
00943 int KJS::compare(const UString& s1, const UString& s2)
00944 {
00945   const int l1 = s1.size();
00946   const int l2 = s2.size();
00947   const int lmin = l1 < l2 ? l1 : l2;
00948   const UChar *c1 = s1.data();
00949   const UChar *c2 = s2.data();
00950   int l = 0;
00951   while (l < lmin && *c1 == *c2) {
00952     c1++;
00953     c2++;
00954     l++;
00955   }
00956   if (l < lmin)
00957     return (c1->uc > c2->uc) ? 1 : -1;
00958 
00959   if (l1 == l2) {
00960     return 0;
00961   }
00962   return (l1 < l2) ? 1 : -1;
00963 }
KDE Logo
This file is part of the documentation for kjs Library Version 3.4.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Sep 16 06:53:27 2005 by doxygen 1.4.4 written by Dimitri van Heesch, © 1997-2003