00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 #include "RConfig.h"
00049 #include <stdlib.h>
00050 #include <ctype.h>
00051 #include <list>
00052
00053 #include "snprintf.h"
00054 #include "Varargs.h"
00055 #include "TString.h"
00056 #include "TBuffer.h"
00057 #include "TError.h"
00058 #include "Bytes.h"
00059 #include "TClass.h"
00060 #include "TObjArray.h"
00061 #include "TObjString.h"
00062 #include "TVirtualMutex.h"
00063
00064 #ifdef R__GLOBALSTL
00065 namespace std { using ::list; }
00066 #endif
00067
00068
00069
00070 TVirtualMutex *gStringMutex = 0;
00071
00072
00073
00074 const UInt_t kHashShift = 5;
00075
00076
00077
00078
00079
00080 static long gNullRef[(sizeof(TStringRef)+1)/sizeof(long) + 1];
00081 static void *gNullRefTmp = gNullRef;
00082
00083
00084
00085
00086
00087 #define gNullStringRef ((TStringRef*)gNullRefTmp)
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 TStringRef *TStringRef::GetRep(Ssiz_t capacity, Ssiz_t nchar)
00137 {
00138
00139
00140
00141 if ((capacity | nchar) == 0) {
00142 gNullStringRef->AddReference();
00143 return gNullStringRef;
00144 }
00145 TStringRef *ret = (TStringRef*)new char[capacity + sizeof(TStringRef) + 1];
00146 ret->fCapacity = capacity;
00147 ret->SetRefCount(1);
00148 ret->Data()[ret->fNchars = nchar] = 0;
00149
00150 return ret;
00151 }
00152
00153
00154 Ssiz_t TStringRef::First(char c) const
00155 {
00156
00157
00158 const char *f = strchr(Data(), c);
00159 return f ? f - Data() : kNPOS;
00160 }
00161
00162
00163 Ssiz_t TStringRef::First(const char *cs) const
00164 {
00165
00166
00167 const char *f = strpbrk(Data(), cs);
00168 return f ? f - Data() : kNPOS;
00169 }
00170
00171 #ifndef R__BYTESWAP
00172
00173 inline static UInt_t SwapInt(UInt_t x)
00174 {
00175 return (((x & 0x000000ffU) << 24) | ((x & 0x0000ff00U) << 8) |
00176 ((x & 0x00ff0000U) >> 8) | ((x & 0xff000000U) >> 24));
00177 }
00178 #endif
00179
00180
00181 inline static void Mash(UInt_t& hash, UInt_t chars)
00182 {
00183
00184
00185 hash = (chars ^
00186 ((hash << kHashShift) |
00187 (hash >> (kBitsPerByte*sizeof(UInt_t) - kHashShift))));
00188 }
00189
00190
00191 UInt_t Hash(const char *str)
00192 {
00193
00194
00195 UInt_t len = str ? strlen(str) : 0;
00196 UInt_t hv = len;
00197 UInt_t i = hv*sizeof(char)/sizeof(UInt_t);
00198
00199 if (((ULong_t)str)%sizeof(UInt_t) == 0) {
00200
00201 const UInt_t *p = (const UInt_t*)str;
00202
00203 while (i--) {
00204 #ifndef R__BYTESWAP
00205 UInt_t h = *p++;
00206 Mash(hv, SwapInt(h));
00207 #else
00208 Mash(hv, *p++);
00209 #endif
00210 }
00211
00212
00213 if ((i = len*sizeof(char)%sizeof(UInt_t)) != 0) {
00214 UInt_t h = 0;
00215 const char* c = (const char*)p;
00216 while (i--)
00217 h = ((h << kBitsPerByte*sizeof(char)) | *c++);
00218 Mash(hv, h);
00219 }
00220 } else {
00221
00222 UInt_t h;
00223 const unsigned char *p = (const unsigned char*)str;
00224
00225 while (i--) {
00226 memcpy(&h, p, sizeof(UInt_t));
00227 #ifndef R__BYTESWAP
00228 Mash(hv, SwapInt(h));
00229 #else
00230 Mash(hv, h);
00231 #endif
00232 p += sizeof(UInt_t);
00233 }
00234
00235
00236 if ((i = len*sizeof(char)%sizeof(UInt_t)) != 0) {
00237 h = 0;
00238 const char* c = (const char*)p;
00239 while (i--)
00240 h = ((h << kBitsPerByte*sizeof(char)) | *c++);
00241 Mash(hv, h);
00242 }
00243 }
00244 return hv;
00245 }
00246
00247
00248 UInt_t TStringRef::Hash() const
00249 {
00250
00251
00252 UInt_t hv = (UInt_t)Length();
00253 UInt_t i = hv*sizeof(char)/sizeof(UInt_t);
00254 const UInt_t *p = (const UInt_t*)Data();
00255 {
00256 while (i--) {
00257 #ifndef R__BYTESWAP
00258 UInt_t h = *p++;
00259 Mash(hv, SwapInt(h));
00260 #else
00261 Mash(hv, *p++);
00262 #endif
00263 }
00264 }
00265
00266 if ((i = Length()*sizeof(char)%sizeof(UInt_t)) != 0) {
00267 UInt_t h = 0;
00268 const char* c = (const char*)p;
00269 while (i--)
00270 h = ((h << kBitsPerByte*sizeof(char)) | *c++);
00271 Mash(hv, h);
00272 }
00273 return hv;
00274 }
00275
00276
00277 UInt_t TStringRef::HashFoldCase() const
00278 {
00279
00280
00281 UInt_t hv = (UInt_t)Length();
00282 UInt_t i = hv;
00283 const unsigned char *p = (const unsigned char*)Data();
00284 while (i--) {
00285 Mash(hv, toupper(*p));
00286 ++p;
00287 }
00288 return hv;
00289 }
00290
00291
00292 Ssiz_t TStringRef::Last(char c) const
00293 {
00294
00295
00296 const char *f = strrchr(Data(), (unsigned char) c);
00297 return f ? f - Data() : kNPOS;
00298 }
00299
00300
00301 ClassImp(TString)
00302
00303
00304
00305
00306
00307
00308
00309
00310 Ssiz_t TString::GetInitialCapacity() { return fgInitialCapac; }
00311 Ssiz_t TString::GetResizeIncrement() { return fgResizeInc; }
00312 Ssiz_t TString::GetMaxWaste() { return fgFreeboard; }
00313
00314
00315 TString::TString()
00316 {
00317
00318
00319 fData = gNullStringRef->Data();
00320 gNullStringRef->AddReference();
00321 }
00322
00323
00324 TString::TString(Ssiz_t ic)
00325 {
00326
00327
00328 fData = TStringRef::GetRep(ic, 0)->Data();
00329 }
00330
00331
00332 TString::TString(const char *cs)
00333 {
00334
00335
00336 if (cs) {
00337 Ssiz_t n = strlen(cs);
00338 fData = TStringRef::GetRep(n, n)->Data();
00339 memcpy(fData, cs, n);
00340 } else
00341 fData = TStringRef::GetRep(0, 0)->Data();
00342 }
00343
00344
00345 TString::TString(const std::string &s)
00346 {
00347
00348
00349 Ssiz_t n = s.length();
00350 fData = TStringRef::GetRep(n, n)->Data();
00351 memcpy(fData, s.c_str(), n);
00352 }
00353
00354
00355 TString::TString(const char *cs, Ssiz_t n)
00356 {
00357
00358
00359 fData = TStringRef::GetRep(n, n)->Data();
00360 memcpy(fData, cs, n);
00361 }
00362
00363
00364 void TString::InitChar(char c)
00365 {
00366
00367
00368 fData = TStringRef::GetRep(GetInitialCapacity(), 1)->Data();
00369 fData[0] = c;
00370 }
00371
00372
00373 TString::TString(char c, Ssiz_t n)
00374 {
00375
00376
00377 fData = TStringRef::GetRep(n, n)->Data();
00378 while (n--) fData[n] = c;
00379 }
00380
00381
00382 TString::TString(const TSubString& substr)
00383 {
00384
00385
00386 Ssiz_t len = substr.IsNull() ? 0 : substr.Length();
00387 fData = TStringRef::GetRep(AdjustCapacity(len), len)->Data();
00388 memcpy(fData, substr.Data(), len);
00389 }
00390
00391
00392 TString::~TString()
00393 {
00394
00395
00396 Pref()->UnLink();
00397 }
00398
00399
00400 TString& TString::operator=(char c)
00401 {
00402
00403
00404 if (!c) {
00405 Pref()->UnLink();
00406 gNullStringRef->AddReference();
00407 fData = gNullStringRef->Data();
00408 return *this;
00409 }
00410 return Replace(0, Length(), &c, 1);
00411 }
00412
00413
00414 TString& TString::operator=(const char *cs)
00415 {
00416
00417
00418 if (!cs || !*cs) {
00419 Pref()->UnLink();
00420 gNullStringRef->AddReference();
00421 fData = gNullStringRef->Data();
00422 return *this;
00423 }
00424 return Replace(0, Length(), cs, strlen(cs));
00425 }
00426
00427
00428 TString& TString::operator=(const std::string &s)
00429 {
00430
00431
00432 if (s.length()==0) {
00433 Pref()->UnLink();
00434 gNullStringRef->AddReference();
00435 fData = gNullStringRef->Data();
00436 return *this;
00437 }
00438 return Replace(0, Length(), s.c_str(), s.length());
00439 }
00440
00441
00442 TString& TString::operator=(const TString &str)
00443 {
00444
00445
00446 str.Pref()->AddReference();
00447 Pref()->UnLink();
00448 fData = str.fData;
00449 return *this;
00450 }
00451
00452
00453 TString& TString::operator=(const TSubString &substr)
00454 {
00455
00456
00457 Ssiz_t len = substr.IsNull() ? 0 : substr.Length();
00458 if (!len) {
00459 Pref()->UnLink();
00460 gNullStringRef->AddReference();
00461 fData = gNullStringRef->Data();
00462 return *this;
00463 }
00464 return Replace(0, Length(), substr.Data(), len);
00465 }
00466
00467
00468 TString& TString::Append(char c, Ssiz_t rep)
00469 {
00470
00471
00472 Ssiz_t tot;
00473 Cow(tot = Length() + rep);
00474 char* p = fData + Length();
00475 while (rep--)
00476 *p++ = c;
00477
00478 fData[Pref()->fNchars = tot] = '\0';
00479
00480 return *this;
00481 }
00482
00483
00484 Ssiz_t TString::Capacity(Ssiz_t nc)
00485 {
00486
00487
00488
00489 if (nc > Length() && nc != Capacity())
00490 Clone(nc);
00491
00492 return Capacity();
00493 }
00494
00495
00496 int TString::CompareTo(const char *cs2, ECaseCompare cmp) const
00497 {
00498
00499
00500 if (!cs2) return 1;
00501
00502 const char *cs1 = Data();
00503 Ssiz_t len = Length();
00504 Ssiz_t i = 0;
00505 if (cmp == kExact) {
00506 for (; cs2[i]; ++i) {
00507 if (i == len) return -1;
00508 if (cs1[i] != cs2[i]) return ((cs1[i] > cs2[i]) ? 1 : -1);
00509 }
00510 } else {
00511 for (; cs2[i]; ++i) {
00512 if (i == len) return -1;
00513 char c1 = tolower((unsigned char)cs1[i]);
00514 char c2 = tolower((unsigned char)cs2[i]);
00515 if (c1 != c2) return ((c1 > c2) ? 1 : -1);
00516 }
00517 }
00518 return (i < len) ? 1 : 0;
00519 }
00520
00521
00522 int TString::CompareTo(const TString &str, ECaseCompare cmp) const
00523 {
00524
00525
00526 const char *s1 = Data();
00527 const char *s2 = str.Data();
00528 Ssiz_t len = str.Length();
00529 if (Length() < len) len = Length();
00530 if (cmp == kExact) {
00531 int result = memcmp(s1, s2, len);
00532 if (result != 0) return result;
00533 } else {
00534 Ssiz_t i = 0;
00535 for (; i < len; ++i) {
00536 char c1 = tolower((unsigned char)s1[i]);
00537 char c2 = tolower((unsigned char)s2[i]);
00538 if (c1 != c2) return ((c1 > c2) ? 1 : -1);
00539 }
00540 }
00541
00542 if (Length() == str.Length()) return 0;
00543 return (Length() > str.Length()) ? 1 : -1;
00544 }
00545
00546
00547 Int_t TString::CountChar(Int_t c) const
00548 {
00549
00550
00551 Int_t count = 0;
00552 Int_t len = Length();
00553 for (Int_t n = 0; n < len; n++)
00554 if (fData[n] == c) count++;
00555
00556 return count;
00557 }
00558
00559
00560 TString TString::Copy() const
00561 {
00562
00563
00564 TString temp(*this);
00565 temp.Clone();
00566 return temp;
00567 }
00568
00569
00570 UInt_t TString::Hash(ECaseCompare cmp) const
00571 {
00572
00573
00574 return (cmp == kExact) ? Pref()->Hash() : Pref()->HashFoldCase();
00575 }
00576
00577
00578 UInt_t TString::Hash(const void *txt, Int_t ntxt)
00579 {
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597 static const UInt_t utab[] = {
00598 0xdd367647,0x9caf993f,0x3f3cc5ff,0xfde25082,0x4c764b21,0x89affca7,0x5431965c,0xce22eeec,
00599 0xc61ab4dc,0x59cc93bd,0xed3107e3,0x0b0a287a,0x4712475a,0xce4a4c71,0x352c8403,0x94cb3cee,
00600 0xc3ac509b,0x09f827a2,0xce02e37e,0x7b20bbba,0x76adcedc,0x18c52663,0x19f74103,0x6f30e47b,
00601 0x132ea5a1,0xfdd279e0,0xa3d57d00,0xcff9cb40,0x9617f384,0x6411acfa,0xff908678,0x5c796b2c,
00602 0x4471b62d,0xd38e3275,0xdb57912d,0x26bf953f,0xfc41b2a5,0xe64bcebd,0x190b7839,0x7e8e6a56,
00603 0x9ca22311,0xef28aa60,0xe6b9208e,0xd257fb65,0x45781c2c,0x9a558ac3,0x2743e74d,0x839417a8,
00604 0x06b54d5d,0x1a82bcb4,0x06e97a66,0x70abdd03,0xd163f30d,0x222ed322,0x777bfeda,0xab7a2e83,
00605 0x8494e0cf,0x2dca2d4f,0x78f94278,0x33f04a09,0x402b6452,0x0cd8b709,0xdb72a39e,0x170e00a2,
00606 0x26354faa,0x80e57453,0xcfe8d4e1,0x19e45254,0x04c291c3,0xeb503738,0x425af3bc,0x67836f2a,
00607 0xfac22add,0xfafc2b8c,0x59b8c2a0,0x03e806f9,0xcb4938b9,0xccc942af,0xcee3ae2e,0xfbe748fa,
00608 0xb223a075,0x85c49b5d,0xe4576ac9,0x0fbd46e2,0xb49f9cf5,0xf3e1e86a,0x7d7927fb,0x711afe12,
00609 0xbf61c346,0x157c9956,0x86b6b046,0x2e402146,0xb2a57d8a,0x0d064bb1,0x30ce390c,0x3a3e1eb1,
00610 0xbe7f6f8f,0xd8e30f87,0x5be2813c,0x73a3a901,0xa3aaf967,0x59ff092c,0x1705c798,0xf610dd66,
00611 0xb17da91e,0x8e59534e,0x2211ea5b,0xa804ba03,0xd890efbb,0xb8b48110,0xff390068,0xc8c325b4,
00612 0xf7289c07,0x787e104f,0x3d0df3d0,0x3526796d,0x10548055,0x1d59a42b,0xed1cc5a3,0xdd45372a,
00613 0x31c50d57,0x65757cb7,0x3cfb85be,0xa329910d,0x6ad8ce39,0xa2de44de,0x0dd32432,0xd4a5b617,
00614 0x8f3107fc,0x96485175,0x7f94d4f3,0x35097634,0xdb3ca782,0x2c0290b8,0x2045300b,0xe0f5d15a,
00615 0x0e8cbffa,0xaa1cc38a,0x84008d6f,0xe9a9e794,0x5c602c25,0xfa3658fa,0x98d9d82b,0x3f1497e7,
00616 0x84b6f031,0xe381eff9,0xfc7ae252,0xb239e05d,0xe3723d1f,0xcc3bda82,0xe21b1ad3,0x9104f7c8,
00617 0x4bb2dfcd,0x4d14a8bc,0x6ba7f28c,0x8f89886c,0xad44c97e,0xb30fd975,0x633cdab1,0xf6c2d514,
00618 0x067a49d2,0xdc461ad9,0xebaf9f3f,0x8dc6cac3,0x7a060f16,0xbab063ad,0xf42e25e6,0x60724ca6,
00619 0xc7245c2e,0x4e48ea3c,0x9f89a609,0xa1c49890,0x4bb7f116,0xd722865c,0xa8ee3995,0x0ee070b1,
00620 0xd9bffcc2,0xe55b64f9,0x25507a5a,0xc7a3e2b5,0x5f395f7e,0xe7957652,0x7381ba6a,0xde3d21f1,
00621 0xdf1708dd,0xad0c9d0c,0x00cbc9e5,0x1160e833,0x6779582c,0x29d5d393,0x3f11d7d7,0x826a6b9b,
00622 0xe73ff12f,0x8bad3d86,0xee41d3e5,0x7f0c8917,0x8089ef24,0x90c5cb28,0x2f7f8e6b,0x6966418a,
00623 0x345453fb,0x7a2f8a68,0xf198593d,0xc079a532,0xc1971e81,0x1ab74e26,0x329ef347,0x7423d3d0,
00624 0x942c510b,0x7f6c6382,0x14ae6acc,0x64b59da7,0x2356fa47,0xb6749d9c,0x499de1bb,0x92ffd191,
00625 0xe8f2fb75,0x848dc913,0x3e8727d3,0x1dcffe61,0xb6e45245,0x49055738,0x827a6b55,0xb4788887,
00626 0x7e680125,0xd19ce7ed,0x6b4b8e30,0xa8cadea2,0x216035d8,0x1c63bc3c,0xe1299056,0x1ad3dff4,
00627 0x0aefd13c,0x0e7b921c,0xca0173c6,0x9995782d,0xcccfd494,0xd4b0ac88,0x53d552b1,0x630dae8b,
00628 0xa8332dad,0x7139d9a2,0x5d76f2c4,0x7a4f8f1e,0x8d1aef97,0xd1cf285d,0xc8239153,0xce2608a9,
00629 0x7b562475,0xe4b4bc83,0xf3db0c3a,0x70a65e48,0x6016b302,0xdebd5046,0x707e786a,0x6f10200c
00630 };
00631
00632 static const UInt_t msk[] = { 0x11111111, 0x33333333, 0x77777777, 0xffffffff };
00633
00634 const UChar_t *uc = (const UChar_t *) txt;
00635 UInt_t uu = 0;
00636 union {
00637 UInt_t u;
00638 UShort_t s[2];
00639 } u;
00640 u.u = 0;
00641 Int_t i, idx;
00642
00643 for (i = 0; i < ntxt; i++) {
00644 idx = (uc[i] ^ i) & 255;
00645 uu = (uu << 1) ^ (utab[idx] & msk[i & 3]);
00646 if ((i & 3) == 3) u.u ^= uu;
00647 }
00648 if (i & 3) u.u ^= uu;
00649
00650 u.u *= 1879048201;
00651 u.s[0] += u.s[1];
00652 u.u *= 1979048191;
00653 u.s[1] ^= u.s[0];
00654 u.u *= 2079048197;
00655
00656 return u.u;
00657 }
00658
00659
00660 static int MemIsEqual(const char *p, const char *q, Ssiz_t n)
00661 {
00662
00663
00664 while (n--)
00665 {
00666 if (tolower((unsigned char)*p) != tolower((unsigned char)*q))
00667 return kFALSE;
00668 p++; q++;
00669 }
00670 return kTRUE;
00671 }
00672
00673
00674 Ssiz_t TString::Index(const char *pattern, Ssiz_t plen, Ssiz_t startIndex,
00675 ECaseCompare cmp) const
00676 {
00677
00678
00679
00680
00681 Ssiz_t slen = Length();
00682 if (slen < startIndex + plen) return kNPOS;
00683 if (plen == 0) return startIndex;
00684 slen -= startIndex + plen;
00685 const char *sp = Data() + startIndex;
00686 if (cmp == kExact) {
00687 char first = *pattern;
00688 for (Ssiz_t i = 0; i <= slen; ++i)
00689 if (sp[i] == first && memcmp(sp+i+1, pattern+1, plen-1) == 0)
00690 return i + startIndex;
00691 } else {
00692 int first = tolower((unsigned char) *pattern);
00693 for (Ssiz_t i = 0; i <= slen; ++i)
00694 if (tolower((unsigned char) sp[i]) == first &&
00695 MemIsEqual(sp+i+1, pattern+1, plen-1))
00696 return i + startIndex;
00697 }
00698 return kNPOS;
00699 }
00700
00701
00702 Bool_t TString::MaybeRegexp() const
00703 {
00704
00705
00706 const char *specials = "^$.[]*+?";
00707
00708 if (First(specials) == kNPOS)
00709 return kFALSE;
00710 return kTRUE;
00711 }
00712
00713
00714 Bool_t TString::MaybeWildcard() const
00715 {
00716
00717
00718 const char *specials = "[]*?";
00719
00720 if (First(specials) == kNPOS)
00721 return kFALSE;
00722 return kTRUE;
00723 }
00724
00725
00726 TString& TString::Prepend(char c, Ssiz_t rep)
00727 {
00728
00729
00730 Ssiz_t tot = Length() + rep;
00731
00732
00733 if ( Pref()->References() > 1 || Capacity() < tot ) {
00734 TStringRef *temp = TStringRef::GetRep(AdjustCapacity(tot), tot);
00735 memcpy(temp->Data()+rep, Data(), Length());
00736 Pref()->UnLink();
00737 fData = temp->Data();
00738 } else {
00739 memmove(fData + rep, Data(), Length());
00740 fData[Pref()->fNchars = tot] = '\0';
00741 }
00742
00743 char *p = fData;
00744 while (rep--)
00745 *p++ = c;
00746
00747 return *this;
00748 }
00749
00750
00751 TString &TString::Replace(Ssiz_t pos, Ssiz_t n1, const char *cs, Ssiz_t n2)
00752 {
00753
00754
00755
00756 if (pos <= kNPOS || pos > Length()) {
00757 Error("TString::Replace",
00758 "first argument out of bounds: pos = %d, Length = %d", pos, Length());
00759 return *this;
00760 }
00761
00762 n1 = TMath::Min(n1, Length()-pos);
00763 if (!cs) n2 = 0;
00764
00765 Ssiz_t tot = Length()-n1+n2;
00766 Ssiz_t rem = Length()-n1-pos;
00767
00768
00769
00770 if (Pref()->References() > 1 ||
00771 Capacity() < tot ||
00772 Capacity() - tot > GetMaxWaste() ||
00773 (cs && (cs >= Data() && cs < Data()+Length())))
00774 {
00775 TStringRef *temp = TStringRef::GetRep(AdjustCapacity(tot), tot);
00776 if (pos) memcpy(temp->Data(), Data(), pos);
00777 if (n2 ) memcpy(temp->Data()+pos, cs, n2);
00778 if (rem) memcpy(temp->Data()+pos+n2, Data()+pos+n1, rem);
00779 Pref()->UnLink();
00780 fData = temp->Data();
00781 } else {
00782 if (rem) memmove(fData+pos+n2, Data()+pos+n1, rem);
00783 if (n2 ) memmove(fData+pos , cs, n2);
00784 fData[Pref()->fNchars = tot] = 0;
00785 }
00786
00787 return *this;
00788 }
00789
00790
00791 TString& TString::ReplaceAll(const char *s1, Ssiz_t ls1, const char *s2,
00792 Ssiz_t ls2)
00793 {
00794
00795
00796 if (s1 && ls1 > 0) {
00797 Ssiz_t index = 0;
00798 while ((index = Index(s1,ls1,index, kExact)) != kNPOS) {
00799 Replace(index,ls1,s2,ls2);
00800 index += ls2;
00801 }
00802 }
00803 return *this;
00804 }
00805
00806
00807 TString &TString::Remove(EStripType st, char c)
00808 {
00809
00810
00811
00812 Ssiz_t start = 0;
00813 Ssiz_t end = Length();
00814 const char *direct = Data();
00815 Ssiz_t send = end;
00816
00817 if (st & kLeading)
00818 while (start < end && direct[start] == c)
00819 ++start;
00820 if (st & kTrailing)
00821 while (start < end && direct[end-1] == c)
00822 --end;
00823 if (end == start) {
00824 Pref()->UnLink();
00825 gNullStringRef->AddReference();
00826 fData = gNullStringRef->Data();
00827 return *this;
00828 }
00829 if (start)
00830 Remove(0, start);
00831 if (send != end)
00832 Remove(send - start - (send - end), send - end);
00833 return *this;
00834 }
00835
00836
00837 void TString::Resize(Ssiz_t n)
00838 {
00839
00840
00841 if (n < Length())
00842 Remove(n);
00843 else
00844 Append(' ', n-Length());
00845 }
00846
00847
00848 TSubString TString::Strip(EStripType st, char c) const
00849 {
00850
00851
00852 Ssiz_t start = 0;
00853 Ssiz_t end = Length();
00854 const char *direct = Data();
00855
00856 if (st & kLeading)
00857 while (start < end && direct[start] == c)
00858 ++start;
00859 if (st & kTrailing)
00860 while (start < end && direct[end-1] == c)
00861 --end;
00862 if (end == start) start = end = kNPOS;
00863 return TSubString(*this, start, end-start);
00864 }
00865
00866
00867 void TString::ToLower()
00868 {
00869
00870
00871 Cow();
00872 register Ssiz_t n = Length();
00873 register char *p = fData;
00874 while (n--) {
00875 *p = tolower((unsigned char)*p);
00876 p++;
00877 }
00878 }
00879
00880
00881 void TString::ToUpper()
00882 {
00883
00884
00885 Cow();
00886 register Ssiz_t n = Length();
00887 register char *p = fData;
00888 while (n--) {
00889 *p = toupper((unsigned char)*p);
00890 p++;
00891 }
00892 }
00893
00894
00895 char& TString::operator[](Ssiz_t i)
00896 {
00897
00898
00899 AssertElement(i);
00900 Cow();
00901 return fData[i];
00902 }
00903
00904
00905 void TString::AssertElement(Ssiz_t i) const
00906 {
00907
00908
00909 if (i == kNPOS || i > Length())
00910 Error("TString::AssertElement",
00911 "out of bounds: i = %d, Length = %d", i, Length());
00912 }
00913
00914
00915 TString::TString(const char *a1, Ssiz_t n1, const char *a2, Ssiz_t n2)
00916 {
00917
00918
00919 if (!a1) n1=0;
00920 if (!a2) n2=0;
00921 Ssiz_t tot = n1+n2;
00922 fData = TStringRef::GetRep(AdjustCapacity(tot), tot)->Data();
00923 memcpy(fData, a1, n1);
00924 memcpy(fData+n1, a2, n2);
00925 }
00926
00927
00928 Ssiz_t TString::AdjustCapacity(Ssiz_t nc)
00929 {
00930
00931
00932 Ssiz_t ic = GetInitialCapacity();
00933 if (nc <= ic) return ic;
00934 Ssiz_t rs = GetResizeIncrement();
00935 return (nc - ic + rs - 1) / rs * rs + ic;
00936 }
00937
00938
00939 void TString::Clear()
00940 {
00941
00942
00943 Clobber(Capacity());
00944 }
00945
00946
00947 void TString::Clobber(Ssiz_t nc)
00948 {
00949
00950
00951 if (Pref()->References() > 1 || Capacity() < nc) {
00952 Pref()->UnLink();
00953 fData = TStringRef::GetRep(nc, 0)->Data();
00954 } else
00955 fData[Pref()->fNchars = 0] = 0;
00956 }
00957
00958
00959 void TString::Clone()
00960 {
00961
00962
00963 TStringRef *temp = TStringRef::GetRep(Length(), Length());
00964 memcpy(temp->Data(), Data(), Length());
00965 Pref()->UnLink();
00966 fData = temp->Data();
00967 }
00968
00969
00970 void TString::Clone(Ssiz_t nc)
00971 {
00972
00973
00974
00975 Ssiz_t len = Length();
00976 if (len > nc) len = nc;
00977 TStringRef *temp = TStringRef::GetRep(nc, len);
00978 memcpy(temp->Data(), Data(), len);
00979 Pref()->UnLink();
00980 fData = temp->Data();
00981 }
00982
00983
00984
00985
00986 void TString::FillBuffer(char *&buffer)
00987 {
00988
00989
00990 UChar_t nwh;
00991 Int_t nchars = Length();
00992
00993 if (nchars > 254) {
00994 nwh = 255;
00995 tobuf(buffer, nwh);
00996 tobuf(buffer, nchars);
00997 } else {
00998 nwh = UChar_t(nchars);
00999 tobuf(buffer, nwh);
01000 }
01001 for (int i = 0; i < nchars; i++) buffer[i] = fData[i];
01002 buffer += nchars;
01003 }
01004
01005
01006 void TString::ReadBuffer(char *&buffer)
01007 {
01008
01009
01010 Pref()->UnLink();
01011
01012 UChar_t nwh;
01013 Int_t nchars;
01014
01015 frombuf(buffer, &nwh);
01016 if (nwh == 255)
01017 frombuf(buffer, &nchars);
01018 else
01019 nchars = nwh;
01020
01021 if (nchars < 0) {
01022 Error("ReadBuffer", "found case with nwh=%d and nchars=%d", nwh, nchars);
01023 return;
01024 }
01025 fData = TStringRef::GetRep(nchars, nchars)->Data();
01026
01027 for (int i = 0; i < nchars; i++) frombuf(buffer, &fData[i]);
01028 }
01029
01030
01031 TString *TString::ReadString(TBuffer &b, const TClass *clReq)
01032 {
01033
01034
01035
01036
01037
01038
01039 R__ASSERT(b.IsReading());
01040
01041
01042 b.InitMap();
01043
01044
01045 UInt_t startpos = UInt_t(b.Length());
01046
01047 UInt_t tag;
01048 TClass *clRef = b.ReadClass(clReq, &tag);
01049
01050 TString *a;
01051 if (!clRef) {
01052
01053 a = 0;
01054
01055 } else {
01056
01057 a = (TString *) clRef->New();
01058 if (!a) {
01059 ::Error("TString::ReadObject", "could not create object of class %s",
01060 clRef->GetName());
01061
01062 return a;
01063 }
01064
01065 a->Streamer(b);
01066
01067 b.CheckByteCount(startpos, tag, clRef);
01068 }
01069
01070 return a;
01071 }
01072
01073
01074 Int_t TString::Sizeof() const
01075 {
01076
01077
01078 if (Length() > 254)
01079 return Length()+sizeof(UChar_t)+sizeof(Int_t);
01080 else
01081 return Length()+sizeof(UChar_t);
01082 }
01083
01084
01085 void TString::Streamer(TBuffer &b)
01086 {
01087
01088
01089 Int_t nbig;
01090 UChar_t nwh;
01091 if (b.IsReading()) {
01092 b >> nwh;
01093 if (nwh == 0) {
01094 if (Pref()->References() > 1) {
01095 Pref()->UnLink();
01096 gNullStringRef->AddReference();
01097 fData = gNullStringRef->Data();
01098 } else {
01099
01100 fData[Pref()->fNchars = 0] = 0;
01101 }
01102 } else {
01103 if (nwh == 255)
01104 b >> nbig;
01105 else
01106 nbig = nwh;
01107
01108 if (Pref()->References() > 1 ||
01109 Capacity() < nbig ||
01110 Capacity() - nbig > GetMaxWaste()) {
01111
01112 Pref()->UnLink();
01113
01114
01115
01116 TStringRef *ret = (TStringRef*)new char[nbig + sizeof(TStringRef) + 1];
01117 ret->fCapacity = nbig;
01118 ret->SetRefCount(1);
01119 fData = ret->Data();
01120 }
01121 fData[Pref()->fNchars = nbig] = 0;
01122 b.ReadFastArray(fData,nbig);
01123 }
01124 } else {
01125 nbig = Length();
01126 if (nbig > 254) {
01127 nwh = 255;
01128 b << nwh;
01129 b << nbig;
01130 } else {
01131 nwh = UChar_t(nbig);
01132 b << nwh;
01133 }
01134 b.WriteFastArray(fData,nbig);
01135
01136 }
01137 }
01138
01139
01140 void TString::WriteString(TBuffer &b, const TString *a)
01141 {
01142
01143
01144
01145
01146
01147
01148 R__ASSERT(b.IsWriting());
01149
01150
01151 b.InitMap();
01152
01153 if (!a) {
01154
01155 b << (UInt_t) 0;
01156
01157 } else {
01158
01159
01160 UInt_t cntpos = UInt_t(b.Length());
01161 b.SetBufferOffset(Int_t(cntpos+sizeof(UInt_t)));
01162
01163 TClass *cl = a->IsA();
01164 b.WriteClass(cl);
01165
01166 ((TString *)a)->Streamer(b);
01167
01168
01169 b.SetByteCount(cntpos);
01170 }
01171 }
01172
01173
01174 #if defined(R__TEMPLATE_OVERLOAD_BUG)
01175 template <>
01176 #endif
01177 TBuffer &operator>>(TBuffer &buf, TString *&s)
01178 {
01179
01180
01181 s = (TString *) TString::ReadString(buf, TString::Class());
01182 return buf;
01183 }
01184
01185
01186 TBuffer &operator<<(TBuffer &buf, const TString *s)
01187 {
01188
01189
01190 TString::WriteString(buf, s);
01191 return buf;
01192 }
01193
01194
01195
01196
01197 Bool_t operator==(const TString& s1, const char *s2)
01198 {
01199
01200
01201 if (!s2) return kFALSE;
01202
01203 const char *data = s1.Data();
01204 Ssiz_t len = s1.Length();
01205 Ssiz_t i;
01206 for (i = 0; s2[i]; ++i)
01207 if (data[i] != s2[i] || i == len) return kFALSE;
01208 return (i == len);
01209 }
01210
01211 #if defined(R__ALPHA)
01212
01213 Bool_t operator==(const TString &s1, const TString &s2)
01214 {
01215
01216
01217 return ((s1.Length() == s2.Length()) && !memcmp(s1.Data(), s2.Data(), s1.Length()));
01218 }
01219 #endif
01220
01221
01222 TString ToLower(const TString &str)
01223 {
01224
01225
01226 register Ssiz_t n = str.Length();
01227 TString temp((char)0, n);
01228 register const char *uc = str.Data();
01229 register char *lc = (char*)temp.Data();
01230
01231 while (n--) { *lc++ = tolower((unsigned char)*uc); uc++; }
01232 return temp;
01233 }
01234
01235
01236 TString ToUpper(const TString &str)
01237 {
01238
01239
01240 register Ssiz_t n = str.Length();
01241 TString temp((char)0, n);
01242 register const char* uc = str.Data();
01243 register char* lc = (char*)temp.Data();
01244
01245 while (n--) { *lc++ = toupper((unsigned char)*uc); uc++; }
01246 return temp;
01247 }
01248
01249
01250 TString operator+(const TString &s, const char *cs)
01251 {
01252
01253
01254 return TString(s.Data(), s.Length(), cs, cs ? strlen(cs) : 0);
01255 }
01256
01257
01258 TString operator+(const char *cs, const TString &s)
01259 {
01260
01261
01262 return TString(cs, cs ? strlen(cs) : 0, s.Data(), s.Length());
01263 }
01264
01265
01266 TString operator+(const TString &s1, const TString &s2)
01267 {
01268
01269
01270 return TString(s1.Data(), s1.Length(), s2.Data(), s2.Length());
01271 }
01272
01273
01274 TString operator+(const TString &s, char c)
01275 {
01276
01277
01278 return TString(s.Data(), s.Length(), &c, 1);
01279 }
01280
01281
01282 TString operator+(const TString &s, Long_t i)
01283 {
01284
01285
01286 char si[32];
01287 snprintf(si, sizeof(si), "%ld", i);
01288 return TString(s.Data(), s.Length(), si, strlen(si));
01289 }
01290
01291
01292 TString operator+(const TString &s, ULong_t i)
01293 {
01294
01295
01296 char si[32];
01297 snprintf(si, sizeof(si), "%lu", i);
01298 return TString(s.Data(), s.Length(), si, strlen(si));
01299 }
01300
01301
01302 TString operator+(const TString &s, Long64_t i)
01303 {
01304
01305
01306 char si[32];
01307 snprintf(si, sizeof(si), "%lld", i);
01308 return TString(s.Data(), s.Length(), si, strlen(si));
01309 }
01310
01311
01312 TString operator+(const TString &s, ULong64_t i)
01313 {
01314
01315
01316 char si[32];
01317 snprintf(si, sizeof(si), "%llu", i);
01318 return TString(s.Data(), s.Length(), si, strlen(si));
01319 }
01320
01321
01322 TString operator+(char c, const TString &s)
01323 {
01324
01325
01326 return TString(&c, 1, s.Data(), s.Length());
01327 }
01328
01329
01330 TString operator+(Long_t i, const TString &s)
01331 {
01332
01333
01334 char si[32];
01335 snprintf(si, sizeof(si), "%ld", i);
01336 return TString(si, strlen(si), s.Data(), s.Length());
01337 }
01338
01339
01340 TString operator+(ULong_t i, const TString &s)
01341 {
01342
01343
01344 char si[32];
01345 snprintf(si, sizeof(si), "%lu", i);
01346 return TString(si, strlen(si), s.Data(), s.Length());
01347 }
01348
01349
01350 TString operator+(Long64_t i, const TString &s)
01351 {
01352
01353
01354 char si[32];
01355 snprintf(si, sizeof(si), "%lld", i);
01356 return TString(si, strlen(si), s.Data(), s.Length());
01357 }
01358
01359
01360 TString operator+(ULong64_t i, const TString &s)
01361 {
01362
01363
01364 char si[32];
01365 snprintf(si, sizeof(si), "%llu", i);
01366 return TString(si, strlen(si), s.Data(), s.Length());
01367 }
01368
01369
01370
01371
01372 Ssiz_t TString::fgInitialCapac = 15;
01373 Ssiz_t TString::fgResizeInc = 16;
01374 Ssiz_t TString::fgFreeboard = 15;
01375
01376
01377 Ssiz_t TString::InitialCapacity(Ssiz_t ic)
01378 {
01379
01380
01381 Ssiz_t ret = fgInitialCapac;
01382 fgInitialCapac = ic;
01383 return ret;
01384 }
01385
01386
01387 Ssiz_t TString::ResizeIncrement(Ssiz_t ri)
01388 {
01389
01390
01391 Ssiz_t ret = fgResizeInc;
01392 fgResizeInc = ri;
01393 return ret;
01394 }
01395
01396
01397 Ssiz_t TString::MaxWaste(Ssiz_t mw)
01398 {
01399
01400
01401
01402 Ssiz_t ret = fgFreeboard;
01403 fgFreeboard = mw;
01404 return ret;
01405 }
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425 TSubString::TSubString(const TString &str, Ssiz_t start, Ssiz_t nextent)
01426 : fStr((TString&)str), fBegin(start), fExtent(nextent)
01427 {
01428
01429 }
01430
01431
01432 TSubString TString::operator()(Ssiz_t start, Ssiz_t len) const
01433 {
01434
01435
01436 if (start < Length() && len > 0) {
01437 if (start+len > Length())
01438 len = Length() - start;
01439 } else {
01440 start = kNPOS;
01441 len = 0;
01442 }
01443 return TSubString(*this, start, len);
01444 }
01445
01446
01447 TSubString TString::SubString(const char *pattern, Ssiz_t startIndex,
01448 ECaseCompare cmp) const
01449 {
01450
01451
01452
01453
01454
01455 Ssiz_t len = pattern ? strlen(pattern) : 0;
01456 Ssiz_t i = Index(pattern, len, startIndex, cmp);
01457 return TSubString(*this, i, i == kNPOS ? 0 : len);
01458 }
01459
01460
01461 char& TSubString::operator[](Ssiz_t i)
01462 {
01463
01464
01465 AssertElement(i);
01466 fStr.Cow();
01467 return fStr.fData[fBegin+i];
01468 }
01469
01470
01471 char& TSubString::operator()(Ssiz_t i)
01472 {
01473
01474
01475 fStr.Cow();
01476 return fStr.fData[fBegin+i];
01477 }
01478
01479
01480 TSubString& TSubString::operator=(const TString &str)
01481 {
01482
01483
01484 if (!IsNull())
01485 fStr.Replace(fBegin, fExtent, str.Data(), str.Length());
01486
01487 return *this;
01488 }
01489
01490
01491 TSubString& TSubString::operator=(const char *cs)
01492 {
01493
01494
01495 if (!IsNull())
01496 fStr.Replace(fBegin, fExtent, cs, cs ? strlen(cs) : 0);
01497
01498 return *this;
01499 }
01500
01501
01502 Bool_t operator==(const TSubString& ss, const char *cs)
01503 {
01504
01505
01506 if (ss.IsNull()) return *cs =='\0';
01507
01508 const char* data = ss.fStr.Data() + ss.fBegin;
01509 Ssiz_t i;
01510 for (i = 0; cs[i]; ++i)
01511 if (cs[i] != data[i] || i == ss.fExtent) return kFALSE;
01512 return (i == ss.fExtent);
01513 }
01514
01515
01516 Bool_t operator==(const TSubString& ss, const TString &s)
01517 {
01518
01519
01520 if (ss.IsNull()) return s.IsNull();
01521 if (ss.fExtent != s.Length()) return kFALSE;
01522 return !memcmp(ss.fStr.Data() + ss.fBegin, s.Data(), ss.fExtent);
01523 }
01524
01525
01526 Bool_t operator==(const TSubString &s1, const TSubString &s2)
01527 {
01528
01529
01530 if (s1.IsNull()) return s2.IsNull();
01531 if (s1.fExtent != s2.fExtent) return kFALSE;
01532 return !memcmp(s1.fStr.Data()+s1.fBegin, s2.fStr.Data()+s2.fBegin,
01533 s1.fExtent);
01534 }
01535
01536
01537 void TSubString::ToLower()
01538 {
01539
01540
01541 if (!IsNull()) {
01542 fStr.Cow();
01543 register char *p = (char*)(fStr.Data() + fBegin);
01544 Ssiz_t n = fExtent;
01545 while (n--) { *p = tolower((unsigned char)*p); p++;}
01546 }
01547 }
01548
01549
01550 void TSubString::ToUpper()
01551 {
01552
01553 if (!IsNull()) {
01554 fStr.Cow();
01555 register char *p = (char*)(fStr.Data() + fBegin);
01556 Ssiz_t n = fExtent;
01557 while (n--) { *p = toupper((unsigned char)*p); p++;}
01558 }
01559 }
01560
01561
01562 void TSubString::SubStringError(Ssiz_t sr, Ssiz_t start, Ssiz_t n) const
01563 {
01564
01565
01566 Error("TSubString::SubStringError",
01567 "out of bounds: start = %d, n = %d, sr = %d", start, n, sr);
01568 }
01569
01570
01571 void TSubString::AssertElement(Ssiz_t i) const
01572 {
01573
01574
01575 if (i == kNPOS || i >= Length())
01576 Error("TSubString::AssertElement",
01577 "out of bounds: i = %d, Length = %d", i, Length());
01578 }
01579
01580
01581 Bool_t TString::IsAscii() const
01582 {
01583
01584
01585 const char *cp = Data();
01586 for (Ssiz_t i = 0; i < Length(); ++i)
01587 if (cp[i] & ~0x7F)
01588 return kFALSE;
01589 return kTRUE;
01590 }
01591
01592
01593 Bool_t TString::IsAlpha() const
01594 {
01595
01596
01597
01598 const char *cp = Data();
01599 Ssiz_t len = Length();
01600 if (len == 0) return kFALSE;
01601 for (Ssiz_t i = 0; i < len; ++i)
01602 if (!isalpha(cp[i]))
01603 return kFALSE;
01604 return kTRUE;
01605 }
01606
01607
01608 Bool_t TString::IsAlnum() const
01609 {
01610
01611
01612
01613 const char *cp = Data();
01614 Ssiz_t len = Length();
01615 if (len == 0) return kFALSE;
01616 for (Ssiz_t i = 0; i < len; ++i)
01617 if (!isalnum(cp[i]))
01618 return kFALSE;
01619 return kTRUE;
01620 }
01621
01622
01623 Bool_t TString::IsDigit() const
01624 {
01625
01626
01627
01628
01629
01630 const char *cp = Data();
01631 Ssiz_t len = Length();
01632 if (len == 0) return kFALSE;
01633 Int_t b = 0, d = 0;
01634 for (Ssiz_t i = 0; i < len; ++i) {
01635 if (cp[i] != ' ' && !isdigit(cp[i])) return kFALSE;
01636 if (cp[i] == ' ') b++;
01637 if (isdigit(cp[i])) d++;
01638 }
01639 if (b && !d)
01640 return kFALSE;
01641 return kTRUE;
01642 }
01643
01644
01645 Bool_t TString::IsFloat() const
01646 {
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657 if (IsDigit()) return kTRUE;
01658
01659 TString tmp = *this;
01660
01661
01662 Int_t i_dot, i_e, i_plus, i_minus, i_comma;
01663 i_dot = i_e = i_plus = i_minus = i_comma = -1;
01664
01665 i_dot = tmp.First('.');
01666 if (i_dot > -1) tmp.Replace(i_dot, 1, " ", 1);
01667 i_comma = tmp.First(',');
01668 if (i_comma > -1) tmp.Replace(i_comma, 1, " ", 1);
01669 i_e = tmp.First('e');
01670 if (i_e > -1)
01671 tmp.Replace(i_e, 1, " ", 1);
01672 else {
01673
01674 i_e = tmp.First('E');
01675 if (i_e > -1) tmp.Replace(i_e, 1, " ", 1);
01676 }
01677 i_plus = tmp.First('+');
01678 if (i_plus > -1) tmp.ReplaceAll("+", " ");
01679 i_minus = tmp.First('-');
01680 if (i_minus > -1) tmp.ReplaceAll("-", " ");
01681
01682
01683 return tmp.IsDigit();
01684 }
01685
01686
01687 Bool_t TString::IsHex() const
01688 {
01689
01690
01691
01692
01693 const char *cp = Data();
01694 Ssiz_t len = Length();
01695 if (len == 0) return kFALSE;
01696 for (Ssiz_t i = 0; i < len; ++i)
01697 if (!isxdigit(cp[i]))
01698 return kFALSE;
01699 return kTRUE;
01700 }
01701
01702
01703 Int_t TString::Atoi() const
01704 {
01705
01706
01707
01708
01709
01710
01711 Int_t end = Index(" ");
01712
01713 if (end == -1) return atoi(Data());
01714
01715 Int_t start = 0;
01716 TString tmp;
01717
01718 while (end > -1) {
01719 tmp += (*this)(start, end-start);
01720 start = end+1; end = Index(" ", start);
01721 }
01722
01723 end = Length();
01724 tmp += (*this)(start, end-start);
01725 return atoi(tmp.Data());
01726 }
01727
01728
01729 Long64_t TString::Atoll() const
01730 {
01731
01732
01733
01734
01735
01736
01737 Int_t end = Index(" ");
01738
01739 #ifndef R__WIN32
01740 if (end == -1) return atoll(Data());
01741 #else
01742 if (end == -1) return _atoi64(Data());
01743 #endif
01744
01745 Int_t start = 0;
01746 TString tmp;
01747
01748 while (end > -1) {
01749 tmp += (*this)(start, end-start);
01750 start = end+1; end = Index(" ", start);
01751 }
01752
01753 end = Length();
01754 tmp += (*this)(start, end-start);
01755 #ifndef R__WIN32
01756 return atoll(tmp.Data());
01757 #else
01758 return _atoi64(tmp.Data());
01759 #endif
01760 }
01761
01762
01763 Double_t TString::Atof() const
01764 {
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775 Int_t comma = Index(",");
01776 Int_t end = Index(" ");
01777
01778 if (comma == -1 && end == -1) return atof(Data());
01779 TString tmp = *this;
01780 if (comma > -1) {
01781
01782 tmp.Replace(comma, 1, ".");
01783 }
01784
01785 if (end == -1) return atof(tmp.Data());
01786
01787 Int_t start = 0;
01788 TString tmp2;
01789 while (end > -1) {
01790 tmp2 += tmp(start, end-start);
01791 start = end+1; end = tmp.Index(" ", start);
01792 }
01793 end = tmp.Length();
01794 tmp2 += tmp(start, end-start);
01795 return atof(tmp2.Data());
01796 }
01797
01798
01799 Bool_t TString::EndsWith(const char *s, ECaseCompare cmp) const
01800 {
01801
01802
01803 if (!s) return kTRUE;
01804
01805 Ssiz_t l = strlen(s);
01806 if (l > Length()) return kFALSE;
01807 const char *s2 = Data() + Length() - l;
01808
01809 if (cmp == kExact)
01810 return strcmp(s, s2) == 0;
01811 return strcasecmp(s, s2) == 0;
01812 }
01813
01814
01815 TObjArray *TString::Tokenize(const TString &delim) const
01816 {
01817
01818
01819
01820
01821
01822
01823 std::list<Int_t> splitIndex;
01824
01825 Int_t i, start, nrDiff = 0;
01826 for (i = 0; i < delim.Length(); i++) {
01827 start = 0;
01828 while (start < Length()) {
01829 Int_t pos = Index(delim(i), start);
01830 if (pos == kNPOS) break;
01831 splitIndex.push_back(pos);
01832 start = pos + 1;
01833 }
01834 if (start > 0) nrDiff++;
01835 }
01836 splitIndex.push_back(Length());
01837
01838 if (nrDiff > 1)
01839 splitIndex.sort();
01840
01841 TObjArray *arr = new TObjArray();
01842 arr->SetOwner();
01843
01844 start = -1;
01845 std::list<Int_t>::const_iterator it;
01846 #ifndef R__HPUX
01847 for (it = splitIndex.begin(); it != splitIndex.end(); it++) {
01848 #else
01849 for (it = splitIndex.begin(); it != (std::list<Int_t>::const_iterator) splitIndex.end(); it++) {
01850 #endif
01851 Int_t stop = *it;
01852 if (stop - 1 >= start + 1) {
01853 TString tok = (*this)(start+1, stop-start-1);
01854 TObjString *objstr = new TObjString(tok);
01855 arr->Add(objstr);
01856 }
01857 start = stop;
01858 }
01859
01860 return arr;
01861 }
01862
01863
01864 void TString::FormImp(const char *fmt, va_list ap)
01865 {
01866
01867
01868
01869 Ssiz_t buflen = 20 + 20 * strlen(fmt);
01870 Clobber(buflen);
01871
01872 va_list sap;
01873 R__VA_COPY(sap, ap);
01874
01875 int n, vc = 0;
01876 again:
01877 n = vsnprintf(fData, buflen, fmt, ap);
01878
01879
01880 if (n == -1 || n >= buflen) {
01881 if (n == -1)
01882 buflen *= 2;
01883 else
01884 buflen = n+1;
01885 Clobber(buflen);
01886 va_end(ap);
01887 R__VA_COPY(ap, sap);
01888 vc = 1;
01889 goto again;
01890 }
01891 va_end(sap);
01892 if (vc)
01893 va_end(ap);
01894
01895 Pref()->fNchars = strlen(fData);
01896 }
01897
01898
01899 void TString::Form(const char *va_(fmt), ...)
01900 {
01901
01902
01903
01904 va_list ap;
01905 va_start(ap, va_(fmt));
01906 FormImp(va_(fmt), ap);
01907 va_end(ap);
01908 }
01909
01910
01911 TString TString::Format(const char *va_(fmt), ...)
01912 {
01913
01914
01915
01916
01917 va_list ap;
01918 va_start(ap, va_(fmt));
01919 TString str;
01920 str.FormImp(va_(fmt), ap);
01921 va_end(ap);
01922 return str;
01923 }
01924
01925
01926
01927 static const int cb_size = 4096;
01928 static const int fld_size = 2048;
01929
01930
01931 static char gFormbuf[cb_size];
01932 static char *gBfree = gFormbuf;
01933 static char *gEndbuf = &gFormbuf[cb_size-1];
01934
01935
01936 static char *SlowFormat(const char *format, va_list ap, int hint)
01937 {
01938
01939
01940
01941 static char *slowBuffer = 0;
01942 static int slowBufferSize = 0;
01943
01944 R__LOCKGUARD2(gStringMutex);
01945
01946 if (hint == -1) hint = fld_size;
01947 if (hint > slowBufferSize) {
01948 delete [] slowBuffer;
01949 slowBufferSize = 2 * hint;
01950 if (hint < 0 || slowBufferSize < 0) {
01951 slowBufferSize = 0;
01952 slowBuffer = 0;
01953 return 0;
01954 }
01955 slowBuffer = new char[slowBufferSize];
01956 }
01957
01958 va_list sap;
01959 R__VA_COPY(sap, ap);
01960
01961 int n = vsnprintf(slowBuffer, slowBufferSize, format, ap);
01962
01963
01964 if (n == -1 || n >= slowBufferSize) {
01965 if (n == -1) n = 2 * slowBufferSize;
01966 if (n == slowBufferSize) n++;
01967 if (n <= 0) {
01968 va_end(sap);
01969 return 0;
01970 }
01971 va_end(ap);
01972 R__VA_COPY(ap, sap);
01973 char *buf = SlowFormat(format, ap, n);
01974 va_end(sap);
01975 va_end(ap);
01976 return buf;
01977 }
01978
01979 va_end(sap);
01980
01981 return slowBuffer;
01982 }
01983
01984
01985 static char *Format(const char *format, va_list ap)
01986 {
01987
01988
01989
01990 R__LOCKGUARD2(gStringMutex);
01991
01992 char *buf = gBfree;
01993
01994 if (buf+fld_size > gEndbuf)
01995 buf = gFormbuf;
01996
01997 va_list sap;
01998 R__VA_COPY(sap, ap);
01999
02000 int n = vsnprintf(buf, fld_size, format, ap);
02001
02002
02003 if (n == -1 || n >= fld_size) {
02004 va_end(ap);
02005 R__VA_COPY(ap, sap);
02006 buf = SlowFormat(format, ap, n);
02007 va_end(sap);
02008 va_end(ap);
02009 return buf;
02010 }
02011
02012 va_end(sap);
02013
02014 gBfree = buf+n+1;
02015 return buf;
02016 }
02017
02018
02019 char *Form(const char *va_(fmt), ...)
02020 {
02021
02022
02023
02024
02025
02026
02027 va_list ap;
02028 va_start(ap,va_(fmt));
02029 char *b = Format(va_(fmt), ap);
02030 va_end(ap);
02031 return b;
02032 }
02033
02034
02035 void Printf(const char *va_(fmt), ...)
02036 {
02037
02038
02039
02040
02041 va_list ap;
02042 va_start(ap,va_(fmt));
02043 if (gPrintViaErrorHandler)
02044 ErrorHandler(kPrint, 0, va_(fmt), ap);
02045 else {
02046 char *b = Format(va_(fmt), ap);
02047 printf("%s\n", b);
02048 fflush(stdout);
02049 }
02050 va_end(ap);
02051 }
02052
02053
02054 char *Strip(const char *s, char c)
02055 {
02056
02057
02058
02059 if (!s) return 0;
02060
02061 int l = strlen(s);
02062 char *buf = new char[l+1];
02063
02064 if (l == 0) {
02065 *buf = '\0';
02066 return buf;
02067 }
02068
02069
02070 const char *t1 = s;
02071 while (*t1 == c)
02072 t1++;
02073
02074
02075 const char *t2 = s + l - 1;
02076 while (*t2 == c && t2 > s)
02077 t2--;
02078
02079 if (t1 > t2) {
02080 *buf = '\0';
02081 return buf;
02082 }
02083 strncpy(buf, t1, (Ssiz_t) (t2-t1+1));
02084 *(buf+(t2-t1+1)) = '\0';
02085
02086 return buf;
02087 }
02088
02089
02090 char *StrDup(const char *str)
02091 {
02092
02093
02094
02095 if (!str) return 0;
02096
02097 char *s = new char[strlen(str)+1];
02098 if (s) strcpy(s, str);
02099
02100 return s;
02101 }
02102
02103
02104 char *Compress(const char *str)
02105 {
02106
02107
02108
02109 if (!str) return 0;
02110
02111 const char *p = str;
02112 char *s, *s1 = new char[strlen(str)+1];
02113 s = s1;
02114
02115 while (*p) {
02116 if (*p != ' ')
02117 *s++ = *p;
02118 p++;
02119 }
02120 *s = '\0';
02121
02122 return s1;
02123 }
02124
02125
02126 int EscChar(const char *src, char *dst, int dstlen, char *specchars,
02127 char escchar)
02128 {
02129
02130
02131 const char *p;
02132 char *q, *end = dst+dstlen-1;
02133
02134 for (p = src, q = dst; *p && q < end; ) {
02135 if (strchr(specchars, *p)) {
02136 *q++ = escchar;
02137 if (q < end)
02138 *q++ = *p++;
02139 } else
02140 *q++ = *p++;
02141 }
02142 *q = '\0';
02143
02144 if (*p != 0)
02145 return -1;
02146 return q-dst;
02147 }
02148
02149
02150 int UnEscChar(const char *src, char *dst, int dstlen, char *specchars, char)
02151 {
02152
02153
02154 const char *p;
02155 char *q, *end = dst+dstlen-1;
02156
02157 for (p = src, q = dst; *p && q < end; ) {
02158 if (strchr(specchars, *p))
02159 p++;
02160 else
02161 *q++ = *p++;
02162 }
02163 *q = '\0';
02164
02165 if (*p != 0)
02166 return -1;
02167 return q-dst;
02168 }
02169
02170 #ifdef NEED_STRCASECMP
02171
02172 int strcasecmp(const char *str1, const char *str2)
02173 {
02174
02175
02176 return strncasecmp(str1, str2, str2 ? strlen(str2)+1 : 0);
02177 }
02178
02179
02180 int strncasecmp(const char *str1, const char *str2, Ssiz_t n)
02181 {
02182
02183
02184 while (n > 0) {
02185 int c1 = *str1;
02186 int c2 = *str2;
02187
02188 if (isupper(c1))
02189 c1 = tolower(c1);
02190
02191 if (isupper(c2))
02192 c2 = tolower(c2);
02193
02194 if (c1 != c2)
02195 return c1 - c2;
02196
02197 str1++;
02198 str2++;
02199 n--;
02200 }
02201 return 0;
02202 }
02203 #endif