#include <SubString.h>
Collaboration diagram for SubString:
Public Member Functions | |
SubString (String &s, const size_t start, const size_t len) throw (std::out_of_range) | |
This constructor initializes the SubString object with a reference to a String object, a start index for the SubString section and a length. | |
operator String () const | |
User defined type conversion between SubString and String. | |
size_t | getRefCnt () |
size_t | length () |
String | operator+ (const char *Cstr) |
String = SubString + Cstr. | |
String | operator+ (const SubString &sub) |
String = SubString + SubString. | |
String | operator+ (const String &str) |
String = SubString + String. | |
String | operator= (const char *CStr) |
operator =: This function assigns a C character string to a SubString. | |
String | operator= (String &str) |
operator =: Assign a String to a SubString. | |
String | operator= (const SubString &sub) |
operator = (SubStr &) | |
bool | operator== (const char *Cstr) |
bool | operator== (String &s) |
bool | operator== (SubString subStr) |
bool | operator!= (const char *Cstr) |
bool | operator!= (String &s) |
bool | operator!= (SubString subStr) |
bool | operator<= (const char *Cstr) |
bool | operator<= (String &s) |
bool | operator<= (SubString subStr) |
bool | operator>= (const char *Cstr) |
bool | operator>= (String &s) |
bool | operator>= (SubString subStr) |
bool | operator< (const char *Cstr) |
bool | operator< (String &s) |
bool | operator< (SubString subStr) |
bool | operator> (const char *Cstr) |
bool | operator> (String &s) |
bool | operator> (SubString subStr) |
Private Member Functions | |
void | rangeCheck (String &s, const size_t start, const size_t len) throw (std::out_of_range) |
Check that start and len are within the bounds of the String argument s. | |
int | compareTo (const char *CStr) |
Compare the SubString to a C string (e.g., const char *). | |
int | compareTo (String &s) |
Compare the SubString to a String. | |
int | compareTo (SubString &subStr) |
Compare two SubStrings. | |
void | createCopySpace (size_t start, size_t charsToCopy) |
A SubString defines a region in a String. | |
String | string () const |
Return the String section defined by the SubString as a String result. | |
Private Attributes | |
RCPtr< SharedData > | value |
SubStrings are usually created by the "()" operator of the String class. As a result, this class and the String class are closely related.
The String class "()" operator takes two numeric arguments, the starting index and the length (String objects follow C/C++ indexing and start at 0).
Examples:
b = a(0,4); -- assignment of SubString to String
a(0, 4) = "0123"; -- assignment of CString to SubString
a(0, 4) = a(4, 4); -- assignment of SubString to SubString
a(0, 4) = b; -- assignment of String to SubStringAlthough a SubString is usually created by the String "()" operator, it can also be created explicitly. For example:
String s = "the lazy dog"; SubString t(s, 9, 3);
t = "golden"; std::cout << (const char *)s << std::endl;Note that a SubString is a reference to a String. So the assignment to the SubString alters the String. The example above will write "the lazy golden" to std::cout.
The SubString class suports relational operators. This is faster than converting the SubString to a String and performing the relational operation on String operands.
The SubString class does not support an argumentless constructor. This assures that all SubString objects are properly initialized with a String and a range (start index and length). The starting index and length are checked in the constructor to assure that they are within the bounds of the String argument. If they are not, an
std::out_of_range
exception will be thrown.There is no type cast supported for SubString to
const char *
although it might be nice to be able to do the following
String a = "morgan dreams of being fat"; const char *sleep = a(0, 13); // Not supported!Unfortunately, there is no practical way to implement this. The right-hand-side operation
a(0, 13)
creates a compiler generated String temporary. This temporary will be deallocated after the statement containing the assignment. If the memory for the temporary were referenced from theconst char *
, theconst char *
pointer would point to deallocated memory.There are some corner cases that I could not figure out how to protect against. For example, it is possible to create a SubString object that references a deallocated string. This is shown in the function
makeSubString
below:
// // Don't do this! // This function will result in a SubString that references // a String which has been deallocated. // SubString makeSubString(const char *Cstr, size_t start, size_t len) { String s( Cstr ); SubString t(s, start, len); return t; // The String "s" will be deallocated on exit }For this function to work, the SubString constructor would have to increment the reference count of the String, so that the String would not be deallocated on exit (when its reference count reaches zero). This could be done if an actual String, rather than a pointer to a String were used in the SubString shared data.
Implementing the SubString in this way break the functionality of the SubString object. Consider the code below:
String a = "12345678"; a(3,0) = "abcd";If the SubString shared data contained a String, rather than a pointer to a string, the constructor for the SubString would increment the reference count for a to 2. This would work well for the
makeSubString
function, but would break the assignment above.If the SubString shared data contained a String, the assignment to this String would result in a unique copy being be made, since the String is shared (e.g., reference count > 1). The C-string "abcd" would be inserted into the String in the SubString shared data (which is now unique). The result will be that "a" is unchanged and the String we have assigned into will be deallocated when the SubString destructor is executed.
In contrast to the String class, only a few SubString functions are inlined. Many SubString functions reference the String class. The String class is defined only as an abstract class here. This is required by the fact that the String class also includes SubString.h.
Definition at line 160 of file SubString.h.
|
This constructor initializes the SubString object with a reference to a String object, a start index for the SubString section and a length. For example:
|
|
Compare two SubStrings. As noted above, we know that the String is initialized in each case, although the Strings might still be null. We also know that the start and length are in range, since this is checked in the constructor. Definition at line 541 of file SubString.C. References value.
00542 { 00543 int result; 00544 const char *pThisCStr = *(value->pStr()); 00545 const char *pRhsCStr = *(subStr.value->pStr()); 00546 00547 // The Strings in both SubStrings are NULL 00548 if (pThisCStr == 0 && pRhsCStr == 0) { 00549 result = 0; 00550 } 00551 else if (pThisCStr != 0 && pRhsCStr == 0) { 00552 result = 1; 00553 } 00554 else if (pThisCStr == 0 && pRhsCStr != 0) { 00555 result = -1; 00556 } 00557 else { 00558 size_t thisLen = value->subStrLen(); 00559 size_t rhsLen = subStr.value->subStrLen(); 00560 size_t compareLen = thisLen; 00561 if (compareLen > rhsLen) { 00562 compareLen = rhsLen; 00563 } 00564 size_t thisStart = value->start(); 00565 size_t rhsStart = subStr.value->start(); 00566 00567 result = strncmp( pThisCStr+thisStart, 00568 pRhsCStr+rhsStart, 00569 compareLen ); 00570 if (result == 0) { 00571 if (thisLen < rhsLen) { 00572 result = -1; 00573 } 00574 else if (thisLen > rhsLen) { 00575 result = 1; 00576 } 00577 } 00578 } 00579 return result; 00580 } // compareTo for SubString |
|
Compare the SubString to a String. The function returns:
Definition at line 524 of file SubString.C. References compareTo().
00525 { 00526 const char *pCStr = s; 00527 return compareTo( pCStr ); 00528 } // compareTo for String |
|
Compare the SubString to a C string (e.g., const char *). The function returns:
Notes: value->pStr() returns a pointer to the String which was used to initialize the SubString. This String pointer is stored as part of the shared data. Since compareTo is called when a SubString operation is being applied, we know that pStr() will is not NULL. However, it IS possible that the string is empty. In this case the String "const char *" operator will return null. If the strings are not the same length, the compareTo function acts as if the shorter string is extended with null characters until both strings are the same length. The compareTo function does not have to check the range of the SubString, since it was checked by the SubString constructor. Definition at line 483 of file SubString.C. References value. Referenced by compareTo(), operator!=(), operator<(), operator<=(), operator==(), operator>(), and operator>=().
00484 { 00485 int result; 00486 const char *pThisCStr = *(value->pStr()); 00487 if (pThisCStr == 0 && CStr == 0) { 00488 result = 0; 00489 } else if (pThisCStr == 0 && CStr != 0) { 00490 result = -1; 00491 } else if (pThisCStr != 0 && CStr == 0) { 00492 result = 1; 00493 } else { // both pThisCStr and CStr are non-NULL 00494 size_t subStrLen = value->subStrLen(); 00495 size_t start = value->start(); 00496 result = strncmp((pThisCStr + start), CStr, subStrLen); 00497 if (result == 0) { 00498 size_t CStrLen = strlen( CStr ); 00499 if (CStrLen > subStrLen) { 00500 result = -1; // ThisCStr < CStr 00501 } 00502 } 00503 } 00504 return result; 00505 } // compareTo for const char * |
|
A SubString defines a region in a String. When an assignment is made to a SubString and the length of the data being assigned is not the same as the SubString length, a copy space must be created. In the case where the length of the data being copied is larger than the SubString length, the area defined by the SubString must be made larger. This extends the length of the string and moves characters above the region to higher indices. In the case where the length of the data being copied is less than the SubString length, the area defined by the SubString must be reduced. This reduces the length of the String and results in moving characters above the copy region to lower indices. This function allows assignment code to simply copy data into the assignment region. Note that both the write() and resize() functions will create an unshared String if the String is shared. Definition at line 172 of file SubString.C. References value. Referenced by operator=().
00173 { 00174 size_t subStrLen = value->subStrLen(); 00175 00176 if (charsToCopy != subStrLen) { 00177 size_t strlen = value->pStr()->strlen(); 00178 if (charsToCopy < subStrLen) { 00179 // The end of the copy region will be start+charsToCopy 00180 // The end of the SubString section is start+subStrLen 00181 size_t dest = start+charsToCopy; 00182 for (size_t i = start+subStrLen; i < strlen; i++, dest++) { 00183 char ch = value->pStr()->read(i); 00184 value->pStr()->write(dest, ch ); 00185 } 00186 size_t shrink = subStrLen - charsToCopy; 00187 size_t newLen = strlen - shrink; 00188 value->pStr()->resize( newLen ); 00189 } 00190 else if (charsToCopy > subStrLen) { 00191 size_t expand = charsToCopy - subStrLen; 00192 size_t newLen = strlen + expand; 00193 value->pStr()->resize( newLen ); 00194 00195 size_t dest = newLen-1; 00196 for (int i = strlen-1; i >= (int)start; i--, dest--) { 00197 char ch = value->pStr()->read(i); 00198 value->pStr()->write(dest, ch ); 00199 } 00200 } 00201 } 00202 } // createCopySpace |
|
Definition at line 208 of file SubString.h. References value. Referenced by SubStringPassByReference(), SubStringPassByValue(), subStrRefCnt(), and test_substr_func_valarg().
00208 { return value->getRefCnt(); } |
|
Definition at line 210 of file SubString.h. References value.
00210 { return value->subStrLen(); } |
|
User defined type conversion between SubString and String. For example
|
|
Definition at line 227 of file SubString.h. References compareTo().
00227 { return (compareTo(subStr) != 0); } |
|
Definition at line 226 of file SubString.h. References compareTo().
00226 { return (compareTo( s ) != 0); } |
|
Definition at line 225 of file SubString.h. References compareTo().
00225 { return (compareTo( Cstr ) != 0); } |
|
Definition at line 232 of file SubString.C.
|
|
String = SubString + SubString.
Definition at line 220 of file SubString.C.
|
|
String = SubString + Cstr.
Definition at line 207 of file SubString.C.
00208 { 00209 String result = *this; 00210 if (Cstr != 0) { 00211 result += Cstr; 00212 } 00213 return result; 00214 } |
|
Definition at line 239 of file SubString.h. References compareTo().
00239 { return (compareTo(subStr) < 0); } |
|
Definition at line 238 of file SubString.h. References compareTo().
00238 { return (compareTo( s ) < 0); } |
|
Definition at line 237 of file SubString.h. References compareTo().
00237 { return (compareTo( Cstr ) < 0); } |
|
Definition at line 231 of file SubString.h. References compareTo().
00231 { return (compareTo(subStr) <= 0); } |
|
Definition at line 230 of file SubString.h. References compareTo().
00230 { return (compareTo( s ) <= 0); } |
|
Definition at line 229 of file SubString.h. References compareTo().
00229 { return (compareTo( Cstr ) <= 0); } |
|
operator = (SubStr &) For example:
|
|
operator =: Assign a String to a SubString. For example:
|
|
operator =: This function assigns a C character string to a SubString. For example:
There are three cases that are dealt with in this assignment:
As a result of the limitations imposed by the SubString constructor, a SubString will always be initialized with a String and the start and length will always be within bounds of that String. Definition at line 323 of file SubString.C. References createCopySpace(), and value.
00324 { 00325 size_t charsToCopy; 00326 00327 if (Cstr && (charsToCopy = ::strlen( Cstr)) > 0) { 00328 size_t start = value->start(); 00329 00330 // create a copy region that is the correct size 00331 createCopySpace( start, charsToCopy ); 00332 00333 size_t cnt = 0; 00334 for (size_t i = start; i < start + charsToCopy; i++, cnt++) { 00335 value->pStr()->write(i, Cstr[ cnt ] ); 00336 } 00337 } 00338 00339 // 00340 // C/C++ allows chained assignment, so one can do something like 00341 // 00342 // String a = b(2,4) = "abcd"; 00343 // 00344 // So the string that results from the substring assignment should 00345 // be returned. 00346 // 00347 String retStr( *(value->pStr()) ); 00348 00349 return retStr; 00350 } // operator = (Cstr) |
|
Definition at line 223 of file SubString.h. References compareTo().
00223 { return (compareTo(subStr) == 0); } |
|
Definition at line 222 of file SubString.h. References compareTo().
00222 { return (compareTo( s ) == 0); } |
|
Definition at line 221 of file SubString.h. References compareTo().
00221 { return (compareTo( Cstr ) == 0); } |
|
Definition at line 243 of file SubString.h. References compareTo().
00243 { return (compareTo(subStr) > 0); } |
|
Definition at line 242 of file SubString.h. References compareTo().
00242 { return (compareTo( s ) > 0); } |
|
Definition at line 241 of file SubString.h. References compareTo().
00241 { return (compareTo( Cstr ) > 0); } |
|
Definition at line 235 of file SubString.h. References compareTo().
00235 { return (compareTo(subStr) >= 0); } |
|
Definition at line 234 of file SubString.h. References compareTo().
00234 { return (compareTo( s ) >= 0); } |
|
Definition at line 233 of file SubString.h. References compareTo().
00233 { return (compareTo( Cstr ) >= 0); } |
|
Check that start and len are within the bounds of the String argument s.
Definition at line 53 of file SubString.C.
00055 { 00056 char *errMsg = 0; 00057 bool rangeError = false; 00058 size_t sLen = s.strlen(); 00059 if (start >= sLen) { 00060 errMsg = "SubString: start >= String length"; 00061 rangeError = true; 00062 } 00063 else if (start + len > sLen) { 00064 errMsg = "SubString: start + len >= String length"; 00065 rangeError = true; 00066 } 00067 00068 if (rangeError) { 00069 throw std::out_of_range( errMsg ); 00070 } 00071 } // rangeCheck |
|
Return the String section defined by the SubString as a String result. A SubString object consists of a String and a range (e.g., start index and length) which defines a string section. In a sense, a SubString object is intent, not action. The string() function performs the action by sectioning the SubString into a String. No bounds check is made here (for example, to assure that subStrEnd is less than sLen) because this check is made when the SubString is constructed. Definition at line 430 of file SubString.C. References value. Referenced by operator String(), and operator=().
00431 { 00432 String retVal; 00433 00434 if (value->pStr()) { 00435 size_t sLen = value->pStr()->strlen(); 00436 size_t start = value->start(); 00437 size_t subStrLen = value->subStrLen(); 00438 size_t subStrEnd = start + subStrLen; 00439 00440 for (size_t i = start; i < subStrEnd; i++) { 00441 retVal += (*(value->pStr()))[i]; 00442 } 00443 00444 } 00445 return retVal; 00446 } // SubString::string |
|
Definition at line 191 of file SubString.h. Referenced by compareTo(), createCopySpace(), getRefCnt(), length(), operator=(), and string(). |