From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org> To: roman.habibov1@yandex.ru, "tarantool-patches@freelists.org" <tarantool-patches@freelists.org> Subject: [tarantool-patches] Re: [PATCH v3] json: add options to json.encode() Date: Wed, 1 Aug 2018 13:37:42 +0300 [thread overview] Message-ID: <d05f5c7e-e5ab-5a74-6f20-32f45b104a2f@tarantool.org> (raw) In-Reply-To: <28658371533050946@myt4-74a8acfc13eb.qloud-c.yandex.net> Hi! Thanks for the fixes! See 8 comments. > commit ebef41bb68abbac75ed2d7cb4a5fa65d282f4ee3 > Author: Roman Khabibov <roman.habibov1@yandex.ru> > Date: Sun Jul 8 02:21:08 2018 +0300 > > json: add options to json.encode() > > Add an ability to pass options to json.encode()/decode(). > > Closes: #2888. > > diff --git a/src/lua/utils.c b/src/lua/utils.c > index 2f0f4dcf8..12fa8ff0d 100644 > --- a/src/lua/utils.c > +++ b/src/lua/utils.c > @@ -214,6 +214,50 @@ static struct { > { NULL, 0, 0, 0}, > }; > > +/** > + * Configure one field in @a cfg. Add one lua table to the top of > + * lua stack. 1. Looks like the comment is deceptive. When the function returns NULL, it pops the value and has no after effects. When it returns not NULL, it pushes not table but integer. Please, rewrite the comment more carefully. 2. This function as well as parse_options is method of luaL_serializer, so it should has prefix luaL_serializer_ like luaL_serializer_cfg. luaL_serializer_parse_option luaL_serializer_parse_options > + * @param L lua stack > + * @param i index of option in OPTIONS[] > + * @param cfg serializer to inherit configuration > + * @return ponter to the value of option, NULL if option is not 3. Typo: 'ponter'. 4. For different retvals use separate @retval lines. 5. Use @retval instead of @return, as I said you in the private chat. > + * in the table > + */ > +static int * > +parse_option(struct lua_State *L, int i, struct luaL_serializer *cfg) { > + lua_getfield(L, 2, OPTIONS[i].name); > + if (lua_isnil(L, -1)) { > + lua_pop(L, 1); /* key hasn't changed */ 6. Write comments on separate lines, start with capital letter, finish with dot. > + return NULL; > + } 7. Lets always pop the value you got above before returning. It is a strange behavior when a function sometimes pushes onto the stack, and sometimes not. And I've found a bug caused by this ambiguity. See the next comment. > + /* > + * Update struct luaL_serializer using pointer to a > + * configuration value (all values must be `int` for that). > + */ > + int *pval = (int *) ((char *) cfg + OPTIONS[i].offset); > + /* Update struct luaL_serializer structure */ > + switch (OPTIONS[i].type) { > + case LUA_TBOOLEAN: > + *pval = lua_toboolean(L, -1); > + break; > + case LUA_TNUMBER: > + *pval = lua_tointeger(L, -1); > + break; > + default: > + unreachable(); > + } > + return pval; > +} > + > +void > +parse_options(struct lua_State *L, struct luaL_serializer *cfg) { > + for (int i = 0; OPTIONS[i].name != NULL; i++) { > + if (parse_option(L, i, cfg) != NULL) > + lua_pop(L, 1); > + } > + lua_pop(L, 1); > +} > + > /** > * @brief serializer.cfg{} Lua binding for serializers. > * serializer.cfg is a table that contains current configuration values from > @@ -225,38 +269,29 @@ static struct { > * @return 0 > */ > static int > -luaL_serializer_cfg(lua_State *L) > +luaL_serializer_cfg(struct lua_State *L) > { > luaL_checktype(L, 1, LUA_TTABLE); /* serializer */ > luaL_checktype(L, 2, LUA_TTABLE); /* serializer.cfg */ > struct luaL_serializer *cfg = luaL_checkserializer(L); > /* Iterate over all available options and checks keys in passed table */ > for (int i = 0; OPTIONS[i].name != NULL; i++) { > - lua_getfield(L, 2, OPTIONS[i].name); > - if (lua_isnil(L, -1)) { > - lua_pop(L, 1); /* key hasn't changed */ > - continue; > - } > - /* > - * Update struct luaL_serializer using pointer to a > - * configuration value (all values must be `int` for that). > - */ > - int *pval = (int *) ((char *) cfg + OPTIONS[i].offset); > + int *pval = parse_option(L, i, cfg); > /* Update struct luaL_serializer structure */ > - switch (OPTIONS[i].type) { > - case LUA_TBOOLEAN: > - *pval = lua_toboolean(L, -1); > - lua_pushboolean(L, *pval); > - break; > - case LUA_TNUMBER: > - *pval = lua_tointeger(L, -1); > - lua_pushinteger(L, *pval); > - break; > - default: > - unreachable(); > + if (pval != NULL) { > + switch (OPTIONS[i].type) { > + case LUA_TBOOLEAN: > + lua_pushboolean(L, *pval); > + break; > + case LUA_TNUMBER: > + lua_pushinteger(L, *pval); > + break; > + default: > + unreachable(); > + } > + /* Save normalized value to serializer.cfg table */ > + lua_setfield(L, 1, OPTIONS[i].name); > } 8. Here you have a bug - the lua stack always grows. It was even before your patch. Before parse_option above you have stack size N. After parse_option is called and returned not NULL you have stack size N + 1. After lua_pushboolean/pushinteger you have stack size N + 2. After lua_setfield it becomes N + 1. So on each iteration of the cycle the stack grows by 1. It should not. > - /* Save normalized value to serializer.cfg table */ > - lua_setfield(L, 1, OPTIONS[i].name); > } > return 0; > }
next prev parent reply other threads:[~2018-08-01 10:37 UTC|newest] Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top [not found] <cover.1531010828.git.roman.habibov1@yandex.ru> 2018-07-08 0:57 ` [tarantool-patches] [PATCH] json: added " Roman Khabibov 2018-07-09 10:33 ` [tarantool-patches] " Vladislav Shpilevoy 2018-07-17 18:19 ` roman.habibov1 2018-07-19 10:18 ` Vladislav Shpilevoy 2018-07-23 22:38 ` [tarantool-patches] Re: [PATCH v3] json: add " roman.habibov1 2018-07-25 21:35 ` Vladislav Shpilevoy 2018-07-26 9:40 ` roman.habibov1 2018-07-26 10:07 ` Vladislav Shpilevoy 2018-07-26 12:29 ` roman.habibov1 2018-07-26 12:33 ` Vladislav Shpilevoy 2018-07-26 13:19 ` roman.habibov1 2018-07-26 21:45 ` Vladislav Shpilevoy 2018-07-31 15:29 ` roman.habibov1 2018-08-01 10:37 ` Vladislav Shpilevoy [this message] 2018-08-01 20:41 ` roman.habibov1 2018-08-02 12:59 ` Vladislav Shpilevoy 2018-08-07 21:52 ` roman.habibov1 2018-08-07 21:53 ` roman.habibov1 2018-08-08 19:07 ` Vladislav Shpilevoy 2018-08-13 23:14 ` roman.habibov1 2018-08-14 22:29 ` Vladislav Shpilevoy 2018-08-23 21:03 ` Alexander Turenko 2018-09-09 15:28 ` Alexander Turenko 2018-09-09 23:42 ` roman.habibov1 2018-09-10 13:12 ` Alexander Turenko 2018-08-08 19:08 ` Vladislav Shpilevoy 2018-07-11 7:57 ` [tarantool-patches] Re: [PATCH] json: added " Kirill Yukhin 2018-07-19 10:24 ` Vladislav Shpilevoy 2018-09-13 15:23 ` Kirill Yukhin
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=d05f5c7e-e5ab-5a74-6f20-32f45b104a2f@tarantool.org \ --to=v.shpilevoy@tarantool.org \ --cc=roman.habibov1@yandex.ru \ --cc=tarantool-patches@freelists.org \ --subject='[tarantool-patches] Re: [PATCH v3] json: add options to json.encode()' \ /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