/**************************************************************************** PROJECT: FlowerSoft C++ library FILE : string.cc --*/ #include #include #include "string.h" #define max( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) #define min( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) ) #include "itoa.h" #include "strupr.h" /**************************************************************************** class StringData --*/ #ifndef __STRINGDATA__STRINGDATA #define __STRINGDATA__STRINGDATA StringData::StringData() { length = 0; references = 1; string = 0; } #endif /**************************************************************************** class String --*/ #ifndef __STRING_STRING #define __STRING_STRING String::String() { data = new StringData; } #endif String::String( const char* source ) { data = new StringData; if ( source && *source ) { data->length = strlen( source ) + 1; data->string = new char[ data->length ]; strcpy( data->string, source ); } } String::String( const String& source ) { data = new StringData; *this = source; } String::String( const char c, const int n ) { data = new StringData; data->length = min( max( n, 0 ), 80 ); if ( data->length ) { data->string = new char[ ++data->length ]; memset( data->string, c, data->length - 1 ); data->string[ data->length - 1 ] = '\0'; } } #include "itoa.h" String::String( const int i ) { data = new StringData; char string[ 81 ]; string[ 0 ] = '\0'; itoa( i, string, 10 ); // assume radix 10 *this = String( string ); } String::String( const int i, const int n, const char c ) { data = new StringData; char fillChar = c; if ( fillChar ) fillChar = '0'; String value( i ); *this = String( fillChar, n - value.len() ) + String( value ); } String::~String() { if ( --data->references == 0 ) { if ( data->string && data->length ) #if 1 DELETE_ARRAY( data->length ) data->string; #else delete data->string; #endif delete data; } } String::operator const char *() const { static char nul = 0; if ( data->length ) return data->string; else return &nul; } int String::operator ==( const Sortable& test ) const { return compare( (String&)test ); } int String::operator &&( const Object& test ) const { int i = min( len(), ( (String&)test ).len() ); return ( i > 0 ) ? ( !strncmp( data->string, ( (String&)test ).data->string, i ) ) : 0; } int String::operator >( const Sortable& test ) const { return strcmp( data->string, ( (String&)test ).data->string ) > 0; } String& String::operator +( const String& s2 ) { if ( !len() ) *this = s2; else if ( s2.len() ) { String string; string.data->length = data->length + s2.data->length - 1; string.data->string = new char[ string.data->length ]; strcpy( string.data->string, *this ); strcat( string.data->string, s2 ); *this = string; } return *this; } String& String::operator +( const char* s2 ) { return ( *this + (String&)String( s2 ) ); } String& String::operator +( const char c ) { return ( *this + (String&)String( c ) ); } #if 0 String operator +( const char* s1, const String& s2 ) { String string( s1 ); string += (String&)s2; return string; } String operator +( const char c, const String& s2 ) { String string( c ); string += (String&)s2; return string; } #endif #if 0 String operator +( const String& s1, const String& s2 ) { if ( !s1.len() ) return String( s2 ); if ( !s2.len() ) return String( s1 ); String newString( 0 ); newString.data->length = s1.data->length + s2.data->length - 1; newString.data->string = new char[ newString.data->length ]; strcpy( newString.data->string, s1 ); strcat( newString.data->string, s2 ); return newString; } #endif void String::operator =( const String& source ) { source.data->references++; if ( --data->references == 0 ) { #if 0 delete[] data->string; #else if ( data->string && data->length ) delete data->string; #endif delete data; } data = source.data; } #if 0 void String::operator =( const char* source ) { if ( this->s == source ) return; if ( length && s ) delete s; if ( source && *source ) { length = strlen( source ) + 1; s = new char[ length ]; strcpy( s, source ); } else { length = 0; s = 0; } } #endif void String::operator +=( const char* source ) { *this = *this + String( source ); } void String::operator +=( const char c ) { *this += String( c ); } void String::operator ()( char* copy ) const { if ( data->length ) strcpy( copy, data->string ); else *copy = 0; } char& String::operator []( const int n ) { static char nul = 0; if ( len() && ( n >= 0 ) && ( n < len() ) ) { if ( data->references > 1 ) { data->references--; StringData* newData = new StringData; newData->length = data->length; if ( newData->length ) { newData->string = new char[ newData->length ]; strcpy( newData->string, data->string ); } data = newData; } return data->string[ n ]; } else return nul; } const char& String::operator []( const int n ) const { static char nul = 0; if ( data->length && ( n >= 0 ) && ( n < data->length - 1 ) ) return data->string[ n ]; else return nul; } //int String::compare( const String& test ) const int String::compare( const char* test ) const { if ( data->string == test ) return 1; if ( !test ) return 0; int testLength = strlen( test ); if ( len() && testLength ) #if 1 return ( ( len() == testLength ) && !strcmp( data->string, test ) ); #else { if ( data->string[ 0 ] != test[ 0 ] ) return 0; else { if ( data->string[ 1 ] != test[ 1 ] ) return 0; else // we can't do +2 , since len may be 1 char return ( !strcmp( data->string + 1, test + 1 ) ); } } #endif else return ( len() == testLength ); } #if 0 double String::fvalue() const { return ( data->length ? atof( s ) : 0 ); } #endif int String::lastPos( const char c ) const { int pos = 0; if ( len() ) { char* p = strrchr( data->string, c ); if ( p ) pos = p - data->string + 1; } return pos; } int String::lastPos( const char* string ) const { int pos = 0; int length = strlen( string ); if ( len() && length ) { int nextpos = this->pos( string ); while( nextpos ) { pos += nextpos; nextpos = right( data->length - pos - length + 1 ).pos( string ); } } return pos; } String String::left( const int n ) const { #if 0 if ( !len() || ( n < 1 ) ) return String( 0 ); String newString( 0 ); newString.data->length = min( data->length - 1, n ) + 1; newString.data->string = new char[ newString.data->length ]; newString.data->string[ 0 ] = '\0'; strncat( newString.data->string, data->string, newString.data->length - 1 ); return newString; #else return String( mid( 1, n ) ); #endif } String& String::lower() { if ( len() ) { if ( data->references > 1 ) { data->references--; StringData* newData = new StringData; newData->length = data->length; strcpy( newData->string, data->string ); data = new StringData; } strlwr( data->string ); } return *this; } String String::nomid( const int pos, const int n ) const { if ( ( pos < 1 ) || ( pos > len() ) ) return String( 0 ); else return String( String( left( pos - 1 ) ) + right( len() - pos - n + 1 ) ); } String String::mid( const int pos, const int n ) const { // pos 1 == data->string[ 0 ]; // pos 0 allowed for conveinience if ( !len() || ( pos < 0 ) || ( pos > len() ) && ( n < 1 ) ) // return *new String; return String( 0 ); // String& newString = *new String; String newString( 0 ); newString.data->length = min( n, data->length - pos ) + 1; newString.data->string = new char[ newString.data->length ]; newString.data->string[ 0 ] = '\0'; strncat( newString.data->string, data->string + pos - 1, newString.data->length - 1 ); return newString; } int String::pos( const char c ) const { int pos = 0; if ( len() ) { char* p = strchr( data->string, c ); if ( p ) pos = p - data->string + 1; } return pos; } int String::pos( const char* string ) const { int pos = 0; if ( len() && string ) { char* p = strstr( data->string , string ); if ( p ) pos = p - data->string + 1; } return pos; } int String::posAny( const char* string ) const { int pos = 0; if ( len() && string ) { char* p = strpbrk( data->string, string ); if ( p ) pos = p - data->string + 1; } return pos; } String String::right( const int n ) const { #if 1 if ( !len() || ( n < 1 ) ) return String( 0 ); String newString( 0 ); newString.data->length = min( data->length - 1, n ) + 1; newString.data->string = new char[ newString.data->length ]; newString.data->string[ 0 ] = '\0'; strncat( newString.data->string, data->string + data->length - newString.data->length, newString.data->length - 1 ); return newString; #else return mid( len() - n + 1, n ); #endif } String& String::upper() { if ( len() ) { if ( data->references > 1 ) { data->references--; StringData* newData = new StringData; newData->length = data->length; strcpy( newData->string, data->string ); data = new StringData; } strupr( data->string ); } return *this; } long String::value() const { return ( len() ? atol( data->string ) : 0 ); } #if 0 void String::each( void (String::*action)( void* ), void* parameters ) { (this->*action)(param); } int String::find(void *test) { return ( *this == (String&)test ); } #endif