TString.cxx

Go to the documentation of this file.
00001 // @(#)root/base:$Id: TString.cxx 37217 2010-12-03 11:24:41Z rdm $
00002 // Author: Fons Rademakers   04/08/95
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // TString                                                              //
00015 //                                                                      //
00016 // Basic string class.                                                  //
00017 //                                                                      //
00018 // Cannot be stored in a TCollection... use TObjString instead.         //
00019 //                                                                      //
00020 // The underlying string is stored as a char* that can be accessed via  //
00021 // TString::Data().                                                     //
00022 // TString provides copy-on-write semantics with reference counting     //
00023 // so that multiple TString objects can refer to the same data.         //
00024 // For example:                                                         //
00025 //   root [0] TString orig("foo")                                       //
00026 //   root [1] TString copy(orig)  // 'orig' and 'copy' point to the     //
00027 //                                // same data...                       //
00028 //   root [2] orig.Data()                                               //
00029 //   (const char* 0x98936f8)"foo"                                       //
00030 //   root [3] copy.Data()                                               //
00031 //   (const char* 0x98936f8)"foo"                                       //
00032 //   root [4] copy="bar"          // Editing 'copy' makes it point      //
00033 //                                // elsewhere
00034 //   (class TString)"bar"                                               //
00035 //   root [5] copy.Data()                                               //
00036 //   (const char* 0x98939b8)"bar"                                       //
00037 //                                                                      //
00038 // Substring operations are provided by the TSubString class, which     //
00039 // holds a reference to the original string and its data, along with    //
00040 // the offset and length of the substring. To retrieve the substring    //
00041 // as a TString, construct a TString from it, eg:                       //
00042 //   root [0] TString s("hello world")                                  //
00043 //   root [1] TString s2( s(0,5) )                                      //
00044 //   root [2] s2                                                        //
00045 //   (class TString)"hello"                                             //
00046 //////////////////////////////////////////////////////////////////////////
00047 
00048 #include "RConfig.h"
00049 #include <stdlib.h>
00050 #include <ctype.h>
00051 #include <list>
00052 
00053 #include "snprintf.h"
00054 #include "Varargs.h"
00055 #include "TString.h"
00056 #include "TBuffer.h"
00057 #include "TError.h"
00058 #include "Bytes.h"
00059 #include "TClass.h"
00060 #include "TObjArray.h"
00061 #include "TObjString.h"
00062 #include "TVirtualMutex.h"
00063 
00064 #ifdef R__GLOBALSTL
00065 namespace std { using ::list; }
00066 #endif
00067 
00068 // Mutex for string format protection
00069 
00070 TVirtualMutex *gStringMutex = 0;
00071 
00072 // Amount to shift hash values to avoid clustering
00073 
00074 const UInt_t kHashShift = 5;
00075 
00076 // This is the global null string representation, shared among all
00077 // empty strings.  The space for it is in "gNullRef" which the
00078 // loader will set to zero
00079 
00080 static long gNullRef[(sizeof(TStringRef)+1)/sizeof(long) + 1];
00081 static void *gNullRefTmp = gNullRef;
00082 
00083 // Use macro in stead of the following to side-step compilers (e.g. DEC)
00084 // that generate pre-main code for the initialization of address constants.
00085 // static TStringRef* const gNullStringRef = (TStringRef*)gNullRef;
00086 
00087 #define gNullStringRef ((TStringRef*)gNullRefTmp)
00088 
00089 // ------------------------------------------------------------------------
00090 //
00091 // In what follows, fCapacity is the length of the underlying representation
00092 // vector. Hence, the capacity for a null terminated string held in this
00093 // vector is fCapacity-1.  The variable fNchars is the length of the held
00094 // string, excluding the terminating null.
00095 //
00096 // The algorithms make no assumptions about whether internal strings
00097 // hold embedded nulls. However, they do assume that any string
00098 // passed in as an argument that does not have a length count is null
00099 // terminated and therefore has no embedded nulls.
00100 //
00101 // The internal string is always null terminated.
00102 //
00103 // ------------------------------------------------------------------------
00104 //
00105 //  This class uses a number of protected and private member functions
00106 //  to do memory management. Here are their semantics:
00107 //
00108 //  TString::Cow();
00109 //    Insure that self is a distinct copy. Preserve previous contents.
00110 //
00111 //  TString::Cow(Ssiz_t nc);
00112 //    Insure that self is a distinct copy with capacity of at
00113 //    least nc. Preserve previous contents.
00114 //
00115 //  TString::Clobber(Ssiz_t nc);
00116 //    Insure that the TStringRef is unshared and has a
00117 //    capacity of at least nc. No need to preserve contents.
00118 //
00119 //  TString::Clone();
00120 //    Make self a distinct copy. Preserve previous contents.
00121 //
00122 //  TString::Clone(Ssiz_t);
00123 //    Make self a distinct copy with capacity of at least nc.
00124 //    Preserve previous contents.
00125 //
00126 // ------------------------------------------------------------------------
00127 
00128 
00129 //////////////////////////////////////////////////////////////////////////
00130 //                                                                      //
00131 //  TStringRef                                                          //
00132 //                                                                      //
00133 //////////////////////////////////////////////////////////////////////////
00134 
00135 //______________________________________________________________________________
00136 TStringRef *TStringRef::GetRep(Ssiz_t capacity, Ssiz_t nchar)
00137 {
00138    // Static member function returning an empty string representation of
00139    // size capacity and containing nchar characters.
00140 
00141    if ((capacity | nchar) == 0) {
00142       gNullStringRef->AddReference();
00143       return gNullStringRef;
00144    }
00145    TStringRef *ret = (TStringRef*)new char[capacity + sizeof(TStringRef) + 1];
00146    ret->fCapacity = capacity;
00147    ret->SetRefCount(1);
00148    ret->Data()[ret->fNchars = nchar] = 0; // Terminating null
00149 
00150    return ret;
00151 }
00152 
00153 //______________________________________________________________________________
00154 Ssiz_t TStringRef::First(char c) const
00155 {
00156    // Find first occurrence of a character c.
00157 
00158    const char *f = strchr(Data(), c);
00159    return f ? f - Data() : kNPOS;
00160 }
00161 
00162 //______________________________________________________________________________
00163 Ssiz_t TStringRef::First(const char *cs) const
00164 {
00165    // Find first occurrence of a character in cs.
00166 
00167    const char *f = strpbrk(Data(), cs);
00168    return f ? f - Data() : kNPOS;
00169 }
00170 
00171 #ifndef R__BYTESWAP
00172 //______________________________________________________________________________
00173 inline static UInt_t SwapInt(UInt_t x)
00174 {
00175    return (((x & 0x000000ffU) << 24) | ((x & 0x0000ff00U) <<  8) |
00176            ((x & 0x00ff0000U) >>  8) | ((x & 0xff000000U) >> 24));
00177 }
00178 #endif
00179 
00180 //______________________________________________________________________________
00181 inline static void Mash(UInt_t& hash, UInt_t chars)
00182 {
00183    // Utility used by Hash().
00184 
00185    hash = (chars ^
00186          ((hash << kHashShift) |
00187           (hash >> (kBitsPerByte*sizeof(UInt_t) - kHashShift))));
00188 }
00189 
00190 //______________________________________________________________________________
00191 UInt_t Hash(const char *str)
00192 {
00193    // Return a case-sensitive hash value (endian independent).
00194 
00195    UInt_t len = str ? strlen(str) : 0;
00196    UInt_t hv  = len; // Mix in the string length.
00197    UInt_t i   = hv*sizeof(char)/sizeof(UInt_t);
00198 
00199    if (((ULong_t)str)%sizeof(UInt_t) == 0) {
00200       // str is word aligned
00201       const UInt_t *p = (const UInt_t*)str;
00202 
00203       while (i--) {
00204 #ifndef R__BYTESWAP
00205          UInt_t h = *p++;
00206          Mash(hv, SwapInt(h));
00207 #else
00208          Mash(hv, *p++);                   // XOR in the characters.
00209 #endif
00210       }
00211 
00212       // XOR in any remaining characters:
00213       if ((i = len*sizeof(char)%sizeof(UInt_t)) != 0) {
00214          UInt_t h = 0;
00215          const char* c = (const char*)p;
00216          while (i--)
00217             h = ((h << kBitsPerByte*sizeof(char)) | *c++);
00218          Mash(hv, h);
00219       }
00220    } else {
00221       // str is not word aligned
00222       UInt_t h;
00223       const unsigned char *p = (const unsigned char*)str;
00224 
00225       while (i--) {
00226          memcpy(&h, p, sizeof(UInt_t));
00227 #ifndef R__BYTESWAP
00228          Mash(hv, SwapInt(h));
00229 #else
00230          Mash(hv, h);
00231 #endif
00232          p += sizeof(UInt_t);
00233       }
00234 
00235       // XOR in any remaining characters:
00236       if ((i = len*sizeof(char)%sizeof(UInt_t)) != 0) {
00237          h = 0;
00238          const char* c = (const char*)p;
00239          while (i--)
00240             h = ((h << kBitsPerByte*sizeof(char)) | *c++);
00241          Mash(hv, h);
00242       }
00243    }
00244    return hv;
00245 }
00246 
00247 //______________________________________________________________________________
00248 UInt_t TStringRef::Hash() const
00249 {
00250    // Return a case-sensitive hash value (endian independent).
00251 
00252    UInt_t hv       = (UInt_t)Length(); // Mix in the string length.
00253    UInt_t i        = hv*sizeof(char)/sizeof(UInt_t);
00254    const UInt_t *p = (const UInt_t*)Data();
00255    {
00256       while (i--) {
00257 #ifndef R__BYTESWAP
00258          UInt_t h = *p++;
00259          Mash(hv, SwapInt(h));             // XOR in the characters.
00260 #else
00261          Mash(hv, *p++);                   // XOR in the characters.
00262 #endif
00263       }
00264    }
00265    // XOR in any remaining characters:
00266    if ((i = Length()*sizeof(char)%sizeof(UInt_t)) != 0) {
00267       UInt_t h = 0;
00268       const char* c = (const char*)p;
00269       while (i--)
00270          h = ((h << kBitsPerByte*sizeof(char)) | *c++);
00271       Mash(hv, h);
00272    }
00273    return hv;
00274 }
00275 
00276 //______________________________________________________________________________
00277 UInt_t TStringRef::HashFoldCase() const
00278 {
00279    // Return a case-insensitive hash value (endian independent).
00280 
00281    UInt_t hv = (UInt_t)Length();    // Mix in the string length.
00282    UInt_t i  = hv;
00283    const unsigned char *p = (const unsigned char*)Data();
00284    while (i--) {
00285       Mash(hv, toupper(*p));
00286       ++p;
00287    }
00288    return hv;
00289 }
00290 
00291 //______________________________________________________________________________
00292 Ssiz_t TStringRef::Last(char c) const
00293 {
00294    // Find last occurrence of a character c.
00295 
00296    const char *f = strrchr(Data(), (unsigned char) c);
00297    return f ? f - Data() : kNPOS;
00298 }
00299 
00300 
00301 ClassImp(TString)
00302 
00303 //////////////////////////////////////////////////////////////////////////
00304 //                                                                      //
00305 //  TString                                                             //
00306 //                                                                      //
00307 //////////////////////////////////////////////////////////////////////////
00308 
00309 // ------------------- The static data members access --------------------------
00310 Ssiz_t  TString::GetInitialCapacity()    { return fgInitialCapac; }
00311 Ssiz_t  TString::GetResizeIncrement()    { return fgResizeInc; }
00312 Ssiz_t  TString::GetMaxWaste()           { return fgFreeboard; }
00313 
00314 //______________________________________________________________________________
00315 TString::TString()
00316 {
00317    // TString default ctor.
00318 
00319    fData = gNullStringRef->Data();
00320    gNullStringRef->AddReference();
00321 }
00322 
00323 //______________________________________________________________________________
00324 TString::TString(Ssiz_t ic)
00325 {
00326    // Create TString able to contain ic characters.
00327 
00328    fData = TStringRef::GetRep(ic, 0)->Data();
00329 }
00330 
00331 //______________________________________________________________________________
00332 TString::TString(const char *cs)
00333 {
00334    // Create TString and initialize it with string cs.
00335 
00336    if (cs) {
00337       Ssiz_t n = strlen(cs);
00338       fData = TStringRef::GetRep(n, n)->Data();
00339       memcpy(fData, cs, n);
00340    } else
00341       fData = TStringRef::GetRep(0, 0)->Data();
00342 }
00343 
00344 //______________________________________________________________________________
00345 TString::TString(const std::string &s)
00346 {
00347    // Create TString and initialize it with string cs.
00348 
00349    Ssiz_t n = s.length();
00350    fData = TStringRef::GetRep(n, n)->Data();
00351    memcpy(fData, s.c_str(), n);
00352 }
00353 
00354 //______________________________________________________________________________
00355 TString::TString(const char *cs, Ssiz_t n)
00356 {
00357    // Create TString and initialize it with the first n characters of cs.
00358 
00359    fData = TStringRef::GetRep(n, n)->Data();
00360    memcpy(fData, cs, n);
00361 }
00362 
00363 //______________________________________________________________________________
00364 void TString::InitChar(char c)
00365 {
00366    // Initialize a string with a single character.
00367 
00368    fData = TStringRef::GetRep(GetInitialCapacity(), 1)->Data();
00369    fData[0] = c;
00370 }
00371 
00372 //______________________________________________________________________________
00373 TString::TString(char c, Ssiz_t n)
00374 {
00375    // Initialize the first n locations of a TString with character c.
00376 
00377    fData = TStringRef::GetRep(n, n)->Data();
00378    while (n--) fData[n] = c;
00379 }
00380 
00381 //______________________________________________________________________________
00382 TString::TString(const TSubString& substr)
00383 {
00384    // Copy a TSubString in a TString.
00385 
00386    Ssiz_t len = substr.IsNull() ? 0 : substr.Length();
00387    fData = TStringRef::GetRep(AdjustCapacity(len), len)->Data();
00388    memcpy(fData, substr.Data(), len);
00389 }
00390 
00391 //______________________________________________________________________________
00392 TString::~TString()
00393 {
00394    // Delete a TString. I.e. decrease its reference count. When 0 free space.
00395 
00396    Pref()->UnLink();
00397 }
00398 
00399 //______________________________________________________________________________
00400 TString& TString::operator=(char c)
00401 {
00402    // Assign character c to TString.
00403 
00404    if (!c) {
00405       Pref()->UnLink();
00406       gNullStringRef->AddReference();
00407       fData = gNullStringRef->Data();
00408       return *this;
00409    }
00410    return Replace(0, Length(), &c, 1);
00411 }
00412 
00413 //______________________________________________________________________________
00414 TString& TString::operator=(const char *cs)
00415 {
00416    // Assign string cs to TString.
00417 
00418    if (!cs || !*cs) {
00419       Pref()->UnLink();
00420       gNullStringRef->AddReference();
00421       fData = gNullStringRef->Data();
00422       return *this;
00423    }
00424    return Replace(0, Length(), cs, strlen(cs));
00425 }
00426 
00427 //______________________________________________________________________________
00428 TString& TString::operator=(const std::string &s)
00429 {
00430    // Assign std::string s to TString.
00431 
00432    if (s.length()==0) {
00433       Pref()->UnLink();
00434       gNullStringRef->AddReference();
00435       fData = gNullStringRef->Data();
00436       return *this;
00437    }
00438    return Replace(0, Length(), s.c_str(), s.length());
00439 }
00440 
00441 //______________________________________________________________________________
00442 TString& TString::operator=(const TString &str)
00443 {
00444    // Assignment operator.
00445 
00446    str.Pref()->AddReference();
00447    Pref()->UnLink();
00448    fData = str.fData;
00449    return *this;
00450 }
00451 
00452 //______________________________________________________________________________
00453 TString& TString::operator=(const TSubString &substr)
00454 {
00455    // Assign a TSubString substr to TString.
00456 
00457    Ssiz_t len = substr.IsNull() ? 0 : substr.Length();
00458    if (!len) {
00459       Pref()->UnLink();
00460       gNullStringRef->AddReference();
00461       fData = gNullStringRef->Data();
00462       return *this;
00463    }
00464    return Replace(0, Length(), substr.Data(), len);
00465 }
00466 
00467 //______________________________________________________________________________
00468 TString& TString::Append(char c, Ssiz_t rep)
00469 {
00470    // Append character c rep times to string.
00471 
00472    Ssiz_t tot;
00473    Cow(tot = Length() + rep);
00474    char* p = fData + Length();
00475    while (rep--)
00476       *p++ = c;
00477 
00478    fData[Pref()->fNchars = tot] = '\0';
00479 
00480    return *this;
00481 }
00482 
00483 //______________________________________________________________________________
00484 Ssiz_t TString::Capacity(Ssiz_t nc)
00485 {
00486    // Return string capacity. If nc != current capacity Clone() the string
00487    // in a string with the desired capacity.
00488 
00489    if (nc > Length() && nc != Capacity())
00490       Clone(nc);
00491 
00492    return Capacity();
00493 }
00494 
00495 //______________________________________________________________________________
00496 int TString::CompareTo(const char *cs2, ECaseCompare cmp) const
00497 {
00498    // Compare a string to char *cs2.
00499 
00500    if (!cs2) return 1;
00501 
00502    const char *cs1 = Data();
00503    Ssiz_t len = Length();
00504    Ssiz_t i = 0;
00505    if (cmp == kExact) {
00506       for (; cs2[i]; ++i) {
00507          if (i == len) return -1;
00508          if (cs1[i] != cs2[i]) return ((cs1[i] > cs2[i]) ? 1 : -1);
00509       }
00510    } else {                  // ignore case
00511       for (; cs2[i]; ++i) {
00512          if (i == len) return -1;
00513          char c1 = tolower((unsigned char)cs1[i]);
00514          char c2 = tolower((unsigned char)cs2[i]);
00515          if (c1 != c2) return ((c1 > c2) ? 1 : -1);
00516       }
00517    }
00518    return (i < len) ? 1 : 0;
00519 }
00520 
00521 //______________________________________________________________________________
00522 int TString::CompareTo(const TString &str, ECaseCompare cmp) const
00523 {
00524    // Compare a string to another string.
00525 
00526    const char *s1 = Data();
00527    const char *s2 = str.Data();
00528    Ssiz_t len = str.Length();
00529    if (Length() < len) len = Length();
00530    if (cmp == kExact) {
00531       int result = memcmp(s1, s2, len);
00532       if (result != 0) return result;
00533    } else {
00534       Ssiz_t i = 0;
00535       for (; i < len; ++i) {
00536          char c1 = tolower((unsigned char)s1[i]);
00537          char c2 = tolower((unsigned char)s2[i]);
00538          if (c1 != c2) return ((c1 > c2) ? 1 : -1);
00539       }
00540    }
00541    // strings are equal up to the length of the shorter one.
00542    if (Length() == str.Length()) return 0;
00543    return (Length() > str.Length()) ? 1 : -1;
00544 }
00545 
00546 //______________________________________________________________________________
00547 Int_t TString::CountChar(Int_t c) const
00548 {
00549    // Return number of times character c occurs in the string.
00550 
00551    Int_t count = 0;
00552    Int_t len   = Length();
00553    for (Int_t n = 0; n < len; n++)
00554       if (fData[n] == c) count++;
00555 
00556    return count;
00557 }
00558 
00559 //______________________________________________________________________________
00560 TString TString::Copy() const
00561 {
00562    // Copy a string.
00563 
00564    TString temp(*this);          // Has increased reference count
00565    temp.Clone();                 // Distinct copy
00566    return temp;
00567 }
00568 
00569 //______________________________________________________________________________
00570 UInt_t TString::Hash(ECaseCompare cmp) const
00571 {
00572    // Return hash value.
00573 
00574    return (cmp == kExact) ? Pref()->Hash() : Pref()->HashFoldCase();
00575 }
00576 
00577 //______________________________________________________________________________
00578 UInt_t TString::Hash(const void *txt, Int_t ntxt)
00579 {
00580    // Calculates hash index from any char string. (static function)
00581    // Based on precalculated table of 256 specially selected numbers.
00582    // These numbers are selected in such a way, that for string
00583    // length == 4 (integer number) the hash is unambigous, i.e.
00584    // from hash value we can recalculate input (no degeneration).
00585    //
00586    // The quality of hash method is good enough, that
00587    // "random" numbers made as R = Hash(1), Hash(2), ...Hash(N)
00588    // tested by <R>, <R*R>, <Ri*Ri+1> gives the same result
00589    // as for libc rand().
00590    //
00591    // For string:  i = TString::Hash(string,nstring);
00592    // For int:     i = TString::Hash(&intword,sizeof(int));
00593    // For pointer: i = TString::Hash(&pointer,sizeof(void*));
00594    //
00595    //              V.Perev
00596 
00597    static const UInt_t utab[] = {
00598       0xdd367647,0x9caf993f,0x3f3cc5ff,0xfde25082,0x4c764b21,0x89affca7,0x5431965c,0xce22eeec,
00599       0xc61ab4dc,0x59cc93bd,0xed3107e3,0x0b0a287a,0x4712475a,0xce4a4c71,0x352c8403,0x94cb3cee,
00600       0xc3ac509b,0x09f827a2,0xce02e37e,0x7b20bbba,0x76adcedc,0x18c52663,0x19f74103,0x6f30e47b,
00601       0x132ea5a1,0xfdd279e0,0xa3d57d00,0xcff9cb40,0x9617f384,0x6411acfa,0xff908678,0x5c796b2c,
00602       0x4471b62d,0xd38e3275,0xdb57912d,0x26bf953f,0xfc41b2a5,0xe64bcebd,0x190b7839,0x7e8e6a56,
00603       0x9ca22311,0xef28aa60,0xe6b9208e,0xd257fb65,0x45781c2c,0x9a558ac3,0x2743e74d,0x839417a8,
00604       0x06b54d5d,0x1a82bcb4,0x06e97a66,0x70abdd03,0xd163f30d,0x222ed322,0x777bfeda,0xab7a2e83,
00605       0x8494e0cf,0x2dca2d4f,0x78f94278,0x33f04a09,0x402b6452,0x0cd8b709,0xdb72a39e,0x170e00a2,
00606       0x26354faa,0x80e57453,0xcfe8d4e1,0x19e45254,0x04c291c3,0xeb503738,0x425af3bc,0x67836f2a,
00607       0xfac22add,0xfafc2b8c,0x59b8c2a0,0x03e806f9,0xcb4938b9,0xccc942af,0xcee3ae2e,0xfbe748fa,
00608       0xb223a075,0x85c49b5d,0xe4576ac9,0x0fbd46e2,0xb49f9cf5,0xf3e1e86a,0x7d7927fb,0x711afe12,
00609       0xbf61c346,0x157c9956,0x86b6b046,0x2e402146,0xb2a57d8a,0x0d064bb1,0x30ce390c,0x3a3e1eb1,
00610       0xbe7f6f8f,0xd8e30f87,0x5be2813c,0x73a3a901,0xa3aaf967,0x59ff092c,0x1705c798,0xf610dd66,
00611       0xb17da91e,0x8e59534e,0x2211ea5b,0xa804ba03,0xd890efbb,0xb8b48110,0xff390068,0xc8c325b4,
00612       0xf7289c07,0x787e104f,0x3d0df3d0,0x3526796d,0x10548055,0x1d59a42b,0xed1cc5a3,0xdd45372a,
00613       0x31c50d57,0x65757cb7,0x3cfb85be,0xa329910d,0x6ad8ce39,0xa2de44de,0x0dd32432,0xd4a5b617,
00614       0x8f3107fc,0x96485175,0x7f94d4f3,0x35097634,0xdb3ca782,0x2c0290b8,0x2045300b,0xe0f5d15a,
00615       0x0e8cbffa,0xaa1cc38a,0x84008d6f,0xe9a9e794,0x5c602c25,0xfa3658fa,0x98d9d82b,0x3f1497e7,
00616       0x84b6f031,0xe381eff9,0xfc7ae252,0xb239e05d,0xe3723d1f,0xcc3bda82,0xe21b1ad3,0x9104f7c8,
00617       0x4bb2dfcd,0x4d14a8bc,0x6ba7f28c,0x8f89886c,0xad44c97e,0xb30fd975,0x633cdab1,0xf6c2d514,
00618       0x067a49d2,0xdc461ad9,0xebaf9f3f,0x8dc6cac3,0x7a060f16,0xbab063ad,0xf42e25e6,0x60724ca6,
00619       0xc7245c2e,0x4e48ea3c,0x9f89a609,0xa1c49890,0x4bb7f116,0xd722865c,0xa8ee3995,0x0ee070b1,
00620       0xd9bffcc2,0xe55b64f9,0x25507a5a,0xc7a3e2b5,0x5f395f7e,0xe7957652,0x7381ba6a,0xde3d21f1,
00621       0xdf1708dd,0xad0c9d0c,0x00cbc9e5,0x1160e833,0x6779582c,0x29d5d393,0x3f11d7d7,0x826a6b9b,
00622       0xe73ff12f,0x8bad3d86,0xee41d3e5,0x7f0c8917,0x8089ef24,0x90c5cb28,0x2f7f8e6b,0x6966418a,
00623       0x345453fb,0x7a2f8a68,0xf198593d,0xc079a532,0xc1971e81,0x1ab74e26,0x329ef347,0x7423d3d0,
00624       0x942c510b,0x7f6c6382,0x14ae6acc,0x64b59da7,0x2356fa47,0xb6749d9c,0x499de1bb,0x92ffd191,
00625       0xe8f2fb75,0x848dc913,0x3e8727d3,0x1dcffe61,0xb6e45245,0x49055738,0x827a6b55,0xb4788887,
00626       0x7e680125,0xd19ce7ed,0x6b4b8e30,0xa8cadea2,0x216035d8,0x1c63bc3c,0xe1299056,0x1ad3dff4,
00627       0x0aefd13c,0x0e7b921c,0xca0173c6,0x9995782d,0xcccfd494,0xd4b0ac88,0x53d552b1,0x630dae8b,
00628       0xa8332dad,0x7139d9a2,0x5d76f2c4,0x7a4f8f1e,0x8d1aef97,0xd1cf285d,0xc8239153,0xce2608a9,
00629       0x7b562475,0xe4b4bc83,0xf3db0c3a,0x70a65e48,0x6016b302,0xdebd5046,0x707e786a,0x6f10200c
00630    };
00631 
00632    static const UInt_t msk[] = { 0x11111111, 0x33333333, 0x77777777, 0xffffffff };
00633 
00634    const UChar_t *uc = (const UChar_t *) txt;
00635    UInt_t uu = 0;
00636    union {
00637       UInt_t   u;
00638       UShort_t s[2];
00639    } u;
00640    u.u = 0;
00641    Int_t i, idx;
00642 
00643    for (i = 0; i < ntxt; i++) {
00644       idx = (uc[i] ^ i) & 255;
00645       uu  = (uu << 1) ^ (utab[idx] & msk[i & 3]);
00646       if ((i & 3) == 3) u.u ^= uu;
00647    }
00648    if (i & 3) u.u ^= uu;
00649 
00650    u.u *= 1879048201;      // prime number
00651    u.s[0] += u.s[1];
00652    u.u *= 1979048191;      // prime number
00653    u.s[1] ^= u.s[0];
00654    u.u *= 2079048197;      // prime number
00655 
00656    return u.u;
00657 }
00658 
00659 //______________________________________________________________________________
00660 static int MemIsEqual(const char *p, const char *q, Ssiz_t n)
00661 {
00662    // Returns false if strings are not equal.
00663 
00664    while (n--)
00665    {
00666       if (tolower((unsigned char)*p) != tolower((unsigned char)*q))
00667          return kFALSE;
00668       p++; q++;
00669    }
00670    return kTRUE;
00671 }
00672 
00673 //______________________________________________________________________________
00674 Ssiz_t TString::Index(const char *pattern, Ssiz_t plen, Ssiz_t startIndex,
00675                       ECaseCompare cmp) const
00676 {
00677    // Search for a string in the TString. Plen is the length of pattern,
00678    // startIndex is the index from which to start and cmp selects the type
00679    // of case-comparison.
00680 
00681    Ssiz_t slen = Length();
00682    if (slen < startIndex + plen) return kNPOS;
00683    if (plen == 0) return startIndex;
00684    slen -= startIndex + plen;
00685    const char *sp = Data() + startIndex;
00686    if (cmp == kExact) {
00687       char first = *pattern;
00688       for (Ssiz_t i = 0; i <= slen; ++i)
00689          if (sp[i] == first && memcmp(sp+i+1, pattern+1, plen-1) == 0)
00690             return i + startIndex;
00691    } else {
00692       int first = tolower((unsigned char) *pattern);
00693       for (Ssiz_t i = 0; i <= slen; ++i)
00694          if (tolower((unsigned char) sp[i]) == first &&
00695              MemIsEqual(sp+i+1, pattern+1, plen-1))
00696             return i + startIndex;
00697    }
00698    return kNPOS;
00699 }
00700 
00701 //______________________________________________________________________________
00702 Bool_t TString::MaybeRegexp() const
00703 {
00704    // Returns true if string contains one of the regexp characters "^$.[]*+?".
00705 
00706    const char *specials = "^$.[]*+?";
00707 
00708    if (First(specials) == kNPOS)
00709       return kFALSE;
00710    return kTRUE;
00711 }
00712 
00713 //______________________________________________________________________________
00714 Bool_t TString::MaybeWildcard() const
00715 {
00716    // Returns true if string contains one of the wildcard characters "[]*?".
00717 
00718    const char *specials = "[]*?";
00719 
00720    if (First(specials) == kNPOS)
00721       return kFALSE;
00722    return kTRUE;
00723 }
00724 
00725 //______________________________________________________________________________
00726 TString& TString::Prepend(char c, Ssiz_t rep)
00727 {
00728    // Prepend characters to self.
00729 
00730    Ssiz_t tot = Length() + rep;  // Final string length
00731 
00732    // Check for shared representation or insufficient capacity
00733    if ( Pref()->References() > 1 || Capacity() < tot ) {
00734       TStringRef *temp = TStringRef::GetRep(AdjustCapacity(tot), tot);
00735       memcpy(temp->Data()+rep, Data(), Length());
00736       Pref()->UnLink();
00737       fData = temp->Data();
00738    } else {
00739       memmove(fData + rep, Data(), Length());
00740       fData[Pref()->fNchars = tot] = '\0';
00741    }
00742 
00743    char *p = fData;
00744    while (rep--)
00745       *p++ = c;
00746 
00747    return *this;
00748 }
00749 
00750 //______________________________________________________________________________
00751 TString &TString::Replace(Ssiz_t pos, Ssiz_t n1, const char *cs, Ssiz_t n2)
00752 {
00753    // Remove at most n1 characters from self beginning at pos,
00754    // and replace them with the first n2 characters of cs.
00755 
00756    if (pos <= kNPOS || pos > Length()) {
00757       Error("TString::Replace",
00758             "first argument out of bounds: pos = %d, Length = %d", pos, Length());
00759       return *this;
00760    }
00761 
00762    n1 = TMath::Min(n1, Length()-pos);
00763    if (!cs) n2 = 0;
00764 
00765    Ssiz_t tot = Length()-n1+n2;  // Final string length
00766    Ssiz_t rem = Length()-n1-pos; // Length of remnant at end of string
00767 
00768    // Check for shared representation, insufficient capacity,
00769    // excess waste, or overlapping copy
00770    if (Pref()->References() > 1 ||
00771        Capacity() < tot ||
00772        Capacity() - tot > GetMaxWaste() ||
00773        (cs && (cs >= Data() && cs < Data()+Length())))
00774    {
00775       TStringRef *temp = TStringRef::GetRep(AdjustCapacity(tot), tot);
00776       if (pos) memcpy(temp->Data(), Data(), pos);
00777       if (n2 ) memcpy(temp->Data()+pos, cs, n2);
00778       if (rem) memcpy(temp->Data()+pos+n2, Data()+pos+n1, rem);
00779       Pref()->UnLink();
00780       fData = temp->Data();
00781    } else {
00782       if (rem) memmove(fData+pos+n2, Data()+pos+n1, rem);
00783       if (n2 ) memmove(fData+pos   , cs, n2);
00784       fData[Pref()->fNchars = tot] = 0;   // Add terminating null
00785    }
00786 
00787    return *this;
00788 }
00789 
00790 //______________________________________________________________________________
00791 TString& TString::ReplaceAll(const char *s1, Ssiz_t ls1, const char *s2,
00792                              Ssiz_t ls2)
00793 {
00794    // Find & Replace ls1 symbols of s1 with ls2 symbols of s2 if any.
00795 
00796    if (s1 && ls1 > 0) {
00797       Ssiz_t index = 0;
00798       while ((index = Index(s1,ls1,index, kExact)) != kNPOS) {
00799          Replace(index,ls1,s2,ls2);
00800          index += ls2;
00801       }
00802    }
00803    return *this;
00804 }
00805 
00806 //______________________________________________________________________________
00807 TString &TString::Remove(EStripType st, char c)
00808 {
00809    // Remove char c at begin and/or end of string (like Strip() but
00810    // modifies directly the string.
00811 
00812    Ssiz_t start = 0;             // Index of first character
00813    Ssiz_t end = Length();        // One beyond last character
00814    const char *direct = Data();  // Avoid a dereference w dumb compiler
00815    Ssiz_t send = end;
00816 
00817    if (st & kLeading)
00818       while (start < end && direct[start] == c)
00819          ++start;
00820    if (st & kTrailing)
00821       while (start < end && direct[end-1] == c)
00822          --end;
00823    if (end == start) {
00824       Pref()->UnLink();
00825       gNullStringRef->AddReference();
00826       fData = gNullStringRef->Data();
00827       return *this;
00828    }
00829    if (start)
00830       Remove(0, start);
00831    if (send != end)
00832       Remove(send - start - (send - end), send - end);
00833    return *this;
00834 }
00835 
00836 //______________________________________________________________________________
00837 void TString::Resize(Ssiz_t n)
00838 {
00839    // Resize the string. Truncate or add blanks as necessary.
00840 
00841    if (n < Length())
00842       Remove(n);                  // Shrank; truncate the string
00843    else
00844       Append(' ', n-Length());    // Grew or staid the same
00845 }
00846 
00847 //______________________________________________________________________________
00848 TSubString TString::Strip(EStripType st, char c) const
00849 {
00850    // Return a substring of self stripped at beginning and/or end.
00851 
00852    Ssiz_t start = 0;             // Index of first character
00853    Ssiz_t end = Length();        // One beyond last character
00854    const char *direct = Data();  // Avoid a dereference w dumb compiler
00855 
00856    if (st & kLeading)
00857       while (start < end && direct[start] == c)
00858          ++start;
00859    if (st & kTrailing)
00860       while (start < end && direct[end-1] == c)
00861          --end;
00862    if (end == start) start = end = kNPOS;  // make the null substring
00863    return TSubString(*this, start, end-start);
00864 }
00865 
00866 //______________________________________________________________________________
00867 void TString::ToLower()
00868 {
00869    // Change string to lower-case.
00870 
00871    Cow();
00872    register Ssiz_t n = Length();
00873    register char *p = fData;
00874    while (n--) {
00875       *p = tolower((unsigned char)*p);
00876       p++;
00877    }
00878 }
00879 
00880 //______________________________________________________________________________
00881 void TString::ToUpper()
00882 {
00883    // Change string to upper case.
00884 
00885    Cow();
00886    register Ssiz_t n = Length();
00887    register char *p = fData;
00888    while (n--) {
00889       *p = toupper((unsigned char)*p);
00890       p++;
00891    }
00892 }
00893 
00894 //______________________________________________________________________________
00895 char& TString::operator[](Ssiz_t i)
00896 {
00897    // Return charcater at location i.
00898 
00899    AssertElement(i);
00900    Cow();
00901    return fData[i];
00902 }
00903 
00904 //______________________________________________________________________________
00905 void TString::AssertElement(Ssiz_t i) const
00906 {
00907    // Check to make sure a string index is in range.
00908 
00909    if (i == kNPOS || i > Length())
00910       Error("TString::AssertElement",
00911             "out of bounds: i = %d, Length = %d", i, Length());
00912 }
00913 
00914 //______________________________________________________________________________
00915 TString::TString(const char *a1, Ssiz_t n1, const char *a2, Ssiz_t n2)
00916 {
00917    // Special constructor to initialize with the concatenation of a1 and a2.
00918 
00919    if (!a1) n1=0;
00920    if (!a2) n2=0;
00921    Ssiz_t tot = n1+n2;
00922    fData = TStringRef::GetRep(AdjustCapacity(tot), tot)->Data();
00923    memcpy(fData,    a1, n1);
00924    memcpy(fData+n1, a2, n2);
00925 }
00926 
00927 //______________________________________________________________________________
00928 Ssiz_t TString::AdjustCapacity(Ssiz_t nc)
00929 {
00930    // Calculate a nice capacity greater than or equal to nc.
00931 
00932    Ssiz_t ic = GetInitialCapacity();
00933    if (nc <= ic) return ic;
00934    Ssiz_t rs = GetResizeIncrement();
00935    return (nc - ic + rs - 1) / rs * rs + ic;
00936 }
00937 
00938 //______________________________________________________________________________
00939 void TString::Clear()
00940 {
00941    // Clear string without changing its capacity.
00942 
00943    Clobber(Capacity());
00944 }
00945 
00946 //______________________________________________________________________________
00947 void TString::Clobber(Ssiz_t nc)
00948 {
00949    // Clear string and make sure it has a capacity of nc.
00950 
00951    if (Pref()->References() > 1 || Capacity() < nc) {
00952       Pref()->UnLink();
00953       fData = TStringRef::GetRep(nc, 0)->Data();
00954    } else
00955       fData[Pref()->fNchars = 0] = 0;
00956 }
00957 
00958 //______________________________________________________________________________
00959 void TString::Clone()
00960 {
00961    // Make string a distinct copy; preserve previous contents.
00962 
00963    TStringRef *temp = TStringRef::GetRep(Length(), Length());
00964    memcpy(temp->Data(), Data(), Length());
00965    Pref()->UnLink();
00966    fData = temp->Data();
00967 }
00968 
00969 //______________________________________________________________________________
00970 void TString::Clone(Ssiz_t nc)
00971 {
00972    // Make self a distinct copy with capacity of at least nc.
00973    // Preserve previous contents.
00974 
00975    Ssiz_t len = Length();
00976    if (len > nc) len = nc;
00977    TStringRef *temp = TStringRef::GetRep(nc, len);
00978    memcpy(temp->Data(), Data(), len);
00979    Pref()->UnLink();
00980    fData = temp->Data();
00981 }
00982 
00983 // ------------------- ROOT I/O ------------------------------------
00984 
00985 //______________________________________________________________________________
00986 void TString::FillBuffer(char *&buffer)
00987 {
00988    // Copy string into I/O buffer.
00989 
00990    UChar_t nwh;
00991    Int_t   nchars = Length();
00992 
00993    if (nchars > 254) {
00994       nwh = 255;
00995       tobuf(buffer, nwh);
00996       tobuf(buffer, nchars);
00997    } else {
00998       nwh = UChar_t(nchars);
00999       tobuf(buffer, nwh);
01000    }
01001    for (int i = 0; i < nchars; i++) buffer[i] = fData[i];
01002    buffer += nchars;
01003 }
01004 
01005 //______________________________________________________________________________
01006 void TString::ReadBuffer(char *&buffer)
01007 {
01008    // Read string from I/O buffer.
01009 
01010    Pref()->UnLink();
01011 
01012    UChar_t nwh;
01013    Int_t   nchars;
01014 
01015    frombuf(buffer, &nwh);
01016    if (nwh == 255)
01017       frombuf(buffer, &nchars);
01018    else
01019       nchars = nwh;
01020 
01021    if (nchars < 0) {
01022       Error("ReadBuffer", "found case with nwh=%d and nchars=%d", nwh, nchars);
01023       return;
01024    }
01025    fData = TStringRef::GetRep(nchars, nchars)->Data();
01026 
01027    for (int i = 0; i < nchars; i++) frombuf(buffer, &fData[i]);
01028 }
01029 
01030 //______________________________________________________________________________
01031 TString *TString::ReadString(TBuffer &b, const TClass *clReq)
01032 {
01033    // Read TString object from buffer. Simplified version of
01034    // TBuffer::ReadObject (does not keep track of multiple
01035    // references to same string).  We need to have it here
01036    // because TBuffer::ReadObject can only handle descendant
01037    // of TObject.
01038 
01039    R__ASSERT(b.IsReading());
01040 
01041    // Make sure ReadArray is initialized
01042    b.InitMap();
01043 
01044    // Before reading object save start position
01045    UInt_t startpos = UInt_t(b.Length());
01046 
01047    UInt_t tag;
01048    TClass *clRef = b.ReadClass(clReq, &tag);
01049 
01050    TString *a;
01051    if (!clRef) {
01052 
01053       a = 0;
01054 
01055    } else {
01056 
01057       a = (TString *) clRef->New();
01058       if (!a) {
01059          ::Error("TString::ReadObject", "could not create object of class %s",
01060                  clRef->GetName());
01061          // Exception
01062          return a;
01063       }
01064 
01065       a->Streamer(b);
01066 
01067       b.CheckByteCount(startpos, tag, clRef);
01068    }
01069 
01070    return a;
01071 }
01072 
01073 //______________________________________________________________________________
01074 Int_t TString::Sizeof() const
01075 {
01076    // Returns size string will occupy on I/O buffer.
01077 
01078    if (Length() > 254)
01079       return Length()+sizeof(UChar_t)+sizeof(Int_t);
01080    else
01081       return Length()+sizeof(UChar_t);
01082 }
01083 
01084 //_______________________________________________________________________
01085 void TString::Streamer(TBuffer &b)
01086 {
01087    // Stream a string object.
01088 
01089    Int_t   nbig;
01090    UChar_t nwh;
01091    if (b.IsReading()) {
01092       b >> nwh;
01093       if (nwh == 0) {
01094          if (Pref()->References() > 1) {
01095             Pref()->UnLink();
01096             gNullStringRef->AddReference();
01097             fData = gNullStringRef->Data();
01098          } else {
01099             // Clear string without changing its capacity.
01100             fData[Pref()->fNchars = 0] = 0;
01101          }
01102       } else {
01103          if (nwh == 255)
01104             b >> nbig;
01105          else
01106             nbig = nwh;
01107 
01108          if (Pref()->References() > 1 ||
01109              Capacity() < nbig ||
01110              Capacity() - nbig > GetMaxWaste()) {
01111 
01112             Pref()->UnLink();
01113             // We trying to optimize the I/O of TNamed in particular, so we duplicate
01114             // some of the code in TStringRef::GetRep to save on the 'if statement'
01115             // at the start of the function.
01116             TStringRef *ret = (TStringRef*)new char[nbig + sizeof(TStringRef) + 1];
01117             ret->fCapacity = nbig;
01118             ret->SetRefCount(1);
01119             fData = ret->Data();
01120          }
01121          fData[Pref()->fNchars = nbig] = 0; // Terminating null
01122          b.ReadFastArray(fData,nbig);
01123       }
01124    } else {
01125       nbig = Length();
01126       if (nbig > 254) {
01127          nwh = 255;
01128          b << nwh;
01129          b << nbig;
01130       } else {
01131          nwh = UChar_t(nbig);
01132          b << nwh;
01133       }
01134       b.WriteFastArray(fData,nbig);
01135       //for (int i = 0; i < nbig; i++) b << fData[i];
01136    }
01137 }
01138 
01139 //______________________________________________________________________________
01140 void TString::WriteString(TBuffer &b, const TString *a)
01141 {
01142    // Write TString object to buffer. Simplified version of
01143    // TBuffer::WriteObject (does not keep track of multiple
01144    // references to the same string).  We need to have it here
01145    // because TBuffer::ReadObject can only handle descendant
01146    // of TObject
01147 
01148    R__ASSERT(b.IsWriting());
01149 
01150    // Make sure WriteMap is initialized
01151    b.InitMap();
01152 
01153    if (!a) {
01154 
01155       b << (UInt_t) 0;
01156 
01157    } else {
01158 
01159       // Reserve space for leading byte count
01160       UInt_t cntpos = UInt_t(b.Length());
01161       b.SetBufferOffset(Int_t(cntpos+sizeof(UInt_t)));
01162 
01163       TClass *cl = a->IsA();
01164       b.WriteClass(cl);
01165 
01166       ((TString *)a)->Streamer(b);
01167 
01168       // Write byte count
01169       b.SetByteCount(cntpos);
01170    }
01171 }
01172 
01173 //_______________________________________________________________________
01174 #if defined(R__TEMPLATE_OVERLOAD_BUG)
01175 template <>
01176 #endif
01177 TBuffer &operator>>(TBuffer &buf, TString *&s)
01178 {
01179    // Read string from TBuffer. Function declared in ClassDef.
01180 
01181    s = (TString *) TString::ReadString(buf, TString::Class());
01182    return buf;
01183 }
01184 
01185 //_______________________________________________________________________
01186 TBuffer &operator<<(TBuffer &buf, const TString *s)
01187 {
01188    // Write TString or derived to TBuffer.
01189 
01190    TString::WriteString(buf, s);
01191    return buf;
01192 }
01193 
01194 // ------------------- Related global functions --------------------
01195 
01196 //______________________________________________________________________________
01197 Bool_t operator==(const TString& s1, const char *s2)
01198 {
01199    // Compare TString with a char *.
01200 
01201    if (!s2) return kFALSE;
01202 
01203    const char *data = s1.Data();
01204    Ssiz_t len = s1.Length();
01205    Ssiz_t i;
01206    for (i = 0; s2[i]; ++i)
01207       if (data[i] != s2[i] || i == len) return kFALSE;
01208    return (i == len);
01209 }
01210 
01211 #if defined(R__ALPHA)
01212 //______________________________________________________________________________
01213 Bool_t operator==(const TString &s1, const TString &s2)
01214 {
01215    // Compare two TStrings.
01216 
01217    return ((s1.Length() == s2.Length()) && !memcmp(s1.Data(), s2.Data(), s1.Length()));
01218 }
01219 #endif
01220 
01221 //______________________________________________________________________________
01222 TString ToLower(const TString &str)
01223 {
01224    // Return a lower-case version of str.
01225 
01226    register Ssiz_t n = str.Length();
01227    TString temp((char)0, n);
01228    register const char *uc = str.Data();
01229    register       char *lc = (char*)temp.Data();
01230    // Guard against tolower() being a macro
01231    while (n--) { *lc++ = tolower((unsigned char)*uc); uc++; }
01232    return temp;
01233 }
01234 
01235 //______________________________________________________________________________
01236 TString ToUpper(const TString &str)
01237 {
01238    // Return an upper-case version of str.
01239 
01240    register Ssiz_t n = str.Length();
01241    TString temp((char)0, n);
01242    register const char* uc = str.Data();
01243    register       char* lc = (char*)temp.Data();
01244    // Guard against toupper() being a macro
01245    while (n--) { *lc++ = toupper((unsigned char)*uc); uc++; }
01246    return temp;
01247 }
01248 
01249 //______________________________________________________________________________
01250 TString operator+(const TString &s, const char *cs)
01251 {
01252    // Use the special concatenation constructor.
01253 
01254    return TString(s.Data(), s.Length(), cs, cs ? strlen(cs) : 0);
01255 }
01256 
01257 //______________________________________________________________________________
01258 TString operator+(const char *cs, const TString &s)
01259 {
01260    // Use the special concatenation constructor.
01261 
01262    return TString(cs, cs ? strlen(cs) : 0, s.Data(), s.Length());
01263 }
01264 
01265 //______________________________________________________________________________
01266 TString operator+(const TString &s1, const TString &s2)
01267 {
01268    // Use the special concatenation constructor.
01269 
01270    return TString(s1.Data(), s1.Length(), s2.Data(), s2.Length());
01271 }
01272 
01273 //______________________________________________________________________________
01274 TString operator+(const TString &s, char c)
01275 {
01276    // Add char to string.
01277 
01278    return TString(s.Data(), s.Length(), &c, 1);
01279 }
01280 
01281 //______________________________________________________________________________
01282 TString operator+(const TString &s, Long_t i)
01283 {
01284    // Add integer to string.
01285 
01286    char si[32];
01287    snprintf(si, sizeof(si), "%ld", i);
01288    return TString(s.Data(), s.Length(), si, strlen(si));
01289 }
01290 
01291 //______________________________________________________________________________
01292 TString operator+(const TString &s, ULong_t i)
01293 {
01294    // Add integer to string.
01295 
01296    char si[32];
01297    snprintf(si, sizeof(si), "%lu", i);
01298    return TString(s.Data(), s.Length(), si, strlen(si));
01299 }
01300 
01301 //______________________________________________________________________________
01302 TString operator+(const TString &s, Long64_t i)
01303 {
01304    // Add integer to string.
01305 
01306    char si[32];
01307    snprintf(si, sizeof(si), "%lld", i);
01308    return TString(s.Data(), s.Length(), si, strlen(si));
01309 }
01310 
01311 //______________________________________________________________________________
01312 TString operator+(const TString &s, ULong64_t i)
01313 {
01314    // Add integer to string.
01315 
01316    char si[32];
01317    snprintf(si, sizeof(si), "%llu", i);
01318    return TString(s.Data(), s.Length(), si, strlen(si));
01319 }
01320 
01321 //______________________________________________________________________________
01322 TString operator+(char c, const TString &s)
01323 {
01324    // Add string to integer.
01325 
01326    return TString(&c, 1, s.Data(), s.Length());
01327 }
01328 
01329 //______________________________________________________________________________
01330 TString operator+(Long_t i, const TString &s)
01331 {
01332    // Add string to integer.
01333 
01334    char si[32];
01335    snprintf(si, sizeof(si), "%ld", i);
01336    return TString(si, strlen(si), s.Data(), s.Length());
01337 }
01338 
01339 //______________________________________________________________________________
01340 TString operator+(ULong_t i, const TString &s)
01341 {
01342    // Add string to integer.
01343 
01344    char si[32];
01345    snprintf(si, sizeof(si), "%lu", i);
01346    return TString(si, strlen(si), s.Data(), s.Length());
01347 }
01348 
01349 //______________________________________________________________________________
01350 TString operator+(Long64_t i, const TString &s)
01351 {
01352    // Add string to integer.
01353 
01354    char si[32];
01355    snprintf(si, sizeof(si), "%lld", i);
01356    return TString(si, strlen(si), s.Data(), s.Length());
01357 }
01358 
01359 //______________________________________________________________________________
01360 TString operator+(ULong64_t i, const TString &s)
01361 {
01362    // Add string to integer.
01363 
01364    char si[32];
01365    snprintf(si, sizeof(si), "%llu", i);
01366    return TString(si, strlen(si), s.Data(), s.Length());
01367 }
01368 
01369 // -------------------- Static Member Functions ----------------------
01370 
01371 // Static member variable initialization:
01372 Ssiz_t TString::fgInitialCapac = 15;
01373 Ssiz_t TString::fgResizeInc    = 16;
01374 Ssiz_t TString::fgFreeboard    = 15;
01375 
01376 //______________________________________________________________________________
01377 Ssiz_t TString::InitialCapacity(Ssiz_t ic)
01378 {
01379    // Set default initial capacity for all TStrings. Default is 15.
01380 
01381    Ssiz_t ret = fgInitialCapac;
01382    fgInitialCapac = ic;
01383    return ret;
01384 }
01385 
01386 //______________________________________________________________________________
01387 Ssiz_t TString::ResizeIncrement(Ssiz_t ri)
01388 {
01389    // Set default resize increment for all TStrings. Default is 16.
01390 
01391    Ssiz_t ret = fgResizeInc;
01392    fgResizeInc = ri;
01393    return ret;
01394 }
01395 
01396 //______________________________________________________________________________
01397 Ssiz_t TString::MaxWaste(Ssiz_t mw)
01398 {
01399    // Set maximum space that may be wasted in a string before doing a resize.
01400    // Default is 15.
01401 
01402    Ssiz_t ret = fgFreeboard;
01403    fgFreeboard = mw;
01404    return ret;
01405 }
01406 
01407 
01408 //////////////////////////////////////////////////////////////////////////
01409 //                                                                      //
01410 //  TSubString                                                          //
01411 //                                                                      //
01412 //////////////////////////////////////////////////////////////////////////
01413 
01414 //
01415 // A zero lengthed substring is legal. It can start
01416 // at any character. It is considered to be "pointing"
01417 // to just before the character.
01418 //
01419 // A "null" substring is a zero lengthed substring that
01420 // starts with the nonsense index kNPOS. It can
01421 // be detected with the member function IsNull().
01422 //
01423 
01424 //______________________________________________________________________________
01425 TSubString::TSubString(const TString &str, Ssiz_t start, Ssiz_t nextent)
01426    : fStr((TString&)str), fBegin(start), fExtent(nextent)
01427 {
01428    // Private constructor.
01429 }
01430 
01431 //______________________________________________________________________________
01432 TSubString TString::operator()(Ssiz_t start, Ssiz_t len) const
01433 {
01434    // Return sub-string of string starting at start with length len.
01435 
01436    if (start < Length() && len > 0) {
01437       if (start+len > Length())
01438          len = Length() - start;
01439    } else {
01440       start = kNPOS;
01441       len   = 0;
01442    }
01443    return TSubString(*this, start, len);
01444 }
01445 
01446 //______________________________________________________________________________
01447 TSubString TString::SubString(const char *pattern, Ssiz_t startIndex,
01448                               ECaseCompare cmp) const
01449 {
01450    // Returns a substring matching "pattern", or the null substring
01451    // if there is no such match.  It would be nice if this could be yet another
01452    // overloaded version of operator(), but this would result in a type
01453    // conversion ambiguity with operator(Ssiz_t, Ssiz_t).
01454 
01455    Ssiz_t len = pattern ? strlen(pattern) : 0;
01456    Ssiz_t i = Index(pattern, len, startIndex, cmp);
01457    return TSubString(*this, i, i == kNPOS ? 0 : len);
01458 }
01459 
01460 //______________________________________________________________________________
01461 char& TSubString::operator[](Ssiz_t i)
01462 {
01463    // Return character at pos i from sub-string. Check validity of i.
01464 
01465    AssertElement(i);
01466    fStr.Cow();
01467    return fStr.fData[fBegin+i];
01468 }
01469 
01470 //______________________________________________________________________________
01471 char& TSubString::operator()(Ssiz_t i)
01472 {
01473    // Return character at pos i from sub-string. No check on i.
01474 
01475    fStr.Cow();
01476    return fStr.fData[fBegin+i];
01477 }
01478 
01479 //______________________________________________________________________________
01480 TSubString& TSubString::operator=(const TString &str)
01481 {
01482    // Assign string to sub-string.
01483 
01484    if (!IsNull())
01485       fStr.Replace(fBegin, fExtent, str.Data(), str.Length());
01486 
01487    return *this;
01488 }
01489 
01490 //______________________________________________________________________________
01491 TSubString& TSubString::operator=(const char *cs)
01492 {
01493    // Assign char* to sub-string.
01494 
01495    if (!IsNull())
01496       fStr.Replace(fBegin, fExtent, cs, cs ? strlen(cs) : 0);
01497 
01498    return *this;
01499 }
01500 
01501 //______________________________________________________________________________
01502 Bool_t operator==(const TSubString& ss, const char *cs)
01503 {
01504    // Compare sub-string to char *.
01505 
01506    if (ss.IsNull()) return *cs =='\0'; // Two null strings compare equal
01507 
01508    const char* data = ss.fStr.Data() + ss.fBegin;
01509    Ssiz_t i;
01510    for (i = 0; cs[i]; ++i)
01511       if (cs[i] != data[i] || i == ss.fExtent) return kFALSE;
01512    return (i == ss.fExtent);
01513 }
01514 
01515 //______________________________________________________________________________
01516 Bool_t operator==(const TSubString& ss, const TString &s)
01517 {
01518    // Compare sub-string to string.
01519 
01520    if (ss.IsNull()) return s.IsNull(); // Two null strings compare equal.
01521    if (ss.fExtent != s.Length()) return kFALSE;
01522    return !memcmp(ss.fStr.Data() + ss.fBegin, s.Data(), ss.fExtent);
01523 }
01524 
01525 //______________________________________________________________________________
01526 Bool_t operator==(const TSubString &s1, const TSubString &s2)
01527 {
01528    // Compare two sub-strings.
01529 
01530    if (s1.IsNull()) return s2.IsNull();
01531    if (s1.fExtent != s2.fExtent) return kFALSE;
01532    return !memcmp(s1.fStr.Data()+s1.fBegin, s2.fStr.Data()+s2.fBegin,
01533                   s1.fExtent);
01534 }
01535 
01536 //______________________________________________________________________________
01537 void TSubString::ToLower()
01538 {
01539    // Convert sub-string to lower-case.
01540 
01541    if (!IsNull()) {                             // Ignore null substrings
01542       fStr.Cow();
01543       register char *p = (char*)(fStr.Data() + fBegin); // Cast away constness
01544       Ssiz_t n = fExtent;
01545       while (n--) { *p = tolower((unsigned char)*p); p++;}
01546    }
01547 }
01548 
01549 //______________________________________________________________________________
01550 void TSubString::ToUpper()
01551 {
01552    // Convert sub-string to upper-case.
01553    if (!IsNull()) {                             // Ignore null substrings
01554       fStr.Cow();
01555       register char *p = (char*)(fStr.Data() + fBegin); // Cast away constness
01556       Ssiz_t n = fExtent;
01557       while (n--) { *p = toupper((unsigned char)*p); p++;}
01558    }
01559 }
01560 
01561 //______________________________________________________________________________
01562 void TSubString::SubStringError(Ssiz_t sr, Ssiz_t start, Ssiz_t n) const
01563 {
01564    // Output error message.
01565 
01566    Error("TSubString::SubStringError",
01567          "out of bounds: start = %d, n = %d, sr = %d", start, n, sr);
01568 }
01569 
01570 //______________________________________________________________________________
01571 void TSubString::AssertElement(Ssiz_t i) const
01572 {
01573    // Check to make sure a sub-string index is in range.
01574 
01575    if (i == kNPOS || i >= Length())
01576       Error("TSubString::AssertElement",
01577             "out of bounds: i = %d, Length = %d", i, Length());
01578 }
01579 
01580 //______________________________________________________________________________
01581 Bool_t TString::IsAscii() const
01582 {
01583    // Returns true if all characters in string are ascii.
01584 
01585    const char *cp = Data();
01586    for (Ssiz_t i = 0; i < Length(); ++i)
01587       if (cp[i] & ~0x7F)
01588          return kFALSE;
01589    return kTRUE;
01590 }
01591 
01592 //______________________________________________________________________________
01593 Bool_t TString::IsAlpha() const
01594 {
01595    // Returns true if all characters in string are alphabetic.
01596    // Returns false in case string length is 0.
01597 
01598    const char *cp = Data();
01599    Ssiz_t len = Length();
01600    if (len == 0) return kFALSE;
01601    for (Ssiz_t i = 0; i < len; ++i)
01602       if (!isalpha(cp[i]))
01603          return kFALSE;
01604    return kTRUE;
01605 }
01606 
01607 //______________________________________________________________________________
01608 Bool_t TString::IsAlnum() const
01609 {
01610    // Returns true if all characters in string are alphanumeric.
01611    // Returns false in case string length is 0.
01612 
01613    const char *cp = Data();
01614    Ssiz_t len = Length();
01615    if (len == 0) return kFALSE;
01616    for (Ssiz_t i = 0; i < len; ++i)
01617       if (!isalnum(cp[i]))
01618          return kFALSE;
01619    return kTRUE;
01620 }
01621 
01622 //______________________________________________________________________________
01623 Bool_t TString::IsDigit() const
01624 {
01625    // Returns true if all characters in string are digits (0-9) or whitespaces,
01626    // i.e. "123456" and "123 456" are both valid integer strings.
01627    // Returns false in case string length is 0 or string contains other
01628    // characters or only whitespace.
01629 
01630    const char *cp = Data();
01631    Ssiz_t len = Length();
01632    if (len == 0) return kFALSE;
01633    Int_t b = 0, d = 0;
01634    for (Ssiz_t i = 0; i < len; ++i) {
01635       if (cp[i] != ' ' && !isdigit(cp[i])) return kFALSE;
01636       if (cp[i] == ' ') b++;
01637       if (isdigit(cp[i])) d++;
01638    }
01639    if (b && !d)
01640       return kFALSE;
01641    return kTRUE;
01642 }
01643 
01644 //______________________________________________________________________________
01645 Bool_t TString::IsFloat() const
01646 {
01647    // Returns kTRUE if string contains a floating point or integer number.
01648    // Examples of valid formats are:
01649    //    64320
01650    //    64 320
01651    //    6 4 3 2 0
01652    //    6.4320     6,4320
01653    //    6.43e20   6.43E20    6,43e20
01654    //    6.43e-20  6.43E-20   6,43e-20
01655 
01656    //we first check if we have an integer, in this case, IsDigit() will be true straight away
01657    if (IsDigit()) return kTRUE;
01658 
01659    TString tmp = *this;
01660    //now we look for occurrences of '.', ',', e', 'E', '+', '-' and replace each
01661    //with ' '. if it is a floating point, IsDigit() will then return kTRUE
01662    Int_t i_dot, i_e, i_plus, i_minus, i_comma;
01663    i_dot = i_e = i_plus = i_minus = i_comma = -1;
01664 
01665    i_dot = tmp.First('.');
01666    if (i_dot > -1) tmp.Replace(i_dot, 1, " ", 1);
01667    i_comma = tmp.First(',');
01668    if (i_comma > -1) tmp.Replace(i_comma, 1, " ", 1);
01669    i_e = tmp.First('e');
01670    if (i_e > -1)
01671       tmp.Replace(i_e, 1, " ", 1);
01672    else {
01673       //try for a capital "E"
01674       i_e = tmp.First('E');
01675       if (i_e > -1) tmp.Replace(i_e, 1, " ", 1);
01676    }
01677    i_plus = tmp.First('+');
01678    if (i_plus > -1) tmp.ReplaceAll("+", " ");
01679    i_minus = tmp.First('-');
01680    if (i_minus > -1) tmp.ReplaceAll("-", " ");
01681 
01682    //test if it is now uniquely composed of numbers
01683    return tmp.IsDigit();
01684 }
01685 
01686 //______________________________________________________________________________
01687 Bool_t TString::IsHex() const
01688 {
01689    // Returns true if all characters in string are hexidecimal digits
01690    // (0-9,a-f,A-F). Returns false in case string length is 0.
01691 
01692 
01693    const char *cp = Data();
01694    Ssiz_t len = Length();
01695    if (len == 0) return kFALSE;
01696    for (Ssiz_t i = 0; i < len; ++i)
01697       if (!isxdigit(cp[i]))
01698          return kFALSE;
01699    return kTRUE;
01700 }
01701 
01702 //______________________________________________________________________________
01703 Int_t TString::Atoi() const
01704 {
01705    // Return integer value of string.
01706    // Valid strings include only digits and whitespace (see IsDigit()),
01707    // i.e. "123456", "123 456" and "1 2 3 4        56" are all valid
01708    // integer strings whose Atoi() value is 123456.
01709 
01710    //any whitespace ?
01711    Int_t end = Index(" ");
01712    //if no whitespaces in string, just use atoi()
01713    if (end == -1) return atoi(Data());
01714    //make temporary string, removing whitespace
01715    Int_t start = 0;
01716    TString tmp;
01717    //loop over all whitespace
01718    while (end > -1) {
01719       tmp += (*this)(start, end-start);
01720       start = end+1; end = Index(" ", start);
01721    }
01722    //finally add part from last whitespace to end of string
01723    end = Length();
01724    tmp += (*this)(start, end-start);
01725    return atoi(tmp.Data());
01726 }
01727 
01728 //______________________________________________________________________________
01729 Long64_t TString::Atoll() const
01730 {
01731    // Return long long value of string.
01732    // Valid strings include only digits and whitespace (see IsDigit()),
01733    // i.e. "123456", "123 456" and "1 2 3 4        56" are all valid
01734    // integer strings whose Atoll() value is 123456.
01735 
01736    //any whitespace ?
01737    Int_t end = Index(" ");
01738    //if no whitespaces in string, just use atoi()
01739 #ifndef R__WIN32
01740    if (end == -1) return atoll(Data());
01741 #else
01742    if (end == -1) return _atoi64(Data());
01743 #endif
01744    //make temporary string, removing whitespace
01745    Int_t start = 0;
01746    TString tmp;
01747    //loop over all whitespace
01748    while (end > -1) {
01749       tmp += (*this)(start, end-start);
01750       start = end+1; end = Index(" ", start);
01751    }
01752    //finally add part from last whitespace to end of string
01753    end = Length();
01754    tmp += (*this)(start, end-start);
01755 #ifndef R__WIN32
01756    return atoll(tmp.Data());
01757 #else
01758    return _atoi64(tmp.Data());
01759 #endif
01760 }
01761 
01762 //______________________________________________________________________________
01763 Double_t TString::Atof() const
01764 {
01765    // Return floating-point value contained in string.
01766    // Examples of valid strings are:
01767    //    64320
01768    //    64 320
01769    //    6 4 3 2 0
01770    //    6.4320     6,4320
01771    //    6.43e20   6.43E20    6,43e20
01772    //    6.43e-20  6.43E-20   6,43e-20
01773 
01774    //look for a comma and some whitespace
01775    Int_t comma = Index(",");
01776    Int_t end = Index(" ");
01777    //if no commas & no whitespace in string, just use atof()
01778    if (comma == -1 && end == -1) return atof(Data());
01779    TString tmp = *this;
01780    if (comma > -1) {
01781       //replace comma with decimal point
01782       tmp.Replace(comma, 1, ".");
01783    }
01784    //no whitespace ?
01785    if (end == -1) return atof(tmp.Data());
01786    //remove whitespace
01787    Int_t start = 0;
01788    TString tmp2;
01789    while (end > -1) {
01790       tmp2 += tmp(start, end-start);
01791       start = end+1; end = tmp.Index(" ", start);
01792    }
01793    end = tmp.Length();
01794    tmp2 += tmp(start, end-start);
01795    return atof(tmp2.Data());
01796 }
01797 
01798 //______________________________________________________________________________
01799 Bool_t TString::EndsWith(const char *s, ECaseCompare cmp) const
01800 {
01801    // Return true if string ends with the specified string.
01802 
01803    if (!s) return kTRUE;
01804 
01805    Ssiz_t l = strlen(s);
01806    if (l > Length()) return kFALSE;
01807    const char *s2 = Data() + Length() - l;
01808 
01809    if (cmp == kExact)
01810       return strcmp(s, s2) == 0;
01811    return strcasecmp(s, s2) == 0;
01812 }
01813 
01814 //__________________________________________________________________________________
01815 TObjArray *TString::Tokenize(const TString &delim) const
01816 {
01817    // This function is used to isolate sequential tokens in a TString.
01818    // These tokens are separated in the string by at least one of the
01819    // characters in delim. The returned array contains the tokens
01820    // as TObjString's. The returned array is the owner of the objects,
01821    // and must be deleted by the user.
01822 
01823    std::list<Int_t> splitIndex;
01824 
01825    Int_t i, start, nrDiff = 0;
01826    for (i = 0; i < delim.Length(); i++) {
01827       start = 0;
01828       while (start < Length()) {
01829          Int_t pos = Index(delim(i), start);
01830          if (pos == kNPOS) break;
01831          splitIndex.push_back(pos);
01832          start = pos + 1;
01833       }
01834       if (start > 0) nrDiff++;
01835    }
01836    splitIndex.push_back(Length());
01837 
01838    if (nrDiff > 1)
01839       splitIndex.sort();
01840 
01841    TObjArray *arr = new TObjArray();
01842    arr->SetOwner();
01843 
01844    start = -1;
01845    std::list<Int_t>::const_iterator it;
01846 #ifndef R__HPUX
01847    for (it = splitIndex.begin(); it != splitIndex.end(); it++) {
01848 #else
01849    for (it = splitIndex.begin(); it != (std::list<Int_t>::const_iterator) splitIndex.end(); it++) {
01850 #endif
01851       Int_t stop = *it;
01852       if (stop - 1 >= start + 1) {
01853          TString tok = (*this)(start+1, stop-start-1);
01854          TObjString *objstr = new TObjString(tok);
01855          arr->Add(objstr);
01856       }
01857       start = stop;
01858    }
01859 
01860    return arr;
01861 }
01862 
01863 //______________________________________________________________________________
01864 void TString::FormImp(const char *fmt, va_list ap)
01865 {
01866    // Formats a string using a printf style format descriptor.
01867    // Existing string contents will be overwritten.
01868 
01869    Ssiz_t buflen = 20 + 20 * strlen(fmt);    // pick a number, any strictly positive number
01870    Clobber(buflen);
01871 
01872    va_list sap;
01873    R__VA_COPY(sap, ap);
01874 
01875    int n, vc = 0;
01876 again:
01877    n = vsnprintf(fData, buflen, fmt, ap);
01878    // old vsnprintf's return -1 if string is truncated new ones return
01879    // total number of characters that would have been written
01880    if (n == -1 || n >= buflen) {
01881       if (n == -1)
01882          buflen *= 2;
01883       else
01884          buflen = n+1;
01885       Clobber(buflen);
01886       va_end(ap);
01887       R__VA_COPY(ap, sap);
01888       vc = 1;
01889       goto again;
01890    }
01891    va_end(sap);
01892    if (vc)
01893       va_end(ap);
01894 
01895    Pref()->fNchars = strlen(fData);
01896 }
01897 
01898 //______________________________________________________________________________
01899 void TString::Form(const char *va_(fmt), ...)
01900 {
01901    // Formats a string using a printf style format descriptor.
01902    // Existing string contents will be overwritten.
01903 
01904    va_list ap;
01905    va_start(ap, va_(fmt));
01906    FormImp(va_(fmt), ap);
01907    va_end(ap);
01908 }
01909 
01910 //______________________________________________________________________________
01911 TString TString::Format(const char *va_(fmt), ...)
01912 {
01913    // Static method which formats a string using a printf style format
01914    // descriptor and return a TString. Same as TString::Form() but it is
01915    // not needed to first create a TString.
01916 
01917    va_list ap;
01918    va_start(ap, va_(fmt));
01919    TString str;
01920    str.FormImp(va_(fmt), ap);
01921    va_end(ap);
01922    return str;
01923 }
01924 
01925 //---- Global String Handling Functions ----------------------------------------
01926 
01927 static const int cb_size  = 4096;
01928 static const int fld_size = 2048;
01929 
01930 // a circular formating buffer
01931 static char gFormbuf[cb_size];       // some slob for form overflow
01932 static char *gBfree  = gFormbuf;
01933 static char *gEndbuf = &gFormbuf[cb_size-1];
01934 
01935 //______________________________________________________________________________
01936 static char *SlowFormat(const char *format, va_list ap, int hint)
01937 {
01938    // Format a string in a formatting buffer (using a printf style
01939    // format descriptor).
01940 
01941    static char *slowBuffer  = 0;
01942    static int   slowBufferSize = 0;
01943 
01944    R__LOCKGUARD2(gStringMutex);
01945 
01946    if (hint == -1) hint = fld_size;
01947    if (hint > slowBufferSize) {
01948       delete [] slowBuffer;
01949       slowBufferSize = 2 * hint;
01950       if (hint < 0 || slowBufferSize < 0) {
01951          slowBufferSize = 0;
01952          slowBuffer = 0;
01953          return 0;
01954       }
01955       slowBuffer = new char[slowBufferSize];
01956    }
01957 
01958    va_list sap;
01959    R__VA_COPY(sap, ap);
01960 
01961    int n = vsnprintf(slowBuffer, slowBufferSize, format, ap);
01962    // old vsnprintf's return -1 if string is truncated new ones return
01963    // total number of characters that would have been written
01964    if (n == -1 || n >= slowBufferSize) {
01965       if (n == -1) n = 2 * slowBufferSize;
01966       if (n == slowBufferSize) n++;
01967       if (n <= 0) {
01968          va_end(sap);
01969          return 0; // int overflow!
01970       }
01971       va_end(ap);
01972       R__VA_COPY(ap, sap);
01973       char *buf = SlowFormat(format, ap, n);
01974       va_end(sap);
01975       va_end(ap);
01976       return buf;
01977    }
01978 
01979    va_end(sap);
01980 
01981    return slowBuffer;
01982 }
01983 
01984 //______________________________________________________________________________
01985 static char *Format(const char *format, va_list ap)
01986 {
01987    // Format a string in a circular formatting buffer (using a printf style
01988    // format descriptor).
01989 
01990    R__LOCKGUARD2(gStringMutex);
01991 
01992    char *buf = gBfree;
01993 
01994    if (buf+fld_size > gEndbuf)
01995       buf = gFormbuf;
01996 
01997    va_list sap;
01998    R__VA_COPY(sap, ap);
01999 
02000    int n = vsnprintf(buf, fld_size, format, ap);
02001    // old vsnprintf's return -1 if string is truncated new ones return
02002    // total number of characters that would have been written
02003    if (n == -1 || n >= fld_size) {
02004       va_end(ap);
02005       R__VA_COPY(ap, sap);
02006       buf = SlowFormat(format, ap, n);
02007       va_end(sap);
02008       va_end(ap);
02009       return buf;
02010    }
02011 
02012    va_end(sap);
02013 
02014    gBfree = buf+n+1;
02015    return buf;
02016 }
02017 
02018 //______________________________________________________________________________
02019 char *Form(const char *va_(fmt), ...)
02020 {
02021    // Formats a string in a circular formatting buffer. Removes the need to
02022    // create and delete short lived strings. Don't pass Form() pointers
02023    // from user code down to ROOT functions as the circular buffer may
02024    // be overwritten downstream. Use Form() results immediately or use
02025    // TString::Format() instead.
02026 
02027    va_list ap;
02028    va_start(ap,va_(fmt));
02029    char *b = Format(va_(fmt), ap);
02030    va_end(ap);
02031    return b;
02032 }
02033 
02034 //______________________________________________________________________________
02035 void Printf(const char *va_(fmt), ...)
02036 {
02037    // Formats a string in a circular formatting buffer and prints the string.
02038    // Appends a newline. If gPrintViaErrorHandler is true it will print via the
02039    // currently active ROOT error handler.
02040 
02041    va_list ap;
02042    va_start(ap,va_(fmt));
02043    if (gPrintViaErrorHandler)
02044       ErrorHandler(kPrint, 0, va_(fmt), ap);
02045    else {
02046       char *b = Format(va_(fmt), ap);
02047       printf("%s\n", b);
02048       fflush(stdout);
02049    }
02050    va_end(ap);
02051 }
02052 
02053 //______________________________________________________________________________
02054 char *Strip(const char *s, char c)
02055 {
02056    // Strip leading and trailing c (blanks by default) from a string.
02057    // The returned string has to be deleted by the user.
02058 
02059    if (!s) return 0;
02060 
02061    int l = strlen(s);
02062    char *buf = new char[l+1];
02063 
02064    if (l == 0) {
02065       *buf = '\0';
02066       return buf;
02067    }
02068 
02069    // get rid of leading c's
02070    const char *t1 = s;
02071    while (*t1 == c)
02072       t1++;
02073 
02074    // get rid of trailing c's
02075    const char *t2 = s + l - 1;
02076    while (*t2 == c && t2 > s)
02077       t2--;
02078 
02079    if (t1 > t2) {
02080       *buf = '\0';
02081       return buf;
02082    }
02083    strncpy(buf, t1, (Ssiz_t) (t2-t1+1));
02084    *(buf+(t2-t1+1)) = '\0';
02085 
02086    return buf;
02087 }
02088 
02089 //______________________________________________________________________________
02090 char *StrDup(const char *str)
02091 {
02092    // Duplicate the string str. The returned string has to be deleted by
02093    // the user.
02094 
02095    if (!str) return 0;
02096 
02097    char *s = new char[strlen(str)+1];
02098    if (s) strcpy(s, str);
02099 
02100    return s;
02101 }
02102 
02103 //______________________________________________________________________________
02104 char *Compress(const char *str)
02105 {
02106    // Remove all blanks from the string str. The returned string has to be
02107    // deleted by the user.
02108 
02109    if (!str) return 0;
02110 
02111    const char *p = str;
02112    char *s, *s1 = new char[strlen(str)+1];
02113    s = s1;
02114 
02115    while (*p) {
02116       if (*p != ' ')
02117          *s++ = *p;
02118       p++;
02119    }
02120    *s = '\0';
02121 
02122    return s1;
02123 }
02124 
02125 //______________________________________________________________________________
02126 int EscChar(const char *src, char *dst, int dstlen, char *specchars,
02127             char escchar)
02128 {
02129    // Escape specchars in src with escchar and copy to dst.
02130 
02131    const char *p;
02132    char *q, *end = dst+dstlen-1;
02133 
02134    for (p = src, q = dst; *p && q < end; ) {
02135       if (strchr(specchars, *p)) {
02136          *q++ = escchar;
02137          if (q < end)
02138             *q++ = *p++;
02139       } else
02140          *q++ = *p++;
02141    }
02142    *q = '\0';
02143 
02144    if (*p != 0)
02145       return -1;
02146    return q-dst;
02147 }
02148 
02149 //______________________________________________________________________________
02150 int UnEscChar(const char *src, char *dst, int dstlen, char *specchars, char)
02151 {
02152    // Un-escape specchars in src from escchar and copy to dst.
02153 
02154    const char *p;
02155    char *q, *end = dst+dstlen-1;
02156 
02157    for (p = src, q = dst; *p && q < end; ) {
02158       if (strchr(specchars, *p))
02159          p++;
02160       else
02161          *q++ = *p++;
02162    }
02163    *q = '\0';
02164 
02165    if (*p != 0)
02166       return -1;
02167    return q-dst;
02168 }
02169 
02170 #ifdef NEED_STRCASECMP
02171 //______________________________________________________________________________
02172 int strcasecmp(const char *str1, const char *str2)
02173 {
02174    // Case insensitive string compare.
02175 
02176    return strncasecmp(str1, str2, str2 ? strlen(str2)+1 : 0);
02177 }
02178 
02179 //______________________________________________________________________________
02180 int strncasecmp(const char *str1, const char *str2, Ssiz_t n)
02181 {
02182    // Case insensitive string compare of n characters.
02183 
02184    while (n > 0) {
02185       int c1 = *str1;
02186       int c2 = *str2;
02187 
02188       if (isupper(c1))
02189          c1 = tolower(c1);
02190 
02191       if (isupper(c2))
02192          c2 = tolower(c2);
02193 
02194       if (c1 != c2)
02195          return c1 - c2;
02196 
02197       str1++;
02198       str2++;
02199       n--;
02200    }
02201    return 0;
02202 }
02203 #endif

Generated on Tue Jul 5 14:11:23 2011 for ROOT_528-00b_version by  doxygen 1.5.1