#ifndef _STRING_CLASS_HPP
#define _STRING_CLASS_HPP 1

/*
**
** StringClass.hpp
**
** (c) 1998 Didier Levet
**
** String classes
**
** $Revision: 1.4 $
** $State: Exp $
** $Date: 1998/11/23 14:38:42 $
**
** $Log: StringClass.hpp $
** Revision 1.4  1998/11/23 14:38:42  kakace
** Reworked CString and CStrArray classes
**
** Revision 1.3  1998/11/22 14:57:35  kakace
** Class CStrArray now uses class CString and seems to work fine
**
** Revision 1.2  1998/11/21 20:58:09  kakace
** Class CString seems to be ok now.
**
** Revision 1.1  1998/11/11 16:34:56  kakace
** Initial revision
**
**
*/


/// Includes

#ifndef  _INCLUDE_FSTREAM_H
#include <fstream.h>
#endif

#ifndef  EXEC_TYPES_H
#include <exec/types.h>
#endif

///


#ifndef STRING
typedef const char *STRING;
#endif


//----------------------------------------------------------------------------------------------------
//========================================== Class CString ===========================================
//----------------------------------------------------------------------------------------------------

class CString
{
    public:

        enum ST_EMPTY  {EMPTY};
        enum ST_UNUSED {UNUSED};

        // Constructors and destructor.

        CString()                                   {release();}
        CString(STRING str, ULONG minLength = 0);
        CString(CString& str)                       {adopt(str);}
        ~CString()                                  {freebuff();}

        // Accessors.

        ULONG length() const                        {return iLength;}
        ULONG buffsize() const                      {return iBuffLen;}
        void  update()                              {iLength = stringlen(pcString);}
        void  release()                             {pcString = NULL; iLength = iBuffLen = 0;}
        ULONG extend(ULONG newSize);

        STRING   string() const                     {return pcString;}
        CString *clone(const CString& str)          {duplicate(str.pcString, str.iLength); return this;}

        void    adopt(CString &str)
                {
                    pcString = str.pcString;
                    iLength  = str.iLength;
                    iBuffLen = str.iBuffLen;
                    str.release();
                }

        // Operators.

        operator char *() const                     {return pcString;}
        int operator !() const                      {return (pcString == NULL);}

        CString& operator =(const CString& str)
                 {
                     if (&str != this)
                         duplicate(str.pcString, str.iLength);
                     return *this;
                 }

        CString& operator = (STRING str)            {duplicate(str, stringlen(str)); return *this;}
        CString& operator +=(const CString& str)    {concat(str.pcString, str.iLength); return *this;}
        CString& operator +=(STRING str)            {concat(str, stringlen(str)); return *this;}
        CString& operator + (const CString& str)    {return *this += (const CString& ) str;}

        int operator > (const CString& str) const;
        int operator !=(const CString& str) const;

        int operator !=(ST_EMPTY f) const           {return (iLength > 0);}
        int operator !=(ST_UNUSED f) const          {return (pcString != NULL);}

        int operator >=(const CString& str) const   {return !((const CString&) str > (const CString&) *this);}
        int operator < (const CString& str) const   {return  ((const CString&) str > (const CString&) *this);}
        int operator <=(const CString& str) const   {return !((const CString&) *this > (const CString&) str);}
        int operator ==(const CString& str) const   {return !((const CString&) *this != (const CString&) str);}

        int operator ==(ST_EMPTY f) const           {return (iLength == 0);}
        int operator ==(ST_UNUSED f) const          {return (pcString == NULL);}

        friend ostream& operator << (ostream& os, const CString& str) {return os << (str.string() ? str.string() : "\0");}

    protected:

        char   *pcString;           // Pointer to the string buffer. NULL == No buffer allocated.
        ULONG   iLength;            // String's length. ZERO = No string held or empty string.
        ULONG   iBuffLen;           // Buffer's length. ZERO = No buffer allocated.

        // Protected function members.

        static ULONG stringlen(const char s[]);
        static ULONG stringcopy(STRING source, char *dest);

        void  newstring(STRING str, ULONG size);
        void  concat(STRING str, ULONG len);
        void  duplicate(STRING str, ULONG len);
        void  freebuff()        { delete [] pcString; }
};


//----------------------------------------------------------------------------------------------------
//========================================= Class CStrArray ==========================================
//----------------------------------------------------------------------------------------------------
//
//  This class is used to hold string arrays on an exclusive manner. Once an object is created, it
// can't be referenced several times. This helps to avoid multiple buffer deallocations.


class CStrArray
{
    public:

        void release()          {voStringArray = NULL; iNumEntries = iCurrentIndex = 0;}

        CStrArray()             {release();}
        ~CStrArray()            {freebuff();}

        // Copy constructor and assignement operator.

        CStrArray(CStrArray& array) {AdoptArray(array);}

        CStrArray& operator =(CStrArray& array);
        CStrArray& operator =(STRING *array);
        CString&   operator [] (int i) const    { return voStringArray[i]; }

        // Misc.

        LONG     CurrentIndex() const           {return iCurrentIndex;}
        int      Add(STRING str)                {return adopt(str);}
        int      adopt(CString& str);
        int      extend(ULONG size = 10);

        // Conditionnal operators.

        operator int() const                    {return (int) voStringArray;}
        int operator !() const                  {return !((int) voStringArray);}

    private:

        CString *voStringArray;             // Array pointer.
        ULONG    iNumEntries;               // Array size.
        LONG     iCurrentIndex;             // Index of the next entry.

        void    cleanup()                   {freebuff(); release();}
        void    freebuff()                  { delete [] voStringArray; }
        void    newstring(CString& str)     { voStringArray[iCurrentIndex++].adopt(str); }

        void    AdoptArray(CStrArray& array)
                {
                    voStringArray = array.voStringArray;
                    iNumEntries   = array.iNumEntries;
                    iCurrentIndex = array.iCurrentIndex;
                    array.release();
                }
};


//----------------------------------------------------------------------------------------------------

#endif  // _STRING_CLASS_HPP

