diff --git a/src/box/lua/func_adapter.c b/src/box/lua/func_adapter.c index f42177da62e702315069d5e83c30510d9054f389..6bcf22291eb55a1a3983f83bdc25d68d3a3c7cc7 100644 --- a/src/box/lua/func_adapter.c +++ b/src/box/lua/func_adapter.c @@ -124,6 +124,13 @@ func_adapter_lua_push_tuple(struct func_adapter_ctx *base, struct tuple *tuple) luaT_pushtuple(ctx->L, tuple); } +static void +func_adapter_lua_push_bool(struct func_adapter_ctx *base, bool val) +{ + struct func_adapter_lua_ctx *ctx = (struct func_adapter_lua_ctx *)base; + lua_pushboolean(ctx->L, val); +} + static void func_adapter_lua_push_null(struct func_adapter_ctx *base) { @@ -194,6 +201,25 @@ func_adapter_lua_pop_tuple(struct func_adapter_ctx *base, struct tuple **out) * of an object. The function checks all the cases. */ static bool +func_adapter_lua_is_bool(struct func_adapter_ctx *base) +{ + struct func_adapter_lua_ctx *ctx = (struct func_adapter_lua_ctx *)base; + return lua_gettop(ctx->L) >= ctx->idx && + lua_isboolean(ctx->L, ctx->idx); +} + +static void +func_adapter_lua_pop_bool(struct func_adapter_ctx *base, bool *val) +{ + struct func_adapter_lua_ctx *ctx = (struct func_adapter_lua_ctx *)base; + *val = lua_toboolean(ctx->L, ctx->idx++); +} + +/** + * Null in Lua can be represented in two ways: nil or box.NULL. + * The function checks both cases. + */ +static bool func_adapter_lua_is_null(struct func_adapter_ctx *base) { struct func_adapter_lua_ctx *ctx = (struct func_adapter_lua_ctx *)base; @@ -245,6 +271,7 @@ func_adapter_lua_create(lua_State *L, int idx) .push_double = func_adapter_lua_push_double, .push_str = func_adapter_lua_push_str, .push_tuple = func_adapter_lua_push_tuple, + .push_bool = func_adapter_lua_push_bool, .push_null = func_adapter_lua_push_null, .is_double = func_adapter_lua_is_double, @@ -253,6 +280,8 @@ func_adapter_lua_create(lua_State *L, int idx) .pop_str = func_adapter_lua_pop_str, .is_tuple = func_adapter_lua_is_tuple, .pop_tuple = func_adapter_lua_pop_tuple, + .is_bool = func_adapter_lua_is_bool, + .pop_bool = func_adapter_lua_pop_bool, .is_null = func_adapter_lua_is_null, .pop_null = func_adapter_lua_pop_null, diff --git a/src/lib/core/func_adapter.h b/src/lib/core/func_adapter.h index 8ace5cefede16843651d8a1954872fab25b2b41d..e63326731963f6c28533dc3091c3626a6b5bea22 100644 --- a/src/lib/core/func_adapter.h +++ b/src/lib/core/func_adapter.h @@ -69,6 +69,10 @@ struct func_adapter_vtab { */ void (*push_str)(struct func_adapter_ctx *ctx, const char *str, size_t len); + /** + * Pushes boolean argument. + */ + void (*push_bool)(struct func_adapter_ctx *ctx, bool val); /** * Pushes null argument. */ @@ -101,6 +105,14 @@ struct func_adapter_vtab { */ void (*pop_str)(struct func_adapter_ctx *ctx, const char **str, size_t *len); + /** + * Checks if the next returned value is a boolean. + */ + bool (*is_bool)(struct func_adapter_ctx *ctx); + /** + * Pops boolean value. + */ + void (*pop_bool)(struct func_adapter_ctx *ctx, bool *val); /** * Checks if the next returned value is null or nothing. */ @@ -189,6 +201,13 @@ func_adapter_push_tuple(struct func_adapter *func, func->vtab->push_tuple(ctx, tuple); } +static inline void +func_adapter_push_bool(struct func_adapter *func, struct func_adapter_ctx *ctx, + bool val) +{ + func->vtab->push_bool(ctx, val); +} + static inline void func_adapter_push_null(struct func_adapter *func, struct func_adapter_ctx *ctx) { @@ -237,6 +256,20 @@ func_adapter_pop_tuple(struct func_adapter *func, func->vtab->pop_tuple(ctx, tuple); } +static inline bool +func_adapter_is_bool(struct func_adapter *func, struct func_adapter_ctx *ctx) +{ + return func->vtab->is_bool(ctx); +} + +static inline void +func_adapter_pop_bool(struct func_adapter *func, struct func_adapter_ctx *ctx, + bool *val) +{ + assert(func_adapter_is_bool(func, ctx)); + func->vtab->pop_bool(ctx, val); +} + static inline bool func_adapter_is_null(struct func_adapter *func, struct func_adapter_ctx *ctx) { diff --git a/test/unit/lua_func_adapter.c b/test/unit/lua_func_adapter.c index 6f30f8f4bd27fadad9ab63c321953d962e0b3043..985fa0eb94427f45d6f6dacd73be22098945c7e2 100644 --- a/test/unit/lua_func_adapter.c +++ b/test/unit/lua_func_adapter.c @@ -167,6 +167,45 @@ test_string(void) check_plan(); } +static void +test_bool(void) +{ + plan(10); + header(); + + int idx = generate_function( + "function(a, b, c, d) " + "return a, not b, c, not d end"); + bool arguments[4]; + for (size_t i = 0; i < lengthof(arguments); ++i) + arguments[i] = rand() % 2 == 0; + struct func_adapter *func = func_adapter_lua_create(tarantool_L, idx); + struct func_adapter_ctx ctx; + func_adapter_begin(func, &ctx); + for (size_t i = 0; i < lengthof(arguments); ++i) + func_adapter_push_bool(func, &ctx, arguments[i]); + int rc = func_adapter_call(func, &ctx); + fail_if(rc != 0); + + for (size_t i = 0; i < lengthof(arguments); ++i) { + ok(func_adapter_is_bool(func, &ctx), "Expected double"); + bool retval = false; + func_adapter_pop_bool(func, &ctx, &retval); + bool is_odd = i % 2 == 0; + bool equal = arguments[i] == retval; + is(is_odd, equal, "Only odd elements are equal"); + } + + ok(!func_adapter_is_bool(func, &ctx), "No values left - no bool"); + ok(func_adapter_is_null(func, &ctx), "No values left"); + func_adapter_end(func, &ctx); + func_adapter_destroy(func); + lua_settop(tarantool_L, 0); + + footer(); + check_plan(); +} + static void test_null(void) { @@ -293,12 +332,13 @@ test_callable(void) static int test_lua_func_adapter(void) { - plan(7); + plan(8); header(); test_numeric(); test_tuple(); test_string(); + test_bool(); test_null(); test_error(); test_get_func();