| 44 | class MetaString; |
| 45 | |
| 46 | class AbstractString : private AutoStorage |
| 47 | { |
| 48 | public: |
| 49 | typedef char char_type; |
| 50 | typedef FB_SIZE_T size_type; |
| 51 | typedef FB_SSIZE_T difference_type; |
| 52 | typedef char* pointer; |
| 53 | typedef const char* const_pointer; |
| 54 | typedef char& reference; |
| 55 | typedef const char& const_reference; |
| 56 | typedef char value_type; |
| 57 | typedef pointer iterator; |
| 58 | typedef const_pointer const_iterator; |
| 59 | static const size_type npos; |
| 60 | enum {INLINE_BUFFER_SIZE = 32, INIT_RESERVE = 16/*, KEEP_SIZE = 512*/}; |
| 61 | |
| 62 | protected: |
| 63 | typedef ULONG internal_size_type; // 32 bits! |
| 64 | |
| 65 | private: |
| 66 | const internal_size_type max_length; |
| 67 | |
| 68 | protected: |
| 69 | char_type inlineBuffer[INLINE_BUFFER_SIZE]; |
| 70 | char_type* stringBuffer; |
| 71 | internal_size_type stringLength, bufferSize; |
| 72 | |
| 73 | private: |
| 74 | void checkPos(size_type pos) const |
| 75 | { |
| 76 | if (pos >= length()) { |
| 77 | fatal_exception::raise("Firebird::string - pos out of range"); |
| 78 | } |
| 79 | } |
| 80 | |
| 81 | void checkLength(size_type len) |
| 82 | { |
| 83 | if (len > getMaxLength()) { |
| 84 | fatal_exception::raise("Firebird::string - length exceeds predefined limit"); |
| 85 | } |
| 86 | } |
| 87 | |
| 88 | // Reserve buffer to allow storing at least newLen characters there |
| 89 | // (not including null terminator). Existing contents of our string are preserved. |
| 90 | void reserveBuffer(const size_type newLen) |
| 91 | { |
| 92 | size_type newSize = newLen + 1; |
| 93 | fb_assert(newSize != 0); // This large argument would be a programming error for sure. |
| 94 | if (newSize > bufferSize) |
| 95 | { |
| 96 | // Make sure we do not exceed string length limit |
| 97 | checkLength(newLen); |
| 98 | |
| 99 | // Order of assignments below is important in case of low memory conditions |
| 100 | |
| 101 | // Grow buffer exponentially to prevent memory fragmentation |
| 102 | if (newSize / 2 < bufferSize) |
| 103 | newSize = size_type(bufferSize) * 2u; |