/*=========================================================================== * * File: DL_Mem.CPP * Author: Dave Humphrey (uesp@m0use.net) * Created On: Sunday, April 01, 2001 * * Implements memory specific routines for Dave's Library of common code. * *=========================================================================*/ /* Include Files */ #include "dl_mem.h" #include <string.h> #include <time.h> #include <ctype.h> #ifndef _MSC_VER #include <alloc.h> #endif #if defined(_WIN32) #include <windows.h> #endif /*=========================================================================== * * Begin Local Variables * *=========================================================================*/ DEFINE_FILE(); /*=========================================================================== * End of Local Variables *=========================================================================*/ /*=========================================================================== * * Function - void* AllocateMemory (const size_t Size); * * For use when you always want a valid block of new memory returned. * Attempts to allocate the given number of bytes (0 is an invalid size) * and return the pointer to the new block of memory. On allocation * error the function throws an exception. * *=========================================================================*/ void* AllocateMemory (const size_t Size) { DEFINE_FUNCTION("AllocateMemory(size_t)"); void* pNewObject; /* Ensure valid input */ ASSERT(Size != 0); /* Attempt to allocate memory */ CreateArrayPointer(pNewObject, char, Size); /* Initialize memory in debug mode */ #if defined(_DEBUG) memset(pNewObject, GARBAGE_CHAR, Size); #endif return (pNewObject); } /*=========================================================================== * End of Function AllocateMemory() *=========================================================================*/ /*========================================================================= * * Function - char* CreateString (pString); * * For use when you always want a valid new string created. * Attempts to allocate a new string and copies the contents of the given * string into it. Throws an exception on allocation error and outputs * error message. Assumes the input string is valid (asserts if it isn't). * *=======================================================================*/ char* CreateString (const char* pString) { DEFINE_FUNCTION("CreateString(char*)"); char* pNewString; size_t NewSize; /* Ensure valid input */ ASSERT(pString != NULL); /* Get the length of the new string and allocate it */ NewSize = strlen(pString) + 1; CreateArrayPointer(pNewString, char, NewSize); /* Copy the string to the new location */ strcpy(pNewString, pString); return (pNewString); } /*========================================================================= * End of Function CreateString() *=======================================================================*/ /*========================================================================= * * Function - char* CreateString (StringSize); * * For use when you always want a valid new string created. * Same as CreateString() above but creates a string pointer of * the given length (plus one for the terminating NULL). String is * initially set to the empty string. * *=======================================================================*/ char* CreateString (const size_t StringSize) { //DEFINE_FUNCTION("CreateString(size_t)"); char* pNewString; /* Allocate the new string pointer */ pNewString = (char *) AllocateMemory(StringSize + 1); *pNewString = NULL_CHAR; pNewString[StringSize] = NULL_CHAR; return (pNewString); } /*========================================================================= * End of Function CreateString() *=======================================================================*/ /*=========================================================================== * * Function - boolean CreateString (ppNewString, pSourceString); * * Attempts to create a new string from the input string, returning the * result in the ppNewString pointer. Returns TRUE on success or FALSE * on any error (source string is NULL). Throws an exception if the * string could not be allocated. * *=========================================================================*/ boolean CreateString (char** ppNewString, const char* pSourceString) { DEFINE_FUNCTION("CreateString(char**, char*)"); /* Ensure valid input */ ASSERT(ppNewString != NULL); /* Special case for a NULL input string */ if (pSourceString == NULL) { *ppNewString = NULL; return (FALSE); } /* Create the new string */ *ppNewString = CreateString(pSourceString); return (TRUE); } /*=========================================================================== * End of Function CreateString() *=========================================================================*/ /*=========================================================================== * * Function - boolean CreateString (ppNewString, StringSize); * * Attempts to create a new string from the given size, returning the * result in the ppNewString pointer. Returns TRUE on success or FALSE * on any error (source string is NULL). Throws an exception if the * string could not be allocated. * *=========================================================================*/ boolean CreateString (char** ppNewString, const size_t StringSize) { DEFINE_FUNCTION("CreateString(char**, size_t)"); /* Ensure valid input */ ASSERT(ppNewString != NULL); /* Create the new string */ *ppNewString = CreateString(StringSize); return (TRUE); } /*=========================================================================== * End of Function CreateString() *=========================================================================*/ /*========================================================================= * * Function - boolean GetFreeMemory (Memory); * * Returns the number of bytes available for allocation. * Returns FALSE on any error (if the amount of memory could not * be retrieved). * *=======================================================================*/ boolean GetFreeMemory (long& Memory) { DEFINE_FUNCTION("GetFreeMemory()"); /*---------- Borland 16 bit ---------------------------------------------*/ #if defined (__BCPLUSPLUS__) Memory = 0; return (TRUE); /*---------- DOS real mode implementation -------------------------------*/ #elif defined (__MSDOS__) Memory = farcoreleft(); return (TRUE); /*---------- Windows implementation -------------------------------------*/ #elif defined(_WIN32) MEMORYSTATUS Status; GlobalMemoryStatus(&Status); Memory = (long) Status.dwAvailVirtual; return (TRUE); /*---------- Any unknown system implementation --------------------------*/ #else ASSERT(FALSE); return (FALSE); #endif } /*========================================================================= * End of Function GetFreeMemory() *=======================================================================*/ /*========================================================================= * * Function - boolean GetTotalMemory (Memory) * * Returns the total amount of memory on the system in bytes. * On error the function returns FALSE. * *=======================================================================*/ boolean GetTotalMemory (long& Memory) { DEFINE_FUNCTION("GetTotalMemory()"); /*---------- Borland 16 bit ---------------------------------------------*/ #if defined (__BCPLUSPLUS__) Memory = 0; return (TRUE); /*---------- DOS real mode implementation -------------------------------*/ #elif defined(__TURBOC__) struct heapinfo HeapInfo; long MemorySize = 0l; /* Make sure the heap is not corrupt */ if (heapcheck() != _HEAPOK) return(FALSE); GetFreeMemory(MemorySize); /* Walk through the heap counting used and free blocks */ HeapInfo.ptr = NULL; while (heapwalk(&HeapInfo) == _HEAPOK) { if (HeapInfo.in_use) MemorySize += HeapInfo.size; } return (TRUE); /*---------- Windows implementation -------------------------------------*/ #elif defined(_WIN32) MEMORYSTATUS Status; GlobalMemoryStatus(&Status); Memory = (long) Status.dwAvailVirtual; return (TRUE); /*---------- Any unknown system implementation --------------------------*/ #else ASSERT(FALSE); return (FALSE); #endif } /*========================================================================= * End of Function GetTotalMemory() *=======================================================================*/ /*========================================================================= * * Function - boolean GetUsedMemory (Memory); * * Returns the amount of allocated memory in bytes. On error the function * returns FALSE. * *=======================================================================*/ boolean GetUsedMemory (long& Memory) { //DEFINE_FUNCTION("GetUserMemory()"); long MemoryFree = 0; long MemoryTotal; boolean Result; /* Get the total/free memory on the system, ensuring they are valid */ Result = GetTotalMemory(MemoryTotal); if (Result) Result = GetFreeMemory(MemoryFree); if (!Result) return (FALSE); /* Compute the difference in memory */ Memory = MemoryTotal - MemoryFree; return (TRUE); } /*========================================================================= * End of Function GetUsedMemory() *=======================================================================*/ /*========================================================================= * * Function - int GetHeapStatus (void); * * Checks and returns the validity of the heap. Return values include * HEAP_OK - Heap is ok. * HEAP_EMPTY - Heap doesn't exist or not initialized.. * HEAP_CORRUPT - Heap is corrupt. * HEAP_NOTDEFINED - No defined heap status function on current system. * * Not all values are defined in all systems. * *=======================================================================*/ int GetHeapStatus (void) { DEFINE_FUNCTION("GetHeapStatus()"); /*---------- Borland 16 bit ---------------------------------------------*/ #if defined (__BCPLUSPLUS__) return (HEAP_NOTDEFINED); /*---------- DOS real mode implementation -------------------------------*/ #elif defined(__MSDOS__) return (heapcheck()); /*---------- Windows implementation -------------------------------------*/ #elif defined(_WIN32) #if defined(_DEBUG) if (_CrtCheckMemory()) return (HEAP_OK); return (HEAP_CORRUPT); #else return (HEAP_NOTDEFINED); #endif /*---------- Any unknown system implementation --------------------------*/ #else ASSERT(FALSE); return (HEAP_NOTDEFINED); #endif } /*========================================================================= * End of Function GetHeapStatus() *=======================================================================*/ /*========================================================================= * * Function - char* GetHeapStatusString (void); * * Returns a string based on the status of the heap. Always returns a * valid string, never NULL. * *=======================================================================*/ char *GetHeapStatusString (void) { switch (GetHeapStatus()) { case HEAP_OK: return ("Ok"); case HEAP_CORRUPT: return ("Corrupt"); case HEAP_EMPTY: return ("Empty or not Initialized" ); case HEAP_NOTDEFINED: return ("Status Not Defined in Current System"); default: return ("Error, Invalid Heap Status"); } } /*========================================================================= * End of Function GetHeapStatusString() *=======================================================================*/ #if defined(_WIN32) && defined(_DEBUG) && !defined(__BCPLUSPLUS__) /*=========================================================================== * * Function - void DebugHeapDumpHook (pUserData, Size); * * The hook function for dumping a block of the debug heap. Only defined * in DEBUG and WIN32 builds. Outputs the block information to the * SystemLog. * *=========================================================================*/ void __cdecl DebugHeapDumpHook (void* pUserData, size_t Size) { //DEFINE_FUNCTION("__cdecl DebugHeapDumpHook()"); SystemLog.Printf ("Block %p (%u bytes)", pUserData, Size); } /*=========================================================================== * End of Function __cdecl DebugHeapDumpHook() *=========================================================================*/ /*=========================================================================== * * Function - int DebugHeapReportHook (ReportType, pMessage, pReturnValue); * * The hook function for reporting information of the debug heap. Only * defined in DEBUG and WIN32 builds. Outputs the block information to the * SystemLog. * *=========================================================================*/ int DebugHeapReportHook (int ReportType, char* pMessage, int* pReturnValue) { //DEFINE_FUNCTION("DebugHeapReportHook()"); static char* ReportStrings[] = {"Warning", "Error", "Assertion"}; boolean Result; /* Set return value to continue program operation. Set this * value to 1 to start the debugger. */ *pReturnValue = 0; /* Attempt to output message to log file */ Result = SystemLog.Printf("Debug Heap Report %s: %s", ReportStrings[ReportType], pMessage); return (Result); } /*=========================================================================== * End of Function DebugHeapReportHook() *=========================================================================*/ /*=========================================================================== * * Function - void fnInitDebugHeap (void); * * Initializes the use of the debug heap for error checking. Only defined * in DEBUG and WIN32 builds. * *=========================================================================*/ void fnInitDebugHeap (void) { //DEFINE_FUNCTION("fnInitDebugHeap()"); /* Set the default debug heap options */ _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF); /* Set the debug heap hook functions */ _CrtSetDumpClient( DebugHeapDumpHook ); _CrtSetReportHook( DebugHeapReportHook ); } /*=========================================================================== * End of Function fnInitDebugHeap() *=========================================================================*/ /*=========================================================================== * * Function - void fnSetDebugHeapFreeMem (Flag); * * Sets or clears the option of keeping freed blocks allocated for testing * of block overwrites. Only defined in DEBUG and WIN32 builds. * *=========================================================================*/ void fnSetDebugHeapFreeMem (const boolean Flag) { //DEFINE_FUNCTION("fnSetDebugHeapFreeMem()"); /* Clear or set the storing of freed memory blocks */ if (Flag) SET_CRT_DEBUG_FIELD(_CRTDBG_DELAY_FREE_MEM_DF); else CLEAR_CRT_DEBUG_FIELD(_CRTDBG_DELAY_FREE_MEM_DF); } /*=========================================================================== * End of Function fnSetDebugHeapFreeMem() *=========================================================================*/ /*=========================================================================== * * Function - void fnSetDebugHeapCheckCRT (Flag); * * Sets or clears the option of including CRT allocated blocks when checking * the status of the debug heap. Only defined in DEBUG and WIN32 builds. * *=========================================================================*/ void fnSetDebugHeapCheckCRT (const boolean Flag) { //DEFINE_FUNCTION("fnSetDebugHeapCheckCRT()"); /* Clear or set the checking of CRT allocated blocks */ if (Flag) SET_CRT_DEBUG_FIELD(_CRTDBG_CHECK_CRT_DF); else CLEAR_CRT_DEBUG_FIELD(_CRTDBG_CHECK_CRT_DF); } /*=========================================================================== * End of Function fnSetDebugHeapCheckCRT() *=========================================================================*/ /*=========================================================================== * * Function - void fnSetDebugHeapAlwaysCheck (Flag); * * Sets or clears the option of checking the heap status whenever an * allocation is made. Setting this flag can slow the application down * considerably but can help in pinpointing difficult to locate memory * problems. Only defined in DEBUG and WIN32 builds. * *=========================================================================*/ void fnSetDebugHeapAlwaysCheck (const boolean Flag) { //DEFINE_FUNCTION("fnSetDebugHeapAlwaysCheck()"); /* Clear or set the checking of the heap when allocated blocks */ if (Flag) SET_CRT_DEBUG_FIELD(_CRTDBG_CHECK_ALWAYS_DF); else CLEAR_CRT_DEBUG_FIELD(_CRTDBG_CHECK_ALWAYS_DF); } /*=========================================================================== * End of Function fnSetDebugHeapAlwaysCheck() *=========================================================================*/ #endif /*========================================================================= * * Function - void* memsearch (pBuffer, pSearchBuffer, BufferLength, SearchLength, StartIndex); * * Searches for the search bytes in given string using a 'binary' search * using the given lengths. Starts searching in the target memory at * the given index. Returns a pointer to the position of the search bytes * in the target bytes. ASSERTs if given invalid input. * *=======================================================================*/ char* memsearch (const char* pBuffer, const char* pSearchBuffer, const size_t BufferLength, const size_t SearchLength, const size_t StartIndex) { DEFINE_FUNCTION("memsearch()"); size_t BufferIndex; /* Loop counters */ size_t SearchIndex; /* Ensure valid input */ ASSERT(pBuffer != NULL && pSearchBuffer != NULL); /* Ensure string lengths allow a possible match */ if (BufferLength < StartIndex || SearchLength == 0 || SearchLength > BufferLength - StartIndex) return (NULL); BufferIndex = StartIndex; SearchIndex = 0; /* The main search loop */ while (BufferIndex < BufferLength) { if (pBuffer[BufferIndex] == pSearchBuffer[SearchIndex]) { SearchIndex++; if (SearchIndex >= SearchLength) return (char*)(pBuffer + BufferIndex - SearchLength + 1); } else if (SearchIndex != 0) { BufferIndex -= SearchIndex; SearchIndex = 0; } BufferIndex++; } /* Nothing found... */ return (NULL); } /*========================================================================= * End of Function memsearch() *=======================================================================*/ /*========================================================================= * * Function - void* memisearch (pBuffer, pSearchBuffer, BufferLength, SearchLength, StartIndex); * * Searches for the search bytes in given string using a 'binary' search * using the given lengths. Starts searching in the target memory at * the given index. Returns a pointer to the position of the search bytes * in the target bytes. ASSERTs if given invalid input. Case insensitive. * *=======================================================================*/ char* memisearch (const char* pBuffer, const char* pSearchBuffer, const size_t BufferLength, const size_t SearchLength, const size_t StartIndex) { DEFINE_FUNCTION("memisearch()"); size_t BufferIndex; /* Loop counters */ size_t SearchIndex; /* Ensure valid input */ ASSERT(pBuffer != NULL && pSearchBuffer != NULL); /* Ensure string lengths allow a possible match */ if (BufferLength < StartIndex || SearchLength == 0 || SearchLength > BufferLength - StartIndex) return (NULL); BufferIndex = StartIndex; SearchIndex = 0; /* The main search loop */ while (BufferIndex < BufferLength) { if (tolower(pBuffer[BufferIndex]) == tolower(pSearchBuffer[SearchIndex])) { SearchIndex++; if (SearchIndex >= SearchLength) return (char*)(pBuffer + BufferIndex - SearchLength + 1); } else if (SearchIndex != 0) { BufferIndex -= SearchIndex; SearchIndex = 0; } BufferIndex++; } /* Nothing found... */ return (NULL); } /*========================================================================= * End of Function memisearch() *=======================================================================*/ /*=========================================================================== * * Function - boolean ReplaceString (ppNewString, pSourceString); * * Same as CreateString(char**, char*) except that the destrination string * is deleted if it is non-NULL. Returns TRUE on success or FALSE * on any error (source string is NULL). Throws an exception if the * string could not be allocated. Ignores if the input and output * strings point to the same object. * *=========================================================================*/ boolean ReplaceString (char** ppNewString, const char* pSourceString) { DEFINE_FUNCTION("ReplaceString(char**, char*)"); /* Ensure valid input */ ASSERT(ppNewString != NULL); /* Check for NULL inputs */ if (*ppNewString == NULL && pSourceString == NULL) return (FALSE); /* Check for same input/output objects */ if (*ppNewString == pSourceString) return (TRUE); /* Delete the destination string if required */ DestroyPointer(*ppNewString); /* Attempt to allocate the new stirng */ return CreateString(ppNewString, pSourceString); } /*=========================================================================== * End of Function ReplaceString() *=========================================================================*/ /*=========================================================================== * * Function - boolean ReplaceString (ppNewString, Length); * * Same as CreateString(char**, size_t) except that the destrination string * is deleted if it is non-NULL. Returns TRUE on success or FALSE * on any error (source string is NULL). Throws an exception if the * string could not be allocated. * *=========================================================================*/ boolean ReplaceString (char** ppNewString, const size_t Length) { DEFINE_FUNCTION("ReplaceString(char**, size_t)"); /* Ensure valid input */ ASSERT(ppNewString != NULL); /* Delete the destination string if required */ DestroyPointer(*ppNewString); /* Attempt to allocate the new stirng */ return CreateString(ppNewString, Length); } /*=========================================================================== * End of Function ReplaceString() *=========================================================================*/ #if defined(__TURBOC__) && !defined(__BCPLUSPLUS__) /*=========================================================================== * * Function - void _DosMemDumpHeap (void); * * Dumps the heap blocks to the SystemLog under TurboC. * *=========================================================================*/ void _DosMemDumpHeap (void) { struct heapinfo HeapInfo; long MemorySize = 0l; long UnusedSize = 0l; long Index = 1l; SystemLog.Printf ("Outputting DOS heap block information..."); /* Make sure the heap is not corrupt */ if (heapcheck() != _HEAPOK) { SystemLog.Printf ("\t\tHeap is corrupt, cannot output block information!"); return; } /* Walk through the heap counting used and free blocks */ HeapInfo.ptr = NULL; while (heapwalk(&HeapInfo) == _HEAPOK) { if (HeapInfo.in_use) MemorySize += HeapInfo.size; else UnusedSize += HeapInfo.size; SystemLog.Printf ("\t\t%3ld) %p: %8ld bytes, Used=%1d ", Index, HeapInfo.ptr, HeapInfo.size, HeapInfo.in_use); Index++; } SystemLog.Printf ("\tOutput %ld bytes of used and %ld bytes of unused heap blocks.", MemorySize, UnusedSize); /* Chain to our custom block handler in debug builds */ #if defined(_DEBUG) OutputBlockInfo(); #endif return; } /*=========================================================================== * End of Function _DosMemDumpHeap() *=========================================================================*/ #endif /*=========================================================================== * * Begin File Test Routines (Debug Builds Only) * *=========================================================================*/ #if defined(_DEBUG) #define CREATESTRING1_BUFFERSIZE 11000 /* Turn off compiler warning options */ #if defined(__BCPLUSPLUS__) #pragma warn -rch #pragma warn -ccc #endif /*=========================================================================== * * Test the CreateString (char*) function * * 1. Tests the allocation of set strings. * 2. Tests the allocation of random sized strings (from 1 to 10000 bytes). * *=========================================================================*/ void Test_CreateString1 (void) { DEFINE_FUNCTION("Test_CreateString1()"); char* Buffer; char* pTestStrings[4] = { "", "\0", "testing", "asdadasd" }; char* pTestPtr; int LoopCounter; size_t RandomSize; /* Test the set string allocation */ SystemLog.Printf (stderr, "========== Testing CreateString(char*) with set strings =========="); /* Allocate because large stack strings mess up in Borland 16-bit */ Buffer = CreateString(CREATESTRING1_BUFFERSIZE); for (LoopCounter = 0; LoopCounter < 4; LoopCounter++) { pTestPtr = CreateString(pTestStrings[LoopCounter]); /* Ensure the string was properly allocated */ ASSERT(pTestPtr != NULL); ASSERT(strcmp(pTestStrings[LoopCounter], pTestPtr) == 0); ASSERT(IsValidPointer(pTestPtr, strlen(pTestStrings[LoopCounter]) + 1)); /* Delete the test string */ DestroyPointer(pTestPtr); SystemLog.Printf (stderr, "\t\tSuccessfully allocated string '%s'.", pTestStrings[LoopCounter]); } /* Test the random string allocation */ SystemLog.Printf (stderr, "========== Testing CreateString(char*) with random length strings =========="); srand( (unsigned)time( NULL ) ); memset(Buffer, 'a', CREATESTRING1_BUFFERSIZE); for (LoopCounter = 0; LoopCounter < 1000; LoopCounter++) { RandomSize = (size_t) ((float)rand() * 10000 / RAND_MAX); Buffer[RandomSize] = NULL_CHAR; pTestPtr = CreateString(Buffer); /* Ensure the string was properly allocated */ ASSERT(pTestPtr != NULL); ASSERT(strcmp(pTestPtr, Buffer) == 0); ASSERT(IsValidPointer(pTestPtr, RandomSize + 1)); /* Delete the test string */ DestroyPointer(pTestPtr); SystemLog.Printf (stderr, "\t\t%7d) Successfully allocated string of length %u bytes.", LoopCounter, RandomSize); Buffer[RandomSize] = 'a'; } ASSERT(DebugHeapCheckMemory()); DestroyPointer(Buffer); } /*=========================================================================== * End of testing the CreateString(char*) function *=========================================================================*/ /*=========================================================================== * * Test the CreateString(size_t) function * * 1. Tests the allocation of strings of set sizes. * 2. Tests the allocation of random sized strings (from 1 to * TEST_MAXSTRING_SIZE bytes). * *=========================================================================*/ void Test_CreateString2 (void) { DEFINE_FUNCTION("Test_CreateString2()"); size_t TestSizes[4] = { 10, 1, 2, 200 }; size_t RandomSize; int LoopCounter; char* pTestPtr; /* Test the allocation of set sized strings */ SystemLog.Printf(stderr, "========== Testing CreateString(size_t) with set sized strings =========="); for (LoopCounter = 0; LoopCounter < 4; LoopCounter++) { pTestPtr = CreateString(TestSizes[LoopCounter]); /* Ensure the string was properly allocated */ ASSERT(pTestPtr != NULL); ASSERT(IsValidPointer(pTestPtr, TestSizes[LoopCounter] + 1)); DestroyPointer(pTestPtr); SystemLog.Printf (stderr, "\t\tSuccessfully allocated string of %u bytes.", TestSizes[LoopCounter]); } /* Test the allocation of randomly sized strings */ SystemLog.Printf (stderr, "========== Testing CreateString(size_t) with randomly sized strings =========="); srand( (unsigned)time( NULL ) ); for (LoopCounter = 0; LoopCounter < 1000; LoopCounter++) { RandomSize = (size_t) ((float)((size_t)rand()) * TEST_MAXSTRING_SIZE / RAND_MAX); pTestPtr = CreateString(RandomSize); /* Ensure the string was properly allocated */ ASSERT(pTestPtr != NULL); ASSERT(IsValidPointer(pTestPtr, RandomSize + 1)); DestroyPointer(pTestPtr); SystemLog.Printf (stderr, "\t\t%7d) Successfully allocated string of %u bytes.", LoopCounter+1, RandomSize); } ASSERT(DebugHeapCheckMemory()); } /*=========================================================================== * End of testing the CreateString(size_t) function *=========================================================================*/ /*=========================================================================== * * Function - void Test_CreateString3 (void); * * Tests the CreateString(char**, char*) function. Since this function * is based on the CreateString(char*) function, some tests can be skipped. * 1. Tests for NULL source string * 2. Check allocation of set strings * *=========================================================================*/ void Test_CreateString3 (void) { DEFINE_FUNCTION("Test_CreateString3()"); char* pStrings[4] = { "asldkja;lkdj;asd", "123785", "", "o[ijopiap98dfp9hsadfp98ashf9as8fh" }; char* pTestString1 = NULL; int LoopCounter; SystemLog.Printf(stdout, "================ Testing CreateString(char**, char*) ==================="); /* Test case of NULL source string */ ASSERT(CreateString(&pTestString1, (char*)NULL) == FALSE); ASSERT(pTestString1 == NULL); /* Check the allocation of set strings */ for (LoopCounter = 0; LoopCounter < 4; LoopCounter++) { ASSERT(CreateString(&pTestString1, pStrings[LoopCounter]) == TRUE); ASSERT(strcmp(pTestString1, pStrings[LoopCounter]) == 0); DestroyPointer(pTestString1); } ASSERT(DebugHeapCheckMemory()); } /*=========================================================================== * End of Function Test_CreateString3() *=========================================================================*/ /*=========================================================================== * * Function - void Test_memsearch (void); * * Tests the memsearch() and memisearch() functions. * 1. Tests for typical buffers * 2. Tests search buffer longer than buffer * 3. Tests empty buffers * 4. Tests overlapping data buffers * *=========================================================================*/ void Test_memsearch (void) { DEFINE_FUNCTION("Test_memsearch()"); char TestBuffer[101] = "Test buffer 1234567890"; char TestSearch[18] = "uff"; char* pResult; SystemLog.Printf(stdout, "================ Testing memsearch()/memisearch() ==================="); /* Test typical buffers */ pResult = memsearch(TestBuffer, TestSearch, 20, 3, 0); ASSERT(strncmp(pResult, "uffer", 5) == 0); pResult = memisearch(TestBuffer, TestSearch, 20, 3, 0); ASSERT(strncmp(pResult, "uffer", 5) == 0); pResult = memsearch(TestBuffer, "aaa", 20, 3, 0); ASSERT(pResult == NULL); pResult = memisearch(TestBuffer, "aaa", 20, 3, 0); ASSERT(pResult == NULL); /* Test typical buffers with start index */ pResult = memsearch(TestBuffer, TestSearch, 20, 3, 4); ASSERT(strncmp(pResult, "uffer", 5) == 0); pResult = memisearch(TestBuffer, TestSearch, 20, 3, 4); ASSERT(strncmp(pResult, "uffer", 5) == 0); pResult = memsearch(TestBuffer, TestSearch, 20, 3, 14); ASSERT(pResult == NULL); pResult = memisearch(TestBuffer, TestSearch, 20, 3, 14); ASSERT(pResult == NULL); /* Test typical buffers with case differences */ strcpy(TestSearch, "UfF"); pResult = memsearch(TestBuffer, TestSearch, 20, 3, 0); ASSERT(pResult == NULL); pResult = memisearch(TestBuffer, TestSearch, 20, 3, 0); ASSERT(strnicmp(pResult, "uffer", 5) == 0); /* Test search buffer longer than main buffer */ pResult = memsearch(TestBuffer, TestSearch, 3, 20, 0); ASSERT(pResult == NULL); pResult = memisearch(TestBuffer, TestSearch, 3, 20, 0); ASSERT(pResult == NULL); /* Test empty buffers */ pResult = memsearch(TestBuffer, TestSearch, 20, 0, 0); ASSERT(pResult == NULL); pResult = memisearch(TestBuffer, TestSearch, 20, 0, 0); ASSERT(pResult == NULL); pResult = memsearch(TestBuffer, TestSearch, 0, 10, 0); ASSERT(pResult == NULL); pResult = memisearch(TestBuffer, TestSearch, 0, 10, 0); ASSERT(pResult == NULL); } /*=========================================================================== * End of Function Test_memsearch() *=========================================================================*/ /*=========================================================================== * * Function - void Test_ReplaceString (void); * * Tests the ReplaceString(char**, char*) function. Is based on the * CreateString(char**, char*) function which eliminates some tests. * 1. Tests empty/NULL destination strings * 2. Check allocation of set strings * *=========================================================================*/ void Test_ReplaceString (void) { DEFINE_FUNCTION("Test_ReplaceString()"); char* pStrings[4] = { "asldkja;lkdj;asd", "123385", "", "o[ijopiap98dfp9hsadfp98ashf9as8fh" }; char* pTestString1; int LoopCounter; SystemLog.Printf(stdout, "================ Testing ReplaceString() ==================="); /* Allocate temp string */ pTestString1 = CreateString("aadkjsdoijsadfhsdpofihdpfaioh"); /* Attempt to reallocate string */ ASSERT(ReplaceString(&pTestString1, "1113233") == TRUE); /* Test allocation of NULL source string with non-NULL destination */ ASSERT(ReplaceString(&pTestString1, (char*)NULL) == FALSE); ASSERT(pTestString1 == NULL); /* Test allocation of NULL source string with NULL destination */ ASSERT(ReplaceString(&pTestString1, (char*)NULL) == FALSE); ASSERT(pTestString1 == NULL); /* Check the allocation of set strings */ for (LoopCounter = 0; LoopCounter < 4; LoopCounter++) { ASSERT(CreateString(&pTestString1, pStrings[LoopCounter]) == TRUE); ASSERT(strcmp(pTestString1, pStrings[LoopCounter]) == 0); DestroyPointer(pTestString1); } ASSERT(DebugHeapCheckMemory()); } /*=========================================================================== * End of Function Test_ReplaceString() *=========================================================================*/ /*=========================================================================== * * Function - void Test_DL_Mem (void); * * Runs the test routines for this file. * - Tests the CreateString(char*) function * - Tests the CreateString(size_t) function * - Tests the CreateString(char**, char*) function * - Tests the ReplaceString(char**, char*) function * - Runs the GetFreeMemory(), GetUsedMemory() and GetTotalMemory() functions, * Outtputing results to log file, ASSERTing if any function returns an error. * - Runs the GetHeapStatus() and GetHeapStatusString() functions, outputting * their results to the log file. * - Tests the memsearch() and memisearch() functions * *=========================================================================*/ void Test_DL_Mem (void) { DEFINE_FUNCTION("Test_DL_Mem()"); long Memory; Test_CreateString1(); Test_CreateString2(); Test_CreateString3(); Test_ReplaceString(); Test_memsearch(); ASSERT(GetFreeMemory(Memory) == TRUE); SystemLog.Printf("\tGetFreeMemory() returned %ld", Memory); ASSERT(GetUsedMemory(Memory) == TRUE); SystemLog.Printf("\tGetUsedMemory() returned %ld", Memory); ASSERT(GetTotalMemory(Memory) == TRUE); SystemLog.Printf("\tGetTotalMemory() returned %ld", Memory); SystemLog.Printf("\tGetHeapStatus() returned %ld", GetHeapStatus()); SystemLog.Printf("\tGetHeapStatusString() returned '%s'", GetHeapStatusString()); } /*=========================================================================== * End of Function Test_DL_Mem() *=========================================================================*/ /* Restore compiler warning options */ #if defined(__BCPLUSPLUS__) #pragma warn .rch #pragma warn .ccc #endif #endif /*=========================================================================== * End of File Test Routines (Debug Builds Only) *=========================================================================*/