Coverage Report

Created: 2024-04-23 06:32

/src/testdir/build/lua-master/source/lstring.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
** $Id: lstring.c $
3
** String table (keeps all strings handled by Lua)
4
** See Copyright Notice in lua.h
5
*/
6
7
#define lstring_c
8
#define LUA_CORE
9
10
#include "lprefix.h"
11
12
13
#include <string.h>
14
15
#include "lua.h"
16
17
#include "ldebug.h"
18
#include "ldo.h"
19
#include "lmem.h"
20
#include "lobject.h"
21
#include "lstate.h"
22
#include "lstring.h"
23
24
25
/*
26
** Maximum size for string table.
27
*/
28
131
#define MAXSTRTB  cast_int(luaM_limitN(MAX_INT, TString*))
29
30
31
/*
32
** equality for long strings
33
*/
34
274k
int luaS_eqlngstr (TString *a, TString *b) {
35
274k
  size_t len = a->u.lnglen;
36
274k
  lua_assert(a->tt == LUA_VLNGSTR && b->tt == LUA_VLNGSTR);
37
274k
  return (a == b) ||  /* same instance or... */
38
274k
    ((len == b->u.lnglen) &&  /* equal length and ... */
39
113k
     (memcmp(getlngstr(a), getlngstr(b), len) == 0));  /* equal contents */
40
274k
}
41
42
43
27.0M
unsigned luaS_hash (const char *str, size_t l, unsigned seed) {
44
27.0M
  unsigned int h = seed ^ cast_uint(l);
45
95.5M
  for (; l > 0; l--)
46
68.4M
    h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1]));
47
27.0M
  return h;
