diff options
1 files changed, 191 insertions, 0 deletions
| -rw-r--r-- | Year 1/Object-oriented Programming/Project 2/src/Generic/String/String.cpp | 191 |
diff --git a/Year 1/Object-oriented Programming/Project 2/src/Generic/String/String.cpp b/Year 1/Object-oriented Programming/Project 2/src/Generic/String/String.cpp new file mode 100644 index 0000000..57e5d58 --- /dev/null +++ b/Year 1/Object-oriented Programming/Project 2/src/Generic/String/String.cpp @@ -0,0 +1,191 @@ +#include "String.h" +#include <cstring> + +/* Private */ + +void String::free() { + delete[] str; +} + +void String::copyFrom(const String& other) { + str = new char[other.length + 1]; + strncpy(str, other.str, other.length + 1); + length = other.length; +} + +/* Public */ + +/*! + * Allocated with length + 1 size, so there is a terminating zero at the end. + */ +String::String(unsigned length) { + this->length = length; + str = new char[length + 1]; + str[length] = '\0'; +} + +/*! \params str C-style string + */ +String::String(const char* str) { + length = strlen(str); + this->str = new char[length + 1]; // capture terminating zero + strncpy(this->str, str, length + 1); +} + +const char* String::get_cstr() const { + return str; +} + +unsigned String::get_length() const { + return length; +} + +char& String::operator[](unsigned index) { + return str[index]; +} + +/*! \params str C-style string + */ +String& String::operator+=(const char* str) { + unsigned strLen = strlen(str); + char* newStr = new char[length + strLen + 1]; + strncpy(newStr, this->str, length + 1); + strncat(newStr, str, strLen + 1); + + delete[] this->str; + this->str = newStr; + length += strLen; + + return *this; +} + +/*! + * Converts the number to a C-style string and then uses += to append it. + */ +String& String::operator+=(int number) { + if (number < 0) { + *this += "-"; + number *= -1; + } + return *this += (unsigned)number; +} + +/*! + * Converts the number to a C-style string and then uses += to append it. + */ +String& String::operator+=(unsigned number) { + unsigned tempLen = 0; + for (unsigned tmp = number; tmp > 0 || tempLen == 0; tmp /= 10) + tempLen++; + + char* tmp = new char[tempLen + 1]; + tmp[tempLen] = '\0'; + for (unsigned i = tempLen - 1; i < tempLen; i--, number /= 10) + tmp[i] = number % 10 + '0'; + + *this += tmp; + delete[] tmp; + return *this; +} + +/*! + * Converts the number to a C-style string and then uses += to append it. + */ +String& String::operator+=(double number) { + if (number < 0) { + *this += "-"; + number *= -1; + } + number += 1.0 / (DOUBLE_PRECISION * 10); // bump up the number, in cases it becomes something like 8.59999999999... + return ((*this += (unsigned)number) += ".") + += (unsigned)((number - (unsigned)number) * DOUBLE_PRECISION); +} + +String::String() : String("") {} + +String::String(const String& other) { + copyFrom(other); +} + +String& String::operator=(const String& other) { + if (this != &other) { + free(); + copyFrom(other); + } + return *this; +} + +String::~String() { + free(); +} + +String::String(String&& other) { + str = other.str; + other.str = nullptr; + length = other.length; +} + +String& String::operator=(String&& other) { + if (this != &other) { + delete[] str; + str = other.str; + other.str = nullptr; + length = other.length; + } + return *this; +} + +/*! \param istr An input stream + * + * Directly reads bytes from stream (calls read() function). + * First reads the string length, then the underlying C-style string (including terminating zero). + * + * \remark Doesn't alter the stream in any other way. + * \note Best used with binary ifstream + */ +void String::read(std::istream& istr) { + istr.read((char*)&length, sizeof(length)); + istr.read(str, sizeof(char) * (length + 1)); +} + +/*! \param ostr An output stream + * + * Directly writes bytes to stream (calls write() function). + * First writes the string length, then the underlying C-style string (including terminating zero). + * + * \remark Doesn't alter the stream in any other way. + * \note Best used with binary ofstream + */ +void String::write(std::ostream& ostr) const { + ostr.write((char*)&length, sizeof(length)); + ostr.write(str, sizeof(char) * (length + 1)); +} + +/*! \params other C-style string + * \returns strcmp between underlying C-style string and "other" + */ +int String::compare(const String& other) const { + return strcmp(str, other.str); +} + +/*! + * Uses the stream's getline function to read the data. + * + * \warning It takes at most 1024 characters from the stream! + * \note Best used with std::cin or text std::ifstream + */ +std::istream& operator>>(std::istream& istr, String& str) { + istr.getline(str.str, 1024); + str.length = strlen(str.str); + + return istr; +} + +/*! + * Uses the stream's << operator to write the underlying C-style string + * + * \note Best used with std::cout or text std::ofstream + */ +std::ostream& operator<<(std::ostream& ostr, const String& str) { + return ostr << str.str; +} |
