//****************************************************************//
// Filename:  StringC.h
// Autor:     Christian Taulien of Strange Intelligence
// Purpose:   Definition der StringC Klasse
// Creation:  27. Mai 1997
//****************************************************************//
#ifndef TAULIEN_STRINGCLASS_HPP
#define TAULIEN_STRINGCLASS_HPP
#define RCSID_SIFC_STRINGS_H "$Id: SIFC_Strings.h 1.19 1998/04/16 03:29:43 Christian_Taulien Exp Christian_Taulien $"

//#include "SIFC.h"
#include <stdarg.h>
#include <string.h>
#include <iostream.h>

#include <exec/types.h>

//*************************************************************************//
//.klasse
//KLASSENNAME   : StringC
//VERSION       : 28. Februar 1998
//AUTOR         : Taulien
//AUFGABE       : Eine leistungsfähige String-Klasse
//DOKUMENTATION : -
//BEMERKUNGEN   : -
//AENDERUNGEN   : -
//28. Februar 1998: Neu: operator+= für nicht konstante Datentypen als
//                  inline Methoden hinzugefügt.
//*************************************************************************//
class StringDataC
{
public:
  char  *m_sStrPtr;
  ULONG  m_ulStrLen;
  ULONG  m_ulBufLen;
  LONG   m_lRefs;
};

class StringC
{
private:
  // ## private Datamembers
  StringDataC *m_poData;

  // Error-String index enumeration
  enum {
     str_AccessOutOfRange=0,
     str_NoMemForAddition,
     str_WriteAccessOnEmptyString,
     str_IllegalZeroLength,
     STRINGC_Last };

  static const char *m_asStringTable[STRINGC_Last];

  // ## private Methods ##
  static const char *getStringTableEntry(ULONG arg_ulIndex);
  StringC(ULONG arg_ulStrLen, ULONG arg_ulBufLen, char *arg_sStrPtr);

  BOOL isFilled();
  BOOL isMultiUsed();
  void incReference();
  void decReference();
  void prepareModify();

protected:
  // ## protected methods ##
  void initStringC(const char *arg_sStrPtr, ULONG arg_ulBufLen);
  void initStringC(ULONG arg_ulBufLen);
  void freeBuffer(void);
  void resizeBuffer(ULONG arg_ulSize);
  ULONG getBufferSize(void) const;

#ifdef si_debug
  void dumpContext(void) const;
#endif

public:
  // ## public methods ##
  enum { STRINGC_AccessLast = STRINGC_Last };
  // Constructors and Destructor
  StringC();
  StringC(const char *arg_sStrPtr);
  StringC(ULONG  arg_ulBufLen);
  StringC(const char *arg_sStrPtr, ULONG arg_ulBufLen);
  StringC(const StringC &arg_roSrcObj);
  ~StringC();

  // common methods
  BOOL isEmpty(void) const;
  void emptyString(void);
  void allocBuffer(ULONG arg_ulSize); // throw ObjectXC*;
  ULONG getLength(void) const;
  const char *getBuffer(void) const;
  char getAt(ULONG arg_ulIndex, BOOL arg_fResizeIfNeccessary=FALSE);
  char setAt(ULONG arg_ulIndex, char arg_cChar, BOOL arg_fResizeIfNeccessary=FALSE);
  char *releaseBuffer(void);
  void freeExtra(void);
  void setString(const char *arg_sString);
  LONG compareStringNoCase(StringC &arg_roCompObj);
  LONG compareStringNoCase(char *arg_sCompStr);
  LONG compareStringLimited(StringC &arg_roCompObj, ULONG arg_ulLength);
  LONG compareStringLimited(char *arg_sCompStr, ULONG arg_ulLength);
  LONG compareStringLimitedNoCase(StringC &arg_roCompObj, ULONG arg_ulLength);
  LONG compareStringLimitedNoCase(char *arg_sCompStr, ULONG arg_ulLength);
  StringC midString(ULONG arg_ulFirst, ULONG arg_ulCount) const;
  StringC midString(ULONG arg_ulFirst) const;
  StringC leftString(ULONG nCount) const;
  StringC rightString(ULONG arg_ulCount) const;
  LONG findChar(char arg_cSearchedChar) const;
  LONG findCharNot(char arg_cSearchedChar) const;
  LONG findCharReverse(char arg_cSearchedChar) const;
  LONG findCharNotReverse(char arg_cSearchedChar) const;
  LONG findString(const StringC &arg_roSearchedString) const;
  LONG findString(char *arg_sSearchedString) const;
  LONG findStringNoCase(const StringC &arg_roSearchedString) const;
  LONG findStringNoCase(char *arg_sSearchedString) const;
  LONG findOneOf(char *arg_sCharSet) const;
  void makeLower(void);
  void makeUpper(void);
  void makeReverse(void);
  void trimRight(void);
  void trimLeft(void);
  void trimString(void);
  void formatString(char *arg_sFormat, ...);
  void fillString(char arg_cFillByte);

