diff options
Diffstat (limited to 'plugins/MirLua/src/lua/lstring.c')
-rw-r--r-- | plugins/MirLua/src/lua/lstring.c | 72 |
1 files changed, 58 insertions, 14 deletions
diff --git a/plugins/MirLua/src/lua/lstring.c b/plugins/MirLua/src/lua/lstring.c index 2947113c3c..5e0e3c40be 100644 --- a/plugins/MirLua/src/lua/lstring.c +++ b/plugins/MirLua/src/lua/lstring.c @@ -1,5 +1,5 @@ /* -** $Id: lstring.c,v 2.45 2014/11/02 19:19:04 roberto Exp $ +** $Id: lstring.c,v 2.49 2015/06/01 16:34:37 roberto Exp $ ** String table (keeps all strings handled by Lua) ** See Copyright Notice in lua.h */ @@ -22,6 +22,8 @@ #include "lstring.h" +#define MEMERRMSG "not enough memory" + /* ** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to @@ -36,10 +38,10 @@ ** equality for long strings */ int luaS_eqlngstr (TString *a, TString *b) { - size_t len = a->len; + size_t len = a->u.lnglen; lua_assert(a->tt == LUA_TLNGSTR && b->tt == LUA_TLNGSTR); return (a == b) || /* same instance or... */ - ((len == b->len) && /* equal length and ... */ + ((len == b->u.lnglen) && /* equal length and ... */ (memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */ } @@ -69,9 +71,9 @@ void luaS_resize (lua_State *L, int newsize) { TString *p = tb->hash[i]; tb->hash[i] = NULL; while (p) { /* for each node in the list */ - TString *hnext = p->hnext; /* save next */ + TString *hnext = p->u.hnext; /* save next */ unsigned int h = lmod(p->hash, newsize); /* new position */ - p->hnext = tb->hash[h]; /* chain it */ + p->u.hnext = tb->hash[h]; /* chain it */ tb->hash[h] = p; p = hnext; } @@ -85,6 +87,34 @@ void luaS_resize (lua_State *L, int newsize) { } +/* +** Clear API string cache. (Entries cannot be empty, so fill them with +** a non-collectable string.) +*/ +void luaS_clearcache (global_State *g) { + int i; + for (i = 0; i < STRCACHE_SIZE; i++) { + if (iswhite(g->strcache[i][0])) /* will entry be collected? */ + g->strcache[i][0] = g->memerrmsg; /* replace it with something fixed */ + } +} + + +/* +** Initialize the string table and the string cache +*/ +void luaS_init (lua_State *L) { + global_State *g = G(L); + int i; + luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ + /* pre-create memory-error message */ + g->memerrmsg = luaS_newliteral(L, MEMERRMSG); + luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */ + for (i = 0; i < STRCACHE_SIZE; i++) /* fill cache with valid strings */ + g->strcache[i][0] = g->memerrmsg; +} + + /* ** creates a new string object @@ -97,7 +127,6 @@ static TString *createstrobj (lua_State *L, const char *str, size_t l, totalsize = sizelstring(l); o = luaC_newobj(L, tag, totalsize); ts = gco2ts(o); - ts->len = l; ts->hash = h; ts->extra = 0; memcpy(getaddrstr(ts), str, l * sizeof(char)); @@ -110,8 +139,8 @@ void luaS_remove (lua_State *L, TString *ts) { stringtable *tb = &G(L)->strt; TString **p = &tb->hash[lmod(ts->hash, tb->size)]; while (*p != ts) /* find previous element */ - p = &(*p)->hnext; - *p = (*p)->hnext; /* remove element from its list */ + p = &(*p)->u.hnext; + *p = (*p)->u.hnext; /* remove element from its list */ tb->nuse--; } @@ -124,8 +153,8 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) { global_State *g = G(L); unsigned int h = luaS_hash(str, l, g->seed); TString **list = &g->strt.hash[lmod(h, g->strt.size)]; - for (ts = *list; ts != NULL; ts = ts->hnext) { - if (l == ts->len && + for (ts = *list; ts != NULL; ts = ts->u.hnext) { + if (l == ts->shrlen && (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { /* found! */ if (isdead(g, ts)) /* dead (but not collected yet)? */ @@ -138,7 +167,8 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) { list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */ } ts = createstrobj(L, str, l, LUA_TSHRSTR, h); - ts->hnext = *list; + ts->shrlen = cast_byte(l); + ts->u.hnext = *list; *list = ts; g->strt.nuse++; return ts; @@ -152,18 +182,32 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { if (l <= LUAI_MAXSHORTLEN) /* short string? */ return internshrstr(L, str, l); else { + TString *ts; if (l + 1 > (MAX_SIZE - sizeof(TString))/sizeof(char)) luaM_toobig(L); - return createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed); + ts = createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed); + ts->u.lnglen = l; + return ts; } } /* -** new zero-terminated string +** Create or reuse a zero-terminated string, first checking in the +** cache (using the string address as a key). The cache can contain +** only zero-terminated strings, so it is safe to use 'strcmp' to +** check hits. */ TString *luaS_new (lua_State *L, const char *str) { - return luaS_newlstr(L, str, strlen(str)); + unsigned int i = point2uint(str) % STRCACHE_SIZE; /* hash */ + TString **p = G(L)->strcache[i]; + if (strcmp(str, getstr(p[0])) == 0) /* hit? */ + return p[0]; /* that it is */ + else { /* normal route */ + TString *s = luaS_newlstr(L, str, strlen(str)); + p[0] = s; + return s; + } } |