Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
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 
15 Basic string class.
16 
17 Cannot be stored in a TCollection... use TObjString instead.
18 
19 The underlying string is stored as a char* that can be accessed via
20 TString::Data().
21 TString provides Short String Optimization (SSO) so that short
22 strings (<15 on 64-bit and <11 on 32-bit) are contained in the
23 TString internal data structure without the need for mallocing the
24 required space.
25 
26 Substring operations are provided by the TSubString class, which
27 holds a reference to the original string and its data, along with
28 the offset and length of the substring. To retrieve the substring
29 as 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
62 namespace std { using ::list; }
63 #endif
64 
65 ClassImp(TString);
66 
67 // Amount to shift hash values to avoid clustering
68 const UInt_t kHashShift = 5;
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 
87 TString::TString()
88 {
89  Zero();
90 }
91 
92 ////////////////////////////////////////////////////////////////////////////////
93 /// Create TString able to contain ic characters.
94 
95 TString::TString(Ssiz_t ic)
96 {
97  Init(ic, 0);
98 }
99 
100 ////////////////////////////////////////////////////////////////////////////////
101 /// Create TString and initialize it with string cs.
102 
103 TString::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 
116 TString::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 
126 TString::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 
139 void TString::InitChar(char c)
140 {
141  char *data = Init(1, 1);
142  data[0] = c;
143 }
144 
145 ////////////////////////////////////////////////////////////////////////////////
146 /// Initialize a string with a single character.
147 
148 TString::TString(char c)
149 {
150  InitChar(c);
151 }
152 
153 ////////////////////////////////////////////////////////////////////////////////
154 /// Initialize the first n locations of a TString with character c.
155 
156 TString::TString(char c, Ssiz_t n)
157 {
158  char *data = Init(n, n);
159  while (n--) data[n] = c;
160 }
161 
162 ////////////////////////////////////////////////////////////////////////////////
163 /// Copy constructor.
164 
165 TString::TString(const TString &s)
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 
179 TString::TString(TString &&s) noexcept
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 
189 TString::TString(const std::string_view& substr)
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 
199 TString::TString(const TSubString& substr)
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 
209 TString::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 
230 TString::~TString()
231 {
232  UnLink();
233 }
234 
235 ////////////////////////////////////////////////////////////////////////////////
236 /// Private member function returning an empty string representation of
237 /// size capacity and containing nchar characters.
238 
239 char *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 
267 TString& TString::operator=(char c)
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 
280 TString& TString::operator=(const char *cs)
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 
293 TString& 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 
306 TString& TString::operator=(const std::string_view &s)
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 
319 TString& TString::operator=(const TString &rhs)
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 
337 TString& TString::operator=(TString &&rhs) noexcept
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 
348 TString& TString::operator=(const TSubString &substr)
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 
362 TString& TString::Append(char c, Ssiz_t rep)
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 
403 Ssiz_t TString::Capacity(Ssiz_t nc)
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 
418 int 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 
448 int 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 
476 Int_t TString::CountChar(Int_t c) const
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 
490 TString TString::Copy() const
491 {
492  TString temp(*this);
493  return temp;
494 }
495 
496 ////////////////////////////////////////////////////////////////////////////////
497 /// Find first occurrence of a character c.
498 
499 Ssiz_t TString::First(char c) const
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 
508 Ssiz_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 
517 inline 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 
527 inline 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 
537 UInt_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 
594 UInt_t TString::HashCase() const
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 
623 UInt_t TString::HashFoldCase() const
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 
638 UInt_t TString::Hash(ECaseCompare cmp) const
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 
690 namespace {
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 
811 UInt_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 
846 static 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 
862 Ssiz_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 
892 Ssiz_t TString::Last(char c) const
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 
901 TString TString::MD5() const
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 
913 Bool_t TString::MaybeRegexp() const
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 
925 Bool_t TString::MaybeWildcard() const
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 
937 TString& TString::Prepend(char c, Ssiz_t rep)
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 
979 TString &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);
1028 finish:
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 
1050 TString& 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 
1067 TString &TString::Remove(EStripType st, char c)
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 
1095 void TString::Resize(Ssiz_t n)
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 
1106 TSubString TString::Strip(EStripType st, char c) const
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 
1125 void TString::ToLower()
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 
1138 void TString::ToUpper()
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 
1151 void TString::AssertElement(Ssiz_t i) const
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 
1161 Ssiz_t TString::AdjustCapacity(Ssiz_t oldCap, Ssiz_t newCap)
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 
1176 void TString::Clear()
1177 {
1178  Clobber(Capacity());
1179 }
1180 
1181 ////////////////////////////////////////////////////////////////////////////////
1182 /// Clear string and make sure it has a capacity of nc.
1183 
1184 void TString::Clobber(Ssiz_t nc)
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 
1212 void TString::Clone(Ssiz_t tot)
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 
1243 void 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 
1264 void 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 
1295 TString *TString::ReadString(TBuffer &b, const TClass *clReq)
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 
1334 Int_t TString::Sizeof() const
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 
1345 void 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 
1361 void TString::WriteString(TBuffer &b, const TString *a)
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)
1392 template <>
1393 #endif
1394 TBuffer &operator>>(TBuffer &buf, TString *&s)
1395 {
1396  s = (TString *) TString::ReadString(buf, TString::Class());
1397  return buf;
1398 }
1399 
1400 ////////////////////////////////////////////////////////////////////////////////
1401 /// Write TString or derived to TBuffer.
1402 
1403 TBuffer &operator<<(TBuffer &buf, const TString *s)
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 
1415 Bool_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 
1430 TString ToLower(const TString &str)
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 
1444 TString ToUpper(const TString &str)
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 
1458 TString 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 
1466 TString 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 
1474 TString operator+(const TString &s1, const TString &s2)
1475 {
1476  return TString(s1.Data(), s1.Length(), s2.Data(), s2.Length());
1477 }
1478 
1479 ////////////////////////////////////////////////////////////////////////////////
1480 /// Add char to string.
1481 
1482 TString operator+(const TString &s, char c)
1483 {
1484  return TString(s.Data(), s.Length(), &c, 1);
1485 }
1486 
1487 ////////////////////////////////////////////////////////////////////////////////
1488 /// Add string to char.
1489 
1490 TString operator+(char c, const TString &s)
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 
1501 Ssiz_t TString::GetInitialCapacity()
1502 {
1503  ::Obsolete("TString::GetInitialCapacity", "v5-30-00", "v5-32-00");
1504  return 15;
1505 }
1506 
1507 ////////////////////////////////////////////////////////////////////////////////
1508 
1509 Ssiz_t TString::GetResizeIncrement()
1510 {
1511  ::Obsolete("TString::GetResizeIncrement", "v5-30-00", "v5-32-00");
1512  return 16;
1513 }
1514 
1515 ////////////////////////////////////////////////////////////////////////////////
1516 
1517 Ssiz_t TString::GetMaxWaste()
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 
1526 Ssiz_t TString::InitialCapacity(Ssiz_t)
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 
1535 Ssiz_t TString::ResizeIncrement(Ssiz_t)
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 
1545 Ssiz_t TString::MaxWaste(Ssiz_t)
1546 {
1547  ::Obsolete("TString::MaxWaste", "v5-30-00", "v5-32-00");
1548  return 15;
1549 }
1550 
1551 /** \class TSubString
1552 A zero length substring is legal. It can start
1553 at any character. It is considered to be "pointing"
1554 to just before the character.
1555 
1556 A "null" substring is a zero length substring that
1557 starts with the nonsense index kNPOS. It can
1558 be detected with the member function IsNull().
1559 */
1560 
1561 ////////////////////////////////////////////////////////////////////////////////
1562 /// Private constructor.
1563 
1564 TSubString::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 
1572 TSubString TString::operator()(Ssiz_t start, Ssiz_t len) const
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 
1590 TSubString 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 
1601 char& TSubString::operator[](Ssiz_t i)
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 
1610 char& TSubString::operator()(Ssiz_t i)
1611 {
1612  return fStr(fBegin+i);
1613 }
1614 
1615 ////////////////////////////////////////////////////////////////////////////////
1616 /// Assign string to sub-string.
1617 
1618 TSubString& TSubString::operator=(const TString &str)
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 
1629 TSubString& TSubString::operator=(const char *cs)
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 
1640 Bool_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 
1654 Bool_t operator==(const TSubString& ss, const TString &s)
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 
1664 Bool_t operator==(const TSubString &s1, const TSubString &s2)
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 
1675 void TSubString::ToLower()
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 
1687 void TSubString::ToUpper()
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 
1699 void TSubString::SubStringError(Ssiz_t sr, Ssiz_t start, Ssiz_t n) const
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 
1708 void TSubString::AssertElement(Ssiz_t i) const
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 
1718 Bool_t TString::IsAscii() const
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 
1731 Bool_t TString::IsAlpha() const
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 
1746 Bool_t TString::IsAlnum() const
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 
1763 Bool_t TString::IsDigit() const
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 
1791 Bool_t TString::IsFloat() const
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 
1825 Bool_t TString::IsHex() const
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 
1841 Bool_t TString::IsBin() const
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 
1857 Bool_t TString::IsOct() const
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 
1873 Bool_t TString::IsDec() const
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 
1890 Bool_t TString::IsInBaseN(Int_t base) const
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 
1921 Int_t TString::Atoi() const
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 
1947 Long64_t TString::Atoll() const
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 
1987 Double_t TString::Atof() const
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 
2025 TString TString::Itoa(Int_t value, Int_t base)
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 
2052 TString TString::UItoa(UInt_t value, Int_t base)
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 
2077 TString TString::LLtoa(Long64_t value, Int_t base)
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 
2104 TString TString::ULLtoa(ULong64_t value, Int_t base)
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 
2127 TString 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 
2177 Bool_t TString::EndsWith(const char *s, ECaseCompare cmp) const
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 
2197 TObjArray *TString::Tokenize(const TString &delim) const
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 
2243 void 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;
2252 again:
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 
2289 void 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 
2311 TString 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 
2327 static 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 
2375 static 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 
2422 char *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 
2436 void Printf(const char *va_(fmt), ...)
2437 {
2438  va_list ap;
2439  va_start(ap,va_(fmt));
2440  if (gPrintViaErrorHandler)
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 
2454 char *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 
2490 char *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 
2504 char *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 
2525 int 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 
2549 int 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 
2571 int 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 
2579 int 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 
2605 std::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 
2613 std::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 
2621 std::string cling::printValue(const std::string_view* val) {
2622  std::string str(*val);
2623  TString s = TString::Format("\"%s\"[%d]", str.c_str(), (int)val->length());
2624  return s.Data();
2625 }