From 06d11d2c0db91b8b64d5e197be8fc4a4ab44c78c Mon Sep 17 00:00:00 2001 From: karl Date: Tue, 16 Mar 2021 15:05:39 +0100 Subject: [PATCH] Add custom String class from ACIC --- cpp/String.cpp | 119 +++++++++++++++++++++++++++++++++++++++++++++++ include/String.h | 53 +++++++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 cpp/String.cpp create mode 100644 include/String.h diff --git a/cpp/String.cpp b/cpp/String.cpp new file mode 100644 index 0000000..cab4507 --- /dev/null +++ b/cpp/String.cpp @@ -0,0 +1,119 @@ +#include "String.h" + +String::String() : String("") { +} + +String::String(const char *stringText) + : length(strlen(stringText)), text(new char[length + sizeof(char)]) { + memcpy(text, stringText, length + sizeof(char)); +} + +String::String(const String &other) + : length(other.getLength()), text(new char[length + sizeof(char)]) { + memcpy(text, other.c_str(), length + sizeof(char)); +} + +String &String::operator=(const String &other) { + // TODO: We could also check whether the other string has the same capacity + // as this one, and if so, reuse the + // current char array. However, this would introduce another check which + // might cost more performance than it gains (since the length will rarely + // be the same) + if (this != &other) { + length = other.length; + + // Delete old text and create new + delete[] text; + + text = new char[length + sizeof(char)]; + + // Copy text + memcpy(text, other.c_str(), length + sizeof(char)); + } + + return *this; +} + +String::String(String &&other) : length(other.length), text(other.text) { + other.text = nullptr; + other.length = 0; +} + +String &String::operator=(String &&other) { + if (this != &other) { + delete[] text; + + text = other.text; + length = other.length; + + other.text = nullptr; + other.length = 0; + } + + return *this; +} + +String &String::operator+=(const String &other) { + concatenate(other); + return *this; +} + +String &String::operator+=(const char *other) { + concatenate(other); + return *this; +} + +String operator+(String left, const String &right) { + left += right; + return left; +} + +String operator+(String left, const char *right) { + left += right; + return left; +} + +// TODO: Should cases like `"Hello" + String("World")` be handled? +// I think not; it would be up to `const char *` to handle that, since getting +// a String after adding something to a `const char *` is strange. It could +// look like this however: +// String operator+(const char *left, const String &right) { +// String left_string = String(left); +// left_string += right; +// return left_string; +//} + +String::operator const char *() const { + return this->c_str(); +} + +String::~String() { + delete[] text; +} + +void String::concatenate(const String &other) { + concatenate(other.c_str()); +} + +void String::concatenate(const char *other) { + // Allocate the new text + size_t newStringLength = strlen(other); + char *newString = new char[length + newStringLength + sizeof(char)]; + + // Copy current string, and other string after it + memcpy(newString, text, length); + memcpy(newString + length, other, newStringLength + sizeof(char)); + + delete[] text; + + text = newString; + length += newStringLength; +} + +const char *String::c_str() const { + return text; +} + +size_t String::getLength() const { + return length; +} \ No newline at end of file diff --git a/include/String.h b/include/String.h new file mode 100644 index 0000000..ecee96e --- /dev/null +++ b/include/String.h @@ -0,0 +1,53 @@ +#include + +class String { + public: + /// Create a new empty String + String(); + + /// Create a new String out of a char array. + /// The given character array must be \0-terminated. + explicit String(const char *stringText); + + /// Copy constructor + String(const String &other); + + /// Copy assignment operator + String &operator=(const String &other); + + /// Move constructor + String(String &&other); + + /// Move assignment operator + String &operator=(String &&other); + + /// += operators for concatenate + /// Used in the + operator as well (defined outside the class) + String &operator+=(const String &other); + String &operator+=(const char *other); + + /// Conversion to char pointer + operator const char *() const; + + ~String(); + + /// Append a String at the end of this String. + void concatenate(const String &other); + + /// Append characters at the end of this String. + /// The given character array must be \0-terminated. + void concatenate(const char *other); + + /// Return the internal char array representation of this String. + /// Note that calling concatenate() on the String invalidates this returned + /// pointer. + const char *c_str() const; + + /// Return the length of the String (without the terminator). + size_t getLength() const; + + private: + size_t length; + + char *text; +}; \ No newline at end of file