Mercurial
comparison third_party/luajit/src/lib_buffer.c @ 178:94705b5986b3
[ThirdParty] Added WRK and luajit for load testing.
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Thu, 22 Jan 2026 20:10:30 -0800 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 177:24fe8ff94056 | 178:94705b5986b3 |
|---|---|
| 1 /* | |
| 2 ** Buffer library. | |
| 3 ** Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h | |
| 4 */ | |
| 5 | |
| 6 #define lib_buffer_c | |
| 7 #define LUA_LIB | |
| 8 | |
| 9 #include "lua.h" | |
| 10 #include "lauxlib.h" | |
| 11 #include "lualib.h" | |
| 12 | |
| 13 #include "lj_obj.h" | |
| 14 | |
| 15 #if LJ_HASBUFFER | |
| 16 #include "lj_gc.h" | |
| 17 #include "lj_err.h" | |
| 18 #include "lj_buf.h" | |
| 19 #include "lj_str.h" | |
| 20 #include "lj_tab.h" | |
| 21 #include "lj_udata.h" | |
| 22 #include "lj_meta.h" | |
| 23 #if LJ_HASFFI | |
| 24 #include "lj_ctype.h" | |
| 25 #include "lj_cdata.h" | |
| 26 #include "lj_cconv.h" | |
| 27 #endif | |
| 28 #include "lj_strfmt.h" | |
| 29 #include "lj_serialize.h" | |
| 30 #include "lj_lib.h" | |
| 31 | |
| 32 /* -- Helper functions ---------------------------------------------------- */ | |
| 33 | |
| 34 /* Check that the first argument is a string buffer. */ | |
| 35 static SBufExt *buffer_tobuf(lua_State *L) | |
| 36 { | |
| 37 if (!(L->base < L->top && tvisbuf(L->base))) | |
| 38 lj_err_argtype(L, 1, "buffer"); | |
| 39 return bufV(L->base); | |
| 40 } | |
| 41 | |
| 42 /* Ditto, but for writers. */ | |
| 43 static LJ_AINLINE SBufExt *buffer_tobufw(lua_State *L) | |
| 44 { | |
| 45 SBufExt *sbx = buffer_tobuf(L); | |
| 46 setsbufXL_(sbx, L); | |
| 47 return sbx; | |
| 48 } | |
| 49 | |
| 50 #define buffer_toudata(sbx) ((GCudata *)(sbx)-1) | |
| 51 | |
| 52 /* -- Buffer methods ------------------------------------------------------ */ | |
| 53 | |
| 54 #define LJLIB_MODULE_buffer_method | |
| 55 | |
| 56 LJLIB_CF(buffer_method_free) | |
| 57 { | |
| 58 SBufExt *sbx = buffer_tobuf(L); | |
| 59 lj_bufx_free(L, sbx); | |
| 60 L->top = L->base+1; /* Chain buffer object. */ | |
| 61 return 1; | |
| 62 } | |
| 63 | |
| 64 LJLIB_CF(buffer_method_reset) LJLIB_REC(.) | |
| 65 { | |
| 66 SBufExt *sbx = buffer_tobuf(L); | |
| 67 lj_bufx_reset(sbx); | |
| 68 L->top = L->base+1; /* Chain buffer object. */ | |
| 69 return 1; | |
| 70 } | |
| 71 | |
| 72 LJLIB_CF(buffer_method_skip) LJLIB_REC(.) | |
| 73 { | |
| 74 SBufExt *sbx = buffer_tobuf(L); | |
| 75 MSize n = (MSize)lj_lib_checkintrange(L, 2, 0, LJ_MAX_BUF); | |
| 76 MSize len = sbufxlen(sbx); | |
| 77 if (n < len) { | |
| 78 sbx->r += n; | |
| 79 } else if (sbufiscow(sbx)) { | |
| 80 sbx->r = sbx->w; | |
| 81 } else { | |
| 82 sbx->r = sbx->w = sbx->b; | |
| 83 } | |
| 84 L->top = L->base+1; /* Chain buffer object. */ | |
| 85 return 1; | |
| 86 } | |
| 87 | |
| 88 LJLIB_CF(buffer_method_set) LJLIB_REC(.) | |
| 89 { | |
| 90 SBufExt *sbx = buffer_tobuf(L); | |
| 91 GCobj *ref; | |
| 92 const char *p; | |
| 93 MSize len; | |
| 94 #if LJ_HASFFI | |
| 95 if (tviscdata(L->base+1)) { | |
| 96 CTState *cts = ctype_cts(L); | |
| 97 lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CVOID), (uint8_t *)&p, | |
| 98 L->base+1, CCF_ARG(2)); | |
| 99 len = (MSize)lj_lib_checkintrange(L, 3, 0, LJ_MAX_BUF); | |
| 100 } else | |
| 101 #endif | |
| 102 { | |
| 103 GCstr *str = lj_lib_checkstrx(L, 2); | |
| 104 p = strdata(str); | |
| 105 len = str->len; | |
| 106 } | |
| 107 lj_bufx_free(L, sbx); | |
| 108 lj_bufx_set_cow(L, sbx, p, len); | |
| 109 ref = gcV(L->base+1); | |
| 110 setgcref(sbx->cowref, ref); | |
| 111 lj_gc_objbarrier(L, buffer_toudata(sbx), ref); | |
| 112 L->top = L->base+1; /* Chain buffer object. */ | |
| 113 return 1; | |
| 114 } | |
| 115 | |
| 116 LJLIB_CF(buffer_method_put) LJLIB_REC(.) | |
| 117 { | |
| 118 SBufExt *sbx = buffer_tobufw(L); | |
| 119 ptrdiff_t arg, narg = L->top - L->base; | |
| 120 for (arg = 1; arg < narg; arg++) { | |
| 121 cTValue *o = &L->base[arg], *mo = NULL; | |
| 122 retry: | |
| 123 if (tvisstr(o)) { | |
| 124 lj_buf_putstr((SBuf *)sbx, strV(o)); | |
| 125 } else if (tvisint(o)) { | |
| 126 lj_strfmt_putint((SBuf *)sbx, intV(o)); | |
| 127 } else if (tvisnum(o)) { | |
| 128 lj_strfmt_putfnum((SBuf *)sbx, STRFMT_G14, numV(o)); | |
| 129 } else if (tvisbuf(o)) { | |
| 130 SBufExt *sbx2 = bufV(o); | |
| 131 if (sbx2 == sbx) lj_err_arg(L, (int)(arg+1), LJ_ERR_BUFFER_SELF); | |
| 132 lj_buf_putmem((SBuf *)sbx, sbx2->r, sbufxlen(sbx2)); | |
| 133 } else if (!mo && !tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) { | |
| 134 /* Call __tostring metamethod inline. */ | |
| 135 copyTV(L, L->top++, mo); | |
| 136 copyTV(L, L->top++, o); | |
| 137 lua_call(L, 1, 1); | |
| 138 o = &L->base[arg]; /* The stack may have been reallocated. */ | |
| 139 copyTV(L, &L->base[arg], L->top-1); | |
| 140 L->top = L->base + narg; | |
| 141 goto retry; /* Retry with the result. */ | |
| 142 } else { | |
| 143 lj_err_argtype(L, (int)(arg+1), "string/number/__tostring"); | |
| 144 } | |
| 145 /* Probably not useful to inline other __tostring MMs, e.g. FFI numbers. */ | |
| 146 } | |
| 147 L->top = L->base+1; /* Chain buffer object. */ | |
| 148 lj_gc_check(L); | |
| 149 return 1; | |
| 150 } | |
| 151 | |
| 152 LJLIB_CF(buffer_method_putf) LJLIB_REC(.) | |
| 153 { | |
| 154 SBufExt *sbx = buffer_tobufw(L); | |
| 155 lj_strfmt_putarg(L, (SBuf *)sbx, 2, 2); | |
| 156 L->top = L->base+1; /* Chain buffer object. */ | |
| 157 lj_gc_check(L); | |
| 158 return 1; | |
| 159 } | |
| 160 | |
| 161 LJLIB_CF(buffer_method_get) LJLIB_REC(.) | |
| 162 { | |
| 163 SBufExt *sbx = buffer_tobuf(L); | |
| 164 ptrdiff_t arg, narg = L->top - L->base; | |
| 165 if (narg == 1) { | |
| 166 narg++; | |
| 167 setnilV(L->top++); /* get() is the same as get(nil). */ | |
| 168 } | |
| 169 for (arg = 1; arg < narg; arg++) { | |
| 170 TValue *o = &L->base[arg]; | |
| 171 MSize n = tvisnil(o) ? LJ_MAX_BUF : | |
| 172 (MSize) lj_lib_checkintrange(L, (int)(arg+1), 0, LJ_MAX_BUF); | |
| 173 MSize len = sbufxlen(sbx); | |
| 174 if (n > len) n = len; | |
| 175 setstrV(L, o, lj_str_new(L, sbx->r, n)); | |
| 176 sbx->r += n; | |
| 177 } | |
| 178 if (sbx->r == sbx->w && !sbufiscow(sbx)) sbx->r = sbx->w = sbx->b; | |
| 179 lj_gc_check(L); | |
| 180 return (int)(narg-1); | |
| 181 } | |
| 182 | |
| 183 #if LJ_HASFFI | |
| 184 LJLIB_CF(buffer_method_putcdata) LJLIB_REC(.) | |
| 185 { | |
| 186 SBufExt *sbx = buffer_tobufw(L); | |
| 187 const char *p; | |
| 188 MSize len; | |
| 189 if (tviscdata(L->base+1)) { | |
| 190 CTState *cts = ctype_cts(L); | |
| 191 lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CVOID), (uint8_t *)&p, | |
| 192 L->base+1, CCF_ARG(2)); | |
| 193 } else { | |
| 194 lj_err_argtype(L, 2, "cdata"); | |
| 195 } | |
| 196 len = (MSize)lj_lib_checkintrange(L, 3, 0, LJ_MAX_BUF); | |
| 197 lj_buf_putmem((SBuf *)sbx, p, len); | |
| 198 L->top = L->base+1; /* Chain buffer object. */ | |
| 199 return 1; | |
| 200 } | |
| 201 | |
| 202 LJLIB_CF(buffer_method_reserve) LJLIB_REC(.) | |
| 203 { | |
| 204 SBufExt *sbx = buffer_tobufw(L); | |
| 205 MSize sz = (MSize)lj_lib_checkintrange(L, 2, 0, LJ_MAX_BUF); | |
| 206 GCcdata *cd; | |
| 207 lj_buf_more((SBuf *)sbx, sz); | |
| 208 ctype_loadffi(L); | |
| 209 cd = lj_cdata_new_(L, CTID_P_UINT8, CTSIZE_PTR); | |
| 210 *(void **)cdataptr(cd) = sbx->w; | |
| 211 setcdataV(L, L->top++, cd); | |
| 212 setintV(L->top++, sbufleft(sbx)); | |
| 213 return 2; | |
| 214 } | |
| 215 | |
| 216 LJLIB_CF(buffer_method_commit) LJLIB_REC(.) | |
| 217 { | |
| 218 SBufExt *sbx = buffer_tobuf(L); | |
| 219 MSize len = (MSize)lj_lib_checkintrange(L, 2, 0, LJ_MAX_BUF); | |
| 220 if (len > sbufleft(sbx)) lj_err_arg(L, 2, LJ_ERR_NUMRNG); | |
| 221 sbx->w += len; | |
| 222 L->top = L->base+1; /* Chain buffer object. */ | |
| 223 return 1; | |
| 224 } | |
| 225 | |
| 226 LJLIB_CF(buffer_method_ref) LJLIB_REC(.) | |
| 227 { | |
| 228 SBufExt *sbx = buffer_tobuf(L); | |
| 229 GCcdata *cd; | |
| 230 ctype_loadffi(L); | |
| 231 cd = lj_cdata_new_(L, CTID_P_UINT8, CTSIZE_PTR); | |
| 232 *(void **)cdataptr(cd) = sbx->r; | |
| 233 setcdataV(L, L->top++, cd); | |
| 234 setintV(L->top++, sbufxlen(sbx)); | |
| 235 return 2; | |
| 236 } | |
| 237 #endif | |
| 238 | |
| 239 LJLIB_CF(buffer_method_encode) LJLIB_REC(.) | |
| 240 { | |
| 241 SBufExt *sbx = buffer_tobufw(L); | |
| 242 cTValue *o = lj_lib_checkany(L, 2); | |
| 243 lj_serialize_put(sbx, o); | |
| 244 lj_gc_check(L); | |
| 245 L->top = L->base+1; /* Chain buffer object. */ | |
| 246 return 1; | |
| 247 } | |
| 248 | |
| 249 LJLIB_CF(buffer_method_decode) LJLIB_REC(.) | |
| 250 { | |
| 251 SBufExt *sbx = buffer_tobufw(L); | |
| 252 setnilV(L->top++); | |
| 253 sbx->r = lj_serialize_get(sbx, L->top-1); | |
| 254 lj_gc_check(L); | |
| 255 return 1; | |
| 256 } | |
| 257 | |
| 258 LJLIB_CF(buffer_method___gc) | |
| 259 { | |
| 260 SBufExt *sbx = buffer_tobuf(L); | |
| 261 lj_bufx_free(L, sbx); | |
| 262 return 0; | |
| 263 } | |
| 264 | |
| 265 LJLIB_CF(buffer_method___tostring) LJLIB_REC(.) | |
| 266 { | |
| 267 SBufExt *sbx = buffer_tobuf(L); | |
| 268 setstrV(L, L->top-1, lj_str_new(L, sbx->r, sbufxlen(sbx))); | |
| 269 lj_gc_check(L); | |
| 270 return 1; | |
| 271 } | |
| 272 | |
| 273 LJLIB_CF(buffer_method___len) LJLIB_REC(.) | |
| 274 { | |
| 275 SBufExt *sbx = buffer_tobuf(L); | |
| 276 setintV(L->top-1, (int32_t)sbufxlen(sbx)); | |
| 277 return 1; | |
| 278 } | |
| 279 | |
| 280 LJLIB_PUSH("buffer") LJLIB_SET(__metatable) | |
| 281 LJLIB_PUSH(top-1) LJLIB_SET(__index) | |
| 282 | |
| 283 /* -- Buffer library functions -------------------------------------------- */ | |
| 284 | |
| 285 #define LJLIB_MODULE_buffer | |
| 286 | |
| 287 LJLIB_PUSH(top-2) LJLIB_SET(!) /* Set environment. */ | |
| 288 | |
| 289 LJLIB_CF(buffer_new) | |
| 290 { | |
| 291 MSize sz = 0; | |
| 292 int targ = 1; | |
| 293 GCtab *env, *dict_str = NULL, *dict_mt = NULL; | |
| 294 GCudata *ud; | |
| 295 SBufExt *sbx; | |
| 296 if (L->base < L->top && !tvistab(L->base)) { | |
| 297 targ = 2; | |
| 298 if (!tvisnil(L->base)) | |
| 299 sz = (MSize)lj_lib_checkintrange(L, 1, 0, LJ_MAX_BUF); | |
| 300 } | |
| 301 if (L->base+targ-1 < L->top) { | |
| 302 GCtab *options = lj_lib_checktab(L, targ); | |
| 303 cTValue *opt_dict, *opt_mt; | |
| 304 opt_dict = lj_tab_getstr(options, lj_str_newlit(L, "dict")); | |
| 305 if (opt_dict && tvistab(opt_dict)) { | |
| 306 dict_str = tabV(opt_dict); | |
| 307 lj_serialize_dict_prep_str(L, dict_str); | |
| 308 } | |
| 309 opt_mt = lj_tab_getstr(options, lj_str_newlit(L, "metatable")); | |
| 310 if (opt_mt && tvistab(opt_mt)) { | |
| 311 dict_mt = tabV(opt_mt); | |
| 312 lj_serialize_dict_prep_mt(L, dict_mt); | |
| 313 } | |
| 314 } | |
| 315 env = tabref(curr_func(L)->c.env); | |
| 316 ud = lj_udata_new(L, sizeof(SBufExt), env); | |
| 317 ud->udtype = UDTYPE_BUFFER; | |
| 318 /* NOBARRIER: The GCudata is new (marked white). */ | |
| 319 setgcref(ud->metatable, obj2gco(env)); | |
| 320 setudataV(L, L->top++, ud); | |
| 321 sbx = (SBufExt *)uddata(ud); | |
| 322 lj_bufx_init(L, sbx); | |
| 323 setgcref(sbx->dict_str, obj2gco(dict_str)); | |
| 324 setgcref(sbx->dict_mt, obj2gco(dict_mt)); | |
| 325 if (sz > 0) lj_buf_need2((SBuf *)sbx, sz); | |
| 326 lj_gc_check(L); | |
| 327 return 1; | |
| 328 } | |
| 329 | |
| 330 LJLIB_CF(buffer_encode) LJLIB_REC(.) | |
| 331 { | |
| 332 cTValue *o = lj_lib_checkany(L, 1); | |
| 333 setstrV(L, L->top++, lj_serialize_encode(L, o)); | |
| 334 lj_gc_check(L); | |
| 335 return 1; | |
| 336 } | |
| 337 | |
| 338 LJLIB_CF(buffer_decode) LJLIB_REC(.) | |
| 339 { | |
| 340 GCstr *str = lj_lib_checkstrx(L, 1); | |
| 341 setnilV(L->top++); | |
| 342 lj_serialize_decode(L, L->top-1, str); | |
| 343 lj_gc_check(L); | |
| 344 return 1; | |
| 345 } | |
| 346 | |
| 347 /* ------------------------------------------------------------------------ */ | |
| 348 | |
| 349 #include "lj_libdef.h" | |
| 350 | |
| 351 int luaopen_string_buffer(lua_State *L) | |
| 352 { | |
| 353 LJ_LIB_REG(L, NULL, buffer_method); | |
| 354 lua_getfield(L, -1, "__tostring"); | |
| 355 lua_setfield(L, -2, "tostring"); | |
| 356 LJ_LIB_REG(L, NULL, buffer); | |
| 357 return 1; | |
| 358 } | |
| 359 | |
| 360 #endif |