#ifndef CORE_ARRAY_STRING_HPP #define CORE_ARRAY_STRING_HPP #include #include "core/utils/Error.hpp" #include "core/utils/Meta.hpp" #include "core/utils/Types.hpp" #include "core/utils/Utility.hpp" namespace Core { class BufferString { protected: size_t length; size_t capacity; char* data; public: BufferString(char* buffer, size_t bufferSize); BufferString(const BufferString&) = delete; BufferString& operator=(const BufferString&); BufferString(BufferString&&) = delete; BufferString& operator=(BufferString&&) = delete; bool operator==(const char* s) const; bool operator==(const BufferString& other) const; bool operator!=(const char* s) const; bool operator!=(const BufferString& other) const; char operator[](size_t index) const; size_t getLength() const; size_t getCapacity() const; BufferString& append(char c); BufferString& append(signed char c); BufferString& append(unsigned char c); BufferString& append(wchar_t c); BufferString& append(c32 c); BufferString& append(const char* s); BufferString& append(const c32* s); BufferString& append(const signed char* s); BufferString& append(const unsigned char* s); BufferString& append(bool b); template BufferString& append(const T& t) { if constexpr(requires { t.toString(*this); }) { (void)t.toString(*this); } else if constexpr(requires { static_cast(t); }) { append(static_cast(t)); } else { char buffer[64]; Core::toString(t, buffer, sizeof(buffer)); append(static_cast(buffer)); } return *this; } void toString(BufferString& s) const; void clear(); void print() const; void printLine() const; template BufferString& format(BufferString& s, Args&&... args) { if constexpr(sizeof...(args) > 0) { formatR(s, 0, forward(args)...); *this = s; } return *this; } bool startsWith(const BufferString& other, size_t from = 0) const; size_t search(const BufferString& other, size_t from = 0) const; bool contains(const BufferString& other, size_t from = 0) const; size_t search(char u, size_t from = 0) const; bool contains(char u, size_t from = 0) const; void substring(BufferString& s, size_t from, size_t to) const; void substring(BufferString& s, size_t from = 0) const; void replace(BufferString& s, const BufferString& search, const BufferString& replace); void replace(char search, char replace); operator const char*() const; private: template void formatR(BufferString& s, size_t index, const T& t, Args&&... args) const { size_t l = getLength(); while(index < l) { char u = data[index++]; if(u == '#') { if(index >= l || data[index] != '#') { break; } index++; } s.append(u); } s.append(t); if constexpr(sizeof...(args) > 0) { formatR(s, index, forward(args)...); return; } while(index < l) { s.append(data[index++]); } } }; template class ArrayString final : public BufferString { char data[N]; public: ArrayString() : BufferString(data, N) { } ArrayString(const ArrayString& other) : BufferString(data, N) { memcpy(data, other.data, sizeof(data)); length = other.length; } ArrayString& operator=(const ArrayString& other) { if(this != &other) { memcpy(data, other.data, sizeof(data)); length = other.length; } return *this; } template ArrayString& format(Args&&... args) { ArrayString s; BufferString::format(s, Core::forward(args)...); return *this; } void replace(const BufferString& search, const BufferString& replace) { ArrayString s; BufferString::replace(s, search, replace); } using BufferString::replace; }; template void toString(String& s, const Iterable& i) { s.append("["); auto current = i.begin(); auto end = i.end(); while(current != end) { s.append(*current); ++current; if(current != end) { s.append(", "); } } s.append("]"); } } inline bool operator==(const char* cs, const Core::BufferString& s) { return s == cs; } inline bool operator!=(const char* cs, const Core::BufferString& s) { return s != cs; } #endif