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