Initial source commit
This commit is contained in:
commit
f1384c11ee
335 changed files with 52715 additions and 0 deletions
450
minorGems/util/stringUtils.cpp
Normal file
450
minorGems/util/stringUtils.cpp
Normal file
|
@ -0,0 +1,450 @@
|
|||
/*
|
||||
* 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 <stdarg.h>
|
||||
|
||||
|
||||
|
||||
char *stringToLowerCase( const char *inString ) {
|
||||
|
||||
unsigned int length = strlen( inString );
|
||||
|
||||
char *returnString = stringDuplicate( inString );
|
||||
|
||||
for( unsigned int i=0; i<length; i++ ) {
|
||||
returnString[i] = (char)tolower( returnString[i] );
|
||||
}
|
||||
|
||||
return returnString;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *stringLocateIgnoreCase( const char *inHaystack,
|
||||
const char *inNeedle ) {
|
||||
|
||||
char *lowerHaystack = stringToLowerCase( inHaystack );
|
||||
char *lowerNeedle = stringToLowerCase( inNeedle );
|
||||
|
||||
char *matchPointer = strstr( lowerHaystack, lowerNeedle );
|
||||
|
||||
char *returnString = NULL;
|
||||
|
||||
if( matchPointer != NULL ) {
|
||||
|
||||
unsigned int matchRemainderLength = strlen( matchPointer );
|
||||
|
||||
unsigned int haystackIndex =
|
||||
strlen( inHaystack ) - matchRemainderLength;
|
||||
|
||||
returnString = (char*)( &( inHaystack[ haystackIndex ] ) );
|
||||
}
|
||||
|
||||
delete [] lowerHaystack;
|
||||
delete [] lowerNeedle;
|
||||
|
||||
return returnString;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int stringCompareIgnoreCase( const char *inStringA,
|
||||
const char *inStringB ) {
|
||||
|
||||
char *lowerA = stringToLowerCase( inStringA );
|
||||
char *lowerB = stringToLowerCase( inStringB );
|
||||
|
||||
int returnVal = strcmp( lowerA, lowerB );
|
||||
|
||||
delete [] lowerB;
|
||||
delete [] lowerA;
|
||||
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char stringStartsWith( const char *inString, const char *inPrefix ) {
|
||||
unsigned int prefixLength = strlen( inPrefix );
|
||||
unsigned int stringLength = strlen( inString );
|
||||
|
||||
if( prefixLength > stringLength ) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
for( unsigned int i=0; i<prefixLength; i++ ) {
|
||||
if( inString[i] != inPrefix[i] ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// all characters, up to prefix length, are equal in both strings
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
char **split( const char *inString, const char *inSeparator,
|
||||
int *outNumParts ) {
|
||||
SimpleVector<char *> *parts = new SimpleVector<char *>();
|
||||
|
||||
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<char> result;
|
||||
|
||||
for( int i=0; i<inNumParts - 1; i++ ) {
|
||||
result.appendElementString( inStrings[i] );
|
||||
result.appendElementString( inGlue );
|
||||
}
|
||||
// no glue after last string
|
||||
result.appendElementString( inStrings[ inNumParts - 1 ] );
|
||||
|
||||
char *returnString = result.getElementString();
|
||||
|
||||
return returnString;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *concatonate( const char *inStringA, const char *inStringB ) {
|
||||
char **tempArray = new char*[2];
|
||||
tempArray[ 0 ] = (char *)inStringA;
|
||||
tempArray[ 1 ] = (char *)inStringB;
|
||||
|
||||
char *result = join( tempArray, 2, "" );
|
||||
|
||||
delete [] tempArray;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *replaceOnce( const char *inHaystack, const char *inTarget,
|
||||
const char *inSubstitute,
|
||||
char *outFound ) {
|
||||
|
||||
char *haystackCopy = stringDuplicate( inHaystack );
|
||||
|
||||
char *fieldTargetPointer = strstr( haystackCopy, inTarget );
|
||||
|
||||
|
||||
if( fieldTargetPointer == NULL ) {
|
||||
// target not found
|
||||
*outFound = false;
|
||||
return haystackCopy;
|
||||
}
|
||||
else {
|
||||
// target found
|
||||
|
||||
// prematurely terminate haystack copy string at
|
||||
// start of target occurence
|
||||
// (okay, since we're working with a copy of the haystack argument)
|
||||
fieldTargetPointer[0] = '\0';
|
||||
|
||||
// pointer to first char after target occurrence
|
||||
char *fieldPostTargetPointer =
|
||||
&( fieldTargetPointer[ strlen( inTarget ) ] );
|
||||
|
||||
char *returnString = new char[
|
||||
strlen( inHaystack )
|
||||
- strlen( inTarget )
|
||||
+ strlen( inSubstitute ) + 1 ];
|
||||
|
||||
sprintf( returnString, "%s%s%s",
|
||||
haystackCopy,
|
||||
inSubstitute,
|
||||
fieldPostTargetPointer );
|
||||
|
||||
delete [] haystackCopy;
|
||||
|
||||
*outFound = true;
|
||||
return returnString;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *replaceAll( const char *inHaystack, const char *inTarget,
|
||||
const char *inSubstitute,
|
||||
char *outFound ) {
|
||||
|
||||
// repeatedly replace once until replacing fails
|
||||
|
||||
char lastFound = true;
|
||||
char atLeastOneFound = false;
|
||||
char *returnString = stringDuplicate( inHaystack );
|
||||
|
||||
while( lastFound ) {
|
||||
|
||||
char *nextReturnString =
|
||||
replaceOnce( returnString, inTarget, inSubstitute, &lastFound );
|
||||
|
||||
delete [] returnString;
|
||||
|
||||
returnString = nextReturnString;
|
||||
|
||||
if( lastFound ) {
|
||||
atLeastOneFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
*outFound = atLeastOneFound;
|
||||
|
||||
return returnString;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *replaceTargetListWithSubstituteList(
|
||||
const char *inHaystack,
|
||||
SimpleVector<char *> *inTargetVector,
|
||||
SimpleVector<char *> *inSubstituteVector ) {
|
||||
|
||||
int numTargets = inTargetVector->size();
|
||||
|
||||
char *newHaystack = stringDuplicate( inHaystack );
|
||||
|
||||
char tagFound;
|
||||
|
||||
for( int i=0; i<numTargets; i++ ) {
|
||||
char *newHaystackWithReplacements
|
||||
= replaceAll( newHaystack,
|
||||
*( inTargetVector->getElement( i ) ),
|
||||
*( inSubstituteVector->getElement( i ) ),
|
||||
&tagFound );
|
||||
delete [] newHaystack;
|
||||
|
||||
newHaystack = newHaystackWithReplacements;
|
||||
}
|
||||
|
||||
return newHaystack;
|
||||
}
|
||||
|
||||
|
||||
|
||||
SimpleVector<char *> *tokenizeString( const char *inString ) {
|
||||
|
||||
char *tempString = stringDuplicate( inString );
|
||||
|
||||
char *restOfString = tempString;
|
||||
|
||||
SimpleVector<char *> *foundTokens = new SimpleVector<char *>();
|
||||
|
||||
SimpleVector<char> *currentToken = new SimpleVector<char>();
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue