Main Page | Namespace List | Class Hierarchy | Compound List | File List | Compound Members | File Members

String Class Reference

This class is a container for strings composed of 8-bit ASCII characters. More...

#include <String.h>

Inheritance diagram for String:

Inheritance graph
[legend]
Collaboration diagram for String:

Collaboration graph
[legend]
List of all members.

Public Member Functions

 String ()
 String (const char ch)
 String constructor with a character argument.

 String (const char *initCstr)
 String constructor with a C-string argument.

 String (const String &Str)
 String copy constructor.

SubString operator() (const size_t start, const size_t len)
 Sub-string operator: this function supports the left hand side (l-value) form for the sub-string operation.

size_t strlen ()
 strlen does not include the null at the end of the string

size_t getRefCnt ()
 Return the reference count.

int compareTo (const char *Cstr)
 Compare the character string in "this" object with the argument Cstr.

Stringresize (const size_t new_size)
 Set the string length of the String to newSize.

 operator const char * () const
 This operator allows the assignment of a String to a const char .

Stringoperator= (const char ch)
 Assign a character to a String.

Stringoperator= (const char *Cstr)
 Assign a C-string to a String.

Stringoperator= (const SubString &sub)
 Assign a SubString to a String.

String operator+ (const char *Cstr)
 operator +: String("abcd") + " efgh"

String operator+ (String &s)
 operator +: String("abcd") + String(" efgh")

String operator+ (const char ch)
 operator+ : String + ch

String operator+ (const SubString &sub)
 Append a String and a SubString.

Stringoperator+= (const char *Cstr)
 Concatenate a C string on to the end of the String object.

Stringoperator+= (String &s)
 Concatenate two String objects.

Stringoperator+= (const char ch)
 Append a character to the end of "this" string.

bool operator== (const char *Cstr)
bool operator== (String &s)
bool operator!= (const char *Cstr)
bool operator!= (String &s)
bool operator<= (const char *Cstr)
bool operator<= (String &s)
bool operator>= (const char *Cstr)
bool operator>= (String &s)
bool operator< (const char *Cstr)
bool operator< (String &s)
bool operator> (const char *Cstr)
bool operator> (String &s)

Protected Member Functions

void init (const char *initCstr)
 Initialize the underlying data structure for a String container from a C string.

size_t length ()
 Return the number of data elements (characters) consumed by the String.

void appendCString (const char *CStr)
 Append a C string at the end of the character string stored in the String object.

void appendString (String &Str)
 Append the characters from "s" onto the end of the characters stored in the String object.

void newEmptyString ()
 Make "this" into an empty String.

void newSharedData ()
 Allocate a new SharedData object which contains a copy of the old data.

int Cstrcmp (const char *s1, const char *s2)
 Compare two C strings pointed to by const char * pointers.

int compareTo (String &s)
 Compare two strings for equality.


Private Attributes

friend SubString

Detailed Description

This class is a container for strings composed of 8-bit ASCII characters.

This class uses reference counts and copy-on-write to improve memory use and, perhaps, performance.

This is the version 3.0 of this class. This class was originally modeled after the Rogue Wave RWCString class (using the documentation available on the Rogue Wave web site).

Why Yet Another String Container

Although I like the Rogue Wave class and the RWCString class in particular, I don't use the Rogue Wave classes in the software I write for Bear Products International. There are several reasons for this. I did not want to pay the Rogue Wave license fees, which are high for a Cave based software developer. Nor did I want to force anyone who licenses my software to also Rogue Wave license fees (sorry guys). I also wanted software that was as transparent as possible. Rogue Wave classes tend to be incompletely documented and it is not always easy to fully understand the way a particular class functions.

Rogue Wave is not the only alternative when it comes to reference counted String containers. The Microsoft Foundation Classes include a string container and some versions of the STL template library implement the STL string container as a reference counted object. Each of these alternatives has some draw back. Microsoft Foundation Class code is not portable outside of Windoz. Also, with the new .NET framework, it seems possible that Microsoft would at some point phase out the Foundation Classes. The reference counted versions of the STL string container that I'm aware of also incur a license fee, although not as steep as Rogue Wave (the Dinkumware STL library is one example of an STL implementation that includes reference counted strings).

Finally, to quote Bjarne Staroustrup

Writing string classes has great educational value...
Chapter 20, The C++ Programming Language, third edition Bjarne Staroustrup

The String class implements a sub-string (string section) operation which results in a SubString object. As a result, the String and SubString classes are closely related.

This class comes with a set of regression tests. I recommend that you run these regression tests with your compiler, on your system. Not all compilers implement C++ in the same way.

