Tarantool development patches archive
 help / color / mirror / Atom feed
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;
>   }

  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