00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "ustring.h"
00023
00024 #include <string.h>
00025 #include <ctype.h>
00026 #include <stdlib.h>
00027 #include <stdio.h>
00028 #include <math.h>
00029
00030 #ifdef _MSC_VER
00031 #define snprintf _snprintf
00032 #endif
00033
00034 using namespace Swinder;
00035
00036 UChar UChar::null;
00037 UString::Rep UString::Rep::null = { 0, 0, 1, 0 };
00038 UString UString::null;
00039 static char *statBuffer = 0L;
00040
00041 UChar::UChar(const UCharReference &c)
00042 : uc( c.unicode() )
00043 {
00044 }
00045
00046 UCharReference& UCharReference::operator=(UChar c)
00047 {
00048 str->detach();
00049 if (offset < str->rep->len)
00050 *(str->rep->dat + offset) = c;
00051
00052 return *this;
00053 }
00054
00055 UChar& UCharReference::ref() const
00056 {
00057 if (offset < str->rep->len)
00058 return *(str->rep->dat + offset);
00059 else
00060 {
00061 static UChar nullRef('\0');
00062 return nullRef;
00063 }
00064 }
00065
00066 namespace {
00067
00068 static inline UChar* allocateChars(int s)
00069 {
00070
00071 return reinterpret_cast<UChar*>(new short[s]);
00072 }
00073 }
00074
00075
00076 UString::Rep *UString::Rep::create(UChar *d, int l)
00077 {
00078 Rep *r = new Rep;
00079 r->dat = d;
00080 r->len = l;
00081 r->cap = l;
00082 r->rc = 1;
00083
00084 return r;
00085 }
00086
00087 UString::Rep *UString::Rep::create(UChar *d, int l, int c)
00088 {
00089 Rep *r = new Rep;
00090 r->dat = d;
00091 r->len = l;
00092 r->cap = c;
00093 r->rc = 1;
00094
00095 return r;
00096 }
00097
00098 UString::UString()
00099 {
00100 null.rep = &Rep::null;
00101 attach(&Rep::null);
00102 }
00103
00104 UString::UString(char c)
00105 {
00106 UChar *d = allocateChars( 1 );
00107 d[0] = UChar(0, c);
00108 rep = Rep::create(d, 1);
00109 }
00110
00111 UString::UString(UChar c)
00112 {
00113 UChar *d = allocateChars( 1 );
00114 d[0] = c;
00115 rep = Rep::create(d, 1);
00116 }
00117
00118 UString::UString(const char *c)
00119 {
00120 attach(&Rep::null);
00121 operator=(c);
00122 }
00123
00124 UString::UString(const UChar *c, int length)
00125 {
00126 UChar *d = allocateChars( length );
00127 memcpy(d, c, length * sizeof(UChar));
00128 rep = Rep::create(d, length);
00129 }
00130
00131 UString::UString(UChar *c, int length, bool copy)
00132 {
00133 UChar *d;
00134 if (copy) {
00135 d = allocateChars( length );
00136 memcpy(d, c, length * sizeof(UChar));
00137 } else
00138 d = c;
00139 rep = Rep::create(d, length);
00140 }
00141
00142 UString::UString(const UString &b)
00143 {
00144 attach(b.rep);
00145 }
00146
00147
00148 UString::UString(Rep *r): rep(r)
00149 {
00150 }
00151
00152
00153 UString::~UString()
00154 {
00155 release();
00156 }
00157
00158 UString UString::number(int i)
00159 {
00160 #if 0
00161
00162 char buf[1+sizeof(int)*3];
00163 snprintf(buf, sizeof(int)*3, "%d", i);
00164 buf[sizeof(int)*3] = '\0';
00165 return UString(buf);
00166 #else
00167
00168 static unsigned short digits[] =
00169 { '9', '8', '7', '6', '5', '4', '3', '2', '1',
00170 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
00171
00172 UString::Rep* rep = 0;
00173
00174 if(i == 0)
00175 {
00176 UChar* buf = allocateChars(1);
00177 buf[0] = '0';
00178 rep = Rep::create(buf, 1);
00179 }
00180 else
00181 {
00182 bool neg = (i < 0);
00183 int ndig = 1 + sizeof(int)*3;
00184
00185 UChar* buf = allocateChars(ndig);
00186 UChar* ptr = buf + ndig - 1;
00187 int len = (neg) ? 1 : 0;
00188
00189
00190 for(; i != 0; i/=10, len++)
00191 *ptr-- = digits[9+i%10];
00192
00193 if(neg)
00194 *ptr-- = '-';
00195
00196
00197 memmove(buf, ptr+1, len*sizeof(unsigned short));
00198
00199 rep = Rep::create(buf, len, ndig);
00200 }
00201
00202 return UString(rep);
00203 #endif
00204 }
00205
00206 UString UString::number(unsigned int u)
00207 {
00208 #if 0
00209
00210 char buf[1+sizeof(unsigned int)*3];
00211 snprintf(buf, sizeof(unsigned int)*3, "%d", u);
00212 buf[sizeof(int)*3] = '\0';
00213 return UString(buf);
00214 #else
00215
00216 static unsigned short digits[] =
00217 { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
00218
00219 UString::Rep* rep = 0;
00220
00221 if(u < 10)
00222 {
00223 UChar* buf = allocateChars(1);
00224 buf[0] = digits[u];
00225 rep = Rep::create(buf, 1);
00226 }
00227 else
00228 {
00229 int ndig = 1 + sizeof(int)*3;
00230 UChar* buf = allocateChars(ndig);
00231 UChar* ptr = buf + ndig - 1;
00232 int len = 0;
00233
00234
00235 for(; u != 0; u/=10, len++)
00236 *ptr-- = digits[u%10];
00237
00238
00239 memmove(buf, ptr+1, len*sizeof(unsigned short));
00240
00241 rep = Rep::create(buf, len, ndig);
00242 }
00243
00244 return UString(rep);
00245 #endif
00246 }
00247
00248 UString UString::number(double d)
00249 {
00250 char buf[40];
00251 snprintf(buf, 39, "%.16g", d);
00252 buf[sizeof(int)*3] = '\0';
00253 return UString(buf);
00254 }
00255
00256 void UString::truncate(int n)
00257 {
00258 if((n >= 0) && (n < length()))
00259 {
00260 detach();
00261 rep->len = n;
00262 }
00263 }
00264
00265 void UString::reserve(int r)
00266 {
00267 if(r > length())
00268 {
00269 int l = length();
00270 UChar* n = allocateChars( r );
00271 memcpy(n, data(), l * sizeof(UChar));
00272 release();
00273 rep = Rep::create(n, l, r);
00274 }
00275 }
00276
00277 UString &UString::append(const UString &t)
00278 {
00279 int tl = t.length();
00280 if(tl > 0)
00281 {
00282 detach();
00283 int l = length();
00284
00285
00286 if(capacity() < tl + l)
00287 reserve(tl +l);
00288
00289 UChar *dd = rep->data();
00290 memcpy(dd+l, t.data(), tl * sizeof(UChar));
00291 rep->len += tl;
00292 }
00293
00294 return *this;
00295 }
00296
00297 UString &UString::append(const char* s)
00298 {
00299 int tl = strlen(s);
00300 if(tl > 0)
00301 {
00302 detach();
00303 int l = length();
00304
00305
00306 if(capacity() < tl + l)
00307 reserve(tl +l);
00308
00309
00310 UChar *dd = rep->data();
00311 for (int i = 0; i < tl; i++)
00312 dd[l+i].uc = static_cast<unsigned char>( s[i] );
00313 rep->len += tl;
00314 }
00315
00316 return *this;
00317 }
00318
00319 UString &UString::append(UChar c)
00320 {
00321 detach();
00322 int l = length();
00323
00324
00325
00326
00327 if(capacity() < l + 1)
00328 reserve(l + 8);
00329
00330 UChar *dd = rep->data();
00331 dd[l] = c;
00332 rep->len++;
00333
00334 return *this;
00335 }
00336
00337 UString &UString::append(char c)
00338 {
00339 return append( UChar((unsigned short)c) );
00340 }
00341
00342
00343 UString &UString::prepend(const UString &t)
00344 {
00345 int tl = t.length();
00346 if(tl > 0)
00347 {
00348 int l = length();
00349
00350
00351 if(capacity() < tl + l)
00352 reserve(tl +l);
00353
00354
00355 UChar *dd = rep->data();
00356 for(int i = l-1; i >= 0; i--)
00357 dd[i+tl] = dd[i];
00358 memcpy(dd, t.data(), tl * sizeof(UChar));
00359 rep->len += tl;
00360 }
00361
00362 return *this;
00363 }
00364
00365 UString &UString::prepend(const char* s)
00366 {
00367 int tl = strlen(s);
00368 if(tl > 0)
00369 {
00370 int l = length();
00371
00372
00373 if(capacity() < tl + l)
00374 reserve(tl +l);
00375
00376
00377 UChar *dd = rep->data();
00378 for(int i = l-1; i >= 0; i--)
00379 dd[i+tl] = dd[i];
00380 for(int j = 0; j < tl; j++)
00381 dd[j].uc = static_cast<unsigned char>( s[j] );
00382 rep->len += tl;
00383 }
00384
00385 return *this;
00386 }
00387
00388 UString &UString::prepend(UChar c)
00389 {
00390 int l = length();
00391
00392
00393
00394 if(capacity() < l + 1)
00395 reserve(l + 8);
00396
00397 UChar *dd = rep->data();
00398 for(int i = l-1; i >= 0; i--)
00399 dd[i+1] = dd[i];
00400 dd[0] = c;
00401 rep->len++;
00402
00403 return *this;
00404 }
00405
00406 UString &UString::prepend(char c)
00407 {
00408 return prepend( UChar((unsigned short)c) );
00409 }
00410
00411 char *UString::ascii() const
00412 {
00413 if (statBuffer)
00414 delete [] statBuffer;
00415
00416 statBuffer = new char[length()+1];
00417 for(int i = 0; i < length(); i++)
00418 statBuffer[i] = data()[i].low();
00419 statBuffer[length()] = '\0';
00420
00421 return statBuffer;
00422 }
00423
00424 UString &UString::operator=(const char *c)
00425 {
00426 release();
00427 int l = c ? strlen(c) : 0;
00428 UChar *d = allocateChars( l );
00429 for (int i = 0; i < l; i++)
00430 d[i].uc = static_cast<unsigned char>( c[i] );
00431 rep = Rep::create(d, l);
00432
00433 return *this;
00434 }
00435
00436 UString &UString::operator=(const UString &str)
00437 {
00438 str.rep->ref();
00439 release();
00440 rep=str.rep;
00441
00442 return *this;
00443 }
00444
00445 UString &UString::operator+=(const UString &s)
00446 {
00447 return append(s);
00448 }
00449
00450 bool UString::is8Bit() const
00451 {
00452 const UChar *u = data();
00453 for(int i = 0; i < length(); i++, u++)
00454 if (u->uc > 0xFF)
00455 return false;
00456
00457 return true;
00458 }
00459
00460 UChar UString::operator[](int pos) const
00461 {
00462 if (pos >= length())
00463 return UChar::null;
00464
00465 return static_cast<const UChar *>( data() )[pos];
00466 }
00467
00468 UCharReference UString::operator[](int pos)
00469 {
00470
00471 return UCharReference(this, pos);
00472 }
00473
00474 UString UString::substr(int pos, int len) const
00475 {
00476 if (isNull())
00477 return UString();
00478 if (pos < 0)
00479 pos = 0;
00480 else if (pos >= static_cast<int>( length() ))
00481 pos = length();
00482 if (len < 0)
00483 len = length();
00484 if (pos + len >= static_cast<int>( length() ))
00485 len = length() - pos;
00486
00487 UChar *tmp = allocateChars( len );
00488 memcpy(tmp, data()+pos, len * sizeof(UChar));
00489 UString result(tmp, len);
00490 delete [] tmp;
00491
00492 return result;
00493 }
00494
00495 int UString::find(const UString &f, int pos) const
00496 {
00497 if (isNull())
00498 return -1;
00499 long fsize = f.length() * sizeof(UChar);
00500 if (pos < 0)
00501 pos = 0;
00502 const UChar *end = data() + length() - f.length();
00503 for (const UChar *c = data() + pos; c <= end; c++)
00504 if (!memcmp(c, f.data(), fsize))
00505 return (c-data());
00506
00507 return -1;
00508 }
00509
00510 void UString::attach(Rep *r)
00511 {
00512 rep = r;
00513 rep->ref();
00514 }
00515
00516 void UString::detach()
00517 {
00518 if (rep->rc > 1)
00519 {
00520 int c = capacity();
00521 int l = length();
00522 UChar *n = allocateChars( c );
00523 memcpy(n, data(), l * sizeof(UChar));
00524 release();
00525 rep = Rep::create(n, l, c);
00526 }
00527 }
00528
00529 void UString::release()
00530 {
00531 if (!rep->deref())
00532 {
00533 delete [] rep->dat;
00534 delete rep;
00535 }
00536 }
00537
00538 bool Swinder::operator==(const UString& s1, const UString& s2)
00539 {
00540 if (s1.rep->len != s2.rep->len)
00541 return false;
00542
00543 return (memcmp(s1.rep->dat, s2.rep->dat,
00544 s1.rep->len * sizeof(UChar)) == 0);
00545 }
00546
00547 bool Swinder::operator==(const UString& s1, const char *s2)
00548 {
00549 if (s2 == 0L)
00550 return s1.isEmpty();
00551
00552 if (s1.length() != static_cast<int>( strlen(s2) ))
00553 return false;
00554
00555 const UChar *u = s1.data();
00556 while (*s2)
00557 {
00558 if (u->uc != *s2 )
00559 return false;
00560 s2++;
00561 u++;
00562 }
00563
00564 return true;
00565 }
00566
00567 bool Swinder::operator<(const UString& s1, const UString& s2)
00568 {
00569 const int l1 = s1.length();
00570 const int l2 = s2.length();
00571 const int lmin = l1 < l2 ? l1 : l2;
00572 const UChar *c1 = s1.data();
00573 const UChar *c2 = s2.data();
00574 int l = 0;
00575 while (l < lmin && *c1 == *c2)
00576 {
00577 c1++;
00578 c2++;
00579 l++;
00580 }
00581 if (l < lmin)
00582 return (c1->unicode() < c2->unicode());
00583
00584 return (l1 < l2);
00585 }
00586
00587 UString Swinder::operator+(const UString& s1, const UString& s2)
00588 {
00589 UString tmp(s1);
00590 tmp.append(s2);
00591
00592 return tmp;
00593 }
00594
00595
00596 UConstString::UConstString( UChar* data, unsigned int length ) :
00597 UString( data, length, false )
00598 {
00599 }
00600
00601 UConstString::~UConstString()
00602 {
00603 if ( rep->rc > 1 ) {
00604 int l = length();
00605 UChar* n = allocateChars( l );
00606 memcpy( n, data(), l * sizeof( UChar ) );
00607 rep->dat = n;
00608 }
00609 else
00610 rep->dat = 0;
00611 }