Author:
Ian Kaplan www.bearcave.com

Definition at line 99 of file String.h.


Constructor & Destructor Documentation

String::String  )  [inline]
 

Definition at line 182 of file String.h.

References CharArray.

00182 : CharArray() {}

String::String const char  ch  )  [inline]
 

String constructor with a character argument.

Definition at line 186 of file String.h.

References CharArray, and RCArray< char >::value.

00186                               : CharArray()
00187 { 
00188   if (ch != '\0') {
00189     value->data.append( ch );
00190     value->data.append('\0');
00191   }
00192 }

String::String const char *  initCstr  )  [inline]
 

String constructor with a C-string argument.

Definition at line 196 of file String.h.

References CharArray, and init().

00196                                      : CharArray()
00197 {
00198   init( initCstr );
00199 }

String::String const String Str  )  [inline]
 

String copy constructor.

Definition at line 205 of file String.h.

References CharArray, and RCArray< char >::value.

00205                                   : CharArray()
00206 {
00207   value = Str.value;
00208 }


Member Function Documentation

void String::appendCString const char *  CStr  )  [protected]
 

Append a C string at the end of the character string stored in the String object.

The character data stored in a String object should be terminated by a null character (''). The null terminator for the "this" string will be overwritten by the first character of CStr.

Reference count and allocation issues should be taken care of by the code that calls this function.

Definition at line 67 of file String.C.

References length(), and RCArray< char >::value.

Referenced by operator+(), and operator+=().

00068 {
00069   if (CStr != 0) {
00070     size_t len = length();
00071     if (len > 0) {
00072       // if there is a null at the end of the string
00073       // (which there should be) write over it.
00074       if (value->data[len-1] == '\0') {
00075         value->data[len-1] = *CStr++;
00076       }
00077     }
00078     while (*CStr) {
00079       value->data.append( *CStr++ );
00080     }
00081     value->data.append('\0');
00082   }
00083 } // appendCString

void String::appendString String s  )  [protected]
 

Append the characters from "s" onto the end of the characters stored in the String object.

Note that when String 's' is appended to the String object the null that terminates 's' should be appended as well.

Reference count and allocation issues should be taken care of by the code that calls this function.

Definition at line 97 of file String.C.

References length(), and RCArray< char >::value.

Referenced by operator+(), and operator+=().

00098 {
00099   size_t i = 0;
00100   size_t len = s.length();
00101   size_t thisLen = length(); // length of "this" String
00102   
00103   if (thisLen > 0 && len > 0) {
00104     // write over the null character
00105     if (value->data[thisLen-1] == '\0') {
00106       value->data[thisLen-1] = s.value->data[i];
00107       i++;
00108     }
00109   } // if
00110   while (i < len) {
00111     char ch = s.value->data[i];
00112     value->data.append( ch );
00113     i++;
00114   } // while
00115 } // appendString

int String::compareTo const char *  Cstr  )  [inline]
 

Compare the character string in "this" object with the argument Cstr.

if (this < Cstr) return -1; if (this == Cstr) return 0; if (this > Cstr) return 1;

Definition at line 324 of file String.h.

References Cstrcmp().

00325 {
00326   const char *pThisCStr = *this;
00327   
00328   return Cstrcmp( pThisCStr, Cstr );
00329 }

int String::compareTo String s  )  [protected]
 

Compare two strings for equality.

Definition at line 122 of file String.C.

References Cstrcmp(), length(), and RCArray< char >::value.

Referenced by operator!=(), operator<(), operator<=(), operator==(), operator>(), and operator>=().

00123 {
00124   if (length() == 0 && s.length() == 0) {
00125     // Both String objects contain no data and so are
00126     // equal
00127     return 0;
00128   }
00129 
00130   if (value == s.value) {
00131       // The two String objects point to the same shared data
00132       return 0;
00133   }
00134 
00135   const char *pThisCStr = *this;
00136   const char *Cstr = s;
00137 
00138   return Cstrcmp( pThisCStr, Cstr );
00139 } // compareTo

int String::Cstrcmp const char *  pThisCStr,
const char *  Cstr
[protected]
 

Compare two C strings pointed to by const char * pointers.

Return 1 if *pThisCStr is greater than *Cstr, -1 if pThisCstr is less than *Cstr and 0 if *pThisCstr is equal to *Cstr.

Definition at line 204 of file String.C.

Referenced by compareTo().

