From cb6dee9d91641b26326480e6ea14630a6d4c997f Mon Sep 17 00:00:00 2001 From: Bananymous Date: Tue, 13 Dec 2022 20:41:32 +0200 Subject: [PATCH] BAN: Implement more basic functionality String has more features StringView was implemented Basic move semantics are now working Added file for forward declarations --- BAN/BAN/String.cpp | 87 +++++++++++++++++++++++++++++---- BAN/BAN/StringView.cpp | 93 ++++++++++++++++++++++++++++++++++++ BAN/Makefile | 1 + BAN/include/BAN/Forward.h | 14 ++++++ BAN/include/BAN/Move.h | 19 ++++++++ BAN/include/BAN/String.h | 32 ++++++++++++- BAN/include/BAN/StringView.h | 50 +++++++++++++++++++ 7 files changed, 284 insertions(+), 12 deletions(-) create mode 100644 BAN/BAN/StringView.cpp create mode 100644 BAN/include/BAN/Forward.h create mode 100644 BAN/include/BAN/Move.h create mode 100644 BAN/include/BAN/StringView.h diff --git a/BAN/BAN/String.cpp b/BAN/BAN/String.cpp index 5837f65f..c79360ed 100644 --- a/BAN/BAN/String.cpp +++ b/BAN/BAN/String.cpp @@ -1,5 +1,10 @@ +#include #include +#include #include +#include + +#include #include #include @@ -10,18 +15,29 @@ namespace BAN String::String() { - MUST(EnsureCapasity(1)); - m_data[0] = '\0'; - m_size = 0; + MUST(copy_impl("", 0)); } - String::String(const char* string) + String::String(const String& other) { - size_type len = strlen(string); - MUST(EnsureCapasity(len + 1)); - memcpy(m_data, string, len); - m_data[len] = '\0'; - m_size = len; + MUST(copy_impl(other.Data(), other.Size())); + } + + String::String(String&& other) + { + move_impl(Move(other)); + } + + String::String(const StringView& other) + { + MUST(copy_impl(other.Data(), other.Size())); + } + + String::String(const char* data, size_type len) + { + if (len == size_type(-1)) + len = strlen(data); + MUST(copy_impl(data, len)); } String::~String() @@ -29,6 +45,19 @@ namespace BAN BAN::deallocator(m_data); } + String& String::operator=(const String& other) + { + copy_impl(other.Data(), other.Size()); + return *this; + } + + String& String::operator=(String&& other) + { + BAN::deallocator(m_data); + move_impl(Move(other)); + return *this; + } + ErrorOr String::PushBack(char ch) { TRY(EnsureCapasity(m_size + 2)); @@ -80,6 +109,12 @@ namespace BAN m_size--; } + void String::Clear() + { + m_data[0] = '\0'; + m_size = 0; + } + char String::operator[](size_type index) const { assert(index < m_size); @@ -92,6 +127,13 @@ namespace BAN return m_data[index]; } + bool String::operator==(const String& other) const + { + if (m_size != other.m_size) + return false; + return memcmp(m_data, other.m_data, m_size) == 0; + } + ErrorOr String::Resize(size_type size, char ch) { if (size < m_size) @@ -113,10 +155,15 @@ namespace BAN ErrorOr String::Reserve(size_type size) { - TRY(EnsureCapasity(size + 1)); + TRY(EnsureCapasity(size)); return {}; } + StringView String::SV() const + { + return StringView(*this); + } + bool String::Empty() const { return m_size == 0; @@ -152,4 +199,24 @@ namespace BAN return {}; } + ErrorOr String::copy_impl(const char* data, size_type len) + { + TRY(EnsureCapasity(len + 1)); + memcpy(m_data, data, len); + m_data[len] = '\0'; + m_size = len; + return {}; + } + + void String::move_impl(String&& other) + { + m_data = other.m_data; + m_size = other.m_size; + m_capasity = other.m_capasity; + + other.m_data = nullptr; + other.m_size = 0; + other.m_capasity = 0; + } + } diff --git a/BAN/BAN/StringView.cpp b/BAN/BAN/StringView.cpp new file mode 100644 index 00000000..97295ab9 --- /dev/null +++ b/BAN/BAN/StringView.cpp @@ -0,0 +1,93 @@ +#include +#include +#include + +#include +#include + +namespace BAN +{ + + StringView::StringView() + { } + + StringView::StringView(const String& other) + : StringView(other.Data(), other.Size()) + { } + + StringView::StringView(const char* string, size_type len) + { + if (len == size_type(-1)) + len = strlen(string); + m_data = string; + m_size = len; + } + + char StringView::operator[](size_type index) const + { + assert(index < m_size); + return m_data[index]; + } + + bool StringView::operator==(const StringView& other) const + { + if (m_size != other.m_size) + return false; + return memcmp(m_data, other.m_data, m_size) == 0; + } + + StringView StringView::Substring(size_type index, size_type len) const + { + assert(index <= m_size); + if (len == size_type(-1)) + len = m_size - index; + assert(len <= m_size - index); // weird order to avoid overflow + StringView result; + result.m_data = m_data + index; + result.m_size = len; + return result; + } + + Vector StringView::Split(char delim, bool allow_empties) + { + Vector result; + size_type start = 0; + for (size_type i = 0; i < m_size; i++) + { + if (m_data[i] == delim) + { + if (allow_empties || start != i) + result.PushBack(this->Substring(start, i - start)); + start = i + 1; + } + } + if (start != m_size) + result.PushBack(this->Substring(start)); + return result; + } + + StringView::size_type StringView::Count(char ch) const + { + size_type result = 0; + for (size_type i = 0; i < m_size; i++) + if (m_data[i] == ch) + result++; + return result; + } + + bool StringView::Empty() const + { + return m_size == 0; + } + + StringView::size_type StringView::Size() const + { + return m_size; + } + + const char* StringView::Data() const + { + return m_data; + } + +} \ No newline at end of file diff --git a/BAN/Makefile b/BAN/Makefile index e8f223fa..1bf066ee 100644 --- a/BAN/Makefile +++ b/BAN/Makefile @@ -32,6 +32,7 @@ BUILDDIR=$(abspath build) FREEOBJS= \ $(ARCH_FREEOBJS) \ BAN/String.o \ +BAN/StringView.o \ HOSTEDOBJS=\ $(ARCH_HOSTEDOBJS) \ diff --git a/BAN/include/BAN/Forward.h b/BAN/include/BAN/Forward.h new file mode 100644 index 00000000..f11c948e --- /dev/null +++ b/BAN/include/BAN/Forward.h @@ -0,0 +1,14 @@ +#pragma once + +template class ErrorOr; + +namespace BAN +{ + + class String; + class StringView; + + template class Vector; + template class Queue; + +} diff --git a/BAN/include/BAN/Move.h b/BAN/include/BAN/Move.h new file mode 100644 index 00000000..056d26b3 --- /dev/null +++ b/BAN/include/BAN/Move.h @@ -0,0 +1,19 @@ +#pragma once + +namespace BAN +{ + + template + struct RemoveReference { typedef T type; }; + + template + struct RemoveReference { typedef T type; }; + + template + struct RemoveReference { typedef T type; }; + + template + typename RemoveReference::type&& + Move( T&& Arg ) { return (typename RemoveReference::type&&)Arg; } + +} \ No newline at end of file diff --git a/BAN/include/BAN/String.h b/BAN/include/BAN/String.h index dbf87763..c37fe22b 100644 --- a/BAN/include/BAN/String.h +++ b/BAN/include/BAN/String.h @@ -1,6 +1,8 @@ #pragma once #include +#include +#include namespace BAN { @@ -12,9 +14,15 @@ namespace BAN public: String(); - String(const char*); + String(const String&); + String(String&&); + String(const StringView&); + String(const char*, size_type = -1); ~String(); + String& operator=(const String&); + String& operator=(String&&); + ErrorOr PushBack(char); ErrorOr Insert(char, size_type); ErrorOr Append(const char*); @@ -23,12 +31,18 @@ namespace BAN void PopBack(); void Remove(size_type); + void Clear(); + char operator[](size_type) const; char& operator[](size_type); + bool operator==(const String&) const; + ErrorOr Resize(size_type, char = '\0'); ErrorOr Reserve(size_type); + StringView SV() const; + bool Empty() const; size_type Size() const; size_type Capasity() const; @@ -38,10 +52,24 @@ namespace BAN private: ErrorOr EnsureCapasity(size_type); + ErrorOr copy_impl(const char*, size_type); + void move_impl(String&&); + private: char* m_data = nullptr; size_type m_capasity = 0; size_type m_size = 0; }; -} \ No newline at end of file +} + +namespace BAN::Formatter +{ + + template void print_argument_impl(const String& string, const ValueFormat&) + { + for (String::size_type i = 0; i < string.Size(); i++) + PUTC_LIKE(string[i]); + } + +} diff --git a/BAN/include/BAN/StringView.h b/BAN/include/BAN/StringView.h new file mode 100644 index 00000000..2c92c339 --- /dev/null +++ b/BAN/include/BAN/StringView.h @@ -0,0 +1,50 @@ +#pragma once + +#include +#include + +namespace BAN +{ + + class StringView + { + public: + using size_type = size_t; + + public: + StringView(); + StringView(const String&); + StringView(const char*, size_type = -1); + + char operator[](size_type) const; + + bool operator==(const StringView&) const; + + StringView Substring(size_type, size_type = -1) const; + + Vector Split(char, bool = false); + + size_type Count(char) const; + + bool Empty() const; + size_type Size() const; + + const char* Data() const; + + private: + const char* m_data = nullptr; + size_type m_size = 0; + }; + +} + +namespace BAN::Formatter +{ + + template void print_argument_impl(const StringView& sv, const ValueFormat&) + { + for (StringView::size_type i = 0; i < sv.Size(); i++) + PUTC_LIKE(sv[i]); + } + +}