From c6448fb242f199d584a27b26a558f86ff2b19b8d Mon Sep 17 00:00:00 2001 From: stillcold Date: Wed, 25 May 2022 22:02:43 +0800 Subject: [PATCH] Add meta table operation support for repeated label. --- pb.c | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/pb.c b/pb.c index 00bbe77..71b98c7 100644 --- a/pb.c +++ b/pb.c @@ -139,6 +139,7 @@ typedef struct lpb_State { int defs_index; int enc_hooks_index; int dec_hooks_index; + int repeated_mt_index; unsigned use_hooks : 1; /* lpb_Int64Mode */ unsigned enum_as_value : 1; unsigned default_mode : 2; /* lpb_DefMode */ @@ -169,6 +170,21 @@ static void lpb_pushenchooktable(lua_State *L, lpb_State *LS) static void lpb_pushdechooktable(lua_State *L, lpb_State *LS) { LS->dec_hooks_index = lpb_reftable(L, LS->dec_hooks_index); } +static void lpb_setrepeatedmttable(lua_State *L, lpb_State *LS) +{ + lua_pushvalue(L, -1); + LS->repeated_mt_index = luaL_ref(L, LUA_REGISTRYINDEX); +} + +static int lpb_pushrepeatedmttable(lua_State *L, lpb_State *LS) +{ + if (LS->repeated_mt_index != LUA_NOREF) { + lua_rawgeti(L, LUA_REGISTRYINDEX, LS->repeated_mt_index); + return 1; + } + return 0; +} + static int Lpb_delete(lua_State *L) { lpb_State *LS = (lpb_State*)luaL_testudata(L, 1, PB_STATE); if (LS != NULL) { @@ -1346,7 +1362,16 @@ static int lpb_pushdeffield(lua_State *L, lpb_State *LS, const pb_Field *f, int const pb_Type *type; char *end; if (f == NULL) return 0; - if (f->repeated) return is_proto3 ? (lua_newtable(L), 1) : 0; + if (f->repeated){ + if (!is_proto3){ + return 0; + } + lua_newtable(L); + if (lpb_pushrepeatedmttable(L, LS)){ + lua_setmetatable(L, -2); + } + return 1; + } switch (f->type_id) { case PB_Tbytes: case PB_Tstring: if (f->default_value) @@ -1469,6 +1494,20 @@ static int Lpb_encode_hook(lua_State *L) { return 1; } +static int Lpb_repeated_mt(lua_State *L) { + lpb_State *LS = default_lstate(L); + int type = lua_type(L, 1); + if (type != LUA_TNONE && type != LUA_TNIL && type != LUA_TTABLE) + { + return 0; + } + if (type == LUA_TTABLE) { + lua_settop(L, 1); + lpb_setrepeatedmttable(L, LS); + } + return 0; +} + static int Lpb_clear(lua_State *L) { lpb_State *LS = default_lstate(L); pb_State *S = (pb_State*)LS->state; @@ -1953,6 +1992,7 @@ LUALIB_API int luaopen_pb(lua_State *L) { ENTRY(defaults), ENTRY(hook), ENTRY(encode_hook), + ENTRY(repeated_mt), ENTRY(tohex), ENTRY(fromhex), ENTRY(result),