48
27.0M
}
49
50
51
203k
unsigned luaS_hashlongstr (TString *ts) {
52
203k
  lua_assert(ts->tt == LUA_VLNGSTR);
53
203k
  if (ts->extra == 0) {  /* no hash? */
54
80.3k
    size_t len = ts->u.lnglen;
55
80.3k
    ts->hash = luaS_hash(getlngstr(ts), len, ts->hash);
56
0
    ts->extra = 1;  /* now it has its hash */
57
80.3k
  }
58
203k
  return ts->hash;
59
203k
}
60
61
62
692
static void tablerehash (TString **vect, int osize, int nsize) {
63
692
  int i;
64
92.8k
  for (i = osize; i < nsize; i++)  /* clear new elements */
65
92.1k
    vect[i] = NULL;
66
21.0k
  for (i = 0; i < osize; i++) {  /* rehash old part of the array */
67
20.3k
    TString *p = vect[i];
68
20.3k
    vect[i] = NULL;
69
40.7k
    while (p) {  /* for each string in the list */
70
20.3k
      TString *hnext = p->u.hnext;  /* save next */
71
20.3k
      unsigned int h = lmod(p->hash, nsize);  /* new position */
72
0
      p->u.hnext = vect[h];  /* chain it into array */
73
20.3k
      vect[h] = p;
74
20.3k
      p = hnext;
75
20.3k
    }
76
20.3k
  }
77
692
}
78
79
80
/*
81
** Resize the string table. If allocation fails, keep the current size.
82
** (This can degrade performance, but any non-zero size should work
83
** correctly.)
84
*/
85
131
void luaS_resize (lua_State *L, int nsize) {
86
131
  stringtable *tb = &G(L)->strt;
87
131
  int osize = tb->size;
88
131
  TString **newvect;
89
131
  if (nsize < osize)  /* shrinking table? */
90
0
    tablerehash(tb->hash, osize, nsize);  /* depopulate shrinking part */
91
131
  newvect = luaM_reallocvector(L, tb->hash, osize, nsize, TString*);
92
131
  if (l_unlikely(newvect == NULL)) {  /* reallocation failed? */
93
0
    if (nsize < osize)  /* was it shrinking table? */
94
0
      tablerehash(tb->hash, nsize, osize);  /* restore to original size */
95
    /* leave table as it was */
96
0
  }
97
131
  else {  /* allocation succeeded */
98
131
    tb->hash = newvect;
99
131
    tb->size = nsize;
100
131
    if (nsize > osize)
101
131
      tablerehash(newvect, osize, nsize);  /* rehash for new size */
102
131
  }
103
131
}
104
105
106
/*
107
** Clear API string cache. (Entries cannot be empty, so fill them with
108
** a non-collectable string.)
109
*/
110
4.74k
void luaS_clearcache (global_State *g) {
111
4.74k
  int i, j;
112
255k
  for (i = 0; i < STRCACHE_N; i++)
113
753k
    for (j = 0; j < STRCACHE_M; j++) {
114
502k
      if (iswhite(g->strcache[i][j]))  /* will entry be collected? */
115
120
        g->strcache[i][j] = g->memerrmsg;  /* replace it with something fixed */
116
502k
    }
117
4.74k
}
118
119
120
/*
121
** Initialize the string table and the string cache
122
*/
123
561
void luaS_init (lua_State *L) {
124
561
  global_State *g = G(L);
125
561
  int i, j;
126
561
  stringtable *tb = &G(L)->strt;
127
561
  tb->hash = luaM_newvector(L, MINSTRTABSIZE, TString*);
128
561
  tablerehash(tb->hash, 0, MINSTRTABSIZE);  /* clear array */
129
561
  tb->size = MINSTRTABSIZE;
130
  /* pre-create memory-error message */
131
561
  g->memerrmsg = luaS_newliteral(L, MEMERRMSG);
132
561
  luaC_fix(L, obj2gco(g->memerrmsg));  /* it should never be collected */
133
30.2k
  for (i = 0; i < STRCACHE_N; i++)  /* fill cache with valid strings */
134
89.1k
    for (j = 0; j < STRCACHE_M; j++)
135
59.4k
      g->strcache[i][j] = g->memerrmsg;
136
561
}
137
138
139
163k
size_t luaS_sizelngstr (size_t len, int kind) {
140
163k
  switch (kind) {
141
163k
    case LSTRREG:  /* regular long string */
142
      /* don't need 'falloc'/'ud', but need space for content */
143
163k
      return offsetof(TString, falloc) + (len + 1) * sizeof(char);
144
0
    case LSTRFIX:  /* fixed external long string */
145
      /* don't need 'falloc'/'ud' */
146
0
      return offsetof(TString, falloc);
147
90
    default:  /* external long string with deallocation */
148
90
      lua_assert(kind == LSTRMEM);
149
90
      return sizeof(TString);
150
163k
  }
151
163k
}
152
153
154
/*
155
** creates a new string object
156
*/
157
static TString *createstrobj (lua_State *L, size_t totalsize, int tag,
158
149k
                              unsigned h) {
159
149k
  TString *ts;
160
149k
  GCObject *o;
161
149k
  o = luaC_newobj(L, tag, totalsize);
162
149k
  ts = gco2ts(o);
163
0
  ts->hash = h;
164
149k
  ts->extra = 0;
165
149k
  return ts;
166
149k
}
167
168
169
81.8k
TString *luaS_createlngstrobj (lua_State *L, size_t l) {
170
81.8k
  size_t totalsize = luaS_sizelngstr(l, LSTRREG);
171
81.8k
  TString *ts = createstrobj(L, totalsize, LUA_VLNGSTR, G(L)->seed);
172
81.8k
  ts->u.lnglen = l;
173
81.8k
  ts->shrlen = LSTRREG;  /* signals that it is a regular long string */
174
81.8k
  ts->contents = cast_charp(ts) + offsetof(TString, falloc);
175
81.8k
  ts->contents[l] = '\0';  /* ending 0 */
176
81.8k
  return ts;
177
81.8k
}
178
179
180
67.6k
void luaS_remove (lua_State *L, TString *ts) {
181
67.6k
  stringtable *tb = &G(L)->strt;
182
67.6k
  TString **p = &tb->hash[lmod(ts->hash, tb->size)];
183
73.2k
  while (*p != ts)  /* find previous element */
184
5.60k
    p = &(*p)->u.hnext;
185
67.6k
  *p = (*p)->u.hnext;  /* remove element from its list */
186
67.6k
  tb->nuse--;
187
67.6k
}
188
189
190
131
static void growstrtab (lua_State *L, stringtable *tb) {
191
131
  if (l_unlikely(tb->nuse == MAX_INT)) {  /* too many strings? */
192
0
    luaC_fullgc(L, 1);  /* try to free some... */
193
0
    if (tb->nuse == MAX_INT)  /* still too many? */
194
0
      luaM_error(L);  /* cannot even create a message... */
195
0
  }
196
131
  if (tb->size <= MAXSTRTB / 2)  /* can grow string table? */
197
131
    luaS_resize(L, tb->size * 2);
198
131
}
199
200
201
/*
202
** Checks whether short string exists and reuses it or creates a new one.
203
*/
204
26.9M
static TString *internshrstr (lua_State *L, const char *str, size_t l) {
205
26.9M
  TString *ts;
206
26.9M
  global_State *g = G(L);
207
26.9M
  stringtable *tb = &g->strt;
208
26.9M
  unsigned int h = luaS_hash(str, l, g->seed);
209
26.9M
  TString **list = &tb->hash[lmod(h, tb->size)];
210
26.9M
  lua_assert(str != NULL);  /* otherwise 'memcmp'/'memcpy' are undefined */
211
34.7M
  for (ts = *list; ts != NULL; ts = ts->u.hnext) {
212
34.6M
    if (l == cast_uint(ts->shrlen) &&
213
34.6M
        (memcmp(str, getshrstr(ts), l * sizeof(char)) == 0)) {
214
      /* found! */
215
26.8M
      if (isdead(g, ts))  /* dead (but not collected yet)? */
216
191
        changewhite(ts);  /* resurrect it */
217
26.8M
      return ts;
218
26.8M
    }
219
34.6M
  }
220
  /* else must create a new string */
221
67.6k
  if (tb->nuse >= tb->size) {  /* need to grow string table? */
222
131
    growstrtab(L, tb);
223
131
    list = &tb->hash[lmod(h, tb->size)];  /* rehash with new size */
224
131
  }
225
67.6k
  ts = createstrobj(L, sizestrshr(l), LUA_VSHRSTR, h);
226
67.6k
  ts->shrlen = cast_byte(l);
227
67.6k
  getshrstr(ts)[l] = '\0';  /* ending 0 */
228
67.6k
  memcpy(getshrstr(ts), str, l * sizeof(char));
229
0
  ts->u.hnext = *list;
230
67.6k
  *list = ts;
231
67.6k
  tb->nuse++;
232
67.6k
  return ts;
233
67.6k
}
234
235
236
/*
237
** new string (with explicit length)
238
*/
239
27.0M
TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
240
27.0M
  if (l <= LUAI_MAXSHORTLEN)  /* short string? */
