#include "common.h" #include "String.h" #ifndef ASSERT #include #define ASSERT(X) assert(X) #endif // // Out-of-line string methods and free list maintenance. // enum { STRING_BUFFER_SIZE = 254, BOB_SENTINEL = 0x66, EOB_SENTINEL = 0x99 }; static void* g_pFreeList = 0; #ifdef NDEBUG #define CheckBuffer(p,n) #else inline static void CheckBuffer(const char* pBuffer,int cbBuffer = STRING_BUFFER_SIZE) { ASSERT(pBuffer); ASSERT(BOB_SENTINEL == (255&*(pBuffer-1))); ASSERT(EOB_SENTINEL == (255&*(pBuffer+cbBuffer))); } #endif void base::String::recycle() { CheckBuffer(sBuffer,cbBufferMax); char* p = sBuffer - 1; sBuffer = 0; cbBufferMax = 0; if (STRING_BUFFER_SIZE == cbBufferMax) { fprintf(stderr,"recycle 0x%08lx\n",(long) p); *((void**) p) = g_pFreeList; g_pFreeList = p; } else { delete p; } } void base::String::upsizeTo(int n) { if (n < STRING_BUFFER_SIZE) { cbBufferMax = STRING_BUFFER_SIZE; // Grab a buffer from the free list if present (the usual case). if (g_pFreeList) { sBuffer = (char*) g_pFreeList; g_pFreeList = *((void**) g_pFreeList); } else { // Allocate a stock-sized buffer. sBuffer = new char[2 + STRING_BUFFER_SIZE]; *sBuffer++ = (char) BOB_SENTINEL; *(sBuffer + STRING_BUFFER_SIZE) = (char) EOB_SENTINEL; } *sBuffer = 0; } else { // round up to a quanta allowing for NUL ++n; n = ((n + STRING_BUFFER_SIZE) / STRING_BUFFER_SIZE) * STRING_BUFFER_SIZE; char* p = new char[n + 2]; p[0] = (char) BOB_SENTINEL; p[1 + n] = (char) EOB_SENTINEL; ++p; ::strcpy(p,sBuffer); recycle(); sBuffer = p; cbBufferMax = n; } }