diff --git a/src/common/classes/fb_string.cpp b/src/common/classes/fb_string.cpp index 40a2a5c1f4..b9eac15bc7 100644 --- a/src/common/classes/fb_string.cpp +++ b/src/common/classes/fb_string.cpp @@ -68,7 +68,7 @@ namespace { m[c >> 3] |= (1 << (c & 7)); } } - inline bool Contains(const char c) { + inline bool Contains(const char c) const { return m[c >> 3] & (1 << (c & 7)); } }; @@ -91,10 +91,12 @@ namespace Firebird { const_pointer p2, size_type n2) { // CVC: npos must be maximum size_type value for all platforms. - // fb_assert(npos - n1 > n2 && n1 + n2 <= max_length()); - checkLength(n1); - checkLength(n2); - checkLength(n1 + n2); + // fb_assert(n2 < npos - n1 && n1 + n2 <= max_length()); + if (n2 > npos - n1) + { + Firebird::fatal_exception::raise("String length overflow"); + } + // checkLength(n1 + n2); redundant: initialize() will check. initialize(n1 + n2); memcpy(stringBuffer, p1, n1); memcpy(stringBuffer + n1, p2, n2); @@ -104,6 +106,18 @@ namespace Firebird { initialize(sizeL); memset(stringBuffer, c, sizeL); } + + AbstractString::size_type AbstractString::copy_to(pointer destination, + size_type bufsize) const + { + if (!destination || !bufsize) + return 0; + + const size_type copy_len = length() < bufsize ? length() : bufsize - 1; + memcpy(destination, stringBuffer, copy_len); + destination[copy_len] = 0; + return copy_len; + } void AbstractString::AdjustRange(size_type length, size_type& pos, size_type& n) { if (pos == npos) { @@ -213,7 +227,7 @@ namespace Firebird { } AbstractString::size_type AbstractString::find_first_of(const_pointer s, size_type pos, size_type n) const { - strBitMask sm(s, n); + const strBitMask sm(s, n); const_pointer p = &c_str()[pos]; while (pos < length()) { if (sm.Contains(*p++)) { @@ -225,7 +239,7 @@ namespace Firebird { } AbstractString::size_type AbstractString::find_last_of(const_pointer s, size_type pos, size_type n) const { - strBitMask sm(s, n); + const strBitMask sm(s, n); int lpos = length() - 1; if (static_cast(pos) < lpos && pos != npos) { lpos = pos; @@ -241,7 +255,7 @@ namespace Firebird { } AbstractString::size_type AbstractString::find_first_not_of(const_pointer s, size_type pos, size_type n) const { - strBitMask sm(s, n); + const strBitMask sm(s, n); const_pointer p = &c_str()[pos]; while (pos < length()) { if (! sm.Contains(*p++)) { @@ -253,7 +267,7 @@ namespace Firebird { } AbstractString::size_type AbstractString::find_last_not_of(const_pointer s, size_type pos, size_type n) const { - strBitMask sm(s, n); + const strBitMask sm(s, n); int lpos = length() - 1; if (static_cast(pos) < lpos && pos != npos) { lpos = pos; @@ -315,7 +329,7 @@ extern "C" { } void AbstractString::baseTrim(TrimType WhereTrim, const_pointer ToTrim) { - strBitMask sm(ToTrim, strlen(ToTrim)); + const strBitMask sm(ToTrim, strlen(ToTrim)); const_pointer b = c_str(); const_pointer e = &c_str()[length() - 1]; if (WhereTrim != TrimRight) { @@ -334,7 +348,7 @@ extern "C" { --e; } } - size_type NewLength = e - b + 1; + const size_type NewLength = e - b + 1; if (NewLength == length()) return; diff --git a/src/include/fb_string.h b/src/include/fb_string.h index 7734a392f6..c3a31834ed 100644 --- a/src/include/fb_string.h +++ b/src/include/fb_string.h @@ -53,17 +53,20 @@ namespace Firebird typedef const_pointer const_iterator; static const size_type npos; enum {INLINE_BUFFER_SIZE = 32, INIT_RESERVE = 16/*, KEEP_SIZE = 512*/}; + protected: typedef USHORT internal_size_type; // 16 bits! char_type inlineBuffer[INLINE_BUFFER_SIZE]; char_type* stringBuffer; internal_size_type stringLength, bufferSize; + private: inline void checkPos(size_type pos) const { if (pos >= length()) { fatal_exception::raise("Firebird::string - pos out of range"); } } + static inline void checkLength(size_type len) { if (len > max_length()) { fatal_exception::raise("Firebird::string - length exceeds predefined limit"); @@ -187,6 +190,7 @@ namespace Firebird enum TrimType {TrimLeft, TrimRight, TrimBoth}; void baseTrim(TrimType WhereTrim, const_pointer ToTrim); + public: inline const_pointer c_str() const { return stringBuffer; @@ -194,15 +198,26 @@ namespace Firebird inline size_type length() const { return stringLength; } + // Call it only when you have worked with at() or operator[] + // in case a null ASCII was inserted in the middle of the string. + inline size_type recalculate_length() + { + stringLength = strlen(stringBuffer); + return stringLength; + } + void reserve(size_type n = 0); void resize(size_type n, char_type c = ' '); - inline size_type copy(pointer s, size_type n, size_type pos = 0) const { + inline size_type copy_from(pointer s, size_type n, size_type pos = 0) const + { AdjustRange(length(), pos, n); memcpy(s, c_str() + pos, n); return n; } + size_type copy_to(pointer destination, size_type bufsize) const; + /* inline void swap(AbstractString& str) { Storage *tmp = StringData; StringData = str.StringData; @@ -253,9 +268,7 @@ namespace Firebird return find_first_not_of(s, pos, strlen(s)); } inline size_type find_first_not_of(char_type c, size_type pos = 0) const { - char s[2]; - s[0] = c; - s[1] = 0; + const char s[2] = {c, 0}; return find_first_not_of(s, pos, 1); } inline size_type find_last_not_of(const AbstractString& str, size_type pos = npos) const { @@ -266,9 +279,7 @@ namespace Firebird return find_last_not_of(s, pos, strlen(s)); } inline size_type find_last_not_of(char_type c, size_type pos = npos) const { - char s[2]; - s[0] = c; - s[1] = 0; + const char s[2] = {c, 0}; return find_last_not_of(s, pos, 1); } @@ -507,7 +518,7 @@ namespace Firebird return it; } inline iterator erase(iterator first, iterator last) { - erase(first - c_str(), last-first); + erase(first - c_str(), last - first); return first; }