241
26.9M
    return internshrstr(L, str, l);
242
81.4k
  else {
243
81.4k
    TString *ts;
244
81.4k
    if (l_unlikely(l * sizeof(char) >= (MAX_SIZE - sizeof(TString))))
245
0
      luaM_toobig(L);
246
81.4k
    ts = luaS_createlngstrobj(L, l);
247
81.4k
    memcpy(getlngstr(ts), str, l * sizeof(char));
248
0
    return ts;
249
81.4k
  }
250
27.0M
}
251
252
253
/*
254
** Create or reuse a zero-terminated string, first checking in the
255
** cache (using the string address as a key). The cache can contain
256
** only zero-terminated strings, so it is safe to use 'strcmp' to
257
** check hits.
258
*/
259
27.5k
TString *luaS_new (lua_State *L, const char *str) {
260
27.5k
  unsigned int i = point2uint(str) % STRCACHE_N;  /* hash */
261
27.5k
  int j;
262
27.5k
  TString **p = G(L)->strcache[i];
263
82.3k
  for (j = 0; j < STRCACHE_M; j++) {
264
54.9k
    if (strcmp(str, getstr(p[j])) == 0)  /* hit? */
265
182
      return p[j];  /* that is it */
266
54.9k
  }
267
  /* normal route */
268
54.7k
  for (j = STRCACHE_M - 1; j > 0; j--)
269
27.3k
    p[j] = p[j - 1];  /* move out last element */
270
  /* new element is first in the list */
271
27.3k
  p[0] = luaS_newlstr(L, str, strlen(str));
272
27.3k
  return p[0];
273
27.5k
}
274
275
276
45
Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue) {
277
45
  Udata *u;
278
45
  int i;
279
45
  GCObject *o;
280
45
  if (l_unlikely(s > MAX_SIZE - udatamemoffset(nuvalue)))
281
0
    luaM_toobig(L);
282
45
  o = luaC_newobj(L, LUA_VUSERDATA, sizeudata(nuvalue, s));
283
45
  u = gco2u(o);
284
0
  u->len = s;
285
45
  u->nuvalue = nuvalue;
286
45
  u->metatable = NULL;
287
45
  for (i = 0; i < nuvalue; i++)
288
45
    setnilvalue(&u->uv[i].uv);
289
45
  return u;
290
45
}
291
292
293
struct NewExt {
294
  int kind;
295
  const char *s;
296
   size_t len;
297
  TString *ts;  /* output */
298
};
299
300
301
45
static void f_newext (lua_State *L, void *ud) {
302
45
  struct NewExt *ne = cast(struct NewExt *, ud);
303
45
  size_t size = luaS_sizelngstr(0, ne->kind);
304
45
  ne->ts = createstrobj(L, size, LUA_VLNGSTR, G(L)->seed);
305
45
}
306
307
308
0
static void f_pintern (lua_State *L, void *ud) {
309
0
  struct NewExt *ne = cast(struct NewExt *, ud);
310
0
  ne->ts = internshrstr(L, ne->s, ne->len);
311
0
}
312
313
314
TString *luaS_newextlstr (lua_State *L,
315
45
            const char *s, size_t len, lua_Alloc falloc, void *ud) {
316
45
  struct NewExt ne;
317
45
  if (len <= LUAI_MAXSHORTLEN) {  /* short string? */
318
0
    ne.s = s; ne.len = len;
319
0
    if (!falloc)
320
0
      f_pintern(L, &ne);  /* just internalize string */
321
0
    else {
322
0
      int status = luaD_rawrunprotected(L, f_pintern, &ne);
323
0
      (*falloc)(ud, cast_voidp(s), len + 1, 0);  /* free external string */
324
0
      if (status != LUA_OK)  /* memory error? */
325
0
        luaM_error(L);  /* re-raise memory error */
326
0
    }
327
0
    return ne.ts;
328
0
  }
329
  /* "normal" case: long strings */
330
45
  if (!falloc) {
331
0
    ne.kind = LSTRFIX;
332
0
    f_newext(L, &ne);  /* just create header */
333
0
  }
334
45
  else {
335
45
    ne.kind = LSTRMEM;
336
45
    if (luaD_rawrunprotected(L, f_newext, &ne) != LUA_OK) {  /* mem. error? */
337
0
      (*falloc)(ud, cast_voidp(s), len + 1, 0);  /* free external string */
338
0
      luaM_error(L);  /* re-raise memory error */
339
0
    }
340
45
    ne.ts->falloc = falloc;
341
45
    ne.ts->ud = ud;
342
45
  }
343
45
  ne.ts->shrlen = ne.kind;
344
45
  ne.ts->u.lnglen = len;
345
45
  ne.ts->contents = cast_charp(s);
346
45
  return ne.ts;
347
45
}
348
349