From 00f230fcb2f0f574a293d7ffa715192f00f803bf Mon Sep 17 00:00:00 2001 From: Bananymous Date: Tue, 13 Dec 2022 14:33:38 +0200 Subject: [PATCH] BAN: Add basic String implementation --- BAN/include/BAN/String.h | 184 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 BAN/include/BAN/String.h diff --git a/BAN/include/BAN/String.h b/BAN/include/BAN/String.h new file mode 100644 index 000000000..2d0da4c9e --- /dev/null +++ b/BAN/include/BAN/String.h @@ -0,0 +1,184 @@ +#pragma + +#include +#include +#include + +#include +#include +#include + +namespace BAN +{ + + class String + { + public: + using size_type = size_t; + + public: + String() = default; + String(const char*); + ~String(); + + ErrorOr PushBack(char); + ErrorOr Insert(char, size_type); + ErrorOr Append(const char*); + ErrorOr Append(const String&); + + void PopBack(); + void Remove(size_type); + + char operator[](size_type) const; + char& operator[](size_type); + + ErrorOr Resize(size_type, char = '\0'); + ErrorOr Reserve(size_type); + + size_type Size() const; + size_type Capasity() const; + + const char* Data() const; + + private: + ErrorOr EnsureCapasity(size_type); + + private: + char* m_data = nullptr; + size_type m_capasity = 0; + size_type m_size = 0; + }; + + String::String(const char* string) + { + size_type len = strlen(string); + MUST(EnsureCapasity(len + 1)); + memcpy(m_data, string, len); + m_data[len] = '\0'; + m_size = len; + } + + String::~String() + { + BAN::deallocator(m_data); + } + + ErrorOr String::PushBack(char ch) + { + TRY(EnsureCapasity(m_size + 2)); + m_data[m_size] = ch; + m_data[m_size + 1] = '\0'; + m_size++; + return {}; + } + + ErrorOr String::Insert(char ch, size_type index) + { + assert(index <= m_size); + TRY(EnsureCapasity(m_size + 2)); + memmove(m_data + index + 1, m_data + index, m_size - index); + m_data[index] = ch; + m_data[m_size + 1] = '\0'; + m_size++; + return {}; + } + + ErrorOr String::Append(const char* string) + { + size_t len = strlen(string); + TRY(EnsureCapasity(m_size + len + 1)); + memcpy(m_data + m_size, string, len); + m_data[m_size + len] = '\0'; + m_size += len; + return {}; + } + + ErrorOr String::Append(const String& string) + { + TRY(Append(string.Data())); + return {}; + } + + void String::PopBack() + { + assert(m_size > 0); + m_data[m_size - 1] = '\0'; + m_size--; + } + + void String::Remove(size_type index) + { + assert(index < m_size); + memmove(m_data + index, m_data + index + 1, m_size - index - 1); + m_data[m_size - 1] = '\0'; + m_size--; + } + + char String::operator[](size_type index) const + { + assert(index < m_size); + return m_data[index]; + } + + char& String::operator[](size_type index) + { + assert(index < m_size); + return m_data[index]; + } + + ErrorOr String::Resize(size_type size, char ch) + { + if (size < m_size) + { + m_data[size] = '\0'; + m_size = size; + } + else if (size > m_size) + { + TRY(EnsureCapasity(size + 1)); + for (size_type i = m_size; i < size; i++) + m_data[i] = ch; + m_data[size] = '\0'; + m_size = size; + } + m_size = size; + return {}; + } + + ErrorOr String::Reserve(size_type size) + { + TRY(EnsureCapasity(size + 1)); + return {}; + } + + String::size_type String::Size() const + { + return m_size; + } + + String::size_type String::Capasity() const + { + return m_capasity; + } + + const char* String::Data() const + { + return m_data; + } + + ErrorOr String::EnsureCapasity(size_type size) + { + if (m_capasity >= size) + return {}; + size_type new_cap = MAX(size, m_capasity * 1.5f); + void* new_data = BAN::allocator(new_cap); + if (new_data == nullptr) + return Error::FromString("String: Could not allocate memory"); + memcpy(new_data, m_data, m_size + 1); + BAN::deallocator(m_data); + m_data = (char*)new_data; + m_capasity = new_cap; + return {}; + } + +} \ No newline at end of file