1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-07 13:11:28 +00:00

Use charpool to back string_pool

string_pool (string interning) was using STL strings with lots of extra
constructions, when all we need is a const char array. We can use
charpool for that and get all the benefits there of tightly-packed heap
allocations.
This commit is contained in:
dmiller
2022-09-12 16:59:36 +00:00
parent cc5cd5f2c6
commit 7ec32df7ea
3 changed files with 63 additions and 45 deletions

View File

@@ -72,8 +72,8 @@
static char *charpool[16]; static char *charpool[16];
static int currentcharpool; static int currentcharpool;
static int currentcharpoolsz; static size_t currentcharpoolsz;
static char *nextchar; static size_t nexti;
/* Allocated blocks are allocated to multiples of ALIGN_ON. This is the /* 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 definition used by the malloc in Glibc 2.7, which says that it "suffices for
@@ -87,7 +87,8 @@ static int cp_init(void) {
/* Create our char pool */ /* Create our char pool */
currentcharpool = 0; currentcharpool = 0;
currentcharpoolsz = 16384; currentcharpoolsz = 16384;
nextchar = charpool[0] = (char *) safe_malloc(currentcharpoolsz); nexti = 0;
charpool[0] = (char *) safe_malloc(currentcharpoolsz);
charpool_initialized = 1; charpool_initialized = 1;
return 0; return 0;
} }
@@ -109,8 +110,8 @@ static inline void cp_grow(void) {
} }
currentcharpoolsz <<= 1; currentcharpoolsz <<= 1;
nextchar = charpool[currentcharpool] = (char *) nexti = 0;
safe_malloc(currentcharpoolsz); charpool[currentcharpool] = (char *) safe_malloc(currentcharpoolsz);
} }
void *cp_alloc(int sz) { void *cp_alloc(int sz) {
@@ -122,9 +123,9 @@ void *cp_alloc(int sz) {
if ((modulus = sz % ALIGN_ON)) if ((modulus = sz % ALIGN_ON))
sz += ALIGN_ON - modulus; sz += ALIGN_ON - modulus;
if ((nextchar - charpool[currentcharpool]) + sz <= currentcharpoolsz) { if (nexti + sz <= currentcharpoolsz) {
p = nextchar; p = charpool[currentcharpool] + nexti;
nextchar += sz; nexti += sz;
return p; return p;
} }
/* Doh! We've got to make room */ /* Doh! We've got to make room */
@@ -134,32 +135,12 @@ void *cp_alloc(int sz) {
} }
char *cp_strdup(const char *src) { const char *cp_strndup(const char *src, int len) {
const char *p; char *dst = (char *) cp_alloc(len + 1); // Additional byte for null terminator
char *q; dst[len] = '\0';
/* end points to the first illegal char */ return (const char *) memcpy(dst, src, len);
char *end; }
int modulus;
const char *cp_strdup(const char *src) {
cp_init(); return cp_strndup(src, strlen(src));
end = charpool[currentcharpool] + currentcharpoolsz;
q = nextchar;
p = src;
while((nextchar < end) && *p) {
*nextchar++ = *p++;
}
if (nextchar < end) {
/* Goody, we have space */
*nextchar++ = '\0';
if ((modulus = (nextchar - q) % ALIGN_ON))
nextchar += ALIGN_ON - modulus;
return q;
}
/* Doh! We ran out -- need to allocate more */
cp_grow();
return cp_strdup(src);
} }

View File

@@ -66,7 +66,9 @@
#define CHARPOOL_H #define CHARPOOL_H
void *cp_alloc(int sz); void *cp_alloc(int sz);
char *cp_strdup(const char *src); /* 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); void cp_free(void);

View File

@@ -58,9 +58,11 @@
***************************************************************************/ ***************************************************************************/
#include "string_pool.h" #include "string_pool.h"
#include <nbase.h> #include <nbase.h>
#include "charpool.h"
#include <set> #include <set>
#include <string> #include <string>
#include <cstring>
#include <utility> #include <utility>
#include <stdarg.h> #include <stdarg.h>
#include <ctype.h> #include <ctype.h>
@@ -69,19 +71,52 @@
#undef NDEBUG #undef NDEBUG
#include <assert.h> #include <assert.h>
class StringPoolItem {
public:
const char *str;
int len;
bool in_cp;
StringPoolItem(const char *i_str, int i_len) : str(i_str), len(i_len), in_cp(false) {}
~StringPoolItem() {} // charpool allocations are permanent and can't be freed.
StringPoolItem(const StringPoolItem& other) {
// If the string is already in the charpool, there's no reason we should
// be copy-constructed, since that only happens on a successful insert
// (new unique item)
assert(!other.in_cp);
this->len = other.len;
this->str = cp_strndup(other.str, other.len);
this->in_cp = true;
}
// asdfq <> asdf
bool operator< (const StringPoolItem& other) const {
return this->len < other.len || memcmp(this->str, other.str, other.len) < 0;
}
};
typedef std::set<StringPoolItem> StringPool;
const char *string_pool_insert_len(const char *s, int len)
{
static StringPool pool;
StringPoolItem spi (s, len);
StringPool::iterator it = pool.insert(spi).first;
assert(it->in_cp); // We should only be storing charpool-allocated strings
return it->str;
}
const char *string_pool_insert(const char *s) const char *string_pool_insert(const char *s)
{ {
static std::set<std::string> pool; return string_pool_insert_len(s, strlen(s));
static std::pair<std::set<std::string>::iterator, bool> pair;
pair = pool.insert(s);
return pair.first->c_str();
} }
const char *string_pool_substr(const char *s, const char *t) const char *string_pool_substr(const char *s, const char *t)
{ {
return string_pool_insert(std::string(s, t).c_str()); assert(t >= s);
return string_pool_insert_len(s, t - s);
} }
const char *string_pool_substr_strip(const char *s, const char *t) { const char *string_pool_substr_strip(const char *s, const char *t) {
@@ -133,7 +168,7 @@ const char *string_pool_sprintf(const char *fmt, ...)
break; break;
} }
s = string_pool_insert(buf); s = string_pool_insert_len(buf, n);
free(buf); free(buf);
return s; return s;