Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5205 | clevermous | 1 | /* |
2 | ** $Id: lstring.c,v 2.19 2011/05/03 16:01:57 roberto Exp $ |
||
3 | ** String table (keeps all strings handled by Lua) |
||
4 | ** See Copyright Notice in lua.h |
||
5 | */ |
||
6 | |||
7 | |||
8 | #include |
||
9 | |||
10 | #define lstring_c |
||
11 | #define LUA_CORE |
||
12 | |||
13 | #include "lua.h" |
||
14 | |||
15 | #include "lmem.h" |
||
16 | #include "lobject.h" |
||
17 | #include "lstate.h" |
||
18 | #include "lstring.h" |
||
19 | |||
20 | |||
21 | |||
22 | void luaS_resize (lua_State *L, int newsize) { |
||
23 | int i; |
||
24 | stringtable *tb = &G(L)->strt; |
||
25 | /* cannot resize while GC is traversing strings */ |
||
26 | luaC_runtilstate(L, ~bitmask(GCSsweepstring)); |
||
27 | if (newsize > tb->size) { |
||
28 | luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *); |
||
29 | for (i = tb->size; i < newsize; i++) tb->hash[i] = NULL; |
||
30 | } |
||
31 | /* rehash */ |
||
32 | for (i=0; i |
||
33 | GCObject *p = tb->hash[i]; |
||
34 | tb->hash[i] = NULL; |
||
35 | while (p) { /* for each node in the list */ |
||
36 | GCObject *next = gch(p)->next; /* save next */ |
||
37 | unsigned int h = lmod(gco2ts(p)->hash, newsize); /* new position */ |
||
38 | gch(p)->next = tb->hash[h]; /* chain it */ |
||
39 | tb->hash[h] = p; |
||
40 | resetoldbit(p); /* see MOVE OLD rule */ |
||
41 | p = next; |
||
42 | } |
||
43 | } |
||
44 | if (newsize < tb->size) { |
||
45 | /* shrinking slice must be empty */ |
||
46 | lua_assert(tb->hash[newsize] == NULL && tb->hash[tb->size - 1] == NULL); |
||
47 | luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *); |
||
48 | } |
||
49 | tb->size = newsize; |
||
50 | } |
||
51 | |||
52 | |||
53 | static TString *newlstr (lua_State *L, const char *str, size_t l, |
||
54 | unsigned int h) { |
||
55 | size_t totalsize; /* total size of TString object */ |
||
56 | GCObject **list; /* (pointer to) list where it will be inserted */ |
||
57 | TString *ts; |
||
58 | stringtable *tb = &G(L)->strt; |
||
59 | if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) |
||
60 | luaM_toobig(L); |
||
61 | if (tb->nuse >= cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) |
||
62 | luaS_resize(L, tb->size*2); /* too crowded */ |
||
63 | totalsize = sizeof(TString) + ((l + 1) * sizeof(char)); |
||
64 | list = &tb->hash[lmod(h, tb->size)]; |
||
65 | ts = &luaC_newobj(L, LUA_TSTRING, totalsize, list, 0)->ts; |
||
66 | ts->tsv.len = l; |
||
67 | ts->tsv.hash = h; |
||
68 | ts->tsv.reserved = 0; |
||
69 | memcpy(ts+1, str, l*sizeof(char)); |
||
70 | ((char *)(ts+1))[l] = '\0'; /* ending 0 */ |
||
71 | tb->nuse++; |
||
72 | return ts; |
||
73 | } |
||
74 | |||
75 | |||
76 | TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { |
||
77 | GCObject *o; |
||
78 | unsigned int h = cast(unsigned int, l); /* seed */ |
||
79 | size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */ |
||
80 | size_t l1; |
||
81 | for (l1=l; l1>=step; l1-=step) /* compute hash */ |
||
82 | h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1])); |
||
83 | for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; |
||
84 | o != NULL; |
||
85 | o = gch(o)->next) { |
||
86 | TString *ts = rawgco2ts(o); |
||
87 | if (h == ts->tsv.hash && |
||
88 | ts->tsv.len == l && |
||
89 | (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { |
||
90 | if (isdead(G(L), o)) /* string is dead (but was not collected yet)? */ |
||
91 | changewhite(o); /* resurrect it */ |
||
92 | return ts; |
||
93 | } |
||
94 | } |
||
95 | return newlstr(L, str, l, h); /* not found; create a new string */ |
||
96 | } |
||
97 | |||
98 | |||
99 | TString *luaS_new (lua_State *L, const char *str) { |
||
100 | return luaS_newlstr(L, str, strlen(str)); |
||
101 | } |
||
102 | |||
103 | |||
104 | Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { |
||
105 | Udata *u; |
||
106 | if (s > MAX_SIZET - sizeof(Udata)) |
||
107 | luaM_toobig(L); |
||
108 | u = &luaC_newobj(L, LUA_TUSERDATA, sizeof(Udata) + s, NULL, 0)->u; |
||
109 | u->uv.len = s; |
||
110 | u->uv.metatable = NULL; |
||
111 | u->uv.env = e; |
||
112 | return u; |
||
113 | }5)+(h><5)+(h>=>>> |
||
114 |