/* * Modification History * * 2003-May-10 Jason Rohrer * Created. * Added a tokenization function. * * 2003-June-14 Jason Rohrer * Added a join function. * * 2003-June-22 Jason Rohrer * Added an autoSprintf function. * * 2003-July-27 Jason Rohrer * Fixed bugs in autoSprintf return values for certain cases. * * 2003-August-12 Jason Rohrer * Added a concatonate function. * * 2003-September-7 Jason Rohrer * Changed so that split returns last part, even if it is empty. * * 2004-January-15 Jason Rohrer * Added work-around for MinGW vsnprintf bug. * * 2006-June-2 Jason Rohrer * Added a stringStartsWith function. * * 2009-September-7 Jason Rohrer * Fixed int types. * Switched away from StringBufferOutputStream to new function in SimpleVector. * * 2010-May-14 Jason Rohrer * String parameters as const to fix warnings. */ #include "stringUtils.h" #include char *stringToLowerCase( const char *inString ) { unsigned int length = strlen( inString ); char *returnString = stringDuplicate( inString ); for( unsigned int i=0; i stringLength ) { return false; } else { for( unsigned int i=0; i *parts = new SimpleVector(); char *workingString = stringDuplicate( inString ); char *workingStart = workingString; unsigned int separatorLength = strlen( inSeparator ); char *foundSeparator = strstr( workingString, inSeparator ); while( foundSeparator != NULL ) { // terminate at separator foundSeparator[0] = '\0'; parts->push_back( stringDuplicate( workingString ) ); // skip separator workingString = &( foundSeparator[ separatorLength ] ); foundSeparator = strstr( workingString, inSeparator ); } // add the remaining part, even if it is the empty string parts->push_back( stringDuplicate( workingString ) ); delete [] workingStart; *outNumParts = parts->size(); char **returnArray = parts->getElementArray(); delete parts; return returnArray; } char *join( char **inStrings, int inNumParts, const char *inGlue ) { SimpleVector result; for( int i=0; i *inTargetVector, SimpleVector *inSubstituteVector ) { int numTargets = inTargetVector->size(); char *newHaystack = stringDuplicate( inHaystack ); char tagFound; for( int i=0; igetElement( i ) ), *( inSubstituteVector->getElement( i ) ), &tagFound ); delete [] newHaystack; newHaystack = newHaystackWithReplacements; } return newHaystack; } SimpleVector *tokenizeString( const char *inString ) { char *tempString = stringDuplicate( inString ); char *restOfString = tempString; SimpleVector *foundTokens = new SimpleVector(); SimpleVector *currentToken = new SimpleVector(); while( restOfString[0] != '\0' ) { // characters remain // skip whitespace char nextChar = restOfString[0]; while( nextChar == ' ' || nextChar == '\n' || nextChar == '\r' || nextChar == '\t' ) { restOfString = &( restOfString[1] ); nextChar = restOfString[0]; } if( restOfString[0] != '\0' ) { // a token while( nextChar != ' ' && nextChar != '\n' && nextChar != '\r' && nextChar != '\t' && nextChar != '\0' ) { // still not whitespace currentToken->push_back( nextChar ); restOfString = &( restOfString[1] ); nextChar = restOfString[0]; } // reached end of token foundTokens->push_back( currentToken->getElementString() ); currentToken->deleteAll(); } } delete [] tempString; delete currentToken; return foundTokens; } char *autoSprintf( const char* inFormatString, ... ) { unsigned int bufferSize = 50; va_list argList; va_start( argList, inFormatString ); char *buffer = new char[ bufferSize ]; int stringLength = vsnprintf( buffer, bufferSize, inFormatString, argList ); va_end( argList ); if( stringLength != -1 ) { // follows C99 standard... // stringLength is the length of the string that would have been // written if the buffer was big enough // not room for string and terminating \0 in bufferSize bytes if( (unsigned int)stringLength >= bufferSize ) { // need to reprint with a bigger buffer delete [] buffer; bufferSize = (unsigned int)( stringLength + 1 ); va_list argList; va_start( argList, inFormatString ); buffer = new char[ bufferSize ]; // can simply use vsprintf now vsprintf( buffer, inFormatString, argList ); va_end( argList ); return buffer; } else { // buffer was big enough // trim the buffer to fit the string char *returnString = stringDuplicate( buffer ); delete [] buffer; return returnString; } } else { // follows old ANSI standard // -1 means the buffer was too small // Note that some buggy non-C99 vsnprintf implementations // (notably MinGW) // do not return -1 if stringLength equals bufferSize (in other words, // if there is not enough room for the trailing \0). // Thus, we need to check for both // (A) stringLength == -1 // (B) stringLength == bufferSize // below. // keep doubling buffer size until it's big enough while( stringLength == -1 || (unsigned int)stringLength == bufferSize ) { delete [] buffer; if( (unsigned int)stringLength == bufferSize ) { // only occurs if vsnprintf implementation is buggy // might as well use the information, though // (instead of doubling the buffer size again) bufferSize = bufferSize + 1; } else { // double buffer size again bufferSize = 2 * bufferSize; } va_list argList; va_start( argList, inFormatString ); buffer = new char[ bufferSize ]; stringLength = vsnprintf( buffer, bufferSize, inFormatString, argList ); va_end( argList ); } // trim the buffer to fit the string char *returnString = stringDuplicate( buffer ); delete [] buffer; return returnString; } }