diff --git a/core/base/inc/TString.h b/core/base/inc/TString.h index 1ddf303d3b28aa48ff7501a2ac344312b592d4c1..1f7fd1e193d51b3de6ae15346747509ab8494e43 100644 --- a/core/base/inc/TString.h +++ b/core/base/inc/TString.h @@ -208,7 +208,7 @@ protected: enum { kAlignment = 16 }; static Ssiz_t Align(Ssiz_t s) { return (s + (kAlignment-1)) & ~(kAlignment-1); } static Ssiz_t Recommend(Ssiz_t s) { return (s < kMinCap ? kMinCap : Align(s+1)) - 1; } - static Ssiz_t AdjustCapacity(Ssiz_t nc); + static Ssiz_t AdjustCapacity(Ssiz_t oldCap, Ssiz_t newCap); private: Bool_t IsLong() const { return Bool_t(fRep.fShort.fSize & kShortMask); } @@ -232,9 +232,9 @@ private: char *GetPointer() { return IsLong() ? GetLongPointer() : GetShortPointer(); } const char *GetPointer() const { return IsLong() ? GetLongPointer() : GetShortPointer(); } #ifdef R__BYTESWAP - Ssiz_t MaxSize() const { return kMaxInt - 1; } + static Ssiz_t MaxSize() { return kMaxInt - 1; } #else - Ssiz_t MaxSize() const { return (kMaxInt >> 1) - 1; } + static Ssiz_t MaxSize() { return (kMaxInt >> 1) - 1; } #endif void UnLink() const { if (IsLong()) delete [] fRep.fLong.fData; } void Zero() { diff --git a/core/base/src/Stringio.cxx b/core/base/src/Stringio.cxx index 5cc288df92a984c4a024f0bb841f611f9c032b27..888be3d3fd68fafe0920ba494f5d9c525505c5b1 100644 --- a/core/base/src/Stringio.cxx +++ b/core/base/src/Stringio.cxx @@ -40,7 +40,8 @@ istream& TString::ReadFile(istream& strm) while(1) { Ssiz_t len = Length(); - strm.read(GetPointer()+len, Capacity()-len); + Ssiz_t cap = Capacity(); + strm.read(GetPointer()+len, cap-len); SetSize(len + strm.gcount()); if (!strm.good()) @@ -49,7 +50,8 @@ istream& TString::ReadFile(istream& strm) // If we got here, the read must have stopped because // the buffer was going to overflow. Resize and keep // going. - Capacity(Length() + incr); + cap = AdjustCapacity(cap, cap+incr); + Capacity(cap); } GetPointer()[Length()] = '\0'; // Add null terminator @@ -90,14 +92,16 @@ istream& TString::ReadToDelim(istream& strm, char delim) const Ssiz_t incr = 32; Clobber(incr); + int p = strm.peek(); // Check if we are already at delim if (p == delim) { strm.get(); // eat the delimiter, and return \0. } else { while (1) { Ssiz_t len = Length(); + Ssiz_t cap = Capacity(); strm.get(GetPointer()+len, // Address of next byte - Capacity()-len+1, // Space available (+1 for terminator) + cap-len+1, // Space available (+1 for terminator) delim); // Delimiter SetSize(len + strm.gcount()); if (!strm.good()) break; // Check for EOF or stream failure @@ -107,7 +111,8 @@ istream& TString::ReadToDelim(istream& strm, char delim) break; } // Delimiter not seen. Resize and keep going: - Capacity(Length() + incr); + cap = AdjustCapacity(cap, cap+incr); + Capacity(cap); } } @@ -135,9 +140,11 @@ istream& TString::ReadToken(istream& strm) strm.get(c).good() && (hitSpace = isspace((Int_t)c)) == 0) { // Check for overflow: Ssiz_t len = Length(); - if (len == Capacity()) - Capacity(len + incr); - + Ssiz_t cap = Capacity(); + if (len == cap) { + cap = AdjustCapacity(cap, cap+incr); + Capacity(cap); + } GetPointer()[len] = c; len++; SetSize(len); diff --git a/core/base/src/TString.cxx b/core/base/src/TString.cxx index 6a70bd1e994851b512597880f6a10ca4b7645a3e..bc71f7d39627b54cc51ed6c760f6453568b693de 100644 --- a/core/base/src/TString.cxx +++ b/core/base/src/TString.cxx @@ -319,7 +319,7 @@ TString& TString::Append(char c, Ssiz_t rep) SetSize(tot); data = p; } else { - Ssiz_t cap = Recommend(tot); + Ssiz_t cap = AdjustCapacity(capac, tot); data = new char[cap+1]; memcpy(data, p, len); UnLink(); @@ -760,7 +760,7 @@ TString& TString::Prepend(char c, Ssiz_t rep) SetSize(tot); data = p; } else { - Ssiz_t cap = Recommend(tot); + Ssiz_t cap = AdjustCapacity(capac, tot); data = new char[cap+1]; memcpy(data+rep, p, len); UnLink(); @@ -825,7 +825,7 @@ finish: SetSize(tot); p[tot] = 0; } else { - Ssiz_t cap = Recommend(tot); + Ssiz_t cap = AdjustCapacity(capac, tot); char *data = new char[cap+1]; if (pos) memcpy(data, p, pos); if (n2 ) memcpy(data + pos, cs, n2); @@ -848,8 +848,8 @@ TString& TString::ReplaceAll(const char *s1, Ssiz_t ls1, const char *s2, if (s1 && ls1 > 0) { Ssiz_t index = 0; - while ((index = Index(s1,ls1,index, kExact)) != kNPOS) { - Replace(index,ls1,s2,ls2); + while ((index = Index(s1, ls1, index, kExact)) != kNPOS) { + Replace(index, ls1, s2, ls2); index += ls2; } } @@ -952,11 +952,18 @@ void TString::AssertElement(Ssiz_t i) const } //______________________________________________________________________________ -Ssiz_t TString::AdjustCapacity(Ssiz_t nc) +Ssiz_t TString::AdjustCapacity(Ssiz_t oldCap, Ssiz_t newCap) { - // Calculate a nice capacity greater than or equal to nc. + // Calculate a nice capacity greater than or equal to newCap. - return Recommend(nc); + Ssiz_t ms = MaxSize(); + if (newCap > ms - 1) { + Error("AdjustCapacity", "capacity too large (%d, max = %d)", + newCap, ms); + } + Ssiz_t cap = oldCap < ms / 2 - kAlignment ? + Recommend(TMath::Max(newCap, 2 * oldCap)) : ms - 1; + return cap; } //______________________________________________________________________________ diff --git a/test/tstring.cxx b/test/tstring.cxx index b25a50cfb1ffe94de6114dd7dde6cd69a7e09928..61b26e7af1277cc47dc6a4a73dfe14490febc326 100644 --- a/test/tstring.cxx +++ b/test/tstring.cxx @@ -7,6 +7,7 @@ #include "TString.h" #include "TRegexp.h" #include "TPRegexp.h" +#include "TSystem.h" void Ok(int i, int b) @@ -156,6 +157,7 @@ int main() Printf("Using Print: %s (%d)\n", (const char*) s9, s9.Length()); + // test comparisons TString s20 = "abc"; TString s21 = "abcd"; TString s22 = "bcde"; @@ -168,5 +170,23 @@ int main() Ok(31, s22.CompareTo(s23, TString::kIgnoreCase) == 0); Ok(32, (s23 < s24) != (s24 < s23)); + // test file access + ifstream f("tstring.cxx"); + f.seekg(0, ios::end); + Ssiz_t size = f.tellg(); + f.seekg(0, ios::beg); + + TString fs; + fs.ReadFile(f); + Ok(33, size == fs.Length()); + + ifstream f2("tstring.cxx"); + fs.ReadLine(f2); // read '// @(#)root/test:$Id: tstring.cxx 38977..." + Ok(34, fs.Contains("root/test")); + + fs.ReadToken(f2); // read '//' + fs.ReadToken(f2); // read 'Author:' + Ok(35, fs == "Author:"); + return 0; }