aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2021-03-25 02:21:31 +0100
committerMike Pall <mike>2021-03-25 02:21:31 +0100
commit4c6b669c419f313306b9e6ee43be4ad5f6d73ec6 (patch)
tree4547f52836e186e94b68b331ea73d6b0086cb415 /src
parent836fb5bbd3a0d48cf3e4de70535925a85aea835f (diff)
downloadluajit-4c6b669c419f313306b9e6ee43be4ad5f6d73ec6.tar.gz
luajit-4c6b669c419f313306b9e6ee43be4ad5f6d73ec6.tar.bz2
luajit-4c6b669c419f313306b9e6ee43be4ad5f6d73ec6.zip
String buffers, part 1: object serialization.
Sponsored by fmad.io.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile6
-rw-r--r--src/Makefile.dep36
-rw-r--r--src/lib_buffer.c66
-rw-r--r--src/lib_string.c3
-rw-r--r--src/lj_arch.h7
-rw-r--r--src/lj_buf.h9
-rw-r--r--src/lj_errmsg.h10
-rw-r--r--src/lj_serialize.c351
-rw-r--r--src/lj_serialize.h21
-rw-r--r--src/ljamalg.c2
-rw-r--r--src/lualib.h1
11 files changed, 494 insertions, 18 deletions
diff --git a/src/Makefile b/src/Makefile
index 6f17bafd..a6e25ba1 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -482,13 +482,15 @@ LJVM_BOUT= $(LJVM_S)
482LJVM_MODE= elfasm 482LJVM_MODE= elfasm
483 483
484LJLIB_O= lib_base.o lib_math.o lib_bit.o lib_string.o lib_table.o \ 484LJLIB_O= lib_base.o lib_math.o lib_bit.o lib_string.o lib_table.o \
485 lib_io.o lib_os.o lib_package.o lib_debug.o lib_jit.o lib_ffi.o 485 lib_io.o lib_os.o lib_package.o lib_debug.o lib_jit.o lib_ffi.o \
486 lib_buffer.o
486LJLIB_C= $(LJLIB_O:.o=.c) 487LJLIB_C= $(LJLIB_O:.o=.c)
487 488
488LJCORE_O= lj_assert.o lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o lj_buf.o \ 489LJCORE_O= lj_assert.o lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o lj_buf.o \
489 lj_str.o lj_tab.o lj_func.o lj_udata.o lj_meta.o lj_debug.o \ 490 lj_str.o lj_tab.o lj_func.o lj_udata.o lj_meta.o lj_debug.o \
490 lj_prng.o lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o \ 491 lj_prng.o lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o \
491 lj_strscan.o lj_strfmt.o lj_strfmt_num.o lj_api.o lj_profile.o \ 492 lj_strscan.o lj_strfmt.o lj_strfmt_num.o lj_serialize.o \
493 lj_api.o lj_profile.o \
492 lj_lex.o lj_parse.o lj_bcread.o lj_bcwrite.o lj_load.o \ 494 lj_lex.o lj_parse.o lj_bcread.o lj_bcwrite.o lj_load.o \
493 lj_ir.o lj_opt_mem.o lj_opt_fold.o lj_opt_narrow.o \ 495 lj_ir.o lj_opt_mem.o lj_opt_fold.o lj_opt_narrow.o \
494 lj_opt_dce.o lj_opt_loop.o lj_opt_split.o lj_opt_sink.o \ 496 lj_opt_dce.o lj_opt_loop.o lj_opt_split.o lj_opt_sink.o \
diff --git a/src/Makefile.dep b/src/Makefile.dep
index 3f26599e..315bf632 100644
--- a/src/Makefile.dep
+++ b/src/Makefile.dep
@@ -10,6 +10,9 @@ lib_bit.o: lib_bit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
10 lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_strscan.h \ 10 lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_strscan.h \
11 lj_strfmt.h lj_ctype.h lj_cdata.h lj_cconv.h lj_carith.h lj_ff.h \ 11 lj_strfmt.h lj_ctype.h lj_cdata.h lj_cconv.h lj_carith.h lj_ff.h \
12 lj_ffdef.h lj_lib.h lj_libdef.h 12 lj_ffdef.h lj_lib.h lj_libdef.h
13lib_buffer.o: lib_buffer.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
14 lj_def.h lj_arch.h lj_gc.h lj_buf.h lj_str.h lj_serialize.h lj_lib.h \
15 lj_libdef.h
13lib_debug.o: lib_debug.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ 16lib_debug.o: lib_debug.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
14 lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_lib.h \ 17 lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_lib.h \
15 lj_libdef.h 18 lj_libdef.h
@@ -170,15 +173,18 @@ lj_parse.o: lj_parse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
170 lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_buf.h lj_str.h lj_tab.h \ 173 lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_buf.h lj_str.h lj_tab.h \
171 lj_func.h lj_state.h lj_bc.h lj_ctype.h lj_strfmt.h lj_lex.h lj_parse.h \ 174 lj_func.h lj_state.h lj_bc.h lj_ctype.h lj_strfmt.h lj_lex.h lj_parse.h \
172 lj_vm.h lj_vmevent.h 175 lj_vm.h lj_vmevent.h
176lj_prng.o: lj_prng.c lj_def.h lua.h luaconf.h lj_arch.h lj_prng.h
173lj_profile.o: lj_profile.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 177lj_profile.o: lj_profile.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
174 lj_buf.h lj_gc.h lj_str.h lj_frame.h lj_bc.h lj_debug.h lj_dispatch.h \ 178 lj_buf.h lj_gc.h lj_str.h lj_frame.h lj_bc.h lj_debug.h lj_dispatch.h \
175 lj_jit.h lj_ir.h lj_trace.h lj_traceerr.h lj_profile.h luajit.h 179 lj_jit.h lj_ir.h lj_trace.h lj_traceerr.h lj_profile.h luajit.h
176lj_prng.o: lj_prng.c lj_def.h lua.h luaconf.h lj_arch.h lj_prng.h
177lj_record.o: lj_record.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 180lj_record.o: lj_record.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
178 lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_meta.h lj_frame.h lj_bc.h \ 181 lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_meta.h lj_frame.h lj_bc.h \
179 lj_ctype.h lj_gc.h lj_ff.h lj_ffdef.h lj_debug.h lj_ir.h lj_jit.h \ 182 lj_ctype.h lj_gc.h lj_ff.h lj_ffdef.h lj_debug.h lj_ir.h lj_jit.h \
180 lj_ircall.h lj_iropt.h lj_trace.h lj_dispatch.h lj_traceerr.h \ 183 lj_ircall.h lj_iropt.h lj_trace.h lj_dispatch.h lj_traceerr.h \
181 lj_record.h lj_ffrecord.h lj_snap.h lj_vm.h lj_prng.h 184 lj_record.h lj_ffrecord.h lj_snap.h lj_vm.h lj_prng.h
185lj_serialize.o: lj_serialize.c lj_obj.h lua.h luaconf.h lj_def.h \
186 lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_tab.h \
187 lj_udata.h lj_ctype.h lj_cdata.h lj_serialize.h
182lj_snap.o: lj_snap.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 188lj_snap.o: lj_snap.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
183 lj_tab.h lj_state.h lj_frame.h lj_bc.h lj_ir.h lj_jit.h lj_iropt.h \ 189 lj_tab.h lj_state.h lj_frame.h lj_bc.h lj_ir.h lj_jit.h lj_iropt.h \
184 lj_trace.h lj_dispatch.h lj_traceerr.h lj_snap.h lj_target.h \ 190 lj_trace.h lj_dispatch.h lj_traceerr.h lj_snap.h lj_target.h \
@@ -189,7 +195,7 @@ lj_state.o: lj_state.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
189 lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_prng.h lj_lex.h \ 195 lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_prng.h lj_lex.h \
190 lj_alloc.h luajit.h 196 lj_alloc.h luajit.h
191lj_str.o: lj_str.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 197lj_str.o: lj_str.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
192 lj_err.h lj_errmsg.h lj_str.h lj_char.h 198 lj_err.h lj_errmsg.h lj_str.h lj_char.h lj_prng.h
193lj_strfmt.o: lj_strfmt.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 199lj_strfmt.o: lj_strfmt.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
194 lj_buf.h lj_gc.h lj_str.h lj_state.h lj_char.h lj_strfmt.h 200 lj_buf.h lj_gc.h lj_str.h lj_state.h lj_char.h lj_strfmt.h
195lj_strfmt_num.o: lj_strfmt_num.c lj_obj.h lua.h luaconf.h lj_def.h \ 201lj_strfmt_num.o: lj_strfmt_num.c lj_obj.h lua.h luaconf.h lj_def.h \
@@ -204,7 +210,7 @@ lj_trace.o: lj_trace.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
204 lj_dispatch.h lj_traceerr.h lj_snap.h lj_gdbjit.h lj_record.h lj_asm.h \ 210 lj_dispatch.h lj_traceerr.h lj_snap.h lj_gdbjit.h lj_record.h lj_asm.h \
205 lj_vm.h lj_vmevent.h lj_target.h lj_target_*.h lj_prng.h 211 lj_vm.h lj_vmevent.h lj_target.h lj_target_*.h lj_prng.h
206lj_udata.o: lj_udata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 212lj_udata.o: lj_udata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
207 lj_gc.h lj_udata.h 213 lj_gc.h lj_err.h lj_errmsg.h lj_udata.h
208lj_vmevent.o: lj_vmevent.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 214lj_vmevent.o: lj_vmevent.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
209 lj_str.h lj_tab.h lj_state.h lj_dispatch.h lj_bc.h lj_jit.h lj_ir.h \ 215 lj_str.h lj_tab.h lj_state.h lj_dispatch.h lj_bc.h lj_jit.h lj_ir.h \
210 lj_vm.h lj_vmevent.h 216 lj_vm.h lj_vmevent.h
@@ -216,23 +222,23 @@ ljamalg.o: ljamalg.c lua.h luaconf.h lauxlib.h lj_assert.c lj_obj.h \
216 lj_bc.h lj_ctype.h lj_cdata.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h \ 222 lj_bc.h lj_ctype.h lj_cdata.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h \
217 lj_traceerr.h lj_vm.h lj_err.c lj_debug.h lj_ff.h lj_ffdef.h lj_strfmt.h \ 223 lj_traceerr.h lj_vm.h lj_err.c lj_debug.h lj_ff.h lj_ffdef.h lj_strfmt.h \
218 lj_char.c lj_char.h lj_bc.c lj_bcdef.h lj_obj.c lj_buf.c lj_str.c \ 224 lj_char.c lj_char.h lj_bc.c lj_bcdef.h lj_obj.c lj_buf.c lj_str.c \
219 lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_strscan.h lj_lib.h lj_debug.c \ 225 lj_prng.h lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_strscan.h lj_lib.h \
220 lj_prng.c lj_prng.h lj_state.c lj_lex.h lj_alloc.h luajit.h \ 226 lj_debug.c lj_prng.c lj_state.c lj_lex.h lj_alloc.h luajit.h \
221 lj_dispatch.c lj_ccallback.h lj_profile.h lj_vmevent.c lj_vmevent.h \ 227 lj_dispatch.c lj_ccallback.h lj_profile.h lj_vmevent.c lj_vmevent.h \
222 lj_vmmath.c lj_strscan.c lj_strfmt.c lj_strfmt_num.c lj_api.c \ 228 lj_vmmath.c lj_strscan.c lj_strfmt.c lj_strfmt_num.c lj_serialize.c \
223 lj_profile.c lj_lex.c lualib.h lj_parse.h lj_parse.c lj_bcread.c \ 229 lj_serialize.h lj_api.c lj_profile.c lj_lex.c lualib.h lj_parse.h \
224 lj_bcdump.h lj_bcwrite.c lj_load.c lj_ctype.c lj_cdata.c lj_cconv.h \ 230 lj_parse.c lj_bcread.c lj_bcdump.h lj_bcwrite.c lj_load.c lj_ctype.c \
225 lj_cconv.c lj_ccall.c lj_ccall.h lj_ccallback.c lj_target.h \ 231 lj_cdata.c lj_cconv.h lj_cconv.c lj_ccall.c lj_ccall.h lj_ccallback.c \
226 lj_target_*.h lj_mcode.h lj_carith.c lj_carith.h lj_clib.c lj_clib.h \ 232 lj_target.h lj_target_*.h lj_mcode.h lj_carith.c lj_carith.h lj_clib.c \
227 lj_cparse.c lj_cparse.h lj_lib.c lj_ir.c lj_ircall.h lj_iropt.h \ 233 lj_clib.h lj_cparse.c lj_cparse.h lj_lib.c lj_ir.c lj_ircall.h \
228 lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c lj_opt_dce.c \ 234 lj_iropt.h lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c \
229 lj_opt_loop.c lj_snap.h lj_opt_split.c lj_opt_sink.c lj_mcode.c \ 235 lj_opt_dce.c lj_opt_loop.c lj_snap.h lj_opt_split.c lj_opt_sink.c \
230 lj_snap.c lj_record.c lj_record.h lj_ffrecord.h lj_crecord.c \ 236 lj_mcode.c lj_snap.c lj_record.c lj_record.h lj_ffrecord.h lj_crecord.c \
231 lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h lj_emit_*.h \ 237 lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h lj_emit_*.h \
232 lj_asm_*.h lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c \ 238 lj_asm_*.h lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c \
233 lib_base.c lj_libdef.h lib_math.c lib_string.c lib_table.c lib_io.c \ 239 lib_base.c lj_libdef.h lib_math.c lib_string.c lib_table.c lib_io.c \
234 lib_os.c lib_package.c lib_debug.c lib_bit.c lib_jit.c lib_ffi.c \ 240 lib_os.c lib_package.c lib_debug.c lib_bit.c lib_jit.c lib_ffi.c \
235 lib_init.c 241 lib_buffer.c lib_init.c
236luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h 242luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h
237host/buildvm.o: host/buildvm.c host/buildvm.h lj_def.h lua.h luaconf.h \ 243host/buildvm.o: host/buildvm.c host/buildvm.h lj_def.h lua.h luaconf.h \
238 lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_gc.h lj_obj.h lj_bc.h lj_ir.h \ 244 lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_gc.h lj_obj.h lj_bc.h lj_ir.h \
diff --git a/src/lib_buffer.c b/src/lib_buffer.c
new file mode 100644
index 00000000..e4555596
--- /dev/null
+++ b/src/lib_buffer.c
@@ -0,0 +1,66 @@
1/*
2** Buffer library.
3** Copyright (C) 2005-2021 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_buf.h"
18#include "lj_serialize.h"
19#include "lj_lib.h"
20
21/* ------------------------------------------------------------------------ */
22
23#define LJLIB_MODULE_buffer
24
25/* Note: this uses interim structs until the SBuf reorg. */
26
27LJLIB_CF(buffer_encode)
28{
29 cTValue *o = lj_lib_checkany(L, 1);
30 StrBuf sbuf;
31 sbuf.sb = lj_buf_tmp_(L);
32 lj_serialize_put(&sbuf, o);
33 setstrV(L, L->top++, lj_buf_str(L, sbuf.sb));
34 lj_gc_check(L);
35 return 1;
36}
37
38LJLIB_CF(buffer_decode)
39{
40 GCstr *str = lj_lib_checkstr(L, 1);
41 const char *p = strdata(str);
42 SBuf sb;
43 StrBuf sbuf;
44 setsbufL(&sb, L);
45 setmref(sb.b, p);
46 setmref(sb.p, p + str->len);
47 setmref(sb.e, p + str->len);
48 sbuf.sb = &sb;
49 sbuf.r = (char *)p;
50 setnilV(L->top++);
51 lj_serialize_get(&sbuf, L->top-1);
52 lj_gc_check(L);
53 return 1;
54}
55
56/* ------------------------------------------------------------------------ */
57
58#include "lj_libdef.h"
59
60int luaopen_string_buffer(lua_State *L)
61{
62 LJ_LIB_REG(L, NULL, buffer);
63 return 1;
64}
65
66#endif
diff --git a/src/lib_string.c b/src/lib_string.c
index 51d1c4b0..4a3ff372 100644
--- a/src/lib_string.c
+++ b/src/lib_string.c
@@ -743,6 +743,9 @@ LUALIB_API int luaopen_string(lua_State *L)
743 setgcref(basemt_it(g, LJ_TSTR), obj2gco(mt)); 743 setgcref(basemt_it(g, LJ_TSTR), obj2gco(mt));
744 settabV(L, lj_tab_setstr(L, mt, mmname_str(g, MM_index)), tabV(L->top-1)); 744 settabV(L, lj_tab_setstr(L, mt, mmname_str(g, MM_index)), tabV(L->top-1));
745 mt->nomm = (uint8_t)(~(1u<<MM_index)); 745 mt->nomm = (uint8_t)(~(1u<<MM_index));
746#if LJ_HASBUFFER
747 lj_lib_prereg(L, LUA_STRLIBNAME ".buffer", luaopen_string_buffer, tabV(L->top-1));
748#endif
746 return 1; 749 return 1;
747} 750}
748 751
diff --git a/src/lj_arch.h b/src/lj_arch.h
index 0a6e1b9f..ae999467 100644
--- a/src/lj_arch.h
+++ b/src/lj_arch.h
@@ -549,6 +549,13 @@
549#define LJ_HASFFI 1 549#define LJ_HASFFI 1
550#endif 550#endif
551 551
552/* Disable or enable the string buffer extension. */
553#if defined(LUAJIT_DISABLE_BUFFER)
554#define LJ_HASBUFFER 0
555#else
556#define LJ_HASBUFFER 1
557#endif
558
552#if defined(LUAJIT_DISABLE_PROFILE) 559#if defined(LUAJIT_DISABLE_PROFILE)
553#define LJ_HASPROFILE 0 560#define LJ_HASPROFILE 0
554#elif LJ_TARGET_POSIX 561#elif LJ_TARGET_POSIX
diff --git a/src/lj_buf.h b/src/lj_buf.h
index ae875298..a720f83b 100644
--- a/src/lj_buf.h
+++ b/src/lj_buf.h
@@ -10,7 +10,7 @@
10#include "lj_gc.h" 10#include "lj_gc.h"
11#include "lj_str.h" 11#include "lj_str.h"
12 12
13/* Resizable string buffers. Struct definition in lj_obj.h. */ 13/* Resizable string buffers. SBuf struct definition in lj_obj.h. */
14#define sbufB(sb) (mref((sb)->b, char)) 14#define sbufB(sb) (mref((sb)->b, char))
15#define sbufP(sb) (mref((sb)->p, char)) 15#define sbufP(sb) (mref((sb)->p, char))
16#define sbufE(sb) (mref((sb)->e, char)) 16#define sbufE(sb) (mref((sb)->e, char))
@@ -100,4 +100,11 @@ static LJ_AINLINE GCstr *lj_buf_str(lua_State *L, SBuf *sb)
100 return lj_str_new(L, sbufB(sb), sbuflen(sb)); 100 return lj_str_new(L, sbufB(sb), sbuflen(sb));
101} 101}
102 102
103/* Interim user-accessible string buffer. */
104typedef struct StrBuf {
105 SBuf *sb; /* Pointer to system buffer. */
106 char *r; /* String buffer read pointer. */
107 int depth; /* Remaining recursion depth. */
108} StrBuf;
109
103#endif 110#endif
diff --git a/src/lj_errmsg.h b/src/lj_errmsg.h
index 9ff4553d..a6f638ce 100644
--- a/src/lj_errmsg.h
+++ b/src/lj_errmsg.h
@@ -179,6 +179,16 @@ ERRDEF(FFI_NYIPACKBIT, "NYI: packed bit fields")
179ERRDEF(FFI_NYICALL, "NYI: cannot call this C function (yet)") 179ERRDEF(FFI_NYICALL, "NYI: cannot call this C function (yet)")
180#endif 180#endif
181 181
182#if LJ_HASBUFFER
183/* String buffer errors. */
184ERRDEF(BUFFER_BADENC, "cannot serialize " LUA_QS)
185ERRDEF(BUFFER_BADDEC, "cannot deserialize tag 0x%02x")
186ERRDEF(BUFFER_DEPTH, "too deep to serialize")
187ERRDEF(BUFFER_DUPKEY, "duplicate table key")
188ERRDEF(BUFFER_EOB, "unexpected end of buffer")
189ERRDEF(BUFFER_LEFTOV, "left-over data in buffer")
190#endif
191
182#undef ERRDEF 192#undef ERRDEF
183 193
184/* Detecting unused error messages: 194/* Detecting unused error messages:
diff --git a/src/lj_serialize.c b/src/lj_serialize.c
new file mode 100644
index 00000000..5d7b7721
--- /dev/null
+++ b/src/lj_serialize.c
@@ -0,0 +1,351 @@
1/*
2** Object de/serialization.
3** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
4*/
5
6#define lj_serialize_c
7#define LUA_CORE
8
9#include "lj_obj.h"
10#include "lj_err.h"
11#include "lj_buf.h"
12#include "lj_str.h"
13#include "lj_tab.h"
14#include "lj_udata.h"
15#if LJ_HASFFI
16#include "lj_ctype.h"
17#include "lj_cdata.h"
18#endif
19#include "lj_serialize.h"
20
21/* Tags for internal serialization format. */
22enum {
23 SER_TAG_NIL, /* 0x00 */
24 SER_TAG_FALSE,
25 SER_TAG_TRUE,
26 SER_TAG_NULL,
27 SER_TAG_LIGHTUD32,
28 SER_TAG_LIGHTUD64,
29 SER_TAG_INT,
30 SER_TAG_NUM,
31 SER_TAG_TAB, /* 0x08 */
32 SER_TAG_0x0e = SER_TAG_TAB+6,
33 SER_TAG_0x0f,
34 SER_TAG_INT64, /* 0x10 */
35 SER_TAG_UINT64,
36 SER_TAG_COMPLEX,
37 SER_TAG_0x13,
38 SER_TAG_0x14,
39 SER_TAG_0x15,
40 SER_TAG_0x16,
41 SER_TAG_0x17,
42 SER_TAG_0x18, /* 0x18 */
43 SER_TAG_0x19,
44 SER_TAG_0x1a,
45 SER_TAG_0x1b,
46 SER_TAG_0x1c,
47 SER_TAG_0x1d,
48 SER_TAG_0x1e,
49 SER_TAG_0x1f,
50 SER_TAG_STR, /* 0x20 + str->len */
51};
52LJ_STATIC_ASSERT((SER_TAG_TAB & 7) == 0);
53
54/* -- Helper functions ---------------------------------------------------- */
55
56static LJ_AINLINE char *serialize_more(char *w, StrBuf *sbuf, MSize sz)
57{
58 if (LJ_UNLIKELY(sz > (MSize)(sbufE(sbuf->sb) - w))) {
59 setsbufP(sbuf->sb, w);
60 w = lj_buf_more2(sbuf->sb, sz);
61 }
62 return w;
63}
64
65/* Write U124 to buffer. */
66static LJ_NOINLINE char *serialize_wu124_(char *w, uint32_t v)
67{
68 if (v < 0x1fe0) {
69 v -= 0xe0;
70 *w++ = (char)(0xe0 | (v >> 8)); *w++ = (char)v;
71 } else {
72 *w++ = (char)0xff;
73#if LJ_BE
74 v = lj_bswap(v);
75#endif
76 memcpy(w, &v, 4); w += 4;
77 }
78 return w;
79}
80
81static LJ_AINLINE char *serialize_wu124(char *w, uint32_t v)
82{
83 if (LJ_LIKELY(v < 0xe0)) {
84 *w++ = (char)v;
85 return w;
86 } else {
87 return serialize_wu124_(w, v);
88 }
89}
90
91static LJ_NOINLINE char *serialize_ru124_(char *r, char *e, uint32_t *pv)
92{
93 uint32_t v = *pv;
94 if (v != 0xff) {
95 if (r >= e) return NULL;
96 v = ((v & 0x1f) << 8) + *(uint8_t *)r + 0xe0; r++;
97 } else {
98 if (r + 4 > e) return NULL;
99 v = lj_getu32(r); r += 4;
100#if LJ_BE
101 v = lj_bswap(v);
102#endif
103 }
104 *pv = v;
105 return r;
106}
107
108static LJ_AINLINE char *serialize_ru124(char *r, char *e, uint32_t *pv)
109{
110 if (LJ_LIKELY(r < e)) {
111 uint32_t v = *(uint8_t *)r; r++;
112 *pv = v;
113 if (LJ_UNLIKELY(v >= 0xe0)) {
114 r = serialize_ru124_(r, e, pv);
115 }
116 return r;
117 }
118 return NULL;
119}
120
121/* -- Internal serializer ------------------------------------------------- */
122
123/* Put serialized object into buffer. */
124static char *serialize_put(char *w, StrBuf *sbuf, cTValue *o)
125{
126 if (LJ_LIKELY(tvisstr(o))) {
127 const GCstr *str = strV(o);
128 MSize len = str->len;
129 w = serialize_more(w, sbuf, 5+len);
130 w = serialize_wu124(w, SER_TAG_STR + len);
131 w = lj_buf_wmem(w, strdata(str), len);
132 } else if (tvisint(o)) {
133 uint32_t x = LJ_BE ? lj_bswap((uint32_t)intV(o)) : (uint32_t)intV(o);
134 w = serialize_more(w, sbuf, 1+4);
135 *w++ = SER_TAG_INT; memcpy(w, &x, 4); w += 4;
136 } else if (tvisnum(o)) {
137 uint64_t x = LJ_BE ? lj_bswap64(o->u64) : o->u64;
138 w = serialize_more(w, sbuf, 1+sizeof(lua_Number));
139 *w++ = SER_TAG_NUM; memcpy(w, &x, 8); w += 8;
140 } else if (tvispri(o)) {
141 w = serialize_more(w, sbuf, 1);
142 *w++ = (char)(SER_TAG_NIL + ~itype(o));
143 } else if (tvistab(o)) {
144 const GCtab *t = tabV(o);
145 uint32_t narray = 0, nhash = 0, one = 2;
146 if (sbuf->depth <= 0) lj_err_caller(sbufL(sbuf->sb), LJ_ERR_BUFFER_DEPTH);
147 sbuf->depth--;
148 if (t->asize > 0) { /* Determine max. length of array part. */
149 ptrdiff_t i;
150 TValue *array = tvref(t->array);
151 for (i = (ptrdiff_t)t->asize-1; i >= 0; i--)
152 if (!tvisnil(&array[i]))
153 break;
154 narray = (uint32_t)(i+1);
155 if (narray && tvisnil(&array[0])) one = 4;
156 }
157 if (t->hmask > 0) { /* Count number of used hash slots. */
158 uint32_t i, hmask = t->hmask;
159 Node *node = noderef(t->node);
160 for (i = 0; i <= hmask; i++)
161 nhash += !tvisnil(&node[i].val);
162 }
163 /* Write number of array slots and hash slots. */
164 w = serialize_more(w, sbuf, 1+2*5);
165 *w++ = (char)(SER_TAG_TAB + (nhash ? 1 : 0) + (narray ? one : 0));
166 if (narray) w = serialize_wu124(w, narray);
167 if (nhash) w = serialize_wu124(w, nhash);
168 if (narray) { /* Write array entries. */
169 cTValue *oa = tvref(t->array) + (one >> 2);
170 cTValue *oe = tvref(t->array) + narray;
171 while (oa < oe) w = serialize_put(w, sbuf, oa++);
172 }
173 if (nhash) { /* Write hash entries. */
174 const Node *node = noderef(t->node) + t->hmask;
175 for (;; node--)
176 if (!tvisnil(&node->val)) {
177 w = serialize_put(w, sbuf, &node->key);
178 w = serialize_put(w, sbuf, &node->val);
179 if (--nhash == 0) break;
180 }
181 }
182 sbuf->depth++;
183#if LJ_HASFFI
184 } else if (tviscdata(o)) {
185 CTState *cts = ctype_cts(sbufL(sbuf->sb));
186 CType *s = ctype_raw(cts, cdataV(o)->ctypeid);
187 uint8_t *sp = cdataptr(cdataV(o));
188 if (ctype_isinteger(s->info) && s->size == 8) {
189 w = serialize_more(w, sbuf, 1+8);
190 *w++ = (s->info & CTF_UNSIGNED) ? SER_TAG_UINT64 : SER_TAG_INT64;
191#if LJ_BE
192 { uint64_t u = lj_bswap64(*(uint64_t *)sp); memcpy(w, &u, 8); }
193#else
194 memcpy(w, sp, 8);
195#endif
196 w += 8;
197 } else if (ctype_iscomplex(s->info) && s->size == 16) {
198 w = serialize_more(w, sbuf, 1+16);
199 *w++ = SER_TAG_COMPLEX;
200#if LJ_BE
201 { /* Only swap the doubles. The re/im order stays the same. */
202 uint64_t u = lj_bswap64(((uint64_t *)sp)[0]); memcpy(w, &u, 8);
203 u = lj_bswap64(((uint64_t *)sp)[1]); memcpy(w+8, &u, 8);
204 }
205#else
206 memcpy(w, sp, 16);
207#endif
208 w += 16;
209 } else {
210 goto badenc; /* NYI other cdata */
211 }
212#endif
213 } else if (tvislightud(o)) {
214 uintptr_t ud = (uintptr_t)lightudV(G(sbufL(sbuf->sb)), o);
215 w = serialize_more(w, sbuf, 1+sizeof(ud));
216 if (ud == 0) {
217 *w++ = SER_TAG_NULL;
218 } else if (LJ_32 || checku32(ud)) {
219#if LJ_BE && LJ_64
220 ud = lj_bswap64(ud);
221#elif LJ_BE
222 ud = lj_bswap(ud);
223#endif
224 *w++ = SER_TAG_LIGHTUD32; memcpy(w, &ud, 4); w += 4;
225 } else {
226#if LJ_BE
227 ud = lj_bswap64(ud);
228#endif
229 *w++ = SER_TAG_LIGHTUD64; memcpy(w, &ud, 8); w += 8;
230 }
231 } else {
232 /* NYI userdata */
233#if LJ_HASFFI
234 badenc:
235#endif
236 lj_err_callerv(sbufL(sbuf->sb), LJ_ERR_BUFFER_BADENC, lj_typename(o));
237 }
238 return w;
239}
240
241/* Get serialized object from buffer. */
242static char *serialize_get(char *r, StrBuf *sbuf, TValue *o)
243{
244 char *e = sbufE(sbuf->sb);
245 uint32_t tp;
246 r = serialize_ru124(r, e, &tp); if (LJ_UNLIKELY(!r)) goto eob;
247 if (LJ_LIKELY(tp >= SER_TAG_STR)) {
248 uint32_t len = tp - SER_TAG_STR;
249 if (LJ_UNLIKELY(len > (uint32_t)(e - r))) goto eob;
250 setstrV(sbufL(sbuf->sb), o, lj_str_new(sbufL(sbuf->sb), r, len));
251 r += len;
252 } else if (tp == SER_TAG_INT) {
253 if (LJ_UNLIKELY(r + 4 > e)) goto eob;
254 setintV(o, (int32_t)(LJ_BE ? lj_bswap(lj_getu32(r)) : lj_getu32(r)));
255 r += 4;
256 } else if (tp == SER_TAG_NUM) {
257 if (LJ_UNLIKELY(r + 8 > e)) goto eob;
258 memcpy(o, r, 8); r += 8;
259#if LJ_BE
260 o->u64 = lj_bswap64(o->u64);
261#endif
262 if (!tvisnum(o)) setnanV(o);
263 } else if (tp <= SER_TAG_TRUE) {
264 setpriV(o, ~tp);
265 } else if (tp >= SER_TAG_TAB && tp < SER_TAG_TAB+6) {
266 uint32_t narray = 0, nhash = 0;
267 GCtab *t;
268 if (tp >= SER_TAG_TAB+2) {
269 r = serialize_ru124(r, e, &narray); if (LJ_UNLIKELY(!r)) goto eob;
270 }
271 if ((tp & 1)) {
272 r = serialize_ru124(r, e, &nhash); if (LJ_UNLIKELY(!r)) goto eob;
273 }
274 t = lj_tab_new(sbufL(sbuf->sb), narray, hsize2hbits(nhash));
275 settabV(sbufL(sbuf->sb), o, t);
276 if (narray) {
277 TValue *oa = tvref(t->array) + (tp >= SER_TAG_TAB+4);
278 TValue *oe = tvref(t->array) + narray;
279 while (oa < oe) r = serialize_get(r, sbuf, oa++);
280 }
281 if (nhash) {
282 do {
283 TValue k, *v;
284 r = serialize_get(r, sbuf, &k);
285 v = lj_tab_set(sbufL(sbuf->sb), t, &k);
286 if (LJ_UNLIKELY(!tvisnil(v)))
287 lj_err_caller(sbufL(sbuf->sb), LJ_ERR_BUFFER_DUPKEY);
288 r = serialize_get(r, sbuf, v);
289 } while (--nhash);
290 }
291#if LJ_HASFFI
292 } else if (tp >= SER_TAG_INT64 && tp <= SER_TAG_COMPLEX) {
293 uint32_t sz = tp == SER_TAG_COMPLEX ? 16 : 8;
294 GCcdata *cd;
295 if (LJ_UNLIKELY(r + sz > e)) goto eob;
296 cd = lj_cdata_new_(sbufL(sbuf->sb),
297 tp == SER_TAG_INT64 ? CTID_INT64 :
298 tp == SER_TAG_UINT64 ? CTID_UINT64 : CTID_COMPLEX_DOUBLE,
299 sz);
300 memcpy(cdataptr(cd), r, sz); r += sz;
301#if LJ_BE
302 *(uint64_t *)cdataptr(cd) = lj_bswap64(*(uint64_t *)cdataptr(cd));
303 if (sz == 16)
304 ((uint64_t *)cdataptr(cd))[1] = lj_bswap64(((uint64_t *)cdataptr(cd))[1]);
305#endif
306 setcdataV(sbufL(sbuf->sb), o, cd);
307#endif
308 } else if (tp <= (LJ_64 ? SER_TAG_LIGHTUD64 : SER_TAG_LIGHTUD32)) {
309 uintptr_t ud = 0;
310 if (tp == SER_TAG_LIGHTUD32) {
311 if (LJ_UNLIKELY(r + 4 > e)) goto eob;
312 ud = (uintptr_t)(LJ_BE ? lj_bswap(lj_getu32(r)) : lj_getu32(r));
313 r += 4;
314 }
315#if LJ_64
316 else if (tp == SER_TAG_LIGHTUD64) {
317 if (LJ_UNLIKELY(r + 8 > e)) goto eob;
318 memcpy(&ud, r, 8); r += 8;
319#if LJ_BE
320 ud = lj_bswap64(ud);
321#endif
322 }
323 setrawlightudV(o, lj_lightud_intern(sbufL(sbuf->sb), (void *)ud));
324#else
325 setrawlightudV(o, (void *)ud);
326#endif
327 } else {
328 lj_err_callerv(sbufL(sbuf->sb), LJ_ERR_BUFFER_BADDEC, tp);
329 }
330 return r;
331eob:
332 lj_err_caller(sbufL(sbuf->sb), LJ_ERR_BUFFER_EOB);
333 return NULL;
334}
335
336StrBuf * LJ_FASTCALL lj_serialize_put(StrBuf *sbuf, cTValue *o)
337{
338 sbuf->depth = LJ_SERIALIZE_DEPTH;
339 setsbufP(sbuf->sb, serialize_put(sbufP(sbuf->sb), sbuf, o));
340 return sbuf;
341}
342
343StrBuf * LJ_FASTCALL lj_serialize_get(StrBuf *sbuf, TValue *o)
344{
345 char *r = serialize_get(sbuf->r, sbuf, o);
346 if (r != sbufP(sbuf->sb))
347 lj_err_caller(sbufL(sbuf->sb), LJ_ERR_BUFFER_LEFTOV);
348 sbuf->r = r;
349 return sbuf;
350}
351
diff --git a/src/lj_serialize.h b/src/lj_serialize.h
new file mode 100644
index 00000000..95d62f4e
--- /dev/null
+++ b/src/lj_serialize.h
@@ -0,0 +1,21 @@
1/*
2** Object de/serialization.
3** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
4*/
5
6#ifndef _LJ_SERIALIZE_H
7#define _LJ_SERIALIZE_H
8
9#include "lj_obj.h"
10#include "lj_buf.h"
11
12#if LJ_HASBUFFER
13
14#define LJ_SERIALIZE_DEPTH 100 /* Default depth. */
15
16LJ_FUNC StrBuf * LJ_FASTCALL lj_serialize_put(StrBuf *sb, cTValue *o);
17LJ_FUNC StrBuf * LJ_FASTCALL lj_serialize_get(StrBuf *sb, TValue *o);
18
19#endif
20
21#endif
diff --git a/src/ljamalg.c b/src/ljamalg.c
index 8e2d4937..384b3cc1 100644
--- a/src/ljamalg.c
+++ b/src/ljamalg.c
@@ -39,6 +39,7 @@
39#include "lj_strscan.c" 39#include "lj_strscan.c"
40#include "lj_strfmt.c" 40#include "lj_strfmt.c"
41#include "lj_strfmt_num.c" 41#include "lj_strfmt_num.c"
42#include "lj_serialize.c"
42#include "lj_api.c" 43#include "lj_api.c"
43#include "lj_profile.c" 44#include "lj_profile.c"
44#include "lj_lex.c" 45#include "lj_lex.c"
@@ -85,5 +86,6 @@
85#include "lib_bit.c" 86#include "lib_bit.c"
86#include "lib_jit.c" 87#include "lib_jit.c"
87#include "lib_ffi.c" 88#include "lib_ffi.c"
89#include "lib_buffer.c"
88#include "lib_init.c" 90#include "lib_init.c"
89 91
diff --git a/src/lualib.h b/src/lualib.h
index 9cd39880..5c18e9ec 100644
--- a/src/lualib.h
+++ b/src/lualib.h
@@ -33,6 +33,7 @@ LUALIB_API int luaopen_debug(lua_State *L);
33LUALIB_API int luaopen_bit(lua_State *L); 33LUALIB_API int luaopen_bit(lua_State *L);
34LUALIB_API int luaopen_jit(lua_State *L); 34LUALIB_API int luaopen_jit(lua_State *L);
35LUALIB_API int luaopen_ffi(lua_State *L); 35LUALIB_API int luaopen_ffi(lua_State *L);
36LUALIB_API int luaopen_string_buffer(lua_State *L);
36 37
37LUALIB_API void luaL_openlibs(lua_State *L); 38LUALIB_API void luaL_openlibs(lua_State *L);
38 39