summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2007-11-16 13:48:23 +0000
committerMichael Matz <matz@suse.de>2007-11-16 13:48:23 +0000
commit9e09e79d5ea318d3e4ec8f9dc7b2d53c9c2a07c6 (patch)
tree096d85b660e63cc5c670a353add5b41c98536f80 /src
parent06ad039561bc89fb3937a0503870333d32ee087e (diff)
downloadlibsolv-9e09e79d5ea318d3e4ec8f9dc7b2d53c9c2a07c6.tar.gz
libsolv-9e09e79d5ea318d3e4ec8f9dc7b2d53c9c2a07c6.tar.bz2
libsolv-9e09e79d5ea318d3e4ec8f9dc7b2d53c9c2a07c6.zip
Reduce C&P code by factoring out the uniquifying string pool.
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt4
-rw-r--r--src/pool.c44
-rw-r--r--src/pool.h16
-rw-r--r--src/poolid.c98
-rw-r--r--src/poolid_private.h4
-rw-r--r--src/pooltypes.h3
-rw-r--r--src/repo_solv.c28
-rw-r--r--src/strpool.c122
-rw-r--r--src/strpool.h31
9 files changed, 206 insertions, 144 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 6d8aec1..be1ec6a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,10 +1,10 @@
-SET(libsatsolver_SRCS bitmap.c poolarch.c poolvendor.c poolid.c
+SET(libsatsolver_SRCS bitmap.c poolarch.c poolvendor.c poolid.c strpool.c
solver.c repo_solv.c evr.c pool.c queue.c repo.c util.c policy.c )
ADD_LIBRARY(satsolver STATIC ${libsatsolver_SRCS})
-SET(libsatsolver_HEADERS bitmap.h evr.h hash.h policy.h poolarch.h poolvendor.h pool.h poolid.h pooltypes.h queue.h solvable.h solver.h repo.h repo_solv.h util.h )
+SET(libsatsolver_HEADERS bitmap.h evr.h hash.h policy.h poolarch.h poolvendor.h pool.h poolid.h pooltypes.h queue.h solvable.h solver.h repo.h repo_solv.h util.h strpool.h )
SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O3 -Wall -fPIC" )
diff --git a/src/pool.c b/src/pool.c
index 765010a..c40d337 100644
--- a/src/pool.c
+++ b/src/pool.c
@@ -40,7 +40,7 @@ pool_freewhatprovides(Pool *pool)
// list of string constants, so we can do pointer/Id instead of string comparison
// index into array matches ID_xxx constants in pool.h
-static char *initpool_data[] = {
+static const char *initpool_data[] = {
"<NULL>", // ID_NULL
"", // ID_EMPTY
"solvable:name",
@@ -64,7 +64,8 @@ static char *initpool_data[] = {
"system:system",
"src",
"nosrc",
- "noarch"
+ "noarch",
+ 0
};
// create pool
@@ -72,29 +73,12 @@ static char *initpool_data[] = {
Pool *
pool_create(void)
{
- int count, totalsize = 0;
Pool *pool;
Solvable *s;
pool = (Pool *)xcalloc(1, sizeof(*pool));
- // count number and total size of predefined strings
- for (count = 0; count < sizeof(initpool_data)/sizeof(*initpool_data); count++)
- totalsize += strlen(initpool_data[count]) + 1;
-
- // alloc appropriate space
- pool->stringspace = (char *)xmalloc((totalsize + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK);
- pool->strings = (Offset *)xmalloc(((count + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Offset));
-
- // now copy predefined strings into allocated space
- pool->sstrings = 0;
- for (count = 0; count < sizeof(initpool_data)/sizeof(*initpool_data); count++)
- {
- strcpy(pool->stringspace + pool->sstrings, initpool_data[count]);
- pool->strings[count] = pool->sstrings;
- pool->sstrings += strlen(initpool_data[count]) + 1;
- }
- pool->nstrings = count;
+ stringpool_init (&pool->ss, initpool_data);
// pre-alloc space for a RelDep
pool->rels = (Reldep *)xcalloc(1 + REL_BLOCK, sizeof(Reldep));
@@ -124,8 +108,8 @@ pool_free(Pool *pool)
pool_freeallrepos(pool, 1);
xfree(pool->id2arch);
xfree(pool->solvables);
- xfree(pool->stringspace);
- xfree(pool->strings);
+ xfree(pool->ss.stringspace);
+ xfree(pool->ss.strings);
xfree(pool->rels);
queue_free(&pool->vendormap);
for (i = 0; i < DEP2STRBUF; i++)
@@ -169,16 +153,16 @@ pool_shrink_whatprovides(Pool *pool)
Offset o;
int r;
- if (pool->nstrings < 3)
+ if (pool->ss.nstrings < 3)
return;
- sorted = xmalloc2(pool->nstrings, sizeof(Id));
- for (id = 0; id < pool->nstrings; id++)
+ sorted = xmalloc2(pool->ss.nstrings, sizeof(Id));
+ for (id = 0; id < pool->ss.nstrings; id++)
sorted[id] = id;
pool_shrink_whatprovides_sortcmp_data = pool;
- qsort(sorted + 1, pool->nstrings - 1, sizeof(Id), pool_shrink_whatprovides_sortcmp);
+ qsort(sorted + 1, pool->ss.nstrings - 1, sizeof(Id), pool_shrink_whatprovides_sortcmp);
last = 0;
lastid = 0;
- for (i = 1; i < pool->nstrings; i++)
+ for (i = 1; i < pool->ss.nstrings; i++)
{
id = sorted[i];
o = pool->whatprovides[id];
@@ -207,7 +191,7 @@ pool_shrink_whatprovides(Pool *pool)
}
xfree(sorted);
dp = pool->whatprovidesdata + 2;
- for (id = 1; id < pool->nstrings; id++)
+ for (id = 1; id < pool->ss.nstrings; id++)
{
o = pool->whatprovides[id];
if (o == 0 || o == 1)
@@ -262,11 +246,11 @@ pool_prepare(Pool *pool)
if (pool->verbose)
printf("number of solvables: %d\n", pool->nsolvables);
if (pool->verbose)
- printf("number of ids: %d + %d\n", pool->nstrings, pool->nrels);
+ printf("number of ids: %d + %d\n", pool->ss.nstrings, pool->nrels);
pool_freeidhashes(pool);
pool_freewhatprovides(pool);
- num = pool->nstrings + pool->nrels;
+ num = pool->ss.nstrings + pool->nrels;
whatprovides = (Offset *)xcalloc(num, sizeof(Offset));
/* count providers for each name */
diff --git a/src/pool.h b/src/pool.h
index 2861c9b..aa019a3 100644
--- a/src/pool.h
+++ b/src/pool.h
@@ -22,12 +22,13 @@ extern "C" {
#include "repo.h"
#include "solvable.h"
#include "queue.h"
+#include "strpool.h"
// see initpool_data[] in pool.c
/* well known ids */
-#define ID_NULL 0
-#define ID_EMPTY 1
+#define ID_NULL STRID_NULL
+#define ID_EMPTY STRID_EMPTY
#define SOLVABLE_NAME 2
#define SOLVABLE_ARCH 3
#define SOLVABLE_EVR 4
@@ -58,19 +59,12 @@ extern "C" {
/* how many strings to maintain (round robin) */
#define DEP2STRBUF 16
-
//-----------------------------------------------
struct _Pool {
int verbose; // pool is used everywhere, so put the verbose flag here
- Offset *strings; // table of offsets into stringspace, indexed by Id: Id -> Offset
- int nstrings; // number of unique strings in stringspace
- char *stringspace; // space for all unique strings: stringspace + Offset = string
- Offset sstrings; // next free pos in stringspace
-
- Hashtable stringhashtbl; // hash table: (string ->) Hash -> Id
- Hashmask stringhashmask; // modulo value for hash table (size of table - 1)
+ struct _Stringpool ss;
Reldep *rels; // table of rels: Id -> Reldep
int nrels; // number of unique rels
@@ -135,7 +129,7 @@ struct _Pool {
#define MAKERELDEP(id) ((id) | 0x80000000)
#define ISRELDEP(id) (((id) & 0x80000000) != 0)
-#define GETRELID(pool, id) ((pool)->nstrings + ((id) ^ 0x80000000)) /* returns Id */
+#define GETRELID(pool, id) ((pool)->ss.nstrings + ((id) ^ 0x80000000)) /* returns Id */
#define GETRELDEP(pool, id) ((pool)->rels + ((id) ^ 0x80000000)) /* returns Reldep* */
#define REL_GT 1
diff --git a/src/poolid.c b/src/poolid.c
index bc49bba..ef76a4a 100644
--- a/src/poolid.c
+++ b/src/poolid.c
@@ -27,84 +27,15 @@
Id
str2id(Pool *pool, const char *str, int create)
{
- Hashval h;
- unsigned int hh;
- Hashmask hashmask;
- int i, space_needed;
- Id id;
- Hashtable hashtbl;
-
- // check string
- if (!str)
- return ID_NULL;
- if (!*str)
- return ID_EMPTY;
-
- hashmask = pool->stringhashmask;
- hashtbl = pool->stringhashtbl;
-
- // expand hashtable if needed
- //
- //
- if (pool->nstrings * 2 > hashmask)
- {
- xfree(hashtbl);
-
- // realloc hash table
- pool->stringhashmask = hashmask = mkmask(pool->nstrings + STRING_BLOCK);
- pool->stringhashtbl = hashtbl = (Hashtable)xcalloc(hashmask + 1, sizeof(Id));
-
- // rehash all strings into new hashtable
- for (i = 1; i < pool->nstrings; i++)
- {
- h = strhash(pool->stringspace + pool->strings[i]) & hashmask;
- hh = HASHCHAIN_START;
- while (hashtbl[h] != ID_NULL) // follow overflow chain
- h = HASHCHAIN_NEXT(h, hh, hashmask);
- hashtbl[h] = i;
- }
- }
-
- // compute hash and check for match
-
- h = strhash(str) & hashmask;
- hh = HASHCHAIN_START;
- while ((id = hashtbl[h]) != ID_NULL) // follow hash overflow chain
- {
- // break if string already hashed
- if(!strcmp(pool->stringspace + pool->strings[id], str))
- break;
- h = HASHCHAIN_NEXT(h, hh, hashmask);
- }
- if (id || !create) // exit here if string found
- return id;
-
- pool_freewhatprovides(pool);
-
- // generate next id and save in table
- id = pool->nstrings++;
- hashtbl[h] = id;
-
- //
- if ((id & STRING_BLOCK) == 0)
- pool->strings = xrealloc(pool->strings, ((pool->nstrings + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Hashval));
- // 'pointer' into stringspace is Offset of next free pos: sstrings
- pool->strings[id] = pool->sstrings;
-
- space_needed = strlen(str) + 1;
-
- // resize string buffer if needed
- if (((pool->sstrings + space_needed - 1) | STRINGSPACE_BLOCK) != ((pool->sstrings - 1) | STRINGSPACE_BLOCK))
- pool->stringspace = xrealloc(pool->stringspace, (pool->sstrings + space_needed + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK);
- // copy new string into buffer
- memcpy(pool->stringspace + pool->sstrings, str, space_needed);
- // next free pos is behind new string
- pool->sstrings += space_needed;
-
+ int old_nstrings = pool->ss.nstrings;
+ Id id = stringpool_str2id (&pool->ss, str, create);
+ /* If we changed the ID->string relations we need to get rid of an
+ eventually existing provides lookup cache. */
+ if (old_nstrings != pool->ss.nstrings)
+ pool_freewhatprovides(pool);
return id;
}
-
Id
rel2id(Pool *pool, Id name, Id evr, int flags, int create)
{
@@ -124,7 +55,7 @@ rel2id(Pool *pool, Id name, Id evr, int flags, int create)
if (pool->nrels * 2 > hashmask)
{
xfree(pool->relhashtbl);
- pool->relhashmask = hashmask = mkmask(pool->nstrings + REL_BLOCK);
+ pool->relhashmask = hashmask = mkmask(pool->ss.nstrings + REL_BLOCK);
pool->relhashtbl = hashtbl = xcalloc(hashmask + 1, sizeof(Id));
// rehash all rels into new hashtable
for (i = 1; i < pool->nrels; i++)
@@ -179,9 +110,9 @@ id2str(Pool *pool, Id id)
Reldep *rd = GETRELDEP(pool, id);
if (ISRELDEP(rd->name))
return "REL";
- return pool->stringspace + pool->strings[rd->name];
+ return pool->ss.stringspace + pool->ss.strings[rd->name];
}
- return pool->stringspace + pool->strings[id];
+ return pool->ss.stringspace + pool->ss.strings[id];
}
static const char *rels[] = {
@@ -235,7 +166,7 @@ id2evr(Pool *pool, Id id)
rd = GETRELDEP(pool, id);
if (ISRELDEP(rd->evr))
return "REL";
- return pool->stringspace + pool->strings[rd->evr];
+ return pool->ss.stringspace + pool->ss.strings[rd->evr];
}
const char *
@@ -247,7 +178,7 @@ dep2str(Pool *pool, Id id)
int n, l, ls1, ls2, lsr;
if (!ISRELDEP(id))
- return pool->stringspace + pool->strings[id];
+ return pool->ss.stringspace + pool->ss.strings[id];
rd = GETRELDEP(pool, id);
n = pool->dep2strn;
@@ -305,8 +236,7 @@ dep2str(Pool *pool, Id id)
void
pool_shrink_strings(Pool *pool)
{
- pool->stringspace = (char *)xrealloc(pool->stringspace, (pool->sstrings + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK);
- pool->strings = (Offset *)xrealloc(pool->strings, ((pool->nstrings + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Offset));
+ stringpool_shrink (&pool->ss);
}
void
@@ -320,9 +250,9 @@ pool_shrink_rels(Pool *pool)
void
pool_freeidhashes(Pool *pool)
{
- pool->stringhashtbl = xfree(pool->stringhashtbl);
+ pool->ss.stringhashtbl = xfree(pool->ss.stringhashtbl);
+ pool->ss.stringhashmask = 0;
pool->relhashtbl = xfree(pool->relhashtbl);
- pool->stringhashmask = 0;
pool->relhashmask = 0;
}
diff --git a/src/poolid_private.h b/src/poolid_private.h
index e293dbb..374b991 100644
--- a/src/poolid_private.h
+++ b/src/poolid_private.h
@@ -15,10 +15,8 @@
// the size of all buffers is incremented in blocks
// these are the block values (increment values) for the
-// string hashtable, rel hashtable, stringspace buffer and idarray
+// rel hashtable
//
-#define STRING_BLOCK 2047 // hashtable for strings
#define REL_BLOCK 1023 // hashtable for relations
-#define STRINGSPACE_BLOCK 65535 // string buffer
#endif /* POOLID_PRIVATE_H */
diff --git a/src/pooltypes.h b/src/pooltypes.h
index 6117c29..f3bc194 100644
--- a/src/pooltypes.h
+++ b/src/pooltypes.h
@@ -16,6 +16,9 @@
/* version number for .solv files */
#define SOLV_VERSION 0
+struct _Stringpool;
+typedef struct _Stringpool Stringpool;
+
struct _Pool;
typedef struct _Pool Pool;
diff --git a/src/repo_solv.c b/src/repo_solv.c
index 1b0b595..6c512e8 100644
--- a/src/repo_solv.c
+++ b/src/repo_solv.c
@@ -230,15 +230,15 @@ repo_add_solv(Repo *repo, FILE *fp)
*/
/* alloc string buffer */
- strsp = (char *)xrealloc(pool->stringspace, pool->sstrings + sizeid + 1);
+ strsp = (char *)xrealloc(pool->ss.stringspace, pool->ss.sstrings + sizeid + 1);
/* alloc string offsets (Id -> Offset into string space) */
- str = (Offset *)xrealloc(pool->strings, (pool->nstrings + numid) * sizeof(Offset));
+ str = (Offset *)xrealloc(pool->ss.strings, (pool->ss.nstrings + numid) * sizeof(Offset));
- pool->stringspace = strsp;
- pool->strings = str; /* array of offsets into strsp, indexed by Id */
+ pool->ss.stringspace = strsp;
+ pool->ss.strings = str; /* array of offsets into strsp, indexed by Id */
/* point to _BEHIND_ already allocated string/Id space */
- strsp += pool->sstrings;
+ strsp += pool->ss.sstrings;
/* alloc id map for name and rel Ids. this maps ids in the solv files
* to the ids in our pool */
@@ -261,7 +261,7 @@ repo_add_solv(Repo *repo, FILE *fp)
*
*/
- hashmask = mkmask(pool->nstrings + numid);
+ hashmask = mkmask(pool->ss.nstrings + numid);
#if 0
printf("read %d strings\n", numid);
@@ -278,9 +278,9 @@ repo_add_solv(Repo *repo, FILE *fp)
* fill hashtable with strings already in pool
*/
- for (i = 1; i < pool->nstrings; i++) /* leave out our dummy zero id */
+ for (i = 1; i < pool->ss.nstrings; i++) /* leave out our dummy zero id */
{
- h = strhash(pool->stringspace + pool->strings[i]) & hashmask;
+ h = strhash(pool->ss.stringspace + pool->ss.strings[i]) & hashmask;
hh = HASHCHAIN_START;
while (hashtbl[h])
h = HASHCHAIN_NEXT(h, hh, hashmask);
@@ -315,7 +315,7 @@ repo_add_solv(Repo *repo, FILE *fp)
id = hashtbl[h];
if (id == 0)
break;
- if (!strcmp(pool->stringspace + pool->strings[id], sp))
+ if (!strcmp(pool->ss.stringspace + pool->ss.strings[id], sp))
break; /* existing string */
h = HASHCHAIN_NEXT(h, hh, hashmask);
}
@@ -324,12 +324,12 @@ repo_add_solv(Repo *repo, FILE *fp)
l = strlen(sp) + 1;
if (id == ID_NULL) /* end of hash chain -> new string */
{
- id = pool->nstrings++;
+ id = pool->ss.nstrings++;
hashtbl[h] = id;
- str[id] = pool->sstrings; /* save Offset */
- if (sp != pool->stringspace + pool->sstrings) /* not at end-of-buffer */
- memmove(pool->stringspace + pool->sstrings, sp, l); /* append to pool buffer */
- pool->sstrings += l;
+ str[id] = pool->ss.sstrings; /* save Offset */
+ if (sp != pool->ss.stringspace + pool->ss.sstrings) /* not at end-of-buffer */
+ memmove(pool->ss.stringspace + pool->ss.sstrings, sp, l); /* append to pool buffer */
+ pool->ss.sstrings += l;
}
idmap[i] = id; /* repo relative -> pool relative */
sp += l; /* next string */
diff --git a/src/strpool.c b/src/strpool.c
new file mode 100644
index 0000000..622664f
--- /dev/null
+++ b/src/strpool.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2007, Novell Inc.
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+#include <string.h>
+#include "util.h"
+#include "strpool.h"
+
+#define STRING_BLOCK 2047
+#define STRINGSPACE_BLOCK 65535
+
+void
+stringpool_init (Stringpool *ss, const char *strs[])
+{
+ unsigned totalsize = 0;
+ unsigned count;
+ // count number and total size of predefined strings
+ for (count = 0; strs[count]; count++)
+ totalsize += strlen(strs[count]) + 1;
+
+ // alloc appropriate space
+ ss->stringspace = (char *)xmalloc((totalsize + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK);
+ ss->strings = (Offset *)xmalloc(((count + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Offset));
+
+ // now copy predefined strings into allocated space
+ ss->sstrings = 0;
+ for (count = 0; strs[count]; count++)
+ {
+ strcpy(ss->stringspace + ss->sstrings, strs[count]);
+ ss->strings[count] = ss->sstrings;
+ ss->sstrings += strlen(strs[count]) + 1;
+ }
+ ss->nstrings = count;
+}
+
+Id
+stringpool_str2id (Stringpool *ss, const char *str, int create)
+{
+ Hashval h;
+ unsigned int hh;
+ Hashmask hashmask;
+ int i, space_needed;
+ Id id;
+ Hashtable hashtbl;
+
+ // check string
+ if (!str)
+ return STRID_NULL;
+ if (!*str)
+ return STRID_EMPTY;
+
+ hashmask = ss->stringhashmask;
+ hashtbl = ss->stringhashtbl;
+
+ // expand hashtable if needed
+ //
+ //
+ if (ss->nstrings * 2 > hashmask)
+ {
+ xfree(hashtbl);
+
+ // realloc hash table
+ ss->stringhashmask = hashmask = mkmask(ss->nstrings + STRING_BLOCK);
+ ss->stringhashtbl = hashtbl = (Hashtable)xcalloc(hashmask + 1, sizeof(Id));
+
+ // rehash all strings into new hashtable
+ for (i = 1; i < ss->nstrings; i++)
+ {
+ h = strhash(ss->stringspace + ss->strings[i]) & hashmask;
+ hh = HASHCHAIN_START;
+ while (hashtbl[h] != 0) // follow overflow chain
+ h = HASHCHAIN_NEXT(h, hh, hashmask);
+ hashtbl[h] = i;
+ }
+ }
+
+ // compute hash and check for match
+
+ h = strhash(str) & 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))
+ break;
+ h = HASHCHAIN_NEXT(h, hh, hashmask);
+ }
+ if (id || !create) // exit here if string found
+ return id;
+
+ // generate next id and save in table
+ id = ss->nstrings++;
+ hashtbl[h] = id;
+
+ //
+ if ((id & STRING_BLOCK) == 0)
+ ss->strings = xrealloc(ss->strings, ((ss->nstrings + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Hashval));
+ // 'pointer' into stringspace is Offset of next free pos: sstrings
+ ss->strings[id] = ss->sstrings;
+
+ space_needed = strlen(str) + 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);
+ // next free pos is behind new string
+ ss->sstrings += space_needed;
+
+ return id;
+}
+
+void
+stringpool_shrink (Stringpool *ss)
+{
+ ss->stringspace = (char *)xrealloc(ss->stringspace, (ss->sstrings + STRINGSPACE_BLOCK) & ~STRINGSPACE_BLOCK);
+ ss->strings = (Offset *)xrealloc(ss->strings, ((ss->nstrings + STRING_BLOCK) & ~STRING_BLOCK) * sizeof(Offset));
+}
diff --git a/src/strpool.h b/src/strpool.h
new file mode 100644
index 0000000..58f7edd
--- /dev/null
+++ b/src/strpool.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007, Novell Inc.
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+#ifndef STRINGPOOL_H
+#define STRINGPOOL_H
+
+#include "pooltypes.h"
+#include "hash.h"
+
+#define STRID_NULL 0
+#define STRID_EMPTY 1
+
+struct _Stringpool
+{
+ Offset *strings; // table of offsets into stringspace, indexed by Id: Id -> Offset
+ int nstrings; // number of unique strings in stringspace
+ char *stringspace; // space for all unique strings: stringspace + Offset = string
+ Offset sstrings; // next free pos in stringspace
+
+ Hashtable stringhashtbl; // hash table: (string ->) Hash -> Id
+ Hashmask stringhashmask; // modulo value for hash table (size of table - 1)
+};
+
+void stringpool_init (Stringpool *ss, const char *strs[]);
+Id stringpool_str2id (Stringpool *ss, const char *str, int create);
+void stringpool_shrink (Stringpool *ss);
+
+#endif