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 | |||
