#pragma once #include #include #include #include #include #include template struct View { size_t size; T* data; // owns its memory public: View() : size(0), data(nullptr) {} // Deep copy constructor View(const T* src, size_t count) : size(count) { if (count == 0) { data = nullptr; return; } data = static_cast(::operator new[](count * sizeof(T))); for (size_t i = 0; i < count; ++i) new (&data[i]) T(src[i]); // copy-construct } // Copy constructor View(const View& other) : View(other.data, other.size) {} // Move constructor View(View&& other) noexcept : size(other.size), data(other.data) { other.size = 0; other.data = nullptr; } View &operator=(const View &other) { if (this != &other) { // free old memory for (size_t i = 0; i < size; ++i) data[i].~T(); ::operator delete[](data); // deep copy size = other.size; data = static_cast(::operator new[](size * sizeof(T))); for (size_t i = 0; i < size; ++i) new (&data[i]) T(other.data[i]); } return *this; } // Destructor ~View() { for (size_t i = 0; i < size; ++i) data[i].~T(); ::operator delete[](data); } const T* begin() const { return data; } const T* end() const { return data + size; } }; // using StringView = View; class StringView final : public View { public: StringView() : View() {} // Construct from C-string — deep copy, including null terminator StringView(const char* s) : View(s, strlen(s) + 1) {} // Construct from View — ensure null termination StringView(const View& v) : View(v) { if (size == 0 || data[size - 1] != '\0') { // Reallocate and append null terminator size_t newSize = size + 1; char* newData = static_cast(::operator new[](newSize * sizeof(char))); for (size_t i = 0; i < size; ++i) newData[i] = data[i]; newData[newSize - 1] = '\0'; // destroy old // for (size_t i = 0; i < size; ++i) // data[i].~char(); ::operator delete[](data); data = newData; size = newSize; } } const char* c_str() const { return data; } }; template struct Builder { size_t size = 0; size_t capacity = 8; T* data; public: Builder() { data = static_cast(::operator new[](capacity * sizeof(T))); } ~Builder() { clear(); ::operator delete[](data); } protected: void grow(size_t newSize) { if (newSize <= capacity) return; size_t newCap = capacity; while (newCap < newSize) newCap += newCap / 2; T* newData = static_cast(::operator new[](newCap * sizeof(T))); // Move-construct into the new buffer for (size_t i = 0; i < size; ++i) new (&newData[i]) T(std::move(data[i])); // Destroy old items for (size_t i = 0; i < size; ++i) data[i].~T(); ::operator delete[](data); data = newData; capacity = newCap; } public: void Push(const T& value) { grow(size + 1); new (&data[size]) T(value); size++; } void Push(T&& value) { grow(size + 1); new (&data[size]) T(std::move(value)); size++; } // Clear Builder storage but keep capacity void clear() { for (size_t i = 0; i < size; ++i) data[i].~T(); size = 0; } // ALWAYS produce a deep-copied View View view() const { return View(data, size); } }; // using StringBuilder = Builder; class StringBuilder final : public Builder { public: StringBuilder() : Builder() {} // Ensure there is room for `n` more characters (not counting terminator) void ensure_extra(size_t n) { // grow size + n (but not including terminator) this->grow(this->size + n); } // Append raw C string (WITHOUT copying terminator) void Extend(const char* str) { if (!str) return; size_t len = strlen(str); ensure_extra(len); for (size_t i = 0; i < len; ++i) this->Push(str[i]); } // Append a single char void Append(char c) { this->Push(c); } void AppendIndent(int indent) { grow(size + indent); memset(data + size, ' ', indent); size += indent; } // Return a null-terminated string pointer owned by builder const char* c_str() { // ensure space for terminator this->grow(this->size + 1); // add terminator (overwrite or place it at end) if (this->size == 0 || this->data[this->size - 1] != '\0') { // If already ended with \0, fine this->Push('\0'); } return this->data; } // Produce a deep-copied StringView StringView view() { return StringView(this->c_str()); } // streaming operators StringBuilder& operator<<(const char* s) { Extend(s); return *this; } StringBuilder& operator<<(const StringView& sv) { Extend(sv.c_str()); return *this; } StringBuilder& operator<<(char c) { Append(c); return *this; } StringBuilder& operator<<(int v) { char buf[32]; snprintf(buf, sizeof(buf), "%d", v); Extend(buf); return *this; } StringBuilder& operator<<(long v) { char buf[32]; snprintf(buf, sizeof(buf), "%ld", v); Extend(buf); return *this; } };