00205 {
00206   int rslt;
00207 
00208   if (pThisCStr == 0) {
00209     if (Cstr == 0)
00210       rslt = 0; // both this and CStr are null
00211     else {
00212       if (::strlen( Cstr ) == 0)
00213         rslt = 0;  // compare to an empty string ("")
00214       else
00215         rslt = -1; // this < Cstr
00216     }
00217   }
00218   else { // pThisCStr != 0
00219     if (Cstr == 0)
00220       rslt = 1; // this > Cstr
00221     else // pThis != 0 && Cstr != 0
00222       rslt = strcmp(pThisCStr, Cstr );
00223   }
00224 
00225   return rslt;
00226 }  // Cstrcmp

size_t String::getRefCnt  )  [inline]
 

Return the reference count.

This useful primarily for debug and verification. In the perfect world of bug free software the reference count could be entirely hidden.

Reimplemented from RCArray< char >.

Definition at line 229 of file String.h.

References RCArray< char >::getRefCnt().

Referenced by checkRefCnt(), checkRefCntVal(), subStrAssign(), subStrRefCnt(), subStrSection(), test_arrayop(), test_assign(), test_constructors(), test_insert(), test_plus(), test_plus_equal(), and test_substring().

00230 {
00231   return CharArray::getRefCnt();
00232 }

void String::init const char *  initCstr  )  [protected]
 

Initialize the underlying data structure for a String container from a C string.

Definition at line 41 of file String.C.

References RCArray< char >::value.

Referenced by String().

00042 {
00043   if (initCstr != 0) {
00044     char ch;
00045     for (ch = *initCstr; ch != '\0'; ch = *initCstr) {
00046       value->data.append( ch );
00047       initCstr++;
00048     }
00049     value->data.append( ch );
00050   }
00051 }

size_t String::length void   )  [inline, protected]
 

Return the number of data elements (characters) consumed by the String.

This includes the null character. So length() == strlen() + 1

Definition at line 217 of file String.h.

References RCArray< char >::length().

Referenced by appendCString(), appendString(), compareTo(), and resize().

00218 {
00219   return CharArray::length();
00220 }

void String::newEmptyString  )  [protected]
 

Make "this" into an empty String.

If "this" is shared, allocate a new SharedData object. If "this" is not shared, set the length to zero.

Definition at line 278 of file String.C.

References RCArray< char >::value.

Referenced by operator=(), and resize().

00279 {
00280   if (value->isShared()) {
00281     value = new SharedData();
00282   }
00283   else {
00284     value->data.set_size(0);
00285   }
00286 } // newEmptyString

void String::newSharedData  )  [inline, protected]
 

Allocate a new SharedData object which contains a copy of the old data.

Note that this code relies on the fact that value is a "smart pointer" which will decrement the reference count and deallocate the space if the reference count is zero.

Definition at line 306 of file String.h.

References RCArray< char >::value.

Referenced by operator+(), operator+=(), and resize().

00307 {
00308   value = new SharedData( value->data );
00309 }

String::operator const char *  )  const
 

This operator allows the assignment of a String to a const char .

For example, in the code below a is assigned to pStr in the code below:

String a("wierd operator"); const char *pStr;

pStr = a;

The compiler fills in the cast (e.g., const char *), it does not have to be explicit. That is we don't have to write

pStr = (const char *)a; -- unnecessary cast

A C++ compiler should issue an error if an attempt is made to assign a String object to a "char *". The data pointed to by the address returned by this operator should never be changed since it belongs to the String object.

Definition at line 256 of file String.C.

References RCArray< char >::value.

00257 {
00258   const char *pCstr = "";
00259   size_t len = value->data.length();
00260 
00261   if (len > 0) {
00262     if (value->data[len-1] != '\0') {
00263       // then add a NULL terminator
00264       value->data.append('\0');
00265     }
00266     pCstr = value->data.getData();
00267   }
00268 
00269   return pCstr;
00270 } // operator const char *

bool String::operator!= String s  )  [inline]
 

Definition at line 155 of file String.h.

References compareTo().

00155 { return (compareTo( s ) != 0); }

bool String::operator!= const char *  Cstr  )  [inline]
 

Definition at line 154 of file String.h.

References compareTo().

00154 { return (compareTo( Cstr ) != 0); }

SubString String::operator() const size_t  start,
const size_t  len
[inline]
 

Sub-string operator: this function supports the left hand side (l-value) form for the sub-string operation.

For example:

String a("abcdefghijkl");

a(4, 5) = "12345";

The String object "a" now contains "abcd12345jkl"

This function returns a SubString object. The SubString object supports the assignment operator, which will assign the C-string to a

Definition at line 255 of file String.h.

