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");
}