#include "String.h" #include "Debug.h" #include #include namespace ecci { String::String(const char* s) { ECCI_DEBUG("Default and conversion constructor: [" << s << ']'); len = strlen(s); str = new char[len + 1]; strcpy(str, s); } String::String(size_t capacity) { ECCI_DEBUG("Capacity constructor: " << capacity); str = new char[capacity + 1]; *str = '\0'; // same as str[0] = '\0'; } void ecci_strcpy(char* t, char* s) { while ( ( *t++ = *s++ ) ) ; } String::String(const String& other) : str( new char[other.len + 1] ) , len( other.len ) { //strcpy(this->str, other.str); //for ( size_t i = 0; i <= other.len; ++i ) // this->str[i] = other.str[i]; ECCI_DEBUG("Copy constructor: [" << other.str << ']'); ecci_strcpy(this->str, other.str); } String::String(String&& temp) : str(temp.str) , len(temp.len) { ECCI_DEBUG("Move constructor: [" << temp.str << ']'); temp.str = nullptr; temp.len = 0; } const String& String::operator=(const String& other) { ECCI_DEBUG("Copy assignment operator [" << (str ? str : "") << "] := [" << other.str << ']'); if ( this != &other ) { delete [] this->str; this->str = new char[other.len + 1]; strcpy(this->str, other.str); this->len = other.len; } return *this; } const String& String::operator=(String &&temp) { ECCI_DEBUG("Move operator [" << (str ? str : "") << "] := [" << temp.str << ']'); if ( this != &temp ) { delete [] this->str; this->str = temp.str; this->len = temp.len; temp.str = nullptr; temp.len = 0; } return *this; } const String& String::operator=(const char* cstr) { ECCI_DEBUG("C-string assignment operator [" << (str ? str : "") << "] := [" << cstr << ']'); size_t newLen = strlen(cstr); if ( len != newLen ) { delete [] str; str = new char[newLen + 1]; len = newLen; } strcpy(str, cstr); return *this; } String::~String() { ECCI_DEBUG("Destructor: [" << (str ? str : "") << ']'); delete [] str; } String String::substr(size_t pos, size_t length) const { // If not a valid position was given, return an empty string if ( pos >= len ) return String(); // If not a valid length was given, assume the rest of the string if ( length > len - pos ) length = len - pos + 1; String result(length); strncpy(result.str, this->str + pos, length); result.str[length] = '\0'; result.len = length; return result; } String String::operator+(char ch) const { ECCI_DEBUG("Operator+: [" << (str ? str : "") << "] + '" << ch << '\''); size_t newlen = this->len + 1; String result( newlen ); strcpy( result.str, this->str ); result.str[this->len] = ch; result.str[newlen] = '\0'; result.len = newlen; return result; } String operator+(char ch, const String& text) { ECCI_DEBUG("Operator+: '" << ch << "' + [" << text.str << ']'); size_t newlen = 1 + text.len; String result( newlen ); *result.str = ch; strcpy( result.str + 1, text.str ); result.len = newlen; return result; } String String::operator+(long long num) const { ECCI_DEBUG("Operator+: [" << (str ? str : "") << "] + [" << num << ']'); char buffer[strlen("-18446744073709551615") + 1]; // strlen(2^64) sprintf(buffer, "%lli", num); return *this + buffer; } String operator+(long long num, const String& text) { ECCI_DEBUG("Operator+: [" << num << "] + [" << text.str << ']'); char buffer[strlen("-18446744073709551615") + 1]; // strlen(2^64) sprintf(buffer, "%lli", num); return buffer + text; } String String::operator+(unsigned long long num) const { ECCI_DEBUG("Operator+: [" << (str ? str : "") << "] + [" << num << ']'); char buffer[strlen("18446744073709551615") + 1]; // strlen(2^64) sprintf(buffer, "%llu", num); return *this + buffer; } String operator+(unsigned long long num, const String& text) { ECCI_DEBUG("Operator+: [" << num << "] + [" << text.str << ']'); char buffer[strlen("18446744073709551615") + 1]; // strlen(2^64) sprintf(buffer, "%llu", num); return buffer + text; } String String::operator+(double num) const { ECCI_DEBUG("Operator+: [" << (str ? str : "") << "] + [" << num << ']'); char buffer[32]; sprintf(buffer, "%lf", num); return *this + buffer; } String operator+(double num, const String& text) { ECCI_DEBUG("Operator+: [" << num << "] + [" << text.str << ']'); char buffer[32]; sprintf(buffer, "%lf", num); return buffer + text; } String operator+(const String& text, const char* cstr) { size_t newlen = text.len + strlen(cstr); String result( newlen ); strcpy( result.str, text.str ); strcpy( result.str + text.len, cstr ); result.len = newlen; return result; } String operator+(const char* cstr, const String& text) { size_t lenBuffer = strlen(cstr); size_t newlen = lenBuffer + text.len; String result( newlen ); strcpy( result.str, cstr ); strcpy( result.str + lenBuffer, text.str ); result.len = newlen; return result; } String String::operator+(const String& other) const { String result( this->len + other.len ); strcpy( result.str, this->str ); strcpy( result.str + this->len, other.str ); result.len = this->len + other.len; return result; } bool operator==(char ch, const String& str2) { return str2.len == 1 && ch == *str2.str; } bool operator==(const String& str1, char ch) { return str1.len == 1 && *str1.str == ch; } bool operator==(const char* str1, const String& str2) { return strcmp(str1, str2.str) == 0; } bool operator==(const String& str1, const char* str2) { return strcmp(str1.str, str2) == 0; } bool operator==(const String& str1, const String& str2) { return str1.len == str2.len && strcmp(str1.str, str2.str) == 0; } size_t String::find(char ch, size_t start) const { if ( start >= len ) return npos; const char* found = strchr(str + start, ch); return found ? found - str : npos; } size_t String::findNoCase(char ch, size_t start) const { ch = tolower(ch); for (size_t i = start; i < len; ++i) if ( tolower(str[i]) == ch ) return i; return npos; } size_t String::find(const char* what, size_t start) const { if ( start >= len ) return npos; const char* found = strstr(str + start, what); return found ? found - str : npos; } size_t String::findNoCase(const char* what, size_t start) const { if ( start >= len ) return npos; if ( *what == '\0' ) return npos; for(const char* tmpPtr = str; start <= len; ++start ) { size_t tmpStart = start; for (const char* tmpWhat = what; ; tmpWhat++ ) { if ( *tmpWhat == '\0' ) return start; if ( tolower(tmpPtr[tmpStart]) != tolower(*tmpWhat) ) break; tmpStart++; } } return -1; } } // namespace ecci