00001
00002
00003
00004
00005
00006
00007
00008 #include <string.h>
00009 #include "util.h"
00010 #include "strpool.h"
00011
00012 #define STRING_BLOCK 2047
00013 #define STRINGSPACE_BLOCK 65535
00014
00015 void
00016 stringpool_init(Stringpool *ss, const char *strs[])
00017 {
00018 unsigned totalsize = 0;
00019 unsigned count;
00020
00021 memset(ss, 0, sizeof(*ss));
00022
00023 for (count = 0; strs[count]; count++)
00024 totalsize += strlen(strs[count]) + 1;
00025
00026
00027 ss->stringspace = sat_extend_resize(0, totalsize, 1, STRINGSPACE_BLOCK);
00028 ss->strings = sat_extend_resize(0, count, sizeof(Offset), STRING_BLOCK);
00029
00030
00031 ss->sstrings = 0;
00032 for (count = 0; strs[count]; count++)
00033 {
00034 strcpy(ss->stringspace + ss->sstrings, strs[count]);
00035 ss->strings[count] = ss->sstrings;
00036 ss->sstrings += strlen(strs[count]) + 1;
00037 }
00038 ss->nstrings = count;
00039 }
00040
00041 void
00042 stringpool_free(Stringpool *ss)
00043 {
00044 sat_free(ss->strings);
00045 sat_free(ss->stringspace);
00046 sat_free(ss->stringhashtbl);
00047 }
00048
00049 void
00050 stringpool_freehash(Stringpool *ss)
00051 {
00052 ss->stringhashtbl = sat_free(ss->stringhashtbl);
00053 ss->stringhashmask = 0;
00054 }
00055
00056 void
00057 stringpool_init_empty(Stringpool *ss)
00058 {
00059 const char *emptystrs[] = {
00060 "<NULL>",
00061 "",
00062 0,
00063 };
00064 stringpool_init(ss, emptystrs);
00065 }
00066
00067 void
00068 stringpool_clone(Stringpool *ss, Stringpool *from)
00069 {
00070 memset(ss, 0, sizeof(*ss));
00071 ss->strings = sat_extend_resize(0, from->nstrings, sizeof(Offset), STRING_BLOCK);
00072 memcpy(ss->strings, from->strings, from->nstrings * sizeof(Offset));
00073 ss->stringspace = sat_extend_resize(0, from->sstrings, 1, STRINGSPACE_BLOCK);
00074 memcpy(ss->stringspace, from->stringspace, from->sstrings);
00075 ss->nstrings = from->nstrings;
00076 ss->sstrings = from->sstrings;
00077 }
00078
00079 Id
00080 stringpool_strn2id(Stringpool *ss, const char *str, unsigned int len, int create)
00081 {
00082 Hashval h;
00083 unsigned int hh;
00084 Hashmask hashmask;
00085 int i;
00086 Id id;
00087 Hashtable hashtbl;
00088
00089
00090 if (!str)
00091 return STRID_NULL;
00092 if (!len)
00093 return STRID_EMPTY;
00094
00095 hashmask = ss->stringhashmask;
00096 hashtbl = ss->stringhashtbl;
00097
00098
00099 if (ss->nstrings * 2 > hashmask)
00100 {
00101 sat_free(hashtbl);
00102
00103
00104 ss->stringhashmask = hashmask = mkmask(ss->nstrings + STRING_BLOCK);
00105 ss->stringhashtbl = hashtbl = (Hashtable)sat_calloc(hashmask + 1, sizeof(Id));
00106
00107
00108 for (i = 1; i < ss->nstrings; i++)
00109 {
00110 h = strhash(ss->stringspace + ss->strings[i]) & hashmask;
00111 hh = HASHCHAIN_START;
00112 while (hashtbl[h] != 0)
00113 h = HASHCHAIN_NEXT(h, hh, hashmask);
00114 hashtbl[h] = i;
00115 }
00116 }
00117
00118
00119 h = strnhash(str, len) & hashmask;
00120 hh = HASHCHAIN_START;
00121 while ((id = hashtbl[h]) != 0)
00122 {
00123
00124 if(!memcmp(ss->stringspace + ss->strings[id], str, len)
00125 && ss->stringspace[ss->strings[id] + len] == 0)
00126 break;
00127 h = HASHCHAIN_NEXT(h, hh, hashmask);
00128 }
00129 if (id || !create)
00130 return id;
00131
00132
00133 id = ss->nstrings++;
00134 hashtbl[h] = id;
00135
00136 ss->strings = sat_extend(ss->strings, id, 1, sizeof(Offset), STRING_BLOCK);
00137 ss->strings[id] = ss->sstrings;
00138
00139
00140 ss->stringspace = sat_extend(ss->stringspace, ss->sstrings, len + 1, 1, STRINGSPACE_BLOCK);
00141 memcpy(ss->stringspace + ss->sstrings, str, len);
00142 ss->stringspace[ss->sstrings + len] = 0;
00143 ss->sstrings += len + 1;
00144 return id;
00145 }
00146
00147 Id
00148 stringpool_str2id(Stringpool *ss, const char *str, int create)
00149 {
00150 if (!str)
00151 return STRID_NULL;
00152 if (!*str)
00153 return STRID_EMPTY;
00154 return stringpool_strn2id(ss, str, (unsigned int)strlen(str), create);
00155 }
00156
00157 void
00158 stringpool_shrink(Stringpool *ss)
00159 {
00160 ss->stringspace = sat_extend_resize(ss->stringspace, ss->sstrings, 1, STRINGSPACE_BLOCK);
00161 ss->strings = sat_extend_resize(ss->strings, ss->nstrings, sizeof(Offset), STRING_BLOCK);
00162 }