//[c]string.cpp - the String and StringBuffer classes //[c] //[of]: Includes //[c] #include #include #include //[c] #include "string.h" //[cf] //[of]: Constants and Macros //[c] #define MEMORY_BUFFER_DEF_SIZE 2048 #define STRING_BUFFER_DEF_SIZE 16384 //[c] #define COUNT_TYPE int #define HEADER sizeof(COUNT_TYPE) #define COUNT(x) (*((COUNT_TYPE*)(x-HEADER))) #define ALLOC(ptr, len) \ ptr = new char[HEADER+len+1]+HEADER; \ COUNT(ptr) = 1; #define RELEASE(p) if( p!=theNullCharPtr && --COUNT(p)==0 ) delete (void*)(p-HEADER); //[cf] //[of]: Globals //[c] const char* theNullCharPtr = ""; String theEmptyString; //[cf] //[c] //[of]: Class RawString //[c]Allows the creation of a string without copying the content //[c] class RawString : public String { public: RawString(const char* s) { p = s; } }; //[cf] //[of]: Class String //[c] //[c] The character string class //[c] //[l]: Declaration of String:string.h#string //[c] //[c]Constructors - Destructor //[c] //[of]: String() //[c]Construct an empty string //[c] String::String() { p = theNullCharPtr; } //[cf] //[of]: String(str) //[c]Construct a string from a raw buffer //[c] String::String(const char* s) { int len = strlen(s); char* buf; ALLOC(buf, len) strcpy(buf, s); p = buf; } //[cf] //[of]: String(str, len) //[c]Construct a string from a raw buffer //[c] String::String(const char* s, int len) { char* buf; ALLOC(buf, len) memcpy(buf, s, len); buf[len] = 0; p = buf; } //[cf] //[of]: String(const String&) //[c]Construct a string from another string //[c] String::String(const String& s) { p = s.p; if( p!=theNullCharPtr ) COUNT(p)++; } //[cf] //[of]: String(const SubString& s) //[c]Construct a string from a substring //[c] String::String(const SubString& s) { int len = s.end-s.start; char* buf; ALLOC(buf, len) memcpy(buf, s.start, len); buf[len] = 0; p = buf; } //[cf] //[of]: String(const char* s1, const char* s2) //[c]Construct a string with two raw buffers //[c] String::String(const char* s1, const char* s2) { int l1 = strlen(s1); int l2 = strlen(s2); char* buf; ALLOC(buf, l1+l2) memcpy(buf, s1, l1); memcpy(buf+l1, s2, l2); buf[l1+l2] = 0; p = buf; } //[cf] //[c] //[of]: ~String() //[c]Free the memory allocated by the string //[c] String::~String() { RELEASE(p) } //[cf] //[c] //[c]Copying //[c] //[of]: operator=(const String& s) //[c]Assign a new string //[c] void String::operator=(const String& s) { // already assign to this string if( p==s.p ) return; // release the old string RELEASE(p) p = s.p; if( p!=theNullCharPtr ) COUNT(p)++; } //[cf] //[of]: operator=(const char* s) //[c]Assign a new string //[c] void String::operator=(const char* s) { // release the old string RELEASE(p) // copy the string in a new buffer int len = strlen(s); char* buf; ALLOC(buf, len); strcpy(buf, s); p = buf; } //[cf] //[c] //[c]Testing //[c] //[of]: startWith(const char* s) //[c]Test if the string starts with the argument //[c] bool String::startWith(const char* s) const { return strncmp(p, s, strlen(s))==0; } //[cf] //[of]: endWith(const char* s) //[c]Tests if the string ends with the argument //[c] bool String::endWith(const char* s) const { int l2 = strlen(s); int l1 = len(); if( l2>l1 ) return false; return strcmp(p+l1-l2, s)==0; } //[cf] //[c] //[c]Accessing //[c] //[of]: empty() //[c]Assign to the empty string //[c] void String::empty() { if( isEmpty() ) return; RELEASE(p); p = theNullCharPtr; } //[cf] //[c] //[of]: hash() //[c]Returns the hash code of the string //[c] int String::hash() const { const char* q = p; int sum = 12345; while( *q ) sum = (sum<<1) ^ *q++; return sum; } //[cf] //[of]: firstOccurrence(char) //[c]Returns the first occurence of a char, -1 if not found //[c] int String::firstOccurrence(char c) const { const char* q = p; char d = *q++; while( d ) { if( d==c ) return q-p-1; d = *q++; } // not found return -1; } //[cf] //[of]: lastOccurrence(char) //[c]Returns the last occurence of a char, -1 if not found //[c] int String::lastOccurrence(char c) const { const char* q = p+len()-1; while( q>=p ) { if( *q==c ) return q-p; q--; } // not found return -1; } //[cf] //[of]: left(int l) //[c]Return the first char //[c] String String::left(int l) const { return SubString(p, l); } //[cf] //[of]: right(int l) //[c]Return the last characters //[c] //[c] If the l is over the length of the string, all the string is returned. //[c] String String::right(int l) const { int offset = len()-l; return p+offset; } //[cf] //[of]: noLeft(int offset) //[c]Return a copy of the string without the first characters //[c] String String::noLeft(int offset) const { return p+offset; } //[cf] //[of]: operator+(const char* s) //[c]Concatenate two strings //[c] String String::operator+(const char* s) const { return String(p, s); } //[cf] //[c] //[c]Converting //[c] //[of]: upper() //[c]Converts the string to an uppercase string //[c] String String::upper() const { int len = strlen(p); char* buf; ALLOC(buf, len) const char* src = p; char* dst = buf; char c; do { c=*src++; *dst++=toupper(c); } while( c ); return RawString(buf); } //[cf] //[of]: lower() //[c]Converts the string to an uppercase string //[c] String String::lower() const { int len = strlen(p); char* buf; ALLOC(buf, len) const char* src = p; char* dst = buf; char c; do { c=*src++; *dst++=tolower(c); } while( c ); return RawString(buf); } //[cf] //[of]: toInteger() //[c]Converts the string to an integer //[c] int String::toInteger() const { return atoi(p); } //[cf] //[of]: hexaToInteger() //[c]Converts an hexadecimal string to an integer //[c] int String::hexaToInteger() const { int value = 0; const char* q = p; char c = *q++; while( c ) { value = value<<4; if( '0'<=c && c<'9'+1 ) value += c-'0'; else if( 'a'<=c && c<'f'+1 ) value += c-'a'+10; else if( 'A'<=c && c<'F'+1 ) value += c-'A'+10; else break; c = *q++; } return value; } //[cf] //[cf] //[of]: Class SubString //[c]The sub-string class //[c] //[l]: Declaration of SubString:string.h#sub-string //[c] //[c]Searching //[c] //[of]: firstOccurrence(c) //[c]Returns the first occurence of a char, -1 if not found //[c] int SubString::firstOccurrence(char c) const { const char* q = start; while( q=start ) { if( *q==c ) return q-start; q--; } // not found return -1; } //[cf] //[c] //[c]Testing //[c] //[of]: startWith(const String&) //[c]Tests if the string start with a substring //[c] bool SubString::startWith(const String& s) const { int len = s.len(); int used = end-start; if( len>used ) return false; return strncmp(start, s.chars(), len)==0; } //[cf] //[of]: endWith(const String&) //[c]Tests if the string end with a substring //[c] bool SubString::endWith(const String& s) const { int len = s.len(); int used = end-start; if( len>used ) return false; return strncmp(end-len, s.chars(), len)==0; } //[cf] //[c] //[c]Extracting //[c] //[c] The following methods returns a copy of the selected //[c] part of the sub-string. //[c] //[of]: content() //[c] String SubString::content() const { return String(start, end); } //[cf] //[of]: left(l) //[c] String SubString::left(int l) const { return String(start, l); } //[cf] //[of]: right(l) //[c] String SubString::right(int l) const { return String(end-l, end); } //[cf] //[of]: noLeft(l) //[c] String SubString::noLeft(int l) const { return String(start+l, end); } //[cf] //[c] //[of]: upper() //[c]Converts the string to an uppercase string //[c] String SubString::upper() const { int len = end-start; char* buf; ALLOC(buf, len) const char* src = start; char* dst = buf; buf[len] = 0; while(len-->0) { *dst++=toupper(*src++); } return RawString(buf); } //[cf] //[of]: lower() //[c]Converts the string to an uppercase string //[c] String SubString::lower() const { int len = end-start; char* buf; ALLOC(buf, len) const char* src = start; char* dst = buf; buf[len] = 0; while(len-->0) { *dst++=tolower(*src++); } return RawString(buf); } //[cf] //[c] //[of]: operator+(const String&) //[c]Concatenates two strings //[c] String SubString::operator+(const String& s) const { int l1 = end-start; int l2 = s.len(); char* buf; ALLOC(buf, l1+l2) memcpy(buf, start, l1); memcpy(buf+l1, s.chars(), l2); buf[l1+l2] = 0; return RawString(buf); } //[cf] //[c] //[c]Converting //[c] //[of]: toInteger() //[c]Converts the substring to an integer //[c] int SubString::toInteger() const { int sum = 0; const char* p = start; while( p