00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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
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
00166 static inline UChar* allocateChars(int s)
00167 {
00168
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);
00259
00260
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
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
00369 while (isspace(*c))
00370 c++;
00371
00372
00373 if (*c == '\0')
00374 return tolerant ? NaN : 0.0;
00375
00376
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
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
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
00411 while (isspace(*c))
00412 c++;
00413
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 }