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   	#ifndef ROOT_TString
13   	#define ROOT_TString
14   	
15   	
16   	//////////////////////////////////////////////////////////////////////////
17   	//                                                                      //
18   	// TString                                                              //
19   	//                                                                      //
20   	// Basic string class.                                                  //
21   	//                                                                      //
22   	// Cannot be stored in a TCollection... use TObjString instead.         //
23   	//                                                                      //
24   	//////////////////////////////////////////////////////////////////////////
25   	
26   	#ifndef __CINT__
27   	#include <string.h>
28   	#include <stdio.h>
29   	#endif
30   	
31   	#ifndef ROOT_Riosfwd
32   	#include "Riosfwd.h"
33   	#endif
34   	
35   	#ifndef ROOT_TMathBase
36   	#include "TMathBase.h"
37   	#endif
38   	
39   	#include <stdarg.h>
40   	#include <string>
41   	
42   	#ifdef R__GLOBALSTL
43   	namespace std { using ::string; }
44   	#endif
45   	
46   	class TRegexp;
47   	class TPRegexp;
48   	class TString;
49   	class TSubString;
50   	class TObjArray;
51   	class TVirtualMutex;
52   	class TBufferFile;
53   	
54   	R__EXTERN TVirtualMutex *gStringMutex;
55   	
56   	TString operator+(const TString &s1, const TString &s2);
57   	TString operator+(const TString &s,  const char *cs);
58   	TString operator+(const char *cs, const TString &s);
59   	TString operator+(const TString &s, char c);
60   	TString operator+(const TString &s, Long_t i);
61   	TString operator+(const TString &s, ULong_t i);
62   	TString operator+(const TString &s, Long64_t i);
63   	TString operator+(const TString &s, ULong64_t i);
64   	TString operator+(char c, const TString &s);
65   	TString operator+(Long_t i, const TString &s);
66   	TString operator+(ULong_t i, const TString &s);
67   	TString operator+(Long64_t i, const TString &s);
68   	TString operator+(ULong64_t i, const TString &s);
69   	Bool_t  operator==(const TString &s1, const TString &s2);
70   	Bool_t  operator==(const TString &s1, const char *s2);
71   	Bool_t  operator==(const TSubString &s1, const TSubString &s2);
72   	Bool_t  operator==(const TSubString &s1, const TString &s2);
73   	Bool_t  operator==(const TSubString &s1, const char *s2);
74   	
75   	
76   	//////////////////////////////////////////////////////////////////////////
77   	//                                                                      //
78   	//  TSubString                                                          //
79   	//                                                                      //
80   	//  The TSubString class allows selected elements to be addressed.      //
81   	//  There are no public constructors.                                   //
82   	//                                                                      //
83   	//////////////////////////////////////////////////////////////////////////
84   	class TSubString {
85   	
86   	friend class TStringLong;
87   	friend class TString;
88   	
89   	friend Bool_t operator==(const TSubString &s1, const TSubString &s2);
90   	friend Bool_t operator==(const TSubString &s1, const TString &s2);
91   	friend Bool_t operator==(const TSubString &s1, const char *s2);
92   	
93   	private:
94   	   TString      &fStr;           // Referenced string
95   	   Ssiz_t        fBegin;         // Index of starting character
96   	   Ssiz_t        fExtent;        // Length of TSubString
97   	
98   	   // NB: the only constructor is private
99   	   TSubString(const TString &s, Ssiz_t start, Ssiz_t len);
100  	
101  	protected:
102  	   void          SubStringError(Ssiz_t, Ssiz_t, Ssiz_t) const;
103  	   void          AssertElement(Ssiz_t i) const;  // Verifies i is valid index
104  	
105  	public:
106  	   TSubString(const TSubString &s)
107  	     : fStr(s.fStr), fBegin(s.fBegin), fExtent(s.fExtent) { }
108  	
109  	   TSubString   &operator=(const char *s);       // Assignment from a char*
110  	   TSubString   &operator=(const TString &s);    // Assignment from a TString
111  	   TSubString   &operator=(const TSubString &s); // Assignment from a TSubString
112  	   char         &operator()(Ssiz_t i);           // Index with optional bounds checking
113  	   char         &operator[](Ssiz_t i);           // Index with bounds checking
114  	   char          operator()(Ssiz_t i) const;     // Index with optional bounds checking
115  	   char          operator[](Ssiz_t i) const;     // Index with bounds checking
116  	
117  	   const char   *Data() const;
118  	   Ssiz_t        Length() const          { return fExtent; }
119  	   Ssiz_t        Start() const           { return fBegin; }
120  	   TString&      String()                { return fStr; }
121  	   void          ToLower();              // Convert self to lower-case
122  	   void          ToUpper();              // Convert self to upper-case
123  	
124  	   // For detecting null substrings
125  	   Bool_t        IsNull() const          { return fBegin == kNPOS; }
126  	   int           operator!() const       { return fBegin == kNPOS; }
127  	};
128  	
129  	
130  	//////////////////////////////////////////////////////////////////////////
131  	//                                                                      //
132  	//  TString                                                             //
133  	//                                                                      //
134  	//////////////////////////////////////////////////////////////////////////
135  	class TString {
136  	
137  	friend class TStringLong;
138  	friend class TSubString;
139  	friend class TBufferFile;
140  	
141  	friend TString operator+(const TString &s1, const TString &s2);
142  	friend TString operator+(const TString &s,  const char *cs);
143  	friend TString operator+(const char *cs, const TString &s);
144  	friend TString operator+(const TString &s, char c);
145  	friend TString operator+(const TString &s, Long_t i);
146  	friend TString operator+(const TString &s, ULong_t i);
147  	friend TString operator+(const TString &s, Long64_t i);
148  	friend TString operator+(const TString &s, ULong64_t i);
149  	friend TString operator+(char c, const TString &s);
150  	friend TString operator+(Long_t i, const TString &s);
151  	friend TString operator+(ULong_t i, const TString &s);
152  	friend TString operator+(Long64_t i, const TString &s);
153  	friend TString operator+(ULong64_t i, const TString &s);
154  	friend Bool_t  operator==(const TString &s1, const TString &s2);
155  	friend Bool_t  operator==(const TString &s1, const char *s2);
156  	
157  	private:
158  	#ifdef R__BYTESWAP
159  	   enum { kShortMask = 0x01, kLongMask  = 0x1 };
160  	#else
161  	   enum { kShortMask = 0x80, kLongMask  = 0x80000000 };
162  	#endif
163  	
164  	   struct LongStr_t
165  	   {
166  	      Ssiz_t    fCap;    // Max string length (including null)
167  	      Ssiz_t    fSize;   // String length (excluding null)
168  	      char     *fData;   // Long string data
169  	   };
170  	
171  	   enum { kMinCap = (sizeof(LongStr_t) - 1)/sizeof(char) > 2 ?
172  	                    (sizeof(LongStr_t) - 1)/sizeof(char) : 2 };
173  	
174  	   struct ShortStr_t
175  	   {
176  	      unsigned char fSize;           // String length (excluding null)
177  	      char          fData[kMinCap];  // Short string data
178  	   };
179  	
180  	   union UStr_t { LongStr_t fL; ShortStr_t fS; };
181  	
182  	   enum { kNwords = sizeof(UStr_t) / sizeof(Ssiz_t)};
183  	
184  	   struct RawStr_t
185  	   {
186  	      Ssiz_t fWords[kNwords];
187  	   };
188  	
189  	   struct Rep_t
190  	   {
191  	      union
192  	      {
193  	         LongStr_t  fLong;
194  	         ShortStr_t fShort;
195  	         RawStr_t   fRaw;
196  	      };
197  	   };
198  	
199  	protected:
200  	#ifndef __CINT__
201  	   Rep_t          fRep;           // String data
202  	#endif
203  	
204  	   // Special concatenation constructor
205  	   TString(const char *a1, Ssiz_t n1, const char *a2, Ssiz_t n2);
206  	   void           AssertElement(Ssiz_t nc) const; // Index in range
207  	   void           Clobber(Ssiz_t nc);             // Remove old contents
208  	   void           InitChar(char c);               // Initialize from char
209  	
210  	   enum { kAlignment = 16 };
211  	   static Ssiz_t  Align(Ssiz_t s) { return (s + (kAlignment-1)) & ~(kAlignment-1); }
212  	   static Ssiz_t  Recommend(Ssiz_t s) { return (s < kMinCap ? kMinCap : Align(s+1)) - 1; }
213  	   static Ssiz_t  AdjustCapacity(Ssiz_t oldCap, Ssiz_t newCap);
214  	
215  	private:
216  	   Bool_t         IsLong() const { return Bool_t(fRep.fShort.fSize & kShortMask); }
217  	#ifdef R__BYTESWAP
218  	   void           SetShortSize(Ssiz_t s) { fRep.fShort.fSize = (unsigned char)(s << 1); }
219  	   Ssiz_t         GetShortSize() const { return fRep.fShort.fSize >> 1; }
220  	#else
221  	   void           SetShortSize(Ssiz_t s) { fRep.fShort.fSize = (unsigned char)s; }
222  	   Ssiz_t         GetShortSize() const { return fRep.fShort.fSize; }
223  	#endif
224  	   void           SetLongSize(Ssiz_t s) { fRep.fLong.fSize = s; }
225  	   Ssiz_t         GetLongSize() const { return fRep.fLong.fSize; }
226  	   void           SetSize(Ssiz_t s) { IsLong() ? SetLongSize(s) : SetShortSize(s); }
227  	   void           SetLongCap(Ssiz_t s) { fRep.fLong.fCap = kLongMask | s; }
228  	   Ssiz_t         GetLongCap() const { return fRep.fLong.fCap & ~kLongMask; }
229  	   void           SetLongPointer(char *p) { fRep.fLong.fData = p; }
230  	   char          *GetLongPointer() { return fRep.fLong.fData; }
231  	   const char    *GetLongPointer() const { return fRep.fLong.fData; }
232  	   char          *GetShortPointer() { return fRep.fShort.fData; }
233  	   const char    *GetShortPointer() const { return fRep.fShort.fData; }
234  	   char          *GetPointer() { return IsLong() ? GetLongPointer() : GetShortPointer(); }
235  	   const char    *GetPointer() const { return IsLong() ? GetLongPointer() : GetShortPointer(); }
236  	#ifdef R__BYTESWAP
237  	   static Ssiz_t  MaxSize() { return kMaxInt - 1; }
238  	#else
239  	   static Ssiz_t  MaxSize() { return (kMaxInt >> 1) - 1; }
240  	#endif
241  	   void           UnLink() const { if (IsLong()) delete [] fRep.fLong.fData; }
242  	   void           Zero() {
243  	      Ssiz_t (&a)[kNwords] = fRep.fRaw.fWords;
244  	      for (UInt_t i = 0; i < kNwords; ++i)
245  	         a[i] = 0;
246  	   }
247  	   char          *Init(Ssiz_t capacity, Ssiz_t nchar);
248  	   void           Clone(Ssiz_t nc); // Make self a distinct copy w. capacity nc
249  	   void           FormImp(const char *fmt, va_list ap);
250  	   UInt_t         HashCase() const;
251  	   UInt_t         HashFoldCase() const;
252  	
253  	public:
254  	   enum EStripType   { kLeading = 0x1, kTrailing = 0x2, kBoth = 0x3 };
255  	   enum ECaseCompare { kExact, kIgnoreCase };
256  	
257  	   TString();                           // Null string
258  	   explicit TString(Ssiz_t ic);         // Suggested capacity
259  	   TString(const TString &s);           // Copy constructor
260  	   TString(const char *s);              // Copy to embedded null
261  	   TString(const char *s, Ssiz_t n);    // Copy past any embedded nulls
262  	   TString(const std::string &s);
263  	   TString(char c);
264  	   TString(char c, Ssiz_t s);
265  	   TString(const TSubString &sub);
266  	
267  	   virtual ~TString();
268  	
269  	   // ROOT I/O interface
270  	   virtual void     FillBuffer(char *&buffer) const;
271  	   virtual void     ReadBuffer(char *&buffer);
272  	   virtual Int_t    Sizeof() const;
273  	
274  	   static TString  *ReadString(TBuffer &b, const TClass *clReq);
275  	   static void      WriteString(TBuffer &b, const TString *a);
276  	
277  	   friend TBuffer &operator<<(TBuffer &b, const TString *obj);
278  	
279  	   // C I/O interface
280  	   Bool_t   Gets(FILE *fp, Bool_t chop=kTRUE);
281  	   void     Puts(FILE *fp);
282  	
283  	   // Type conversion
284  	   operator const char*() const { return GetPointer(); }
285  	
286  	   // Assignment
287  	   TString    &operator=(char s);                // Replace string
288  	   TString    &operator=(const char *s);
289  	   TString    &operator=(const TString &s);
290  	   TString    &operator=(const std::string &s);
291  	   TString    &operator=(const TSubString &s);
292  	   TString    &operator+=(const char *s);        // Append string
293  	   TString    &operator+=(const TString &s);
294  	   TString    &operator+=(char c);
295  	   TString    &operator+=(Short_t i);
296  	   TString    &operator+=(UShort_t i);
297  	   TString    &operator+=(Int_t i);
298  	   TString    &operator+=(UInt_t i);
299  	   TString    &operator+=(Long_t i);
300  	   TString    &operator+=(ULong_t i);
301  	   TString    &operator+=(Float_t f);
302  	   TString    &operator+=(Double_t f);
303  	   TString    &operator+=(Long64_t i);
304  	   TString    &operator+=(ULong64_t i);
305  	
306  	   // Indexing operators
307  	   char         &operator[](Ssiz_t i);         // Indexing with bounds checking
308  	   char         &operator()(Ssiz_t i);         // Indexing with optional bounds checking
309  	   char          operator[](Ssiz_t i) const;
310  	   char          operator()(Ssiz_t i) const;
311  	   TSubString    operator()(Ssiz_t start, Ssiz_t len) const;   // Sub-string operator
312  	   TSubString    operator()(const TRegexp &re) const;          // Match the RE
313  	   TSubString    operator()(const TRegexp &re, Ssiz_t start) const;
314  	   TSubString    operator()(TPRegexp &re) const;               // Match the Perl compatible Regular Expression
315  	   TSubString    operator()(TPRegexp &re, Ssiz_t start) const;
316  	   TSubString    SubString(const char *pat, Ssiz_t start = 0,
317  	                           ECaseCompare cmp = kExact) const;
318  	
319  	   // Non-static member functions
320  	   TString     &Append(const char *cs);
321  	   TString     &Append(const char *cs, Ssiz_t n);
322  	   TString     &Append(const TString &s);
323  	   TString     &Append(const TString &s, Ssiz_t n);
324  	   TString     &Append(char c, Ssiz_t rep = 1);   // Append c rep times
325  	   Int_t        Atoi() const;
326  	   Long64_t     Atoll() const;
327  	   Double_t     Atof() const;
328  	   Bool_t       BeginsWith(const char *s,      ECaseCompare cmp = kExact) const;
329  	   Bool_t       BeginsWith(const TString &pat, ECaseCompare cmp = kExact) const;
330  	   Ssiz_t       Capacity() const { return (IsLong() ? GetLongCap() : kMinCap) - 1; }
331  	   Ssiz_t       Capacity(Ssiz_t n);
332  	   TString     &Chop();
333  	   void         Clear();
334  	   int          CompareTo(const char *cs,    ECaseCompare cmp = kExact) const;
335  	   int          CompareTo(const TString &st, ECaseCompare cmp = kExact) const;
336  	   Bool_t       Contains(const char *pat,    ECaseCompare cmp = kExact) const;
337  	   Bool_t       Contains(const TString &pat, ECaseCompare cmp = kExact) const;
338  	   Bool_t       Contains(const TRegexp &pat) const;
339  	   Bool_t       Contains(TPRegexp &pat) const;
340  	   Int_t        CountChar(Int_t c) const;
341  	   TString      Copy() const;
342  	   const char  *Data() const { return GetPointer(); }
343  	   Bool_t       EndsWith(const char *pat, ECaseCompare cmp = kExact) const;
344  	   Bool_t       EqualTo(const char *cs,    ECaseCompare cmp = kExact) const;
345  	   Bool_t       EqualTo(const TString &st, ECaseCompare cmp = kExact) const;
346  	   Ssiz_t       First(char c) const;
347  	   Ssiz_t       First(const char *cs) const;
348  	   void         Form(const char *fmt, ...)
349  	#if defined(__GNUC__) && !defined(__CINT__)
350  	   __attribute__((format(printf, 2, 3)))   /* 1 is the this pointer */
351  	#endif
352  	   ;
353  	   UInt_t       Hash(ECaseCompare cmp = kExact) const;
354  	   Ssiz_t       Index(const char *pat, Ssiz_t i = 0,
355  	                      ECaseCompare cmp = kExact) const;
356  	   Ssiz_t       Index(const TString &s, Ssiz_t i = 0,
357  	                      ECaseCompare cmp = kExact) const;
358  	   Ssiz_t       Index(const char *pat, Ssiz_t patlen, Ssiz_t i,
359  	                      ECaseCompare cmp) const;
360  	   Ssiz_t       Index(const TString &s, Ssiz_t patlen, Ssiz_t i,
361  	                      ECaseCompare cmp) const;
362  	   Ssiz_t       Index(const TRegexp &pat, Ssiz_t i = 0) const;
363  	   Ssiz_t       Index(const TRegexp &pat, Ssiz_t *ext, Ssiz_t i = 0) const;
364  	   Ssiz_t       Index(TPRegexp &pat, Ssiz_t i = 0) const;
365  	   Ssiz_t       Index(TPRegexp &pat, Ssiz_t *ext, Ssiz_t i = 0) const;
366  	   TString     &Insert(Ssiz_t pos, const char *s);
367  	   TString     &Insert(Ssiz_t pos, const char *s, Ssiz_t extent);
368  	   TString     &Insert(Ssiz_t pos, const TString &s);
369  	   TString     &Insert(Ssiz_t pos, const TString &s, Ssiz_t extent);
370  	   Bool_t       IsAscii() const;
371  	   Bool_t       IsAlpha() const;
372  	   Bool_t       IsAlnum() const;
373  	   Bool_t       IsDigit() const;
374  	   Bool_t       IsFloat() const;
375  	   Bool_t       IsHex() const;
376  	   Bool_t       IsBin() const;
377  	   Bool_t       IsOct() const;
378  	   Bool_t       IsDec() const;
379  	   Bool_t       IsInBaseN(Int_t base) const;
380  	   Bool_t       IsNull() const         { return Length() == 0; }
381  	   Bool_t       IsWhitespace() const   { return (Length() == CountChar(' ')); }
382  	   Ssiz_t       Last(char c) const;
383  	   Ssiz_t       Length() const         { return IsLong() ? GetLongSize() : GetShortSize(); }
384  	   Bool_t       MaybeRegexp() const;
385  	   Bool_t       MaybeWildcard() const;
386  	   TString      MD5() const;
387  	   TString     &Prepend(const char *cs);     // Prepend a character string
388  	   TString     &Prepend(const char *cs, Ssiz_t n);
389  	   TString     &Prepend(const TString &s);
390  	   TString     &Prepend(const TString &s, Ssiz_t n);
391  	   TString     &Prepend(char c, Ssiz_t rep = 1);  // Prepend c rep times
392  	   istream     &ReadFile(istream &str);      // Read to EOF or null character
393  	   istream     &ReadLine(istream &str,
394  	                         Bool_t skipWhite = kTRUE);   // Read to EOF or newline
395  	   istream     &ReadString(istream &str);             // Read to EOF or null character
396  	   istream     &ReadToDelim(istream &str, char delim = '\n'); // Read to EOF or delimitor
397  	   istream     &ReadToken(istream &str);                // Read separated by white space
398  	   TString     &Remove(Ssiz_t pos);                     // Remove pos to end of string
399  	   TString     &Remove(Ssiz_t pos, Ssiz_t n);           // Remove n chars starting at pos
400  	   TString     &Remove(EStripType s, char c);           // Like Strip() but changing string directly
401  	   TString     &Replace(Ssiz_t pos, Ssiz_t n, const char *s);
402  	   TString     &Replace(Ssiz_t pos, Ssiz_t n, const char *s, Ssiz_t ns);
403  	   TString     &Replace(Ssiz_t pos, Ssiz_t n, const TString &s);
404  	   TString     &Replace(Ssiz_t pos, Ssiz_t n1, const TString &s, Ssiz_t n2);
405  	   TString     &ReplaceAll(const TString &s1, const TString &s2); // Find&Replace all s1 with s2 if any
406  	   TString     &ReplaceAll(const TString &s1, const char *s2);    // Find&Replace all s1 with s2 if any
407  	   TString     &ReplaceAll(const    char *s1, const TString &s2); // Find&Replace all s1 with s2 if any
408  	   TString     &ReplaceAll(const char *s1, const char *s2);       // Find&Replace all s1 with s2 if any
409  	   TString     &ReplaceAll(const char *s1, Ssiz_t ls1, const char *s2, Ssiz_t ls2);  // Find&Replace all s1 with s2 if any
410  	   void         Resize(Ssiz_t n);                       // Truncate or add blanks as necessary
411  	   TSubString   Strip(EStripType s = kTrailing, char c = ' ') const;
412  	   void         ToLower();                              // Change self to lower-case
413  	   void         ToUpper();                              // Change self to upper-case
414  	   TObjArray   *Tokenize(const TString &delim) const;
415  	   Bool_t       Tokenize(TString &tok, Ssiz_t &from, const char *delim = " ") const;
416  	
417  	   // Static member functions
418  	   static UInt_t  Hash(const void *txt, Int_t ntxt);    // Calculates hash index from any char string.
419  	   static Ssiz_t  InitialCapacity(Ssiz_t ic = 15);      // Initial allocation capacity
420  	   static Ssiz_t  MaxWaste(Ssiz_t mw = 15);             // Max empty space before reclaim
421  	   static Ssiz_t  ResizeIncrement(Ssiz_t ri = 16);      // Resizing increment
422  	   static Ssiz_t  GetInitialCapacity();
423  	   static Ssiz_t  GetResizeIncrement();
424  	   static Ssiz_t  GetMaxWaste();
425  	   static TString Itoa   (    Int_t value, Int_t base);  // Converts int to string with respect to the base specified (2-36)
426  	   static TString UItoa  (   UInt_t value, Int_t base);
427  	   static TString LLtoa  ( Long64_t value, Int_t base);
428  	   static TString ULLtoa (ULong64_t value, Int_t base);
429  	   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 (supported bases 2-36)
430  	   static TString Format(const char *fmt, ...)
431  	#if defined(__GNUC__) && !defined(__CINT__)
432  	   __attribute__((format(printf, 1, 2)))
433  	#endif
434  	   ;
435  	
436  	   ClassDef(TString,2)  //Basic string class
437  	};
438  	
439  	// Related global functions
440  	istream  &operator>>(istream &str,       TString &s);
441  	ostream  &operator<<(ostream &str, const TString &s);
442  	#if defined(R__TEMPLATE_OVERLOAD_BUG)
443  	template <>
444  	#endif
445  	TBuffer  &operator>>(TBuffer &buf,       TString *&sp);
446  	
447  	TString ToLower(const TString &s);    // Return lower-case version of argument
448  	TString ToUpper(const TString &s);    // Return upper-case version of argument
449  	
450  	inline UInt_t Hash(const TString &s) { return s.Hash(); }
451  	inline UInt_t Hash(const TString *s) { return s->Hash(); }
452  	       UInt_t Hash(const char *s);
453  	
454  	extern char *Form(const char *fmt, ...)      // format in circular buffer
455  	#if defined(__GNUC__) && !defined(__CINT__)
456  	__attribute__((format(printf, 1, 2)))
457  	#endif
458  	;
459  	extern void  Printf(const char *fmt, ...)    // format and print
460  	#if defined(__GNUC__) && !defined(__CINT__)
461  	__attribute__((format(printf, 1, 2)))
462  	#endif
463  	;
464  	extern char *Strip(const char *str, char c = ' '); // strip c off str, free with delete []
465  	extern char *StrDup(const char *str);        // duplicate str, free with delete []
466  	extern char *Compress(const char *str);      // remove blanks from string, free with delele []
467  	extern int   EscChar(const char *src, char *dst, int dstlen, char *specchars,
468  	                     char escchar);          // copy from src to dst escaping specchars by escchar
469  	extern int   UnEscChar(const char *src, char *dst, int dstlen, char *specchars,
470  	                       char escchar);        // copy from src to dst removing escchar from specchars
471  	
472  	#ifdef NEED_STRCASECMP
473  	extern int strcasecmp(const char *str1, const char *str2);
474  	extern int strncasecmp(const char *str1, const char *str2, Ssiz_t n);
475  	#endif
476  	
477  	//////////////////////////////////////////////////////////////////////////
478  	//                                                                      //
479  	//  Inlines                                                             //
480  	//                                                                      //
481  	//////////////////////////////////////////////////////////////////////////
482  	
483  	inline TString &TString::Append(const char *cs)
484  	{ return Replace(Length(), 0, cs, cs ? strlen(cs) : 0); }
485  	
486  	inline TString &TString::Append(const char *cs, Ssiz_t n)
487  	{ return Replace(Length(), 0, cs, n); }
488  	
489  	inline TString &TString::Append(const TString &s)
490  	{ return Replace(Length(), 0, s.Data(), s.Length()); }
491  	
492  	inline TString &TString::Append(const TString &s, Ssiz_t n)
493  	{ return Replace(Length(), 0, s.Data(), TMath::Min(n, s.Length())); }
494  	
495  	inline TString &TString::operator+=(const char *cs)
496  	{ return Append(cs, cs ? strlen(cs) : 0); }
497  	
498  	inline TString &TString::operator+=(const TString &s)
499  	{ return Append(s.Data(), s.Length()); }
500  	
501  	inline TString &TString::operator+=(char c)
502  	{ return Append(c); }
503  	
504  	inline TString &TString::operator+=(Long_t i)
505  	{ char s[32]; sprintf(s, "%ld", i); return operator+=(s); }
506  	
507  	inline TString &TString::operator+=(ULong_t i)
508  	{ char s[32]; sprintf(s, "%lu", i); return operator+=(s); }
509  	
510  	inline TString &TString::operator+=(Short_t i)
511  	{ return operator+=((Long_t) i); }
512  	
513  	inline TString &TString::operator+=(UShort_t i)
514  	{ return operator+=((ULong_t) i); }
515  	
516  	inline TString &TString::operator+=(Int_t i)
517  	{ return operator+=((Long_t) i); }
518  	
519  	inline TString &TString::operator+=(UInt_t i)
520  	{ return operator+=((ULong_t) i); }
521  	
522  	inline TString &TString::operator+=(Double_t f)
523  	{
524  	   char s[32];
525  	   // coverity[secure_coding] Buffer is large enough: width specified in format
526  	   sprintf(s, "%.17g", f);
527  	   return operator+=(s);
528  	}
529  	
530  	inline TString &TString::operator+=(Float_t f)
531  	{ return operator+=((Double_t) f); }
532  	
533  	inline TString &TString::operator+=(Long64_t l)
534  	{
535  	   char s[32];
536  	   // coverity[secure_coding] Buffer is large enough (2^64 = 20 digits).
537  	   sprintf(s, "%lld", l);
538  	   return operator+=(s);
539  	}
540  	
541  	inline TString &TString::operator+=(ULong64_t ul)
542  	{
543  	   char s[32];
544  	   // coverity[secure_coding] Buffer is large enough (2^64 = 20 digits).
545  	   sprintf(s, "%llu", ul);
546  	   return operator+=(s);
547  	}
548  	
549  	inline Bool_t TString::BeginsWith(const char *s, ECaseCompare cmp) const
550  	{ return Index(s, s ? strlen(s) : (Ssiz_t)0, (Ssiz_t)0, cmp) == 0; }
551  	
552  	inline Bool_t TString::BeginsWith(const TString &pat, ECaseCompare cmp) const
553  	{ return Index(pat.Data(), pat.Length(), (Ssiz_t)0, cmp) == 0; }
554  	
555  	inline Bool_t TString::Contains(const TString &pat, ECaseCompare cmp) const
556  	{ return Index(pat.Data(), pat.Length(), (Ssiz_t)0, cmp) != kNPOS; }
557  	
558  	inline Bool_t TString::Contains(const char *s, ECaseCompare cmp) const
559  	{ return Index(s, s ? strlen(s) : 0, (Ssiz_t)0, cmp) != kNPOS; }
560  	
561  	inline Bool_t TString::Contains(const TRegexp &pat) const
562  	{ return Index(pat, (Ssiz_t)0) != kNPOS; }
563  	
564  	inline Bool_t TString::Contains(TPRegexp &pat) const
565  	{ return Index(pat, (Ssiz_t)0) != kNPOS; }
566  	
567  	inline Bool_t TString::EqualTo(const char *cs, ECaseCompare cmp) const
568  	{ return (CompareTo(cs, cmp) == 0) ? kTRUE : kFALSE; }
569  	
570  	inline Bool_t TString::EqualTo(const TString &st, ECaseCompare cmp) const
571  	{ return (CompareTo(st, cmp) == 0) ? kTRUE : kFALSE; }
572  	
573  	inline Ssiz_t TString::Index(const char *s, Ssiz_t i, ECaseCompare cmp) const
574  	{ return Index(s, s ? strlen(s) : 0, i, cmp); }
575  	
576  	inline Ssiz_t TString::Index(const TString &s, Ssiz_t i, ECaseCompare cmp) const
577  	{ return Index(s.Data(), s.Length(), i, cmp); }
578  	
579  	inline Ssiz_t TString::Index(const TString &pat, Ssiz_t patlen, Ssiz_t i,
580  	                             ECaseCompare cmp) const
581  	{ return Index(pat.Data(), patlen, i, cmp); }
582  	
583  	inline TString &TString::Insert(Ssiz_t pos, const char *cs)
584  	{ return Replace(pos, 0, cs, cs ? strlen(cs) : 0); }
585  	
586  	inline TString &TString::Insert(Ssiz_t pos, const char *cs, Ssiz_t n)
587  	{ return Replace(pos, 0, cs, n); }
588  	
589  	inline TString &TString::Insert(Ssiz_t pos, const TString &s)
590  	{ return Replace(pos, 0, s.Data(), s.Length()); }
591  	
592  	inline TString &TString::Insert(Ssiz_t pos, const TString &s, Ssiz_t n)
593  	{ return Replace(pos, 0, s.Data(), TMath::Min(n, s.Length())); }
594  	
595  	inline TString &TString::Prepend(const char *cs)
596  	{ return Replace(0, 0, cs, cs ? strlen(cs) : 0); }
597  	
598  	inline TString &TString::Prepend(const char *cs, Ssiz_t n)
599  	{ return Replace(0, 0, cs, n); }
600  	
601  	inline TString &TString::Prepend(const TString &s)
602  	{ return Replace(0, 0, s.Data(), s.Length()); }
603  	
604  	inline TString &TString::Prepend(const TString &s, Ssiz_t n)
605  	{ return Replace(0, 0, s.Data(), TMath::Min(n, s.Length())); }
606  	
607  	inline TString &TString::Remove(Ssiz_t pos)
608  	{ return Replace(pos, TMath::Max(0, Length()-pos), 0, 0); }
609  	
610  	inline TString &TString::Remove(Ssiz_t pos, Ssiz_t n)
611  	{ return Replace(pos, n, 0, 0); }
612  	
613  	inline TString &TString::Chop()
614  	{ return Remove(TMath::Max(0, Length()-1)); }
615  	
616  	inline TString &TString::Replace(Ssiz_t pos, Ssiz_t n, const char *cs)
617  	{ return Replace(pos, n, cs, cs ? strlen(cs) : 0); }
618  	
619  	inline TString &TString::Replace(Ssiz_t pos, Ssiz_t n, const TString& s)
620  	{ return Replace(pos, n, s.Data(), s.Length()); }
621  	
622  	inline TString &TString::Replace(Ssiz_t pos, Ssiz_t n1, const TString &s,
623  	                                 Ssiz_t n2)
624  	{ return Replace(pos, n1, s.Data(), TMath::Min(s.Length(), n2)); }
625  	
626  	inline TString &TString::ReplaceAll(const TString &s1, const TString &s2)
627  	{ return ReplaceAll(s1.Data(), s1.Length(), s2.Data(), s2.Length()) ; }
628  	
629  	inline TString &TString::ReplaceAll(const TString &s1, const char *s2)
630  	{ return ReplaceAll(s1.Data(), s1.Length(), s2, s2 ? strlen(s2) : 0); }
631  	
632  	inline TString &TString::ReplaceAll(const char *s1, const TString &s2)
633  	{ return ReplaceAll(s1, s1 ? strlen(s1) : 0, s2.Data(), s2.Length()); }
634  	
635  	inline TString &TString::ReplaceAll(const char *s1,const char *s2)
636  	{ return ReplaceAll(s1, s1 ? strlen(s1) : 0, s2, s2 ? strlen(s2) : 0); }
637  	
638  	inline char &TString::operator()(Ssiz_t i)
639  	{ return GetPointer()[i]; }
640  	
641  	inline char TString::operator()(Ssiz_t i) const
642  	{ return GetPointer()[i]; }
643  	
644  	inline char &TString::operator[](Ssiz_t i)
645  	{ AssertElement(i); return GetPointer()[i]; }
646  	
647  	inline char TString::operator[](Ssiz_t i) const
648  	{ AssertElement(i); return GetPointer()[i]; }
649  	
650  	inline const char *TSubString::Data() const
651  	{
652  	   // Return a pointer to the beginning of the substring. Note that the
653  	   // terminating null is in the same place as for the original
654  	   // TString, so this method is not appropriate for converting the
655  	   // TSubString to a string. To do that, construct a TString from the
656  	   // TSubString. For example:
657  	   //
658  	   //   root [0] TString s("hello world")
659  	   //   root [1] TSubString sub=s(0, 5)
660  	   //   root [2] sub.Data()
661  	   //   (const char* 0x857c8b8)"hello world"
662  	   //   root [3] TString substr(sub)
663  	   //   root [4] substr
664  	   //   (class TString)"hello"
665  	
666  	   return fStr.Data() + fBegin;
667  	}
668  	
669  	// Access to elements of sub-string with bounds checking
670  	inline char TSubString::operator[](Ssiz_t i) const
671  	{ AssertElement(i); return fStr.GetPointer()[fBegin+i]; }
672  	
673  	inline char TSubString::operator()(Ssiz_t i) const
674  	{ return fStr.GetPointer()[fBegin+i]; }
675  	
676  	inline TSubString &TSubString::operator=(const TSubString &s)
677  	{ fStr = s.fStr; fBegin = s.fBegin; fExtent = s.fExtent; return *this; }
678  	
679  	
680  	// String Logical operators
681  	inline Bool_t operator==(const TString &s1, const TString &s2)
682  	{
683  	   return ((s1.Length() == s2.Length()) &&
684  	            !memcmp(s1.Data(), s2.Data(), s1.Length()));
685  	}
686  	
687  	inline Bool_t operator!=(const TString &s1, const TString &s2)
688  	{ return !(s1 == s2); }
689  	
690  	inline Bool_t operator<(const TString &s1, const TString &s2)
691  	{ return s1.CompareTo(s2) < 0; }
692  	
693  	inline Bool_t operator>(const TString &s1, const TString &s2)
694  	{ return s1.CompareTo(s2) > 0; }
695  	
696  	inline Bool_t operator<=(const TString &s1, const TString &s2)
697  	{ return s1.CompareTo(s2) <= 0; }
698  	
699  	inline Bool_t operator>=(const TString &s1, const TString &s2)
700  	{ return s1.CompareTo(s2) >= 0; }
701  	
702  	//     Bool_t operator==(const TString &s1, const char *s2);
703  	inline Bool_t operator!=(const TString &s1, const char *s2)
704  	{ return !(s1 == s2); }
705  	
706  	inline Bool_t operator<(const TString &s1, const char *s2)
707  	{ return s1.CompareTo(s2) < 0; }
708  	
709  	inline Bool_t operator>(const TString &s1, const char *s2)
710  	{ return s1.CompareTo(s2) > 0; }
711  	
712  	inline Bool_t operator<=(const TString &s1, const char *s2)
713  	{ return s1.CompareTo(s2) <= 0; }
714  	
715  	inline Bool_t operator>=(const TString &s1, const char *s2)
716  	{ return s1.CompareTo(s2) >= 0; }
717  	
718  	inline Bool_t operator==(const char *s1, const TString &s2)
719  	{ return (s2 == s1); }
720  	
721  	inline Bool_t operator!=(const char *s1, const TString &s2)
722  	{ return !(s2 == s1); }
723  	
724  	inline Bool_t operator<(const char *s1, const TString &s2)
725  	{ return s2.CompareTo(s1) > 0; }
726  	
727  	inline Bool_t operator>(const char *s1, const TString &s2)
728  	{ return s2.CompareTo(s1) < 0; }
729  	
730  	inline Bool_t operator<=(const char *s1, const TString &s2)
731  	{ return s2.CompareTo(s1) >= 0; }
732  	
733  	inline Bool_t operator>=(const char *s1, const TString &s2)
734  	{ return s2.CompareTo(s1) <= 0; }
735  	
736  	// SubString Logical operators
737  	//     Bool_t operator==(const TSubString &s1, const TSubString &s2);
738  	//     Bool_t operator==(const TSubString &s1, const char *s2);
739  	//     Bool_t operator==(const TSubString &s1, const TString &s2);
740  	inline Bool_t operator==(const TString &s1, const TSubString &s2)
741  	{ return (s2 == s1); }
742  	
743  	inline Bool_t operator==(const char *s1, const TSubString &s2)
744  	{ return (s2 == s1); }
745  	
746  	inline Bool_t operator!=(const TSubString &s1, const char *s2)
747  	{ return !(s1 == s2); }
748  	
749  	inline Bool_t operator!=(const TSubString &s1, const TString &s2)
750  	{ return !(s1 == s2); }
751  	
752  	inline Bool_t operator!=(const TSubString &s1, const TSubString &s2)
753  	{ return !(s1 == s2); }
754  	
755  	inline Bool_t operator!=(const TString &s1, const TSubString &s2)
756  	{ return !(s2 == s1); }
757  	
758  	inline Bool_t operator!=(const char *s1, const TSubString &s2)
759  	{ return !(s2 == s1); }
760  	
761  	#endif
762