From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org> To: Mergen Imeev <imeevma@tarantool.org> Cc: tarantool-patches@freelists.org Subject: [tarantool-patches] Re: [PATCH v9 4/7] lua: remove exceptions from function luaL_tofield() Date: Thu, 28 Mar 2019 21:40:00 +0300 [thread overview] Message-ID: <58e2a19a-e6ce-bfaf-d926-c216ae83f197@tarantool.org> (raw) In-Reply-To: <20190328175410.GC4864@tarantool.org> Thanks for the fixes! I've pushed my review fixes on the branch, and dropped at the end of the email. But I've not tested them, so I propose you to do that, if you agree with the concept. ========================================================= diff --git a/src/lua/utils.c b/src/lua/utils.c index 6150e84ff..38245a979 100644 --- a/src/lua/utils.c +++ b/src/lua/utils.c @@ -399,47 +399,58 @@ lua_field_inspect_ucdata(struct lua_State *L, struct luaL_serializer *cfg, } /** - * Check that the field LUAL_SERIALIZE of the metatable is - * available. If so, create field using it. - * - * This function returns two values on stack. On top of the stack - * is boolean that shows if error happened. On the next position - * can be boolean or result of execution of function from the - * metatable. If it is boolean, that if its value is false than - * there were no metatables.It its value is true than there was - * string in that field of metatable. - * - * @param L Lua State. + * A helper structure to simplify safe call of __serialize method. + * It passes some arguments into the serializer called via pcall, + * and carries out some results. + */ +struct lua_serialize_status { + /** + * True if an attempt to call __serialize has failed. A + * diag message is set. + */ + bool is_error; + /** + * True, if __serialize exists. Otherwise an ordinary + * default serialization is used. + */ + bool is_serialize_used; + /** Parameters, passed originally to luaL_tofield. */ + struct luaL_serializer *cfg; + struct luaL_field *field; +}; + +/** + * Call __serialize method of a table object if the former exists. + * The function expects 2 values pushed onto the Lua stack: a + * value to serialize, and a pointer at a struct + * lua_serialize_status object. If __serialize exists and is + * correct, then one value is pushed as a result of serialization. + * Otherwise is_error and is_serialize_used attributes of status + * should be checked. */ static int -get_metafield_serialize(struct lua_State *L) +lua_field_try_serialize(struct lua_State *L) { - if (luaL_getmetafield(L, 1, LUAL_SERIALIZE) == 0) { - lua_pushboolean(L, false); - lua_pushboolean(L, false); - return 2; - } - bool is_error = false; - struct luaL_serializer *cfg = - (struct luaL_serializer *)lua_touserdata(L, 2); - struct luaL_field *field = - (struct luaL_field *)lua_touserdata(L, 3); - + struct lua_serialize_status *s = + (struct lua_serialize_status *) lua_touserdata(L, 2); + s->is_serialize_used = (luaL_getmetafield(L, 1, LUAL_SERIALIZE) != 0); + s->is_error = false; + if (! s->is_serialize_used) + return 0; + struct luaL_serializer *cfg = s->cfg; + struct luaL_field *field = s->field; if (lua_isfunction(L, -1)) { /* copy object itself */ lua_pushvalue(L, 1); lua_call(L, 1, 1); - is_error = (luaL_tofield(L, cfg, -1, field) != 0); - lua_pushboolean(L, is_error); - return 2; + s->is_error = (luaL_tofield(L, cfg, -1, field) != 0); + return s->is_error ? 0 : 1; } - if (!lua_isstring(L, -1)) { diag_set(LuajitError, "invalid " LUAL_SERIALIZE " value"); - lua_pushboolean(L, true); - return 2; + s->is_error = true; + return 0; } - const char *type = lua_tostring(L, -1); if (strcmp(type, "array") == 0 || strcmp(type, "seq") == 0 || strcmp(type, "sequence") == 0) { @@ -449,9 +460,7 @@ get_metafield_serialize(struct lua_State *L) if (cfg->has_compact && type[3] == '\0') field->compact = true; lua_pop(L, 1); /* type */ - lua_pushboolean(L, true); - lua_pushboolean(L, false); - return 2; + return 1; } else if (strcmp(type, "map") == 0 || strcmp(type, "mapping") == 0) { field->type = MP_MAP; /* Override type */ field->size = luaL_maplen(L, 1); @@ -459,13 +468,11 @@ get_metafield_serialize(struct lua_State *L) if (cfg->has_compact && type[3] == '\0') field->compact = true; lua_pop(L, 1); /* type */ - lua_pushboolean(L, true); - lua_pushboolean(L, false); - return 2; + return 1; } else { diag_set(LuajitError, "invalid " LUAL_SERIALIZE " value"); - lua_pushboolean(L, true); - return 2; + s->is_error = true; + return 0; } } @@ -478,27 +485,19 @@ lua_field_inspect_table(struct lua_State *L, struct luaL_serializer *cfg, uint32_t max = 0; if (cfg->encode_load_metatables) { - lua_pushcfunction(L, get_metafield_serialize); + struct lua_serialize_status s; + s.cfg = cfg; + s.field = field; + lua_pushcfunction(L, lua_field_try_serialize); lua_pushvalue(L, idx); - lua_pushlightuserdata(L, cfg); - lua_pushlightuserdata(L, field); - if (lua_pcall(L, 3, 2, 0) != 0) { + lua_pushlightuserdata(L, &s); + if (lua_pcall(L, 2, 1, 0) != 0) { diag_set(LuajitError, lua_tostring(L, -1)); return -1; } - bool is_error = lua_toboolean(L, -1); - bool is_bool = lua_isboolean(L, -2); - if (is_error) { - lua_pop(L, 2); + if (s.is_error) return -1; - } - if (is_bool) { - bool is_metatable_available = lua_toboolean(L, -2); - lua_pop(L, 2); - if (is_metatable_available) - return 0; - } else { - lua_pop(L, 1); + if (s.is_serialize_used) { lua_replace(L, idx); return 0; }
next prev parent reply other threads:[~2019-03-28 18:40 UTC|newest] Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-03-22 10:50 [tarantool-patches] [PATCH v9 0/7] sql: remove box.sql.execute imeevma 2019-03-22 10:50 ` [tarantool-patches] [PATCH v9 1/7] sql: add column name to SQL change counter imeevma 2019-03-22 15:42 ` [tarantool-patches] " Konstantin Osipov 2019-03-25 19:34 ` Mergen Imeev 2019-03-29 12:00 ` Kirill Yukhin 2019-03-22 10:50 ` [tarantool-patches] [PATCH v9 2/7] sql: fix error code for SQL errors in execute.c imeevma 2019-03-22 15:45 ` [tarantool-patches] " Konstantin Osipov 2019-03-26 21:48 ` Vladislav Shpilevoy 2019-03-27 11:43 ` Konstantin Osipov 2019-03-28 17:46 ` Mergen Imeev 2019-03-29 12:01 ` Kirill Yukhin 2019-03-22 10:50 ` [tarantool-patches] [PATCH v9 3/7] sql: remove box.sql.debug() imeevma 2019-03-22 15:46 ` [tarantool-patches] " Konstantin Osipov 2019-03-25 19:39 ` Mergen Imeev 2019-03-26 21:48 ` Vladislav Shpilevoy 2019-03-28 17:48 ` Mergen Imeev 2019-03-28 18:01 ` Vladislav Shpilevoy 2019-03-29 12:02 ` Kirill Yukhin 2019-03-22 10:50 ` [tarantool-patches] [PATCH v9 4/7] lua: remove exceptions from function luaL_tofield() imeevma 2019-03-22 15:53 ` [tarantool-patches] " Konstantin Osipov 2019-03-29 19:26 ` Vladislav Shpilevoy 2019-03-26 21:48 ` Vladislav Shpilevoy 2019-03-28 17:54 ` Mergen Imeev 2019-03-28 18:40 ` Vladislav Shpilevoy [this message] 2019-03-28 19:56 ` Mergen Imeev 2019-03-28 21:41 ` Mergen Imeev 2019-03-29 21:06 ` Vladislav Shpilevoy 2019-03-22 10:50 ` [tarantool-patches] [PATCH v9 5/7] iproto: create port_sql imeevma 2019-03-22 15:55 ` [tarantool-patches] " Konstantin Osipov 2019-03-22 10:50 ` [tarantool-patches] [PATCH v9 6/7] sql: create box.execute() imeevma 2019-03-22 15:57 ` [tarantool-patches] " Konstantin Osipov 2019-03-22 10:50 ` [tarantool-patches] [PATCH v9 7/7] sql: remove box.sql.execute() imeevma 2019-03-26 21:48 ` [tarantool-patches] " Vladislav Shpilevoy 2019-03-28 20:13 ` Mergen Imeev 2019-03-29 21:06 ` Vladislav Shpilevoy 2019-03-29 21:07 ` [tarantool-patches] Re: [PATCH v9 0/7] sql: remove box.sql.execute Vladislav Shpilevoy
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=58e2a19a-e6ce-bfaf-d926-c216ae83f197@tarantool.org \ --to=v.shpilevoy@tarantool.org \ --cc=imeevma@tarantool.org \ --cc=tarantool-patches@freelists.org \ --subject='[tarantool-patches] Re: [PATCH v9 4/7] lua: remove exceptions from function luaL_tofield()' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox