# kjs Library API Documentation

Overview | Class Hierarchy | Classes | Classes (annotated) | Members | 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  *
    00006  *  This library is free software; you can redistribute it and/or
    00007  *  modify it under the terms of the GNU Lesser General Public
    00008  *  License as published by the Free Software Foundation; either
    00009  *  version 2 of the License, or (at your option) any later version.
    00010  *
    00011  *  This library is distributed in the hope that it will be useful,
    00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00014  *  Lesser General Public License for more details.
    00015  *
    00016  *  You should have received a copy of the GNU Lesser General Public License
    00017  *  along with this library; see the file COPYING.LIB.  If not, write to
    00018  *  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00019  *  Boston, MA 02111-1307, USA.
    00020  *
    00021  */
    00022
    00023 #ifdef HAVE_CONFIG_H
    00024 #include <config.h>
    00025 #endif
    00026
    00027 #include <stdlib.h>
    00028 #include <stdio.h>
    00029 #include <ctype.h>
    00030 #ifdef HAVE_STRING_H
    00031 #include <string.h>
    00032 #endif
    00033 #ifdef HAVE_STRINGS_H
    00034 #include <strings.h>
    00035 #endif
    00036
    00037 #include "ustring.h"
    00038 #include "operations.h"
    00039 #include <math.h>
    00040
    00041 namespace KJS {
    00042   extern const double NaN;
    00043   extern const double Inf;
    00044 }
    00045
    00046 using namespace KJS;
    00047
    00048 CString::CString(const char *c)
    00049 {
    00050   data = new char[strlen(c)+1];
    00051   strcpy(data, c);
    00052 }
    00053
    00054 CString::CString(const CString &b)
    00055 {
    00056   data = new char[b.size()+1];
    00057   strcpy(data, b.c_str());
    00058 }
    00059
    00060 CString::~CString()
    00061 {
    00062   delete [] data;
    00063 }
    00064
    00065 CString &CString::append(const CString &t)
    00066 {
    00067   char *n;
    00068   if (data) {
    00069     n = new char[strlen(data)+t.size()+1];
    00070     strcpy(n, data);
    00071   } else {
    00072     n = new char[t.size()+1];
    00073     n[0] = '\0';
    00074   }
    00075   strcat(n, t.c_str());
    00076
    00077   delete [] data;
    00078   data = n;
    00079
    00080   return *this;
    00081 }
    00082
    00083 CString &CString::operator=(const char *c)
    00084 {
    00085   if (data)
    00086     delete [] data;
    00087   data = new char[strlen(c)+1];
    00088   strcpy(data, c);
    00089
    00090   return *this;
    00091 }
    00092
    00093 CString &CString::operator=(const CString &str)
    00094 {
    00095   if (this == &str)
    00096     return *this;
    00097
    00098   if (data)
    00099     delete [] data;
    00100   data = new char[str.size()+1];
    00101   strcpy(data, str.c_str());
    00102
    00103   return *this;
    00104 }
    00105
    00106 CString &CString::operator+=(const CString &str)
    00107 {
    00108   return append(str.c_str());
    00109 }
    00110
    00111 int CString::size() const
    00112 {
    00113   return strlen(data);
    00114 }
    00115
    00116 bool KJS::operator==(const KJS::CString& c1, const KJS::CString& c2)
    00117 {
    00118   return (strcmp(c1.c_str(), c2.c_str()) == 0);
    00119 }
    00120
    00121 UChar UChar::null;
    00122 UString::Rep UString::Rep::null = { 0, 0, 1 };
    00123 UString UString::null;
    00124 static char *statBuffer = 0L;
    00125
    00126 UChar::UChar(const UCharReference &c)
    00127     : uc( c.unicode() )
    00128 {
    00129 }
    00130
    00131 UChar UChar::toLower() const
    00132 {
    00133   // ### properly supprot unicode tolower
    00134   if (uc >= 256 || islower(uc))
    00135     return *this;
    00136
    00137   return UChar(tolower(uc));
    00138 }
    00139
    00140 UChar UChar::toUpper() const
    00141 {
    00142   if (uc >= 256 || isupper(uc))
    00143     return *this;
    00144
    00145   return UChar(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->rc = 1;
    00178
    00179   return r;
    00180 }
    00181
    00182 UString::UString()
    00183 {
    00184   null.rep = &Rep::null;
    00185   attach(&Rep::null);
    00186 }
    00187
    00188 UString::UString(char c)
    00189 {
    00190     UChar *d = allocateChars(1);
    00191     d[0] = UChar(0, c);
    00192     rep = Rep::create(d, 1);
    00193 }
    00194
    00195 UString::UString(const char *c)
    00196 {
    00197   attach(&Rep::null);
    00198   operator=(c);
    00199 }
    00200
    00201 UString::UString(const UChar *c, int length)
    00202 {
    00203   UChar *d = allocateChars(length);
    00204   memcpy(d, c, length * sizeof(UChar));
    00205   rep = Rep::create(d, length);
    00206 }
    00207
    00208 UString::UString(UChar *c, int length, bool copy)
    00209 {
    00210   UChar *d;
    00211   if (copy) {
    00212     d = allocateChars(length);
    00213     memcpy(d, c, length * sizeof(UChar));
    00214   } else
    00215     d = c;
    00216   rep = Rep::create(d, length);
    00217 }
    00218
    00219 UString::UString(const UString &b)
    00220 {
    00221   attach(b.rep);
    00222 }
    00223
    00224 UString::~UString()
    00225 {
    00226   release();
    00227 }
    00228
    00229 UString UString::from(int i)
    00230 {
    00231   char buf[40];
    00232   sprintf(buf, "%d", i);
    00233
    00234   return UString(buf);
    00235 }
    00236
    00237 UString UString::from(unsigned int u)
    00238 {
    00239   char buf[40];
    00240   sprintf(buf, "%u", u);
    00241
    00242   return UString(buf);
    00243 }
    00244
    00245 UString UString::from(double d)
    00246 {
    00247   char buf[40];
    00248
    00249   if (d == -0)
    00250     strcpy(buf,"0");
    00251   else if (KJS::isNaN(d))
    00252     strcpy(buf,"NaN");
    00253   else if (KJS::isPosInf(d))
    00254     strcpy(buf,"Infinity");
    00255   else if (KJS::isNegInf(d))
    00256     strcpy(buf,"-Infinity");
    00257   else
    00258     sprintf(buf, "%.16g", d);   // does the right thing
    00259
    00260   // ECMA 3rd ed. 9.8.1 9 e: "with no leading zeros"
    00261   int buflen = strlen(buf);
    00262   if (buflen >= 4 && buf[buflen-4] == 'e' && buf[buflen-2] == '0') {
    00263     buf[buflen-2] = buf[buflen-1];
    00264     buf[buflen-1] = 0;
    00265   }
    00266
    00267   return UString(buf);
    00268 }
    00269
    00270 UString &UString::append(const UString &t)
    00271 {
    00272   int l = size();
    00273   UChar *n = allocateChars(l+t.size());
    00274   memcpy(n, data(), l * sizeof(UChar));
    00275   memcpy(n+l, t.data(), t.size() * sizeof(UChar));
    00276   release();
    00277   rep = Rep::create(n, l + t.size());
    00278
    00279   return *this;
    00280 }
    00281
    00282 CString UString::cstring() const
    00283 {
    00284   return CString(ascii());
    00285 }
    00286
    00287 char *UString::ascii() const
    00288 {
    00289   if (statBuffer)
    00290     delete [] statBuffer;
    00291
    00292   statBuffer = new char[size()+1];
    00293   for(int i = 0; i < size(); i++)
    00294     statBuffer[i] = data()[i].low();
    00295   statBuffer[size()] = '\0';
    00296
    00297   return statBuffer;
    00298 }
    00299
    00300 #ifdef KJS_DEBUG_MEM
    00301 void UString::globalClear()
    00302 {
    00303   delete [] statBuffer;
    00304   statBuffer = 0L;
    00305 }
    00306 #endif
    00307
    00308 UString &UString::operator=(const char *c)
    00309 {
    00310   release();
    00311   int l = c ? strlen(c) : 0;
    00312   UChar *d = allocateChars(l);
    00313   for (int i = 0; i < l; i++)
    00314     d[i].uc = (unsigned char)c[i];
    00315   rep = Rep::create(d, l);
    00316
    00317   return *this;
    00318 }
    00319
    00320 UString &UString::operator=(const UString &str)
    00321 {
    00322   str.rep->ref();
    00323   release();
    00324   rep = str.rep;
    00325
    00326   return *this;
    00327 }
    00328
    00329 UString &UString::operator+=(const UString &s)
    00330 {
    00331   return append(s);
    00332 }
    00333
    00334 bool UString::is8Bit() const
    00335 {
    00336   const UChar *u = data();
    00337   for(int i = 0; i < size(); i++, u++)
    00338     if (u->uc > 0xFF)
    00339       return false;
    00340
    00341   return true;
    00342 }
    00343
    00344 UChar UString::operator[](int pos) const
    00345 {
    00346   if (pos >= size())
    00347     return UChar::null;
    00348
    00349   return ((UChar *)data())[pos];
    00350 }
    00351
    00352 UCharReference UString::operator[](int pos)
    00353 {
    00354   /* TODO: boundary check */
    00355   return UCharReference(this, pos);
    00356 }
    00357
    00358 double UString::toDouble( bool tolerant ) const
    00359 {
    00360   double d;
    00361
    00362   if (!is8Bit())
    00363     return NaN;
    00364
    00365   CString str = cstring();
    00366   const char *c = str.c_str();
    00367
    00368   // skip leading white space
    00369   while (isspace(*c))
    00370     c++;
    00371
    00372   // empty string ?
    00373   if (*c == '\0')
    00374     return tolerant ? NaN : 0.0;
    00375
    00376   // hex number ?
    00377   if (*c == '0' && (*(c+1) == 'x' || *(c+1) == 'X')) {
    00378     c++;
    00379     d = 0.0;
    00380     while (*(++c)) {
    00381       if (*c >= '0' && *c <= '9')
    00382         d = d * 16.0 + *c - '0';
    00383       else if ((*c >= 'A' && *c <= 'F') || (*c >= 'a' && *c <= 'f'))
    00384         d = d * 16.0 + (*c & 0xdf) - 'A' + 10.0;
    00385       else
    00386         break;
    00387     }
    00388   } else {
    00389     // regular number ?
    00390     char *end;
    00391     d = strtod(c, &end);
    00392     if ((d != 0.0 || end != c) && d != HUGE_VAL && d != -HUGE_VAL) {
    00393       c = end;
    00394     } else {
    00395       // infinity ?
    00396       d = 1.0;
    00397       if (*c == '+')
    00398         c++;
    00399       else if (*c == '-') {
    00400         d = -1.0;
    00401         c++;
    00402       }
    00403       if (strncmp(c, "Infinity", 8) != 0)
    00404         return NaN;
    00405       d = d * Inf;
    00406       c += 8;
    00407     }
    00408   }
    00409
    00410   // allow trailing white space
    00411   while (isspace(*c))
    00412     c++;
    00413   // don't allow anything after - unless tolerant=true
    00414   if ( !tolerant && *c != '\0')
    00415     d = NaN;
    00416
    00417   return d;
    00418 }
    00419
    00420 unsigned long UString::toULong(bool *ok) const
    00421 {
    00422   double d = toDouble();
    00423   bool b = true;
    00424
    00425   if (isNaN(d) || d != static_cast<unsigned long>(d)) {
    00426     b = false;
    00427     d = 0;
    00428   }
    00429
    00430   if (ok)
    00431     *ok = b;
    00432
    00433   return static_cast<unsigned long>(d);
    00434 }
    00435
    00436 UString UString::toLower() const
    00437 {
    00438   UString u = *this;
    00439   for (int i = 0; i < size(); i++)
    00440     u[i] = u[i].toLower();
    00441   return u;
    00442 }
    00443
    00444 UString UString::toUpper() const
    00445 {
    00446   UString u = *this;
    00447   for (int i = 0; i < size(); i++)
    00448     u[i] = u[i].toUpper();
    00449   return u;
    00450 }
    00451
    00452 int UString::find(const UString &f, int pos) const
    00453 {
    00454   if (isNull())
    00455     return -1;
    00456   long fsize = f.size() * sizeof(UChar);
    00457   if (pos < 0)
    00458     pos = 0;
    00459   const UChar *end = data() + size() - f.size();
    00460   for (const UChar *c = data() + pos; c <= end; c++)
    00461     if (!memcmp((void*)c, (void*)f.data(), fsize))
    00462       return (c-data());
    00463
    00464   return -1;
    00465 }
    00466
    00467 int UString::rfind(const UString &f, int pos) const
    00468 {
    00469   if (isNull())
    00470     return -1;
    00471   if (pos + f.size() >= size())
    00472     pos = size() - f.size();
    00473   long fsize = f.size() * sizeof(UChar);
    00474   for (const UChar *c = data() + pos; c >= data(); c--) {
    00475     if (!memcmp((void*)c, (void*)f.data(), fsize))
    00476       return (c-data());
    00477   }
    00478
    00479   return -1;
    00480 }
    00481
    00482 UString UString::substr(int pos, int len) const
    00483 {
    00484   if (isNull())
    00485     return UString();
    00486   if (pos < 0)
    00487     pos = 0;
    00488   else if (pos >= (int) size())
    00489     pos = size();
    00490   if (len < 0)
    00491     len = size();
    00492   if (pos + len >= (int) size())
    00493     len = size() - pos;
    00494
    00495   UChar *tmp = allocateChars(len);
    00496   memcpy(tmp, data()+pos, len * sizeof(UChar));
    00497   UString result(tmp, len);
    00498   delete [] tmp;
    00499
    00500   return result;
    00501 }
    00502
    00503 void UString::attach(Rep *r)
    00504 {
    00505   rep = r;
    00506   rep->ref();
    00507 }
    00508
    00509 void UString::detach()
    00510 {
    00511   if (rep->rc > 1) {
    00512     int l = size();
    00513     UChar *n = allocateChars(l);
    00514     memcpy(n, data(), l * sizeof(UChar));
    00515     release();
    00516     rep = Rep::create(n, l);
    00517   }
    00518 }
    00519
    00520 void UString::release()
    00521 {
    00522   if (!rep->deref()) {
    00523     delete [] rep->dat;
    00524     delete rep;
    00525   }
    00526 }
    00527
    00528 bool KJS::operator==(const UString& s1, const UString& s2)
    00529 {
    00530   if (s1.rep->len != s2.rep->len)
    00531     return false;
    00532
    00533   return (memcmp(s1.rep->dat, s2.rep->dat,
    00534                  s1.rep->len * sizeof(UChar)) == 0);
    00535 }
    00536
    00537 bool KJS::operator==(const UString& s1, const char *s2)
    00538 {
    00539   if (s2 == 0L && s1.isNull())
    00540     return true;
    00541
    00542   if (s1.size() != (int) strlen(s2))
    00543     return false;
    00544
    00545   const UChar *u = s1.data();
    00546   while (*s2) {
    00547     if (u->uc != *s2 )
    00548       return false;
    00549     s2++;
    00550     u++;
    00551   }
    00552
    00553   return true;
    00554 }
    00555
    00556 bool KJS::operator<(const UString& s1, const UString& s2)
    00557 {
    00558   const int l1 = s1.size();
    00559   const int l2 = s2.size();
    00560   const int lmin = l1 < l2 ? l1 : l2;
    00561   const UChar *c1 = s1.data();
    00562   const UChar *c2 = s2.data();
    00563   int l = 0;
    00564   while (l < lmin && *c1 == *c2) {
    00565     c1++;
    00566     c2++;
    00567     l++;
    00568   }
    00569   if (l < lmin)
    00570     return (c1->unicode() < c2->unicode());
    00571
    00572   return (l1 < l2);
    00573 }
    00574
    00575 UString KJS::operator+(const UString& s1, const UString& s2)
    00576 {
    00577   UString tmp(s1);
    00578   tmp.append(s2);
    00579
    00580   return tmp;
    00581 }

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:08:37 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001