//---------------------------------------------------------------- strings.h -
// Module:       strings.h
//
// Version:      $Revision: 1.5 $
//               $Date: 1997/06/27 21:05:18 $
//
// Description:  'string' class declarations
//----------------------------------------------------------------------------


#if ! defined( STRINGS_H )                        // avoid multiple inclusions
#  define   STRINGS_H


#include  <stddef.h>
#include  <functional>
#include  <iostream>
using namespace std;
#include  <string.h>


class StringData
{
private:
     StringData();

     StringData(
     const char *st);

     StringData(
     const StringData &oldData);

     StringData(
     char ch,
     int chcount);

    ~StringData();

     char *GetData()
     {
          return( m_buf );
     }

     void
     AddRef();

     void
     DecRef();

     int
     RefCount();

     void
     Resize(
     int buflen);

     friend class String;

     char *m_buf;
     int m_allocated;
     int m_curlen;
     int m_refs;
     static int totalRefs;

     void
     AddTotalRef();

     void
     DecTotalRef();
};


class String
{
public:
  String();
  String( const char *chs );
  String( const String &st );
  String( char ch, int n = 1 );  // for Pascal-like char-to-String conversion

 ~String();

  String & operator = ( const String & a );
  String & operator = ( const char *s );

  String & operator +=( const String & a );
  String & operator +=( const char *s );
  String & operator +=( const char a );

  //  too simple and used too often not to be inlined
  //
  const char *c_str() const
  {
     return( m_data->GetData() );
  }

//  operator const char *() const
//  {
//    return( c_str() );
//  }

  char & operator[] ( int n );
  const char & operator[] ( int n ) const;

  String    substr( int from, int len = -1 ) const;
  void      remove( int from, int len = -1 );
  void      insert( int at, const char *st );
  void      append(const char* st,int len);

  int       length() const
  {
     return( CurLen() );
  }

  int       find( char c, int caseInsensitive = 0 ) const;
  int       find( const char *s, int caseInsensitive = 0 ) const;
  int       find( const String &s, int caseInsensitive = 0 ) const
  {
     return( find( s.c_str(), caseInsensitive ) );
  }

  int                              //   position of match, or -1
  find_first_of(                   // find first of a set of chars in a string
  const char *charlist,            //   chars to search for
  int startAt) const;              //   starting from what pos?

  int                              //   first non-match, or -1
  find_first_not_of(               // find first not of a set of chars
  const char *charlist,            //   chars to match
  int startAt) const;              //   start searching at

  int                              //   index of 'c' in string, or -1
  reverseFind(                     // find last occurence of a char in the string
  char c,                          //   char to search for
  int caseInsensitive = 0) const;  //   non-zero for case-insensitive search

  friend bool     operator == ( const String & a, const String & b );
  friend bool     operator == ( const char *s, const String & b );
  friend bool     operator == ( const String & a, const char *s );
  friend String   operator +  ( const String & a, const String & b );
  friend String   operator +  ( const String & a, const char * b );
  friend bool     operator != ( const String & a, const String & b );
  friend bool     operator >= ( const String & a, const String & b );
  friend bool     operator <= ( const String & a, const String & b );
  friend bool     operator <  ( const String & a, const String & b );
  friend bool     operator >  ( const String & a, const String & b );

  friend size_t   strlen( const String & st );

  static int npos;

private:
     friend class StringModRefs;

  StringData *m_data;

  void
  AddRef();

  void
  DecRef();

  inline char *buf() const
  {
     return( m_data->GetData() );
  }

  inline int Allocated() const
  {
     return( m_data->m_allocated );
  }

  inline int CurLen() const
  {
     return( m_data->m_curlen );
  }

  void      resize( size_t n );

  static void InitializeEmpty();
  static void DeleteEmpty();
};


// istream& operator>>( istream & is, String &s );
inline ostream& operator <<( ostream &os, String &s )
{
     os << s.c_str();
     return( os );
}


inline size_t strlen( const String & st )
{
  return( st.CurLen() );
}

inline bool operator < ( const String & a, const String & b )
{
     bool result = (strcmp( a.c_str(), b.c_str() ) < 0);

     return( result );
}


inline bool samestr(
const char *a,
const char *b)
{
     return( stricmp( a, b ) == 0 );
}


inline bool sameas(
const String &a,
const String &b)
{
     return( samestr( a.c_str(), b.c_str() ) );
}

inline bool sameas(
const String &a,
const char *b)
{
     return( samestr( a.c_str(), b ) );
}

inline bool sameas(
const char *a,
const String &b)
{
     return( samestr( a, b.c_str() ) );
}

struct lessStr : public binary_function<String, String, bool>
{
    bool operator() (const String& x, const String& y) const { return x < y; }
};

struct lessStrI : public binary_function<String, String, bool>
{
    bool operator() (const String& x, const String& y) const { return( stricmp( x.c_str(), y.c_str() ) < 0 ); }
};

class StringModRefs
{
public:
     StringModRefs();
    ~StringModRefs();

private:
     static int m_refs;
};

static StringModRefs modRef;

#endif    // ! defined (STRINGS_H)

