diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-12-01 14:40:29 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-12-01 14:40:29 -0200 |
| commit | 9d28b401527ccb41f544d431abe52da69e8beb3c (patch) | |
| tree | f079b0259179b3b1e5c0f9cc531a6b5b833da7a7 | |
| parent | e0bece77d6ee926de4ab3108b0fa84f03ff759d4 (diff) | |
| download | lua-9d28b401527ccb41f544d431abe52da69e8beb3c.tar.gz lua-9d28b401527ccb41f544d431abe52da69e8beb3c.tar.bz2 lua-9d28b401527ccb41f544d431abe52da69e8beb3c.zip | |
rehashes string table always allocating a new array instead of
reallocating old one. (Avoids problems if reallocation to a small
size fails.)
| -rw-r--r-- | lstring.c | 28 |
1 files changed, 11 insertions, 17 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstring.c,v 2.56 2015/11/23 11:32:51 roberto Exp roberto $ | 2 | ** $Id: lstring.c,v 2.57 2017/07/27 13:50:16 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 | */ |
| @@ -63,32 +63,26 @@ unsigned int luaS_hashlongstr (TString *ts) { | |||
| 63 | 63 | ||
| 64 | 64 | ||
| 65 | /* | 65 | /* |
| 66 | ** resizes the string table | 66 | ** Resizes the string table. |
| 67 | */ | 67 | */ |
| 68 | void luaS_resize (lua_State *L, int newsize) { | 68 | void luaS_resize (lua_State *L, int newsize) { |
| 69 | int i; | 69 | int i; |
| 70 | TString **newhash = luaM_newvector(L, newsize, TString *); | ||
| 70 | stringtable *tb = &G(L)->strt; | 71 | stringtable *tb = &G(L)->strt; |
| 71 | if (newsize > tb->size) { /* grow table if needed */ | 72 | for (i = 0; i < newsize; i++) /* initialize new hash array */ |
| 72 | luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *); | 73 | newhash[i] = NULL; |
| 73 | for (i = tb->size; i < newsize; i++) | 74 | for (i = 0; i < tb->size; i++) { /* rehash all elements into new array */ |
| 74 | tb->hash[i] = NULL; | ||
| 75 | } | ||
| 76 | for (i = 0; i < tb->size; i++) { /* rehash */ | ||
| 77 | TString *p = tb->hash[i]; | 75 | TString *p = tb->hash[i]; |
| 78 | tb->hash[i] = NULL; | 76 | while (p) { /* for each string in the list */ |
| 79 | while (p) { /* for each node in the list */ | ||
| 80 | TString *hnext = p->u.hnext; /* save next */ | 77 | TString *hnext = p->u.hnext; /* save next */ |
| 81 | unsigned int h = lmod(p->hash, newsize); /* new position */ | 78 | unsigned int h = lmod(p->hash, newsize); /* new position */ |
| 82 | p->u.hnext = tb->hash[h]; /* chain it */ | 79 | p->u.hnext = newhash[h]; /* chain it into new array */ |
| 83 | tb->hash[h] = p; | 80 | newhash[h] = p; |
| 84 | p = hnext; | 81 | p = hnext; |
| 85 | } | 82 | } |
| 86 | } | 83 | } |
| 87 | if (newsize < tb->size) { /* shrink table if needed */ | 84 | luaM_freearray(L, tb->hash, tb->size); /* free old array */ |
| 88 | /* vanishing slice should be empty */ | 85 | tb->hash = newhash; |
| 89 | lua_assert(tb->hash[newsize] == NULL && tb->hash[tb->size - 1] == NULL); | ||
| 90 | luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *); | ||
| 91 | } | ||
| 92 | tb->size = newsize; | 86 | tb->size = newsize; |
| 93 | } | 87 | } |
| 94 | 88 | ||
