kjs Library: ustring.cpp Source File (kjs Library)

| # kjs Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# 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 }

This file is part of the documentation for kjs Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:23:07 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003