/*=========================================================================== * * File: DL_Chr.CPP * Author: Dave Humphrey (uesp@m0use.net) * Created On: Sunday, May 06, 2001 * * Implementation of character related functions for Dave's Library of * common code. * *=========================================================================*/ /* Include Files */ #include "dl_chr.h" #include <ctype.h> /*=========================================================================== * * Begin Local Variable Definitions * *=========================================================================*/ DEFINE_FILE(); /*=========================================================================== * End of Local Variable Definitions *=========================================================================*/ /*=========================================================================== * * Function - void chradd (pString, CharIndex, NewChar); * * Attempts to insert the specified character into the string at the * given position CharIndex. First character in string is at position 0. * Assumes the string is long enough to add another character. ASSERTs * if any invalid input is received. * *=========================================================================*/ void chradd (char* pString, const size_t CharIndex, const char NewChar) { DEFINE_FUNCTION("chradd()"); char* pInsertPosition; size_t StringLength; /* Ensure valid input */ ASSERT(pString != NULL); StringLength = strlen(pString); ASSERT(CharIndex <= StringLength); /* Shift the characters after insert position right by one */ pInsertPosition = pString + CharIndex; memmove (pInsertPosition + 1, pInsertPosition, StringLength - CharIndex + 1); /* Add the new character to the string */ *pInsertPosition = NewChar; } /*=========================================================================== * End of Function chradd() *=========================================================================*/ /*=========================================================================== * * Function - void chrcat (char* pString, const char NewChar); * * Attempts to add a character to the end of the given string. Assumes * that the string is long enough to add another character. ASSERTs if * any bad input is received. * *=========================================================================*/ void chrcat (char* pString, const char NewChar) { DEFINE_FUNCTION("chrcat()"); char* pInsertPosition; /* Ensure valid input */ ASSERT(pString != NULL); /* Find the end of the string */ pInsertPosition = pString + strlen(pString); /* Add the character to end of string, making sure we NULL terminate */ pInsertPosition[1] = NULL_CHAR; pInsertPosition[0] = NewChar; } /*=========================================================================== * End of Function chrcat() *=========================================================================*/ /*=========================================================================== * * Function - void chrdel (pString, CharIndex); * * Attempts to delete the character at the given position from the string. * Position 0 is the first character in the string. ASSERTs on any bad * input. * *=========================================================================*/ void chrdel (char* pString, const size_t CharIndex) { DEFINE_FUNCTION("chrdel()"); char* pDeletePosition; size_t StringLength; /* Ensure valid input */ ASSERT(pString != NULL); StringLength = strlen(pString); ASSERT(CharIndex <= StringLength); /* Shift the characters left of the deletion position by one */ pDeletePosition = pString + CharIndex; memmove (pDeletePosition, pDeletePosition + 1, StringLength - CharIndex); } /*=========================================================================== * End of Function chrdel() *=========================================================================*/ /*=========================================================================== * * Function - void chrdellast (pString); * * Deletes the last character from the string. ASSERTs on bad input. * *=========================================================================*/ void chrdellast (char* pString) { DEFINE_FUNCTION("chrdellast()"); size_t StringLength; /* Ensure valid input */ ASSERT(pString != NULL); /* Find last character in string, and ensure at least one exists */ StringLength = strlen(pString); /* Delete the last character in the string, if any */ if (StringLength > 0) pString[StringLength - 1] = NULL_CHAR; } /*=========================================================================== * End of Function chrdellast() *=========================================================================*/ /*=========================================================================== * * Function - boolean chrrpunc (CharIndex, pString); * * Looks for the first punctuation character from the end of the string. * Saves the character index if one is found (0 is the first character * in the string) and returns TRUE. Returns FALSE if no matching character * was found. ASSERTs on bad input. * *=========================================================================*/ boolean chrrpunc (size_t& CharIndex, const char* pString) { DEFINE_FUNCTION("chrrpunc()"); size_t StringPosition; /* Ensure valid input */ ASSERT(pString != NULL); /* Start at the end of the string */ StringPosition = strlen(pString); /* Look for a punctuating character until start of string is reached */ while (StringPosition != 0) { StringPosition--; if (ispunct(pString[StringPosition])) { CharIndex = StringPosition; return (TRUE); } } /* Character not found in string */ return (FALSE); } /*=========================================================================== * End of Function chrrpunc() *=========================================================================*/ /*=========================================================================== * * Function - char* chrtok (pString, TokenChar); * * Seperates the given string into substrings divided by the given token * character, as strtok(). Returns NULL when no substrings are * left. Uses an internal static variable which prevents use of nesting * chrtok() calls. ASSERTs on invalid input. The TokenChar cannot be * the terminating NULL character. * * Unlike strtok(), chrtok() ignores multiple occurences of the TokenChar, * for example, the TestString "11x22x33xxx44" * strtok(TestString, "x") = "11", "22", "33", "44" * chrtok(TestString, 'x') = "11", "22", "33", "", "", "44" * The use is otherwise identical to strok(). * *=========================================================================*/ char* chrtok (char* pString, const char TokenChar) { DEFINE_FUNCTION("chrtok()"); static char* pParse = NULL; char* pSearchChar; char* pResult; /* Ensure valid input */ ASSERT(TokenChar != NULL_CHAR); /* Check for end of parsed token string */ if (pString == NULL && pParse == NULL) return (NULL); /* Start parsing a new string */ if (pString != NULL) pParse = pString; /* Search for the next substring */ pSearchChar = strchr(pParse, TokenChar); /* No more substrings */ if (pSearchChar == NULL) { pResult = pParse; pParse = NULL; return (pResult); } /* Terminate substring */ *pSearchChar = NULL_CHAR; pResult = pParse; pParse = pSearchChar + 1; return (pResult); } /*=========================================================================== * End of Function chrtok() *=========================================================================*/ /*=========================================================================== * * Function - char* chrtrunc (pString, TruncateChar); * * Truncates the character at the first occurence of the given character. * Returns the string. ASSERTs if given invalid input. * *=========================================================================*/ char* chrtrunc (char* pString, const char TruncateChar) { DEFINE_FUNCTION("chrtrunc()"); char* pFindChar; /* Ensure valid input */ ASSERT(pString != NULL && TruncateChar != NULL_CHAR); /* Attempt to find the first truncation character */ pFindChar = strchr(pString, TruncateChar); if (pFindChar != NULL) *pFindChar = NULL_CHAR; return (pString); } /*=========================================================================== * End of Function chrtrunc() *=========================================================================*/ /*=========================================================================== * * Function - char* chrrtrunc (pString, TruncateChar); * * Truncates the character at the last occurence of the given character. * Returns the string. ASSERTs if given invalid input. * *=========================================================================*/ char* chrrtrunc (char* pString, const char TruncateChar) { DEFINE_FUNCTION("chrrtrunc()"); char* pFindChar; /* Ensure valid input */ ASSERT(pString != NULL && TruncateChar != NULL_CHAR); /* Attempt to find the last truncation character */ pFindChar = strrchr(pString, TruncateChar); if (pFindChar != NULL) *pFindChar = NULL_CHAR; return (pString); } /*=========================================================================== * End of Function chrrtrunc() *=========================================================================*/ /*=========================================================================== * * Begin Module Test Routines * * Test routines for the functions in this module. Only defined in * DEBUG builds. * *=========================================================================*/ #if defined(_DEBUG) /*=========================================================================== * * Function - void Test_chradd (void); * * Tests the chradd() function. * 1. Ensures characters are correctly inserted in middle of string * 2. Check adding characters at start of string * 3. Check adding characters at end of string * *=========================================================================*/ void Test_chradd (void) { DEFINE_FUNCTION("Test_chradd()"); char TestString[101] = "123456789"; SystemLog.Printf(stdout, "============= Testing chradd() ===================="); /* Add a character in the middle of the string */ chradd(TestString, 4, '4'); ASSERT(strcmp(TestString, "1234456789") == 0); /* Add a character at the start of the string */ chradd(TestString, 0, '0'); ASSERT(strcmp(TestString, "01234456789") == 0); /* Add a character at the end of the string */ chradd(TestString, 11, '0'); ASSERT(strcmp(TestString, "012344567890") == 0); } /*=========================================================================== * End of Function Test_chradd() *=========================================================================*/ /*=========================================================================== * * Function - void Test_chrcat (void); * * Test the chrcat() function. * 1. Tests adding a character to a regular string. * 2. Tests adding a character to an empty string. * *=========================================================================*/ void Test_chrcat (void) { DEFINE_FUNCTION("Test_chrcat()"); char TestString[101] = "123456789"; SystemLog.Printf(stdout, "============= Testing chrcat() ===================="); /* Test adding character to regular string */ chrcat(TestString, '0'); ASSERT(strcmp(TestString, "1234567890") == 0); /* Test adding character to empty string */ TestString[0] = NULL_CHAR; chrcat(TestString, '0'); ASSERT(strcmp(TestString, "0") == 0); } /*=========================================================================== * End of Function Test_chrcat() *=========================================================================*/ /*=========================================================================== * * Function - void Test_chrdel (void); * * Tests the chrdel() function * 1. Deletes characters from middle of regular string. * 2. Delete characters from start/end of string * 3. Test empty string deletion * *=========================================================================*/ void Test_chrdel (void) { DEFINE_FUNCTION("Test_chrdel()"); char TestString[101] = "123456789"; SystemLog.Printf(stdout, "============= Testing chrdel() ===================="); /* Delete characters from middle of string */ chrdel(TestString, 4); ASSERT(strcmp(TestString, "12346789") == 0); /* Delete characters from end of string */ chrdel(TestString, 7); ASSERT(strcmp(TestString, "1234678") == 0); /* Delete characters from start of string */ chrdel(TestString, 0); ASSERT(strcmp(TestString, "234678") == 0); /* Delete character from empty string */ TestString[0] = NULL_CHAR; chrdel(TestString, 0); ASSERT(strcmp(TestString, "") == 0); } /*=========================================================================== * End of Function Test_chrdel() *=========================================================================*/ /*=========================================================================== * * Function - void Test_chrdellast (void); * * Tests the chrdellast() function. * 1. Delete the last character from a regular string * 2. Delete character from empty string. * *=========================================================================*/ void Test_chrdellast (void) { DEFINE_FUNCTION("Test_chrdellast()"); char TestString[101] = "123456789"; SystemLog.Printf(stdout, "============= Testing chrdellast() ===================="); /* Delete characters from regular of string */ chrdellast(TestString); ASSERT(strcmp(TestString, "12345678") == 0); /* Delete character from empty string */ TestString[0] = NULL_CHAR; chrdellast(TestString); ASSERT(strcmp(TestString, "") == 0); } /*=========================================================================== * End of Function Test_chrdellast() *=========================================================================*/ /*=========================================================================== * * Function - void Test_chrtok (void); * * Tests the chrtok() function. * 1. Test a regular string, comparing results with strtok() * 2. Check the function enhanced cabapility. * *=========================================================================*/ void Test_chrtok (void) { DEFINE_FUNCTION("Test_chrtok()"); char TestString1[] = "111x222x333x444x555"; char TestString2[] = "111x222x333x444x555"; char* pChrPtr; char* pStrPtr; SystemLog.Printf(stdout, "============= Testing chrtok() ===================="); /* Compare chrtok() results with strtok() for a normal string */ pChrPtr = chrtok(TestString1, 'x'); pStrPtr = strtok(TestString2, "x"); while (pChrPtr != NULL && pStrPtr != NULL) { SystemLog.Printf ("\t chrtok() / strtok() = %s / %s", pChrPtr, pStrPtr); ASSERT(strcmp(pChrPtr, pStrPtr) == 0); pChrPtr = chrtok(NULL, 'x'); pStrPtr = strtok(NULL, "x"); } ASSERT(pChrPtr == NULL && pStrPtr == NULL); /* Test the enhanced feature of chrtok() */ strcpy (TestString1, "111x222xx333xx"); pChrPtr = chrtok(TestString1, 'x'); ASSERT(strcmp(pChrPtr, "111") == 0); pChrPtr = chrtok(NULL, 'x'); ASSERT(strcmp(pChrPtr, "222") == 0); pChrPtr = chrtok(NULL, 'x'); ASSERT(strcmp(pChrPtr, "") == 0); pChrPtr = chrtok(NULL, 'x'); ASSERT(strcmp(pChrPtr, "333") == 0); pChrPtr = chrtok(NULL, 'x'); ASSERT(strcmp(pChrPtr, "") == 0); pChrPtr = chrtok(NULL, 'x'); ASSERT(strcmp(pChrPtr, "") == 0); pChrPtr = chrtok(NULL, 'x'); ASSERT(pChrPtr == NULL); } /*=========================================================================== * End of Function Test_chrtok() *=========================================================================*/ /*=========================================================================== * * Function - void Test_chrrpunc (void); * * Tests the chrrpunc() function. * 1. Ensures the function finds a punctuation in middle/start/end of string * 2. Check multiple punctuation case * 3. Check case where string contains no punctuation * 4. Check empty string case. * *=========================================================================*/ void Test_chrrpunc (void) { DEFINE_FUNCTION("Test_chrrpunc()"); char TestString[101] = "0123=5678"; boolean Result; size_t CharIndex; SystemLog.Printf(stdout, "============= Testing chrrpunc() ===================="); /* Test for punctuation in middle of string */ Result = chrrpunc(CharIndex, TestString); ASSERT(Result); ASSERT(CharIndex == 4); /* Test for punctuation at end of string */ strcpy (TestString, "012345678."); Result = chrrpunc(CharIndex, TestString); ASSERT(Result); ASSERT(CharIndex == 9); /* Test for punctuation at start of string */ strcpy (TestString, ".123456789"); Result = chrrpunc(CharIndex, TestString); ASSERT(Result); ASSERT(CharIndex == 0); /* Test for multiple punctuations in of string */ strcpy (TestString, "01234.67.0"); Result = chrrpunc(CharIndex, TestString); ASSERT(Result); ASSERT(CharIndex == 8); /* Test for no punctuation in string */ strcpy (TestString, "0123456789"); Result = chrrpunc(CharIndex, TestString); ASSERT(Result == FALSE); /* Test empty string case */ strcpy (TestString, ""); Result = chrrpunc(CharIndex, TestString); ASSERT(Result == FALSE); } /*=========================================================================== * End of Function Test_chrrpunc() *=========================================================================*/ /*=========================================================================== * * Function - void Test_chrtrunc (void); * * Tests the chrtrunc() function. * 1. Test function with regular string with truncation character in * middle/start/end of string * 2. Check with no truncation character in string * 3. Test with empty string * *=========================================================================*/ void Test_chrtrunc (void) { DEFINE_FUNCTION("Test_chrtrunc()"); char TestString[101]; SystemLog.Printf(stdout, "============= Testing chrtrunc() ===================="); /* Check with truncation character in middle of string */ strcpy(TestString, "123456789"); chrtrunc(TestString, '5'); ASSERT(strcmp(TestString, "1234") == 0); /* Check with truncation character at end of string */ strcpy(TestString, "123456789"); chrtrunc(TestString, '9'); ASSERT(strcmp(TestString, "12345678") == 0); /* Check with truncation character at start of string */ strcpy(TestString, "123456789"); chrtrunc(TestString, '1'); ASSERT(strcmp(TestString, "") == 0); /* Check with no truncation character in string */ strcpy(TestString, "123456789"); chrtrunc(TestString, 'a'); ASSERT(strcmp(TestString, "123456789") == 0); /* Check with empty string */ strcpy(TestString, ""); chrtrunc(TestString, '5'); ASSERT(strcmp(TestString, "") == 0); } /*=========================================================================== * End of Function Test_chrtrunc() *=========================================================================*/ /*=========================================================================== * * Function - void Test_chrtrunc (void); * * Tests the chrrtrunc() function. * 1. Test function with regular string with truncation character in * middle/start/end of string * 2. Check with no truncation character in string * 3. Test with empty string * *=========================================================================*/ void Test_chrrtrunc (void) { DEFINE_FUNCTION("Test_chrrtrunc()"); char TestString[101]; SystemLog.Printf(stdout, "============= Testing chrrtrunc() ===================="); /* Check with truncation character in middle of string */ strcpy(TestString, "123456789"); chrrtrunc(TestString, '5'); ASSERT(strcmp(TestString, "1234") == 0); /* Check with truncation character at end of string */ strcpy(TestString, "123456789"); chrrtrunc(TestString, '9'); ASSERT(strcmp(TestString, "12345678") == 0); /* Check with truncation character at start of string */ strcpy(TestString, "123456789"); chrrtrunc(TestString, '1'); ASSERT(strcmp(TestString, "") == 0); /* Check with no truncation character in string */ strcpy(TestString, "123456789"); chrrtrunc(TestString, 'a'); ASSERT(strcmp(TestString, "123456789") == 0); /* Check with empty string */ strcpy(TestString, ""); chrrtrunc(TestString, '5'); ASSERT(strcmp(TestString, "") == 0); } /*=========================================================================== * End of Function Test_chrrtrunc() *=========================================================================*/ /*=========================================================================== * * Function - void Test_DLChr (void); * * Tests all the functions in this module. * 1. Tests the chradd() function * 2. Tests the chrcat() function * 3. Tests the chrdel() and chrdellast() functions * 4. Tests the chrtok() function * 5. Tests the chrrpunc() function * 6. Tests the chrtrunc() and chrrtrunc() functions * *=========================================================================*/ void Test_DLChr (void) { //DEFINE_FUNCTION("Test_DLChr()"); Test_chradd(); Test_chrcat(); Test_chrdel(); Test_chrdellast(); Test_chrtok(); Test_chrrpunc(); Test_chrtrunc(); Test_chrrtrunc(); } /*=========================================================================== * End of Function Test_DLChr() *=========================================================================*/ #endif /*=========================================================================== * End of Module Test Routines *=========================================================================*/