/*
....[@@@..[@@@..............[@.................. MUD++ is a written from
....[@..[@..[@..[@..[@..[@@@@@....[@......[@.... scratch multi-user swords and
....[@..[@..[@..[@..[@..[@..[@..[@@@@@..[@@@@@.. sorcery game written in C++.
....[@......[@..[@..[@..[@..[@....[@......[@.... This server is an ongoing
....[@......[@..[@@@@@..[@@@@@.................. development project.  All 
................................................ contributions are welcome. 
....Copyright(C).1995.Melvin.Smith.............. Enjoy. 
------------------------------------------------------------------------------
Melvin Smith (aka Fusion)         msmith@falcon.mercer.peachnet.edu 
MUD++ development mailing list    mudpp-list@spice.com
------------------------------------------------------------------------------
string.h
*/

// 25 Apr 1995  Written by Fusion <msmith@falcon.mercer.peachnet.edu>
// 25 Apr 1995  Casual hacking by Furey <mec@duracef.shout.net>

#ifndef STRING_H
#define STRING_H

#include "io.h"
#include <string.h>
#include <ctype.h>
#include <stdlib.h>

#include "signal.h"
#define ASSERT( p ) if( !p ) raise( SIGSEGV )

#define BUF 4096

#define TAB 0x09

const char * itoa( int );
const char * ltoa( unsigned long );
int str_cmp( const char *, const char * );

class String;


class StringRep 
{
	private:
		friend class String;
		int count;
		int sz;       // actual size, strlen will return len
		char *str; 

		StringRep( )
		: count(1), sz(0), str(0) { }
		StringRep( const char * );
		StringRep( const StringRep & );
		StringRep( int );
		~StringRep( );
    
		const StringRep & operator = ( const StringRep & );
};


inline StringRep::StringRep( const char *x )
:	count( 1 ), sz( strlen(x)+1 ),
	str( new char[ strlen(x)+1 ] )
{
	strcpy( str, x ); 
}


inline StringRep::StringRep( const StringRep &orig )
: count( 1 ), sz( strlen( orig.str ) + 1 ), str( new char[ sz ] )
{
	strcpy( str, orig.str );
}


inline StringRep::StringRep( int asize )
: count( 1 ), sz( asize ), str( new char[ asize ] )
{
	*str = '\0';
}

inline StringRep::~StringRep()
{
	delete [] str;
}



// String class

class String
{
	private:
		StringRep *rep;

	protected:
		// For startArgs(), getArg(), and getArgRest()
		static char _argbuf[ 1024 ];
		static char *_argptr;
		static char *_argnext;

	public:
		String();
		String( const char * );
		String( const String & );
		String( int );  
		~String();
   
		operator const char *() { return rep->str; }
  
		int count() { return rep->count; } 
		int len() const;            // strlen
        void clr();		
		int size() const;              // size of allocated mem
		void allocate( int );          // explicitly allocate size mem
		const char * chars() const;
		char * dup() const;
		String asUpper() const;  
		String asLower() const;
		String asProper() const;
		String & chop();
		String & clean();
		String & crypt( const String & salt );
		int asInt() const;
		bool isNumber() const;
		String & toUpper();  
		String & toLower();
		String & toProper();
		String & operator = ( const char * );
		String & operator = ( const String & ); 
		bool operator == ( const String & ) const;
		bool operator == ( const char * ) const;
		bool operator != ( const String & ) const;
		bool operator != ( const char * ) const;
		String & append( const String & );
		String & append( const char );
		String & append( const char * );
		String & operator += ( const String & ); 
		String & operator += ( const char ); 
		String & operator += ( const char * ); 
		String & operator += ( int ); 
		String & operator += ( unsigned long int );
		String operator + ( const String & ) const;
		String operator + ( const char * ) const;
		String operator + ( const char ) const;
		String operator + ( int ) const;
		String operator + ( unsigned long ) const;
		operator bool() const { return (bool)*rep->str; }
		char & operator [] ( int i );
		char operator [] ( int i ) const;
		bool compare( const String & ) const;
		bool compare( const char * ) const;
		bool compareWithCase( const String & ) const;
		bool compareWithCase( const char * ) const;
		bool hasChar( const char & x ) const { return (bool)strchr( rep->str, x ); }
		bool abbrev( const String & ) const;
		bool abbrev( const char * ) const;
		bool subStr( const String & ) const;
		bool subStr( const char * ) const;
        String getLine( int ) const;
		String & operator << ( const char * );
        String & operator << ( const String & );
        String & operator << ( char );
        String & operator << ( int );
        String & operator << ( unsigned long int );
        String & operator << ( float );
		int sprintf( const char * fmt, ... );
		int sprintfAdd( const char * fmt, ... );
		void startArgs();
		const char * getArg();
		const char * getArgRest();
		void shiftLeft();
		void shiftRight();
//		void rotateLeft();
//		void rotateRight();
		friend OStream & operator << ( OStream &, const String & );
//		friend IStream & operator >> ( IStream &, const String & );

//	Disabled
		void setLen();                 // these are needed if the [] array
		void setLen( int );            //   operators are used to mod the string
};


// This fixes the problem which arises in a lot of implementations
// when you do   if( "blah" == str ) and the const char * operator is
// invoked for the string object instead of the ==

inline bool operator == ( const char * ptr, const String & str )
{
	// Invoke string operator first.
	return str.compare( ptr );
}


inline const char * String::chars() const
{
	return rep->str;
}

inline String & String::operator += ( const String & x )
{
	return append( x );
}

inline String & String::operator += ( const char x )
{
	return append( x );
}

inline String & String::operator += ( const char * x )
{
	return append( x );
}

inline String & String::operator += ( int x )
{
	return append( itoa( x ) );
}

inline String & String::operator += ( unsigned long x )
{
	return append( ltoa( x ) );
}

inline bool String::operator == ( const String & str ) const
{
	return compare( str );
}

inline bool String::operator == ( const char * str ) const
{
	return compare( str );
}

inline bool String::operator != ( const String & str ) const
{
	return !(compare( str ));
}

inline bool String::subStr( const String & str ) const
{
	return abbrev( str );
}

inline bool String::subStr( const char * str ) const
{
	return abbrev( str );
}

inline void String::startArgs()
{
	strcpy( _argbuf, rep->str );
	_argnext = _argbuf;
}

inline const char * String::getArgRest()
{
	return _argnext;
}

#endif