From 2d8658e1b24a89ad1e09ddce50f91e88e25a4ba9 Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Thu, 27 Dec 2007 17:32:46 +0000 Subject: [PATCH] I'll have a need for inserting substrings into a stringpool. --- src/hash.h | 10 ++++++++++ src/strpool.c | 21 ++++++++++++++++----- src/strpool.h | 7 +++++++ 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/hash.h b/src/hash.h index 731a3e7..829085d 100644 --- a/src/hash.h +++ b/src/hash.h @@ -41,6 +41,16 @@ strhash(const char *str) return r; } +static inline Hashval +strnhash(const char *str, unsigned len) +{ + Hashval r = 0; + unsigned int c; + while (len-- && (c = *(const unsigned char *)str++) != 0) + r += (r << 3) + c; + return r; +} + /* hash for rel * rel -> hash */ diff --git a/src/strpool.c b/src/strpool.c index 622664f..7b0d765 100644 --- a/src/strpool.c +++ b/src/strpool.c @@ -37,7 +37,7 @@ stringpool_init (Stringpool *ss, const char *strs[]) } Id -stringpool_str2id (Stringpool *ss, const char *str, int create) +stringpool_strn2id (Stringpool *ss, const char *str, unsigned len, int create) { Hashval h; unsigned int hh; @@ -79,12 +79,13 @@ stringpool_str2id (Stringpool *ss, const char *str, int create) // compute hash and check for match - h = strhash(str) & hashmask; + h = strnhash(str, len) & hashmask; hh = HASHCHAIN_START; while ((id = hashtbl[h]) != 0) // follow hash overflow chain { // break if string already hashed - if(!strcmp(ss->stringspace + ss->strings[id], str)) + if(!memcmp(ss->stringspace + ss->strings[id], str, len) + && ss->stringspace[ss->strings[id] + len] == 0) break; h = HASHCHAIN_NEXT(h, hh, hashmask); } @@ -101,19 +102,29 @@ stringpool_str2id (Stringpool *ss, const char *str, int create) // 'pointer' into stringspace is Offset of next free pos: sstrings ss->strings[id] = ss->sstrings; - space_needed = strlen(str) + 1; + space_needed = len + 1; // resize string buffer if needed if (((ss->sstrings + space_needed - 1) | STRINGSPACE_BLOCK) != ((ss->sstrings - 1) | STRINGSPACE_BLOCK)) ss->stringspace = xrealloc(ss->stringspace, (ss->sstrings + space_needed + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK); // copy new string into buffer - memcpy(ss->stringspace + ss->sstrings, str, space_needed); + memcpy(ss->stringspace + ss->sstrings, str, space_needed - 1); + // add the sentinel, we can't rely on it being in the source string (in + // case the LEN is not really strlen(str)) + ss->stringspace[ss->sstrings + space_needed - 1] = 0; // next free pos is behind new string ss->sstrings += space_needed; return id; } +Id +stringpool_str2id (Stringpool *ss, const char *str, int create) +{ + unsigned len = strlen (str); + return stringpool_strn2id (ss, str, len, create); +} + void stringpool_shrink (Stringpool *ss) { diff --git a/src/strpool.h b/src/strpool.h index d326c4f..c8429b9 100644 --- a/src/strpool.h +++ b/src/strpool.h @@ -26,6 +26,13 @@ struct _Stringpool void stringpool_init (Stringpool *ss, const char *strs[]); Id stringpool_str2id (Stringpool *ss, const char *str, int create); +Id stringpool_strn2id (Stringpool *ss, const char *str, unsigned len, int create); void stringpool_shrink (Stringpool *ss); +static inline const char * +stringpool_id2str (Stringpool *ss, Id id) +{ + return ss->stringspace + ss->strings[id]; +} + #endif -- 2.7.4