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:
53
charpool.cc
53
charpool.cc
@@ -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);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user