#ifndef STRINGBUFFER_H #define STRINGBUFFER_H #include #include #include "utils/Types.h" template class StringBuffer final { int length; Hash hash; char data[N]; void addToHash(char c) { hash = 2120251889 * hash + c; } void addToHash(int from, int to) { for(int i = from; i < to; i++) { addToHash(data[i]); } } public: StringBuffer() : length(0), hash(0) { data[0] = '\0'; } template StringBuffer(const T& t) : StringBuffer() { append(t); } bool operator==(const char* str) const { return strcmp(data, str) == 0; } bool operator==(const StringBuffer& other) const { return length == other.length && other == data; } bool operator!=(const char* str) const { return !((*this) == str); } bool operator!=(const StringBuffer& other) const { return !((*this) == other); } operator const char*() const { return data; } char operator[](int index) const { return data[index]; } int getLength() const { return length; } StringBuffer& append(char c) { if(length < N - 1) { data[length++] = c; addToHash(c); data[length] = '\0'; } return *this; } StringBuffer& append(signed char c) { return append(static_cast(c)); } StringBuffer& append(const char* str) { return appendString(str); } StringBuffer& append(const signed char* str) { return appendString(str); } StringBuffer& append(const unsigned char* str) { return appendString(str); } template StringBuffer& append(const char* format, const T& t) { int left = N - length; int written = snprintf(data + length, left, format, t); int oldLength = length; if(written < left) { length += written; } else { length = N - 1; } addToHash(oldLength, length); return *this; } StringBuffer& append(int i) { return append("%d", i); } StringBuffer& append(unsigned int i) { return append("%u", i); } StringBuffer& append(float i) { return append("%.2f", i); } StringBuffer& append(bool b) { return b ? append("true") : append("false"); } template StringBuffer& append(const T& t) { t.toString(*this); return *this; } StringBuffer& appendUnicode(unsigned int c) { if(c < (1 << 7)) { append(static_cast(c & 0x7F)); } else if(c < (1 << 11)) { append(static_cast(((c >> 6) & 0x1F) | 0xC0)); append(static_cast(((c >> 0) & 0x3F) | 0x80)); } else if(c < (1 << 16)) { append(static_cast(((c >> 12) & 0x0F) | 0xE0)); append(static_cast(((c >> 6) & 0x3F) | 0x80)); append(static_cast(((c >> 0) & 0x3F) | 0x80)); } else if(c < (1 << 21)) { append(static_cast(((c >> 18) & 0x07) | 0xF0)); append(static_cast(((c >> 12) & 0x3F) | 0x80)); append(static_cast(((c >> 6) & 0x3F) | 0x80)); append(static_cast(((c >> 0) & 0x3F) | 0x80)); } return *this; } StringBuffer& clear() { length = 0; hash = 0; data[0] = '\0'; return *this; } Hash hashCode() const { return hash; } void print() const { std::cout << data; } void printLine() const { std::cout << data << '\n'; } private: template StringBuffer& appendString(T str) { for(int i = 0; length < N - 1 && str[i] != '\0'; length++, i++) { data[length] = str[i]; addToHash(str[i]); } data[length] = '\0'; return *this; } }; template bool operator==(const char* str, const StringBuffer buffer) { return buffer == str; } template bool operator!=(const char* str, const StringBuffer buffer) { return buffer != str; } #endif