diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1998-03-06 13:54:42 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1998-03-06 13:54:42 -0300 |
| commit | 88a2023c3285c4514519158fba90e644fc6ffca3 (patch) | |
| tree | da6611257545c486ff856dd48d66d94e056f3d66 /lstring.c | |
| parent | 5ef1989c4b05aff8362a7ea6ba62aad76d4a040d (diff) | |
| download | lua-88a2023c3285c4514519158fba90e644fc6ffca3.tar.gz lua-88a2023c3285c4514519158fba90e644fc6ffca3.tar.bz2 lua-88a2023c3285c4514519158fba90e644fc6ffca3.zip | |
support for strings with '\0'
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 | ||
