I'm creating my own general purpose library for personal use in C++ and it needs a string class that fits in with the rest of the library. Currently, it only has a few basic features, but because strings are a pretty important thing, I want my class to be very optimized. I don't want to be writing a bunch of methods for a string model that doesn't work very well, so please leave some feedback so I can change things before it's too late.
common.h:
#ifndef _COMMON
#define _COMMON
namespace chaos {
typedef long long llong;
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long long ulong;
typedef signed char schar;
typedef signed short sshort;
typedef signed int sint;
typedef signed long long slong;
}
#endif
string.h:
#ifndef _STRING
#define _STRING
#include "common.h"
namespace chaos {
class String {
private:
char* str;
ushort len;
public:
String();
String(ushort);
String(const char*);
String(const String&);
String(const String&, ushort, ushort);
~String();
bool operator==(const String&);
bool operator!=(const String&);
String& operator=(const String&);
String& operator+=(const String&);
String operator+(const String&);
char* getStr() const;
ushort getLen() const;
void set(ushort, char);
char get(ushort) const;
template<class T> static String From(T value, ushort base);
template<class T> T to() const;
};
}
#endif
string.cpp:
#include "string.h"
namespace chaos {
String::String() {
this->len = 0;
this->str = new char[this->len + 1];
}
String::String(ushort length) {
this->len = length;
this->str = new char[this->len + 1];
for (ushort i = 0; i < this->len; i++)
this->str[i] = '.';
this->str[this->len] = '\0';
}
String::String(const char* str) {
for (this->len = 0; str[this->len] != '\0'; this->len++);
this->str = new char[this->len + 1];
for (ushort i = 0; i <= this->len; i++)
this->str[i] = str[i];
}
String::String(const String& string) {
this->len = string.len;
this->str = new char[this->len + 1];
for (ushort i = 0; i <= this->len; i++)
this->str[i] = string.str[i];
}
String::String(const String& string, ushort offset, ushort length) {
// TODO: out of bounds?
this->len = length;
this->str = new char[this->len + 1];
for (ushort i = 0; i <= this->len; i++)
this->str[i] = string.str[offset + i];
}
String::~String() {
delete[] this->str;
}
bool String::operator==(const String& string) {
if (this->len != string.len) return false;
for (ushort i = 0; i < this->len; i++)
if (this->str[i] != string.str[i]) return false;
return true;
}
bool String::operator!=(const String& string) {
return !(*this == string);
}
String& String::operator=(const String& string) {
this->len = string.len;
delete[] this->str;
this->str = new char[this->len + 1];
for (ushort i = 0; i <= this->len; i++)
this->str[i] = string.str[i];
return *this;
}
String& String::operator+=(const String& string) {
char* str = new char[this->len + string.len + 1];
for (ushort i = 0; i < this->len; i++)
str[i] = this->str[i];
for (ushort i = 0; i <= string.len; i++)
str[this->len + i] = string.str[i];
delete[] this->str;
this->len = this->len + string.len;
this->str = str;
return *this;
}
String String::operator+(const String& string) {
char* str = new char[this->len + string.len + 1];
for (ushort i = 0; i < this->len; i++)
str[i] = this->str[i];
for (ushort i = 0; i <= string.len; i++)
str[this->len + i] = string.str[i];
return String(str);
}
char* String::getStr() const {
return this->str;
}
unsigned short String::getLen() const {
return this->len;
}
void String::set(ushort index, char value) {
// TODO: out of bounds?
this->str[index] = value;
}
char String::get(ushort index) const {
// TODO: out of bounds?
return this->str[index];
}
template<class T> String String::From(T value, ushort base) {
// TODO: check negative base
if (value == 0) return "0";
ushort length = value < 0 ? 1 : 0;
T temp = value;
while (temp != 0) {
length++;
temp /= base;
}
String result(length);
if (value < 0) {
result.str[0] = '-';
value = 0 - value;
}
while (value != 0) {
ushort rem = (value % base);
result.str[--length] = (rem <= 9) ? rem + '0' : (rem - 10) + 'a';
value /= base;
}
return result;
}
template<class T> T String::to() const {
T result = 0;
bool sign = str[0] == '-';
for (ushort i = sign; i < this->len; i++)
result = result * 10 + str[i] - '0';
return sign ? 0 - result : result;
}
template String String::From<char>(char, ushort);
template String String::From<short>(short, ushort);
template String String::From<int>(int, ushort);
template String String::From<llong>(llong, ushort);
template String String::From<uchar>(uchar, ushort);
template String String::From<ushort>(ushort, ushort);
template String String::From<uint>(uint, ushort);
template String String::From<ulong>(ulong, ushort);
template String String::From<schar>(schar, ushort);
template String String::From<sshort>(sshort, ushort);
template String String::From<sint>(sint, ushort);
template String String::From<slong>(slong, ushort);
template char String::to<char>() const;
template short String::to<short>() const;
template int String::to<int>() const;
template llong String::to<llong>() const;
template uchar String::to<uchar>() const;
template ushort String::to<ushort>() const;
template uint String::to<uint>() const;
template ulong String::to<ulong>() const;
template schar String::to<schar>() const;
template sshort String::to<sshort>() const;
template sint String::to<sint>() const;
template slong String::to<slong>() const;
}
std::string? \$\endgroup\$std::stringis a fine string class, but it doesn't fit my library. My string class also has some extra features that allow it to work nicely with the rest of my library, but i removed them since they are not relevant for reviewing the string class itself. \$\endgroup\$std::string. It's hard to help you meet your goals when we don't know what those goals are. \$\endgroup\$std::stringdoesn't have in order to fit in my library. I'll give an example. My library has aWritableclass, all children ofWritableshould implement atoStringmethod.Writablealso implements awritemethod that callstoStringand prints it out to the screen.std::stringdoes NOT extendWritableso you can't dostd::string("Hello, World!").write();, but you can doMyString("Hello, World!").write();. This is why i need my own String class. \$\endgroup\$