From bbb12f3c85932c82cf7702a6eaa20b33e4a18018 Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Mon, 29 Dec 2025 18:51:36 +0800 Subject: [PATCH] update sproto --- lualib-src/sproto/lsproto.c | 47 +++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/lualib-src/sproto/lsproto.c b/lualib-src/sproto/lsproto.c index 74b5397e..caf039dd 100644 --- a/lualib-src/sproto/lsproto.c +++ b/lualib-src/sproto/lsproto.c @@ -242,8 +242,8 @@ get_encodefield(const struct sproto_arg *args) { self->iter_table = top - 1; self->iter_key = top; } else if (!lua_istable(L,self->array_index)) { - return luaL_error(L, ".*%s(%d) should be a table or an userdata with metamethods (Is a %s)", - args->tagname, args->index, lua_typename(L, lua_type(L, -1))); + return luaL_error(L, "%s.%s(%d) should be a table or an userdata with metamethods (Is a %s)", + sproto_name(self->st), args->tagname, args->index, lua_typename(L, lua_type(L, -1))); } else { lua_pushnil(L); self->iter_func = 0; @@ -296,8 +296,8 @@ encode_one(const struct sproto_arg *args, struct encode_ud *self) { } else { v = tointegerx(L, -1, &isnum); if(!isnum) { - return luaL_error(L, ".%s[%d] is not an integer (Is a %s)", - args->tagname, args->index, lua_typename(L, lua_type(L, -1))); + return luaL_error(L, "%s.%s[%d] is not an integer (Is a %s)", + sproto_name(self->st), args->tagname, args->index, lua_typename(L, lua_type(L, -1))); } } lua_pop(L,1); @@ -315,14 +315,15 @@ encode_one(const struct sproto_arg *args, struct encode_ud *self) { case SPROTO_TDOUBLE: { lua_Number v = lua_tonumber(L, -1); *(double*)args->value = (double)v; + lua_pop(L,1); return 8; } case SPROTO_TBOOLEAN: { int isbool; int v = tobooleanx(L, -1, &isbool); if (!isbool) { - return luaL_error(L, ".%s[%d] is not a boolean (Is a %s)", - args->tagname, args->index, lua_typename(L, lua_type(L, -1))); + return luaL_error(L, "%s.%s[%d] is not a boolean (Is a %s)", + sproto_name(self->st), args->tagname, args->index, lua_typename(L, lua_type(L, -1))); } *(int *)args->value = v; lua_pop(L,1); @@ -334,8 +335,8 @@ encode_one(const struct sproto_arg *args, struct encode_ud *self) { int type = lua_type(L, -1); // get the type firstly, lua_tolstring may convert value on stack to string const char * str = tolstringx(L, -1, &sz, &isstring); if (!isstring) { - return luaL_error(L, ".%s[%d] is not a string (Is a %s)", - args->tagname, args->index, lua_typename(L, type)); + return luaL_error(L, "%s.%s[%d] is not a string (Is a %s)", + sproto_name(self->st), args->tagname, args->index, lua_typename(L, type)); } if (sz > args->length) return SPROTO_CB_ERROR; @@ -359,7 +360,7 @@ encode_one(const struct sproto_arg *args, struct encode_ud *self) { sub.iter_key = 0; r = sproto_encode(args->subtype, args->value, args->length, encode, &sub); lua_settop(L, top-1); // pop the value - if (r < 0) + if (r < 0) return SPROTO_CB_ERROR; return r; } @@ -389,15 +390,26 @@ encode(const struct sproto_arg *args) { static void * expand_buffer(lua_State *L, int osz, int nsz) { - void *output; - do { - osz *= 2; - } while (osz < nsz); - if (osz > ENCODE_MAXSIZE) { + // assert(osz > 0 && osz < nsz) + if (luai_unlikely(nsz > ENCODE_MAXSIZE)) { luaL_error(L, "object is too large (>%d)", ENCODE_MAXSIZE); return NULL; } - output = lua_newuserdata(L, osz); + + // osz = osz * 1.5 + // factor > 1.618... never reuse alloced space + // factor = 1.3, reuse after 3 steps + // factor = 1.4, reuse after 4 steps + // factor = 1.5, reuse after 5 steps + // factor = 1.6, reuse after 8 steps + osz += osz >> 1; + if (osz < nsz) { + osz = nsz; + } else if (osz > ENCODE_MAXSIZE) { + osz = ENCODE_MAXSIZE; + } + + void *output = lua_newuserdata(L, osz); lua_replace(L, lua_upvalueindex(1)); lua_pushinteger(L, osz); lua_replace(L, lua_upvalueindex(2)); @@ -440,8 +452,9 @@ lencode(lua_State *L) { r = sproto_encode(st, buffer, sz, encode, &self); if (r<0) { - buffer = expand_buffer(L, sz, sz*2); - sz *= 2; + // nsz > osz to double sz + buffer = expand_buffer(L, sz, sz + 1); + sz = lua_tointeger(L, lua_upvalueindex(2)); } else { lua_pushlstring(L, buffer, r); return 1;