diff options
Diffstat (limited to 'lstring.c')
-rw-r--r-- | lstring.c | 111 |
1 files changed, 35 insertions, 76 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstring.c,v 1.34 2000/03/10 18:37:44 roberto Exp roberto $ | 2 | ** $Id: lstring.c,v 1.35 2000/05/08 19:32:53 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 | */ |
@@ -17,30 +17,20 @@ | |||
17 | 17 | ||
18 | 18 | ||
19 | 19 | ||
20 | #define gcsizestring(L, l) numblocks(L, 0, sizeof(TString)+l) | ||
21 | #define gcsizeudata gcsizestring(L, 0) | ||
22 | |||
23 | |||
24 | |||
25 | void luaS_init (lua_State *L) { | 20 | void luaS_init (lua_State *L) { |
26 | int i; | 21 | L->strt.size = L->udt.size = 1; |
27 | L->string_root = luaM_newvector(L, NUM_HASHS, stringtable); | 22 | L->strt.nuse = L->udt.nuse = 0; |
28 | for (i=0; i<NUM_HASHS; i++) { | 23 | L->strt.hash = luaM_newvector(L, 1, TString *); |
29 | L->string_root[i].size = 1; | 24 | L->udt.hash = luaM_newvector(L, 1, TString *); |
30 | L->string_root[i].nuse = 0; | 25 | L->strt.hash[0] = L->udt.hash[0] = NULL; |
31 | L->string_root[i].hash = luaM_newvector(L, 1, TString *);; | ||
32 | L->string_root[i].hash[0] = NULL; | ||
33 | } | ||
34 | } | 26 | } |
35 | 27 | ||
36 | 28 | ||
37 | void luaS_freeall (lua_State *L) { | 29 | void luaS_freeall (lua_State *L) { |
38 | int i; | 30 | LUA_ASSERT(L, L->strt.nuse==0, "non-empty string table"); |
39 | for (i=0; i<NUM_HASHS; i++) { | 31 | luaM_free(L, L->strt.hash); |
40 | LUA_ASSERT(L, L->string_root[i].nuse==0, "non-empty string table"); | 32 | LUA_ASSERT(L, L->udt.nuse==0, "non-empty udata table"); |
41 | luaM_free(L, L->string_root[i].hash); | 33 | luaM_free(L, L->udt.hash); |
42 | } | ||
43 | luaM_free(L, L->string_root); | ||
44 | } | 34 | } |
45 | 35 | ||
46 | 36 | ||
@@ -62,8 +52,7 @@ void luaS_resize (lua_State *L, stringtable *tb, int newsize) { | |||
62 | TString *p = tb->hash[i]; | 52 | TString *p = tb->hash[i]; |
63 | while (p) { /* for each node in the list */ | 53 | while (p) { /* for each node in the list */ |
64 | TString *next = p->nexthash; /* save next */ | 54 | TString *next = p->nexthash; /* save next */ |
65 | unsigned long h = (p->constindex == -1) ? IntPoint(p->u.d.value) : | 55 | unsigned long h = (tb == &L->strt) ? p->u.s.hash : IntPoint(p->u.d.value); |
66 | p->u.s.hash; | ||
67 | int h1 = h&(newsize-1); /* new position */ | 56 | int h1 = h&(newsize-1); /* new position */ |
68 | LUA_ASSERT(L, h%newsize == (h&(newsize-1)), | 57 | LUA_ASSERT(L, h%newsize == (h&(newsize-1)), |
69 | "a&(x-1) == a%x, for x power of 2"); | 58 | "a&(x-1) == a%x, for x power of 2"); |
@@ -78,79 +67,55 @@ void luaS_resize (lua_State *L, stringtable *tb, int newsize) { | |||
78 | } | 67 | } |
79 | 68 | ||
80 | 69 | ||
81 | static TString *newone (lua_State *L, long l) { | ||
82 | TString *ts = (TString *)luaM_malloc(L, sizeof(TString)+l*sizeof(char)); | ||
83 | ts->marked = 0; | ||
84 | ts->nexthash = NULL; | ||
85 | return ts; | ||
86 | } | ||
87 | |||
88 | |||
89 | static TString *newone_s (lua_State *L, const char *str, | ||
90 | long l, unsigned long h) { | ||
91 | TString *ts = newone(L, l); | ||
92 | memcpy(ts->str, str, l); | ||
93 | ts->str[l] = 0; /* ending 0 */ | ||
94 | ts->u.s.len = l; | ||
95 | ts->u.s.hash = h; | ||
96 | ts->constindex = 0; | ||
97 | L->nblocks += gcsizestring(L, l); | ||
98 | return ts; | ||
99 | } | ||
100 | |||
101 | |||
102 | static TString *newone_u (lua_State *L, void *buff, int tag) { | ||
103 | TString *ts = newone(L, 0); | ||
104 | ts->u.d.value = buff; | ||
105 | ts->u.d.tag = (tag == LUA_ANYTAG) ? 0 : tag; | ||
106 | ts->constindex = -1; /* tag -> this is a userdata */ | ||
107 | L->nblocks += gcsizeudata; | ||
108 | return ts; | ||
109 | } | ||
110 | |||
111 | |||
112 | static void newentry (lua_State *L, stringtable *tb, TString *ts, int h) { | 70 | static void newentry (lua_State *L, stringtable *tb, TString *ts, int h) { |
113 | ts->nexthash = tb->hash[h]; /* chain new entry */ | 71 | ts->nexthash = tb->hash[h]; /* chain new entry */ |
114 | tb->hash[h] = ts; | 72 | tb->hash[h] = ts; |
115 | tb->nuse++; | 73 | tb->nuse++; |
116 | if (tb->nuse > tb->size) /* too crowded? */ | 74 | if (tb->nuse > tb->size && tb->size < MAX_INT/2) /* too crowded? */ |
117 | luaS_resize(L, tb, tb->size*2); | 75 | luaS_resize(L, tb, tb->size*2); |
118 | } | 76 | } |
119 | 77 | ||
120 | 78 | ||
79 | |||
121 | TString *luaS_newlstr (lua_State *L, const char *str, long l) { | 80 | TString *luaS_newlstr (lua_State *L, const char *str, long l) { |
122 | unsigned long h = hash_s(str, l); | 81 | unsigned long h = hash_s(str, l); |
123 | stringtable *tb = &L->string_root[(l==0) ? 0 : | 82 | int h1 = h&(L->strt.size-1); |
124 | ((unsigned int)(str[0]+str[l-1]))&(NUM_HASHSTR-1)]; | ||
125 | int h1 = h&(tb->size-1); | ||
126 | TString *ts; | 83 | TString *ts; |
127 | for (ts = tb->hash[h1]; ts; ts = ts->nexthash) { | 84 | for (ts = L->strt.hash[h1]; ts; ts = ts->nexthash) { |
128 | if (ts->u.s.len == l && (memcmp(str, ts->str, l) == 0)) | 85 | if (ts->u.s.len == l && (memcmp(str, ts->str, l) == 0)) |
129 | return ts; | 86 | return ts; |
130 | } | 87 | } |
131 | /* not found */ | 88 | /* not found */ |
132 | ts = newone_s(L, str, l, h); /* create new entry */ | 89 | ts = (TString *)luaM_malloc(L, sizeof(TString)+l*sizeof(char)); |
133 | newentry(L, tb, ts, h1); /* insert it on table */ | 90 | ts->marked = 0; |
91 | ts->nexthash = NULL; | ||
92 | ts->u.s.len = l; | ||
93 | ts->u.s.hash = h; | ||
94 | ts->u.s.constindex = 0; | ||
95 | memcpy(ts->str, str, l); | ||
96 | ts->str[l] = 0; /* ending 0 */ | ||
97 | L->nblocks += gcsizestring(L, l); | ||
98 | newentry(L, &L->strt, ts, h1); /* insert it on table */ | ||
134 | return ts; | 99 | return ts; |
135 | } | 100 | } |
136 | 101 | ||
137 | 102 | ||
138 | /* | ||
139 | ** uses '%' for one hashing with userdata because addresses are too regular, | ||
140 | ** so two '&' operations would be highly correlated | ||
141 | */ | ||
142 | TString *luaS_createudata (lua_State *L, void *udata, int tag) { | 103 | TString *luaS_createudata (lua_State *L, void *udata, int tag) { |
143 | unsigned long h = IntPoint(udata); | 104 | unsigned long h = IntPoint(udata); |
144 | stringtable *tb = &L->string_root[(h%NUM_HASHUDATA)+NUM_HASHSTR]; | 105 | int h1 = h&(L->udt.size-1); |
145 | int h1 = h&(tb->size-1); | ||
146 | TString *ts; | 106 | TString *ts; |
147 | for (ts = tb->hash[h1]; ts; ts = ts->nexthash) { | 107 | for (ts = L->udt.hash[h1]; ts; ts = ts->nexthash) { |
148 | if (udata == ts->u.d.value && (tag == ts->u.d.tag || tag == LUA_ANYTAG)) | 108 | if (udata == ts->u.d.value && (tag == ts->u.d.tag || tag == LUA_ANYTAG)) |
149 | return ts; | 109 | return ts; |
150 | } | 110 | } |
151 | /* not found */ | 111 | /* not found */ |
152 | ts = newone_u(L, udata, tag); | 112 | ts = luaM_new(L, TString); |
153 | newentry(L, tb, ts, h1); | 113 | ts->marked = 0; |
114 | ts->nexthash = NULL; | ||
115 | ts->u.d.value = udata; | ||
116 | ts->u.d.tag = (tag == LUA_ANYTAG) ? 0 : tag; | ||
117 | L->nblocks += gcsizeudata; | ||
118 | newentry(L, &L->udt, ts, h1); /* insert it on table */ | ||
154 | return ts; | 119 | return ts; |
155 | } | 120 | } |
156 | 121 | ||
@@ -159,16 +124,10 @@ TString *luaS_new (lua_State *L, const char *str) { | |||
159 | return luaS_newlstr(L, str, strlen(str)); | 124 | return luaS_newlstr(L, str, strlen(str)); |
160 | } | 125 | } |
161 | 126 | ||
127 | |||
162 | TString *luaS_newfixed (lua_State *L, const char *str) { | 128 | TString *luaS_newfixed (lua_State *L, const char *str) { |
163 | TString *ts = luaS_new(L, str); | 129 | TString *ts = luaS_new(L, str); |
164 | if (ts->marked == 0) ts->marked = FIXMARK; /* avoid GC */ | 130 | if (ts->marked == 0) ts->marked = FIXMARK; /* avoid GC */ |
165 | return ts; | 131 | return ts; |
166 | } | 132 | } |
167 | 133 | ||
168 | |||
169 | void luaS_free (lua_State *L, TString *t) { | ||
170 | L->nblocks -= (t->constindex == -1) ? gcsizeudata : | ||
171 | gcsizestring(L, t->u.s.len); | ||
172 | luaM_free(L, t); | ||
173 | } | ||
174 | |||