diff options
Diffstat (limited to 'lstring.c')
-rw-r--r-- | lstring.c | 116 |
1 files changed, 75 insertions, 41 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstring.c,v 1.10 1998/01/13 18:06:27 roberto Exp roberto $ | 2 | ** $Id: lstring.c,v 1.11 1998/01/28 16:50:33 roberto Exp roberto $ |
3 | ** String table (keeps all strings handled by Lua) | 3 | ** String table (keeps all strings handled by Lua) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -21,7 +21,8 @@ | |||
21 | 21 | ||
22 | 22 | ||
23 | 23 | ||
24 | static TaggedString EMPTY = {{NULL, 2}, 0, 0L, {{LUA_T_NIL, {NULL}}}, {0}}; | 24 | static TaggedString EMPTY = {{NULL, 2}, 0L, 0, |
25 | {{{LUA_T_NIL, {NULL}}, 0L}}, {0}}; | ||
25 | 26 | ||
26 | 27 | ||
27 | void luaS_init (void) | 28 | void luaS_init (void) |
@@ -36,20 +37,14 @@ void luaS_init (void) | |||
36 | } | 37 | } |
37 | 38 | ||
38 | 39 | ||
39 | static unsigned long hash (char *s, int tag) | 40 | static unsigned long hash_s (char *s, long l) |
40 | { | 41 | { |
41 | unsigned long h; | 42 | unsigned long h = 0; |
42 | if (tag != LUA_T_STRING) | 43 | while (l--) |
43 | h = (unsigned long)s; | 44 | h = ((h<<5)-h)^(unsigned char)*(s++); |
44 | else { | ||
45 | h = 0; | ||
46 | while (*s) | ||
47 | h = ((h<<5)-h)^(unsigned char)*(s++); | ||
48 | } | ||
49 | return h; | 45 | return h; |
50 | } | 46 | } |
51 | 47 | ||
52 | |||
53 | static int newsize (stringtable *tb) | 48 | static int newsize (stringtable *tb) |
54 | { | 49 | { |
55 | int size = tb->size; | 50 | int size = tb->size; |
@@ -91,34 +86,67 @@ static void grow (stringtable *tb) | |||
91 | } | 86 | } |
92 | 87 | ||
93 | 88 | ||
94 | static TaggedString *newone (char *buff, int tag, unsigned long h) | 89 | static TaggedString *newone_s (char *str, long l, unsigned long h) |
95 | { | 90 | { |
96 | TaggedString *ts; | 91 | TaggedString *ts = (TaggedString *)luaM_malloc(sizeof(TaggedString)+l); |
97 | if (tag == LUA_T_STRING) { | 92 | memcpy(ts->str, str, l); |
98 | long l = strlen(buff); | 93 | ts->str[l] = 0; /* ending 0 */ |
99 | ts = (TaggedString *)luaM_malloc(sizeof(TaggedString)+l); | 94 | ts->u.s.globalval.ttype = LUA_T_NIL; /* initialize global value */ |
100 | strcpy(ts->str, buff); | 95 | ts->u.s.len = l; |
101 | ts->u.globalval.ttype = LUA_T_NIL; /* initialize global value */ | 96 | ts->constindex = 0; |
102 | ts->constindex = 0; | 97 | L->nblocks += gcsizestring(l); |
103 | L->nblocks += gcsizestring(l); | ||
104 | } | ||
105 | else { | ||
106 | ts = luaM_new(TaggedString); | ||
107 | ts->u.d.v = buff; | ||
108 | ts->u.d.tag = tag == LUA_ANYTAG ? 0 : tag; | ||
109 | ts->constindex = -1; /* tag -> this is a userdata */ | ||
110 | L->nblocks++; | ||
111 | } | ||
112 | ts->head.marked = 0; | 98 | ts->head.marked = 0; |
113 | ts->head.next = (GCnode *)ts; /* signal it is in no list */ | 99 | ts->head.next = (GCnode *)ts; /* signal it is in no list */ |
114 | ts->hash = h; | 100 | ts->hash = h; |
115 | return ts; | 101 | return ts; |
116 | } | 102 | } |
117 | 103 | ||
118 | static TaggedString *insert (char *buff, int tag, stringtable *tb) | 104 | static TaggedString *newone_u (char *buff, int tag, unsigned long h) |
105 | { | ||
106 | TaggedString *ts = luaM_new(TaggedString); | ||
107 | ts->u.d.v = buff; | ||
108 | ts->u.d.tag = (tag == LUA_ANYTAG) ? 0 : tag; | ||
109 | ts->constindex = -1; /* tag -> this is a userdata */ | ||
110 | L->nblocks++; | ||
111 | ts->head.marked = 0; | ||
112 | ts->head.next = (GCnode *)ts; /* signal it is in no list */ | ||
113 | ts->hash = h; | ||
114 | return ts; | ||
115 | } | ||
116 | |||
117 | static TaggedString *insert_s (char *str, long l, stringtable *tb) | ||
118 | { | ||
119 | TaggedString *ts; | ||
120 | unsigned long h = hash_s(str, l); | ||
121 | int size = tb->size; | ||
122 | int i; | ||
123 | int j = -1; | ||
124 | if ((long)tb->nuse*3 >= (long)size*2) { | ||
125 | grow(tb); | ||
126 | size = tb->size; | ||
127 | } | ||
128 | for (i = h%size; (ts = tb->hash[i]) != NULL; ) { | ||
129 | if (ts == &EMPTY) | ||
130 | j = i; | ||
131 | else if (ts->constindex >= 0 && | ||
132 | ts->u.s.len == l && | ||
133 | (memcmp(str, ts->str, l) == 0)) | ||
134 | return ts; | ||
135 | if (++i == size) i=0; | ||
136 | } | ||
137 | /* not found */ | ||
138 | if (j != -1) /* is there an EMPTY space? */ | ||
139 | i = j; | ||
140 | else | ||
141 | tb->nuse++; | ||
142 | ts = tb->hash[i] = newone_s(str, l, h); | ||
143 | return ts; | ||
144 | } | ||
145 | |||
146 | static TaggedString *insert_u (void *buff, int tag, stringtable *tb) | ||
119 | { | 147 | { |
120 | TaggedString *ts; | 148 | TaggedString *ts; |
121 | unsigned long h = hash(buff, tag); | 149 | unsigned long h = (unsigned long)buff; |
122 | int size = tb->size; | 150 | int size = tb->size; |
123 | int i; | 151 | int i; |
124 | int j = -1; | 152 | int j = -1; |
@@ -129,9 +157,9 @@ static TaggedString *insert (char *buff, int tag, stringtable *tb) | |||
129 | for (i = h%size; (ts = tb->hash[i]) != NULL; ) { | 157 | for (i = h%size; (ts = tb->hash[i]) != NULL; ) { |
130 | if (ts == &EMPTY) | 158 | if (ts == &EMPTY) |
131 | j = i; | 159 | j = i; |
132 | else if ((ts->constindex >= 0) ? /* is a string? */ | 160 | else if (ts->constindex < 0 && /* is a udata? */ |
133 | (tag == LUA_T_STRING && (strcmp(buff, ts->str) == 0)) : | 161 | (tag == ts->u.d.tag || tag == LUA_ANYTAG) && |
134 | ((tag == ts->u.d.tag || tag == LUA_ANYTAG) && buff == ts->u.d.v)) | 162 | buff == ts->u.d.v) |
135 | return ts; | 163 | return ts; |
136 | if (++i == size) i=0; | 164 | if (++i == size) i=0; |
137 | } | 165 | } |
@@ -140,18 +168,24 @@ static TaggedString *insert (char *buff, int tag, stringtable *tb) | |||
140 | i = j; | 168 | i = j; |
141 | else | 169 | else |
142 | tb->nuse++; | 170 | tb->nuse++; |
143 | ts = tb->hash[i] = newone(buff, tag, h); | 171 | ts = tb->hash[i] = newone_u(buff, tag, h); |
144 | return ts; | 172 | return ts; |
145 | } | 173 | } |
146 | 174 | ||
147 | TaggedString *luaS_createudata (void *udata, int tag) | 175 | TaggedString *luaS_createudata (void *udata, int tag) |
148 | { | 176 | { |
149 | return insert(udata, tag, &L->string_root[(unsigned)udata%NUM_HASHS]); | 177 | return insert_u(udata, tag, &L->string_root[(unsigned)udata%NUM_HASHS]); |
178 | } | ||
179 | |||
180 | TaggedString *luaS_newlstr (char *str, long l) | ||
181 | { | ||
182 | int i = (l==0)?0:(unsigned char)str[0]; | ||
183 | return insert_s(str, l, &L->string_root[i%NUM_HASHS]); | ||
150 | } | 184 | } |
151 | 185 | ||
152 | TaggedString *luaS_new (char *str) | 186 | TaggedString *luaS_new (char *str) |
153 | { | 187 | { |
154 | return insert(str, LUA_T_STRING, &L->string_root[(unsigned)str[0]%NUM_HASHS]); | 188 | return luaS_newlstr(str, strlen(str)); |
155 | } | 189 | } |
156 | 190 | ||
157 | TaggedString *luaS_newfixedstring (char *str) | 191 | TaggedString *luaS_newfixedstring (char *str) |
@@ -167,7 +201,7 @@ void luaS_free (TaggedString *l) | |||
167 | { | 201 | { |
168 | while (l) { | 202 | while (l) { |
169 | TaggedString *next = (TaggedString *)l->head.next; | 203 | TaggedString *next = (TaggedString *)l->head.next; |
170 | L->nblocks -= (l->constindex == -1) ? 1 : gcsizestring(strlen(l->str)); | 204 | L->nblocks -= (l->constindex == -1) ? 1 : gcsizestring(l->u.s.len); |
171 | luaM_free(l); | 205 | luaM_free(l); |
172 | l = next; | 206 | l = next; |
173 | } | 207 | } |
@@ -253,7 +287,7 @@ void luaS_freeall (void) | |||
253 | 287 | ||
254 | void luaS_rawsetglobal (TaggedString *ts, TObject *newval) | 288 | void luaS_rawsetglobal (TaggedString *ts, TObject *newval) |
255 | { | 289 | { |
256 | ts->u.globalval = *newval; | 290 | ts->u.s.globalval = *newval; |
257 | if (ts->head.next == (GCnode *)ts) { /* is not in list? */ | 291 | if (ts->head.next == (GCnode *)ts) { /* is not in list? */ |
258 | ts->head.next = L->rootglobal.next; | 292 | ts->head.next = L->rootglobal.next; |
259 | L->rootglobal.next = (GCnode *)ts; | 293 | L->rootglobal.next = (GCnode *)ts; |
@@ -265,7 +299,7 @@ char *luaS_travsymbol (int (*fn)(TObject *)) | |||
265 | { | 299 | { |
266 | TaggedString *g; | 300 | TaggedString *g; |
267 | for (g=(TaggedString *)L->rootglobal.next; g; g=(TaggedString *)g->head.next) | 301 | for (g=(TaggedString *)L->rootglobal.next; g; g=(TaggedString *)g->head.next) |
268 | if (fn(&g->u.globalval)) | 302 | if (fn(&g->u.s.globalval)) |
269 | return g->str; | 303 | return g->str; |
270 | return NULL; | 304 | return NULL; |
271 | } | 305 | } |
@@ -274,6 +308,6 @@ char *luaS_travsymbol (int (*fn)(TObject *)) | |||
274 | int luaS_globaldefined (char *name) | 308 | int luaS_globaldefined (char *name) |
275 | { | 309 | { |
276 | TaggedString *ts = luaS_new(name); | 310 | TaggedString *ts = luaS_new(name); |
277 | return ts->u.globalval.ttype != LUA_T_NIL; | 311 | return ts->u.s.globalval.ttype != LUA_T_NIL; |
278 | } | 312 | } |
279 | 313 | ||