diff --git a/charpool.cc b/charpool.cc index 313db169a..6f3218b43 100644 --- a/charpool.cc +++ b/charpool.cc @@ -63,6 +63,8 @@ /* $Id$ */ #include +#undef NDEBUG +#include #include "nbase.h" @@ -70,77 +72,56 @@ #include "charpool.h" #include "nmap_error.h" -static char *charpool[16]; -static int currentcharpool; -static size_t currentcharpoolsz; -static size_t nexti; +static CharPool g_charpool (16384); + +const char *cp_strndup(const char *src, int len) { + return g_charpool.dup(src, len); +} +const char *cp_strdup(const char *src) { + return g_charpool.dup(src); +} +void cp_free(void) { + return g_charpool.clear(); +} /* Allocated blocks are allocated to multiples of ALIGN_ON. This is the definition used by the malloc in Glibc 2.7, which says that it "suffices for nearly all current machines and C compilers." */ #define ALIGN_ON (2 * sizeof(size_t)) -static int cp_init(void) { - static int charpool_initialized = 0; - if (charpool_initialized) return 0; - +CharPool::CharPool(size_t init_sz) { + assert(init_sz >= 256); /* Create our char pool */ - currentcharpool = 0; - currentcharpoolsz = 16384; + currentbucketsz = init_sz; nexti = 0; - charpool[0] = (char *) safe_malloc(currentcharpoolsz); - charpool_initialized = 1; - return 0; + char *b = (char *) safe_malloc(currentbucketsz); + buckets.push_back(b); } -void cp_free(void) { - int ccp; - for(ccp=0; ccp <= currentcharpool; ccp++) - if(charpool[ccp]){ - free(charpool[ccp]); - charpool[ccp] = NULL; +void CharPool::clear(void) { + for (BucketList::iterator it=buckets.begin(); it != buckets.end(); it++) { + free(*it); } - currentcharpool = 0; + buckets.clear(); } -static inline void cp_grow(void) { - /* Doh! We've got to make room */ - if (++currentcharpool > 15) { - fatal("Character Pool is out of buckets!"); - } - currentcharpoolsz <<= 1; - - nexti = 0; - charpool[currentcharpool] = (char *) safe_malloc(currentcharpoolsz); -} - -void *cp_alloc(int sz) { - char *p; +const char *CharPool::dup(const char *src, int len) { + int sz = len < 0 ? strlen(src) : len; + char *p = buckets.back() + nexti; int modulus; - cp_init(); - if ((modulus = sz % ALIGN_ON)) sz += ALIGN_ON - modulus; - if (nexti + sz <= currentcharpoolsz) { - p = charpool[currentcharpool] + nexti; - nexti += sz; - return p; + while (nexti + sz > currentbucketsz) { + /* Doh! We've got to make room */ + currentbucketsz <<= 1; + nexti = 0; + p = (char *) safe_malloc(currentbucketsz); + buckets.push_back(p); } - /* Doh! We've got to make room */ - cp_grow(); - - return cp_alloc(sz); -} - -const char *cp_strndup(const char *src, int len) { - char *dst = (char *) cp_alloc(len + 1); // Additional byte for null terminator - dst[len] = '\0'; - return (const char *) memcpy(dst, src, len); -} - -const char *cp_strdup(const char *src) { - return cp_strndup(src, strlen(src)); + nexti += sz; + p[sz] = '\0'; + return (const char *) memcpy(p, src, sz); } diff --git a/charpool.h b/charpool.h index e9bc26fb1..0e7ed9e41 100644 --- a/charpool.h +++ b/charpool.h @@ -65,12 +65,29 @@ #ifndef CHARPOOL_H #define CHARPOOL_H -void *cp_alloc(int sz); +#include + /* len does not include null terminator */ const char *cp_strndup(const char *src, int len); const char *cp_strdup(const char *src); void cp_free(void); +typedef std::vector BucketList; + +class CharPool { + private: + BucketList buckets; + size_t currentbucketsz; + size_t nexti; + public: + CharPool(size_t init_sz=256); + ~CharPool() { this->clear(); } + // Free all allocated buckets + void clear(); + // if len < 0, strlen will be used to determine src length + const char *dup(const char *src, int len=-1); +}; + #endif