diff options
Diffstat (limited to 'plugins/MirLua/src/lua/lstring.c')
| -rw-r--r-- | plugins/MirLua/src/lua/lstring.c | 182 | 
1 files changed, 182 insertions, 0 deletions
diff --git a/plugins/MirLua/src/lua/lstring.c b/plugins/MirLua/src/lua/lstring.c new file mode 100644 index 0000000000..2947113c3c --- /dev/null +++ b/plugins/MirLua/src/lua/lstring.c @@ -0,0 +1,182 @@ +/* +** $Id: lstring.c,v 2.45 2014/11/02 19:19:04 roberto Exp $ +** String table (keeps all strings handled by Lua) +** See Copyright Notice in lua.h +*/ + +#define lstring_c +#define LUA_CORE + +#include "lprefix.h" + + +#include <string.h> + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" + + + +/* +** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to +** compute its hash +*/ +#if !defined(LUAI_HASHLIMIT) +#define LUAI_HASHLIMIT		5 +#endif + + +/* +** equality for long strings +*/ +int luaS_eqlngstr (TString *a, TString *b) { +  size_t len = a->len; +  lua_assert(a->tt == LUA_TLNGSTR && b->tt == LUA_TLNGSTR); +  return (a == b) ||  /* same instance or... */ +    ((len == b->len) &&  /* equal length and ... */ +     (memcmp(getstr(a), getstr(b), len) == 0));  /* equal contents */ +} + + +unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) { +  unsigned int h = seed ^ cast(unsigned int, l); +  size_t l1; +  size_t step = (l >> LUAI_HASHLIMIT) + 1; +  for (l1 = l; l1 >= step; l1 -= step) +    h = h ^ ((h<<5) + (h>>2) + cast_byte(str[l1 - 1])); +  return h; +} + + +/* +** resizes the string table +*/ +void luaS_resize (lua_State *L, int newsize) { +  int i; +  stringtable *tb = &G(L)->strt; +  if (newsize > tb->size) {  /* grow table if needed */ +    luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *); +    for (i = tb->size; i < newsize; i++) +      tb->hash[i] = NULL; +  } +  for (i = 0; i < tb->size; i++) {  /* rehash */ +    TString *p = tb->hash[i]; +    tb->hash[i] = NULL; +    while (p) {  /* for each node in the list */ +      TString *hnext = p->hnext;  /* save next */ +      unsigned int h = lmod(p->hash, newsize);  /* new position */ +      p->hnext = tb->hash[h];  /* chain it */ +      tb->hash[h] = p; +      p = hnext; +    } +  } +  if (newsize < tb->size) {  /* shrink table if needed */ +    /* vanishing slice should be empty */ +    lua_assert(tb->hash[newsize] == NULL && tb->hash[tb->size - 1] == NULL); +    luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *); +  } +  tb->size = newsize; +} + + + +/* +** creates a new string object +*/ +static TString *createstrobj (lua_State *L, const char *str, size_t l, +                              int tag, unsigned int h) { +  TString *ts; +  GCObject *o; +  size_t totalsize;  /* total size of TString object */ +  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)); +  getaddrstr(ts)[l] = '\0';  /* ending 0 */ +  return ts; +} + + +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 */ +  tb->nuse--; +} + + +/* +** checks whether short string exists and reuses it or creates a new one +*/ +static TString *internshrstr (lua_State *L, const char *str, size_t l) { +  TString *ts; +  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 && +        (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { +      /* found! */ +      if (isdead(g, ts))  /* dead (but not collected yet)? */ +        changewhite(ts);  /* resurrect it */ +      return ts; +    } +  } +  if (g->strt.nuse >= g->strt.size && g->strt.size <= MAX_INT/2) { +    luaS_resize(L, g->strt.size * 2); +    list = &g->strt.hash[lmod(h, g->strt.size)];  /* recompute with new size */ +  } +  ts = createstrobj(L, str, l, LUA_TSHRSTR, h); +  ts->hnext = *list; +  *list = ts; +  g->strt.nuse++; +  return ts; +} + + +/* +** new string (with explicit length) +*/ +TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { +  if (l <= LUAI_MAXSHORTLEN)  /* short string? */ +    return internshrstr(L, str, l); +  else { +    if (l + 1 > (MAX_SIZE - sizeof(TString))/sizeof(char)) +      luaM_toobig(L); +    return createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed); +  } +} + + +/* +** new zero-terminated string +*/ +TString *luaS_new (lua_State *L, const char *str) { +  return luaS_newlstr(L, str, strlen(str)); +} + + +Udata *luaS_newudata (lua_State *L, size_t s) { +  Udata *u; +  GCObject *o; +  if (s > MAX_SIZE - sizeof(Udata)) +    luaM_toobig(L); +  o = luaC_newobj(L, LUA_TUSERDATA, sizeludata(s)); +  u = gco2u(o); +  u->len = s; +  u->metatable = NULL; +  setuservalue(L, u, luaO_nilobject); +  return u; +} +  | 
