diff options
Diffstat (limited to 'src/lib_buffer.c')
-rw-r--r-- | src/lib_buffer.c | 60 |
1 files changed, 42 insertions, 18 deletions
diff --git a/src/lib_buffer.c b/src/lib_buffer.c index 78c4eeb9..f13320c4 100644 --- a/src/lib_buffer.c +++ b/src/lib_buffer.c | |||
@@ -29,9 +29,7 @@ | |||
29 | #include "lj_serialize.h" | 29 | #include "lj_serialize.h" |
30 | #include "lj_lib.h" | 30 | #include "lj_lib.h" |
31 | 31 | ||
32 | /* ------------------------------------------------------------------------ */ | 32 | /* -- Helper functions ---------------------------------------------------- */ |
33 | |||
34 | #define LJLIB_MODULE_buffer_method | ||
35 | 33 | ||
36 | /* Check that the first argument is a string buffer. */ | 34 | /* Check that the first argument is a string buffer. */ |
37 | static SBufExt *buffer_tobuf(lua_State *L) | 35 | static SBufExt *buffer_tobuf(lua_State *L) |
@@ -49,11 +47,16 @@ static LJ_AINLINE SBufExt *buffer_tobufw(lua_State *L) | |||
49 | return sbx; | 47 | return sbx; |
50 | } | 48 | } |
51 | 49 | ||
50 | #define buffer_toudata(sbx) ((GCudata *)(sbx)-1) | ||
51 | |||
52 | /* -- Buffer methods ------------------------------------------------------ */ | ||
53 | |||
54 | #define LJLIB_MODULE_buffer_method | ||
55 | |||
52 | LJLIB_CF(buffer_method_free) | 56 | LJLIB_CF(buffer_method_free) |
53 | { | 57 | { |
54 | SBufExt *sbx = buffer_tobuf(L); | 58 | SBufExt *sbx = buffer_tobuf(L); |
55 | lj_bufx_free(G(L), sbx); | 59 | lj_bufx_free(L, sbx); |
56 | lj_bufx_init(L, sbx); | ||
57 | L->top = L->base+1; /* Chain buffer object. */ | 60 | L->top = L->base+1; /* Chain buffer object. */ |
58 | return 1; | 61 | return 1; |
59 | } | 62 | } |
@@ -83,6 +86,7 @@ LJLIB_CF(buffer_method_skip) | |||
83 | LJLIB_CF(buffer_method_set) | 86 | LJLIB_CF(buffer_method_set) |
84 | { | 87 | { |
85 | SBufExt *sbx = buffer_tobuf(L); | 88 | SBufExt *sbx = buffer_tobuf(L); |
89 | GCobj *ref; | ||
86 | const char *p; | 90 | const char *p; |
87 | MSize len; | 91 | MSize len; |
88 | #if LJ_HASFFI | 92 | #if LJ_HASFFI |
@@ -98,9 +102,11 @@ LJLIB_CF(buffer_method_set) | |||
98 | p = strdata(str); | 102 | p = strdata(str); |
99 | len = str->len; | 103 | len = str->len; |
100 | } | 104 | } |
101 | lj_bufx_free(G(L), sbx); | 105 | lj_bufx_free(L, sbx); |
102 | lj_bufx_init_cow(L, sbx, p, len); | 106 | lj_bufx_set_cow(L, sbx, p, len); |
103 | setgcref(sbx->cowref, gcV(L->base+1)); | 107 | ref = gcV(L->base+1); |
108 | setgcref(sbx->cowref, ref); | ||
109 | lj_gc_objbarrier(L, buffer_toudata(sbx), ref); | ||
104 | L->top = L->base+1; /* Chain buffer object. */ | 110 | L->top = L->base+1; /* Chain buffer object. */ |
105 | return 1; | 111 | return 1; |
106 | } | 112 | } |
@@ -249,8 +255,7 @@ LJLIB_CF(buffer_method_decode) | |||
249 | LJLIB_CF(buffer_method___gc) | 255 | LJLIB_CF(buffer_method___gc) |
250 | { | 256 | { |
251 | SBufExt *sbx = buffer_tobuf(L); | 257 | SBufExt *sbx = buffer_tobuf(L); |
252 | lj_bufx_free(G(L), sbx); | 258 | lj_bufx_free(L, sbx); |
253 | lj_bufx_init(L, sbx); | ||
254 | return 0; | 259 | return 0; |
255 | } | 260 | } |
256 | 261 | ||
@@ -272,7 +277,7 @@ LJLIB_CF(buffer_method___len) | |||
272 | LJLIB_PUSH("buffer") LJLIB_SET(__metatable) | 277 | LJLIB_PUSH("buffer") LJLIB_SET(__metatable) |
273 | LJLIB_PUSH(top-1) LJLIB_SET(__index) | 278 | LJLIB_PUSH(top-1) LJLIB_SET(__index) |
274 | 279 | ||
275 | /* ------------------------------------------------------------------------ */ | 280 | /* -- Buffer library functions -------------------------------------------- */ |
276 | 281 | ||
277 | #define LJLIB_MODULE_buffer | 282 | #define LJLIB_MODULE_buffer |
278 | 283 | ||
@@ -280,16 +285,33 @@ LJLIB_PUSH(top-2) LJLIB_SET(!) /* Set environment. */ | |||
280 | 285 | ||
281 | LJLIB_CF(buffer_new) | 286 | LJLIB_CF(buffer_new) |
282 | { | 287 | { |
283 | MSize sz = L->base == L->top ? 0u : | 288 | MSize sz = 0; |
284 | (MSize)lj_lib_checkintrange(L, 1, 0, LJ_MAX_BUF); | 289 | int targ = 1; |
285 | GCtab *env = tabref(curr_func(L)->c.env); | 290 | GCtab *env, *dict = NULL; |
286 | GCudata *ud = lj_udata_new(L, sizeof(SBufExt), env); | 291 | GCudata *ud; |
287 | SBufExt *sbx = (SBufExt *)uddata(ud); | 292 | SBufExt *sbx; |
293 | if (L->base < L->top && !tvistab(L->base)) { | ||
294 | targ = 2; | ||
295 | if (!tvisnil(L->base)) | ||
296 | sz = (MSize)lj_lib_checkintrange(L, 1, 0, LJ_MAX_BUF); | ||
297 | } | ||
298 | if (L->base+targ-1 < L->top) { | ||
299 | GCtab *options = lj_lib_checktab(L, targ); | ||
300 | cTValue *opt_dict = lj_tab_getstr(options, lj_str_newlit(L, "dict")); | ||
301 | if (opt_dict && tvistab(opt_dict)) { | ||
302 | dict = tabV(opt_dict); | ||
303 | lj_serialize_dict_prep(L, dict); | ||
304 | } | ||
305 | } | ||
306 | env = tabref(curr_func(L)->c.env); | ||
307 | ud = lj_udata_new(L, sizeof(SBufExt), env); | ||
288 | ud->udtype = UDTYPE_BUFFER; | 308 | ud->udtype = UDTYPE_BUFFER; |
289 | /* NOBARRIER: The GCudata is new (marked white). */ | 309 | /* NOBARRIER: The GCudata is new (marked white). */ |
290 | setgcref(ud->metatable, obj2gco(env)); | 310 | setgcref(ud->metatable, obj2gco(env)); |
291 | setudataV(L, L->top++, ud); | 311 | setudataV(L, L->top++, ud); |
312 | sbx = (SBufExt *)uddata(ud); | ||
292 | lj_bufx_init(L, sbx); | 313 | lj_bufx_init(L, sbx); |
314 | setgcref(sbx->dict, obj2gco(dict)); | ||
293 | if (sz > 0) lj_buf_need2((SBuf *)sbx, sz); | 315 | if (sz > 0) lj_buf_need2((SBuf *)sbx, sz); |
294 | return 1; | 316 | return 1; |
295 | } | 317 | } |
@@ -298,7 +320,8 @@ LJLIB_CF(buffer_encode) | |||
298 | { | 320 | { |
299 | cTValue *o = lj_lib_checkany(L, 1); | 321 | cTValue *o = lj_lib_checkany(L, 1); |
300 | SBufExt sbx; | 322 | SBufExt sbx; |
301 | lj_bufx_init_borrow(L, &sbx, &G(L)->tmpbuf); | 323 | memset(&sbx, 0, sizeof(SBufExt)); |
324 | lj_bufx_set_borrow(L, &sbx, &G(L)->tmpbuf); | ||
302 | lj_serialize_put(&sbx, o); | 325 | lj_serialize_put(&sbx, o); |
303 | setstrV(L, L->top++, lj_buf_str(L, (SBuf *)&sbx)); | 326 | setstrV(L, L->top++, lj_buf_str(L, (SBuf *)&sbx)); |
304 | lj_gc_check(L); | 327 | lj_gc_check(L); |
@@ -309,7 +332,8 @@ LJLIB_CF(buffer_decode) | |||
309 | { | 332 | { |
310 | GCstr *str = lj_lib_checkstrx(L, 1); | 333 | GCstr *str = lj_lib_checkstrx(L, 1); |
311 | SBufExt sbx; | 334 | SBufExt sbx; |
312 | lj_bufx_init_cow(L, &sbx, strdata(str), str->len); | 335 | memset(&sbx, 0, sizeof(SBufExt)); |
336 | lj_bufx_set_cow(L, &sbx, strdata(str), str->len); | ||
313 | /* No need to set sbx.cowref here. */ | 337 | /* No need to set sbx.cowref here. */ |
314 | setnilV(L->top++); | 338 | setnilV(L->top++); |
315 | lj_serialize_get(&sbx, L->top-1); | 339 | lj_serialize_get(&sbx, L->top-1); |