rlm@1: /* rlm@1: ** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ rlm@1: ** String table (keeps all strings handled by Lua) rlm@1: ** See Copyright Notice in lua.h rlm@1: */ rlm@1: rlm@1: rlm@1: #include rlm@1: rlm@1: #define lstring_c rlm@1: #define LUA_CORE rlm@1: rlm@1: #include "lua.h" rlm@1: rlm@1: #include "lmem.h" rlm@1: #include "lobject.h" rlm@1: #include "lstate.h" rlm@1: #include "lstring.h" rlm@1: rlm@1: rlm@1: rlm@1: void luaS_resize (lua_State *L, int newsize) { rlm@1: GCObject **newhash; rlm@1: stringtable *tb; rlm@1: int i; rlm@1: if (G(L)->gcstate == GCSsweepstring) rlm@1: return; /* cannot resize during GC traverse */ rlm@1: newhash = luaM_newvector(L, newsize, GCObject *); rlm@1: tb = &G(L)->strt; rlm@1: for (i=0; isize; i++) { rlm@1: GCObject *p = tb->hash[i]; rlm@1: while (p) { /* for each node in the list */ rlm@1: GCObject *next = p->gch.next; /* save next */ rlm@1: unsigned int h = gco2ts(p)->hash; rlm@1: int h1 = lmod(h, newsize); /* new position */ rlm@1: lua_assert(cast_int(h%newsize) == lmod(h, newsize)); rlm@1: p->gch.next = newhash[h1]; /* chain it */ rlm@1: newhash[h1] = p; rlm@1: p = next; rlm@1: } rlm@1: } rlm@1: luaM_freearray(L, tb->hash, tb->size, TString *); rlm@1: tb->size = newsize; rlm@1: tb->hash = newhash; rlm@1: } rlm@1: rlm@1: rlm@1: static TString *newlstr (lua_State *L, const char *str, size_t l, rlm@1: unsigned int h) { rlm@1: TString *ts; rlm@1: stringtable *tb; rlm@1: if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) rlm@1: luaM_toobig(L); rlm@1: ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString))); rlm@1: ts->tsv.len = l; rlm@1: ts->tsv.hash = h; rlm@1: ts->tsv.marked = luaC_white(G(L)); rlm@1: ts->tsv.tt = LUA_TSTRING; rlm@1: ts->tsv.reserved = 0; rlm@1: memcpy(ts+1, str, l*sizeof(char)); rlm@1: ((char *)(ts+1))[l] = '\0'; /* ending 0 */ rlm@1: tb = &G(L)->strt; rlm@1: h = lmod(h, tb->size); rlm@1: ts->tsv.next = tb->hash[h]; /* chain new entry */ rlm@1: tb->hash[h] = obj2gco(ts); rlm@1: tb->nuse++; rlm@1: if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) rlm@1: luaS_resize(L, tb->size*2); /* too crowded */ rlm@1: return ts; rlm@1: } rlm@1: rlm@1: rlm@1: TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { rlm@1: GCObject *o; rlm@1: unsigned int h = cast(unsigned int, l); /* seed */ rlm@1: size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */ rlm@1: size_t l1; rlm@1: for (l1=l; l1>=step; l1-=step) /* compute hash */ rlm@1: h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1])); rlm@1: for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; rlm@1: o != NULL; rlm@1: o = o->gch.next) { rlm@1: TString *ts = rawgco2ts(o); rlm@1: if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) { rlm@1: /* string may be dead */ rlm@1: if (isdead(G(L), o)) changewhite(o); rlm@1: return ts; rlm@1: } rlm@1: } rlm@1: return newlstr(L, str, l, h); /* not found */ rlm@1: } rlm@1: rlm@1: rlm@1: Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { rlm@1: Udata *u; rlm@1: if (s > MAX_SIZET - sizeof(Udata)) rlm@1: luaM_toobig(L); rlm@1: u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata))); rlm@1: u->uv.marked = luaC_white(G(L)); /* is not finalized */ rlm@1: u->uv.tt = LUA_TUSERDATA; rlm@1: u->uv.len = s; rlm@1: u->uv.metatable = NULL; rlm@1: u->uv.env = e; rlm@1: /* chain it on udata list (after main thread) */ rlm@1: u->uv.next = G(L)->mainthread->next; rlm@1: G(L)->mainthread->next = obj2gco(u); rlm@1: return u; rlm@1: } rlm@1: