diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2023-11-09 17:05:42 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2023-11-09 17:05:42 -0300 |
commit | 024f9064f1b43758eb36aba52547edc0312bf4ba (patch) | |
tree | 9d8609112058e885196a581f0736fbdd94f7f94d /lstring.c | |
parent | 7f4906f565ab9f8b1125107a3abae3d759f3ecf2 (diff) | |
download | lua-024f9064f1b43758eb36aba52547edc0312bf4ba.tar.gz lua-024f9064f1b43758eb36aba52547edc0312bf4ba.tar.bz2 lua-024f9064f1b43758eb36aba52547edc0312bf4ba.zip |
External strings
Strings can use external buffers to store their contents.
Diffstat (limited to 'lstring.c')
-rw-r--r-- | lstring.c | 78 |
1 files changed, 75 insertions, 3 deletions
@@ -136,6 +136,20 @@ void luaS_init (lua_State *L) { | |||
136 | } | 136 | } |
137 | 137 | ||
138 | 138 | ||
139 | size_t luaS_sizelngstr (size_t len, int kind) { | ||
140 | switch (kind) { | ||
141 | case LSTRREG: /* regular long string */ | ||
142 | /* don't need 'falloc'/'ud', but need space for content */ | ||
143 | return offsetof(TString, falloc) + (len + 1) * sizeof(char); | ||
144 | case LSTRFIX: /* fixed external long string */ | ||
145 | /* don't need 'falloc'/'ud' */ | ||
146 | return offsetof(TString, falloc); | ||
147 | default: /* external long string with deallocation */ | ||
148 | lua_assert(kind == LSTRMEM); | ||
149 | return sizeof(TString); | ||
150 | } | ||
151 | } | ||
152 | |||
139 | 153 | ||
140 | /* | 154 | /* |
141 | ** creates a new string object | 155 | ** creates a new string object |
@@ -153,11 +167,11 @@ static TString *createstrobj (lua_State *L, size_t totalsize, int tag, | |||
153 | 167 | ||
154 | 168 | ||
155 | TString *luaS_createlngstrobj (lua_State *L, size_t l) { | 169 | TString *luaS_createlngstrobj (lua_State *L, size_t l) { |
156 | size_t totalsize = sizestrlng(l); | 170 | size_t totalsize = luaS_sizelngstr(l, LSTRREG); |
157 | TString *ts = createstrobj(L, totalsize, LUA_VLNGSTR, G(L)->seed); | 171 | TString *ts = createstrobj(L, totalsize, LUA_VLNGSTR, G(L)->seed); |
158 | ts->u.lnglen = l; | 172 | ts->u.lnglen = l; |
159 | ts->shrlen = -1; /* signals that it is a long string */ | 173 | ts->shrlen = LSTRREG; /* signals that it is a regular long string */ |
160 | ts->contents = cast_charp(ts) + sizeof(TString); | 174 | ts->contents = cast_charp(ts) + offsetof(TString, falloc); |
161 | ts->contents[l] = '\0'; /* ending 0 */ | 175 | ts->contents[l] = '\0'; /* ending 0 */ |
162 | return ts; | 176 | return ts; |
163 | } | 177 | } |
@@ -275,3 +289,61 @@ Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue) { | |||
275 | return u; | 289 | return u; |
276 | } | 290 | } |
277 | 291 | ||
292 | |||
293 | struct NewExt { | ||
294 | int kind; | ||
295 | const char *s; | ||
296 | size_t len; | ||
297 | TString *ts; /* output */ | ||
298 | }; | ||
299 | |||
300 | |||
301 | static void f_newext (lua_State *L, void *ud) { | ||
302 | struct NewExt *ne = cast(struct NewExt *, ud); | ||
303 | size_t size = luaS_sizelngstr(0, ne->kind); | ||
304 | ne->ts = createstrobj(L, size, LUA_VLNGSTR, G(L)->seed); | ||
305 | } | ||
306 | |||
307 | |||
308 | static void f_pintern (lua_State *L, void *ud) { | ||
309 | struct NewExt *ne = cast(struct NewExt *, ud); | ||
310 | ne->ts = internshrstr(L, ne->s, ne->len); | ||
311 | } | ||
312 | |||
313 | |||
314 | TString *luaS_newextlstr (lua_State *L, | ||
315 | const char *s, size_t len, lua_Alloc falloc, void *ud) { | ||
316 | struct NewExt ne; | ||
317 | if (len <= LUAI_MAXSHORTLEN) { /* short string? */ | ||
318 | ne.s = s; ne.len = len; | ||
319 | if (!falloc) | ||
320 | f_pintern(L, &ne); /* just internalize string */ | ||
321 | else { | ||
322 | int status = luaD_rawrunprotected(L, f_pintern, &ne); | ||
323 | (*falloc)(ud, cast_voidp(s), len + 1, 0); /* free external string */ | ||
324 | if (status != LUA_OK) /* memory error? */ | ||
325 | luaM_error(L); /* re-raise memory error */ | ||
326 | } | ||
327 | return ne.ts; | ||
328 | } | ||
329 | /* "normal" case: long strings */ | ||
330 | if (!falloc) { | ||
331 | ne.kind = LSTRFIX; | ||
332 | f_newext(L, &ne); /* just create header */ | ||
333 | } | ||
334 | else { | ||
335 | ne.kind = LSTRMEM; | ||
336 | if (luaD_rawrunprotected(L, f_newext, &ne) != LUA_OK) { /* mem. error? */ | ||
337 | (*falloc)(ud, cast_voidp(s), len + 1, 0); /* free external string */ | ||
338 | luaM_error(L); /* re-raise memory error */ | ||
339 | } | ||
340 | ne.ts->falloc = falloc; | ||
341 | ne.ts->ud = ud; | ||
342 | } | ||
343 | ne.ts->shrlen = ne.kind; | ||
344 | ne.ts->u.lnglen = len; | ||
345 | ne.ts->contents = cast_charp(s); | ||
346 | return ne.ts; | ||
347 | } | ||
348 | |||
349 | |||