/*=========================================================================== * * File: DL_Str.CPP * Author: Dave Humphrey (uesp@m0use.net) * Created On: Saturday, May 05, 2001 * * Comtains implementation of string related functions for Dave's Library * of common code. * *=========================================================================*/ /* Include Files */ #include "dl_str.h" #include "dl_chr.h" #include <ctype.h> /*=========================================================================== * * Begin Local Variable Definitions * *=========================================================================*/ DEFINE_FILE(); /*=========================================================================== * End of Local Variable Definitions *=========================================================================*/ /*=========================================================================== * * Function - size_t CountSubstrings (pSourceString, pSearchString); * * Counts the number of times pSearchString occurs in pSourceString. * ASSERTs if any input is invalid. Supports finding of overlapping * search strings, for example, a count of strings "yy" in string "yyyyyy" * yields 5 (rather than just 3 if it didn't support overlapping strings). * *=========================================================================*/ size_t CountSubstrings (const char* pSourceString, const char* pSearchString) { DEFINE_FUNCTION("CountSubstrings()"); size_t Count = 0; char* pFind; /* Ensure valid input */ ASSERT(pSourceString != NULL && pSearchString != NULL); pFind = (char *)strstr(pSourceString, pSearchString); while (pFind != NULL) { Count++; pFind = strstr(pFind+1, pSearchString); } return (Count); } /*=========================================================================== * End of Function CountSubstrings() *=========================================================================*/ /*=========================================================================== * * Function - boolean IsStringNumber (pString); * * Returns TRUE if the string is composed only of whitespace and numbers * from 0 to 9. * *=========================================================================*/ boolean IsStringNumber (const char* pString) { DEFINE_FUNCTION("IsStringNumber()"); /* Ensure valid input */ ASSERT(pString != NULL); /* Parse string character by character */ while (*pString != NULL_CHAR) { if (!isspace(*pString) && !isdigit(*pString)) return (FALSE); pString++; } return (TRUE); } /*=========================================================================== * End of Function IsStringNumber() *=========================================================================*/ /*=========================================================================== * * Function - boolean IsStringDigit (pString); * * Returns TRUE if the string is composed only of decimal numbers 0 to 9. * *=========================================================================*/ boolean IsStringDigit (const char* pString) { DEFINE_FUNCTION("IsStringDigit()"); /* Ensure valid input */ ASSERT(pString != NULL); /* Parse string character by character */ while (*pString != NULL_CHAR) { if (!isdigit(*pString)) return (FALSE); pString++; } return (TRUE); } /*=========================================================================== * End of Function IsStringDigit() *=========================================================================*/ /*=========================================================================== * * Function - char* ltrim (char* pString); * * Strips all space characters from the left side of the given string, * returning a pointer to the first non-whitespace character. * Space characters include spaces, tabs and line feeds a defined by * the isspace() function. ASSERTs if given invalid input. * *=========================================================================*/ char* ltrim (char* pString) { DEFINE_FUNCTION("ltrim()"); size_t Index = 0; /* Ensure valid input */ ASSERT(pString != NULL); /* Ignore any spaces or TABs until end of string */ while (pString[Index] != '\0' && isspace(pString[Index])) { Index++; } /* Return pointer to the first non-whitespace char */ return (pString + Index); } /*=========================================================================== * End of Function ltrim() *=========================================================================*/ /*=========================================================================== * * Function - char* rtrim (char* pString); * * Strips all space characters from the right side of the given string, * returning a pointer to the modified string. Space characters include * spaces, tabs and line feeds a defined by the isspace() function. * ASSERTs if given invalid input. * *=========================================================================*/ char* rtrim (char* pString) { DEFINE_FUNCTION("rtrim()"); size_t Index; /* Ensure valid input */ ASSERT(pString != NULL); /* Start at the end of the string */ Index = strlen(pString); while (Index != 0) { Index--; /* Terminate string and return if non-whitespace found */ if (!isspace(pString[Index])) { pString[Index + 1] = NULL_CHAR; return (pString); } } /* Return an empty string */ *pString = NULL_CHAR; return (pString); } /*=========================================================================== * End of Function rtrim() *=========================================================================*/ /*=========================================================================== * * Function - boolean SeperateVarValue (ppVariable, ppValue, pString, SeperatorChar = '=', CommentChar = '#'); * * Takes the input string and attempts to seperate it into a variable/value * pair. If the CommentChar is non-NULL, everything after the last comment * character in a line is ignored. The string is then split into two * where the first SeperatorChar is found. Whitespace is trimmed and the * results stored in ppVariable and ppValue. Returns TRUE on success. * FALSE is returned if no variable/value pair was found (ppVariable then * points to the string with no comments and whitespace trimmed). * ASSERTs if given invalid input. * *=========================================================================*/ boolean SeperateVarValue (char** ppVariable, char** ppValue, char* pString, const char SeperatorChar, const char CommentChar) { DEFINE_FUNCTION("SeperateVarValue()"); char* pParse; /* Ensure valid input */ ASSERT(ppVariable != NULL && ppValue != NULL && pString != NULL); ASSERT(SeperatorChar != NULL_CHAR); /* Remove any comments from string, if required */ if (CommentChar != NULL_CHAR) chrrtrunc(pString, CommentChar); /* Look for the seperator char */ *ppVariable = trim(pString); pParse = strchr(pString, SeperatorChar); if (pParse == NULL) return (FALSE); *pParse = NULL_CHAR; /* Remove trailing spaces from variable */ rtrim(*ppVariable); /* Remove leading spaces from the value */ *ppValue = ltrim(pParse + 1); return (TRUE); } /*=========================================================================== * End of Function SeperateVarValue() *=========================================================================*/ /*=========================================================================== * * Function - boolean StringToBoolean (pString); * * Returns the boolean equivalent of a string. For use when it doesn't * matter if the string does not represent a boolean string. * * See Also: StringToBoolean (boolean&, char*); * *=========================================================================*/ boolean StringToBoolean (const char* pString) { //DEFINE_FUNCTION("StringToBoolean(char*)"); boolean Flag = FALSE; StringToBoolean(Flag, pString); return (Flag); } /*=========================================================================== * End of Function StringToBoolean() *=========================================================================*/ /*=========================================================================== * * Function - boolean StringToBoolean (Flag, pString); * * Atempts to convert a string to a boolean TRUE/FALSE value, returning * the result in the Flag referenced variable. Returns TRUE if the * string was successfully parsed to a boolean, or FALSE otherwise. * ASSERTs if passed invalid input. * 1. Checks string against 'TRUE' or 'FALSE', case insensitive * 2. Checks for a zero/non-zero integral value. * 3. If conversion to a number failed, FALSE is returned. * * See Also: StringToBoolean (char*); * *=========================================================================*/ boolean StringToBoolean (boolean& Flag, const char* pString) { DEFINE_FUNCTION("StringToBoolean(boolean&, char*)"); char* pError; long Result; /* Make sure the string is valid */ ASSERT(pString != NULL); /* See if the string contains explicit TRUE/FALSE strings */ if (stricmp(pString, "TRUE") == 0) { Flag = TRUE; return (TRUE); } else if (stricmp(pString, "FALSE") == 0) { Flag = FALSE; return (TRUE); } /* Special case for an empty string */ else if (*pString == NULL_CHAR) { return (FALSE); } /* Convert the string to a number as a last resort*/ Result = strtol(pString, &pError, 0); if (*pError != NULL_CHAR) return (FALSE); Flag = (boolean) (Result == 0) ? FALSE : TRUE; return (TRUE); } /*=========================================================================== * End of Function StringToBoolean() *=========================================================================*/ /*=========================================================================== * * Function - boolean StringChanged (pString1, pString2, CaseSensitive); * * Smart string compare which returns TRUE if the two strings are different. * Handles NULL cases and case sensitivity. Default is case insensitive. * *=========================================================================*/ boolean StringChanged (const char* pString1, const char* pString2, const boolean CaseSensitive) { //DEFINE_FUNCTION("StringChanged()"); /* Check for NULL strings */ if (pString1 == NULL && pString2 == NULL) return (FALSE); if (pString1 == NULL) return (TRUE); if (pString2 == NULL) return (TRUE); /* Compare the two valid strings depending on the case option */ if (CaseSensitive) { if (strcmp(pString1, pString2) == 0) return (FALSE); } else { if (stricmp(pString1, pString2) == 0) return (FALSE); } return (TRUE); } /*=========================================================================== * End of Function StringChanged() *=========================================================================*/ /*========================================================================= * * Function - size_t strhgt (pString); * * Returns the number of lines in the string (seperated by a Line Feed). * ASSERTs if given invalid input. * *=======================================================================*/ size_t strhgt (const char* pString) { DEFINE_FUNCTION("strhgt()"); size_t LineCount = 1; /* Ensure valid input */ ASSERT(pString != NULL); while (*pString != NULL_CHAR) { if (*pString == LF_CHAR) LineCount++; pString++; } return (LineCount); } /*========================================================================= * End of Function strhgt() *=======================================================================*/ /*=========================================================================== * * Function - char* stristr (pString, pSearchString); * * Returns the first position of the given substring in the string, ignoring * case. Returns NULL if the substring is not found in the string. ASSERTs * if given invalid input. Functions the same as the standard strstr() * function. * *=========================================================================*/ char* stristr (const char* pString, const char* pSearchString) { DEFINE_FUNCTION("stristr()"); size_t StringIndex = 0; size_t SearchIndex = 0; /* Ensure valid input */ ASSERT(pString != NULL && pSearchString != NULL); /* Special case for an empty search string */ if (*pSearchString == NULL_CHAR) return (NULL); /* The main search loop */ while (pString[StringIndex] != NULL_CHAR) { if (toupper(pString[StringIndex]) == toupper(pSearchString[SearchIndex])) { SearchIndex++; if (pSearchString[SearchIndex] == NULL_CHAR) return(((char *)pString) + StringIndex - SearchIndex + 1); } else if (SearchIndex != 0) { StringIndex -= SearchIndex; SearchIndex = 0; } StringIndex++; } /* Nothing found... */ return (NULL); } /*=========================================================================== * End of Function stristr() *=========================================================================*/ /*========================================================================= * * Function - int strlicmp (pString1, pString2); * * Compares the two strings, up to the end of the shortest string, * with case insensitivity. ASSERTs if given invalid input. Returns * same values as the strcmp() function: * < 0 : String1 is less than String2 * = 0 : String1 is the same as String2 * > 0 : String1 is greater than String2 * *=======================================================================*/ int strlicmp (const char *pString1, const char *pString2) { DEFINE_FUNCTION("strlicmp()"); int StringDifference; size_t Index = 0; /* Can't use NULL pointers */ ASSERT(pString1 != NULL && pString2 != NULL); /* Compare the strings up to end of string */ while (pString1[Index] != NULL_CHAR && pString2[Index] != NULL_CHAR) { StringDifference = toupper(pString1[Index]) - toupper(pString2[Index]); if (StringDifference != 0) return (StringDifference); Index++; } return (0); } /*========================================================================= * End of Function strlicmp() *=======================================================================*/ /*=========================================================================== * * Function - size_t strlinelen (pString); * * Returns the number of characters up to the first Line Feed in the * string, or the end of the string if no CR is found. ASSERTs if input * is invalid. * *=========================================================================*/ size_t strlinelen (const char* pString) { DEFINE_FUNCTION("strlinelen()"); size_t Index = 0; /* Ensure valid input */ ASSERT(pString != NULL); /* Find end of string or first CR */ while (pString[Index] != NULL_CHAR && pString[Index] != LF_CHAR) { Index++; } return (Index); } /*=========================================================================== * End of Function strlinelen() *=========================================================================*/ /*========================================================================= * * Function - char *strlwr (string); * * Converts a string to lowercase. Only used if not available in * the current system. ASSERTs if given invalid input. * *=======================================================================*/ #if !defined(__TURBOC__) && !defined(_WIN32) char* strlwr (char* pString) { DEFINE_FUNCTION("strlwr()"); size_t Index = 0; /* Ensure valid input */ ASSERT(pString != NULL); while (pString[Index] != NULL_CHAR) { pString[Index] = (char)tolower(pString[Index]); Index++; } return (pString); } #endif /*========================================================================= * End of Function strlwr() *=======================================================================*/ /*========================================================================= * * Function - size_t strmaxlinelen (pString); * * Finds and returns the length of the longest substring in the string * separated by Line Feeds. ASSERTs if given invalid input. * *=======================================================================*/ size_t strmaxlinelen (const char* pString) { DEFINE_FUNCTION("strmaxlinelen()"); size_t LineLength = 0; size_t MaxLineLength = 0; /* Ensure valid input */ ASSERT(pString != NULL); /* Find all lines in string */ while (*pString != NULL_CHAR) { if (*pString == LF_CHAR) { if (LineLength > MaxLineLength) MaxLineLength = LineLength; LineLength = 0; } else { LineLength++; } pString++; } if (LineLength > MaxLineLength) MaxLineLength = LineLength; return (MaxLineLength); } /*========================================================================= * End of Function strmaxlinelen() *=======================================================================*/ /*======================================================================== * * Function - int strnicmp (pString1, pString2, MaxStringLength); * * Compares the two strings, up to the max length characters, and returns * a value based on their equality (with case insensitivity). * < 0 : String1 is less than String2 * = 0 : String1 is the same as String2 * > 0 : String1 is greater than String2 * ASSERTs if given invalid inputs. Is only used in systems where a * similar function is not available. * *=======================================================================*/ #if !defined(__TURBOC__) && !defined(_WIN32) int strnicmp (const char* pString1, const char* pString2, const size_t MaxStringLength) { DEFINE_FUNCTION("strnicmp()"); int StringDiff; size_t Index = 0; /* Ensure valid inputs */ ASSERT(pString1 != NULL && pString2 != NULL); /* Compare the strings up to maxlen or end of string */ while (pString1[Index] != NULL_CHAR && pString2[Index] != NULL_CHAR && Index < MaxStringLength) { StringDiff = toupper(pString1[Index]) - toupper(pString2[Index]); if (StringDiff != 0) return (StringDiff); Index++; } if (Index == MaxStringLength) return (0); return (toupper(pString1[Index]) - toupper(pString2[Index])); } #endif /*========================================================================= * End of Function strnicmp() *=======================================================================*/ /*========================================================================= * * Function - char *strnncpy (pDestString, pSourceString, MaxStringLegth); * * Just like the standard strncpy function but appends a NUL character * to the end of the destination if required. Returns a pointer to the * destination string. ASSERTs if given invalid input. * *=======================================================================*/ char* strnncpy (char* pDestString, const char* pSourceString, const size_t MaxStringLength) { DEFINE_FUNCTION("strnncpy()"); size_t Index = 0; /* Ensure valid Input */ ASSERT(pDestString != NULL && pSourceString != NULL); /* Start copying */ while (Index < MaxStringLength && *pSourceString != NULL_CHAR) { pDestString[Index] = *pSourceString; pSourceString++; Index++; } /* Null terminate */ pDestString[Index] = NULL_CHAR; return (pDestString); } /*========================================================================= * End of Function strnncpy() *=======================================================================*/ /*========================================================================= * * Function - char* strproper (pString); * * Converts the specified string to proper case (first letter in each word * is capitalized). Returns a pointer to the modified string. ASSERTs * if given invalid input. Whitespace is defined according to the * isspace() function. * *=======================================================================*/ char* strproper (char* pString) { DEFINE_FUNCTION("strproper()"); char* pInitialString = pString; /* Make sure it is a valid string */ ASSERT(pString != NULL); /* Find the next non-whitespace character */ while (*pString != NULL_CHAR) { pString = ltrim(pString); *pString = (char)toupper(*pString); /* Find the next whitespace character */ while (*pString != NULL_CHAR && !isspace(*pString)) { pString++; } } /* Return the string pointer */ return (pInitialString); } /*========================================================================= * End of Function strproper() *=======================================================================*/ /*========================================================================= * * Function - char *strupr (string); * * Converts a string to uppercase. Only used if not available in * the current system. ASSERTs if given invalid input. * *=======================================================================*/ #if !defined(__TURBOC__) && !defined(_WIN32) char* strupr (char* pString) { DEFINE_FUNCTION("strupr()"); size_t Index = 0; /* Ensure valid input */ ASSERT(pString != NULL); while (pString[Index] != NULL_CHAR) { pString[Index] = (char)toupper(pString[Index]); Index++; } return (pString); } #endif /*========================================================================= * End of Function strupr() *=======================================================================*/ /*=========================================================================== * * Function - int snprintf (pBuffer, MaxLength, pFormat, ...); * * Similar to the sprintf() function which outputs a printf() formatted * list of arguments to a string buffer, but also limits the number of * bytes output to the buffer. For systems that have no builtin version * of a snprintf() function, the function ASSERTs if more than MaxLength * characters have been output to the buffer. Returns the number of * bytes output to the string, or negative value on error. * * See Also: vsnprintf() * *=========================================================================*/ int snprintf (char* pBuffer, const size_t MaxLength, const char* pFormat, ...) { DEFINE_FUNCTION("vsnprintf()"); va_list Args; int Result; /* Ensure valid input */ ASSERT(pBuffer != NULL && pFormat != NULL); va_start(Args, pFormat); Result = vsnprintf (pBuffer, MaxLength, pFormat, Args); va_end(Args); return (Result); } /*=========================================================================== * End of Function snprintf() *=========================================================================*/ /*=========================================================================== * * Function - int vsnprintf (pBuffer, MaxLength, pFormat, Args); * * Similar to the function vsprintf() which outputs a variable list of * arguments to a string buffer, but outputs a maximum of MaxLength bytes * to the output buffer. In systems that have no builtin vsnprintf() * type function, the function ASSERTs if more than MaxLength characters * are output to the buffer. Returns the number of characters output * to the buffer, not including the terminating NULL character, or a * negative value on any error. * *=========================================================================*/ int vsnprintf (char* pBuffer, const size_t MaxLength, const char* pFormat, va_list Args) { DEFINE_FUNCTION("vsnprintf()"); int Result; /* Ensure valid input */ ASSERT(pBuffer != NULL && pFormat != NULL); /* Windows has a builtin vsnprintf() type function */ #if defined(_WIN32) && !defined(__BCPLUSPLUS__) Result = _vsnprintf(pBuffer, MaxLength, pFormat, Args); #else Result = vsprintf(pBuffer, pFormat, Args); //ASSERT(Result >= 0 && ((size_t)Result) <= MaxLength); if (Result > 0 && (size_t)Result > MaxLength) { ErrorHandler.AddError(ERR_OVERFLOW, "Wrote %d bytes to a maximum buffer size of %u bytes!", Result, MaxLength); Result = -1; } #endif if (Result < 0) pBuffer[MaxLength] = NULL_CHAR; return (Result); } /*=========================================================================== * End of Function vsnprintf() *=========================================================================*/ /*=========================================================================== * * Begin Module Test Routines * * Test routines for the functions in this module. Only defined in * DEBUG builds. * *=========================================================================*/ #if defined(_DEBUG) /* Turn off compiler warning options */ #if defined(__BCPLUSPLUS__) #pragma warn -rch #pragma warn -ccc #endif /*=========================================================================== * * Function - void Test_CountSubstrings (void); * * Tests the CountSubstrings() function * 1. Checks function with a regular search string * 2. Tests with a string containing overlapping search strings. * 3. Test empty string case * 4. Test nosubstrings case * *=========================================================================*/ void Test_CountSubstrings (void) { DEFINE_FUNCTION("Test_CountSubstrings()"); char TestString[101]; size_t Result; SystemLog.Printf(stdout, "============= Testing CountSubstrings() ===================="); /* Check function with a regular string */ strcpy(TestString, ".....11....11..11...11.11"); Result = CountSubstrings(TestString, "11"); ASSERT(Result == 5); /* Check function with string containing overlapping strings */ strcpy(TestString, "...1111....111111"); Result = CountSubstrings(TestString, "11"); ASSERT(Result == 8); /* Check function with a empty string */ strcpy(TestString, ""); Result = CountSubstrings(TestString, "11"); ASSERT(Result == 0); /* Check function with a string with no substrings*/ strcpy(TestString, ".....22....22..22...22.22"); Result = CountSubstrings(TestString, "11"); ASSERT(Result == 0); } /*=========================================================================== * End of Function Test_CountSubstrings() *=========================================================================*/ /*=========================================================================== * * Function - void Test_ltrim (void); * * Tests the ltrim() function. * 1. Test string with whitespace to remove * 2. Test string with no whitespace * 3. Test string with all whitespace * 4. Test empty string * *=========================================================================*/ void Test_ltrim (void) { DEFINE_FUNCTION("Test_ltrim()"); char TestString[101]; char* pTrimmed; SystemLog.Printf(stdout, "============= Testing ltrim() ===================="); /* Check with a regular string with whitespace */ strcpy(TestString, " \t\t 123"); pTrimmed = ltrim(TestString); ASSERT(strcmp(pTrimmed, "123") == 0); /* Check with a regular string with no whitespace */ strcpy(TestString, "123"); pTrimmed = ltrim(TestString); ASSERT(strcmp(pTrimmed, "123") == 0); /* Check with a regular string with all whitespace */ strcpy(TestString, " \t\t "); pTrimmed = ltrim(TestString); ASSERT(strcmp(pTrimmed, "") == 0); /* Check with a emnpty string*/ strcpy(TestString, ""); pTrimmed = ltrim(TestString); ASSERT(strcmp(pTrimmed, "") == 0); } /*=========================================================================== * End of Function Test_ltrim() *=========================================================================*/ /*=========================================================================== * * Function - void Test_rtrim (void); * * Tests the rtrim() function. * 1. Test string with whitespace to remove * 2. Test string with no whitespace * 3. Test string with all whitespace * 4. Test empty string * *=========================================================================*/ void Test_rtrim (void) { DEFINE_FUNCTION("Test_rtrim()"); char TestString[101]; char* pTrimmed; SystemLog.Printf(stdout, "============= Testing rtrim() ===================="); /* Check with a regular string with whitespace */ strcpy(TestString, "123 \t\t "); pTrimmed = rtrim(TestString); ASSERT(strcmp(pTrimmed, "123") == 0); /* Check with a regular string with no whitespace */ strcpy(TestString, "123"); pTrimmed = rtrim(TestString); ASSERT(strcmp(pTrimmed, "123") == 0); /* Check with a regular string with all whitespace */ strcpy(TestString, " \t\t "); pTrimmed = rtrim(TestString); ASSERT(strcmp(pTrimmed, "") == 0); /* Check with a empty string*/ strcpy(TestString, ""); pTrimmed = rtrim(TestString); ASSERT(strcmp(pTrimmed, "") == 0); } /*=========================================================================== * End of Function Test_rtrim() *=========================================================================*/ /*=========================================================================== * * Function - void Test_SeperateVarValue (void); * * Tests the SeperateVarValue() function. * 1. Tests for a variety of regular strings with Var, Value, and Comment * using default characters. * 2. Test using specific characters for seperation/comment * 3. Test with NULL comment character * 4. Test with string with no seperator character * *=========================================================================*/ void Test_SeperateVarValue (void) { DEFINE_FUNCTION("Test_SeperateVarValue()"); char TestString[101]; boolean Result; char* pVar; char* pVal; SystemLog.Printf(stdout, "============= Testing SeperateVarValue() ===================="); /* Test a regular string using function default characters */ strcpy(TestString, " Variable = Value # Comment"); Result = SeperateVarValue(&pVar, &pVal, TestString); ASSERT(Result); ASSERT(strcmp(pVar, "Variable") == 0); ASSERT(strcmp(pVal, "Value") == 0); /* Test a regular string using function default characters, no whitespace */ strcpy(TestString, "Variable=Value#Comment"); Result = SeperateVarValue(&pVar, &pVal, TestString); ASSERT(Result); ASSERT(strcmp(pVar, "Variable") == 0); ASSERT(strcmp(pVal, "Value") == 0); /* Test a string with multiple characters */ strcpy(TestString, " Variable === Value ###Comment"); Result = SeperateVarValue(&pVar, &pVal, TestString); ASSERT(Result); ASSERT(strcmp(pVar, "Variable") == 0); ASSERT(strcmp(pVal, "== Value ##") == 0); /* Test a regular string using specific seperator character */ strcpy(TestString, " Variable * Value # Comment"); Result = SeperateVarValue(&pVar, &pVal, TestString, '*'); ASSERT(Result); ASSERT(strcmp(pVar, "Variable") == 0); ASSERT(strcmp(pVal, "Value") == 0); /* Test a regular string using specific characters */ strcpy(TestString, " Variable * Value { Comment"); Result = SeperateVarValue(&pVar, &pVal, TestString, '*', '{'); ASSERT(Result); ASSERT(strcmp(pVar, "Variable") == 0); ASSERT(strcmp(pVal, "Value") == 0); /* Test a regular string with NULL comment character */ strcpy(TestString, " Variable = Value#Comment"); Result = SeperateVarValue(&pVar, &pVal, TestString, '=', NULL_CHAR); ASSERT(Result); ASSERT(strcmp(pVar, "Variable") == 0); ASSERT(strcmp(pVal, "Value#Comment") == 0); /* Test a regular string with no seperator character */ strcpy(TestString, " Variable # Comment"); Result = SeperateVarValue(&pVar, &pVal, TestString); ASSERT(Result == FALSE); ASSERT(strcmp(pVar, "Variable") == 0); } /*=========================================================================== * End of Function Test_SeperateVarValue() *=========================================================================*/ /*=========================================================================== * * Function - void Test_StringToBoolean (void); * * Tests the StringToBoolean() function. * 1. Tests strings of 'TRUE' and 'FALSE' * 2. Tests strings with positive/negative decimal numbers * 3. Tests with octal and hexadecimal numbers * 4. Tests with invalid boolean strings * *=========================================================================*/ void Test_StringToBoolean (void) { DEFINE_FUNCTION("Test_StringToBoolean()"); char TestString[101]; boolean Flag; boolean Result; SystemLog.Printf(stdout, "============= Testing StringToBoolean() ===================="); /* Test the 'TRUE' string */ strcpy(TestString, "True"); Result = StringToBoolean(Flag, TestString); ASSERT(Result); ASSERT(Flag == TRUE); /* Test the 'FALSE' string */ strcpy(TestString, "FaLsE"); Result = StringToBoolean(Flag, TestString); ASSERT(Result); ASSERT(Flag == FALSE); /* Test the '0' decimal string */ strcpy(TestString, "0"); Result = StringToBoolean(Flag, TestString); ASSERT(Result); ASSERT(Flag == FALSE); /* Test the '1' decimal string */ strcpy(TestString, "1"); Result = StringToBoolean(Flag, TestString); ASSERT(Result); ASSERT(Flag == TRUE); /* Test the '-1' decimal string */ strcpy(TestString, "-1"); Result = StringToBoolean(Flag, TestString); ASSERT(Result); ASSERT(Flag == TRUE); /* Test the '103' decimal string */ strcpy(TestString, "103"); Result = StringToBoolean(Flag, TestString); ASSERT(Result); ASSERT(Flag == TRUE); /* Test an octal string */ strcpy(TestString, "05"); Result = StringToBoolean(Flag, TestString); ASSERT(Result); ASSERT(Flag == TRUE); /* Test a hexadecimal string */ strcpy(TestString, "0xf5"); Result = StringToBoolean(Flag, TestString); ASSERT(Result); ASSERT(Flag == TRUE); /* Test with empty string */ strcpy(TestString, ""); Result = StringToBoolean(Flag, TestString); ASSERT(Result == FALSE); /* Test with invalid string */ strcpy(TestString, "asd9p8adsf"); Result = StringToBoolean(Flag, TestString); ASSERT(Result == FALSE); } /*=========================================================================== * End of Function Test_StringToBoolean() *=========================================================================*/ /*=========================================================================== * * Function - void Test_StringChanged (void); * * Tests the StringChanged() function * 1. Tests all possible NULL cases. * 2. Check TRUE and FALSE regular cases with default case sensitivity. * 3. Check TRUE and FALSE regular cases with case sensitivity. * 4. Check TRUE and FALSE regular cases without case sensitivity. * 5. Check empty string cases * *=========================================================================*/ void Test_StringChanged (void) { DEFINE_FUNCTION("Test_StringChanged()"); boolean Result; SystemLog.Printf(stdout, "============= Testing StringChanged() ===================="); /* Check double-NULL case */ Result = StringChanged(NULL, NULL); ASSERT(Result == FALSE); /* Check single-NULL case #1 */ Result = StringChanged(NULL, "asd"); ASSERT(Result == TRUE); /* Check single-NULL case #2 */ Result = StringChanged("asd", NULL); ASSERT(Result == TRUE); /* Check FALSE regular case with default case sensitivity */ Result = StringChanged("asd", "ASD"); ASSERT(Result == FALSE); /* Check TRUE regular case with default case sensitivity */ Result = StringChanged("111", "ASD"); ASSERT(Result == TRUE); /* Check FALSE regular case with case sensitivity */ Result = StringChanged("asd", "asd", TRUE); ASSERT(Result == FALSE); /* Check TRUE regular case with case sensitivity */ Result = StringChanged("ASD", "asd", TRUE); ASSERT(Result == TRUE); /* Check TRUE regular case with case sensitivity */ Result = StringChanged("111", "ASD", TRUE); ASSERT(Result == TRUE); /* Check FALSE regular case without case sensitivity */ Result = StringChanged("asd", "asd", FALSE); ASSERT(Result == FALSE); /* Check FALSE regular case without case sensitivity */ Result = StringChanged("ASD", "asd", FALSE); ASSERT(Result == FALSE); /* Check TRUE regular case without case sensitivity */ Result = StringChanged("111", "ASD", FALSE); ASSERT(Result == TRUE); /* Check empty string case */ Result = StringChanged("111", ""); ASSERT(Result == TRUE); /* Check empty string case */ Result = StringChanged("", ""); ASSERT(Result == FALSE); } /*=========================================================================== * End of Function Test_StringChanged() *=========================================================================*/ /*=========================================================================== * * Function - void Test_IsStringNumber (void); * * Tests the IsStringNumber() function * 1. Checks several typical positive/negative cases * 2. Checks empty string case. * *=========================================================================*/ void Test_IsStringNumber (void) { DEFINE_FUNCTION("Test_IsStringNumber()"); SystemLog.Printf(stdout, "============= Testing IsStringNumber() ===================="); /* Check several typical positive cases */ ASSERT(IsStringNumber(" 123 ") == TRUE); ASSERT(IsStringNumber("16285") == TRUE); ASSERT(IsStringNumber("\t1 2 3 4 5 6 7 8 9 0 ") == TRUE); /* Check several typical negative cases */ ASSERT(IsStringNumber("123.6") == FALSE); ASSERT(IsStringNumber("0xC5") == FALSE); /* Check the empty string case */ ASSERT(IsStringNumber("") == TRUE); } /*=========================================================================== * End of Function Test_IsStringNumber() *========================================================================*/ /*=========================================================================== * * Function - void Test_strhgt (void); * * Tests the strhgt() function * 1. Test with typical strings * 2. Test with empty string * *=========================================================================*/ void Test_strhgt (void) { DEFINE_FUNCTION("Test_strhgt()"); SystemLog.Printf(stdout, "============= Testing strhgt() ===================="); /* Test several typical strings */ ASSERT(strhgt("Test String") == 1); ASSERT(strhgt("Test\nString") == 2); ASSERT(strhgt("\nTest\nString") == 3); ASSERT(strhgt("\n\nTest\nString") == 4); ASSERT(strhgt("Test\nString\n") == 3); ASSERT(strhgt("Test\nStri\nng") == 3); /* Test with empty string */ ASSERT(strhgt("") == 1); ASSERT(strhgt("\n") == 2); ASSERT(strhgt("\n\n") == 3); } /*=========================================================================== * End of Function Test_strhgt() *=========================================================================*/ /*=========================================================================== * * Function - void Test_stristr (void); * * Tests the stristr() function * 1. Test several typical positive/negative cases * 2. Check case insensitivity * 3. Check overlapping string case * 4. Check empty string cases * *=========================================================================*/ void Test_stristr (void) { DEFINE_FUNCTION("Test_stristr()"); char* pStr; SystemLog.Printf(stdout, "============= Testing stristr() ===================="); /* Check several typical positive cases */ pStr = stristr("0123456789", "45"); ASSERT(strcmp(pStr, "456789") == 0); pStr = stristr("0123456789", "01"); ASSERT(strcmp(pStr, "0123456789") == 0); pStr = stristr("0123456789", "789"); ASSERT(strcmp(pStr, "789") == 0); /* Check several typical negative cases */ pStr = stristr("0123456789", "ab"); ASSERT(pStr == NULL); /* Check case insensitivity */ pStr = stristr("aBcDeFG", "DEF"); ASSERT(stricmp(pStr, "defg") == 0); /* Check overlapping string case */ pStr = stristr("1111111234", "11112"); ASSERT(stricmp(pStr, "1111234") == 0); /* Check empty string cases */ pStr = stristr("", "111"); ASSERT(pStr == NULL); } /*=========================================================================== * End of Function Test_stristr() *=========================================================================*/ /*=========================================================================== * * Function - void Test_strlicmp (void); * * Test the strlicmp() function * 1. Test with typical equality cases. * 2. Test several less-than cases * 3. Test several greater-than cases * 4, Check empty string cases * *=========================================================================*/ void Test_strlicmp (void) { DEFINE_FUNCTION("Test_strlicmp()"); SystemLog.Printf(stdout, "============= Testing strlicmp() ===================="); /* Check several equal cases */ ASSERT(strlicmp("123", "123") == 0); ASSERT(strlicmp("AsD", "asd") == 0); ASSERT(strlicmp("123", "1234567") == 0); ASSERT(strlicmp("1234567", "123") == 0); /* Check several less-than cases */ ASSERT(strlicmp("123", "234") < 0); ASSERT(strlicmp("123", "124") < 0); /* Check several greater-than cases */ ASSERT(strlicmp("234", "123") > 0); ASSERT(strlicmp("124", "123") > 0); /* Check empty string cases */ ASSERT(strlicmp("123", "") == 0); ASSERT(strlicmp("", "124") == 0); ASSERT(strlicmp("", "") == 0); } /*=========================================================================== * End of Function Test_strlicmp() *=========================================================================*/ /*=========================================================================== * * Function - void Test_strlinelen (void); * * Tests the strlinelen() function * 1. Checks function with regular string with CR in middle/start/end * 2. Tests with string containing no CR * 3. Tests with empty string * 4. Tests with string with multiple CRs * *=========================================================================*/ void Test_strlinelen (void) { DEFINE_FUNCTION("Test_strlinelen()"); char TestString[101]; size_t Result; SystemLog.Printf(stdout, "============= Testing strlinelen() ===================="); /* Check with a regular string with CR in middle */ strcpy(TestString, "123456\n890"); Result = strlinelen(TestString); ASSERT(Result == 6); /* Check with a regular string with CR at end */ strcpy(TestString, "123456789\n"); Result = strlinelen(TestString); ASSERT(Result == 9); /* Check with a regular string with CR at start*/ strcpy(TestString, "\n234567890"); Result = strlinelen(TestString); ASSERT(Result == 0); /* Check with a regular string with no CR */ strcpy(TestString, "1234567890"); Result = strlinelen(TestString); ASSERT(Result == 10); ASSERT(Result == strlen(TestString)); /* Check with a empty string */ strcpy(TestString, ""); Result = strlinelen(TestString); ASSERT(Result == 0); /* Check with a regular string with multiple CRs */ strcpy(TestString, "12\n4\n6\n890"); Result = strlinelen(TestString); ASSERT(Result == 2); } /*=========================================================================== * End of Function Test_strlinelen() *=========================================================================*/ /*=========================================================================== * * Function - void Test_strmaxlinelen (void); * * Tests the strmaxlinelen() function. * 1. Tests with typical strings * 2. Test with empty string * *=========================================================================*/ void Test_strmaxlinelen (void) { DEFINE_FUNCTION("Test_strmaxlinelen()"); SystemLog.Printf(stdout, "============= Testing strmaxlinelen() ===================="); /* Test several typical strings */ ASSERT(strmaxlinelen("1234567890") == 10); ASSERT(strmaxlinelen("1\n234567890") == 9); ASSERT(strmaxlinelen("12345678\n90") == 8); ASSERT(strmaxlinelen("12\n34\n56\n78\n90") == 2); ASSERT(strmaxlinelen("123\n4567\n890") == 4); ASSERT(strmaxlinelen("\n\n\n") == 0); ASSERT(strmaxlinelen("\n1\n\n") == 1); /* Test empty string */ ASSERT(strmaxlinelen("") == 0); } /*=========================================================================== * End of Function Test_strmaxlinelen() *=========================================================================*/ /*=========================================================================== * * Function - void Test_strnicmp (void); * * Tests the strnicmp() function * 1. Test with typical equal strings * 2. Test with typical less than strings * 3. Test with typical greater than strings * 4. Test with empty strings * *=========================================================================*/ void Test_strnicmp (void) { DEFINE_FUNCTION("Test_strnicmp()"); SystemLog.Printf(stdout, "============= Testing strnicmp() ===================="); /* Test several equal strings */ ASSERT(strnicmp("123", "123", 5) == 0); ASSERT(strnicmp("123", "123", 2) == 0); ASSERT(strnicmp("abcdef123", "ABCDEF", 4) == 0); /* Test several less than strings */ ASSERT(strnicmp("123", "234", 5) < 0); ASSERT(strnicmp("123", "234", 2) < 0); /* Test several greater than strings */ ASSERT(strnicmp("234", "123", 5) > 0); ASSERT(strnicmp("234", "123", 2) > 0); /* Test several empty strings */ ASSERT(strnicmp("123", "", 5) > 0); ASSERT(strnicmp("", "234", 2) < 0); ASSERT(strnicmp("", "", 2) == 0); } /*=========================================================================== * End of Function Test_strnicmp() *=========================================================================*/ /*=========================================================================== * * Function - void Test_strnncpy (void); * * Tests the strnncpy() function. * 1. Test with regular strings * 2. Test with short strings to ensure strings are NULL terminated * 3. Test with empty string * *=========================================================================*/ void Test_strnncpy (void) { DEFINE_FUNCTION("Test_strnncpy()"); char TestString[101]; SystemLog.Printf(stdout, "============= Testing strnncpy() ===================="); /* Test a regular string copy */ strnncpy(TestString, "123456789", 50); ASSERT(strcmp(TestString, "123456789") == 0); /* Test a short string copy */ strnncpy(TestString, "123456789", 5); ASSERT(strcmp(TestString, "12345") == 0); /* Test an empty string copy */ strnncpy(TestString, "", 50); ASSERT(strcmp(TestString, "") == 0); } /*=========================================================================== * End of Function Test_strnncpy() *=========================================================================*/ /*=========================================================================== * * Function - void Test_strproper (void); * * Tests the string proper function. * 1. Test with several typical strings * 2. Test with empty string * 3. Test with string without whitespace * *=========================================================================*/ void Test_strproper (void) { DEFINE_FUNCTION("Test_strproper()"); char TestString[101]; SystemLog.Printf(stdout, "============= Testing strproper() ===================="); /* Check several typical strings */ strcpy(TestString, "this is\ta test"); ASSERT(strcmp(strproper(TestString), "This Is\tA Test") == 0); strcpy(TestString, " test\nnew line "); ASSERT(strcmp(strproper(TestString), " Test\nNew Line ") == 0); /* Check an empty string */ strcpy(TestString, ""); ASSERT(strcmp(strproper(TestString), "") == 0); /* Check a string without whitespace */ strcpy(TestString, "thisisastring"); ASSERT(strcmp(strproper(TestString), "Thisisastring") == 0); } /*=========================================================================== * End of Function Test_strproper() *=========================================================================*/ /*=========================================================================== * * Function - void Test_strupr (void); * * Tests the strupr()/strlwr() functions. * 1. Test strlwr() with typical strings * 2. Test strupr() with typical strings * *=========================================================================*/ void Test_strupr (void) { DEFINE_FUNCTION("Test_strupr()"); char TestString[101]; SystemLog.Printf(stdout, "============= Testing strlwr()/strupr() ===================="); /* Test strlwr() with typical strings */ strcpy(TestString, "ABCD 123 abcd"); ASSERT(strcmp(strlwr(TestString), "abcd 123 abcd") == 0); strcpy(TestString, ""); ASSERT(strcmp(strlwr(TestString), "") == 0); /* Test strupr() with typical strings */ strcpy(TestString, "ABCD 123 abcd"); ASSERT(strcmp(strupr(TestString), "ABCD 123 ABCD") == 0); strcpy(TestString, ""); ASSERT(strcmp(strupr(TestString), "") == 0); } /*=========================================================================== * End of Function Test_strupr() *=========================================================================*/ /*=========================================================================== * * Function - void Test_vsnprintf (void); * * Tests the vsnprintf() as well as the snprintf() functions. Note that * the snprintf() function is based on the vsnprintf() function, * 1. Test a plain string and ensure correct output * 2. Test outputting more than allowed string length * *=========================================================================*/ void Test_vsnprintf (void) { DEFINE_FUNCTION("Test_vsnprintf()"); char TestString[] = "This is a test string...\n\r 1010 kkasdlkj"; char OutputString[1024]; char* pShortString; int Result; SystemLog.Printf(stdout, "============= Testing vsnprintf() ===================="); /* Check basic function of snprintf() (and thus vsnprintf()) */ Result = snprintf(OutputString, 1000, "%s", TestString); ASSERT(Result > 0); ASSERT(Result == (int) strlen(TestString)); ASSERT(strcmp(OutputString, TestString) == 0); Result = snprintf(OutputString, 1000, TestString); ASSERT(Result > 0); ASSERT(Result == (int) strlen(TestString)); ASSERT(strcmp(OutputString, TestString) == 0); Result = snprintf (OutputString, 1000, "This %s, 101 = %d", "is a test", 101); ASSERT(Result > 0); SystemLog.Printf(stdout, "snprintf() Output: %s", OutputString); /* Check outputting more than allowed characters */ Result = snprintf (OutputString, 5, "Testing maximum 5 characters"); ASSERT(Result < 0); SystemLog.Printf(stdout, "snprintf(5) Output 1: %s", OutputString); pShortString = CreateString(6); Result = snprintf(pShortString, 5, "Testing max 5 characters"); ASSERT(Result < 0); SystemLog.Printf(stdout, "snprintf(5) Output 2: %s", pShortString); ASSERT(DebugHeapCheckMemory()); DestroyPointer(pShortString); } /*=========================================================================== * End of Function Test_vsnprintf() *=========================================================================*/ /*=========================================================================== * * Function - void Test_DLStr (void); * * Tests all the functions in this module. * 1. Tests the vsnprintf() and snprintf() functions * 2. Tests the CountSubstrings() function * 3. Tests the ltrim() and rtrim() functions * 4. Tests the strlinelen() function * 5. Tests the SeperateVarValue() function * 6. Tests the StringToBoolean() function * 7. Tests the StringChanged() function * 8. Tests the IsStringNumber() function * 9. Tests the stristr() function * 10.Tests the strlicmp() function * 11. Tests the strproper() function * 12. Tests the strhgt() function * 13. Tests the strmaxlinelen() function * 14. Tests the strupr()/strlwr() functions * 15. Tests the strnicmp() function * *=========================================================================*/ void Test_DLStr (void) { //DEFINE_FUNCTION("Test_DLStr()"); Test_vsnprintf(); Test_CountSubstrings(); Test_ltrim(); Test_rtrim(); Test_strlinelen(); Test_SeperateVarValue(); Test_StringToBoolean(); Test_StringChanged(); Test_IsStringNumber(); Test_stristr(); Test_strlicmp(); Test_strnncpy(); Test_strproper(); Test_strhgt(); Test_strmaxlinelen(); Test_strupr(); Test_strnicmp(); } /*=========================================================================== * End of Function Test_DLStr() *=========================================================================*/ /* Restore compiler warning options */ #if defined(__BCPLUSPLUS__) #pragma warn .rch #pragma warn .ccc #endif #endif /*=========================================================================== * End of Module Test Routines *=========================================================================*/