#ifndef CSTRING_H
#define CSTRING_H


#include <list.h>


//#define CODE_COVERAGE_TESTING_DEBUG(pnt)     printf("\nCODE_COVERAGE_POINT_" pnt "\n")
#define CODE_COVERAGE_TESTING_DEBUG(pnt)


// Should template for the char type
class String : public List<char>
{
public:
    String() : List<char>()
    {
        CODE_COVERAGE_TESTING_DEBUG("0000\n");
    }

    String(const String &cpy)
    {
        items = 0;
        cnt = 0;
        if ( &cpy != this ) {
            CODE_COVERAGE_TESTING_DEBUG("0001\n");
            copy(cpy.items);
        } else {
            CODE_COVERAGE_TESTING_DEBUG("0002\n");
        }
    }

    String(const char *cpy)
    {
        CODE_COVERAGE_TESTING_DEBUG("0003\n");
        items = 0;
        copy(cpy);
    }

    const String& operator=(const String& cpy)
    {
        if ( &cpy != this ) {
            CODE_COVERAGE_TESTING_DEBUG("0004\n");
            copy(cpy.items);
        } else {
            CODE_COVERAGE_TESTING_DEBUG("0005\n");
        }
        return *this;
    }
    
    const String &operator=(const char *cpy)
    {
        CODE_COVERAGE_TESTING_DEBUG("0006\n");
        copy(cpy);
        return *this;
    }

    void copy(const char *str)
    {
        free(items);
        items = 0;
        cnt = 0;
        if ( str ) {
            CODE_COVERAGE_TESTING_DEBUG("0007\n");
            items = strdup(str);
            cnt = strlen(str);
        } else {
            CODE_COVERAGE_TESTING_DEBUG("0008\n");
        }
    }

    const String &operator+=(const char *str)
    {
        if ( str ) {
            int oldCnt = cnt;
            int addCnt = strlen(str);
            cnt += addCnt;
            items = (char *)realloc(items, sizeof(char) * (cnt + 1));
            memcpy(items + oldCnt, str, addCnt + 1);
            CODE_COVERAGE_TESTING_DEBUG("0009\n");
        } else {
            CODE_COVERAGE_TESTING_DEBUG("0010\n");
        }
        return *this;
    }

    const String &operator+=(const String &str)
    {
        if ( str.items ) {
            int oldCnt = cnt;
            cnt += str.cnt;
            items = (char *)realloc(items, sizeof(char) * (cnt + 1));
            memcpy(items + oldCnt, str.items, str.cnt + 1);
            CODE_COVERAGE_TESTING_DEBUG("0011\n");
        } else {
            CODE_COVERAGE_TESTING_DEBUG("0012\n");
        }
        return *this;
    }

    inline operator const char *() const
    {
        CODE_COVERAGE_TESTING_DEBUG("0013\n");
        return items;
    }

    const char *className() const { return "String"; }
    const char *dump() const;
};
 

const String &operator+(const String &stra, const String &strb)
{
    CODE_COVERAGE_TESTING_DEBUG("0014\n");
    static String ret;
    ret = stra;
    ret += strb;
    return ret;
}


const String &operator+(const String &stra, const char *strb)
{
    CODE_COVERAGE_TESTING_DEBUG("0015\n");
    static String ret;
    ret = stra;
    ret += strb;
    return ret;
}


const char *String::dump() const
{
    return (const char *)(String("\"") + items + String("\""));
}


#endif // CSTRING_H

