From 346f0c1e3341bf081401753acfaa2b6543cf4799 Mon Sep 17 00:00:00 2001 From: Roman Tsisyk <roman@tsisyk.com> Date: Fri, 21 Feb 2014 18:18:04 +0400 Subject: [PATCH] Rewrite tuple[x] and #tuple bindings using FFI --- src/box/lua/tuple.cc | 41 ----------------------------------------- src/box/lua/tuple.lua | 19 +++++++++++++++++-- src/box/tuple.h | 6 +++--- src/ffisyms.cc | 5 ++++- 4 files changed, 24 insertions(+), 47 deletions(-) diff --git a/src/box/lua/tuple.cc b/src/box/lua/tuple.cc index d8522df934..a725236e26 100644 --- a/src/box/lua/tuple.cc +++ b/src/box/lua/tuple.cc @@ -111,14 +111,6 @@ lbox_tuple_gc(struct lua_State *L) return 0; } -static int -lbox_tuple_len(struct lua_State *L) -{ - struct tuple *tuple = lua_checktuple(L, 1); - lua_pushnumber(L, tuple_arity(tuple)); - return 1; -} - static int lbox_tuple_slice(struct lua_State *L) { @@ -425,37 +417,6 @@ lbox_tuple_totable(struct lua_State *L) return 1; } -/** - * Implementation of tuple __index metamethod. - * - * Provides operator [] access to individual fields for integer - * indexes, as well as searches and invokes metatable methods - * for strings. - */ -static int -lbox_tuple_index(struct lua_State *L) -{ - struct tuple *tuple = lua_checktuple(L, 1); - /* For integer indexes, implement [] operator */ - if (lua_isnumber(L, 2)) { - int i = luaL_checkint(L, 2); - const char *field = tuple_field(tuple, i); - if (field == NULL) { - const char *data = tuple->data; - luaL_error(L, "%s: index %d is out of bounds (0..%d)", - tuplelib_name, i, mp_decode_array(&data)); - } - luamp_decode(L, &field); - return 1; - } - - /* If we got a string, try to find a method for it. */ - const char *sz = luaL_checkstring(L, 2); - lua_getmetatable(L, 1); - lua_getfield(L, -1, sz); - return 1; -} - void lbox_pushtuple(struct lua_State *L, struct tuple *tuple) { @@ -524,8 +485,6 @@ lbox_tuple_pairs(struct lua_State *L) static const struct luaL_reg lbox_tuple_meta[] = { {"__gc", lbox_tuple_gc}, - {"__len", lbox_tuple_len}, - {"__index", lbox_tuple_index}, {"next", lbox_tuple_next}, {"pairs", lbox_tuple_pairs}, {"slice", lbox_tuple_slice}, diff --git a/src/box/lua/tuple.lua b/src/box/lua/tuple.lua index c2989d2897..f53f17a21e 100644 --- a/src/box/lua/tuple.lua +++ b/src/box/lua/tuple.lua @@ -2,6 +2,7 @@ local ffi = require('ffi') local yaml = require('yaml') +local msgpackffi = require('msgpackffi') ffi.cdef([[ struct tuple @@ -12,6 +13,11 @@ struct tuple uint32_t _bsize; char data[0]; } __attribute__((packed)); + +uint32_t +tuple_arity(const struct tuple *tuple); +const char * +tuple_field(const struct tuple *tuple, uint32_t i); ]]) local builtin = ffi.C @@ -33,10 +39,19 @@ local methods = { local tuple_gc = cfuncs.__gc; -local tuple_field = cfuncs.__index +local tuple_field = function(tuple, field_n) + local field = builtin.tuple_field(tuple, field_n) + if field == nil then + return nil + end + return msgpackffi.decode_unchecked(field) +end + ffi.metatype('struct tuple', { __gc = tuple_gc; - __len = cfuncs.__len; + __len = function(tuple) + return builtin.tuple_arity(tuple) + end; __tostring = function(tuple) -- Unpack tuple, call yaml.encode, remove yaml header and footer -- 5 = '---\n\n' (header), -6 = '\n...\n' (footer) diff --git a/src/box/tuple.h b/src/box/tuple.h index 5f1f62e01e..58a0a64931 100644 --- a/src/box/tuple.h +++ b/src/box/tuple.h @@ -206,7 +206,7 @@ tuple_format(const struct tuple *tuple) * @param tuple * @return the number of fields in tuple */ -static inline uint32_t +extern "C" inline uint32_t tuple_arity(const struct tuple *tuple) { const char *data = tuple->data; @@ -220,7 +220,7 @@ tuple_arity(const struct tuple *tuple) * @pre field < tuple->field_count. * @returns field data if field exists or NULL */ -static inline const char * +inline const char * tuple_field_old(const struct tuple_format *format, const struct tuple *tuple, uint32_t i) { @@ -261,7 +261,7 @@ tuple_field_old(const struct tuple_format *format, * or NULL if field is out of range * @param len pointer where the len of the field will be stored */ -inline const char * +extern "C" inline const char * tuple_field(const struct tuple *tuple, uint32_t i) { return tuple_field_old(tuple_format(tuple), tuple, i); diff --git a/src/ffisyms.cc b/src/ffisyms.cc index f7346dce0e..523b9a9284 100644 --- a/src/ffisyms.cc +++ b/src/ffisyms.cc @@ -1,5 +1,6 @@ #include <bit/bit.h> #include <lib/msgpuck/msgpuck.h> +#include <box/tuple.h> /* * A special hack to cc/ld to keep symbols in an optimized binary. @@ -9,5 +10,7 @@ void *ffi_symbols[] = { (void *) bswap_u32, (void *) bswap_u64, (void *) mp_bswap_float, - (void *) mp_bswap_double + (void *) mp_bswap_double, + (void *) tuple_arity, + (void *) tuple_field }; -- GitLab