00256 {
00257   SubString subStr( *this, start, len );
00258 
00259   return subStr;
00260 }

String String::operator+ const SubString sub  )  [inline]
 

Append a String and a SubString.

String a = "abcde"; // indices: 01234567 String b = "123 5678"; String c = a + b(3,4); // result will be "abcde 567"

Definition at line 275 of file String.h.

00276 {
00277   String section = sub;
00278   String result = *this + section;
00279   return result;
00280 } // operator +

String String::operator+ const char  ch  )  [inline]
 

operator+ : String + ch

Append a String and a character.

Definition at line 410 of file String.h.

00411 {
00412   char buf[4];
00413 
00414   buf[0] = ch;
00415   buf[1] = '\0';
00416 
00417   String tmp;
00418 
00419   tmp = *this + buf;  // call String + Cstr
00420 
00421   return tmp;
00422 } // operator +

String String::operator+ String s  )  [inline]
 

operator +: String("abcd") + String(" efgh")

Definition at line 389 of file String.h.

References appendString(), and newSharedData().

00390 {
00391   String tmp;
00392   
00393   tmp.newSharedData();
00394 
00395   tmp.appendString( *this );
00396   tmp.appendString( s );
00397   
00398   return tmp;
00399 } // operator +

String String::operator+ const char *  Cstr  )  [inline]
 

operator +: String("abcd") + " efgh"

Create a new String object which contains the concatenation of the two operand strings (self and the argument "s"). The reference count for the new String object will be zero. If it is assigned then it will be incremented.

Example:

String a("abcd"); String b = a + " efgh";

When these statements are executed String 'a' will contain "abcd" and String 'b' will contain "abcd efgh". The reference count for both String objects will be 1.

Definition at line 373 of file String.h.

References appendCString(), and appendString().

00374 {
00375   String tmp;
00376   
00377   tmp.appendString( *this );
00378   tmp.appendCString( Cstr );
00379 
00380   return tmp;
00381 } // operator +

String & String::operator+= const char  ch  )  [inline]
 

Append a character to the end of "this" string.

Definition at line 338 of file String.h.

00339 {
00340   char buf[4];
00341 
00342   buf[0] = ch;
00343   buf[1] = '\0';
00344 
00345   *this += buf;   // call String += Cstr
00346   return *this;
00347 } // operator +=

String & String::operator+= String s  ) 
 

Concatenate two String objects.

Definition at line 375 of file String.C.

References appendString(), newSharedData(), and RCArray< char >::value.

00376 {
00377   if (s.value->data.length() > 0) {
00378     if (value->isShared()) {
00379        newSharedData();
00380     }
00381 
00382     // If there is a null character, delete it so we don't
00383     // append after the null.
00384     size_t len = value->data.length();
00385     if (len > 0 && value->data[len-1] == '\0') {
00386       value->data.remove();
00387     }
00388 
00389     appendString( s );
00390   }
00391   return *this;
00392 } // operator +=

String & String::operator+= const char *  Cstr  ) 
 

Concatenate a C string on to the end of the String object.

For example:

String s("abcd ");

s += "efgh";

will result in "s" containing "abcd efgh".

Definition at line 352 of file String.C.

References appendCString(), newSharedData(), and RCArray< char >::value.

00353 {
00354   if (value->isShared()) {
00355     newSharedData();
00356   }
00357 
00358   // If there is a null character, delete it so we don't
00359   // append after the null.
00360   size_t len = value->data.length();
00361   if (len > 0 && value->data[len-1] == '\0')
00362     value->data.remove();
00363 
00364   appendCString( Cstr );
00365 
00366   return *this;
00367 } // operator +=

bool String::operator< String s  )  [inline]
 

Definition at line 161 of file String.h.

References compareTo().

00161 { return (compareTo( s ) < 0); }

bool String::operator< const char *  Cstr  )  [inline]
 

Definition at line 160 of file String.h.

References compareTo().

00160 { return (compareTo( Cstr ) < 0); }

bool String::operator<= String s  )  [inline]
 

Definition at line 157 of file String.h.

References compareTo().

00157 { return (compareTo( s ) <= 0); }

bool String::operator<= const char *  Cstr  )  [inline]
 

Definition at line 156 of file String.h.

References compareTo().

00156 { return (compareTo( Cstr ) <= 0); }

String & String::operator= const SubString sub  )  [inline]
 

Assign a SubString to a String.

For example:

String a = "lazy dog"; String b = a(5, 3);

Definition at line 292 of file String.h.

00293 {
00294   *this = (String)sub;
00295   return *this;
00296 } // operator =

