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  *
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 }
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.0.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Oct 8 12:21:15 2003 by doxygen 1.2.18 written by Dimitri van Heesch, © 1997-2001