[tarantool-patches] [PATCH 6/7] msgpack: allow to pass 'const char *' into decode()
Vladislav Shpilevoy
v.shpilevoy at tarantool.org
Wed May 15 02:06:24 MSK 2019
msgpack.decode() internally uses 'const char *' variable to
decode msgpack, but somewhy expects only 'char *' as input.
This commit allows to pass 'const char *' as well.
---
src/lua/msgpack.c | 16 +++++-----------
src/lua/utils.c | 20 +++++++++++++++++++-
src/lua/utils.h | 11 +++++++++++
test/app-tap/msgpack.test.lua | 7 ++++---
test/app/msgpack.result | 18 ++++++++++++++++++
test/app/msgpack.test.lua | 7 +++++++
6 files changed, 64 insertions(+), 15 deletions(-)
diff --git a/src/lua/msgpack.c b/src/lua/msgpack.c
index 73bda80ea..66b83b894 100644
--- a/src/lua/msgpack.c
+++ b/src/lua/msgpack.c
@@ -50,8 +50,6 @@ luamp_error(void *error_ctx)
luaL_error(L, diag_last_error(diag_get())->errmsg);
}
-static uint32_t CTID_CHAR_PTR;
-
struct luaL_serializer *luaL_msgpack_default = NULL;
static enum mp_type
@@ -332,9 +330,8 @@ lua_msgpack_encode(lua_State *L)
static int
lua_msgpack_decode_cdata(lua_State *L, bool check)
{
- uint32_t ctypeid;
- const char *data = *(const char **)luaL_checkcdata(L, 1, &ctypeid);
- if (ctypeid != CTID_CHAR_PTR) {
+ const char *data;
+ if (luaL_checkconstchar(L, 1, &data) != 0) {
return luaL_error(L, "msgpack.decode: "
"a Lua string or 'char *' expected");
}
@@ -346,7 +343,7 @@ lua_msgpack_decode_cdata(lua_State *L, bool check)
}
struct luaL_serializer *cfg = luaL_checkserializer(L);
luamp_decode(L, cfg, &data);
- *(const char **)luaL_pushcdata(L, ctypeid) = data;
+ *(const char **)luaL_pushcdata(L, CTID_CHAR_PTR) = data;
return 2;
}
@@ -435,9 +432,8 @@ verify_decode_header_args(lua_State *L, const char *func_name,
return luaL_error(L, "Usage: %s(ptr, size)", func_name);
/* Verify ptr type. */
- uint32_t ctypeid;
- const char *data = *(char **) luaL_checkcdata(L, 1, &ctypeid);
- if (ctypeid != CTID_CHAR_PTR)
+ const char *data;
+ if (luaL_checkconstchar(L, 1, &data) != 0)
return luaL_error(L, "%s: 'char *' expected", func_name);
/* Verify size type and value. */
@@ -525,8 +521,6 @@ lua_msgpack_new(lua_State *L)
LUALIB_API int
luaopen_msgpack(lua_State *L)
{
- CTID_CHAR_PTR = luaL_ctypeid(L, "char *");
- assert(CTID_CHAR_PTR != 0);
luaL_msgpack_default = luaL_newserializer(L, "msgpack", msgpacklib);
return 1;
}
diff --git a/src/lua/utils.c b/src/lua/utils.c
index f53d7e588..01a0cd894 100644
--- a/src/lua/utils.c
+++ b/src/lua/utils.c
@@ -43,6 +43,8 @@ int luaL_array_metatable_ref = LUA_REFNIL;
static uint32_t CTID_STRUCT_IBUF;
static uint32_t CTID_STRUCT_IBUF_PTR;
+uint32_t CTID_CHAR_PTR;
+uint32_t CTID_CONST_CHAR_PTR;
void *
luaL_pushcdata(struct lua_State *L, uint32_t ctypeid)
@@ -1076,6 +1078,19 @@ luaL_checkibuf(struct lua_State *L, int idx)
return NULL;
}
+int
+luaL_checkconstchar(struct lua_State *L, int idx, const char **res)
+{
+ if (lua_type(L, idx) != LUA_TCDATA)
+ return -1;
+ uint32_t cdata_type;
+ void *cdata = luaL_checkcdata(L, idx, &cdata_type);
+ if (cdata_type != CTID_CHAR_PTR && cdata_type != CTID_CONST_CHAR_PTR)
+ return -1;
+ *res = cdata != NULL ? *(const char **) cdata : NULL;
+ return 0;
+}
+
lua_State *
luaT_state(void)
{
@@ -1209,6 +1224,9 @@ tarantool_lua_utils_init(struct lua_State *L)
assert(CTID_STRUCT_IBUF != 0);
CTID_STRUCT_IBUF_PTR = luaL_ctypeid(L, "struct ibuf *");
assert(CTID_STRUCT_IBUF_PTR != 0);
-
+ CTID_CHAR_PTR = luaL_ctypeid(L, "char *");
+ assert(CTID_CHAR_PTR != 0);
+ CTID_CONST_CHAR_PTR = luaL_ctypeid(L, "const char *");
+ assert(CTID_CONST_CHAR_PTR != 0);
return 0;
}
diff --git a/src/lua/utils.h b/src/lua/utils.h
index cf51eb132..3d887a5ce 100644
--- a/src/lua/utils.h
+++ b/src/lua/utils.h
@@ -67,6 +67,9 @@ struct ibuf;
extern struct lua_State *tarantool_L;
extern struct ibuf *tarantool_lua_ibuf;
+extern uint32_t CTID_CONST_CHAR_PTR;
+extern uint32_t CTID_CHAR_PTR;
+
/** \cond public */
/**
@@ -544,6 +547,14 @@ luaL_checkfinite(struct lua_State *L, struct luaL_serializer *cfg,
struct ibuf *
luaL_checkibuf(struct lua_State *L, int idx);
+/**
+ * Check if a value on @a L stack by index @a idx is pointer at
+ * char or const char. '(char *)NULL' is also considered a valid
+ * char pointer.
+ */
+int
+luaL_checkconstchar(struct lua_State *L, int idx, const char **res);
+
/* {{{ Helper functions to interact with a Lua iterator from C */
/**
diff --git a/test/app-tap/msgpack.test.lua b/test/app-tap/msgpack.test.lua
index 1b0bb9806..bd095e5ae 100755
--- a/test/app-tap/msgpack.test.lua
+++ b/test/app-tap/msgpack.test.lua
@@ -57,6 +57,7 @@ local function test_decode_array_map_header(test, s)
'of buffer'
local non_positive_size_err = 'msgpack.decode_[^_]+_header: ' ..
'non%-positive size'
+ local wrong_type_err = "msgpack.decode_[^_]+_header: 'char %*' expected"
local decode_cases = {
{
@@ -175,17 +176,17 @@ local function test_decode_array_map_header(test, s)
{
'data is nil',
args = {nil, 1},
- exp_err = 'expected cdata as 1 argument',
+ exp_err = wrong_type_err,
},
{
'data is not cdata',
args = {1, 1},
- exp_err = 'expected cdata as 1 argument',
+ exp_err = wrong_type_err,
},
{
'data with wrong cdata type',
args = {box.tuple.new(), 1},
- exp_err = "msgpack.decode_[^_]+_header: 'char %*' expected",
+ exp_err = wrong_type_err,
},
{
'size has wrong type',
diff --git a/test/app/msgpack.result b/test/app/msgpack.result
index 9fc42fc3c..105f503da 100644
--- a/test/app/msgpack.result
+++ b/test/app/msgpack.result
@@ -4,6 +4,9 @@ buffer = require 'buffer'
msgpack = require 'msgpack'
---
...
+ffi = require 'ffi'
+---
+...
-- Arguments check.
buf = buffer.ibuf()
---
@@ -226,3 +229,18 @@ size = msgpack.encode({c = 3, d = 4}, buf)
---
- {'c': 3, 'd': 4}
...
+-- Decode should accept both 'char *' and 'const char *'.
+buf:reset()
+---
+...
+size = msgpack.encode(100, buf)
+---
+...
+(msgpack.decode(ffi.cast('char *', buf.rpos), size))
+---
+- 100
+...
+(msgpack.decode(ffi.cast('const char *', buf.rpos), size))
+---
+- 100
+...
diff --git a/test/app/msgpack.test.lua b/test/app/msgpack.test.lua
index 0920fa507..de8fd4e37 100644
--- a/test/app/msgpack.test.lua
+++ b/test/app/msgpack.test.lua
@@ -1,5 +1,6 @@
buffer = require 'buffer'
msgpack = require 'msgpack'
+ffi = require 'ffi'
-- Arguments check.
buf = buffer.ibuf()
@@ -71,3 +72,9 @@ size = msgpack.encode({a = 1, b = 2}, buf)
buf = buffer.ibuf()
size = msgpack.encode({c = 3, d = 4}, buf)
(msgpack.decode(buf.rpos, size))
+
+-- Decode should accept both 'char *' and 'const char *'.
+buf:reset()
+size = msgpack.encode(100, buf)
+(msgpack.decode(ffi.cast('char *', buf.rpos), size))
+(msgpack.decode(ffi.cast('const char *', buf.rpos), size))
--
2.20.1 (Apple Git-117)
More information about the Tarantool-patches
mailing list