/*
....[@@@..[@@@..............[@.................. 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@hom.net
MUD++ development mailing list mudpp@van.ml.org
------------------------------------------------------------------------------
string.h
*/
// 25 Apr 1995 Written by Fusion <msmith@hom.net>
// 25 Apr 1995 Casual hacking by Furey <mec@duracef.shout.net>
#ifndef STRING_H
#define STRING_H
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#ifndef WIN32
#include <sys/time.h>
#endif // WIN32
#ifdef WIN32
#include <winsock.h>
#endif // win32 to get the timeval struct */
#include <signal.h>
#define ASSERT( p ) if( !p ) raise( SIGSEGV )
#define BUF 4096
#define TAB 0x09
const char * ltoa( long );
inline const char * itoa( int x ) { return ltoa( (long)x ); }
const char * ultoa( unsigned long );
int str_cmp( const char *, const char * );
int str_abbrev( 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 ] )
{}
inline StringRep::~StringRep()
{ delete [] str; }
class String
{
private:
static StringRep * repEmpty;
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 *() const { 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 & ltrim();
String & rtrim();
String & strip( const char & );
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 String &, int );
String & append( const char & );
String & append( const char * );
String & append( const char *, int );
String & append( const timeval & );
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 );
const 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 isAbbrev( const String & ) const;
bool isAbbrev( const char * ) const;
bool hasAbbrev( const char * ) const;
bool hasAbbrev( const String & ) const;
String getLine( int ) const;
String & operator << ( const char * );
String & operator << ( const String & );
String & operator << ( const char & );
String & operator << ( short );
String & operator << ( int );
String & operator << ( long );
String & operator << ( unsigned long );
String & operator << ( float );
String & operator << ( const timeval & );
int sprintf( const char * fmt, ... );
int sprintfAdd( const char * fmt, ... );
void startArgs() const;
String getArg() const;
String getArgRest() const;
void shiftLeft();
void shiftRight();
bool legalFilename() const;
};
inline String::String()
: rep( repEmpty )
{ rep->count++; }
inline String::String( const char * s )
: rep( new StringRep( s ) )
{}
inline String::String( const String & x )
: rep( x.rep )
{ rep->count++; }
inline String::String( int asize )
: rep( new StringRep( asize ) )
{ *rep->str = '\0'; }
inline String::~String()
{
if( rep->count == 1 )
delete rep;
else rep->count--;
}
// 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 const char & String::operator[]( int i ) const
{
if( i >= rep->sz )
abort();
return *(rep->str + i);
}
inline int String::len() const
{ return strlen( rep->str ); }
inline int String::size() const
{ return rep->sz; }
inline String & String::append( const String & x )
{ return append( x, strlen( x.chars() ) ); }
inline String & String::append( const char * x)
{ return append( x, strlen( x ) ); }
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 String & String::operator << ( const char * x )
{ return append( x ); }
inline String & String::operator << ( const String & 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 << ( short x )
{ return append( itoa( (int) x ) ); }
inline String & String::operator << ( long x )
{ return append( itoa( x ) ); }
inline String & String::operator << ( unsigned long x )
{ return append( ltoa( x ) ); }
inline String & String::operator << ( const timeval & x )
{ return append( x ); }
inline void String::startArgs() const
{
// Solaris ProWorks C++ does not support const_cast<> yet
// strcpy( const_cast<String *>(this)->_argbuf, rep->str );
strcpy( ((String *)this)->_argbuf, rep->str );
// const_cast<String *>(this)->_argnext = _argbuf;
((String *)this)->_argnext = _argbuf;
}
inline String String::getArgRest() const
{ return String( _argnext ); }
inline int String::asInt() const
{ return atoi( rep->str ); }
inline bool String::isAbbrev( const String & x ) const
{ return isAbbrev( x.chars() ); }
inline bool String::hasAbbrev( const String & x ) const
{ return hasAbbrev( x.chars() ); }
#endif