Logo ROOT  
Reference Guide
TString.cxx
Go to the documentation of this file.
1// @(#)root/base:$Id$
2// Author: Fons Rademakers 04/08/95
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/** \class TString
13\ingroup Base
14
15Basic string class.
16
17Cannot be stored in a TCollection... use TObjString instead.
18
19The underlying string is stored as a char* that can be accessed via
20TString::Data().
21TString provides Short String Optimization (SSO) so that short
22strings (<15 on 64-bit and <11 on 32-bit) are contained in the
23TString internal data structure without the need for mallocing the
24required space.
25
26Substring operations are provided by the TSubString class, which
27holds a reference to the original string and its data, along with
28the offset and length of the substring. To retrieve the substring
29as a TString, construct a TString from it, eg:
30~~~ {.cpp}
31 root [0] TString s("hello world")
32 root [1] TString s2( s(0,5) )
33 root [2] s2
34 (class TString)"hello"
35~~~
36*/
37
38#include <ROOT/RConfig.hxx>
39#include <stdlib.h>
40#include <ctype.h>
41#include <list>
42#include <algorithm>
43
44#include "Varargs.h"
45#include "strlcpy.h"
46#include "TString.h"
47#include "TBuffer.h"
48#include "TError.h"
49#include "Bytes.h"
50#include "TClass.h"
51#include "TMD5.h"
52#include "TObjArray.h"
53#include "TObjString.h"
54#include "TVirtualMutex.h"
55#include "ThreadLocalStorage.h"
56
57
58#if defined(R__WIN32)
59#define strtoull _strtoui64
60#endif
61
62#ifdef R__GLOBALSTL
63namespace std { using ::list; }
64#endif
65
67
68// Amount to shift hash values to avoid clustering
70
71////////////////////////////////////////////////////////////////////////////////
72//
73// In what follows, fCap is the length of the underlying representation
74// vector. Hence, the capacity for a null terminated string held in this
75// vector is fCap-1. The variable fSize is the length of the held
76// string, excluding the terminating null.
77//
78// The algorithms make no assumptions about whether internal strings
79// hold embedded nulls. However, they do assume that any string
80// passed in as an argument that does not have a length count is null
81// terminated and therefore has no embedded nulls.
82//
83// The internal string is always null terminated.
84
85////////////////////////////////////////////////////////////////////////////////
86/// TString default ctor.
87
89{
90 Zero();
91}
92
93////////////////////////////////////////////////////////////////////////////////
94/// Create TString able to contain ic characters.
95
97{
98 Init(ic, 0);
99}
100
101////////////////////////////////////////////////////////////////////////////////
102/// Create TString and initialize it with string cs.
103
104TString::TString(const char *cs)
105{
106 if (cs) {
107 Ssiz_t n = strlen(cs);
108 char *data = Init(n, n);
109 memcpy(data, cs, n);
110 } else
111 Init(0, 0);
112}
113
114////////////////////////////////////////////////////////////////////////////////
115/// Create TString and initialize it with string cs.
116
117TString::TString(const std::string &s)
118{
119 Ssiz_t n = s.length();
120 char *data = Init(n, n);
121 memcpy(data, s.c_str(), n);
122}
123
124////////////////////////////////////////////////////////////////////////////////
125/// Create TString and initialize it with the first n characters of cs.
126
127TString::TString(const char *cs, Ssiz_t n)
128{
129 if (n < 0) {
130 Error("TString::TString", "Negative length!");
131 Zero();
132 return;
133 }
134 if (strlen(cs) < (size_t)n) {
135 Warning("TString::TString", "Input string is shorter than requested size.");
136 }
137 char *data = Init(n, n);
138 memcpy(data, cs, n);
139}
140
141////////////////////////////////////////////////////////////////////////////////
142/// Initialize a string with a single character.
143
145{
146 char *data = Init(1, 1);
147 data[0] = c;
148}
149
150////////////////////////////////////////////////////////////////////////////////
151/// Initialize a string with a single character.
152
154{
155 InitChar(c);
156}
157
158////////////////////////////////////////////////////////////////////////////////
159/// Initialize the first n locations of a TString with character c.
160
162{
163 if (n < 0) {
164 Error("TString::TString", "Negative length!");
165 Zero();
166 return;
167 }
168 char *data = Init(n, n);
169 while (n--) data[n] = c;
170}
171
172////////////////////////////////////////////////////////////////////////////////
173/// Copy constructor.
174
176{
177 if (!s.IsLong())
178 fRep.fRaw = s.fRep.fRaw;
179 else {
180 Ssiz_t n = s.GetLongSize();
181 char *data = Init(n, n);
182 memcpy(data, s.GetLongPointer(), n);
183 }
184}
185
186////////////////////////////////////////////////////////////////////////////////
187/// Move constructor.
188
190{
191 // Short or long, all data is in fRaw.
192 fRep.fRaw = s.fRep.fRaw;
193 s.Init(0,0);
194}
195
196////////////////////////////////////////////////////////////////////////////////
197/// Copy a std::string_view in a TString.
198
200{
201 Ssiz_t len = substr.length();
202 char *data = Init(len, len);
203 memcpy(data, substr.data(), len);
204}
205
206////////////////////////////////////////////////////////////////////////////////
207/// Copy a TSubString in a TString.
208
210{
211 Ssiz_t len = substr.IsNull() ? 0 : substr.Length();
212 char *data = Init(len, len);
213 memcpy(data, substr.Data(), len);
214}
215
216////////////////////////////////////////////////////////////////////////////////
217/// Special constructor to initialize with the concatenation of a1 and a2.
218
219TString::TString(const char *a1, Ssiz_t n1, const char *a2, Ssiz_t n2)
220{
221 if (n1 < 0) {
222 Error("TString::TString", "Negative first length!");
223 Zero();
224 return;
225 }
226 if (n2 < 0) {
227 Error("TString::TString", "Negative second length!");
228 Zero();
229 return;
230 }
231 if (!a1) n1 = 0;
232 if (!a2) n2 = 0;
233 Ssiz_t tot = n1+n2;
234 char *data = Init(tot, tot);
235 if (a1) memcpy(data, a1, n1);
236 if (a2) memcpy(data+n1, a2, n2);
237}
238
239////////////////////////////////////////////////////////////////////////////////
240/// Delete a TString.
241
243{
244 UnLink();
245}
246
247////////////////////////////////////////////////////////////////////////////////
248/// Private member function returning an empty string representation of
249/// size capacity and containing nchar characters.
250
251char *TString::Init(Ssiz_t capacity, Ssiz_t nchar)
252{
253 if (capacity < 0) {
254 Error("TString::Init", "Negative length!");
255 capacity = 0;
256 }
257 if (nchar < 0) {
258 Error("*TString::Init", "Negative length!");
259 nchar = 0;
260 }
261 if (capacity > MaxSize()) {
262 Error("TString::Init", "capacity too large (%d, max = %d)", capacity, MaxSize());
263 capacity = MaxSize();
264 if (nchar > capacity)
265 nchar = capacity;
266 }
267
268 char *data;
269 if (capacity < kMinCap) {
270 SetShortSize(nchar);
271 data = GetShortPointer();
272 } else {
273 Ssiz_t cap = Recommend(capacity);
274 data = new char[cap+1];
275 SetLongCap(cap+1);
276 SetLongSize(nchar);
277 SetLongPointer(data);
278 }
279 data[nchar] = 0; // terminating null
280
281 return data;
282}
283
284////////////////////////////////////////////////////////////////////////////////
285/// Assign character c to TString.
286
288{
289 if (!c) {
290 UnLink();
291 Zero();
292 return *this;
293 }
294 return Replace(0, Length(), &c, 1);
295}
296
297////////////////////////////////////////////////////////////////////////////////
298/// Assign string cs to TString.
299
301{
302 if (!cs || !*cs) {
303 UnLink();
304 Zero();
305 return *this;
306 }
307 return Replace(0, Length(), cs, strlen(cs));
308}
309
310////////////////////////////////////////////////////////////////////////////////
311/// Assign std::string s to TString.
312
313TString& TString::operator=(const std::string &s)
314{
315 if (s.length()==0) {
316 UnLink();
317 Zero();
318 return *this;
319 }
320 return Replace(0, Length(), s.c_str(), s.length());
321}
322
323////////////////////////////////////////////////////////////////////////////////
324/// Assign std::string s to TString.
325
327{
328 if (s.length()==0) {
329 UnLink();
330 Zero();
331 return *this;
332 }
333 return Replace(0, Length(), s.data(), s.length());
334}
335
336////////////////////////////////////////////////////////////////////////////////
337/// Assignment operator.
338
340{
341 if (this != &rhs) {
342 UnLink();
343 if (!rhs.IsLong())
344 fRep.fRaw = rhs.fRep.fRaw;
345 else {
346 Ssiz_t n = rhs.GetLongSize();
347 char *data = Init(n, n);
348 memcpy(data, rhs.GetLongPointer(), n);
349 }
350 }
351 return *this;
352}
353
354////////////////////////////////////////////////////////////////////////////////
355/// Move-Assignment operator.
356
358{
359 UnLink();
360 fRep.fRaw = rhs.fRep.fRaw;
361 rhs.Zero();
362 return *this;
363}
364
365////////////////////////////////////////////////////////////////////////////////
366/// Assign a TSubString substr to TString.
367
369{
370 Ssiz_t len = substr.IsNull() ? 0 : substr.Length();
371 if (!len) {
372 UnLink();
373 Zero();
374 return *this;
375 }
376 return Replace(0, Length(), substr.Data(), len);
377}
378
379////////////////////////////////////////////////////////////////////////////////
380/// Append character c rep times to string.
381
383{
384 if (!rep) return *this;
385
386 if (rep < 0) {
387 Error("TString::Append", "Negative length!");
388 return *this;
389 }
390 Ssiz_t len = Length();
391 Ssiz_t tot = len + rep; // Final string length
392
393 if (tot > MaxSize()) {
394 Error("TString::Append", "rep too large (%d, max = %d)", rep, MaxSize()-len);
395 tot = MaxSize();
396 rep = tot - len;
397 }
398
399 Ssiz_t capac = Capacity();
400 char *data, *p = GetPointer();
401
402 if (capac - tot >= 0) {
403 SetSize(tot);
404 data = p;
405 } else {
406 Ssiz_t cap = AdjustCapacity(capac, tot);
407 data = new char[cap+1];
408 memcpy(data, p, len);
409 UnLink();
410 SetLongCap(cap+1);
411 SetLongSize(tot);
412 SetLongPointer(data);
413 }
414 data[tot] = 0;
415
416 data += len;
417 while (rep--)
418 *data++ = c;
419
420 return *this;
421}
422
423////////////////////////////////////////////////////////////////////////////////
424/// Return string capacity. If nc != current capacity Clone() the string
425/// in a string with the desired capacity.
426
428{
429 if (nc > Length())
430 Clone(nc);
431
432 return Capacity();
433}
434
435////////////////////////////////////////////////////////////////////////////////
436/// Compare a string to char *cs2. Returns returns zero if the two
437/// strings are identical, otherwise returns the difference between
438/// the first two differing bytes (treated as unsigned char values,
439/// so that `\200' is greater than `\0', for example). Zero-length
440/// strings are always identical.
441
442int TString::CompareTo(const char *cs2, ECaseCompare cmp) const
443{
444 if (!cs2) return 1;
445
446 const char *cs1 = Data();
447 Ssiz_t len = Length();
448 Ssiz_t i = 0;
449 if (cmp == kExact) {
450 for (; cs2[i]; ++i) {
451 if (i == len) return -1;
452 if (cs1[i] != cs2[i]) return ((cs1[i] > cs2[i]) ? 1 : -1);
453 }
454 } else { // ignore case
455 for (; cs2[i]; ++i) {
456 if (i == len) return -1;
457 char c1 = tolower((unsigned char)cs1[i]);
458 char c2 = tolower((unsigned char)cs2[i]);
459 if (c1 != c2) return ((c1 > c2) ? 1 : -1);
460 }
461 }
462 return (i < len) ? 1 : 0;
463}
464
465////////////////////////////////////////////////////////////////////////////////
466/// Compare a string to another string. Returns returns zero if the two
467/// strings are identical, otherwise returns the difference between
468/// the first two differing bytes (treated as unsigned char values,
469/// so that `\200' is greater than `\0', for example). Zero-length
470/// strings are always identical.
471
472int TString::CompareTo(const TString &str, ECaseCompare cmp) const
473{
474 const char *s1 = Data();
475 const char *s2 = str.Data();
476 Ssiz_t len = Length();
477 Ssiz_t slen, sleno = str.Length();
478 slen = sleno;
479 if (len < slen) slen = len;
480 if (cmp == kExact) {
481 int result = memcmp(s1, s2, slen);
482 if (result != 0) return result;
483 } else {
484 Ssiz_t i = 0;
485 for (; i < slen; ++i) {
486 char c1 = tolower((unsigned char)s1[i]);
487 char c2 = tolower((unsigned char)s2[i]);
488 if (c1 != c2) return ((c1 > c2) ? 1 : -1);
489 }
490 }
491 // strings are equal up to the length of the shorter one.
492 slen = sleno;
493 if (len == slen) return 0;
494 return (len > slen) ? 1 : -1;
495}
496
497////////////////////////////////////////////////////////////////////////////////
498/// Return number of times character c occurs in the string.
499
501{
502 Int_t count = 0;
503 Int_t len = Length();
504 const char *data = Data();
505 for (Int_t n = 0; n < len; n++)
506 if (data[n] == c) count++;
507
508 return count;
509}
510
511////////////////////////////////////////////////////////////////////////////////
512/// Copy a string.
513
515{
516 TString temp(*this);
517 return temp;
518}
519
520////////////////////////////////////////////////////////////////////////////////
521/// Find first occurrence of a character c.
522
524{
525 const char *f = strchr(Data(), c);
526 return f ? f - Data() : kNPOS;
527}
528
529////////////////////////////////////////////////////////////////////////////////
530/// Find first occurrence of a character in cs.
531
532Ssiz_t TString::First(const char *cs) const
533{
534 const char *f = strpbrk(Data(), cs);
535 return f ? f - Data() : kNPOS;
536}
537
538#ifndef R__BYTESWAP
539////////////////////////////////////////////////////////////////////////////////
540
541inline static UInt_t SwapInt(UInt_t x)
542{
543 return (((x & 0x000000ffU) << 24) | ((x & 0x0000ff00U) << 8) |
544 ((x & 0x00ff0000U) >> 8) | ((x & 0xff000000U) >> 24));
545}
546#endif
547
548////////////////////////////////////////////////////////////////////////////////
549/// Utility used by Hash().
550
551inline static void Mash(UInt_t& hash, UInt_t chars)
552{
553 hash = (chars ^
554 ((hash << kHashShift) |
555 (hash >> (kBitsPerByte*sizeof(UInt_t) - kHashShift))));
556}
557
558////////////////////////////////////////////////////////////////////////////////
559/// Return a case-sensitive hash value (endian independent).
560
561UInt_t Hash(const char *str)
562{
563 UInt_t len = str ? strlen(str) : 0;
564 UInt_t hv = len; // Mix in the string length.
565 UInt_t i = hv*sizeof(char)/sizeof(UInt_t);
566
567 if (((ULongptr_t)str)%sizeof(UInt_t) == 0) {
568 // str is word aligned
569 const UInt_t *p = (const UInt_t*)str;
570
571 while (i--) {
572#ifndef R__BYTESWAP
573 UInt_t h = *p++;
574 Mash(hv, SwapInt(h));
575#else
576 Mash(hv, *p++); // XOR in the characters.
577#endif
578 }
579
580 // XOR in any remaining characters:
581 if ((i = len*sizeof(char)%sizeof(UInt_t)) != 0) {
582 UInt_t h = 0;
583 const char* c = (const char*)p;
584 while (i--)
585 h = ((h << kBitsPerByte*sizeof(char)) | *c++);
586 Mash(hv, h);
587 }
588 } else {
589 // str is not word aligned
590 UInt_t h;
591 const unsigned char *p = (const unsigned char*)str;
592
593 while (i--) {
594 memcpy(&h, p, sizeof(UInt_t));
595#ifndef R__BYTESWAP
596 Mash(hv, SwapInt(h));
597#else
598 Mash(hv, h);
599#endif
600 p += sizeof(UInt_t);
601 }
602
603 // XOR in any remaining characters:
604 if ((i = len*sizeof(char)%sizeof(UInt_t)) != 0) {
605 h = 0;
606 const char* c = (const char*)p;
607 while (i--)
608 h = ((h << kBitsPerByte*sizeof(char)) | *c++);
609 Mash(hv, h);
610 }
611 }
612 return hv;
613}
614
615////////////////////////////////////////////////////////////////////////////////
616/// Return a case-sensitive hash value (endian independent).
617
619{
620 UInt_t hv = (UInt_t)Length(); // Mix in the string length.
621 UInt_t i = hv*sizeof(char)/sizeof(UInt_t);
622 const UInt_t *p = (const UInt_t*)Data();
623 {
624 while (i--) {
625#ifndef R__BYTESWAP
626 UInt_t h = *p++;
627 Mash(hv, SwapInt(h)); // XOR in the characters.
628#else
629 Mash(hv, *p++); // XOR in the characters.
630#endif
631 }
632 }
633 // XOR in any remaining characters:
634 if ((i = Length()*sizeof(char)%sizeof(UInt_t)) != 0) {
635 UInt_t h = 0;
636 const char* c = (const char*)p;
637 while (i--)
638 h = ((h << kBitsPerByte*sizeof(char)) | *c++);
639 Mash(hv, h);
640 }
641 return hv;
642}
643
644////////////////////////////////////////////////////////////////////////////////
645/// Return a case-insensitive hash value (endian independent).
646
648{
649 UInt_t hv = (UInt_t)Length(); // Mix in the string length.
650 UInt_t i = hv;
651 const unsigned char *p = (const unsigned char*)Data();
652 while (i--) {
653 Mash(hv, toupper(*p));
654 ++p;
655 }
656 return hv;
657}
658
659////////////////////////////////////////////////////////////////////////////////
660/// Return hash value.
661
663{
664 return (cmp == kExact) ? HashCase() : HashFoldCase();
665}
666
667 // MurmurHash3 - a blazingly fast public domain hash!
668 // See http://code.google.com/p/smhasher/
669 // There are two versions, one optimized for 32 bit and one for 64 bit.
670 // They give different hash results!
671 // We use only the 64 bit version which also works on 32 bit.
672
673 //-----------------------------------------------------------------------------
674 // MurmurHash3 was written by Austin Appleby, and is placed in the public
675 // domain. The author hereby disclaims copyright to this source code.
676
677 // Note - The x86 and x64 versions do _not_ produce the same results, as the
678 // algorithms are optimized for their respective platforms. You can still
679 // compile and run any of them on any platform, but your performance with the
680 // non-native version will be less than optimal.
681
682 //-----------------------------------------------------------------------------
683 // Platform-specific functions and macros
684
685 // From MurmurHash.h:
686
687#if defined(_MSC_VER) && (_MSC_VER < 1800)
688 // Microsoft Visual Studio
689 typedef unsigned char uint8_t;
690 typedef unsigned long uint32_t;
691 typedef unsigned __int64 uint64_t;
692#else // defined(_MSC_VER)
693 // Other compilers
694#include <stdint.h>
695#endif // !defined(_MSC_VER)
696
697 // From MurmurHash.cpp:
698#if defined(_MSC_VER)
699 // Microsoft Visual Studio
700#include <stdlib.h>
701#define ROTL64(x,y) _rotl64(x,y)
702#define BIG_CONSTANT(x) (x)
703#else // defined(_MSC_VER)
704 // Other compilers
705 inline uint64_t rotl64 ( uint64_t x, int8_t r )
706 {
707 return (x << r) | (x >> (64 - r));
708 }
709
710#define ROTL64(x,y) rotl64(x,y)
711#define BIG_CONSTANT(x) (x##LLU)
712#endif // !defined(_MSC_VER)
713
714namespace {
715
716 /////////////////////////////////////////////////////////////////////////////
717 /// Block read - if your platform needs to do endian-swapping or can only
718 /// handle aligned reads, do the conversion here
719
720 R__ALWAYS_INLINE uint64_t getblock(const uint64_t* p, int i)
721 {
722 return p[i];
723 }
724
725 /////////////////////////////////////////////////////////////////////////////
726 /// Finalization mix - force all bits of a hash block to avalanche
727
728 R__ALWAYS_INLINE uint64_t fmix(uint64_t k)
729 {
730 k ^= k >> 33;
731 k *= BIG_CONSTANT(0xff51afd7ed558ccd);
732 k ^= k >> 33;
733 k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);
734 k ^= k >> 33;
735
736 return k;
737 }
738
739 /////////////////////////////////////////////////////////////////////////////
740 /// "key" is input to be hashed.
741 /// "len" is the number of bytes to hash starting at "key".
742 /// "seed" is a hash seed, "out" is a buffer (128 bytes) that will receive
743 /// the results.
744
745 static void MurmurHash3_x64_128(const void * key, const int len,
746 const uint32_t seed, uint64_t out[2] )
747 {
748 const uint8_t * data = (const uint8_t*)key;
749 const int nblocks = len / 16;
750
751 uint64_t h1 = seed;
752 uint64_t h2 = seed;
753
754 uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5);
755 uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f);
756
757 //----------
758 // body
759
760 const uint64_t * blocks = (const uint64_t *)(data);
761
762 for(int i = 0; i < nblocks; i++)
763 {
764 uint64_t k1 = getblock(blocks,i*2+0);
765 uint64_t k2 = getblock(blocks,i*2+1);
766
767 k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
768
769 h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;
770
771 k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
772
773 h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
774 }
775
776 //----------
777 // tail
778
779 const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
780
781 uint64_t k1 = 0;
782 uint64_t k2 = 0;
783
784 switch(len & 15) {
785 case 15: k2 ^= uint64_t(tail[14]) << 48; // fall through
786 case 14: k2 ^= uint64_t(tail[13]) << 40; // fall through
787 case 13: k2 ^= uint64_t(tail[12]) << 32; // fall through
788 case 12: k2 ^= uint64_t(tail[11]) << 24; // fall through
789 case 11: k2 ^= uint64_t(tail[10]) << 16; // fall through
790 case 10: k2 ^= uint64_t(tail[ 9]) << 8; // fall through
791 case 9: k2 ^= uint64_t(tail[ 8]) << 0;
792 k2 *= c2; k2 = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
793 // fall through
794 case 8: k1 ^= uint64_t(tail[ 7]) << 56; // fall through
795 case 7: k1 ^= uint64_t(tail[ 6]) << 48; // fall through
796 case 6: k1 ^= uint64_t(tail[ 5]) << 40; // fall through
797 case 5: k1 ^= uint64_t(tail[ 4]) << 32; // fall through
798 case 4: k1 ^= uint64_t(tail[ 3]) << 24; // fall through
799 case 3: k1 ^= uint64_t(tail[ 2]) << 16; // fall through
800 case 2: k1 ^= uint64_t(tail[ 1]) << 8; // fall through
801 case 1: k1 ^= uint64_t(tail[ 0]) << 0;
802 k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
803 };
804
805 //----------
806 // finalization
807
808 h1 ^= len; h2 ^= len;
809
810 h1 += h2;
811 h2 += h1;
812
813 h1 = fmix(h1);
814 h2 = fmix(h2);
815
816 h1 += h2;
817 h2 += h1;
818
819 ((uint64_t*)out)[0] = h1;
820 ((uint64_t*)out)[1] = h2;
821 }
822
823}
824
825////////////////////////////////////////////////////////////////////////////////
826/// Calculates hash index from any char string. (static function)
827/// - For string: i = TString::Hash(string,nstring);
828/// - For int: i = TString::Hash(&intword,sizeof(int));
829/// - For pointer: i = TString::Hash(&pointer,sizeof(void*));
830///
831/// This employs two different hash functions, depending on ntxt:
832/// - ntxt == sizeof(void*): a simple bitwise xor to get fast pointer hashes
833/// - else: MurmurHash3_x64_128 http://code.google.com/p/smhasher/
834
835UInt_t TString::Hash(const void *txt, Int_t ntxt)
836{
837 if (ntxt != sizeof(void*)) {
838 uint64_t buf[2] = {0};
839 MurmurHash3_x64_128(txt, ntxt, 0x6384BA69, buf);
840 return (UInt_t) buf[0];
841 } else {
842 // simple, superfast hash for pointers and alike
843 UInt_t ret = (UInt_t)0x6384BA69;
844 // aligned?
845 if (((size_t)txt) % sizeof(void*)) {
846 UInt_t* itxt = (UInt_t*)txt;
847 ret ^= itxt[0];
848 if (sizeof(void*) > sizeof(UInt_t)) {
849 ret ^= itxt[1];
850 }
851 } else {
852 const unsigned char* ctxt = (const unsigned char*) txt;
853 for (unsigned int i = 0; i < 4; ++i) {
854 ret ^= ctxt[i] << (i * 8);
855 }
856 if (sizeof(void*) > sizeof(UInt_t)) {
857 ctxt += 4;
858 for (unsigned int i = 0; i < 4; ++i) {
859 ret ^= ctxt[i] << (i * 8);
860 }
861 }
862 }
863 return ret;
864 }
865}
866
867////////////////////////////////////////////////////////////////////////////////
868/// Returns false if strings are not equal.
869
870static int MemIsEqual(const char *p, const char *q, Ssiz_t n)
871{
872 while (n--)
873 {
874 if (tolower((unsigned char)*p) != tolower((unsigned char)*q))
875 return kFALSE;
876 p++; q++;
877 }
878 return kTRUE;
879}
880
881////////////////////////////////////////////////////////////////////////////////
882/// Search for a string in the TString. Plen is the length of pattern,
883/// startIndex is the index from which to start and cmp selects the type
884/// of case-comparison.
885
886Ssiz_t TString::Index(const char *pattern, Ssiz_t plen, Ssiz_t startIndex,
887 ECaseCompare cmp) const
888{
889 if (plen < 0) {
890 Error("TString::Index", "Negative first pattern length!");
891 return kNPOS;
892 }
893 Ssiz_t slen = Length();
894 if (slen < startIndex + plen) return kNPOS;
895 if (plen == 0) return startIndex;
896 slen -= startIndex + plen;
897 const char *sp = Data() + startIndex;
898 if (cmp == kExact) {
899 char first = *pattern;
900 for (Ssiz_t i = 0; i <= slen; ++i)
901 if (sp[i] == first && memcmp(sp+i+1, pattern+1, plen-1) == 0)
902 return i + startIndex;
903 } else {
904 int first = tolower((unsigned char) *pattern);
905 for (Ssiz_t i = 0; i <= slen; ++i)
906 if (tolower((unsigned char) sp[i]) == first &&
907 MemIsEqual(sp+i+1, pattern+1, plen-1))
908 return i + startIndex;
909 }
910 return kNPOS;
911}
912
913////////////////////////////////////////////////////////////////////////////////
914/// Find last occurrence of a character c.
915
917{
918 const char *f = strrchr(Data(), (unsigned char) c);
919 return f ? f - Data() : kNPOS;
920}
921
922////////////////////////////////////////////////////////////////////////////////
923/// Return the MD5 digest for this string, in a string representation.
924
926{
927 TMD5 md5;
928 md5.Update((const UChar_t*)Data(), Length());
929 UChar_t digest[16];
930 md5.Final(digest);
931 return md5.AsString();
932}
933
934////////////////////////////////////////////////////////////////////////////////
935/// Returns true if string contains one of the regexp characters "^$.[]*+?".
936
938{
939 const char *specials = "^$.[]*+?";
940
941 if (First(specials) == kNPOS)
942 return kFALSE;
943 return kTRUE;
944}
945
946////////////////////////////////////////////////////////////////////////////////
947/// Returns true if string contains one of the wildcard characters "[]*?".
948
950{
951 const char *specials = "[]*?";
952
953 if (First(specials) == kNPOS)
954 return kFALSE;
955 return kTRUE;
956}
957
958////////////////////////////////////////////////////////////////////////////////
959/// Prepend character c rep times to string.
960
962{
963 if (rep <= 0)
964 return *this;
965
966 Ssiz_t len = Length();
967 Ssiz_t tot = len + rep; // Final string length
968
969 if (tot > MaxSize()) {
970 Error("TString::Prepend", "rep too large (%d, max = %d)", rep, MaxSize()-len);
971 tot = MaxSize();
972 rep = tot - len;
973 }
974
975 Ssiz_t capac = Capacity();
976 char *data, *p = GetPointer();
977
978 if (capac - tot >= 0) {
979 memmove(p + rep, p, len);
980 SetSize(tot);
981 data = p;
982 } else {
983 Ssiz_t cap = AdjustCapacity(capac, tot);
984 data = new char[cap+1];
985 memcpy(data+rep, p, len);
986 UnLink();
987 SetLongCap(cap+1);
988 SetLongSize(tot);
989 SetLongPointer(data);
990 }
991 data[tot] = 0;
992
993 while (rep--)
994 *data++ = c;
995
996 return *this;
997}
998
999////////////////////////////////////////////////////////////////////////////////
1000/// Remove at most n1 characters from self beginning at pos,
1001/// and replace them with the first n2 characters of cs.
1002
1003TString &TString::Replace(Ssiz_t pos, Ssiz_t n1, const char *cs, Ssiz_t n2)
1004{
1005 Ssiz_t len = Length();
1006 if (pos <= kNPOS || pos > len) {
1007 Error("TString::Replace",
1008 "first argument out of bounds: pos = %d, Length = %d", pos, len);
1009 return *this;
1010 }
1011 if (n1 < 0) {
1012 Error("TString::Replace", "Negative number of characters to remove!");
1013 return *this;
1014 }
1015 if (n2 < 0) {
1016 Error("TString::Replace", "Negative number of replacement characters!");
1017 return *this;
1018 }
1019
1020 n1 = TMath::Min(n1, len - pos);
1021 if (!cs) n2 = 0;
1022
1023 Ssiz_t tot = len - n1 + n2; // Final string length
1024 Ssiz_t rem = len - n1 - pos; // Length of remnant at end of string
1025
1026 Ssiz_t capac = Capacity();
1027 char *p = GetPointer();
1028
1029 if (capac - len + n1 >= n2) {
1030 if (n1 != n2) {
1031 if (rem) {
1032 if (n1 > n2) {
1033 if (n2) memmove(p + pos, cs, n2);
1034 memmove(p + pos + n2, p + pos + n1, rem);
1035 SetSize(tot);
1036 p[tot] = 0;
1037 return *this;
1038 }
1039 if (p + pos < cs && cs < p + len) {
1040 if (p + pos + n1 <= cs)
1041 cs += n2 - n1;
1042 else { // p + pos < cs < p + pos + n1
1043 memmove(p + pos, cs, n1);
1044 pos += n1;
1045 cs += n2;
1046 n2 -= n1;
1047 n1 = 0;
1048 }
1049 }
1050 memmove(p + pos + n2, p + pos + n1, rem);
1051 }
1052 }
1053 if (n2) memmove(p + pos, cs, n2);
1054 SetSize(tot);
1055 p[tot] = 0;
1056 } else {
1057 Ssiz_t cap = AdjustCapacity(capac, tot);
1058 char *data = new char[cap+1];
1059 if (pos) memcpy(data, p, pos);
1060 if (n2 ) memcpy(data + pos, cs, n2);
1061 if (rem) memcpy(data + pos + n2, p + pos + n1, rem);
1062 UnLink();
1063 SetLongCap(cap+1);
1064 SetLongSize(tot);
1065 SetLongPointer(data);
1066 data[tot] = 0;
1067 }
1068
1069 return *this;
1070}
1071
1072////////////////////////////////////////////////////////////////////////////////
1073/// Find & Replace ls1 symbols of s1 with ls2 symbols of s2 if any.
1074
1075TString& TString::ReplaceAll(const char *s1, Ssiz_t ls1, const char *s2,
1076 Ssiz_t ls2)
1077{
1078 if (s1 && ls1 > 0) {
1079 Ssiz_t index = 0;
1080 while ((index = Index(s1, ls1, index, kExact)) != kNPOS) {
1081 Replace(index, ls1, s2, ls2);
1082 index += ls2;
1083 }
1084 }
1085 return *this;
1086}
1087
1088////////////////////////////////////////////////////////////////////////////////
1089/// Remove char c at begin and/or end of string (like Strip()) but
1090/// modifies directly the string.
1091
1093{
1094 Ssiz_t start = 0; // Index of first character
1095 Ssiz_t end = Length(); // One beyond last character
1096 const char *direct = Data(); // Avoid a dereference w dumb compiler
1097 Ssiz_t send = end;
1098
1099 if (st & kLeading)
1100 while (start < end && direct[start] == c)
1101 ++start;
1102 if (st & kTrailing)
1103 while (start < end && direct[end-1] == c)
1104 --end;
1105 if (end == start) {
1106 UnLink();
1107 Zero();
1108 return *this;
1109 }
1110 if (start)
1111 Remove(0, start);
1112 if (send != end)
1113 Remove(send - start - (send - end), send - end);
1114 return *this;
1115}
1116
1117////////////////////////////////////////////////////////////////////////////////
1118/// Resize the string. Truncate or add blanks as necessary.
1119
1121{
1122 if (n < Length())
1123 Remove(n); // Shrank; truncate the string
1124 else
1125 Append(' ', n-Length()); // Grew or staid the same
1126}
1127
1128////////////////////////////////////////////////////////////////////////////////
1129/// Return a substring of self stripped at beginning and/or end.
1130
1132{
1133 Ssiz_t start = 0; // Index of first character
1134 Ssiz_t end = Length(); // One beyond last character
1135 const char *direct = Data(); // Avoid a dereference w dumb compiler
1136
1137 if (st & kLeading)
1138 while (start < end && direct[start] == c)
1139 ++start;
1140 if (st & kTrailing)
1141 while (start < end && direct[end-1] == c)
1142 --end;
1143 if (end == start) start = end = kNPOS; // make the null substring
1144 return TSubString(*this, start, end-start);
1145}
1146
1147////////////////////////////////////////////////////////////////////////////////
1148/// Change string to lower-case.
1149
1151{
1152 Ssiz_t n = Length();
1153 char *p = GetPointer();
1154 while (n--) {
1155 *p = tolower((unsigned char)*p);
1156 p++;
1157 }
1158}
1159
1160////////////////////////////////////////////////////////////////////////////////
1161/// Change string to upper case.
1162
1164{
1165 Ssiz_t n = Length();
1166 char *p = GetPointer();
1167 while (n--) {
1168 *p = toupper((unsigned char)*p);
1169 p++;
1170 }
1171}
1172
1173////////////////////////////////////////////////////////////////////////////////
1174/// Check to make sure a string index is in range.
1175
1177{
1178 if (i == kNPOS || i > Length())
1179 Error("TString::AssertElement",
1180 "out of bounds: i = %d, Length = %d", i, Length());
1181}
1182
1183////////////////////////////////////////////////////////////////////////////////
1184/// Calculate a nice capacity greater than or equal to newCap.
1185
1187{
1188 Ssiz_t ms = MaxSize();
1189 if (newCap > ms - 1) {
1190 Error("TString::AdjustCapacity", "capacity too large (%d, max = %d)",
1191 newCap, ms);
1192 }
1193 Ssiz_t cap = oldCap < ms / 2 - kAlignment ?
1194 Recommend(TMath::Max(newCap, 2 * oldCap)) : ms - 1;
1195 return cap;
1196}
1197
1198////////////////////////////////////////////////////////////////////////////////
1199/// Clear string without changing its capacity.
1200
1202{
1203 Clobber(Capacity());
1204}
1205
1206////////////////////////////////////////////////////////////////////////////////
1207/// Clear string and make sure it has a capacity of nc.
1208
1210{
1211 if (nc > MaxSize()) {
1212 Error("TString::Clobber", "capacity too large (%d, max = %d)", nc, MaxSize());
1213 nc = MaxSize();
1214 }
1215
1216 if (nc < kMinCap) {
1217 UnLink();
1218 Zero();
1219 } else {
1220 char *data = GetLongPointer();
1221 Ssiz_t cap = Recommend(nc);
1222 if (cap != Capacity()) {
1223 data = new char[cap+1];
1224 UnLink();
1225 SetLongCap(cap+1);
1226 SetLongPointer(data);
1227 }
1228 SetLongSize(0);
1229 data[0] = 0;
1230 }
1231}
1232
1233////////////////////////////////////////////////////////////////////////////////
1234/// Make self a distinct copy with capacity of at least tot, where tot cannot
1235/// be smaller than the current length. Preserve previous contents.
1236
1238{
1239 Ssiz_t len = Length();
1240 if (len >= tot) return;
1241
1242 if (tot > MaxSize()) {
1243 Error("TString::Clone", "tot too large (%d, max = %d)", tot, MaxSize());
1244 tot = MaxSize();
1245 }
1246
1247 Ssiz_t capac = Capacity();
1248 char *data, *p = GetPointer();
1249
1250 if (capac - tot < 0) {
1251 Ssiz_t cap = Recommend(tot);
1252 data = new char[cap+1];
1253 memcpy(data, p, len);
1254 UnLink();
1255 SetLongCap(cap+1);
1256 SetLongSize(len);
1257 SetLongPointer(data);
1258 data[len] = 0;
1259 }
1260}
1261
1262////////////////////////////////////////////////////////////////////////////////
1263// ROOT I/O
1264
1265////////////////////////////////////////////////////////////////////////////////
1266/// Copy string into I/O buffer.
1267
1268void TString::FillBuffer(char *&buffer) const
1269{
1270 UChar_t nwh;
1271 Int_t nchars = Length();
1272
1273 if (nchars > 254) {
1274 nwh = 255;
1275 tobuf(buffer, nwh);
1276 tobuf(buffer, nchars);
1277 } else {
1278 nwh = UChar_t(nchars);
1279 tobuf(buffer, nwh);
1280 }
1281 const char *data = GetPointer();
1282 for (int i = 0; i < nchars; i++) buffer[i] = data[i];
1283 buffer += nchars;
1284}
1285
1286////////////////////////////////////////////////////////////////////////////////
1287/// Read string from I/O buffer.
1288
1289void TString::ReadBuffer(char *&buffer)
1290{
1291 UnLink();
1292 Zero();
1293
1294 UChar_t nwh;
1295 Int_t nchars;
1296
1297 frombuf(buffer, &nwh);
1298 if (nwh == 255)
1299 frombuf(buffer, &nchars);
1300 else
1301 nchars = nwh;
1302
1303 if (nchars < 0) {
1304 Error("TString::ReadBuffer", "found case with nwh=%d and nchars=%d", nwh, nchars);
1305 return;
1306 }
1307
1308 char *data = Init(nchars, nchars);
1309
1310 for (int i = 0; i < nchars; i++) frombuf(buffer, &data[i]);
1311}
1312
1313////////////////////////////////////////////////////////////////////////////////
1314/// Read TString object from buffer. Simplified version of
1315/// TBuffer::ReadObject (does not keep track of multiple
1316/// references to same string). We need to have it here
1317/// because TBuffer::ReadObject can only handle descendant
1318/// of TObject.
1319
1321{
1322 R__ASSERT(b.IsReading());
1323
1324 // Make sure ReadArray is initialized
1325 b.InitMap();
1326
1327 // Before reading object save start position
1328 UInt_t startpos = UInt_t(b.Length());
1329
1330 UInt_t tag;
1331 TClass *clRef = b.ReadClass(clReq, &tag);
1332
1333 TString *a;
1334 if (!clRef) {
1335
1336 a = nullptr;
1337
1338 } else {
1339
1340 a = (TString *) clRef->New();
1341 if (!a) {
1342 ::Error("TString::ReadObject", "could not create object of class %s",
1343 clRef->GetName());
1344 // Exception
1345 return a;
1346 }
1347
1348 a->Streamer(b);
1349
1350 b.CheckByteCount(startpos, tag, clRef);
1351 }
1352
1353 return a;
1354}
1355
1356////////////////////////////////////////////////////////////////////////////////
1357/// Returns size string will occupy on I/O buffer.
1358
1360{
1361 if (Length() > 254)
1362 return Length()+sizeof(UChar_t)+sizeof(Int_t);
1363 else
1364 return Length()+sizeof(UChar_t);
1365}
1366
1367////////////////////////////////////////////////////////////////////////////////
1368/// Stream a string object.
1369
1370void TString::Streamer(TBuffer &b)
1371{
1372 if (b.IsReading()) {
1373 b.ReadTString(*this);
1374 } else {
1375 b.WriteTString(*this);
1376 }
1377}
1378
1379////////////////////////////////////////////////////////////////////////////////
1380/// Write TString object to buffer. Simplified version of
1381/// TBuffer::WriteObject (does not keep track of multiple
1382/// references to the same string). We need to have it here
1383/// because TBuffer::ReadObject can only handle descendant
1384/// of TObject
1385
1387{
1388 R__ASSERT(b.IsWriting());
1389
1390 // Make sure WriteMap is initialized
1391 b.InitMap();
1392
1393 if (!a) {
1394
1395 b << (UInt_t) 0;
1396
1397 } else {
1398
1399 // Reserve space for leading byte count
1400 UInt_t cntpos = UInt_t(b.Length());
1401 b.SetBufferOffset(Int_t(cntpos+sizeof(UInt_t)));
1402
1403 TClass *cl = a->IsA();
1404 b.WriteClass(cl);
1405
1406 ((TString *)a)->Streamer(b);
1407
1408 // Write byte count
1409 b.SetByteCount(cntpos);
1410 }
1411}
1412
1413////////////////////////////////////////////////////////////////////////////////
1414/// Read string from TBuffer. Function declared in ClassDef.
1415
1416#if defined(R__TEMPLATE_OVERLOAD_BUG)
1417template <>
1418#endif
1420{
1422 return buf;
1423}
1424
1425////////////////////////////////////////////////////////////////////////////////
1426/// Write TString or derived to TBuffer.
1427
1429{
1430 TString::WriteString(buf, s);
1431 return buf;
1432}
1433
1434////////////////////////////////////////////////////////////////////////////////
1435// Related global functions
1436
1437////////////////////////////////////////////////////////////////////////////////
1438/// Compare TString with a char *.
1439
1440Bool_t operator==(const TString& s1, const char *s2)
1441{
1442 if (!s2) return kFALSE;
1443
1444 const char *data = s1.Data();
1445 Ssiz_t len = s1.Length();
1446 Ssiz_t i;
1447 for (i = 0; s2[i]; ++i)
1448 if (data[i] != s2[i] || i == len) return kFALSE;
1449 return (i == len);
1450}
1451
1452////////////////////////////////////////////////////////////////////////////////
1453/// Return a lower-case version of str.
1454
1456{
1457 Ssiz_t n = str.Length();
1458 TString temp((char)0, n);
1459 const char *uc = str.Data();
1460 char *lc = (char*)temp.Data();
1461 // Guard against tolower() being a macro
1462 while (n--) { *lc++ = tolower((unsigned char)*uc); uc++; }
1463 return temp;
1464}
1465
1466////////////////////////////////////////////////////////////////////////////////
1467/// Return an upper-case version of str.
1468
1470{
1471 Ssiz_t n = str.Length();
1472 TString temp((char)0, n);
1473 const char* uc = str.Data();
1474 char* lc = (char*)temp.Data();
1475 // Guard against toupper() being a macro
1476 while (n--) { *lc++ = toupper((unsigned char)*uc); uc++; }
1477 return temp;
1478}
1479
1480////////////////////////////////////////////////////////////////////////////////
1481/// Use the special concatenation constructor.
1482
1483TString operator+(const TString &s, const char *cs)
1484{
1485 return TString(s.Data(), s.Length(), cs, cs ? strlen(cs) : 0);
1486}
1487
1488////////////////////////////////////////////////////////////////////////////////
1489/// Use the special concatenation constructor.
1490
1491TString operator+(const char *cs, const TString &s)
1492{
1493 return TString(cs, cs ? strlen(cs) : 0, s.Data(), s.Length());
1494}
1495
1496////////////////////////////////////////////////////////////////////////////////
1497/// Use the special concatenation constructor.
1498
1500{
1501 return TString(s1.Data(), s1.Length(), s2.Data(), s2.Length());
1502}
1503
1504////////////////////////////////////////////////////////////////////////////////
1505/// Add char to string.
1506
1508{
1509 return TString(s.Data(), s.Length(), &c, 1);
1510}
1511
1512////////////////////////////////////////////////////////////////////////////////
1513/// Add string to char.
1514
1516{
1517 return TString(&c, 1, s.Data(), s.Length());
1518}
1519
1520////////////////////////////////////////////////////////////////////////////////
1521// Static Member Functions
1522// The static data members access
1523
1524////////////////////////////////////////////////////////////////////////////////
1525
1527{
1528 ::Obsolete("TString::GetInitialCapacity", "v5-30-00", "v5-32-00");
1529 return 15;
1530}
1531
1532////////////////////////////////////////////////////////////////////////////////
1533
1535{
1536 ::Obsolete("TString::GetResizeIncrement", "v5-30-00", "v5-32-00");
1537 return 16;
1538}
1539
1540////////////////////////////////////////////////////////////////////////////////
1541
1543{
1544 ::Obsolete("TString::GetMaxWaste", "v5-30-00", "v5-32-00");
1545 return 15;
1546}
1547
1548////////////////////////////////////////////////////////////////////////////////
1549/// Set default initial capacity for all TStrings. Default is 15.
1550
1552{
1553 ::Obsolete("TString::InitialCapacity", "v5-30-00", "v5-32-00");
1554 return 15;
1555}
1556
1557////////////////////////////////////////////////////////////////////////////////
1558/// Set default resize increment for all TStrings. Default is 16.
1559
1561{
1562 ::Obsolete("TString::ResizeIncrement", "v5-30-00", "v5-32-00");
1563 return 16;
1564}
1565
1566////////////////////////////////////////////////////////////////////////////////
1567/// Set maximum space that may be wasted in a string before doing a resize.
1568/// Default is 15.
1569
1571{
1572 ::Obsolete("TString::MaxWaste", "v5-30-00", "v5-32-00");
1573 return 15;
1574}
1575
1576/** \class TSubString
1577A zero length substring is legal. It can start
1578at any character. It is considered to be "pointing"
1579to just before the character.
1580
1581A "null" substring is a zero length substring that
1582starts with the nonsense index kNPOS. It can
1583be detected with the member function IsNull().
1584*/
1585
1586////////////////////////////////////////////////////////////////////////////////
1587/// Private constructor.
1588
1589TSubString::TSubString(const TString &str, Ssiz_t start, Ssiz_t nextent)
1590 : fStr((TString&)str), fBegin(start), fExtent(nextent)
1591{
1592}
1593
1594////////////////////////////////////////////////////////////////////////////////
1595/// Return sub-string of string starting at start with length len.
1596
1598{
1599 if (start < Length() && len > 0) {
1600 if (start+len > Length())
1601 len = Length() - start;
1602 } else {
1603 start = kNPOS;
1604 len = 0;
1605 }
1606 return TSubString(*this, start, len);
1607}
1608
1609////////////////////////////////////////////////////////////////////////////////
1610/// Returns a substring matching "pattern", or the null substring
1611/// if there is no such match. It would be nice if this could be yet another
1612/// overloaded version of operator(), but this would result in a type
1613/// conversion ambiguity with operator(Ssiz_t, Ssiz_t).
1614
1616 ECaseCompare cmp) const
1617{
1618 Ssiz_t len = pattern ? strlen(pattern) : 0;
1619 Ssiz_t i = Index(pattern, len, startIndex, cmp);
1620 return TSubString(*this, i, i == kNPOS ? 0 : len);
1621}
1622
1623////////////////////////////////////////////////////////////////////////////////
1624/// Return character at pos i from sub-string. Check validity of i.
1625
1627{
1628 AssertElement(i);
1629 return fStr(fBegin+i);
1630}
1631
1632////////////////////////////////////////////////////////////////////////////////
1633/// Return character at pos i from sub-string. No check on i.
1634
1636{
1637 return fStr(fBegin+i);
1638}
1639
1640////////////////////////////////////////////////////////////////////////////////
1641/// Assign string to sub-string.
1642
1644{
1645 if (!IsNull())
1646 fStr.Replace(fBegin, fExtent, str.Data(), str.Length());
1647
1648 return *this;
1649}
1650
1651////////////////////////////////////////////////////////////////////////////////
1652/// Assign char* to sub-string.
1653
1655{
1656 if (!IsNull())
1657 fStr.Replace(fBegin, fExtent, cs, cs ? strlen(cs) : 0);
1658
1659 return *this;
1660}
1661
1662////////////////////////////////////////////////////////////////////////////////
1663/// Compare sub-string to char *.
1664
1665Bool_t operator==(const TSubString& ss, const char *cs)
1666{
1667 if (ss.IsNull()) return *cs =='\0'; // Two null strings compare equal
1668
1669 const char* data = ss.fStr.Data() + ss.fBegin;
1670 Ssiz_t i;
1671 for (i = 0; cs[i]; ++i)
1672 if (cs[i] != data[i] || i == ss.fExtent) return kFALSE;
1673 return (i == ss.fExtent);
1674}
1675
1676////////////////////////////////////////////////////////////////////////////////
1677/// Compare sub-string to string.
1678
1680{
1681 if (ss.IsNull()) return s.IsNull(); // Two null strings compare equal.
1682 if (ss.fExtent != s.Length()) return kFALSE;
1683 return !memcmp(ss.fStr.Data() + ss.fBegin, s.Data(), ss.fExtent);
1684}
1685
1686////////////////////////////////////////////////////////////////////////////////
1687/// Compare two sub-strings.
1688
1690{
1691 if (s1.IsNull()) return s2.IsNull();
1692 if (s1.fExtent != s2.fExtent) return kFALSE;
1693 return !memcmp(s1.fStr.Data()+s1.fBegin, s2.fStr.Data()+s2.fBegin,
1694 s1.fExtent);
1695}
1696
1697////////////////////////////////////////////////////////////////////////////////
1698/// Convert sub-string to lower-case.
1699
1701{
1702 if (!IsNull()) { // Ignore null substrings
1703 char *p = fStr.GetPointer() + fBegin;
1704 Ssiz_t n = fExtent;
1705 while (n--) { *p = tolower((unsigned char)*p); p++;}
1706 }
1707}
1708
1709////////////////////////////////////////////////////////////////////////////////
1710/// Convert sub-string to upper-case.
1711
1713{
1714 if (!IsNull()) { // Ignore null substrings
1715 char *p = fStr.GetPointer() + fBegin;
1716 Ssiz_t n = fExtent;
1717 while (n--) { *p = toupper((unsigned char)*p); p++;}
1718 }
1719}
1720
1721////////////////////////////////////////////////////////////////////////////////
1722/// Output error message.
1723
1725{
1726 Error("TSubString::SubStringError",
1727 "out of bounds: start = %d, n = %d, sr = %d", start, n, sr);
1728}
1729
1730////////////////////////////////////////////////////////////////////////////////
1731/// Check to make sure a sub-string index is in range.
1732
1734{
1735 if (i == kNPOS || i >= Length())
1736 Error("TSubString::AssertElement",
1737 "out of bounds: i = %d, Length = %d", i, Length());
1738}
1739
1740////////////////////////////////////////////////////////////////////////////////
1741/// Returns true if all characters in string are ascii.
1742
1744{
1745 const char *cp = Data();
1746 for (Ssiz_t i = 0; i < Length(); ++i)
1747 if (cp[i] & ~0x7F)
1748 return kFALSE;
1749 return kTRUE;
1750}
1751
1752////////////////////////////////////////////////////////////////////////////////
1753/// Returns true if all characters in string are alphabetic.
1754/// Returns false in case string length is 0.
1755
1757{
1758 const char *cp = Data();
1759 Ssiz_t len = Length();
1760 if (len == 0) return kFALSE;
1761 for (Ssiz_t i = 0; i < len; ++i)
1762 if (!isalpha(cp[i]))
1763 return kFALSE;
1764 return kTRUE;
1765}
1766
1767////////////////////////////////////////////////////////////////////////////////
1768/// Returns true if all characters in string are alphanumeric.
1769/// Returns false in case string length is 0.
1770
1772{
1773 const char *cp = Data();
1774 Ssiz_t len = Length();
1775 if (len == 0) return kFALSE;
1776 for (Ssiz_t i = 0; i < len; ++i)
1777 if (!isalnum(cp[i]))
1778 return kFALSE;
1779 return kTRUE;
1780}
1781
1782////////////////////////////////////////////////////////////////////////////////
1783/// Returns true if all characters in string are digits (0-9) or white spaces,
1784/// i.e. "123456" and "123 456" are both valid integer strings.
1785/// Returns false in case string length is 0 or string contains other
1786/// characters or only whitespace.
1787
1789{
1790 const char *cp = Data();
1791 Ssiz_t len = Length();
1792 if (len == 0) return kFALSE;
1793 Int_t b = 0, d = 0;
1794 for (Ssiz_t i = 0; i < len; ++i) {
1795 if (cp[i] != ' ' && !isdigit(cp[i])) return kFALSE;
1796 if (cp[i] == ' ') b++;
1797 if (isdigit(cp[i])) d++;
1798 }
1799 if (b && !d)
1800 return kFALSE;
1801 return kTRUE;
1802}
1803
1804////////////////////////////////////////////////////////////////////////////////
1805/// Returns kTRUE if string contains a floating point or integer number.
1806/// Examples of valid formats are:
1807/// ~~~ {.cpp}
1808/// 64320
1809/// 64 320
1810/// 6 4 3 2 0
1811/// 6.4320 6,4320
1812/// 6.43e20 6.43E20 6,43e20
1813/// 6.43e-20 6.43E-20 6,43e-20, -6.43e+20
1814/// ~~~
1815
1817{
1818 //we first check if we have an integer, in this case, IsDigit() will be true straight away
1819 if (IsDigit()) return kTRUE;
1820
1821 TString tmp = *this;
1822 //now we look for occurrences of '.', ',', e', 'E', '+', '-' and replace each
1823 //with ' ', if it is a floating point, IsDigit() will then return kTRUE
1824
1825 tmp.ToLower();
1826 Ssiz_t pos = tmp.First('.');
1827 if (pos != kNPOS) tmp.Replace(pos, 1, " ", 1);
1828 pos = tmp.First(',');
1829 if (pos != kNPOS) tmp.Replace(pos, 1, " ", 1);
1830 pos = tmp.Index("e-");
1831 if (pos >= 1) tmp.Replace(pos, 2, " ", 1);
1832 pos = tmp.Index("e+");
1833 if (pos >= 1) tmp.Replace(pos, 2, " ", 1);
1834 pos = tmp.Index("e");
1835 if (pos >= 1) tmp.Replace(pos, 1, " ", 1);
1836 pos = tmp.First('-');
1837 if (pos == 0) tmp.Replace(pos, 1, " ", 1);
1838 pos = tmp.First('+');
1839 if (pos == 0) tmp.Replace(pos, 1, " ", 1);
1840
1841 //test if it is now uniquely composed of numbers
1842 return tmp.IsDigit();
1843}
1844
1845////////////////////////////////////////////////////////////////////////////////
1846/// Returns true if all characters in string are hexadecimal digits
1847/// (0-9,a-f,A-F). Returns false in case string length is 0 or string
1848/// contains other characters.
1849
1851{
1852 const char *cp = Data();
1853 Ssiz_t len = Length();
1854 if (len == 0) return kFALSE;
1855 for (Ssiz_t i = 0; i < len; ++i)
1856 if (!isxdigit(cp[i]))
1857 return kFALSE;
1858 return kTRUE;
1859}
1860
1861////////////////////////////////////////////////////////////////////////////////
1862/// Returns true if all characters in string are binary digits (0,1).
1863/// Returns false in case string length is 0 or string contains other
1864/// characters.
1865
1867{
1868 const char *cp = Data();
1869 Ssiz_t len = Length();
1870 if (len == 0) return kFALSE;
1871 for (Ssiz_t i = 0; i < len; ++i)
1872 if (cp[i] != '0' && cp[i] != '1')
1873 return kFALSE;
1874 return kTRUE;
1875}
1876
1877////////////////////////////////////////////////////////////////////////////////
1878/// Returns true if all characters in string are octal digits (0-7).
1879/// Returns false in case string length is 0 or string contains other
1880/// characters.
1881
1883{
1884 const char *cp = Data();
1885 Ssiz_t len = Length();
1886 if (len == 0) return kFALSE;
1887 for (Ssiz_t i = 0; i < len; ++i)
1888 if (!isdigit(cp[i]) || cp[i]=='8' || cp[i]=='9')
1889 return kFALSE;
1890 return kTRUE;
1891}
1892
1893////////////////////////////////////////////////////////////////////////////////
1894/// Returns true if all characters in string are decimal digits (0-9).
1895/// Returns false in case string length is 0 or string contains other
1896/// characters.
1897
1899{
1900 const char *cp = Data();
1901 Ssiz_t len = Length();
1902 if (len == 0) return kFALSE;
1903 for (Ssiz_t i = 0; i < len; ++i)
1904 if (!isdigit(cp[i]))
1905 return kFALSE;
1906 return kTRUE;
1907}
1908
1909////////////////////////////////////////////////////////////////////////////////
1910/// Returns true if all characters in string are expressed in the base
1911/// specified (range=2-36), i.e. {0,1} for base 2, {0-9,a-f,A-F} for base 16,
1912/// {0-9,a-z,A-Z} for base 36. Returns false in case string length is 0 or
1913/// string contains other characters.
1914
1916{
1917 if (base < 2 || base > 36) {
1918 Error("TString::IsInBaseN", "base %d is not supported. Supported bases are {2,3,...,36}.", base);
1919 return kFALSE;
1920 }
1921 if (Length() == 0) {
1922 Error("TString::IsInBaseN", "input string is empty.") ;
1923 return kFALSE;
1924 }
1925 TString str = TString(Data()) ;
1926 str.ToUpper() ;
1927 TString str_ref0 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;
1928 TString str_ref = str_ref0 ;
1929 str_ref.Remove(base) ;
1930 Bool_t isInBase = kTRUE ;
1931 for (Int_t k = 0; k < str.Length(); k++) {
1932 if (! str_ref.Contains(str[k])) {
1933 isInBase = kFALSE ;
1934 break ;
1935 }
1936 }
1937 return (isInBase);
1938}
1939
1940////////////////////////////////////////////////////////////////////////////////
1941/// Return integer value of string.
1942/// Valid strings include only digits and whitespace (see IsDigit()),
1943/// i.e. "123456", "123 456" and "1 2 3 4 56" are all valid
1944/// integer strings whose Atoi() value is 123456.
1945
1947{
1948 //any whitespace ?
1949 Int_t end = Index(" ");
1950 //if no white spaces in string, just use atoi()
1951 if (end == -1) return atoi(Data());
1952 //make temporary string, removing whitespace
1953 Int_t start = 0;
1954 TString tmp;
1955 //loop over all whitespace
1956 while (end > -1) {
1957 tmp += (*this)(start, end-start);
1958 start = end+1; end = Index(" ", start);
1959 }
1960 //finally add part from last whitespace to end of string
1961 end = Length();
1962 tmp += (*this)(start, end-start);
1963 return atoi(tmp.Data());
1964}
1965
1966////////////////////////////////////////////////////////////////////////////////
1967/// Return long long value of string.
1968/// Valid strings include only digits and whitespace (see IsDigit()),
1969/// i.e. "123456", "123 456" and "1 2 3 4 56" are all valid
1970/// integer strings whose Atoll() value is 123456.
1971
1973{
1974 //any whitespace ?
1975 Int_t end = Index(" ");
1976 //if no white spaces in string, just use atoi()
1977#ifndef R__WIN32
1978 if (end == -1) return atoll(Data());
1979#else
1980 if (end == -1) return _atoi64(Data());
1981#endif
1982 //make temporary string, removing whitespace
1983 Int_t start = 0;
1984 TString tmp;
1985 //loop over all whitespace
1986 while (end > -1) {
1987 tmp += (*this)(start, end-start);
1988 start = end+1; end = Index(" ", start);
1989 }
1990 //finally add part from last whitespace to end of string
1991 end = Length();
1992 tmp += (*this)(start, end-start);
1993#ifndef R__WIN32
1994 return atoll(tmp.Data());
1995#else
1996 return _atoi64(tmp.Data());
1997#endif
1998}
1999
2000////////////////////////////////////////////////////////////////////////////////
2001/// Return floating-point value contained in string.
2002/// Examples of valid strings are:
2003/// ~~~ {.cpp}
2004/// 64320
2005/// 64 320
2006/// 6 4 3 2 0
2007/// 6.4320 6,4320
2008/// 6.43e20 6.43E20 6,43e20
2009/// 6.43e-20 6.43E-20 6,43e-20
2010/// ~~~
2011
2013{
2014 //look for a comma and some whitespace
2015 Int_t comma = Index(",");
2016 Int_t end = Index(" ");
2017 //if no commas & no whitespace in string, just use atof()
2018 if (comma == -1 && end == -1) return atof(Data());
2019 TString tmp = *this;
2020 if (comma > -1) {
2021 //replace comma with decimal point
2022 tmp.Replace(comma, 1, ".");
2023 }
2024 //no whitespace ?
2025 if (end == -1) return atof(tmp.Data());
2026 //remove whitespace
2027 Int_t start = 0;
2028 TString tmp2;
2029 while (end > -1) {
2030 tmp2 += tmp(start, end-start);
2031 start = end+1; end = tmp.Index(" ", start);
2032 }
2033 end = tmp.Length();
2034 tmp2 += tmp(start, end-start);
2035 return atof(tmp2.Data());
2036}
2037
2038////////////////////////////////////////////////////////////////////////////////
2039/// Converts an Int_t to a TString with respect to the base specified (2-36).
2040/// Thus it is an enhanced version of sprintf (adapted from versions 0.4 of
2041/// http://www.jb.man.ac.uk/~slowe/cpp/itoa.html).
2042/// Usage: the following statement produce the same output, namely "1111"
2043/// ~~~ {.cpp}
2044/// std::cout << TString::Itoa(15,2) ;
2045/// std::cout << TString::Itoa(0xF,2) ; /// 0x prefix to handle hex
2046/// std::cout << TString::Itoa(017,2) ; /// 0 prefix to handle oct
2047/// ~~~
2048/// In case of error returns the "!" string.
2049
2051{
2052 std::string buf;
2053 // check that the base if valid
2054 if (base < 2 || base > 36) {
2055 Error("TString::Itoa", "base %d is not supported. Supported bases are {2,3,...,36}.",base) ;
2056 return (TString("!"));
2057 }
2058 buf.reserve(35); // Pre-allocate enough space (35=kMaxDigits)
2059 Int_t quotient = value;
2060 // Translating number to string with base:
2061 do {
2062 buf += "0123456789abcdefghijklmnopqrstuvwxyz"[ TMath::Abs(quotient % base) ];
2063 quotient /= base;
2064 } while (quotient);
2065 // Append the negative sign
2066 if (value < 0) buf += '-';
2067 std::reverse(buf.begin(), buf.end());
2068 return (TString(buf.data()));
2069}
2070
2071////////////////////////////////////////////////////////////////////////////////
2072/// Converts a UInt_t (twice the range of an Int_t) to a TString with respect
2073/// to the base specified (2-36). Thus it is an enhanced version of sprintf
2074/// (adapted from versions 0.4 of http://www.jb.man.ac.uk/~slowe/cpp/itoa.html).
2075/// In case of error returns the "!" string.
2076
2078{
2079 std::string buf;
2080 // check that the base if valid
2081 if (base < 2 || base > 36) {
2082 Error("TString::UItoa", "base %d is not supported. Supported bases are {2,3,...,36}.",base);
2083 return (TString("!"));
2084 }
2085 buf.reserve(35); // Pre-allocate enough space (35=kMaxDigits)
2086 UInt_t quotient = value;
2087 // Translating number to string with base:
2088 do {
2089 buf += "0123456789abcdefghijklmnopqrstuvwxyz"[ quotient % base ];
2090 quotient /= base;
2091 } while (quotient);
2092 std::reverse(buf.begin(), buf.end());
2093 return (TString(buf.data()));
2094}
2095
2096////////////////////////////////////////////////////////////////////////////////
2097/// Converts a Long64_t to a TString with respect to the base specified (2-36).
2098/// Thus it is an enhanced version of sprintf (adapted from versions 0.4 of
2099/// http://www.jb.man.ac.uk/~slowe/cpp/itoa.html).
2100/// In case of error returns the "!" string.
2101
2103{
2104 std::string buf;
2105 // check that the base if valid
2106 if (base < 2 || base > 36) {
2107 Error("TString::LLtoa", "base %d is not supported. Supported bases are {2,3,...,36}.",base);
2108 return (TString("!"));
2109 }
2110 buf.reserve(35); // Pre-allocate enough space (35=kMaxDigits)
2111 Long64_t quotient = value;
2112 // Translating number to string with base:
2113 do {
2114 buf += "0123456789abcdefghijklmnopqrstuvwxyz"[ TMath::Abs(quotient % base) ];
2115 quotient /= base;
2116 } while (quotient);
2117 // Append the negative sign
2118 if (value < 0) buf += '-';
2119 std::reverse(buf.begin(), buf.end());
2120 return (TString(buf.data()));
2121}
2122
2123////////////////////////////////////////////////////////////////////////////////
2124/// Converts a ULong64_t (twice the range of an Long64_t) to a TString with
2125/// respect to the base specified (2-36). Thus it is an enhanced version of
2126/// sprintf (adapted from versions 0.4 of http://www.jb.man.ac.uk/~slowe/cpp/itoa.html).
2127/// In case of error returns the "!" string.
2128
2130{
2131 std::string buf;
2132 // check that the base if valid
2133 if (base < 2 || base > 36) {
2134 Error("TString::ULLtoa", "base %d is not supported. Supported bases are {2,3,...,36}.",base);
2135 return (TString("!"));
2136 }
2137 buf.reserve(35); // Pre-allocate enough space (35=kMaxDigits)
2138 ULong64_t quotient = value;
2139 // Translating number to string with base:
2140 do {
2141 buf += "0123456789abcdefghijklmnopqrstuvwxyz"[ quotient % base ];
2142 quotient /= base;
2143 } while (quotient);
2144 std::reverse(buf.begin(), buf.end());
2145 return (TString(buf.data()));
2146}
2147
2148////////////////////////////////////////////////////////////////////////////////
2149/// Converts string from base base_in to base base_out. Supported bases
2150/// are 2-36. At most 64 bit data can be converted.
2151
2152TString TString::BaseConvert(const TString& s_in, Int_t base_in, Int_t base_out)
2153{
2154 TString s_out = "!" ; // return value in case of issue
2155 // checking base range
2156 if (base_in < 2 || base_in > 36 || base_out < 2 || base_out > 36) {
2157 Error("TString::BaseConvert", "only bases 2-36 are supported (base_in=%d, base_out=%d).", base_in, base_out);
2158 return (s_out);
2159 }
2160 // cleaning s_in
2161 TString s_in_ = s_in;
2162 Bool_t isSigned = kFALSE;
2163 if (s_in_[0] == '-') {
2164 isSigned = kTRUE;
2165 s_in_.Remove(0, 1);
2166 }
2167 if (!isSigned && s_in_[0] == '+') s_in_.Remove(0, 1); // !isSigned to avoid strings beginning with "-+"
2168 if (base_in == 16 && s_in_.BeginsWith("0x")) s_in_.Remove(0, 2); // removing hex prefix if any
2169 s_in_ = TString(s_in_.Strip(TString::kLeading, '0')); // removing leading zeros (necessary for length comparison below)
2170 if (!s_in_.Length()) s_in_ += '0';
2171 // checking s_in_ is expressed in the mentioned base
2172 if (!s_in_.IsInBaseN(base_in)) {
2173 Error("TString::BaseConvert", "s_in=\"%s\" is not in base %d", s_in.Data(), base_in);
2174 return (s_out);
2175 }
2176 // checking s_in <= 64 bits
2177 TString s_max = TString::ULLtoa(18446744073709551615ULL, base_in);
2178 if (s_in_.Length() > s_max.Length()) {
2179 // string comparison (s_in_>s_max) does not take care of length
2180 Error("TString::BaseConvert", "s_in=\"%s\" > %s = 2^64-1 in base %d.", s_in.Data(), s_max.Data(), base_in);
2181 return (s_out);
2182 } else if (s_in_.Length() == s_max.Length()) {
2183 // if ( s_in_.Length() < s_max.Length() ) everything's fine
2184 s_in_.ToLower(); // s_max is lower case
2185 if (s_in_ > s_max) {
2186 // string comparison
2187 Error("TString::BaseConvert", "s_in=\"%s\" > %s = 2^64-1 in base %d.", s_in.Data(), s_max.Data(), base_in);
2188 return (s_out);
2189 }
2190 }
2191
2192 // computing s_out
2193 ULong64_t i = ULong64_t(strtoull(s_in.Data(), nullptr, base_in));
2194 s_out = TString::ULLtoa(i, base_out);
2195 if (isSigned) s_out.Prepend("-");
2196 return (s_out);
2197}
2198
2199////////////////////////////////////////////////////////////////////////////////
2200/// Return true if string ends with the specified string.
2201
2203{
2204 if (!s) return kTRUE;
2205
2206 Ssiz_t l = strlen(s);
2207 if (l > Length()) return kFALSE;
2208 const char *s2 = Data() + Length() - l;
2209
2210 if (cmp == kExact)
2211 return strcmp(s, s2) == 0;
2212 return strcasecmp(s, s2) == 0;
2213}
2214
2215////////////////////////////////////////////////////////////////////////////////
2216/// This function is used to isolate sequential tokens in a TString.
2217/// These tokens are separated in the string by at least one of the
2218/// characters in delim. The returned array contains the tokens
2219/// as TObjString's. The returned array is the owner of the objects,
2220/// and must be deleted by the user.
2221
2223{
2224 std::list<Int_t> splitIndex;
2225
2226 Int_t i, start, nrDiff = 0;
2227 for (i = 0; i < delim.Length(); i++) {
2228 start = 0;
2229 while (start < Length()) {
2230 Int_t pos = Index(delim(i), start);
2231 if (pos == kNPOS) break;
2232 splitIndex.push_back(pos);
2233 start = pos + 1;
2234 }
2235 if (start > 0) nrDiff++;
2236 }
2237 splitIndex.push_back(Length());
2238
2239 if (nrDiff > 1)
2240 splitIndex.sort();
2241
2242 TObjArray *arr = new TObjArray();
2243 arr->SetOwner();
2244
2245 start = -1;
2246 std::list<Int_t>::const_iterator it;
2247#ifndef R__HPUX
2248 for (it = splitIndex.begin(); it != splitIndex.end(); ++it) {
2249#else
2250 for (it = splitIndex.begin(); it != (std::list<Int_t>::const_iterator) splitIndex.end(); ++it) {
2251#endif
2252 Int_t stop = *it;
2253 if (stop - 1 >= start + 1) {
2254 TString tok = (*this)(start+1, stop-start-1);
2255 TObjString *objstr = new TObjString(tok);
2256 arr->Add(objstr);
2257 }
2258 start = stop;
2259 }
2260
2261 return arr;
2262}
2263
2264////////////////////////////////////////////////////////////////////////////////
2265/// Formats a string using a printf style format descriptor.
2266/// Existing string contents will be overwritten.
2267
2268void TString::FormImp(const char *fmt, va_list ap)
2269{
2270 Ssiz_t buflen = 20 + 20 * strlen(fmt); // pick a number, any strictly positive number
2271 Clobber(buflen);
2272
2273 va_list sap;
2274 R__VA_COPY(sap, ap);
2275
2276 int n, vc = 0;
2277again:
2278 n = vsnprintf(GetPointer(), buflen, fmt, ap);
2279 // old vsnprintf's return -1 if string is truncated new ones return
2280 // total number of characters that would have been written
2281 if (n == -1 || n >= buflen) {
2282 if (n == -1)
2283 buflen *= 2;
2284 else
2285 buflen = n+1;
2286 Clobber(buflen);
2287 va_end(ap);
2288 R__VA_COPY(ap, sap);
2289 vc = 1;
2290 goto again;
2291 }
2292 va_end(sap);
2293 if (vc)
2294 va_end(ap);
2295
2296 SetSize(strlen(Data()));
2297}
2298
2299////////////////////////////////////////////////////////////////////////////////
2300/// Formats a string using a printf style format descriptor.
2301/// Existing string contents will be overwritten.
2302/// See also the static version TString::Format
2303/// ~~~ {.cpp}
2304/// TString formatted;
2305/// formatted.Form("%s in <%s>: %s", type, location, msg);
2306///
2307/// lines.emplace_back(TString::Format("Welcome to ROOT %s%%shttp://root.cern.ch",
2308/// gROOT->GetVersion()));
2309/// ~~~
2310///
2311/// Note: this is not to be confused with ::Format and ::Form (in the global namespace)
2312/// which returns a const char* and relies on a thread-local static character buffer.
2313
2314void TString::Form(const char *va_(fmt), ...)
2315{
2316 va_list ap;
2317 va_start(ap, va_(fmt));
2318 FormImp(va_(fmt), ap);
2319 va_end(ap);
2320}
2321
2322////////////////////////////////////////////////////////////////////////////////
2323/// Static method which formats a string using a printf style format
2324/// descriptor and return a TString. Similar to TString::Form() but it is
2325/// not needed to first create a TString.
2326/// ~~~ {.cpp}
2327/// lines.emplace_back(TString::Format("Welcome to ROOT %s%%shttp://root.cern.ch",
2328/// gROOT->GetVersion()));
2329/// TString formatted;
2330/// formatted.Form("%s in <%s>: %s", type, location, msg);
2331/// ~~~
2332///
2333/// Note: this is not to be confused with ::Format and ::Form (in the global namespace)
2334/// which returns a const char* and relies on a thread-local static character buffer.
2335
2336TString TString::Format(const char *va_(fmt), ...)
2337{
2338 va_list ap;
2339 va_start(ap, va_(fmt));
2340 TString str;
2341 str.FormImp(va_(fmt), ap);
2342 va_end(ap);
2343 return str;
2344}
2345
2346//---- Global String Handling Functions ----------------------------------------
2347
2348////////////////////////////////////////////////////////////////////////////////
2349/// Format a string in a formatting buffer (using a printf style
2350/// format descriptor).
2351
2352static char *SlowFormat(const char *format, va_list ap, int hint)
2353{
2354 static const int fld_size = 2048;
2355 TTHREAD_TLS(char*) slowBuffer(nullptr);
2356 TTHREAD_TLS(int) slowBufferSize(0);
2357
2358 if (hint == -1) hint = fld_size;
2359 if (hint > slowBufferSize) {
2360 delete [] slowBuffer;
2361 slowBufferSize = 2 * hint;
2362 if (hint < 0 || slowBufferSize < 0) {
2363 slowBufferSize = 0;
2364 slowBuffer = nullptr;
2365 return nullptr;
2366 }
2367 slowBuffer = new char[slowBufferSize];
2368 }
2369
2370 va_list sap;
2371 R__VA_COPY(sap, ap);
2372
2373 int n = vsnprintf(slowBuffer, slowBufferSize, format, ap);
2374 // old vsnprintf's return -1 if string is truncated new ones return
2375 // total number of characters that would have been written
2376 if (n == -1 || n >= slowBufferSize) {
2377 if (n == -1) n = 2 * slowBufferSize;
2378 if (n == slowBufferSize) n++;
2379 if (n <= 0) {
2380 va_end(sap);
2381 return nullptr; // int overflow!
2382 }
2383 va_end(ap);
2384 R__VA_COPY(ap, sap);
2385 char *buf = SlowFormat(format, ap, n);
2386 va_end(sap);
2387 va_end(ap);
2388 return buf;
2389 }
2390
2391 va_end(sap);
2392
2393 return slowBuffer;
2394}
2395
2396////////////////////////////////////////////////////////////////////////////////
2397/// Format a string in a circular formatting buffer (using a printf style
2398/// format descriptor).
2399
2400static char *Format(const char *format, va_list ap)
2401{
2402 static const int cb_size = 4096;
2403 static const int fld_size = 2048;
2404
2405 // a circular formating buffer
2406 TTHREAD_TLS_ARRAY(char,cb_size,gFormbuf); // gFormbuf[cb_size]; // some slob for form overflow
2407 TTHREAD_TLS(char*) gBfree(nullptr);
2408 TTHREAD_TLS(char*) gEndbuf(nullptr);
2409
2410 if (gBfree == nullptr) {
2411 gBfree = gFormbuf;
2412 gEndbuf = &gFormbuf[cb_size-1];
2413 }
2414 char *buf = gBfree;
2415
2416 if (buf+fld_size > gEndbuf)
2417 buf = gFormbuf;
2418
2419 va_list sap;
2420 R__VA_COPY(sap, ap);
2421
2422 int n = vsnprintf(buf, fld_size, format, ap);
2423 // old vsnprintf's return -1 if string is truncated new ones return
2424 // total number of characters that would have been written
2425 if (n == -1 || n >= fld_size) {
2426 va_end(ap);
2427 R__VA_COPY(ap, sap);
2428 buf = SlowFormat(format, ap, n);
2429 va_end(sap);
2430 va_end(ap);
2431 return buf;
2432 }
2433
2434 va_end(sap);
2435
2436 gBfree = buf+n+1;
2437 return buf;
2438}
2439
2440////////////////////////////////////////////////////////////////////////////////
2441/// Formats a string in a circular formatting buffer. Removes the need to
2442/// create and delete short lived strings. Don't pass Form() pointers
2443/// from user code down to ROOT functions as the circular buffer may
2444/// be overwritten downstream. Use Form() results immediately or use
2445/// TString::Format() instead.
2446
2447char *Form(const char *va_(fmt), ...)
2448{
2449 va_list ap;
2450 va_start(ap,va_(fmt));
2451 char *b = Format(va_(fmt), ap);
2452 va_end(ap);
2453 return b;
2454}
2455
2456////////////////////////////////////////////////////////////////////////////////
2457/// Formats a string in a circular formatting buffer and prints the string.
2458/// Appends a newline. If gPrintViaErrorHandler is true it will print via the
2459/// currently active ROOT error handler.
2460
2461void Printf(const char *va_(fmt), ...)
2462{
2463 va_list ap;
2464 va_start(ap,va_(fmt));
2466 ErrorHandler(kPrint, nullptr, va_(fmt), ap);
2467 else {
2468 char *b = Format(va_(fmt), ap);
2469 printf("%s\n", b);
2470 fflush(stdout);
2471 }
2472 va_end(ap);
2473}
2474
2475////////////////////////////////////////////////////////////////////////////////
2476/// Strip leading and trailing c (blanks by default) from a string.
2477/// The returned string has to be deleted by the user.
2478
2479char *Strip(const char *s, char c)
2480{
2481 if (!s) return nullptr;
2482
2483 int l = strlen(s);
2484 char *buf = new char[l+1];
2485
2486 if (l == 0) {
2487 *buf = '\0';
2488 return buf;
2489 }
2490
2491 // get rid of leading c's
2492 const char *t1 = s;
2493 while (*t1 == c)
2494 t1++;
2495
2496 // get rid of trailing c's
2497 const char *t2 = s + l - 1;
2498 while (*t2 == c && t2 > s)
2499 t2--;
2500
2501 if (t1 > t2) {
2502 *buf = '\0';
2503 return buf;
2504 }
2505 strncpy(buf, t1, (Ssiz_t) (t2-t1+1));
2506 *(buf+(t2-t1+1)) = '\0';
2507
2508 return buf;
2509}
2510
2511////////////////////////////////////////////////////////////////////////////////
2512/// Duplicate the string str. The returned string has to be deleted by
2513/// the user.
2514
2515char *StrDup(const char *str)
2516{
2517 if (!str) return nullptr;
2518
2519 auto len = strlen(str)+1;
2520 char *s = new char[len];
2521 if (s) strlcpy(s, str, len);
2522
2523 return s;
2524}
2525
2526////////////////////////////////////////////////////////////////////////////////
2527/// Remove all blanks from the string str. The returned string has to be
2528/// deleted by the user.
2529
2530char *Compress(const char *str)
2531{
2532 if (!str) return nullptr;
2533
2534 const char *p = str;
2535 char *s, *s1 = new char[strlen(str)+1];
2536 s = s1;
2537
2538 while (*p) {
2539 if (*p != ' ')
2540 *s++ = *p;
2541 p++;
2542 }
2543 *s = '\0';
2544
2545 return s1;
2546}
2547
2548////////////////////////////////////////////////////////////////////////////////
2549/// Escape specchars in src with escchar and copy to dst.
2550
2551int EscChar(const char *src, char *dst, int dstlen, char *specchars,
2552 char escchar)
2553{
2554 const char *p;
2555 char *q, *end = dst+dstlen-1;
2556
2557 for (p = src, q = dst; *p && q < end; ) {
2558 if (strchr(specchars, *p)) {
2559 *q++ = escchar;
2560 if (q < end)
2561 *q++ = *p++;
2562 } else
2563 *q++ = *p++;
2564 }
2565 *q = '\0';
2566
2567 if (*p != 0)
2568 return -1;
2569 return q-dst;
2570}
2571
2572////////////////////////////////////////////////////////////////////////////////
2573/// Un-escape specchars in src from escchar and copy to dst.
2574
2575int UnEscChar(const char *src, char *dst, int dstlen, char *specchars, char)
2576{
2577 const char *p;
2578 char *q, *end = dst+dstlen-1;
2579
2580 for (p = src, q = dst; *p && q < end; ) {
2581 if (strchr(specchars, *p))
2582 p++;
2583 else
2584 *q++ = *p++;
2585 }
2586 *q = '\0';
2587
2588 if (*p != 0)
2589 return -1;
2590 return q-dst;
2591}
2592
2593#ifdef NEED_STRCASECMP
2594////////////////////////////////////////////////////////////////////////////////
2595/// Case insensitive string compare.
2596
2597int strcasecmp(const char *str1, const char *str2)
2598{
2599 return strncasecmp(str1, str2, str2 ? strlen(str2)+1 : 0);
2600}
2601
2602////////////////////////////////////////////////////////////////////////////////
2603/// Case insensitive string compare of n characters.
2604
2605int strncasecmp(const char *str1, const char *str2, Ssiz_t n)
2606{
2607 while (n > 0) {
2608 int c1 = *str1;
2609 int c2 = *str2;
2610
2611 if (isupper(c1))
2612 c1 = tolower(c1);
2613
2614 if (isupper(c2))
2615 c2 = tolower(c2);
2616
2617 if (c1 != c2)
2618 return c1 - c2;
2619
2620 str1++;
2621 str2++;
2622 n--;
2623 }
2624 return 0;
2625}
2626#endif
2627
2628////////////////////////////////////////////////////////////////////////////////
2629/// Print a TString in the cling interpreter:
2630
2631std::string cling::printValue(const TString* val) {
2632 TString s = TString::Format("\"%s\"[%d]", val->Data(), (int)val->Length());
2633 return s.Data();
2634}
2635
2636////////////////////////////////////////////////////////////////////////////////
2637/// Print a TString in the cling interpreter:
2638
2639std::string cling::printValue(const TSubString* val) {
2640 TString s = TString::Format("\"%.*s\"[%d]", (int)val->Length(), val->Data(), (int)val->Length());
2641 return s.Data();
2642}
2643
2644////////////////////////////////////////////////////////////////////////////////
2645/// Print a TString in the cling interpreter:
2646
2647std::string cling::printValue(const std::string_view* val) {
2648 std::string str(*val);
2649 TString s = TString::Format("\"%s\"[%d]", str.c_str(), (int)val->length());
2650 return s.Data();
2651}
void frombuf(char *&buf, Bool_t *x)
Definition: Bytes.h:278
void tobuf(char *&buf, Bool_t x)
Definition: Bytes.h:55
void Class()
Definition: Class.C:29
uint8_t
Definition: Converters.cxx:876
ROOT::R::TRInterface & r
Definition: Object.C:4
#define R__ALWAYS_INLINE
Definition: RConfig.hxx:561
#define d(i)
Definition: RSha256.hxx:102
#define b(i)
Definition: RSha256.hxx:100
#define f(i)
Definition: RSha256.hxx:104
#define c(i)
Definition: RSha256.hxx:101
#define s1(x)
Definition: RSha256.hxx:91
#define h(i)
Definition: RSha256.hxx:106
const Ssiz_t kNPOS
Definition: RtypesCore.h:124
int Int_t
Definition: RtypesCore.h:45
unsigned char UChar_t
Definition: RtypesCore.h:38
int Ssiz_t
Definition: RtypesCore.h:67
unsigned long ULongptr_t
Definition: RtypesCore.h:83
unsigned int UInt_t
Definition: RtypesCore.h:46
const Bool_t kFALSE
Definition: RtypesCore.h:101
bool Bool_t
Definition: RtypesCore.h:63
const ULong_t kBitsPerByte
Definition: RtypesCore.h:123
double Double_t
Definition: RtypesCore.h:59
long long Long64_t
Definition: RtypesCore.h:80
unsigned long long ULong64_t
Definition: RtypesCore.h:81
const Bool_t kTRUE
Definition: RtypesCore.h:100
#define ClassImp(name)
Definition: Rtypes.h:364
#define R__ASSERT(e)
Definition: TError.h:118
const Int_t kPrint
Definition: TError.h:43
void ErrorHandler(int level, const char *location, const char *fmt, std::va_list va)
General error handler function. It calls the user set error handler.
Definition: TError.cxx:111
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition: TError.cxx:187
R__EXTERN Bool_t gPrintViaErrorHandler
Definition: TError.h:129
void Obsolete(const char *function, const char *asOfVers, const char *removedFromVers)
Use this function to declare a function obsolete.
Definition: TError.cxx:179
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition: TError.cxx:231
float * q
Definition: THbookFile.cxx:89
const UInt_t kHashShift
Definition: TString.cxx:69
TBuffer & operator<<(TBuffer &buf, const TString *s)
Write TString or derived to TBuffer.
Definition: TString.cxx:1428
uint64_t rotl64(uint64_t x, int8_t r)
Definition: TString.cxx:705
TString ToLower(const TString &str)
Return a lower-case version of str.
Definition: TString.cxx:1455
char * Compress(const char *str)
Remove all blanks from the string str.
Definition: TString.cxx:2530
TString operator+(const TString &s, const char *cs)
Use the special concatenation constructor.
Definition: TString.cxx:1483
#define ROTL64(x, y)
Definition: TString.cxx:710
static int MemIsEqual(const char *p, const char *q, Ssiz_t n)
Returns false if strings are not equal.
Definition: TString.cxx:870
TBuffer & operator>>(TBuffer &buf, TString *&s)
Read string from TBuffer. Function declared in ClassDef.
Definition: TString.cxx:1419
#define BIG_CONSTANT(x)
Definition: TString.cxx:711
Bool_t operator==(const TString &s1, const char *s2)
Compare TString with a char *.
Definition: TString.cxx:1440
int UnEscChar(const char *src, char *dst, int dstlen, char *specchars, char)
Un-escape specchars in src from escchar and copy to dst.
Definition: TString.cxx:2575
UInt_t Hash(const char *str)
Return a case-sensitive hash value (endian independent).
Definition: TString.cxx:561
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2515
static char * SlowFormat(const char *format, va_list ap, int hint)
Format a string in a formatting buffer (using a printf style format descriptor).
Definition: TString.cxx:2352
int EscChar(const char *src, char *dst, int dstlen, char *specchars, char escchar)
Escape specchars in src with escchar and copy to dst.
Definition: TString.cxx:2551
TString ToUpper(const TString &str)
Return an upper-case version of str.
Definition: TString.cxx:1469
static UInt_t SwapInt(UInt_t x)
Definition: TString.cxx:541
void Printf(const char *va_(fmt),...)
Formats a string in a circular formatting buffer and prints the string.
Definition: TString.cxx:2461
static void Mash(UInt_t &hash, UInt_t chars)
Utility used by Hash().
Definition: TString.cxx:551
#define R__VA_COPY(to, from)
Definition: Varargs.h:56
#define va_(arg)
Definition: Varargs.h:41
Buffer base class used for serializing objects.
Definition: TBuffer.h:43
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:80
void * New(ENewType defConstructor=kClassNew, Bool_t quiet=kFALSE) const
Return a pointer to a newly allocated object of this class.
Definition: TClass.cxx:4971
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
This code implements the MD5 message-digest algorithm.
Definition: TMD5.h:44
const char * AsString() const
Return message digest as string.
Definition: TMD5.cxx:220
void Update(const UChar_t *buf, UInt_t len)
Update TMD5 object to reflect the concatenation of another buffer full of bytes.
Definition: TMD5.cxx:108
void Final()
MD5 finalization, ends an MD5 message-digest operation, writing the the message digest and zeroizing ...
Definition: TMD5.cxx:167
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
An array of TObjects.
Definition: TObjArray.h:37
void Add(TObject *obj)
Definition: TObjArray.h:74
Collectable string class.
Definition: TObjString.h:28
Basic string class.
Definition: TString.h:136
TString Copy() const
Copy a string.
Definition: TString.cxx:514
static TString UItoa(UInt_t value, Int_t base)
Converts a UInt_t (twice the range of an Int_t) to a TString with respect to the base specified (2-36...
Definition: TString.cxx:2077
Ssiz_t Length() const
Definition: TString.h:410
friend class TSubString
Definition: TString.h:139
static TString LLtoa(Long64_t value, Int_t base)
Converts a Long64_t to a TString with respect to the base specified (2-36).
Definition: TString.cxx:2102
Rep_t fRep
Definition: TString.h:214
void SetShortSize(Ssiz_t s)
Definition: TString.h:234
char & operator()(Ssiz_t i)
Definition: TString.h:714
Bool_t IsDec() const
Returns true if all characters in string are decimal digits (0-9).
Definition: TString.cxx:1898
Bool_t IsLong() const
Definition: TString.h:229
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1150
int CompareTo(const char *cs, ECaseCompare cmp=kExact) const
Compare a string to char *cs2.
Definition: TString.cxx:442
static Ssiz_t MaxWaste(Ssiz_t mw=15)
Set maximum space that may be wasted in a string before doing a resize.
Definition: TString.cxx:1570
Int_t Atoi() const
Return integer value of string.
Definition: TString.cxx:1946
void SetLongSize(Ssiz_t s)
Definition: TString.h:237
static const Ssiz_t kNPOS
Definition: TString.h:269
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2202
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1131
TString()
TString default ctor.
Definition: TString.cxx:88
Bool_t IsHex() const
Returns true if all characters in string are hexadecimal digits (0-9,a-f,A-F).
Definition: TString.cxx:1850
Double_t Atof() const
Return floating-point value contained in string.
Definition: TString.cxx:2012
Bool_t IsFloat() const
Returns kTRUE if string contains a floating point or integer number.
Definition: TString.cxx:1816
void Clear()
Clear string without changing its capacity.
Definition: TString.cxx:1201
TSubString SubString(const char *pat, Ssiz_t start=0, ECaseCompare cmp=kExact) const
Returns a substring matching "pattern", or the null substring if there is no such match.
Definition: TString.cxx:1615
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition: TString.h:682
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition: TString.cxx:523
const char * Data() const
Definition: TString.h:369
static TString * ReadString(TBuffer &b, const TClass *clReq)
Read TString object from buffer.
Definition: TString.cxx:1320
Bool_t IsDigit() const
Returns true if all characters in string are digits (0-9) or white spaces, i.e.
Definition: TString.cxx:1788
Bool_t MaybeRegexp() const
Returns true if string contains one of the regexp characters "^$.[]*+?".
Definition: TString.cxx:937
static Ssiz_t ResizeIncrement(Ssiz_t ri=16)
Set default resize increment for all TStrings. Default is 16.
Definition: TString.cxx:1560
UInt_t HashCase() const
Return a case-sensitive hash value (endian independent).
Definition: TString.cxx:618
Bool_t IsOct() const
Returns true if all characters in string are octal digits (0-7).
Definition: TString.cxx:1882
virtual ~TString()
Delete a TString.
Definition: TString.cxx:242
Ssiz_t Capacity() const
Definition: TString.h:357
static Ssiz_t GetMaxWaste()
Definition: TString.cxx:1542
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:692
static Ssiz_t AdjustCapacity(Ssiz_t oldCap, Ssiz_t newCap)
Calculate a nice capacity greater than or equal to newCap.
Definition: TString.cxx:1186
TString MD5() const
Return the MD5 digest for this string, in a string representation.
Definition: TString.cxx:925
void Resize(Ssiz_t n)
Resize the string. Truncate or add blanks as necessary.
Definition: TString.cxx:1120
EStripType
Definition: TString.h:267
@ kLeading
Definition: TString.h:267
@ kTrailing
Definition: TString.h:267
ECaseCompare
Definition: TString.h:268
@ kExact
Definition: TString.h:268
Bool_t IsAlpha() const
Returns true if all characters in string are alphabetic.
Definition: TString.cxx:1756
UInt_t HashFoldCase() const
Return a case-insensitive hash value (endian independent).
Definition: TString.cxx:647
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:916
void ToUpper()
Change string to upper case.
Definition: TString.cxx:1163
Bool_t IsAscii() const
Returns true if all characters in string are ascii.
Definition: TString.cxx:1743
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2222
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:615
static Ssiz_t GetResizeIncrement()
Definition: TString.cxx:1534
void SetLongCap(Ssiz_t s)
Definition: TString.h:240
@ kAlignment
Definition: TString.h:223
TString & Prepend(const char *cs)
Definition: TString.h:661
Bool_t IsBin() const
Returns true if all characters in string are binary digits (0,1).
Definition: TString.cxx:1866
void UnLink() const
Definition: TString.h:254
static TString BaseConvert(const TString &s_in, Int_t base_in, Int_t base_out)
Converts string from base base_in to base base_out.
Definition: TString.cxx:2152
static TString ULLtoa(ULong64_t value, Int_t base)
Converts a ULong64_t (twice the range of an Long64_t) to a TString with respect to the base specified...
Definition: TString.cxx:2129
Int_t CountChar(Int_t c) const
Return number of times character c occurs in the string.
Definition: TString.cxx:500
UInt_t Hash(ECaseCompare cmp=kExact) const
Return hash value.
Definition: TString.cxx:662
static void WriteString(TBuffer &b, const TString *a)
Write TString object to buffer.
Definition: TString.cxx:1386
virtual void FillBuffer(char *&buffer) const
Copy string into I/O buffer.
Definition: TString.cxx:1268
TString & operator=(char s)
Assign character c to TString.
Definition: TString.cxx:287
TString & Remove(Ssiz_t pos)
Definition: TString.h:673
static Ssiz_t InitialCapacity(Ssiz_t ic=15)
Set default initial capacity for all TStrings. Default is 15.
Definition: TString.cxx:1551
char * GetShortPointer()
Definition: TString.h:245
TString & Append(const char *cs)
Definition: TString.h:564
Bool_t IsInBaseN(Int_t base) const
Returns true if all characters in string are expressed in the base specified (range=2-36),...
Definition: TString.cxx:1915
char * Init(Ssiz_t capacity, Ssiz_t nchar)
Private member function returning an empty string representation of size capacity and containing ncha...
Definition: TString.cxx:251
Bool_t MaybeWildcard() const
Returns true if string contains one of the wildcard characters "[]*?".
Definition: TString.cxx:949
void InitChar(char c)
Initialize a string with a single character.
Definition: TString.cxx:144
static Ssiz_t MaxSize()
Definition: TString.h:252
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition: TString.cxx:2336
char * GetLongPointer()
Definition: TString.h:243
static TString Itoa(Int_t value, Int_t base)
Converts an Int_t to a TString with respect to the base specified (2-36).
Definition: TString.cxx:2050
virtual Int_t Sizeof() const
Returns size string will occupy on I/O buffer.
Definition: TString.cxx:1359
void Clone(Ssiz_t nc)
Make self a distinct copy with capacity of at least tot, where tot cannot be smaller than the current...
Definition: TString.cxx:1237
void SetSize(Ssiz_t s)
Definition: TString.h:239
void Zero()
Definition: TString.h:255
void SetLongPointer(char *p)
Definition: TString.h:242
Ssiz_t GetLongSize() const
Definition: TString.h:238
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2314
static Ssiz_t GetInitialCapacity()
Definition: TString.cxx:1526
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:624
void AssertElement(Ssiz_t nc) const
Check to make sure a string index is in range.
Definition: TString.cxx:1176
virtual void ReadBuffer(char *&buffer)
Read string from I/O buffer.
Definition: TString.cxx:1289
Bool_t IsAlnum() const
Returns true if all characters in string are alphanumeric.
Definition: TString.cxx:1771
void FormImp(const char *fmt, va_list ap)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2268
char * GetPointer()
Definition: TString.h:247
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:639
void Clobber(Ssiz_t nc)
Clear string and make sure it has a capacity of nc.
Definition: TString.cxx:1209
static Ssiz_t Recommend(Ssiz_t s)
Definition: TString.h:225
Long64_t Atoll() const
Return long long value of string.
Definition: TString.cxx:1972
A zero length substring is legal.
Definition: TString.h:82
TSubString(const TString &s, Ssiz_t start, Ssiz_t len)
Private constructor.
Definition: TString.cxx:1589
TSubString & operator=(const char *s)
Assign char* to sub-string.
Definition: TString.cxx:1654
Bool_t IsNull() const
Definition: TString.h:126
void ToUpper()
Convert sub-string to upper-case.
Definition: TString.cxx:1712
TString & fStr
Definition: TString.h:92
void SubStringError(Ssiz_t, Ssiz_t, Ssiz_t) const
Output error message.
Definition: TString.cxx:1724
Ssiz_t fBegin
Definition: TString.h:93
char & operator[](Ssiz_t i)
Return character at pos i from sub-string. Check validity of i.
Definition: TString.cxx:1626
Ssiz_t fExtent
Definition: TString.h:94
void AssertElement(Ssiz_t i) const
Check to make sure a sub-string index is in range.
Definition: TString.cxx:1733
void ToLower()
Convert sub-string to lower-case.
Definition: TString.cxx:1700
const char * Data() const
Definition: TString.h:726
char & operator()(Ssiz_t i)
Return character at pos i from sub-string. No check on i.
Definition: TString.cxx:1635
Ssiz_t Length() const
Definition: TString.h:119
return c1
Definition: legend1.C:41
Double_t x[n]
Definition: legend1.C:17
const Int_t n
Definition: legend1.C:16
TH1F * h1
Definition: legend1.C:5
return c2
Definition: legend2.C:14
basic_string_view< char > string_view
static const std::string pattern("pattern")
static constexpr double sr
static constexpr double s
static constexpr double ms
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:208
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:176
Short_t Abs(Short_t d)
Definition: TMathBase.h:120
Definition: first.py:1
RawStr_t fRaw
Definition: TString.h:208
auto * l
Definition: textangle.C:4
auto * a
Definition: textangle.C:12
auto * t1
Definition: textangle.C:20