module;
#include <cstring>

export module CString;

// Klassendefinition
export class CString
{
    char* pString;          // String
public:
    // ctor
    CString();
    CString(const char* const pS);
    CString(const CString& source);
    // dtor
    ~CString();
    // String Zuweisungen
    CString& operator = (this CString& self, const char* const pS);
    CString& operator = (this CString& self, const CString& add);
    // Strings addieren
    void AddString(const char* const pS);
    void AddString(const CString& add);
    // String zurueckgeben
    const char* GetString() const
    {
        return pString;
    }
};

// Definition der Memberfunktionen
// Delegierender Konstruktor
CString::CString() :
    CString("")
{
}
// copy-ctor, delegierender ctor
CString::CString(const CString& source) :
    CString(source.GetString())
{
}
// Target ctor
CString::CString(const char* const pS)
{
    // Nun neuen Speicherplatz für String anfordern
    // Die abschliessende binäre 0 dabei nicht vergessen!
    auto len = strlen(pS) + 1;
    pString = new char[len];
    // String umkopieren
    strcpy_s(pString, len, pS);
}
// Destruktor
CString::~CString()
{
    // Speicher für char-Feld freigeben!
    delete[] pString;
}
// Fügt den über den char-Zeiger übergebenen String hinzu
void CString::AddString(const char* const pS)
{
    // Zuerst Speicher für neuen String reservieren
    auto bufSize = strlen(pString) + strlen(pS) + 1;
    auto pTemp = new char[bufSize];
    // Dann den ursprünglichen String umkopieren
    strcpy_s(pTemp, bufSize, pString);
    // und nun den neuen String hinzufügen
    strcat_s(pTemp, bufSize, pS);
    // Jetzt erst den ursprünglichen Speicher freigeben
    delete[] pString;
    // und Zeiger auf neuen Speicherbereich setzen
    pString = pTemp;
}
// Fügt den über die String-Referenz übergebenen String hinzu
void CString::AddString(const CString& add)
{
    AddString(add.GetString());
}
// Weist einen C-String zu
CString& CString::operator = (this CString& self, const char* const pS)
{
    delete[] self.pString;
    self.pString = new char[strlen(pS) + 1];
    strcpy_s(self.pString, strlen(pS) + 1, pS);
    return self;
}
// Weist ein CString Objekt zu
CString& CString::operator = (this CString& self, const CString& add)
{
    // Gleicher Ablauf wie operator=(char*)
    return self.operator = (add.GetString());
}
