You can download all programs as a single tar.gz file from Download String . To get this file, in the web-browser, save this file as 'Text' type.
//***************************************************************** // Copyright policy is GNU/GPL and it is requested that // you include author's name and email on all copies // Author : Al Dev Email: alavoor@yahoo.com //***************************************************************** // To prevent memory leaks - a char class to manage character variables // Always prefer to use string class // instead of char[] or char * // // To compile and test this program do - // g++ String.cpp #include "String.h" //#include <sys/va_list.h> for Format() //#include <sys/varargs.h> for Format() // Global variables .... //String *String::_global_String = NULL; // global var list<String> String::explodeH; String::String() { debug_("In cstr()", "ok"); sval = (char *) my_malloc(sizeof(char)* INITIAL_SIZE); _pString = NULL; } String::String(char *bb) { unsigned long tmpii = strlen(bb); sval = (char *) my_malloc(sizeof(char)* tmpii); strncpy(sval, bb, tmpii); sval[tmpii] = '\0'; //debug_("In cstr(char *bb) bb", bb); debug_("In cstr(char *bb) sval", sval); #ifdef DEBUG //fprintf(stderr, "\nAddress of sval=%x\n", & sval); //fprintf(stderr, "\nAddress of this-pointer=%x\n", this); #endif // DEBUG _pString = NULL; } String::String(int bb) { sval = (char *) my_malloc(NUMBER_LENGTH); // integers 70 digits max sprintf(sval, "%d", bb); debug_("In cstr(int bb) sval", sval); _pString = NULL; } String::String(unsigned long bb) { sval = (char *) my_malloc(NUMBER_LENGTH); // long 70 digits max sprintf(sval, "%lu", bb); debug_("In cstr(unsigned long bb) sval", sval); _pString = NULL; } String::String(long bb) { sval = (char *) my_malloc(NUMBER_LENGTH); // long 70 digits max sprintf(sval, "%ld", bb); debug_("In cstr(long bb) sval", sval); _pString = NULL; } String::String(float bb) { sval = (char *) my_malloc(NUMBER_LENGTH); // float 70 digits max sprintf(sval, "%f", bb); debug_("In cstr(float bb) sval", sval); _pString = NULL; } String::String(double bb) { sval = (char *) my_malloc(NUMBER_LENGTH); // double 70 digits max sprintf(sval, "%f", bb); debug_("In cstr(double bb) sval", sval); _pString = NULL; } // Copy Constructor needed by operator + String::String(const String & rhs) { // Do a deep-copy instead of compiler's default shallow copy copy-cstr debug_("In copy-cstr()", "ok"); unsigned long tmpii = strlen(rhs.sval); sval = (char *) my_malloc(sizeof(char)* tmpii); strncpy(sval, rhs.sval, tmpii); sval[tmpii] = '\0'; _pString = NULL; } // For use by StringBuffer class. Put a dummy // variable for different signature. // StringBuffer class imitates Java's StringBuffer object String::String(int size, bool dummy) { sval = (char *) my_malloc(sizeof(char)* size); debug_("In cstr(int size, bool dummy) sval", sval); #ifdef DEBUG //fprintf(stderr, "\nAddress of sval=%x\n", & sval); //fprintf(stderr, "\nAddress of this-pointer=%x\n", this); #endif // DEBUG _pString = NULL; } String::~String() { debug_("In dstr sval", sval); #ifdef DEBUG //fprintf(stderr, "\nAddress of sval=%x\n", & sval); //fprintf(stderr, "\nAddress of this-pointer=%x\n", this); #endif // DEBUG my_free(sval); //delete [] sval; sval = NULL; delete _pString; _pString = NULL; } inline void String::_allocpString() { // _pString will be deleted in destructor if (!_pString) // if (_pString == NULL) _pString = new String(this->sval); else *_pString = this->sval; } // MUST use pointer-to-pointer **aa, otherwise the argument // is NOT freed !! /* inline void String::_free_glob(String **aa) { debug_("called _free_glob()", "ok" ); if (*aa != NULL) // (*aa != NULL) { debug_("*aa is not null", "ok"); delete *aa; *aa = NULL; } //else debug_("*aa is null", "ok"); //if (*aa == NULL) debug_("*aa set to null", "ok"); } */ // Imitating Java's charAt string function... char String::charAt(int where) { verifyIndex(where); return (sval[where]); } // Imitate Java's getChars function... // The sourceStart specifies the index of the beginning of the substring // and sourceEnd specifies an index that is one past the end of desired // substring. Thus the substring contains characters from sourceStart // through (sourceEnd - 1). The array that will receive the characters // is specified by target. The index within target at which the substring // will be copied is passed in targetStart. Care must be taken to assure // that the target array is large enough to hold the number of characters // in the specified substring. // For e.g. getChars(3, 6, aa, 0) on "ABCDEFGHIJK" gives aa ="DEF" void String::getChars(int sourceStart, int sourceEnd, char target[], int targetStart) { verifyIndex(sourceStart); verifyIndex(sourceEnd); if (sourceEnd >= sourceStart) { strncpy(& target[targetStart], & sval[sourceStart], sourceEnd - sourceStart); target[targetStart + (sourceEnd - sourceStart)] = 0; } else { cerr << "\ngetChars() - SourceEnd is greater than SourceStart!!\n" << endl; exit(1); } } // Imitate Java's getChars string function... // Returns array of characters for the entire string char* String::toCharArray() { return (sval); } // Imitate Java's getBytes string function... // Returns array of characters for the entire string char* String::getBytes() { return (sval); } // Imitate Java's equals string function... bool String::equals(String str2) // See also == operator { return ( _equalto(str2.sval)); } // Imitate Java's equals string function... bool String::equals(char *str2) // See also == operator { return ( _equalto(str2)); } // Imitate Java's equalsIgnoreCase string function... bool String::equalsIgnoreCase(String str2) { String aa, bb; aa = this->toLowerCase(); bb = str2.toLowerCase(); return ( aa._equalto(bb.sval) ); } // Imitate Java's regionMatches string function... // The startIndex specifies the index at which the region begins within // the invoking String object. The string being compared is str2. The // index at which comparison will start within str2 is specified by // str2Index. The length of the substring being compared is numChars. bool String::regionMatches(int startIndex, String str2, int str2StartIndex, int numChars) { verifyIndex(startIndex); str2.verifyIndex(str2StartIndex); if (strncmp(& this->sval[startIndex], & str2.sval[str2StartIndex], numChars) == 0) return true; else return false; } // Imitate Java's regionMatches string function... // This is overloaded function of regionMatches // If ignoreCase is true, the case of the characters is ignored, otherwise // case is significant (i.e. if ignoreCase is true then ignore the // case and compare) // The startIndex specifies the index at which the region begins within // the invoking String object. The string being compared is str2. The // index at which comparison will start within str2 is specified by // str2Index. The length of the substring being compared is numChars. bool String::regionMatches(bool ignoreCase, int startIndex, String str2, int str2StartIndex, int numChars) { if (ignoreCase) // if (ignoreCase == true) { verifyIndex(startIndex); str2.verifyIndex(str2StartIndex); String string1, string2; string1 = this->toLowerCase(); string2 = str2.toLowerCase(); if (strncmp(& string1.sval[startIndex], & string2.sval[str2StartIndex], numChars) == 0) return true; else return false; } else { return regionMatches(startIndex, str2, str2StartIndex, numChars); } } // Imitate Java's toLowerCase string function... // String ss("sometest"); // String egg = ss.toLowerCase(); String String::toLowerCase() { _allocpString(); for (long tmpii = strlen(_pString->sval); tmpii >= 0; tmpii--) { _pString->sval[tmpii] = tolower(_pString->sval[tmpii]); } return *_pString; // return the object now } // Imitate Java's toUpperCase string function... // String ss("sometest"); // String egg = ss.toUpperCase(); String String::toUpperCase() { _allocpString(); for (long tmpii = strlen(_pString->sval); tmpii >= 0; tmpii--) { _pString->sval[tmpii] = toupper(_pString->sval[tmpii]); } return *_pString; // return the object now } // Imitate Java's startsWith string function... bool String::startsWith(String str2) { if (!strncmp(this->sval, str2.sval, strlen(str2.sval) )) // if (strncmp() == 0) return true; else return false; } // Imitate Java's startsWith string function... // overloaded function bool String::startsWith(char *str2) { int lenstr2 = strlen(str2); if (!strncmp(this->sval, str2, lenstr2)) // if (strncmp() == 0) return true; else return false; } // Imitate Java's endsWith string function... bool String::endsWith(String str2) { // string length of str2 should be less than current string if (strlen(str2.sval) > strlen(sval)) return false; if (!strncmp(& this->sval[strlen(sval) - strlen(str2.sval)], str2.sval, strlen(str2.sval) )) // if (strncmp() == 0) return true; else return false; } // Imitate Java's endsWith string function... bool String::endsWith(char *str2) { // string length of str2 should be less than current string if (strlen(str2) > strlen(sval)) return false; if (!strncmp(& this->sval[strlen(sval) - strlen(str2)], str2, strlen(str2) ) ) // if (strncmp() == 0) return true; else return false; } // Imitate Java's compareTo string function... // For sorting applications, you need to know which is less than, equal to // or greater than the next. // A string is less than another if it comes before the other in dictionary // order. A string is greater than another if it comes after the other in // dictionary order. // Less than zero --> The invoking string is less than str2 // Greater than zero --> The invoking string is greater than str2 // Zero --> The two strings are equal. int String::compareTo(String str2) { int flag = 0; // Compare letters in string to each letter in str2 for (int tmpii = 0, tmpjj = strlen(sval), tmpkk = strlen(str2.sval); tmpii < tmpjj; tmpii++) { if (tmpii > tmpkk) break; if (sval[tmpii] == str2.sval[tmpii]) flag = 0; else if (sval[tmpii] > str2.sval[tmpii]) { flag = 1; break; } else // if (sval[tmpii] < str2.sval[tmpii]) { flag = -1; break; } } return flag; } // Imitate Java's compareTo string function... // Overloaded function of compareTo int String::compareTo(char *str2) { int flag = 0; // Compare letters in string to each letter in str2 for (int tmpii = 0, tmpjj = strlen(sval), tmpkk = strlen(str2); tmpii < tmpjj; tmpii++) { if (tmpii > tmpkk) break; if (sval[tmpii] == str2[tmpii]) flag = 0; else if (sval[tmpii] > str2[tmpii]) { flag = 1; break; } else // if (sval[tmpii] < str2[tmpii]) { flag = -1; break; } } return flag; } // Imitate Java's compareToIgnoreCase string function... int String::compareToIgnoreCase(String str2) { String tmpaa = this->toLowerCase(), tmpbb = str2.toLowerCase(); return tmpaa.compareTo(tmpbb); } // Imitate Java's compareToIgnoreCase string function... // Overloaded function int String::compareToIgnoreCase(char *str2) { String tmpaa = this->toLowerCase(), tmpcc(str2), tmpbb = tmpcc.toLowerCase(); return tmpaa.compareTo(tmpbb); } // Imitate Java's indexOf string function... // Searches for the first occurence of a character or string // Return the index at which the character or substring was // found, or -1 on failure. int String::indexOf(char ch, int startIndex = 0) { verifyIndex(startIndex); int ii = startIndex; for (; ii < (int) strlen(sval); ii++) { if (sval[ii] == ch) break; } if (ii == (int) strlen(sval)) return -1; return ii; } // Imitate Java's indexOf string function... // Overloaded function int String::indexOf(char *str2, int startIndex = 0) { verifyIndex(startIndex); char * tok; long res = -1; if ( !isNull() ) { tok = strstr(sval + startIndex, str2); if (tok == NULL) res = -1; else res = (int) (tok - sval); } return res; } // Imitate Java's indexOf string function... // Overloaded function int String::indexOf(String str2, int startIndex = 0) { verifyIndex(startIndex); char * tok; long res = -1; if ( !isNull() ) { tok = strstr(sval + startIndex, str2.sval); if (tok == NULL) res = -1; else res = (int) (tok - sval); } return res; } // Imitate Java's lastIndexOf string function... // Searches for the last occurence of a character or string // Return the index at which the character or substring was // found, or -1 on failure. int String::lastIndexOf(char ch, int startIndex = 0) { verifyIndex(startIndex); int ii; // Begin search from the last character of string if (!startIndex) // if (startIndex == 0) ii = strlen(sval); else ii = startIndex; for (; ii > -1; ii--) { if (sval[ii] == ch) break; } if (!ii && sval[ii] != ch) // if (ii == 0) return -1; return ii; } // Imitate Java's lastIndexOf string function... // Overloaded function int String::lastIndexOf(char *str2, int startIndex = 0) { verifyIndex(startIndex); char *tok = NULL; int res = -1; register char *tmpaa = strdup(sval); // malloc here if (!tmpaa) // tmpaa == NULL { cerr << "\nMemory alloc failed in strdup in lastIndexOf()\n" << endl; exit(-1); } if (!startIndex) // if (startIndex == 0) startIndex = strlen(sval); else tmpaa[startIndex+1] = 0; for (int ii = 0; ii <= startIndex; ii++) { tok = strstr(& tmpaa[ii], str2); if (tok == NULL) break; else { res = (int) (tok - tmpaa); debug_("res", res); ii = res; // jump to where it matched (+1 in for loop) } } free(tmpaa); debug_("res", res); debug_("indexOf", & sval[res]); return res; } // Imitate Java's lastIndexOf string function... // Overloaded function int String::lastIndexOf(String str2, int startIndex = 0) { verifyIndex(startIndex); char *tok = NULL; int res = -1; register char *tmpaa = strdup(sval); // malloc here if (!tmpaa) // tmpaa == NULL { cerr << "\nMemory alloc failed in strdup in lastIndexOf()\n" << endl; exit(-1); } if (!startIndex) // if (startIndex == 0) startIndex = strlen(sval); else tmpaa[startIndex+1] = 0; for (int ii = 0; ii <= startIndex; ii++) { tok = strstr(& tmpaa[ii], str2.sval); if (tok == NULL) break; else { res = (int) (tok - tmpaa); debug_("res", res); ii = res; // jump to where it matched (+1 in for loop) } } free(tmpaa); debug_("res", res); debug_("indexOf", & sval[res]); return res; } // Imitate Java's substring string function... // The startIndex specifies the beginning index, and endIndex specifies // the stopping point. The string returned contains all the characters // from the beginning index, up to, but not including, the ending index. String String::substring(int startIndex, int endIndex = 0) { String tmpstr = String(sval); tmpstr._substring(startIndex, endIndex); return tmpstr; } // Imitate Java's concat string function... String String::concat(String str2) { return (*this + str2); } // Imitate Java's concat string function... // overloaded function String String::concat(char *str2) { return (*this + str2); } // Imitate Java's replace string function... // Replace all occurences of string 'original' with // 'replacement' in 'sval' String String::replace(char original, char replacement) { // For example - // replace('A', 'B') on sval = "some AAA and AAACC" // reurns sval = "some BBB and BBBCC" //String *tmpstr = new String(sval); Use default copy cstr String tmpstr(sval); for (int ii = 0, len = strlen(sval); ii < len; ii++) { if (tmpstr.sval[ii] == original) tmpstr.sval[ii] = replacement; } return tmpstr; // this will use copy constructor to make a default copy } // Imitate Java's replace string function... // overloaded function // Replace all occurences of string 'original' with // 'replacement' in 'sval' String String::replace(char *original, char *replacement) { char *tok = NULL, *bb; register char *aa = strdup(sval); int lenrepl = strlen(replacement); // Allocate space for bb { // local scope int tmpii = 0; for (int ii = 0; ;ii++) { tok = strstr(& aa[ii], original); if (tok == NULL) break; else { ii = ii + (int) (tok -aa); tmpii++; } } if (!tmpii) // tmpii == 0, no match of 'original' found return (String(sval)); // return original string tmpii = strlen(sval) + (tmpii * lenrepl) + 20; debug_("strstr tmpii", tmpii ); bb = (char *) malloc(tmpii); memset(bb, 0, tmpii); } for (int res = -1; ;) { debug_("aa", aa); tok = strstr(aa, original); if (tok == NULL) { strcat(bb, aa); break; } else { res = (int) (tok - aa); strncat(bb, aa, res); strcat(bb, replacement); //bb[strlen(bb)] = 0; debug_("res", res ); debug_("bb", bb ); strcpy(aa, & aa[res+lenrepl]); } } debug_("bb", bb ); free(aa); String tmpstr(bb); free(bb); return tmpstr; } /* another method of doing replace function but slow.. String String::replace(char *original, char *replacement) { // For example - // replace("AAA", "BB") on sval = "some AAA and AAACC" // reurns sval = "some BB and BBCC" String bb(this->before(original).sval); if (strlen(bb.sval) == 0) return String(sval); // return original string bb += replacement; String tmpaa(this->sval), cc, dd; for (;;) { cc = tmpaa.after(original).sval; debug_("cc", cc.sval ); if (!strlen(cc.sval)) // if (strlen(cc.sval) == 0) break; dd = cc.before(original).sval; if (strlen(dd.sval) == 0) { bb += cc; break; } else { bb += dd; bb += replacement; } tmpaa = cc; } debug_("bb.sval", bb.sval ); return bb; } */ // Imitate Java's replace function - StringBuffer String String::replace (int startIndex, int endIndex, String str) { verifyIndex(startIndex); verifyIndex(endIndex); int tmpjj = strlen(str.sval); if (tmpjj == 0) return *this; int tmpii = endIndex-startIndex-1; if (tmpjj < tmpii) // length of str is less than specified indexes. tmpii = tmpjj; debug_("sval", sval); debug_("str.sval", str.sval); strncpy(& sval[startIndex], str.sval, tmpii); sval[startIndex+tmpii] = 0; debug_("sval", sval); return *this; } // Imitate Java's trim string function... String String::trim() { //String *tmpstr = new String(sval); String tmpstr(sval); tmpstr._trim(); debug_("tmpstr.sval", tmpstr.sval); return tmpstr; // this will use copy constructor to make a default copy } // Imitate Java's insert string function... String String::insert(int index, String str2) { String tmpstr(this->insert(str2.sval, index).sval); debug_("tmpstr.sval", tmpstr.sval); return tmpstr; } // Imitate Java's insert string function... String String::insert(int index, char ch) { char aa[2]; aa[0] = ch; aa[1] = 0; String tmpstr(this->insert(aa, index).sval); debug_("tmpstr.sval", tmpstr.sval); return tmpstr; } // Imitate Java's deleteCharAt string function... String String::deleteCharAt(int loc) { String tmpstr(sval); tmpstr._deleteCharAt(loc); return tmpstr; } // Imitate Java's delete string function... // Note: -->Java name is "delete()", cannot use reserved name delete() in C++ // The startIndex specifies the index of the first character to remove, // and endIndex specifies an index one past the last character to remove. // Thus, the substring deleted runs from startIndex to (endIndex - 1) String String::deleteStr(int startIndex, int endIndex) { // For example - // deleteStr(3,3) on val = 'pokemon' returns 'poon' String tmpstr(sval); tmpstr._deleteStr(startIndex, endIndex); return tmpstr; } // Imitate Java's reverse string function... String String::reverse() { // For example - // reverse() on "12345" returns "54321" String tmpstr(sval); tmpstr._reverse(); return tmpstr; } // Imitate Java's valueOf string function... String String::valueOf(char chars[], int startIndex, int numChars) { verifyIndex(startIndex); int ii = strlen(chars); if (startIndex > ii) { cerr << "\nvalueOf() - startIndex greater than string length of" << "string passed" << endl; exit(0); } if ( (numChars+startIndex) > ii) { cerr << "\nvalueOf() - numChars exceeds the string length of" << "string passed" << endl; exit(0); } char *aa = strdup(chars); aa[startIndex + numChars] = 0; String tmpstr(& aa[startIndex]); free(aa); return tmpstr; } // Imitate Java's ensureCapacity string function... // For use by StringBuffer class. // Pre-allocate room for certain number of chars, useful // if you know in advance that you will be appending a large // number of small strings to StringBuffer void String::ensureCapacity(int capacity) { sval = (char *) my_realloc(sval, capacity); sval[0] = '\0'; debug_("In ensureCapacity(int capacity) sval", sval); } // Imitate Java's setLength string function... // For use by StringBuffer class. void String::setLength(int len) { sval = (char *) my_realloc(sval, len); sval[0] = '\0'; debug_("In ensureCapacity(int len) sval", sval); } // Imitate Java's setCharAt function - StringBuffer void String::setCharAt(int where, char ch) { verifyIndex(where); sval[where] = ch; debug_("in StringBuffer dstr()", "ok"); } // ---- End of Java like String object functions ----- // overloaded function - directly changes object // Variable dummy will give different signature to function void String::substring(int startIndex, int endIndex, bool dummy) { this->_substring(startIndex, endIndex); } inline void String::_substring(int startIndex, int endIndex) { verifyIndex(startIndex); verifyIndex(endIndex); if (!endIndex) // endIndex == 0 strcpy(sval, & sval[startIndex] ) ; else { if (endIndex > startIndex) { strcpy(sval, & sval[startIndex] ) ; sval[endIndex -startIndex] = 0; } else { cerr << "\n_substring() - startIndex is greater than endIndex!!\n" << endl; exit(-1); } } } // overloaded function - directly changes object String String::deleteStr(int startIndex, int endIndex, bool dummy) { this->_deleteStr(startIndex, endIndex); return *this; } inline void String::_deleteStr(int startIndex, int endIndex) { verifyIndex(startIndex); verifyIndex(endIndex); // For example - // deleteStr(3,3) on val = 'pokemon' returns 'poon' char *tmpaa = strdup(sval); // malloc here strcpy(& tmpaa[startIndex], & tmpaa[endIndex]); *this = tmpaa; free(tmpaa); } // overloaded function - directly changes object String String::deleteCharAt(int loc, bool dummy) { this->_deleteCharAt(loc); return *this; } inline void String::_deleteCharAt(int loc) { char *tmpaa = strdup(sval); // malloc here strcpy(& tmpaa[loc], & tmpaa[loc+1]); *this = tmpaa; free(tmpaa); } // Returns string before regx. Matches first occurence of regx String String::at(char *regx) { char *tok = NULL; tok = strstr(sval, regx); if (tok == NULL) return(String("")); else { int res = (int) (tok - sval); char *lefttok = strdup(sval); memset(lefttok, 0, strlen(sval)); strcpy(lefttok, & sval[res]); String tmpstr(lefttok); free(lefttok); return(tmpstr); } } // Returns string before regx. Matches first occurence of regx String String::before(char *regx) { char *tok = NULL; tok = strstr(sval, regx); if (tok == NULL) return(String("")); else { int res = (int) (tok - sval); char *lefttok = strdup(sval); lefttok[res] = 0; String tmpstr(lefttok); free(lefttok); return(tmpstr); } } // Returns string after regx. Matches first occurence of regx String String::after(char *regx) { char *tok = NULL; tok = strstr(sval, regx); if (tok == NULL) return(String("")); else { int res = (int) (tok - sval); char *lefttok = strdup(sval); memset(lefttok, 0, strlen(sval)); strcpy(lefttok, & sval[res + strlen(regx)]); String tmpstr(lefttok); free(lefttok); return(tmpstr); } } // Explodes the string and returns the list in // the list-head pointer explodeH // See also token() void String::explode(char *seperator) { char *aa = NULL, *bb = NULL; aa = (char *) my_malloc(strlen(sval)); for (bb = strtok(aa, seperator); bb != NULL; bb = strtok(NULL, seperator) ) { String *tmp = new String(bb); String::explodeH.insert(String::explodeH.end(), *tmp); } my_free(aa); list<String>::iterator iter1; // see file include/g++/stl_list.h debug_("Before checking explode..", "ok"); if (String::explodeH.empty() == true ) { debug_("List is empty!!", "ok"); } for (iter1 = String::explodeH.begin(); iter1 != String::explodeH.end(); iter1++) { if (iter1 == NULL) { debug_("Iterator iter1 is NULL!!", "ok" ); break; } debug_("(*iter1).sval", (*iter1).sval); } } // Overloaded function of explode(). This will return an // array of strings and total number in strcount reference // variable. // See also token() String *String::explode(int & strcount, char seperator = ' ') { String aa(sval); aa.trim(true); strcount = 0; for (int ii = 0, jj = strlen(aa.sval); ii < jj; ii++) { if (aa.sval[ii] == seperator) strcount++; } String *tmpstr = new String[strcount+1]; if (!strcount) // strcount == 0 tmpstr[0] = aa.sval; else { for (int ii = 0; ii <= strcount; ii++) tmpstr[ii] = aa.token(); } return tmpstr; } // Implodes the strings in the list-head // pointer explodeH and returns the String class void String::implode(char *glue) { } // Joins the strings in the list-head // pointer explodeH and returns the String class void String::join(char *glue) { implode(glue); } // Repeat the input string n times String String::repeat(char *input, unsigned int multiplier) { // For example - // repeat("k", 4) returns "kkkk" if (!input) // input == NULL { return (String("")); } char *aa = (char *) my_malloc(strlen(input) * multiplier); for (unsigned int tmpii = 0; tmpii < multiplier; tmpii++) { strcat(aa, input); } String tmpstr(aa); my_free(aa); return tmpstr; } // Reverse the string // Overloaded version of reverse(). This will directly // change the object. void String::reverse(bool dummy) { this->_reverse(); } inline void String::_reverse() { // For example - // reverse() on "12345" returns "54321" char aa; unsigned long tot_len = strlen(sval); unsigned long midpoint = tot_len / 2; for (unsigned long tmpjj = 0; tmpjj < midpoint; tmpjj++) { aa = sval[tmpjj]; // temporary storage var sval[tmpjj] = sval[tot_len - tmpjj - 1]; // swap the values sval[tot_len - tmpjj - 1] = aa; // swap the values } } // Translate certain chars // For e.g ("abcd", "ABC") translates all occurences of each // character in 'from' to corresponding character in 'to' String String::tr(char *from, char *to) { int lenfrom = strlen(from), lento = strlen(to); if (lento > lenfrom) lento = lenfrom; // set it to least else if (lento < lenfrom) lenfrom = lento; // set it to least debug_("lento", lento); register char *aa = strdup(sval); for (int ii = 0, jj = strlen(sval); ii < jj; ii++) // for every char in val { for (int kk = 0; kk < lento; kk++) // for every char in "from" string { if (aa[ii] == from[kk]) aa[ii] = to[kk]; } } String tmpstr(aa); free(aa); return tmpstr; } // Center the text String String::center(int padlength, char padchar = ' ') { // For example - // center(10, '*') on sval="aa" returns "****aa****" // center(10) on sval="aa" returns " aa " // The result is a string of 'padlength' characters with sval centered in it. int tmpii = sizeof(char) * (padlength + strlen(sval) + 10); char *aa = (char *) malloc(tmpii); memset(aa, 0, tmpii); for (int jj = 0, kk = (int) padlength/2; jj < kk; jj++) { aa[jj] = padchar; } strcat(aa, sval); for (int jj = strlen(aa), kk = jj + (int) padlength/2; jj < kk; jj++) { aa[jj] = padchar; } String tmpstr(aa); free(aa); return tmpstr; } // Formats the original string by placing <number> of <padchar> characters // between each set of blank-delimited words. Leading and Trailing blanks // are always removed. If <number> is omitted or is 0, then all spaces are // in the string are removed. The default number is 0 and // default padchar ' ' String String::space(int number, char padchar = ' ') { // For example - // space(3) on sval = "I do not know" // will return "I do not know" // space(1, '_') on sval = "A deep black space" // will return "A_deep_black_space" // space() on sval = "I know this" // will return "Iknowthis" debug_("this->sval", this->sval ); String tmpstr = this->trim().sval; debug_("tmpstr.sval", tmpstr.sval ); // count spaces int spacecount = 0; for (int ii = 0, jj = strlen(tmpstr.sval); ii < jj; ii++) { if (tmpstr.sval[ii] == ' ') spacecount++; } debug_("spacecount", spacecount); char ee[2]; ee[0] = padchar; ee[1] = 0; String bb = tmpstr.repeat(ee, spacecount); int tmpii = sizeof(char) * (strlen(tmpstr.sval) + (number * spacecount) + 20); char *aa = (char *) malloc(tmpii); memset(aa, 0, tmpii); for (int ii = 0, jj = strlen(tmpstr.sval); ii < jj; ii++) { if (tmpstr.sval[ii] == ' ') strcat(aa, bb.sval); else { ee[0] = sval[ii]; strcat(aa, ee); } } tmpstr = aa; free(aa); return tmpstr; } // The result is string comprised of all characters between // and including <start> and <end> String String::xrange(char start, char end) { // For example - // xrange('a', 'j') returns val = "abcdefghij" // xrange(1, 8) returns val = "12345678" if (end < start) { cerr << "\nThe 'end' character is less than 'start' !!" << endl; return String(""); } // Note: The 'end' is greater than 'start'!! And add +1 int tmpii = sizeof(char) * (end - start + 11); char *aa = (char *) malloc(tmpii); memset(aa, 0, tmpii); debug_("xrange tmpii", tmpii); for (int ii = start, jj = 0; ii <= end; ii++, jj++) { aa[jj] = ii; debug_("xrange aa[jj]", aa[jj] ); } String tmpstr(aa); free(aa); return tmpstr; } // Removes any characters contained in <list>. The default character // for <list> is a blank ' ' String String::compress(char *list = " ") { // For example - // compress("$,%") on sval = "$1,934" returns "1934" // compress() on sval = "call me alavoor vasudevan" returns "callmealavoorvasudevan" int lenlist = strlen(list); register char *aa = strdup(sval); for (int ii = 0, jj = strlen(sval); ii < jj; ii++) // for every char in sval { for (int kk = 0; kk < lenlist; kk++) // for every char in "from" string { if (aa[ii] == list[kk]) { strcpy(& aa[ii], & aa[ii+1]); } } } String tmpstr(aa); free(aa); return tmpstr; } // The <newstr> is inserted into sval beginning at <start>. The <newstr> will // be padded or truncated to <length> characters. The default <length> is // string length of newstr String String::insert(char *newstr, int start = 0, int lengthstr = 0, char padchar = ' ') { // For example - // insert("something new", 4, 20, '*') on sval = "old thing" // returns "old something new*******thing" int tmplen = sizeof(char) * strlen(sval) + strlen(newstr) + lengthstr + 10; char *tmpaa = (char *) malloc (tmplen); memset(tmpaa, 0, tmplen); if (!start) // start == 0 { strcpy(tmpaa, newstr); strcat(tmpaa, this->sval); } else { strncpy(tmpaa, this->sval, start); strcat(tmpaa, newstr); strcat(tmpaa, & this->sval[start]); } String tmpstr(tmpaa); free(tmpaa); return tmpstr; } // overloaded insert function... String String::insert(int index, String str2, bool dummy) { *this = this->insert(str2.sval, index).sval; //debug_("tmpstr.sval", tmpstr.sval); return *this; } // overloaded insert function... String String::insert(int index, char ch, bool dummy) { char aa[2]; aa[0] = ch; aa[1] = 0; *this = this->insert(aa, index).sval; //debug_("tmpstr.sval", tmpstr.sval); return *this; } // The result is string of <length> chars madeup of leftmost chars in sval. // Quick way to left justify a string. String String::left(int slength = 0, char padchar = ' ') { // For example - // left(15) on sval = "Wig" returns "Wig " // left(4) on sval = "Wighat" returns "Wigh" // left() on sval = " Wighat" returns "Wighat " if (!slength) // slength == 0 slength = strlen(sval); debug_("left() slength", slength); int tmpii = slength + 20; char *aa = (char *) malloc(tmpii); memset(aa, 0, tmpii); debug_("this->ltrim().sval ", this->ltrim().sval); strcpy(aa, this->ltrim().sval); debug_("left() aa", aa ); int currlen = strlen(aa); if (currlen < slength) { // pad the string now char ee[2]; ee[0] = padchar; ee[1] = 0; strcat(aa, this->repeat(ee, (unsigned int) (slength-currlen) ).sval); } else { aa[slength] = 0; } debug_("left() aa", aa ); String tmpstr(aa); free(aa); return tmpstr; } // The result is string of <length> chars madeup of rightmost chars in sval. // Quick way to right justify a string. String String::right(int slength = 0, char padchar = ' ') { // For example - // right(10) on sval = "never to saying " returns " to saying" // right(4) on sval = "Wighat" returns "ghat" // right(8) on sval = "4.50" returns " 4.50" // right() on sval = " 4.50 " returns " 4.50" if (!slength) // slength == 0 slength = strlen(sval); debug_("right() slength", slength); int tmpii = slength + 20; char *aa = (char *) malloc(tmpii); memset(aa, 0, tmpii); int currlen = strlen(this->rtrim().sval); debug_("right() currlen", currlen ); if (currlen < slength) { // pad the string now char ee[2]; ee[0] = padchar; ee[1] = 0; strcpy(aa, this->repeat(ee, (unsigned int) (slength-currlen) ).sval); strcat(aa, this->rtrim().sval); debug_("right() aa", aa ); } else { strcpy(aa, this->rtrim().sval); strcpy(aa, & aa[currlen-slength]); aa[slength] = 0; } debug_("right() aa", aa ); String tmpstr(aa); free(aa); return tmpstr; } // The <newstr> is overlayed into sval beginning at <start>. The <newstr> will // be padded or truncated to <length> characters. The default <length> is // string length of newstr String String::overlay(char *newstr, int start = 0, int slength = 0, char padchar = ' ') { // For example - // overlay("12345678", 4, 10, '*') on sval = "oldthing is very bad" // returns "old12345678**ery bad" // overlay("12345678", 4, 5, '*') on sval = "oldthing is very bad" // returns "old12345ery bad" int len_newstr = strlen(newstr); if (!slength) // slength == 0 slength = len_newstr; char *aa = (char *) malloc(slength + len_newstr + 10); aa[0] = 0; char ee[2]; ee[0] = padchar; ee[1] = 0; if (len_newstr < slength) { // pad it now strcpy(aa, newstr); strcat(aa, this->repeat(ee, (slength-len_newstr)).sval ); } else { strcpy(aa, newstr); aa[slength] = 0; } // Now overlay the string. String tmpstr(sval); debug_("tmpstr.sval", tmpstr.sval); for (int ii=start, jj=strlen(tmpstr.sval), kk=start+slength, mm=0; ii < jj; ii++, mm++) { if (ii == kk) break; if (mm == slength) break; tmpstr.sval[ii] = aa[mm]; } free(aa); debug_("tmpstr.sval", tmpstr.sval); return tmpstr; } // If string is literrally equal to .. or not equal to // If type is false than it is == bool String::_equalto(const String & rhs, bool type = false) { if (type == false) // test for == { if (strlen(rhs.sval) == strlen(sval)) { if (!strncmp(rhs.sval, sval, strlen(sval))) // == 0 return true; else return false; } else return false; } else // test for != { if (strlen(rhs.sval) != strlen(sval)) { if (!strncmp(rhs.sval, sval, strlen(sval))) // == 0 return true; else return false; } else return false; } } // If string is literrally equal to .. or not equal to // If type is false than it is == bool String::_equalto(const char *rhs, bool type = false) { if (type == false) // test for == { if (strlen(rhs) == strlen(sval)) { if (!strncmp(rhs, sval, strlen(sval))) // == 0 return true; else return false; } else return false; } else // test for != { if (strlen(rhs) != strlen(sval)) { if (!strncmp(rhs, sval, strlen(sval))) // == 0 return true; else return false; } else return false; } } // Synonym function is vacuum() void String::clear() { sval = (char *) my_realloc(sval, 10); sval[0] = '\0'; } // Remove trailing ALL given character 'ch' - see also chop() // For example : // sval = "abcdef\n\n\n" then chopall() = "abcdef" // sval = "abcdefffff" then chopall('f') = "abcde" void String::chopall(char ch='\n') { unsigned long tmpii = strlen(sval) - 1 ; for (; tmpii >= 0; tmpii--) { if (sval[tmpii] == ch) sval[tmpii] = 0; else break; } } // Remove trailing character - see also chopall() // chop() is often used to remove trailing newline character void String::chop() { sval[strlen(sval)-1] = 0; } // Overloaded version of trim(). This will directly // change the object. void String::trim(bool dummy) { this->_trim(); } inline void String::_trim() { this->rtrim(true); this->ltrim(true); debug_("this->sval", this->sval); } // Overloaded version of ltrim(). This will directly // change the object. void String::ltrim(bool dummy) { this->_ltrim(); } inline void String::_ltrim() { // May cause problems in my_realloc since // location of bb will be destroyed !! char *bb = sval; if (bb == NULL) return; while (isspace(*bb)) bb++; debug_("bb", bb); if (bb != NULL && bb != sval) { debug_("doing string copy", "done"); _str_cpy(bb); // causes problems in my_realloc and bb is getting destroyed!! } else debug_("Not doing string copy", "done"); } String String::ltrim() { String tmpstr(sval); tmpstr._ltrim(); return tmpstr; } // Overloaded version of rtrim(). This will directly // change the object. void String::rtrim(bool dummy) { this->_rtrim(); } inline void String::_rtrim() { for (long tmpii = strlen(sval) - 1 ; tmpii >= 0; tmpii--) { if ( isspace(sval[tmpii]) ) sval[tmpii] = '\0'; else break; } } String String::rtrim() { String tmpstr(sval); tmpstr._rtrim(); return tmpstr; } // Use for rounding off fractions digits of floats // Rounds-off floats with given precision and then // stores the result into String's sval field // Also returns the result as a char * void String::roundf(float input_val, short precision) { float integ_flt, deci_flt; const short MAX_PREC = 4; debug_("In roundf", "ok"); if (precision > MAX_PREC) // this is the max reliable precision precision = MAX_PREC; // get the integral and decimal parts of the float value.. deci_flt = modff(input_val, & integ_flt); for (int tmpzz = 0; tmpzz < precision; tmpzz++) { debug_("deci_flt", deci_flt); deci_flt *= 10; } debug_("deci_flt", deci_flt); unsigned long deci_int = (unsigned long) ( rint(deci_flt) ); sval = (char *) my_malloc(NUMBER_LENGTH); // float 70 digits max if (deci_int > 999) // (MAX_PREC) digits sprintf(sval, "%lu.%lu", (unsigned long) integ_flt, deci_int); else if (deci_int > 99) // (MAX_PREC - 1) digits sprintf(sval, "%lu.0%lu", (unsigned long) integ_flt, deci_int); else if (deci_int > 9) // (MAX_PREC - 2) digits sprintf(sval, "%lu.00%lu", (unsigned long) integ_flt, deci_int); else sprintf(sval, "%lu.00000%lu", (unsigned long) integ_flt, deci_int); } void String::roundd(double input_val, short precision) { double integ_flt, deci_flt; const short MAX_PREC = 6; if (precision > MAX_PREC) // this is the max reliable precision precision = MAX_PREC; debug_("In roundd", "ok"); // get the integral and decimal parts of the double value.. deci_flt = modf(input_val, & integ_flt); for (int tmpzz = 0; tmpzz < precision; tmpzz++) { debug_("deci_flt", deci_flt); deci_flt *= 10; } debug_("deci_flt", deci_flt); sval = (char *) my_malloc(NUMBER_LENGTH); // double 70 digits max unsigned long deci_int = (unsigned long) ( rint(deci_flt) ); if (deci_int > 99999) // (MAX_PREC) digits sprintf(sval, "%lu.%lu", (unsigned long) integ_flt, deci_int); else if (deci_int > 9999) // (MAX_PREC - 1) digits sprintf(sval, "%lu.0%lu", (unsigned long) integ_flt, deci_int); else if (deci_int > 999) // (MAX_PREC - 2) digits sprintf(sval, "%lu.00%lu", (unsigned long) integ_flt, deci_int); else if (deci_int > 99) // (MAX_PREC - 3) digits sprintf(sval, "%lu.000%lu", (unsigned long) integ_flt, deci_int); else if (deci_int > 9) // (MAX_PREC - 4) digits sprintf(sval, "%lu.0000%lu", (unsigned long) integ_flt, deci_int); else // (MAX_PREC - 5) digits sprintf(sval, "%lu.00000%lu", (unsigned long) integ_flt, deci_int); } // Provided for documentation purpose only // You must use the function indexOf() bool String::contains(char *str2, int startIndex = 0) { // For example - // if (indexOf("ohboy") > -1 ) // cout << "\nString contains 'ohboy'" << endl; // if (indexOf("ohboy") < 0 ) // cout << "\nString does NOT contain 'ohboy'" << endl; // if (indexOf("ohboy", 4) > -1 ) // cout << "\nString contains 'ohboy'" << endl; // if (indexOf("ohboy", 4) < 0 ) // cout << "\nString does NOT contain 'ohboy'" << endl; cerr << "\nYou must use indexOf() function instead of contains()\n" << endl; exit(-1); } // Synonym function is empty() bool String::isNull() { if (sval[0] == '\0') return true; else { if (sval == NULL) return true; else return false; } } // Leading, trailing white-spaces of string are ignored bool String::isInteger() { String tmpstr(sval); tmpstr.trim(true); debug_("tmpstr.sval", tmpstr.sval ); if ( strspn ( tmpstr.sval, "0123456789" ) != strlen(tmpstr.sval) ) return ( false ) ; else return ( true ) ; } // overloaded func bool String::isInteger(int pos) { verifyIndex(pos); return (isdigit(sval[pos])); } // Leading, trailing white-spaces of string are ignored bool String::isNumeric() { String tmpstr(sval); tmpstr.trim(true); debug_("tmpstr.sval", tmpstr.sval ); if ( strspn ( tmpstr.sval, "0123456789.+-e" ) != strlen(tmpstr.sval) ) return ( false ) ; else return ( true ) ; } // overloaded func bool String::isNumeric(int pos) { verifyIndex(pos); return (isdigit(sval[pos])); } bool String::isEmpty() { if (strlen(sval) == 0) return true; else return false; } // See also explode() // Warning : The String instance is modified by removing // the returned token from the string. It is advised // that you save the original string before calling // this function like for example : // String savestr = origstr; // String aa, bb, cc; // aa = origstr.token(); // bb = origstr.token(); // cc = origstr.token(); // // This routine returns the first non-'seperator' (default // white-space) token string from the String instance String String::token(char seperator = ' ') { char ee[2]; ee[0] = seperator; ee[1] = 0; char *res = strtok(sval, ee); if (!res) // if res == NULL { debug_("token", res); debug_("sval", sval); return(String(sval)); } else { String tmpstr(res); // Should take string length of sval and not res // because strtok() had put a NULL ('\0') at the location // and also strtok() ignores the leading blanks of sval strcpy(sval, & sval[strlen(sval)+1]); debug_("token", res); debug_("sval", sval); return tmpstr; } } String String::crypt(char *original, char *salt) { return String(""); } int String::int_value() { if ( strlen(sval) == 0 ) { cerr << "Cannot convert a zero length string " << " to a numeric" << endl ; abort() ; } if ( ! isInteger() ) { cerr << "Cannot convert string [" << sval << "] to an integer numeric string" << endl ; abort() ; } return ( atoi ( sval ) ) ; } double String::double_value() { if ( strlen(sval) == 0 ) { cerr << "Cannot convert a zero length string " << " to a numeric" << endl ; abort() ; } if ( ! isNumeric() ) { cerr << "Cannot convert string [" << sval << "] to a double numeric string" << endl ; abort() ; } double d = atof ( sval ) ; return ( d ) ; } String String::getline(FILE *infp = stdin) { register char ch, *aa = NULL; register const short SZ = 100; // Initial value of ii > SZ so that aa is alloc'ed memory register int jj = 0; for (int ii = SZ+1; (ch = getc(infp)) != EOF; ii++, jj++) { if (ii > SZ) // allocate memory in steps of SZ for performance { aa = (char *) realloc(aa, jj + ii + 15); // +15 is safe mem ii = 0; } if (ch == '\n') // read untill newline is encountered break; aa[jj] = ch; } aa[jj] = 0; _str_cpy(aa); // puts the value in string free(aa); return *this; } /* void String::Format(const char *fmt, ... ) { va_list iterator; va_start(iterator, fmt ); va_end(iterator); } */ inline void String::verifyIndex(unsigned long index) const { if (index < 0 || index >= strlen(sval) ) { // throw "Index Out Of Bounds Exception"; cerr << "Index Out Of Bounds Exception at [" << index << "] in:\n" << sval << endl; exit(1); } } ////////////////////////////////////////////////////////// // Private functions start from here ......... ////////////////////////////////////////////////////////// void String::_str_cpy(char bb[]) { debug_("In _str_cpy bb", bb); if (bb == NULL) { sval[0] = '\0'; return; } unsigned long tmpii = strlen(bb); if (tmpii == 0) { sval[0] = '\0'; return; } debug_("In _str_cpy tmpii", tmpii); debug_("In _str_cpy sval", sval); sval = (char *) my_realloc(sval, tmpii); //sval = new char [tmpii + SAFE_MEM_2]; debug_("In _str_cpy bb", bb); strncpy(sval, bb, tmpii); debug_("In _str_cpy sval", sval); sval[tmpii] = '\0'; debug_("In _str_cpy sval", sval); } void String::_str_cpy(int bb) { char tmpaa[100]; sprintf(tmpaa, "%d", bb); _str_cpy(tmpaa); } void String::_str_cpy(unsigned long bb) { char tmpaa[100]; sprintf(tmpaa, "%ld", bb); _str_cpy(tmpaa); } void String::_str_cpy(float bb) { char tmpaa[100]; sprintf(tmpaa, "%f", bb); _str_cpy(tmpaa); } void String::_str_cat(char bb[]) { unsigned long tmpjj = strlen(bb), tmpii = strlen(sval); sval = (char *) my_realloc(sval, tmpii + tmpjj); debug_("sval in _str_cat() ", sval); strncat(sval, bb, tmpjj); } void String::_str_cat(int bb) { char tmpaa[100]; sprintf(tmpaa, "%d", bb); unsigned long tmpjj = strlen(tmpaa), tmpii = strlen(sval); sval = (char *) my_realloc(sval, tmpii + tmpjj); strncat(sval, tmpaa, tmpjj); } void String::_str_cat(unsigned long bb) { char tmpaa[100]; sprintf(tmpaa, "%ld", bb); unsigned long tmpjj = strlen(tmpaa), tmpii = strlen(sval); sval = (char *) my_realloc(sval, tmpii + tmpjj); strncat(sval, tmpaa, tmpjj); } void String::_str_cat(float bb) { char tmpaa[100]; sprintf(tmpaa, "%f", bb); unsigned long tmpjj = strlen(tmpaa), tmpii = strlen(sval); sval = (char *) my_realloc(sval, tmpii + tmpjj); strncat(sval, tmpaa, tmpjj); } ////////////////////////////////////////////////////////// // All operator functions start from here ......... ////////////////////////////////////////////////////////// String operator+ (const String & lhs, const String & rhs) { /*******************************************************/ // Note : For adding two char strings, first cast String // as in - //aa = (String) "alkja " + " 99djd " ; /*******************************************************/ String tmp(lhs); tmp._str_cat(rhs.sval); return(tmp); /* if (String::_global_String == NULL) { String::_global_String = new String; String::_global_String->_str_cpy(lhs.sval); String::_global_String->_str_cat(rhs.sval); //return *String::_global_String; return String(String::_global_String->val); } */ /* else if (String::_global_String1 == NULL) { debug_("1)global", "ok" ); String::_global_String1 = new String; String::_global_String1->_str_cpy(lhs.sval); String::_global_String1->_str_cat(rhs.sval); return *String::_global_String1; } */ /* else { fprintf(stderr, "\nError: cannot alloc _global_String\n"); exit(-1); } */ /* String *aa = new String; aa->_str_cpy(lhs.sval); aa->_str_cat(rhs.sval); return *aa; */ } String String::operator+ (const String & rhs) { String tmp(*this); tmp._str_cat(rhs.sval); debug_("rhs.sval in operator+", rhs.sval ); debug_("tmp.sval in operator+", tmp.sval ); return (tmp); } // Using reference will be faster in = operator String& String:: operator= ( const String& rhs ) { if (& rhs == this) { debug_("Fatal Error: In operator(=). rhs is == to 'this pointer'!!", "ok" ); return *this; } this->_str_cpy(rhs.sval); debug_("rhs value", rhs.sval ); // Free global vars memory //_free_glob(& String::_global_String); //if (String::_global_String == NULL) //fprintf(stderr, "\n_global_String is freed!\n"); //return (String(*this)); return *this; } // Using reference will be faster in = operator String& String::operator+= (const String & rhs) { /*******************************************************/ // Note : For adding two char strings, first cast String // as in - //aa += (String) "cccc" + "dddd"; /*******************************************************/ if (& rhs == this) { debug_("Fatal error: In operator+= rhs is equals 'this' ptr", "ok"); return *this; } this->_str_cat(rhs.sval); return *this; //return (String(*this)); } bool String::operator== (const String & rhs) { return(_equalto(rhs.sval)); } bool String::operator== (const char *rhs) { return(_equalto(rhs)); } bool String::operator!= (const String & rhs) { return(_equalto(rhs.sval, true)); } bool String::operator!= (const char *rhs) { return(_equalto(rhs, true)); } char String::operator[] (unsigned long Index) const { verifyIndex(Index); return sval[Index]; } char & String::operator[] (unsigned long Index) { verifyIndex(Index); return sval[Index]; } istream & operator >> (istream & In, String & str2) { // allocate max size of 2048 characters static char aa[MAX_ISTREAM_SIZE]; In >> aa; str2 = aa; // assign to reference String return In; // return istream } ostream & operator << (ostream & Out, const String & str2) { Out << str2.sval; return Out; } //////////////////////////////////////////////////// // Imitate Java's StringBuffer Object // StringBuffer class functions //////////////////////////////////////////////////// // Imitate Java's StringBuffer - the default constructor // (the one with no parameters) reserves room for 16 // characters. StringBuffer::StringBuffer() :String() // calls base class cstr no params { debug_("in StringBuffer cstr()", "ok"); } // Imitate Java's StringBuffer StringBuffer::StringBuffer(int size) :String(size, true) // calls base class cstr { // String(size, true) -- do not call here in body but call // in initialization stage which will avoid extra call on // default base-class constructor and will be faster // and very efficient debug_("in StringBuffer cstr(int size)", "ok"); } // Imitate Java's StringBuffer // calls base class cstr with string param StringBuffer::StringBuffer(String str) :String(str.val()) // calls base class cstr { // String(str.val()) -- do not call here in body but call // in initialization stage which will avoid extra call on // default base-class constructor and will be faster // and very efficient debug_("in StringBuffer cstr(String str)", "ok"); } // Imitate Java's StringBuffer StringBuffer::~StringBuffer() { debug_("in StringBuffer dstr()", "ok"); }