String & String::operator= const char *  Cstr  ) 
 

Assign a C-string to a String.

The String(C-string) constructor could be used for this. However, using this default generates code which is more inefficient. The write() function is used here since it properly handles the String shared data.

If a null string is assigned to a String, the result will be the same as if an empty String were assigned. For example:

char *pCstr = 0; String a = "fubar"; a = pCstr; // same as if "" were assigned

Definition at line 323 of file String.C.

References newEmptyString(), and RCArray< char >::value.

00324 {
00325   newEmptyString();
00326   if (Cstr != 0) {
00327     char ch;
00328     for (ch = *Cstr; ch != '\0'; ch = *Cstr) {
00329       value->data.append(ch);
00330       Cstr++;
00331     }
00332     value->data.append(ch);
00333   }
00334   return *this;
00335 } // operator= (String = C-string)

String & String::operator= const char  ch  ) 
 

Assign a character to a String.

Definition at line 293 of file String.C.

References newEmptyString(), and RCArray< char >::value.

00294 {
00295   newEmptyString();
00296   if (ch != '\0') {
00297     value->data.append( ch );
00298     value->data.append('\0');
00299   }
00300   return *this;
00301 } // operator= (String = char)

bool String::operator== String s  )  [inline]
 

Definition at line 153 of file String.h.

References compareTo().

00153 { return (compareTo( s ) == 0); }

bool String::operator== const char *  Cstr  )  [inline]
 

Definition at line 152 of file String.h.

References compareTo().

00152 { return (compareTo( Cstr ) == 0); }

bool String::operator> String s  )  [inline]
 

Definition at line 163 of file String.h.

References compareTo().

00163 { return (compareTo( s ) > 0); }

bool String::operator> const char *  Cstr  )  [inline]
 

Definition at line 162 of file String.h.

References compareTo().

00162 { return (compareTo( Cstr ) > 0); }

bool String::operator>= String s  )  [inline]
 

Definition at line 159 of file String.h.

References compareTo().

00159 { return (compareTo( s ) >= 0); }

bool String::operator>= const char *  Cstr  )  [inline]
 

Definition at line 158 of file String.h.

References compareTo().

00158 { return (compareTo( Cstr ) >= 0); }

String & String::resize const size_t  newSize  ) 
 

Set the string length of the String to newSize.

This will be the size returned by String::strlen(). So the actual amount of data allocated will be newSize+1 to account for the null character, assuming that newSize > 0. If newSize == 0, strlen() will be zero and the number of data elements will be zero.

The private function length() will return new_size + 1, since the String data is terminated by a null character. If the String is expanded, the String will be padded with spaces.

If the reference count of the String object is greater than one, a unique copy will be made when it is resized, since other copies should be unaffected.

Definition at line 158 of file String.C.

References length(), newEmptyString(), newSharedData(), and RCArray< char >::value.

Referenced by test_resize().

00159 {
00160   if (newSize == 0) {
00161     newEmptyString();
00162   }
00163   else { // newSize > 0
00164     size_t new_len = newSize + 1;
00165     size_t old_len = length();
00166 
00167     if (value->isShared()) {
00168       if (new_len >= old_len) {
00169         // this will copy the data into a new shared data object
00170         newSharedData();
00171         value->data.set_size( new_len );
00172       }
00173       else { // new_len < old_len
00174         RCPtr<SharedData> new_value = new SharedData();
00175         for (size_t i = 0; i < newSize; i++) {
00176           new_value->data.append( value->data[i] );
00177         }
00178         new_value->data.append('\0');
00179         // note: smart pointer assignment
00180         value = new_value;
00181       }
00182     }
00183     else {
00184       value->data.set_size( new_len );
00185     }
00186 
00187     for (size_t i = old_len-1; i < new_len-1; i++) {
00188       value->data[i] = ' ';
00189     }
00190     value->data[ new_len-1 ] = '\0';
00191   }
00192   return *this;
00193 } // resize

size_t String::strlen  )  [inline]
 

strlen does not include the null at the end of the string

Definition at line 433 of file String.h.

References RCArray< char >::value.

Referenced by SubString::operator=(), subStrAssign(), subStrSection(), test_constructors(), test_resize(), and test_substring().

00434 {
00435   int len = value->data.length(); 
00436   if (len > 0 && value->data[len-1] == '\0')
00437     len--;
00438   return len;
00439 }


Member Data Documentation

friend String::SubString [private]
 

Definition at line 103 of file String.h.


The documentation for this class was generated from the following files:
Generated on Mon Sep 22 20:23:03 2003 by doxygen 1.3.3