  BOOL checkInstance(void) const;
  void validateInstance(void);
  void initInstance(void);
  static void initStatic(StringC *arg_poString);

  // ## operator-Stuff ##
  char operator[](int arg_iIndex);
  operator char *() const;
  operator const StringC &() { return (const StringC &) *this; };
  StringC &operator=(const char *arg_sString);
  StringC &operator=(const StringC &arg_roSrcObj);
  StringC &operator += (const StringC &arg_roSummand);
  StringC &operator += (StringC &arg_roSummand) { return operator+=((const StringC &) arg_roSummand); };
  StringC &operator += (const char *arg_sSummand);
  StringC &operator += (char *arg_sSummand)     { return operator+=((const char *) arg_sSummand); };
  StringC &operator += (const char arg_cSummand);
  StringC &operator += (char arg_cSummand)      { return operator+=((const char) arg_cSummand); };
  friend StringC operator+(const StringC &arg_roFirst, const StringC &arg_roSecond);

  friend StringC operator+(const StringC &arg_roFirst, char arg_cSecond);
  friend StringC operator+(char arg_cFirst, const StringC &arg_roSecond);

  friend StringC operator+(const StringC &arg_roFirst, const char *arg_sSecond);
  friend StringC operator+(const char *arg_sFirst, const StringC& arg_roSecond);
};

BOOL operator==(const StringC &arg_ro1, const StringC &arg_ro2);
BOOL operator==(const StringC &arg_ro1, const char *s2);
BOOL operator==(const StringC &arg_ro1, char *s2)
                  { return operator==(arg_ro1, (const char *) s2); };
BOOL operator==(const char *s1, const StringC &arg_ro2);
BOOL operator==(char *s1, const StringC &arg_ro2)
                  { return operator==((const char *) s1, arg_ro2); };
BOOL operator!=(const StringC &arg_ro1, const StringC &arg_ro2);
BOOL operator!=(const StringC &arg_ro1, const char *s2);
BOOL operator!=(const char *s1, const StringC &arg_ro2);
BOOL operator<(const StringC &arg_ro1, const StringC &arg_ro2);
BOOL operator<(const StringC &arg_ro1, const char *s2);
BOOL operator<(const char *s1, const StringC &arg_ro2);
BOOL operator>(const StringC &arg_ro1, const StringC &arg_ro2);
BOOL operator>(const StringC &arg_ro1, const char *s2);
BOOL operator>(const char *s1, const StringC &arg_ro2);
BOOL operator<=(const StringC &arg_ro1, const StringC &arg_ro2);
BOOL operator<=(const StringC &arg_ro1, const char *s2);
BOOL operator<=(const char *s1, const StringC &arg_ro2);
BOOL operator>=(const StringC &arg_ro1, const StringC &arg_ro2);
BOOL operator>=(const StringC &arg_ro1, const char *s2);
BOOL operator>=(const char *s1, const StringC &arg_ro2);

inline ostream &operator << (ostream &arg_roCout, const StringC &arg_roSrcObj)
  { arg_roCout << arg_roSrcObj.getBuffer(); return(arg_roCout); };

// StringC-Tags
#define SIFCT_StringC_Index   SIFC_TAGBASE(StringC) + 1
#define SIFCT_StringC_BufLen  SIFC_TAGBASE(StringC) + 2
#define SIFCT_StringC_StrLen  SIFC_TAGBASE(StringC) + 3

// StringC-IDs
#define SIFCID_StringC_ErrCode_AccessOutOfRange           SIFC_TAGBASE(StringC) + 1
#define SIFCID_StringC_ErrCode_WriteAccessOnEmptyString   SIFC_TAGBASE(StringC) + 2
#define SIFCID_StringC_ErrCode_ZeroLength                 SIFC_TAGBASE(StringC) + 3

#endif

