58 #define strtoull _strtoui64
62 namespace std { using ::list; }
68 const UInt_t kHashShift = 5;
95 TString::TString(Ssiz_t ic)
103 TString::TString(
const char *cs)
106 Ssiz_t n = strlen(cs);
107 char *data = Init(n, n);
116 TString::TString(
const std::string &s)
118 Ssiz_t n = s.length();
119 char *data = Init(n, n);
120 memcpy(data, s.c_str(), n);
126 TString::TString(
const char *cs, Ssiz_t n)
129 Error(
"TString::TString",
"Negative length!");
132 char *data = Init(n, n);
139 void TString::InitChar(
char c)
141 char *data = Init(1, 1);
148 TString::TString(
char c)
156 TString::TString(
char c, Ssiz_t n)
158 char *data = Init(n, n);
159 while (n--) data[n] = c;
165 TString::TString(
const TString &s)
168 fRep.fRaw = s.fRep.fRaw;
170 Ssiz_t n = s.GetLongSize();
171 char *data = Init(n, n);
172 memcpy(data, s.GetLongPointer(), n);
179 TString::TString(TString &&s) noexcept
182 fRep.fRaw = s.fRep.fRaw;
189 TString::TString(
const std::string_view& substr)
191 Ssiz_t len = substr.length();
192 char *data = Init(len, len);
193 memcpy(data, substr.data(), len);
199 TString::TString(
const TSubString& substr)
201 Ssiz_t len = substr.IsNull() ? 0 : substr.Length();
202 char *data = Init(len, len);
203 memcpy(data, substr.Data(), len);
209 TString::TString(
const char *a1, Ssiz_t n1,
const char *a2, Ssiz_t n2)
212 Error(
"TString::TString",
"Negative first length!");
216 Error(
"TString::TString",
"Negative second length!");
222 char *data = Init(tot, tot);
223 memcpy(data, a1, n1);
224 memcpy(data+n1, a2, n2);
239 char *TString::Init(Ssiz_t capacity, Ssiz_t nchar)
241 if (capacity > MaxSize()) {
242 Error(
"TString::Init",
"capacity too large (%d, max = %d)", capacity, MaxSize());
243 capacity = MaxSize();
244 if (nchar > capacity)
249 if (capacity < kMinCap) {
251 data = GetShortPointer();
253 Ssiz_t cap = Recommend(capacity);
254 data =
new char[cap+1];
257 SetLongPointer(data);
267 TString& TString::operator=(
char c)
274 return Replace(0, Length(), &c, 1);
280 TString& TString::operator=(
const char *cs)
287 return Replace(0, Length(), cs, strlen(cs));
293 TString& TString::operator=(
const std::string &s)
300 return Replace(0, Length(), s.c_str(), s.length());
306 TString& TString::operator=(
const std::string_view &s)
313 return Replace(0, Length(), s.data(), s.length());
319 TString& TString::operator=(
const TString &rhs)
324 fRep.fRaw = rhs.fRep.fRaw;
326 Ssiz_t n = rhs.GetLongSize();
327 char *data = Init(n, n);
328 memcpy(data, rhs.GetLongPointer(), n);
337 TString& TString::operator=(TString &&rhs) noexcept
340 fRep.fRaw = rhs.fRep.fRaw;
348 TString& TString::operator=(
const TSubString &substr)
350 Ssiz_t len = substr.IsNull() ? 0 : substr.Length();
356 return Replace(0, Length(), substr.Data(), len);
362 TString& TString::Append(
char c, Ssiz_t rep)
364 if (!rep)
return *
this;
366 Ssiz_t len = Length();
367 Ssiz_t tot = len + rep;
369 if (tot > MaxSize()) {
370 Error(
"TString::Append",
"rep too large (%d, max = %d)", rep, MaxSize()-len);
375 Ssiz_t capac = Capacity();
376 char *data, *p = GetPointer();
378 if (capac - tot >= 0) {
382 Ssiz_t cap = AdjustCapacity(capac, tot);
383 data =
new char[cap+1];
384 memcpy(data, p, len);
388 SetLongPointer(data);
403 Ssiz_t TString::Capacity(Ssiz_t nc)
418 int TString::CompareTo(
const char *cs2, ECaseCompare cmp)
const
422 const char *cs1 = Data();
423 Ssiz_t len = Length();
426 for (; cs2[i]; ++i) {
427 if (i == len)
return -1;
428 if (cs1[i] != cs2[i])
return ((cs1[i] > cs2[i]) ? 1 : -1);
431 for (; cs2[i]; ++i) {
432 if (i == len)
return -1;
433 char c1 = tolower((
unsigned char)cs1[i]);
434 char c2 = tolower((
unsigned char)cs2[i]);
435 if (c1 != c2)
return ((c1 > c2) ? 1 : -1);
438 return (i < len) ? 1 : 0;
448 int TString::CompareTo(
const TString &str, ECaseCompare cmp)
const
450 const char *s1 = Data();
451 const char *s2 = str.Data();
452 Ssiz_t len = Length();
453 Ssiz_t slen, sleno = str.Length();
455 if (len < slen) slen = len;
457 int result = memcmp(s1, s2, slen);
458 if (result != 0)
return result;
461 for (; i < slen; ++i) {
462 char c1 = tolower((
unsigned char)s1[i]);
463 char c2 = tolower((
unsigned char)s2[i]);
464 if (c1 != c2)
return ((c1 > c2) ? 1 : -1);
469 if (len == slen)
return 0;
470 return (len > slen) ? 1 : -1;
476 Int_t TString::CountChar(Int_t c)
const
479 Int_t len = Length();
480 const char *data = Data();
481 for (Int_t n = 0; n < len; n++)
482 if (data[n] == c) count++;
490 TString TString::Copy()
const
499 Ssiz_t TString::First(
char c)
const
501 const char *f = strchr(Data(), c);
502 return f ? f - Data() : kNPOS;
508 Ssiz_t TString::First(
const char *cs)
const
510 const char *f = strpbrk(Data(), cs);
511 return f ? f - Data() : kNPOS;
517 inline static UInt_t SwapInt(UInt_t x)
519 return (((x & 0x000000ffU) << 24) | ((x & 0x0000ff00U) << 8) |
520 ((x & 0x00ff0000U) >> 8) | ((x & 0xff000000U) >> 24));
527 inline static void Mash(UInt_t& hash, UInt_t chars)
530 ((hash << kHashShift) |
531 (hash >> (kBitsPerByte*
sizeof(UInt_t) - kHashShift))));
537 UInt_t Hash(
const char *str)
539 UInt_t len = str ? strlen(str) : 0;
541 UInt_t i = hv*
sizeof(char)/
sizeof(UInt_t);
543 if (((ULong_t)str)%
sizeof(UInt_t) == 0) {
545 const UInt_t *p = (
const UInt_t*)str;
550 Mash(hv, SwapInt(h));
557 if ((i = len*
sizeof(
char)%
sizeof(UInt_t)) != 0) {
559 const char* c = (
const char*)p;
561 h = ((h << kBitsPerByte*
sizeof(char)) | *c++);
567 const unsigned char *p = (
const unsigned char*)str;
570 memcpy(&h, p,
sizeof(UInt_t));
572 Mash(hv, SwapInt(h));
580 if ((i = len*
sizeof(
char)%
sizeof(UInt_t)) != 0) {
582 const char* c = (
const char*)p;
584 h = ((h << kBitsPerByte*
sizeof(char)) | *c++);
594 UInt_t TString::HashCase()
const
596 UInt_t hv = (UInt_t)Length();
597 UInt_t i = hv*
sizeof(char)/
sizeof(UInt_t);
598 const UInt_t *p = (
const UInt_t*)Data();
603 Mash(hv, SwapInt(h));
610 if ((i = Length()*
sizeof(
char)%
sizeof(UInt_t)) != 0) {
612 const char* c = (
const char*)p;
614 h = ((h << kBitsPerByte*
sizeof(char)) | *c++);
623 UInt_t TString::HashFoldCase()
const
625 UInt_t hv = (UInt_t)Length();
627 const unsigned char *p = (
const unsigned char*)Data();
629 Mash(hv, toupper(*p));
638 UInt_t TString::Hash(ECaseCompare cmp)
const
640 return (cmp == kExact) ? HashCase() : HashFoldCase();
663 #if defined(_MSC_VER) && (_MSC_VER < 1800)
665 typedef unsigned char uint8_t;
666 typedef unsigned long uint32_t;
667 typedef unsigned __int64 uint64_t;
668 #else // defined(_MSC_VER)
671 #endif // !defined(_MSC_VER)
674 #if defined(_MSC_VER)
677 #define ROTL64(x,y) _rotl64(x,y)
678 #define BIG_CONSTANT(x) (x)
679 #else // defined(_MSC_VER)
681 inline uint64_t rotl64 ( uint64_t x, int8_t r )
683 return (x << r) | (x >> (64 - r));
686 #define ROTL64(x,y) rotl64(x,y)
687 #define BIG_CONSTANT(x) (x##LLU)
688 #endif // !defined(_MSC_VER)
696 R__ALWAYS_INLINE uint64_t getblock(
const uint64_t* p,
int i)
704 R__ALWAYS_INLINE uint64_t fmix(uint64_t k)
707 k *= BIG_CONSTANT(0xff51afd7ed558ccd);
709 k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);
721 static void MurmurHash3_x64_128(
const void * key,
const int len,
722 const uint32_t seed, uint64_t out[2] )
724 const uint8_t * data = (
const uint8_t*)key;
725 const int nblocks = len / 16;
730 uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5);
731 uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f);
736 const uint64_t * blocks = (
const uint64_t *)(data);
738 for(
int i = 0; i < nblocks; i++)
740 uint64_t k1 = getblock(blocks,i*2+0);
741 uint64_t k2 = getblock(blocks,i*2+1);
743 k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
745 h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;
747 k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
749 h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
755 const uint8_t * tail = (
const uint8_t*)(data + nblocks*16);
761 case 15: k2 ^= uint64_t(tail[14]) << 48;
762 case 14: k2 ^= uint64_t(tail[13]) << 40;
763 case 13: k2 ^= uint64_t(tail[12]) << 32;
764 case 12: k2 ^= uint64_t(tail[11]) << 24;
765 case 11: k2 ^= uint64_t(tail[10]) << 16;
766 case 10: k2 ^= uint64_t(tail[ 9]) << 8;
767 case 9: k2 ^= uint64_t(tail[ 8]) << 0;
768 k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
770 case 8: k1 ^= uint64_t(tail[ 7]) << 56;
771 case 7: k1 ^= uint64_t(tail[ 6]) << 48;
772 case 6: k1 ^= uint64_t(tail[ 5]) << 40;
773 case 5: k1 ^= uint64_t(tail[ 4]) << 32;
774 case 4: k1 ^= uint64_t(tail[ 3]) << 24;
775 case 3: k1 ^= uint64_t(tail[ 2]) << 16;
776 case 2: k1 ^= uint64_t(tail[ 1]) << 8;
777 case 1: k1 ^= uint64_t(tail[ 0]) << 0;
778 k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
784 h1 ^= len; h2 ^= len;
795 ((uint64_t*)out)[0] = h1;
796 ((uint64_t*)out)[1] = h2;
811 UInt_t TString::Hash(
const void *txt, Int_t ntxt)
813 if (ntxt !=
sizeof(
void*)) {
814 uint64_t buf[2] = {0};
815 MurmurHash3_x64_128(txt, ntxt, 0x6384BA69, buf);
816 return (UInt_t) buf[0];
819 UInt_t ret = (UInt_t)0x6384BA69;
821 if (((
size_t)txt) %
sizeof(
void*)) {
822 UInt_t* itxt = (UInt_t*)txt;
824 if (
sizeof(
void*) >
sizeof(UInt_t)) {
828 const unsigned char* ctxt = (
const unsigned char*) txt;
829 for (
unsigned int i = 0; i < 4; ++i) {
830 ret ^= ctxt[i] << (i * 8);
832 if (
sizeof(
void*) >
sizeof(UInt_t)) {
834 for (
unsigned int i = 0; i < 4; ++i) {
835 ret ^= ctxt[i] << (i * 8);
846 static int MemIsEqual(
const char *p,
const char *q, Ssiz_t n)
850 if (tolower((
unsigned char)*p) != tolower((
unsigned char)*q))
862 Ssiz_t TString::Index(
const char *pattern, Ssiz_t plen, Ssiz_t startIndex,
863 ECaseCompare cmp)
const
866 Error(
"TString::Index",
"Negative first pattern length!");
869 Ssiz_t slen = Length();
870 if (slen < startIndex + plen)
return kNPOS;
871 if (plen == 0)
return startIndex;
872 slen -= startIndex + plen;
873 const char *sp = Data() + startIndex;
875 char first = *pattern;
876 for (Ssiz_t i = 0; i <= slen; ++i)
877 if (sp[i] == first && memcmp(sp+i+1, pattern+1, plen-1) == 0)
878 return i + startIndex;
880 int first = tolower((
unsigned char) *pattern);
881 for (Ssiz_t i = 0; i <= slen; ++i)
882 if (tolower((
unsigned char) sp[i]) == first &&
883 MemIsEqual(sp+i+1, pattern+1, plen-1))
884 return i + startIndex;
892 Ssiz_t TString::Last(
char c)
const
894 const char *f = strrchr(Data(), (
unsigned char) c);
895 return f ? f - Data() : kNPOS;
901 TString TString::MD5()
const
904 md5.Update((
const UChar_t*)Data(), Length());
907 return md5.AsString();
913 Bool_t TString::MaybeRegexp()
const
915 const char *specials =
"^$.[]*+?";
917 if (First(specials) == kNPOS)
925 Bool_t TString::MaybeWildcard()
const
927 const char *specials =
"[]*?";
929 if (First(specials) == kNPOS)
937 TString& TString::Prepend(
char c, Ssiz_t rep)
942 Ssiz_t len = Length();
943 Ssiz_t tot = len + rep;
945 if (tot > MaxSize()) {
946 Error(
"TString::Prepend",
"rep too large (%d, max = %d)", rep, MaxSize()-len);
951 Ssiz_t capac = Capacity();
952 char *data, *p = GetPointer();
954 if (capac - tot >= 0) {
955 memmove(p + rep, p, len);
959 Ssiz_t cap = AdjustCapacity(capac, tot);
960 data =
new char[cap+1];
961 memcpy(data+rep, p, len);
965 SetLongPointer(data);
979 TString &TString::Replace(Ssiz_t pos, Ssiz_t n1,
const char *cs, Ssiz_t n2)
981 Ssiz_t len = Length();
982 if (pos <= kNPOS || pos > len) {
983 Error(
"TString::Replace",
984 "first argument out of bounds: pos = %d, Length = %d", pos, len);
988 Error(
"TString::Replace",
"Negative number of characters to remove!");
992 Error(
"TString::Replace",
"Negative number of replacement characters!");
996 n1 = TMath::Min(n1, len - pos);
999 Ssiz_t tot = len - n1 + n2;
1000 Ssiz_t rem = len - n1 - pos;
1002 Ssiz_t capac = Capacity();
1003 char *p = GetPointer();
1005 if (capac - len + n1 >= n2) {
1009 if (n2) memmove(p + pos, cs, n2);
1010 memmove(p + pos + n2, p + pos + n1, rem);
1013 if (p + pos < cs && cs < p + len) {
1014 if (p + pos + n1 <= cs)
1017 memmove(p + pos, cs, n1);
1024 memmove(p + pos + n2, p + pos + n1, rem);
1027 if (n2) memmove(p + pos, cs, n2);
1032 Ssiz_t cap = AdjustCapacity(capac, tot);
1033 char *data =
new char[cap+1];
1034 if (pos) memcpy(data, p, pos);
1035 if (n2 ) memcpy(data + pos, cs, n2);
1036 if (rem) memcpy(data + pos + n2, p + pos + n1, rem);
1040 SetLongPointer(data);
1050 TString& TString::ReplaceAll(
const char *s1, Ssiz_t ls1,
const char *s2,
1053 if (s1 && ls1 > 0) {
1055 while ((index = Index(s1, ls1, index, kExact)) != kNPOS) {
1056 Replace(index, ls1, s2, ls2);
1067 TString &TString::Remove(EStripType st,
char c)
1070 Ssiz_t end = Length();
1071 const char *direct = Data();
1075 while (start < end && direct[start] == c)
1078 while (start < end && direct[end-1] == c)
1088 Remove(send - start - (send - end), send - end);
1095 void TString::Resize(Ssiz_t n)
1100 Append(
' ', n-Length());
1106 TSubString TString::Strip(EStripType st,
char c)
const
1109 Ssiz_t end = Length();
1110 const char *direct = Data();
1113 while (start < end && direct[start] == c)
1116 while (start < end && direct[end-1] == c)
1118 if (end == start) start = end = kNPOS;
1119 return TSubString(*
this, start, end-start);
1125 void TString::ToLower()
1127 Ssiz_t n = Length();
1128 char *p = GetPointer();
1130 *p = tolower((
unsigned char)*p);
1138 void TString::ToUpper()
1140 Ssiz_t n = Length();
1141 char *p = GetPointer();
1143 *p = toupper((
unsigned char)*p);
1151 void TString::AssertElement(Ssiz_t i)
const
1153 if (i == kNPOS || i > Length())
1154 Error(
"TString::AssertElement",
1155 "out of bounds: i = %d, Length = %d", i, Length());
1161 Ssiz_t TString::AdjustCapacity(Ssiz_t oldCap, Ssiz_t newCap)
1163 Ssiz_t ms = MaxSize();
1164 if (newCap > ms - 1) {
1165 Error(
"TString::AdjustCapacity",
"capacity too large (%d, max = %d)",
1168 Ssiz_t cap = oldCap < ms / 2 - kAlignment ?
1169 Recommend(TMath::Max(newCap, 2 * oldCap)) : ms - 1;
1176 void TString::Clear()
1178 Clobber(Capacity());
1184 void TString::Clobber(Ssiz_t nc)
1186 if (nc > MaxSize()) {
1187 Error(
"TString::Clobber",
"capacity too large (%d, max = %d)", nc, MaxSize());
1195 char *data = GetLongPointer();
1196 Ssiz_t cap = Recommend(nc);
1197 if (cap != Capacity()) {
1198 data =
new char[cap+1];
1201 SetLongPointer(data);
1212 void TString::Clone(Ssiz_t tot)
1214 Ssiz_t len = Length();
1215 if (len >= tot)
return;
1217 if (tot > MaxSize()) {
1218 Error(
"TString::Clone",
"tot too large (%d, max = %d)", tot, MaxSize());
1222 Ssiz_t capac = Capacity();
1223 char *data, *p = GetPointer();
1225 if (capac - tot < 0) {
1226 Ssiz_t cap = Recommend(tot);
1227 data =
new char[cap+1];
1228 memcpy(data, p, len);
1232 SetLongPointer(data);
1243 void TString::FillBuffer(
char *&buffer)
const
1246 Int_t nchars = Length();
1251 tobuf(buffer, nchars);
1253 nwh = UChar_t(nchars);
1256 const char *data = GetPointer();
1257 for (
int i = 0; i < nchars; i++) buffer[i] = data[i];
1264 void TString::ReadBuffer(
char *&buffer)
1272 frombuf(buffer, &nwh);
1274 frombuf(buffer, &nchars);
1279 Error(
"TString::ReadBuffer",
"found case with nwh=%d and nchars=%d", nwh, nchars);
1283 char *data = Init(nchars, nchars);
1285 for (
int i = 0; i < nchars; i++) frombuf(buffer, &data[i]);
1295 TString *TString::ReadString(TBuffer &b,
const TClass *clReq)
1297 R__ASSERT(b.IsReading());
1303 UInt_t startpos = UInt_t(b.Length());
1306 TClass *clRef = b.ReadClass(clReq, &tag);
1315 a = (TString *) clRef->New();
1317 ::Error(
"TString::ReadObject",
"could not create object of class %s",
1325 b.CheckByteCount(startpos, tag, clRef);
1334 Int_t TString::Sizeof()
const
1337 return Length()+
sizeof(UChar_t)+
sizeof(Int_t);
1339 return Length()+
sizeof(UChar_t);
1345 void TString::Streamer(TBuffer &b)
1347 if (b.IsReading()) {
1348 b.ReadTString(*
this);
1350 b.WriteTString(*
this);
1361 void TString::WriteString(TBuffer &b,
const TString *a)
1363 R__ASSERT(b.IsWriting());
1375 UInt_t cntpos = UInt_t(b.Length());
1376 b.SetBufferOffset(Int_t(cntpos+
sizeof(UInt_t)));
1378 TClass *cl = a->IsA();
1381 ((TString *)a)->Streamer(b);
1384 b.SetByteCount(cntpos);
1391 #if defined(R__TEMPLATE_OVERLOAD_BUG)
1394 TBuffer &operator>>(TBuffer &buf, TString *&s)
1396 s = (TString *) TString::ReadString(buf, TString::Class());
1403 TBuffer &operator<<(TBuffer &buf,
const TString *s)
1405 TString::WriteString(buf, s);
1415 Bool_t operator==(
const TString& s1,
const char *s2)
1417 if (!s2)
return kFALSE;
1419 const char *data = s1.Data();
1420 Ssiz_t len = s1.Length();
1422 for (i = 0; s2[i]; ++i)
1423 if (data[i] != s2[i] || i == len)
return kFALSE;
1430 TString ToLower(
const TString &str)
1432 Ssiz_t n = str.Length();
1433 TString temp((
char)0, n);
1434 const char *uc = str.Data();
1435 char *lc = (
char*)temp.Data();
1437 while (n--) { *lc++ = tolower((
unsigned char)*uc); uc++; }
1444 TString ToUpper(
const TString &str)
1446 Ssiz_t n = str.Length();
1447 TString temp((
char)0, n);
1448 const char* uc = str.Data();
1449 char* lc = (
char*)temp.Data();
1451 while (n--) { *lc++ = toupper((
unsigned char)*uc); uc++; }
1458 TString operator+(
const TString &s,
const char *cs)
1460 return TString(s.Data(), s.Length(), cs, cs ? strlen(cs) : 0);
1466 TString operator+(
const char *cs,
const TString &s)
1468 return TString(cs, cs ? strlen(cs) : 0, s.Data(), s.Length());
1474 TString operator+(
const TString &s1,
const TString &s2)
1476 return TString(s1.Data(), s1.Length(), s2.Data(), s2.Length());
1482 TString operator+(
const TString &s,
char c)
1484 return TString(s.Data(), s.Length(), &c, 1);
1490 TString operator+(
char c,
const TString &s)
1492 return TString(&c, 1, s.Data(), s.Length());
1501 Ssiz_t TString::GetInitialCapacity()
1503 ::Obsolete(
"TString::GetInitialCapacity",
"v5-30-00",
"v5-32-00");
1509 Ssiz_t TString::GetResizeIncrement()
1511 ::Obsolete(
"TString::GetResizeIncrement",
"v5-30-00",
"v5-32-00");
1517 Ssiz_t TString::GetMaxWaste()
1519 ::Obsolete(
"TString::GetMaxWaste",
"v5-30-00",
"v5-32-00");
1526 Ssiz_t TString::InitialCapacity(Ssiz_t)
1528 ::Obsolete(
"TString::InitialCapacity",
"v5-30-00",
"v5-32-00");
1535 Ssiz_t TString::ResizeIncrement(Ssiz_t)
1537 ::Obsolete(
"TString::ResizeIncrement",
"v5-30-00",
"v5-32-00");
1545 Ssiz_t TString::MaxWaste(Ssiz_t)
1547 ::Obsolete(
"TString::MaxWaste",
"v5-30-00",
"v5-32-00");
1564 TSubString::TSubString(
const TString &str, Ssiz_t start, Ssiz_t nextent)
1565 : fStr((TString&)str), fBegin(start), fExtent(nextent)
1572 TSubString TString::operator()(Ssiz_t start, Ssiz_t len)
const
1574 if (start < Length() && len > 0) {
1575 if (start+len > Length())
1576 len = Length() - start;
1581 return TSubString(*
this, start, len);
1590 TSubString TString::SubString(
const char *pattern, Ssiz_t startIndex,
1591 ECaseCompare cmp)
const
1593 Ssiz_t len = pattern ? strlen(pattern) : 0;
1594 Ssiz_t i = Index(pattern, len, startIndex, cmp);
1595 return TSubString(*
this, i, i == kNPOS ? 0 : len);
1601 char& TSubString::operator[](Ssiz_t i)
1604 return fStr(fBegin+i);
1610 char& TSubString::operator()(Ssiz_t i)
1612 return fStr(fBegin+i);
1618 TSubString& TSubString::operator=(
const TString &str)
1621 fStr.Replace(fBegin, fExtent, str.Data(), str.Length());
1629 TSubString& TSubString::operator=(
const char *cs)
1632 fStr.Replace(fBegin, fExtent, cs, cs ? strlen(cs) : 0);
1640 Bool_t operator==(
const TSubString& ss,
const char *cs)
1642 if (ss.IsNull())
return *cs ==
'\0';
1644 const char* data = ss.fStr.Data() + ss.fBegin;
1646 for (i = 0; cs[i]; ++i)
1647 if (cs[i] != data[i] || i == ss.fExtent)
return kFALSE;
1648 return (i == ss.fExtent);
1654 Bool_t operator==(
const TSubString& ss,
const TString &s)
1656 if (ss.IsNull())
return s.IsNull();
1657 if (ss.fExtent != s.Length())
return kFALSE;
1658 return !memcmp(ss.fStr.Data() + ss.fBegin, s.Data(), ss.fExtent);
1664 Bool_t operator==(
const TSubString &s1,
const TSubString &s2)
1666 if (s1.IsNull())
return s2.IsNull();
1667 if (s1.fExtent != s2.fExtent)
return kFALSE;
1668 return !memcmp(s1.fStr.Data()+s1.fBegin, s2.fStr.Data()+s2.fBegin,
1675 void TSubString::ToLower()
1678 char *p = fStr.GetPointer() + fBegin;
1680 while (n--) { *p = tolower((
unsigned char)*p); p++;}
1687 void TSubString::ToUpper()
1690 char *p = fStr.GetPointer() + fBegin;
1692 while (n--) { *p = toupper((
unsigned char)*p); p++;}
1699 void TSubString::SubStringError(Ssiz_t sr, Ssiz_t start, Ssiz_t n)
const
1701 Error(
"TSubString::SubStringError",
1702 "out of bounds: start = %d, n = %d, sr = %d", start, n, sr);
1708 void TSubString::AssertElement(Ssiz_t i)
const
1710 if (i == kNPOS || i >= Length())
1711 Error(
"TSubString::AssertElement",
1712 "out of bounds: i = %d, Length = %d", i, Length());
1718 Bool_t TString::IsAscii()
const
1720 const char *cp = Data();
1721 for (Ssiz_t i = 0; i < Length(); ++i)
1731 Bool_t TString::IsAlpha()
const
1733 const char *cp = Data();
1734 Ssiz_t len = Length();
1735 if (len == 0)
return kFALSE;
1736 for (Ssiz_t i = 0; i < len; ++i)
1737 if (!isalpha(cp[i]))
1746 Bool_t TString::IsAlnum()
const
1748 const char *cp = Data();
1749 Ssiz_t len = Length();
1750 if (len == 0)
return kFALSE;
1751 for (Ssiz_t i = 0; i < len; ++i)
1752 if (!isalnum(cp[i]))
1763 Bool_t TString::IsDigit()
const
1765 const char *cp = Data();
1766 Ssiz_t len = Length();
1767 if (len == 0)
return kFALSE;
1769 for (Ssiz_t i = 0; i < len; ++i) {
1770 if (cp[i] !=
' ' && !isdigit(cp[i]))
return kFALSE;
1771 if (cp[i] ==
' ') b++;
1772 if (isdigit(cp[i])) d++;
1791 Bool_t TString::IsFloat()
const
1794 if (IsDigit())
return kTRUE;
1796 TString tmp = *
this;
1801 Ssiz_t pos = tmp.First(
'.');
1802 if (pos != kNPOS) tmp.Replace(pos, 1,
" ", 1);
1803 pos = tmp.First(
',');
1804 if (pos != kNPOS) tmp.Replace(pos, 1,
" ", 1);
1805 pos = tmp.Index(
"e-");
1806 if (pos >= 1) tmp.Replace(pos, 2,
" ", 1);
1807 pos = tmp.Index(
"e+");
1808 if (pos >= 1) tmp.Replace(pos, 2,
" ", 1);
1809 pos = tmp.Index(
"e");
1810 if (pos >= 1) tmp.Replace(pos, 1,
" ", 1);
1811 pos = tmp.First(
'-');
1812 if (pos == 0) tmp.Replace(pos, 1,
" ", 1);
1813 pos = tmp.First(
'+');
1814 if (pos == 0) tmp.Replace(pos, 1,
" ", 1);
1817 return tmp.IsDigit();
1825 Bool_t TString::IsHex()
const
1827 const char *cp = Data();
1828 Ssiz_t len = Length();
1829 if (len == 0)
return kFALSE;
1830 for (Ssiz_t i = 0; i < len; ++i)
1831 if (!isxdigit(cp[i]))
1841 Bool_t TString::IsBin()
const
1843 const char *cp = Data();
1844 Ssiz_t len = Length();
1845 if (len == 0)
return kFALSE;
1846 for (Ssiz_t i = 0; i < len; ++i)
1847 if (cp[i] !=
'0' && cp[i] !=
'1')
1857 Bool_t TString::IsOct()
const
1859 const char *cp = Data();
1860 Ssiz_t len = Length();
1861 if (len == 0)
return kFALSE;
1862 for (Ssiz_t i = 0; i < len; ++i)
1863 if (!isdigit(cp[i]) || cp[i]==
'8' || cp[i]==
'9')
1873 Bool_t TString::IsDec()
const
1875 const char *cp = Data();
1876 Ssiz_t len = Length();
1877 if (len == 0)
return kFALSE;
1878 for (Ssiz_t i = 0; i < len; ++i)
1879 if (!isdigit(cp[i]))
1890 Bool_t TString::IsInBaseN(Int_t base)
const
1892 if (base < 2 || base > 36) {
1893 Error(
"TString::IsInBaseN",
"base %d is not supported. Supported bases are {2,3,...,36}.", base);
1896 if (Length() == 0) {
1897 Error(
"TString::IsInBaseN",
"input string is empty.") ;
1900 TString str = TString(Data()) ;
1902 TString str_ref0 =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;
1903 TString str_ref = str_ref0 ;
1904 str_ref.Remove(base) ;
1905 Bool_t isInBase = kTRUE ;
1906 for (Int_t k = 0; k < str.Length(); k++) {
1907 if (! str_ref.Contains(str[k])) {
1921 Int_t TString::Atoi()
const
1924 Int_t end = Index(
" ");
1926 if (end == -1)
return atoi(Data());
1932 tmp += (*this)(start, end-start);
1933 start = end+1; end = Index(
" ", start);
1937 tmp += (*this)(start, end-start);
1938 return atoi(tmp.Data());
1947 Long64_t TString::Atoll()
const
1950 Int_t end = Index(
" ");
1953 if (end == -1)
return atoll(Data());
1955 if (end == -1)
return _atoi64(Data());
1962 tmp += (*this)(start, end-start);
1963 start = end+1; end = Index(
" ", start);
1967 tmp += (*this)(start, end-start);
1969 return atoll(tmp.Data());
1971 return _atoi64(tmp.Data());
1987 Double_t TString::Atof()
const
1990 Int_t comma = Index(
",");
1991 Int_t end = Index(
" ");
1993 if (comma == -1 && end == -1)
return atof(Data());
1994 TString tmp = *
this;
1997 tmp.Replace(comma, 1,
".");
2000 if (end == -1)
return atof(tmp.Data());
2005 tmp2 += tmp(start, end-start);
2006 start = end+1; end = tmp.Index(
" ", start);
2009 tmp2 += tmp(start, end-start);
2010 return atof(tmp2.Data());
2025 TString TString::Itoa(Int_t value, Int_t base)
2029 if (base < 2 || base > 36) {
2030 Error(
"TString::Itoa",
"base %d is not supported. Supported bases are {2,3,...,36}.",base) ;
2031 return (TString(
"!"));
2034 Int_t quotient = value;
2037 buf +=
"0123456789abcdefghijklmnopqrstuvwxyz"[ TMath::Abs(quotient % base) ];
2041 if (value < 0) buf +=
'-';
2042 std::reverse(buf.begin(), buf.end());
2043 return (TString(buf.data()));
2052 TString TString::UItoa(UInt_t value, Int_t base)
2056 if (base < 2 || base > 36) {
2057 Error(
"TString::UItoa",
"base %d is not supported. Supported bases are {2,3,...,36}.",base);
2058 return (TString(
"!"));
2061 UInt_t quotient = value;
2064 buf +=
"0123456789abcdefghijklmnopqrstuvwxyz"[ quotient % base ];
2067 std::reverse(buf.begin(), buf.end());
2068 return (TString(buf.data()));
2077 TString TString::LLtoa(Long64_t value, Int_t base)
2081 if (base < 2 || base > 36) {
2082 Error(
"TString::LLtoa",
"base %d is not supported. Supported bases are {2,3,...,36}.",base);
2083 return (TString(
"!"));
2086 Long64_t quotient = value;
2089 buf +=
"0123456789abcdefghijklmnopqrstuvwxyz"[ TMath::Abs(quotient % base) ];
2093 if (value < 0) buf +=
'-';
2094 std::reverse(buf.begin(), buf.end());
2095 return (TString(buf.data()));
2104 TString TString::ULLtoa(ULong64_t value, Int_t base)
2108 if (base < 2 || base > 36) {
2109 Error(
"TString::ULLtoa",
"base %d is not supported. Supported bases are {2,3,...,36}.",base);
2110 return (TString(
"!"));
2113 ULong64_t quotient = value;
2116 buf +=
"0123456789abcdefghijklmnopqrstuvwxyz"[ quotient % base ];
2119 std::reverse(buf.begin(), buf.end());
2120 return (TString(buf.data()));
2127 TString TString::BaseConvert(
const TString& s_in, Int_t base_in, Int_t base_out)
2129 TString s_out =
"!" ;
2131 if (base_in < 2 || base_in > 36 || base_out < 2 || base_out > 36) {
2132 Error(
"TString::BaseConvert",
"only bases 2-36 are supported (base_in=%d, base_out=%d).", base_in, base_out);
2136 TString s_in_ = s_in;
2137 Bool_t isSigned = kFALSE;
2138 if (s_in_[0] ==
'-') {
2142 if (!isSigned && s_in_[0] ==
'+') s_in_.Remove(0, 1);
2143 if (base_in == 16 && s_in_.BeginsWith(
"0x")) s_in_.Remove(0, 2);
2144 s_in_ = TString(s_in_.Strip(TString::kLeading,
'0'));
2145 if (!s_in_.Length()) s_in_ +=
'0';
2147 if (!s_in_.IsInBaseN(base_in)) {
2148 Error(
"TString::BaseConvert",
"s_in=\"%s\" is not in base %d", s_in.Data(), base_in);
2152 TString s_max = TString::ULLtoa(18446744073709551615ULL, base_in);
2153 if (s_in_.Length() > s_max.Length()) {
2155 Error(
"TString::BaseConvert",
"s_in=\"%s\" > %s = 2^64-1 in base %d.", s_in.Data(), s_max.Data(), base_in);
2157 }
else if (s_in_.Length() == s_max.Length()) {
2160 if (s_in_ > s_max) {
2162 Error(
"TString::BaseConvert",
"s_in=\"%s\" > %s = 2^64-1 in base %d.", s_in.Data(), s_max.Data(), base_in);
2168 ULong64_t i = ULong64_t(strtoull(s_in.Data(), 0, base_in));
2169 s_out = TString::ULLtoa(i, base_out);
2170 if (isSigned) s_out.Prepend(
"-");
2177 Bool_t TString::EndsWith(
const char *s, ECaseCompare cmp)
const
2179 if (!s)
return kTRUE;
2181 Ssiz_t l = strlen(s);
2182 if (l > Length())
return kFALSE;
2183 const char *s2 = Data() + Length() - l;
2186 return strcmp(s, s2) == 0;
2187 return strcasecmp(s, s2) == 0;
2197 TObjArray *TString::Tokenize(
const TString &delim)
const
2199 std::list<Int_t> splitIndex;
2201 Int_t i, start, nrDiff = 0;
2202 for (i = 0; i < delim.Length(); i++) {
2204 while (start < Length()) {
2205 Int_t pos = Index(delim(i), start);
2206 if (pos == kNPOS)
break;
2207 splitIndex.push_back(pos);
2210 if (start > 0) nrDiff++;
2212 splitIndex.push_back(Length());
2217 TObjArray *arr =
new TObjArray();
2221 std::list<Int_t>::const_iterator it;
2223 for (it = splitIndex.begin(); it != splitIndex.end(); ++it) {
2225 for (it = splitIndex.begin(); it != (std::list<Int_t>::const_iterator) splitIndex.end(); ++it) {
2228 if (stop - 1 >= start + 1) {
2229 TString tok = (*this)(start+1, stop-start-1);
2230 TObjString *objstr =
new TObjString(tok);
2243 void TString::FormImp(
const char *fmt, va_list ap)
2245 Ssiz_t buflen = 20 + 20 * strlen(fmt);
2249 R__VA_COPY(sap, ap);
2253 n = vsnprintf(GetPointer(), buflen, fmt, ap);
2256 if (n == -1 || n >= buflen) {
2263 R__VA_COPY(ap, sap);
2271 SetSize(strlen(Data()));
2289 void TString::Form(
const char *va_(fmt), ...)
2292 va_start(ap, va_(fmt));
2293 FormImp(va_(fmt), ap);
2311 TString TString::Format(
const char *va_(fmt), ...)
2314 va_start(ap, va_(fmt));
2316 str.FormImp(va_(fmt), ap);
2327 static char *SlowFormat(
const char *format, va_list ap,
int hint)
2329 static const int fld_size = 2048;
2330 TTHREAD_TLS(
char*) slowBuffer(0);
2331 TTHREAD_TLS(
int) slowBufferSize(0);
2333 if (hint == -1) hint = fld_size;
2334 if (hint > slowBufferSize) {
2335 delete [] slowBuffer;
2336 slowBufferSize = 2 * hint;
2337 if (hint < 0 || slowBufferSize < 0) {
2342 slowBuffer =
new char[slowBufferSize];
2346 R__VA_COPY(sap, ap);
2348 int n = vsnprintf(slowBuffer, slowBufferSize, format, ap);
2351 if (n == -1 || n >= slowBufferSize) {
2352 if (n == -1) n = 2 * slowBufferSize;
2353 if (n == slowBufferSize) n++;
2359 R__VA_COPY(ap, sap);
2360 char *buf = SlowFormat(format, ap, n);
2375 static char *Format(
const char *format, va_list ap)
2377 static const int cb_size = 4096;
2378 static const int fld_size = 2048;
2381 TTHREAD_TLS_ARRAY(
char,cb_size,gFormbuf);
2382 TTHREAD_TLS(
char*) gBfree(0);
2383 TTHREAD_TLS(
char*) gEndbuf(0);
2387 gEndbuf = &gFormbuf[cb_size-1];
2391 if (buf+fld_size > gEndbuf)
2395 R__VA_COPY(sap, ap);
2397 int n = vsnprintf(buf, fld_size, format, ap);
2400 if (n == -1 || n >= fld_size) {
2402 R__VA_COPY(ap, sap);
2403 buf = SlowFormat(format, ap, n);
2422 char *Form(
const char *va_(fmt), ...)
2425 va_start(ap,va_(fmt));
2426 char *b = Format(va_(fmt), ap);
2436 void Printf(
const char *va_(fmt), ...)
2439 va_start(ap,va_(fmt));
2440 if (gPrintViaErrorHandler)
2441 ErrorHandler(kPrint, 0, va_(fmt), ap);
2443 char *b = Format(va_(fmt), ap);
2454 char *Strip(
const char *s,
char c)
2459 char *buf =
new char[l+1];
2472 const char *t2 = s + l - 1;
2473 while (*t2 == c && t2 > s)
2480 strncpy(buf, t1, (Ssiz_t) (t2-t1+1));
2481 *(buf+(t2-t1+1)) =
'\0';
2490 char *StrDup(
const char *str)
2494 char *s =
new char[strlen(str)+1];
2495 if (s) strcpy(s, str);
2504 char *Compress(
const char *str)
2508 const char *p = str;
2509 char *s, *s1 =
new char[strlen(str)+1];
2525 int EscChar(
const char *src,
char *dst,
int dstlen,
char *specchars,
2529 char *q, *end = dst+dstlen-1;
2531 for (p = src, q = dst; *p && q < end; ) {
2532 if (strchr(specchars, *p)) {
2549 int UnEscChar(
const char *src,
char *dst,
int dstlen,
char *specchars,
char)
2552 char *q, *end = dst+dstlen-1;
2554 for (p = src, q = dst; *p && q < end; ) {
2555 if (strchr(specchars, *p))
2567 #ifdef NEED_STRCASECMP
2571 int strcasecmp(
const char *str1,
const char *str2)
2573 return strncasecmp(str1, str2, str2 ? strlen(str2)+1 : 0);
2579 int strncasecmp(
const char *str1,
const char *str2, Ssiz_t n)
2605 std::string cling::printValue(
const TString* val) {
2606 TString s = TString::Format(
"\"%s\"[%d]", val->Data(), (int)val->Length());
2613 std::string cling::printValue(
const TSubString* val) {
2614 TString s = TString::Format(
"\"%.*s\"[%d]", (
int)val->Length(), val->Data(), (int)val->Length());
2621 std::string cling::printValue(
const std::string_view* val) {
2622 std::string str(*val);
2623 TString s = TString::Format(
"\"%s\"[%d]", str.c_str(), (int)val->length());